From e50274b7366dc4cfa7b448d510fadcf030e004b6 Mon Sep 17 00:00:00 2001 From: Maciej Maciejewski Date: Mon, 11 Nov 2024 22:49:15 +0100 Subject: [PATCH] dodanie start, stop dnia pracy, generowanie PDF --- Controllers/PdfController.cs | 113 +++++++++++++++++++++++++++++++ Controllers/WorkDayController.cs | 55 +++++++++++++++ FirmTracker-Server.csproj | 1 + Program.cs | 5 +- nHIbernate/PdfData.cs | 98 +++++++++++++++++++++++++++ 5 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 Controllers/PdfController.cs create mode 100644 Controllers/WorkDayController.cs create mode 100644 nHIbernate/PdfData.cs diff --git a/Controllers/PdfController.cs b/Controllers/PdfController.cs new file mode 100644 index 0000000..b9a7229 --- /dev/null +++ b/Controllers/PdfController.cs @@ -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 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 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(); + } + } + } +} diff --git a/Controllers/WorkDayController.cs b/Controllers/WorkDayController.cs new file mode 100644 index 0000000..1abfed7 --- /dev/null +++ b/Controllers/WorkDayController.cs @@ -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 WorkStartTimes = new ConcurrentDictionary(); + + // 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] }); + } + } + } +} diff --git a/FirmTracker-Server.csproj b/FirmTracker-Server.csproj index 91768c3..05849f9 100644 --- a/FirmTracker-Server.csproj +++ b/FirmTracker-Server.csproj @@ -29,6 +29,7 @@ + diff --git a/Program.cs b/Program.cs index 2c10c9c..adedab0 100644 --- a/Program.cs +++ b/Program.cs @@ -37,6 +37,7 @@ using FirmTracker_Server.Middleware; using FirmTracker_Server.Services; using System.Reflection; using FirmTracker_Server.Mappings; +using NuGet.Packaging; namespace FirmTracker_Server @@ -69,7 +70,8 @@ namespace FirmTracker_Server TestClass test = new TestClass(); test.AddTestProduct(); - + QuestPDF.Settings.License = QuestPDF.Infrastructure.LicenseType.Community; + builder.Services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", @@ -173,6 +175,7 @@ namespace FirmTracker_Server services.AddScoped(); services.AddScoped(); services.AddScoped, PasswordHasher>(); + services.AddScoped(); services.AddMvc(); } diff --git a/nHIbernate/PdfData.cs b/nHIbernate/PdfData.cs new file mode 100644 index 0000000..3028bf4 --- /dev/null +++ b/nHIbernate/PdfData.cs @@ -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 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 GetAllExpenses() + { + using (var session = SessionFactory.OpenSession()) + { + return session.Query().ToList(); + } + } + + // Retrieve a specific expense by ID + public Expense GetExpense(int expenseId) + { + using (var session = SessionFactory.OpenSession()) + { + return session.Get(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(expenseId); + if (expense != null) + { + session.Delete(expense); + } + transaction.Commit(); + } + catch + { + transaction.Rollback(); + throw; + } + } + } + } +}