PI2024-30 #6
113
Controllers/PdfController.cs
Normal file
113
Controllers/PdfController.cs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using FirmTracker_Server.nHibernate;
|
||||||
|
using FirmTracker_Server.nHibernate.Expenses;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using QuestPDF.Fluent;
|
||||||
|
using QuestPDF.Helpers;
|
||||||
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
|
namespace FirmTracker_Server.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class PdfController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IExpenseRepository _expenseRepository;
|
||||||
|
|
||||||
|
public PdfController(IExpenseRepository expenseRepository)
|
||||||
|
{
|
||||||
|
_expenseRepository = expenseRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("download")]
|
||||||
|
public IActionResult DownloadExpenseReport()
|
||||||
|
{
|
||||||
|
// Fetch expense data from the repository
|
||||||
|
List<Expense> expenses = _expenseRepository.GetAllExpenses();
|
||||||
|
|
||||||
|
// Generate the PDF file
|
||||||
|
byte[] pdfBytes = GeneratePdf(expenses);
|
||||||
|
string date = DateTime.Now.ToString("yyyy-MM-dd");
|
||||||
|
string fileName = $"ExpenseReport_{date}.pdf";
|
||||||
|
|
||||||
|
// Return the PDF as a downloadable file
|
||||||
|
return File(pdfBytes, "application/pdf", fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] GeneratePdf(List<Expense> expenses)
|
||||||
|
{
|
||||||
|
using (var ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
// Calculate total and average expenses
|
||||||
|
decimal totalExpenses = expenses.Sum(e => e.Value);
|
||||||
|
decimal averageExpense = expenses.Count > 0 ? totalExpenses / expenses.Count : 0;
|
||||||
|
|
||||||
|
// Define the document using QuestPDF
|
||||||
|
Document.Create(container =>
|
||||||
|
{
|
||||||
|
container.Page(page =>
|
||||||
|
{
|
||||||
|
page.Size(PageSizes.A4);
|
||||||
|
page.Margin(2, Unit.Centimetre);
|
||||||
|
page.PageColor(Colors.White);
|
||||||
|
page.DefaultTextStyle(x => x.FontSize(12));
|
||||||
|
|
||||||
|
// Main header
|
||||||
|
page.Header()
|
||||||
|
.Text("Expense Report")
|
||||||
|
.FontSize(20)
|
||||||
|
.SemiBold()
|
||||||
|
.AlignCenter();
|
||||||
|
|
||||||
|
// Summary section
|
||||||
|
page.Content().PaddingVertical(1, Unit.Centimetre).Column(column =>
|
||||||
|
{
|
||||||
|
column.Spacing(10);
|
||||||
|
|
||||||
|
column.Item().Row(row =>
|
||||||
|
{
|
||||||
|
row.RelativeItem().Text($"Total Expenses: {totalExpenses:C}").FontSize(14).Bold();
|
||||||
|
row.RelativeItem().Text($"Average Expense: {averageExpense:C}").FontSize(14).Bold();
|
||||||
|
});
|
||||||
|
|
||||||
|
column.Item().Text("Expense Details").FontSize(16).Underline();
|
||||||
|
|
||||||
|
// Add a table header
|
||||||
|
column.Item().Row(row =>
|
||||||
|
{
|
||||||
|
row.RelativeItem().Text("Date").SemiBold();
|
||||||
|
row.RelativeItem().Text("Value").SemiBold();
|
||||||
|
row.RelativeItem().Text("Description").SemiBold();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Populate table rows with expense data
|
||||||
|
foreach (var expense in expenses)
|
||||||
|
{
|
||||||
|
column.Item().Row(row =>
|
||||||
|
{
|
||||||
|
row.RelativeItem().Text(expense.Date.ToString("yyyy-MM-dd"));
|
||||||
|
row.RelativeItem().Text(expense.Value.ToString("C"));
|
||||||
|
row.RelativeItem().Text(expense.Description);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Footer with generation date
|
||||||
|
page.Footer()
|
||||||
|
.AlignCenter()
|
||||||
|
.Text(text =>
|
||||||
|
{
|
||||||
|
text.Span("Generated on ");
|
||||||
|
text.Span(DateTime.Now.ToString("yyyy-MM-dd")).SemiBold();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).GeneratePdf(ms);
|
||||||
|
|
||||||
|
return ms.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
Controllers/WorkDayController.cs
Normal file
55
Controllers/WorkDayController.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace YourNamespace.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class WorkdayController : ControllerBase
|
||||||
|
{
|
||||||
|
// In-memory storage for simplicity, where the key is the userId.
|
||||||
|
private static readonly ConcurrentDictionary<string, DateTime?> WorkStartTimes = new ConcurrentDictionary<string, DateTime?>();
|
||||||
|
|
||||||
|
// Get the current status of the user's workday (started or not)
|
||||||
|
[HttpGet("status/{userId}")]
|
||||||
|
public IActionResult GetWorkdayStatus(string userId)
|
||||||
|
{
|
||||||
|
if (WorkStartTimes.TryGetValue(userId, out DateTime? startTime))
|
||||||
|
{
|
||||||
|
if (startTime.HasValue)
|
||||||
|
{
|
||||||
|
return Ok(new { status = "started", startTime = startTime });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Ok(new { status = "stopped" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NotFound(new { message = "User not found" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start or stop the user's workday by toggling the start/stop state
|
||||||
|
[HttpPost("toggle/{userId}")]
|
||||||
|
public IActionResult ToggleWorkday(string userId)
|
||||||
|
{
|
||||||
|
// If the workday has already started, stop it, otherwise start it
|
||||||
|
if (WorkStartTimes.ContainsKey(userId) && WorkStartTimes[userId].HasValue)
|
||||||
|
{
|
||||||
|
// Stop the workday
|
||||||
|
WorkStartTimes[userId] = null;
|
||||||
|
return Ok(new { status = "stopped" });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Start the workday
|
||||||
|
WorkStartTimes[userId] = DateTime.Now;
|
||||||
|
return Ok(new { status = "started", startTime = WorkStartTimes[userId] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -29,6 +29,7 @@
|
|||||||
<PackageReference Include="NLog" Version="5.3.4" />
|
<PackageReference Include="NLog" Version="5.3.4" />
|
||||||
<PackageReference Include="NLog.Database" Version="5.3.4" />
|
<PackageReference Include="NLog.Database" Version="5.3.4" />
|
||||||
<PackageReference Include="NSwag.Annotations" Version="14.0.7" />
|
<PackageReference Include="NSwag.Annotations" Version="14.0.7" />
|
||||||
|
<PackageReference Include="QuestPDF" Version="2024.10.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
|
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.1.2" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.1.2" />
|
||||||
|
@ -37,6 +37,7 @@ using FirmTracker_Server.Middleware;
|
|||||||
using FirmTracker_Server.Services;
|
using FirmTracker_Server.Services;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using FirmTracker_Server.Mappings;
|
using FirmTracker_Server.Mappings;
|
||||||
|
using NuGet.Packaging;
|
||||||
|
|
||||||
|
|
||||||
namespace FirmTracker_Server
|
namespace FirmTracker_Server
|
||||||
@ -69,7 +70,8 @@ namespace FirmTracker_Server
|
|||||||
|
|
||||||
TestClass test = new TestClass();
|
TestClass test = new TestClass();
|
||||||
test.AddTestProduct();
|
test.AddTestProduct();
|
||||||
|
QuestPDF.Settings.License = QuestPDF.Infrastructure.LicenseType.Community;
|
||||||
|
|
||||||
builder.Services.AddCors(options =>
|
builder.Services.AddCors(options =>
|
||||||
{
|
{
|
||||||
options.AddPolicy("AllowSpecificOrigin",
|
options.AddPolicy("AllowSpecificOrigin",
|
||||||
@ -173,6 +175,7 @@ namespace FirmTracker_Server
|
|||||||
services.AddScoped<IUserService, UserService>();
|
services.AddScoped<IUserService, UserService>();
|
||||||
services.AddScoped<ErrorHandling>();
|
services.AddScoped<ErrorHandling>();
|
||||||
services.AddScoped<IPasswordHasher<User>, PasswordHasher<User>>();
|
services.AddScoped<IPasswordHasher<User>, PasswordHasher<User>>();
|
||||||
|
services.AddScoped<IExpenseRepository, ExpenseRepository>();
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
98
nHIbernate/PdfData.cs
Normal file
98
nHIbernate/PdfData.cs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using FirmTracker_Server.nHibernate.Expenses;
|
||||||
|
using NHibernate;
|
||||||
|
|
||||||
|
namespace FirmTracker_Server.nHibernate
|
||||||
|
{
|
||||||
|
public interface IExpenseRepository
|
||||||
|
{
|
||||||
|
List<Expense> GetAllExpenses();
|
||||||
|
Expense GetExpense(int expenseId);
|
||||||
|
void AddExpense(Expense expense);
|
||||||
|
void UpdateExpense(Expense expense);
|
||||||
|
void DeleteExpense(int expenseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExpenseRepository : IExpenseRepository
|
||||||
|
{
|
||||||
|
// Retrieve all expenses
|
||||||
|
public List<Expense> GetAllExpenses()
|
||||||
|
{
|
||||||
|
using (var session = SessionFactory.OpenSession())
|
||||||
|
{
|
||||||
|
return session.Query<Expense>().ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve a specific expense by ID
|
||||||
|
public Expense GetExpense(int expenseId)
|
||||||
|
{
|
||||||
|
using (var session = SessionFactory.OpenSession())
|
||||||
|
{
|
||||||
|
return session.Get<Expense>(expenseId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new expense
|
||||||
|
public void AddExpense(Expense expense)
|
||||||
|
{
|
||||||
|
using (var session = SessionFactory.OpenSession())
|
||||||
|
using (var transaction = session.BeginTransaction())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
session.Save(expense);
|
||||||
|
transaction.Commit();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
transaction.Rollback();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update an existing expense
|
||||||
|
public void UpdateExpense(Expense expense)
|
||||||
|
{
|
||||||
|
using (var session = SessionFactory.OpenSession())
|
||||||
|
using (var transaction = session.BeginTransaction())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
session.Update(expense);
|
||||||
|
transaction.Commit();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
transaction.Rollback();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete an expense by ID
|
||||||
|
public void DeleteExpense(int expenseId)
|
||||||
|
{
|
||||||
|
using (var session = SessionFactory.OpenSession())
|
||||||
|
using (var transaction = session.BeginTransaction())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var expense = session.Get<Expense>(expenseId);
|
||||||
|
if (expense != null)
|
||||||
|
{
|
||||||
|
session.Delete(expense);
|
||||||
|
}
|
||||||
|
transaction.Commit();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
transaction.Rollback();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user