Files
Distribution_GL/PROJECT_SPECIFICATION.md

85 lines
7.7 KiB
Markdown

# 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<T>` 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<string, JsonElement>` 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<string, JsonElement>` (for use with `DataExtractor`), plus a safe generic `DeserializeJson<T>` 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.