ca81e9bc42
- Implemented General Ledger client component for managing GL integration. - Created a dedicated page for General Ledger configuration. - Developed Finance Report client component for generating various financial reports. - Added report blocks for structured display of financial data. - Introduced API endpoints for fetching GL accounts and financial reports. - Updated navigation to include links for GL integration and financial reports. - Enhanced permissions to manage GL and view financial reports. - Updated appsettings to include General Ledger API configuration.
75 lines
3.6 KiB
C#
75 lines
3.6 KiB
C#
using System.Text;
|
|
using System.Text.Json;
|
|
using Distribution.Features.GeneralLedger;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace Distribution.Features.FinanceReport;
|
|
|
|
/// <summary>
|
|
/// Proxies the General Ledger service's reports (TrialBalance, GeneralLedger, BalanceSheet, ProfitAndLoss, CashFlow,
|
|
/// BudgetVsActual, TaxSummary). Query parameters are forwarded as-is; Json is returned as the GL data payload and
|
|
/// Pdf/Csv are returned as downloadable files.
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/reports/finance")]
|
|
public class FinanceReportController(IGeneralLedgerClient gl) : ControllerBase
|
|
{
|
|
/// <summary>Active GL accounts (code + name) for the report filters' account dropdown.</summary>
|
|
[HttpGet("accounts")]
|
|
[Authorize("finance-reports.view")]
|
|
public async Task<IActionResult> Accounts(CancellationToken ct)
|
|
{
|
|
GeneralLedgerResult result;
|
|
try { result = await gl.SendAsync(HttpMethod.Get, "v1/accounts?isActive=true", null, ct); }
|
|
catch (HttpRequestException) { return StatusCode(502, new { error = "The General Ledger service is unreachable." }); }
|
|
|
|
if (!result.Success || GlJson.Data(result) is not { } data)
|
|
return StatusCode(502, new { error = GlJson.Message(result) ?? "Could not load GL accounts." });
|
|
|
|
var items = GlJson.Get(data, "items");
|
|
var accounts = items is { ValueKind: JsonValueKind.Array }
|
|
? items.Value.EnumerateArray()
|
|
.Select(a => new { accountCode = GlJson.GetString(a, "accountCode") ?? "", accountName = GlJson.GetString(a, "accountName") ?? "" })
|
|
.OrderBy(a => a.accountCode, StringComparer.Ordinal)
|
|
.ToList()
|
|
: [];
|
|
return Ok(accounts);
|
|
}
|
|
|
|
[HttpGet("{reportType}")]
|
|
[Authorize("finance-reports.view")]
|
|
public async Task<IActionResult> Get(string reportType, [FromQuery] string outputFormat = "Json", CancellationToken ct = default)
|
|
{
|
|
var query = new StringBuilder($"v1/reports?reportType={Uri.EscapeDataString(reportType)}&outputFormat={Uri.EscapeDataString(outputFormat)}");
|
|
foreach (var (key, values) in Request.Query)
|
|
{
|
|
if (key is "reportType" or "outputFormat") continue;
|
|
foreach (var v in values)
|
|
query.Append('&').Append(Uri.EscapeDataString(key)).Append('=').Append(Uri.EscapeDataString(v ?? ""));
|
|
}
|
|
|
|
GeneralLedgerResult result;
|
|
try { result = await gl.SendAsync(HttpMethod.Get, query.ToString(), null, ct); }
|
|
catch (HttpRequestException) { return StatusCode(502, new { error = "The General Ledger service is unreachable." }); }
|
|
|
|
if (!result.Success)
|
|
return StatusCode(result.StatusCode is >= 400 and < 500 ? result.StatusCode : 502,
|
|
new { error = GlJson.Message(result) ?? "The General Ledger service rejected the request." });
|
|
|
|
var data = GlJson.Data(result);
|
|
if (data is null) return StatusCode(502, new { error = "The General Ledger service returned no data." });
|
|
|
|
if (!outputFormat.Equals("Json", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
var base64 = GlJson.GetString(data.Value, "contentBase64");
|
|
if (base64 is null) return StatusCode(502, new { error = "The General Ledger service returned no file." });
|
|
return File(Convert.FromBase64String(base64),
|
|
GlJson.GetString(data.Value, "contentType") ?? "application/octet-stream",
|
|
GlJson.GetString(data.Value, "fileName"));
|
|
}
|
|
|
|
return Content(data.Value.GetRawText(), "application/json");
|
|
}
|
|
}
|