# General Ledger Service — Project Specification This is an early-stage **ASP.NET Core Web API** (.NET 10) microservice, scaffolded as part of a larger multi-service ERP system (JWT issuer is `ERPCore`, audience `ERPCore.Clients`, suggesting this service authenticates against a shared identity provider). Only the foundational skeleton exists — domain models, repositories, and business logic are not yet implemented (several folders are empty placeholders). ## 1. Project root | File | Purpose | |---|---| | `General-Ledgar-Service.csproj` | SDK-style project file targeting `net10.0`, `Nullable`/`ImplicitUsings` enabled, root namespace `General_Ledger_Service`. Declares empty placeholder folders (`Interfaces/Repositories`, `Interfaces/Services`, `Models`, `Repositories`, `Services`) that are referenced but not yet populated. | | `Program.cs` | Application entry point and DI/middleware composition root (detailed below). | | `General-Ledgar-Service.slnx` | Visual Studio solution file (new XML-based `.slnx` format). | | `appsettings.json` / `appsettings.Development.json` / `appsettings.Production.json` | Environment-layered configuration. `appsettings.json` holds only settings common to every environment (logging, Kestrel URL, allowed hosts, JWT issuer/audience/token lifetime). `appsettings.Development.json` holds development-only values (local MySQL connection string, JWT signing key, API key, demo company details); `appsettings.Production.json` holds production-only values, currently blank/placeholder secrets meant to be filled via environment variables/secret store at deploy time. | | `General_Ledger_Service.http` | VS/Rider `.http` scratch file for manual endpoint testing (still has the default `weatherforecast` template call — not yet updated for this service's real routes). | | `.gitignore` | Standard .NET ignore rules. | ## 2. `Program.cs` — composition root Configures, in order: 1. **MVC controllers** (`AddControllers`) 2. **Swagger/OpenAPI** (dev-only UI) 3. **EF Core + MySQL** via `Pomelo.EntityFrameworkCore.MySql`, reading `ConnectionStrings:DefaultConnection` 4. **Unit of Work** — `IUnitOfWork` → `EFUnitOfWork` registered as scoped 5. **Health checks** — `/health` endpoint backed by a DbContext check 6. **JWT Bearer authentication** — conditionally wired up only if a `Jwt:SigningKey` is configured; validates issuer, audience, lifetime, and signing key 7. **Authorization**, HTTPS redirection, and controller routing This is a fairly standard, clean ASP.NET Core startup — no custom middleware or exception-handling pipeline registered yet (the custom exception types in `Exceptions/` aren't currently caught by any global handler). ## 3. `Controllers/` **Purpose:** HTTP API surface (thin layer, delegates to services once they exist). - `GeneralLedgerController.cs` — currently only exposes `GET /api/GeneralLedger/status`, a liveness/status probe returning service name, status, and UTC timestamp. This is a placeholder; no ledger domain endpoints (accounts, journal entries, postings, trial balance, etc.) exist yet. ## 4. `AppDBContext.cs` (root-level, namespace `General_Ledger_Service.Infra`) **Purpose:** EF Core `DbContext`. Currently has no `DbSet` properties or entity configuration — a bare shell awaiting the domain model (accounts, journal entries, ledger lines, periods, etc.). ## 5. `Infra/UoW/` — Unit of Work pattern **Purpose:** Wraps EF Core's `SaveChanges`/transaction lifecycle behind an abstraction so services aren't coupled directly to `DbContext`. - `IUnitOfWork.cs` — contract: `BeginAsync`, `CommitAsync`, `RollbackAsync`, `SaveChangesAsync`. - `EFUnitOfWork.cs` — EF Core implementation; manages an `IDbContextTransaction`, commits both the transaction and pending changes together, supports rollback/dispose cleanup. ## 6. `DTOs/Common/` **Purpose:** Shared response envelope used by every endpoint in this service. - `ApiResponse.cs` — generic envelope (`StatusCode`, `Success`, `Message`, `Data`). Renamed from `AuthResponse`/`DTOs/Auth/` (2026-07-19) since this service does not perform authentication/authorization itself — the name no longer implied that. ## 7. `Exceptions/` **Purpose:** Domain-level custom exceptions for consistent HTTP-status-mapped error handling. - `CustomExceptions.cs` — `NotFoundException`, `BadRequestException`, `UnauthorizedException`, `ForbiddenException`. Not yet wired to a global exception-handling middleware/filter, so today they'd surface as unhandled 500s unless caught locally. ## 8. `Helpers/` **Purpose:** Cross-cutting utility code. - `DataExtractor.cs` — a large, defensive helper for pulling typed values (`string`, `int`, `float`, `decimal`, `bool`, `Guid`, `DateTime`, `DateOnly`) out of a `Dictionary` payload, with required/optional/multi-key variants that throw `BadRequestException` on invalid input. Also has `GetUserIdFromContext` (reads a `UserId` claim/HttpContext item, throws if missing/unauthenticated) and `GetRequiredApiResponse` (builds an `ApiResponse` from raw payload data). This is the backbone for manually parsing loosely-typed JSON request bodies rather than relying purely on strongly-typed model binding. - `DeserializePayload.cs` — round-trips an arbitrary object through `JsonSerializer` into a `Dictionary` (for use with `DataExtractor`), plus a safe generic `DeserializeJson` that swallows exceptions and returns `null` on failure. - `EncryptionHelper.cs` — AES encrypt/decrypt using a **hardcoded** 256-bit key embedded in source, IV prepended to ciphertext and base64-encoded. ⚠️ Worth flagging: a hardcoded symmetric key in source control is a real security concern for anything beyond a placeholder/dev stub — it should move to configuration/secrets before this handles real data. ## 9. Empty placeholder folders (declared in `.csproj`, not yet populated) - `Interfaces/Repositories/`, `Interfaces/Services/`, `Models/`, `Repositories/`, `Services/` — the intended layering (Controller → Service → Repository → DbContext, with a Unit of Work spanning repositories) is scaffolded structurally but has no files yet. ## 10. Build output (`bin/`, `obj/`, `.vs/`) Standard generated/IDE artifacts — not source, ignored by git, no need to document further. ### Package references (`.csproj`) | Package | Version | Purpose | |---|---|---| | `ClosedXML` | 0.105.0 | Reading/writing `.xlsx` files (likely for ledger import/export to Excel) | | `Microsoft.EntityFrameworkCore` | 10.0.9 | Core ORM | | `Microsoft.EntityFrameworkCore.Design` | 10.0.9 | Design-time tooling (migrations scaffolding) | | `Microsoft.EntityFrameworkCore.Tools` | 10.0.9 | Package Manager Console / CLI tooling for migrations | | `Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore` | 10.0.9 | Backs the `/health` DbContext check | | `Pomelo.EntityFrameworkCore.MySql` | 9.0.0 | MySQL provider for EF Core (EF Core packages are pinned to 9.0.9 to match) | | `QuestPDF` | 2026.7.1 | PDF generation (likely ledger/financial statement output) | | `Serilog.AspNetCore` | 10.0.0 | Structured logging integration | | `Serilog.Sinks.File` | 7.0.0 | File sink for Serilog | | `Swashbuckle.AspNetCore` | 10.2.3 | Swagger/OpenAPI generation | --- ### Overall assessment This is a **bootstrap/scaffold commit** (git log shows only "Initial project setup") for a General Ledger microservice within a larger ERP suite. The architecture direction is clear — layered (Controllers → Services → Repositories), Unit-of-Work-mediated persistence, JWT auth against a shared ERPCore identity issuer, PostgreSQL storage, PDF generation capability reserved — but no actual ledger domain logic (chart of accounts, journal entries, double-entry postings, trial balance, period close, etc.) has been built yet.