From f28ad710bc85fd763f991c1e7e098c2ee2258b06 Mon Sep 17 00:00:00 2001 From: arickor Date: Wed, 4 Dec 2024 14:52:48 -0800 Subject: [PATCH 1/2] Fixed routing to Receipt Allocation page --- .../Controllers/SalesController.cs | 171 ++++++++++++------ src/AccountGoWeb/Views/Sales/Allocate.cshtml | 12 +- .../Views/Sales/SalesReceipts.cshtml | 70 +++++-- 3 files changed, 174 insertions(+), 79 deletions(-) diff --git a/src/AccountGoWeb/Controllers/SalesController.cs b/src/AccountGoWeb/Controllers/SalesController.cs index 491e7641e..83987e3b9 100644 --- a/src/AccountGoWeb/Controllers/SalesController.cs +++ b/src/AccountGoWeb/Controllers/SalesController.cs @@ -269,45 +269,59 @@ public async System.Threading.Tasks.Task AddSalesInvoice(SalesInv public async System.Threading.Tasks.Task SalesReceipts() { ViewBag.PageContentHeader = "Sales Receipts"; - using (var client = new HttpClient()) + try { - var baseUri = _configuration!["ApiUrl"]; - client.BaseAddress = new System.Uri(baseUri!); - client.DefaultRequestHeaders.Accept.Clear(); - var response = await client.GetAsync(baseUri + "sales/salesreceipts"); - if (response.IsSuccessStatusCode) + using (var client = new HttpClient()) { - var responseJson = await response.Content.ReadAsStringAsync(); - return View(model: responseJson); + var baseUri = _configuration!["ApiUrl"]; + client.BaseAddress = new Uri(baseUri!); + client.DefaultRequestHeaders.Accept.Clear(); + + var response = await client.GetAsync("sales/salesreceipts"); + if (response.IsSuccessStatusCode) + { + var responseJson = await response.Content.ReadAsStringAsync(); + return View(model: responseJson); + } + else + { + _logger.LogError("Failed to fetch sales receipts. API returned status code: {StatusCode}", response.StatusCode); + ViewBag.ErrorMessage = "Failed to load sales receipts. Please try again later."; + } } } - return View(); + catch (Exception ex) + { + _logger.LogError(ex, "An error occurred while fetching sales receipts."); + ViewBag.ErrorMessage = "An unexpected error occurred while loading sales receipts."; + } + + // Return the view with an error message if the API call fails + return View(model: "[]"); } [HttpGet] public IActionResult AddReceipt() { - - var model = new Models.Sales.AddReceipt(); - - if (ModelState.IsValid) + try { - var serialize = Newtonsoft.Json.JsonConvert.SerializeObject(model); - var content = new StringContent(serialize); - content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); - var response = Post("Sales/SaveReceipt", content); - if (response.IsSuccessStatusCode) - return RedirectToAction("salesreceipts"); + ViewBag.PageContentHeader = "New Receipt"; + ViewBag.Customers = Models.SelectListItemHelper.Customers(); + ViewBag.DebitAccounts = Models.SelectListItemHelper.CashBanks(); + ViewBag.CreditAccounts = Models.SelectListItemHelper.Accounts(); + ViewBag.CustomersDetail = Newtonsoft.Json.JsonConvert.SerializeObject( + GetAsync>("sales/customers").Result + ); + + var model = new Models.Sales.AddReceipt(); + return View(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "An error occurred while preparing the Add Receipt page."); + ViewBag.ErrorMessage = "Failed to load the page for adding a receipt. Please try again later."; + return View(new Models.Sales.AddReceipt()); } - - ViewBag.PageContentHeader = "New Receipt"; - - ViewBag.Customers = Models.SelectListItemHelper.Customers(); - ViewBag.DebitAccounts = Models.SelectListItemHelper.CashBanks(); - ViewBag.CreditAccounts = Models.SelectListItemHelper.Accounts(); - ViewBag.CustomersDetail = Newtonsoft.Json.JsonConvert.SerializeObject(GetAsync>("sales/customers").Result); - - return View(model); } [HttpPost] @@ -315,25 +329,42 @@ public IActionResult AddReceipt(Models.Sales.AddReceipt model) { if (ModelState.IsValid) { - var serialize = Newtonsoft.Json.JsonConvert.SerializeObject(model); - var content = new StringContent(serialize); - content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); - var response = Post("sales/savereceipt", content); - if (response.IsSuccessStatusCode) - return RedirectToAction("salesreceipts"); + try + { + var serialize = Newtonsoft.Json.JsonConvert.SerializeObject(model); + var content = new StringContent(serialize); + content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); + + var response = Post("sales/savereceipt", content); + if (response.IsSuccessStatusCode) + { + return RedirectToAction("SalesReceipts"); + } + else + { + _logger.LogError("Failed to save receipt. API returned status code: {StatusCode}", response.StatusCode); + ViewBag.ErrorMessage = "Failed to save the receipt. Please try again."; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "An error occurred while saving the receipt."); + ViewBag.ErrorMessage = "An unexpected error occurred. Please try again."; + } } + // Reload dropdowns and return the view if validation or API call fails ViewBag.PageContentHeader = "New Receipt"; - ViewBag.Customers = Models.SelectListItemHelper.Customers(); ViewBag.DebitAccounts = Models.SelectListItemHelper.CashBanks(); ViewBag.CreditAccounts = Models.SelectListItemHelper.Accounts(); - ViewBag.CustomersDetail = Newtonsoft.Json.JsonConvert.SerializeObject(GetAsync>("sales/customers").Result); + ViewBag.CustomersDetail = Newtonsoft.Json.JsonConvert.SerializeObject( + GetAsync>("sales/customers").Result + ); return View(model); } - public async System.Threading.Tasks.Task Customers() { ViewBag.PageContentHeader = "Customers"; @@ -433,39 +464,63 @@ public IActionResult CustomerAllocations(int id) return View(); } + // [HttpGet] public IActionResult Allocate(int id) { - ViewBag.PageContentHeader = "Receipt Allocation"; + Console.WriteLine($"Allocate called with ID: {id}"); - var model = new Models.Sales.Allocate(); + try + { + ViewBag.PageContentHeader = "Receipt Allocation"; - var receipt = GetAsync("sales/salesreceipt?id=" + id).Result; + var model = new Models.Sales.Allocate(); - ViewBag.CustomerName = receipt.CustomerName; - ViewBag.ReceiptNo = receipt.ReceiptNo; + // Fetch receipt details + var receipt = GetAsync("sales/salesreceipt?id=" + id).Result; + if (receipt == null) + { + Console.WriteLine($"Receipt not found for ID: {id}"); + _logger.LogError("Failed to fetch receipt with id: {id}", id); + return NotFound($"Receipt with id {id} not found."); + } - model.CustomerId = receipt.CustomerId; - model.ReceiptId = receipt.Id; - model.Date = receipt.ReceiptDate; - model.Amount = receipt.Amount; - model.RemainingAmountToAllocate = receipt.RemainingAmountToAllocate; + ViewBag.CustomerName = receipt.CustomerName; + ViewBag.ReceiptNo = receipt.ReceiptNo; - var invoices = GetAsync>("sales/customerinvoices?id=" + receipt.CustomerId).Result; + model.CustomerId = receipt.CustomerId; + model.ReceiptId = receipt.Id; + model.Date = receipt.ReceiptDate; + model.Amount = receipt.Amount; + model.RemainingAmountToAllocate = receipt.RemainingAmountToAllocate; - foreach (var invoice in invoices) - { - if (invoice.Posted && invoice.TotalAllocatedAmount < invoice.Amount) + // Fetch customer invoices + var invoices = GetAsync>("sales/customerinvoices?id=" + receipt.CustomerId).Result; + if (invoices == null) { - model.AllocationLines.Add(new Models.Sales.AllocationLine() + _logger.LogError("Failed to fetch invoices for customer with id: {CustomerId}", receipt.CustomerId); + return NotFound($"Invoices for customer with id {receipt.CustomerId} not found."); + } + + foreach (var invoice in invoices) + { + if (invoice.Posted && invoice.TotalAllocatedAmount < invoice.Amount) { - InvoiceId = invoice.Id, - Amount = invoice.Amount, - AllocatedAmount = invoice.TotalAllocatedAmount - }); + model.AllocationLines.Add(new Models.Sales.AllocationLine() + { + InvoiceId = invoice.Id, + Amount = invoice.Amount, + AllocatedAmount = invoice.TotalAllocatedAmount + }); + } } - } - return View(model); + return View(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "An error occurred while processing the Allocate action for id: {id}", id); + return StatusCode(500, "An error occurred while processing your request."); + } } [HttpPost] diff --git a/src/AccountGoWeb/Views/Sales/Allocate.cshtml b/src/AccountGoWeb/Views/Sales/Allocate.cshtml index 20c1631d3..2f9ae444b 100644 --- a/src/AccountGoWeb/Views/Sales/Allocate.cshtml +++ b/src/AccountGoWeb/Views/Sales/Allocate.cshtml @@ -1,12 +1,14 @@ @model AccountGoWeb.Models.Sales.Allocate -
+ + @Html.AntiForgeryToken()

General

-
@@ -55,7 +57,8 @@

Invoice

-
@@ -86,7 +89,8 @@ @Model.AllocationLines[i].AllocatedAmount - + } diff --git a/src/AccountGoWeb/Views/Sales/SalesReceipts.cshtml b/src/AccountGoWeb/Views/Sales/SalesReceipts.cshtml index 0a06610b0..1e7c26f66 100644 --- a/src/AccountGoWeb/Views/Sales/SalesReceipts.cshtml +++ b/src/AccountGoWeb/Views/Sales/SalesReceipts.cshtml @@ -1,14 +1,22 @@ @model string + +
New Receipt - + Allocate + View @@ -22,41 +30,69 @@ var selectedRow = {}; var columnDefs = [ - {headerName: "Receipt", field: "id", width: 50}, - {headerName: "No", field: "receiptNo", width: 50}, - {headerName: "Customer Name", field: "customerName", width: 350}, - {headerName: "Receipt Date", field: "receiptDate", width: 100}, - {headerName: "Amount", field: "amount", width: 100}, - {headerName: "Left to Allocate", field: "remainingAmountToAllocate", width: 100} + { headerName: "Receipt", field: "id", width: 50 }, + { headerName: "No", field: "receiptNo", width: 50 }, + { headerName: "Customer Name", field: "customerName", width: 350 }, + { headerName: "Receipt Date", field: "receiptDate", width: 100 }, + { headerName: "Amount", field: "amount", width: 100 }, + { headerName: "Left to Allocate", field: "remainingAmountToAllocate", width: 100 } ]; var gridOptions = { columnDefs: columnDefs, rowData: @Html.Raw(Model), enableSorting: true, - // PROPERTIES - simple boolean / string / number properties rowSelection: 'single', onSelectionChanged: onSelectionChanged, + rowClassRules: { + 'highlighted-row': params => params.node.isSelected() // Add 'highlighted-row' to selected rows + }, }; function onSelectionChanged() { + console.log("Selection changed"); + + // Get all selected rows var selectedRows = gridOptions.api.getSelectedRows(); + console.log("Selected rows:", selectedRows); + + if (!selectedRows.length) { + console.log("No row selected"); + return; // Exit if no row is selected + } + + // Get the selected row selectedRow = selectedRows[0]; + console.log("Selected row data:", selectedRow); + + // Update the Allocate and View Receipt links + document.getElementById('linkAllocate').setAttribute('href', '/sales/allocate/' + selectedRow.id); + console.log("Updated Allocate link to:", 'allocate/' + selectedRow.id); + + document.getElementById('linkViewReceipt').setAttribute('href', '/sales/SalesReceipt?id=' + selectedRow.id); + console.log("Updated View Receipt link to:", 'SalesReceipt?id=' + selectedRow.id); - document.getElementById('linkAllocate').setAttribute('href', 'allocate/' + selectedRow.id); - document.getElementById('linkViewReceipt').setAttribute('href', 'SalesReceipt?id=' + selectedRow.id); document.getElementById('linkViewReceipt').setAttribute('class', 'btn'); - - if(selectedRow.remainingAmountToAllocate > 0) + + if (selectedRow.remainingAmountToAllocate > 0) { document.getElementById('linkAllocate').setAttribute('class', 'btn'); - else + console.log("Set Allocate button to active"); + } else { document.getElementById('linkAllocate').setAttribute('class', 'btn inactiveLink'); + console.log("Set Allocate button to inactive"); + } + + // Highlight the selected row + gridOptions.api.forEachNode(node => { + console.log("Processing row node with ID:", node.data.id); + node.setSelected(node.data.id === selectedRow.id); // Mark row as selected + }); } - // wait for the document to be loaded, otherwise - // ag-Grid will not find the div in the document. - document.addEventListener("DOMContentLoaded", function() { + document.addEventListener("DOMContentLoaded", function () { + console.log("Document loaded"); var eGridDiv = document.querySelector('#receipts'); new agGrid.Grid(eGridDiv, gridOptions); + console.log("ag-Grid initialized"); }); - \ No newline at end of file + From 04ef7ad4e9f9d111131ab3bcdd69dcd77adbff3a Mon Sep 17 00:00:00 2001 From: arickor Date: Wed, 4 Dec 2024 17:19:14 -0800 Subject: [PATCH 2/2] Diagnosed Posted flag error --- .../Controllers/SalesController.cs | 12 ++ .../Views/Sales/AddSalesInvoice.cshtml | 109 ++++++++++++++---- src/AccountGoWeb/Views/Sales/Allocate.cshtml | 27 ++++- 3 files changed, 123 insertions(+), 25 deletions(-) diff --git a/src/AccountGoWeb/Controllers/SalesController.cs b/src/AccountGoWeb/Controllers/SalesController.cs index 83987e3b9..81ccb0eb9 100644 --- a/src/AccountGoWeb/Controllers/SalesController.cs +++ b/src/AccountGoWeb/Controllers/SalesController.cs @@ -1,6 +1,7 @@ using AccountGoWeb.Models; using Dto.Sales; using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; namespace AccountGoWeb.Controllers { @@ -248,11 +249,14 @@ public async System.Threading.Tasks.Task AddSalesInvoice(SalesInv } else if (ModelState.IsValid) { + _logger.LogInformation("Posted value received: {Posted}", Dto.Posted); var serialize = Newtonsoft.Json.JsonConvert.SerializeObject(Dto); var content = new StringContent(serialize); content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); + _logger.LogInformation("AddSalesInvoice: " + await content.ReadAsStringAsync()); var response = Post("Sales/CreateSalesInvoice", content); + _logger.LogInformation("AddSalesInvoice response: " + response.ToString()); if (response.IsSuccessStatusCode) return RedirectToAction("salesinvoices"); @@ -494,6 +498,8 @@ public IActionResult Allocate(int id) model.RemainingAmountToAllocate = receipt.RemainingAmountToAllocate; // Fetch customer invoices + _logger.LogInformation("Calling API: sales/customerinvoices?id={id}", receipt.CustomerId); + var invoices = GetAsync>("sales/customerinvoices?id=" + receipt.CustomerId).Result; if (invoices == null) { @@ -503,6 +509,7 @@ public IActionResult Allocate(int id) foreach (var invoice in invoices) { + _logger.LogInformation("Invoice: {Invoice}", JsonConvert.SerializeObject(invoice)); if (invoice.Posted && invoice.TotalAllocatedAmount < invoice.Amount) { model.AllocationLines.Add(new Models.Sales.AllocationLine() @@ -512,6 +519,11 @@ public IActionResult Allocate(int id) AllocatedAmount = invoice.TotalAllocatedAmount }); } + else + { + _logger.LogInformation("Invoice excluded: Posted={Posted}, TotalAllocatedAmount={TotalAllocatedAmount}, Amount={Amount}", + invoice.Posted, invoice.TotalAllocatedAmount, invoice.Amount); + } } return View(model); diff --git a/src/AccountGoWeb/Views/Sales/AddSalesInvoice.cshtml b/src/AccountGoWeb/Views/Sales/AddSalesInvoice.cshtml index dbd442688..17bd3f528 100644 --- a/src/AccountGoWeb/Views/Sales/AddSalesInvoice.cshtml +++ b/src/AccountGoWeb/Views/Sales/AddSalesInvoice.cshtml @@ -1,12 +1,14 @@ @model Dto.Sales.SalesInvoice - +
@Html.AntiForgeryToken() @Html.ValidationSummary(true) @@ -34,7 +36,8 @@
Posted
- + +
@@ -47,40 +50,45 @@ Discount Measurement - @for (int i = 0; i < Model.SalesInvoiceLines!.Count; i++) + + @for (int i = 0; i < Model.SalesInvoiceLines!.Count; i++) { - - + + - - + + - - + + - - + + - - + + } - - - - - -
@@ -90,4 +98,57 @@
Close
- \ No newline at end of file + + + diff --git a/src/AccountGoWeb/Views/Sales/Allocate.cshtml b/src/AccountGoWeb/Views/Sales/Allocate.cshtml index 2f9ae444b..fbabf6627 100644 --- a/src/AccountGoWeb/Views/Sales/Allocate.cshtml +++ b/src/AccountGoWeb/Views/Sales/Allocate.cshtml @@ -104,4 +104,29 @@ Close
- \ No newline at end of file + + + \ No newline at end of file