7d6e597389
- Implemented CRUD operations for production templates, including listing, retrieving, creating, updating, and deactivating templates. - Introduced a new API contract for production runs, detailing the lifecycle from creation to completion, including handling of stock inputs and outputs. - Documented the architecture, requirements, entity model, and API contract for the manufacturing phase 2, ensuring clarity on the production process and its integration with existing systems.
379 lines
17 KiB
Markdown
379 lines
17 KiB
Markdown
# 00 · CORE — ERP System (Phase 1: Inventory & Supply Chain)
|
|
|
|
> **This file is the hub. Start every task here.**
|
|
> It defines the repository structure, the tech stack, how to stand up a runnable backend, and — most importantly — **where to go next** for any piece of work. Do not begin backend or frontend work without first reading the relevant section below and following the routing table in §7.
|
|
|
|
---
|
|
|
|
## 1. What this project is
|
|
|
|
A modular ERP built in phases. **Phase 1** delivers the **Inventory & Supply Chain** subsystem: master data, procurement, goods receipt, and stock management (FIFO costing, multi-warehouse, single-tenant).
|
|
|
|
| Decision | Value |
|
|
|---|---|
|
|
| Costing method | **FIFO** (cost-layer tracking, per item per warehouse) |
|
|
| Warehouses | **Multi-warehouse** |
|
|
| Tenancy | **Single-tenant** |
|
|
| Approvals (PO, adjustment) | **Auto-approve**, config-gated off (RBAC deferred) |
|
|
| Access control | Authentication only; **RBAC deferred**, user identity stamped for audit |
|
|
| Vendor invoice / 3-way match | **Deferred** to Accounting phase (GRN retains hooks) |
|
|
|
|
Full requirements live in the backend spec (see §7). This file does **not** duplicate them.
|
|
|
|
**Phase 2 (HRM)** is now underway alongside Phase 1 — see §7 routing to `12-BACKEND-HRM.md` / `13-BACKEND-HRM-API.md` / `21-FRONTEND-HRM.md`.
|
|
|
|
---
|
|
|
|
## 2. Repository structure
|
|
|
|
```
|
|
erp-monorepo/
|
|
├── README.md # Root: what this is + how to run both sides
|
|
├── .gitignore # ignore appsettings.*.json secrets, .env*, bin/, obj/, node_modules/
|
|
│
|
|
├── Backend/ # ASP.NET Core Web API (.NET 10) — see §5 to initialize
|
|
│ ├── ERPCore.sln
|
|
│ ├── PROGRESS.md # ← backend change checklist (Claude-maintained, git-shared)
|
|
│ └── ERPCore/ # single Web API project (folders, not multi-project)
|
|
│
|
|
├── Frontend/ # Next.js (App Router + TypeScript) — already initialized
|
|
│ └── PROGRESS.md # ← frontend change checklist (Claude-maintained, git-shared)
|
|
│
|
|
└── docs/ # ALL documentation
|
|
├── 00-CORE.md # ← you are here (hub)
|
|
├── 01-DOC-GUIDE.md # documentation map + tracking conventions
|
|
├── 02-SECURITY.md # accepted-risks register + per-feature security checklist
|
|
├── 10-BACKEND-PHASE1.md # backend spec: SRS + ER/entities + tech + architecture
|
|
├── 11-BACKEND-PHASE1.md # backend API reference (complete req/res)
|
|
└── 20-FRONTEND.md # frontend user-flows + architecture rules + validation posture
|
|
```
|
|
|
|
The `Backend/ERPCore/` internal layout is created in §5.3.
|
|
|
|
---
|
|
|
|
## 3. Tech stack
|
|
|
|
### Backend
|
|
| Concern | Choice |
|
|
|---|---|
|
|
| Runtime | **.NET 10** (`net10.0`) |
|
|
| Framework | ASP.NET Core Web API (controllers) |
|
|
| ORM | EF Core 10 |
|
|
| Database | **PostgreSQL** (Npgsql provider) |
|
|
| Auth | JWT bearer (simple in-app login; RBAC deferred) |
|
|
| Logging | Serilog (file sink) |
|
|
| API docs | Swashbuckle / Swagger UI |
|
|
| Health | HealthChecks + EF Core DB check → `GET /health` |
|
|
|
|
### Frontend
|
|
| Concern | Choice |
|
|
|---|---|
|
|
| Framework | **Next.js** (App Router) + TypeScript |
|
|
| State/forms | **Plain React hooks** (`useState` / custom hooks) |
|
|
| Validation | **Dependency-free** (hand-rolled) — client-side for UX only; **server is authoritative** |
|
|
| API access | Typed fetch client against the backend (`NEXT_PUBLIC_API_BASE_URL`) |
|
|
|
|
> The Frontend project is **already initialized**. Do not scaffold it here. For all frontend architecture, flows, and validation rules, go to `20-FRONTEND.md`.
|
|
|
|
### Database
|
|
PostgreSQL, running on **localhost** for development. Secrets management (User Secrets / environment variables) is deferred; see §5.4 for the current local configuration and the note on secrets.
|
|
|
|
---
|
|
|
|
## 4. Architecture (high-level, both sides)
|
|
|
|
### Backend layering — strict, one direction
|
|
```
|
|
Controller → Service → Repository → UnitOfWork/DbContext
|
|
(DTOs) (logic) (entities) (transaction boundary)
|
|
```
|
|
|
|
Rules (non-negotiable for Phase 1):
|
|
- **DTOs at the controller boundary.** Controllers accept and return DTOs only — **never** EF entities and **never** `DbContext`.
|
|
- **Services hold business logic** and return DTOs. Controllers stay thin (HTTP concerns only).
|
|
- **Repositories own EF entities** and data access. No business rules in repositories.
|
|
- **UnitOfWork is the transaction boundary.** Every stock-affecting operation (GRN confirm, transfer dispatch/receive, adjustment, return, count post) runs inside a single UoW transaction.
|
|
- **FIFO lives in a domain service** (`FifoCostingService`), invoked by stock services inside the UoW transaction — **not** in a controller or repository. Layer consumption must lock affected rows for concurrency safety.
|
|
- **Errors use RFC 7807 `ProblemDetails`** (ASP.NET Core default). Domain errors carry a stable `code`. The error catalog is in `11-BACKEND-PHASE1.md`.
|
|
- **Audit actor** is derived from the authenticated principal (token `sub`), never from the request body.
|
|
|
|
### Frontend (summary — full rules in `20-FRONTEND.md`)
|
|
- Stick to the existing initialized architecture; do not restructure.
|
|
- **Validate on the client for UX, but never trust it.** The server re-validates everything. Business rules that depend on server state (stock availability, negative-stock block, over-receipt tolerance, FIFO sufficiency) are **server-authoritative** and must not be assumed valid client-side.
|
|
|
|
---
|
|
|
|
## 5. Backend initialization (runnable)
|
|
|
|
Follow in order. Commands assume repo root `erp-monorepo/`.
|
|
|
|
### 5.1 Prerequisites
|
|
- **.NET 10 SDK** (`dotnet --version` → `10.0.x`)
|
|
- **PostgreSQL** running on localhost, and a login you can use
|
|
- **EF Core CLI**: `dotnet tool install --global dotnet-ef` (or `dotnet tool update --global dotnet-ef`)
|
|
- Node.js (for the Frontend, handled separately)
|
|
|
|
### 5.2 Create solution and project
|
|
```bash
|
|
mkdir -p Backend && cd Backend
|
|
dotnet new sln -n ERPCore
|
|
dotnet new webapi -n ERPCore --use-controllers -f net10.0
|
|
dotnet sln add ERPCore/ERPCore.csproj
|
|
cd ERPCore
|
|
```
|
|
|
|
### 5.3 Create the internal folder structure
|
|
```bash
|
|
# from Backend/ERPCore/
|
|
mkdir -p Controllers Services/Interfaces Services/Stock \
|
|
Repositories/Interfaces \
|
|
Domain/Entities Domain/Enums \
|
|
Dtos/Common \
|
|
Common/Models \
|
|
Infra/UoW Infra/Persistence/Configurations Infra/Persistence/Migrations Infra/Auth Infra/Logging \
|
|
System/Errors \
|
|
HealthChecks
|
|
```
|
|
Target internal layout:
|
|
```
|
|
ERPCore/
|
|
├── ERPCore.csproj
|
|
├── Program.cs
|
|
├── appsettings.json # base (no real secrets)
|
|
├── appsettings.Development.json # local dev (localhost Postgres)
|
|
├── appsettings.Production.json # env-var driven
|
|
├── Controllers/ # HTTP; DTOs in/out
|
|
├── Services/ # business logic → DTOs
|
|
│ ├── Interfaces/
|
|
│ └── Stock/ (StockService, FifoCostingService)
|
|
├── Repositories/ # EF data access (entities)
|
|
│ └── Interfaces/
|
|
├── Domain/
|
|
│ ├── Entities/ # 38 EF entities
|
|
│ └── Enums/ # ItemType, TrackingMode, HoldStatus, Direction, *Status
|
|
├── Dtos/ # request/response DTOs (+ Common: paging)
|
|
├── Common/Models/ # PagedResult<T>, PaginationMeta, Result<T>
|
|
├── Infra/
|
|
│ ├── UoW/ # IUnitOfWork, UnitOfWork
|
|
│ ├── Persistence/ # ErpDbContext, Configurations/, Migrations/
|
|
│ ├── Auth/ # JWT setup, ICurrentUser (audit source)
|
|
│ └── Logging/ # Serilog config
|
|
├── System/Errors/ # domain exceptions, error codes, ProblemDetails middleware
|
|
└── HealthChecks/ # EF Core DB health check
|
|
```
|
|
|
|
### 5.4 Add packages
|
|
Pinned versions below are current for .NET 10 at time of writing. All `Microsoft.EntityFrameworkCore.*` packages **must share the same version**.
|
|
|
|
```bash
|
|
# from Backend/ERPCore/
|
|
dotnet add package Microsoft.EntityFrameworkCore --version 10.0.9
|
|
dotnet add package Microsoft.EntityFrameworkCore.Design --version 10.0.9
|
|
dotnet add package Microsoft.EntityFrameworkCore.Tools --version 10.0.9
|
|
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 10.0.2
|
|
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer --version 10.0.9
|
|
dotnet add package Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore --version 10.0.9
|
|
dotnet add package Serilog.AspNetCore --version 9.0.0
|
|
dotnet add package Serilog.Sinks.File --version 6.0.0
|
|
dotnet add package Swashbuckle.AspNetCore --version 10.2.3
|
|
```
|
|
|
|
Resulting `ERPCore.csproj`:
|
|
```xml
|
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
|
|
<PropertyGroup>
|
|
<TargetFramework>net10.0</TargetFramework>
|
|
<Nullable>enable</Nullable>
|
|
<ImplicitUsings>enable</ImplicitUsings>
|
|
</PropertyGroup>
|
|
|
|
<ItemGroup>
|
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.9" />
|
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.9">
|
|
<PrivateAssets>all</PrivateAssets>
|
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
</PackageReference>
|
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.9">
|
|
<PrivateAssets>all</PrivateAssets>
|
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
</PackageReference>
|
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.2" />
|
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.9" />
|
|
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.9" />
|
|
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
|
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.3" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<Folder Include="Common\Models\" />
|
|
<Folder Include="Infra\UoW\" />
|
|
<Folder Include="System\Errors\" />
|
|
</ItemGroup>
|
|
|
|
</Project>
|
|
```
|
|
> **Swashbuckle v10 note:** v10 upgraded to `Microsoft.OpenApi` 2.x and emits **OpenAPI 3.1**. `Program.cs` uses `using Microsoft.OpenApi;` and `AddSwaggerGen(...)` / `UseSwagger()` / `UseSwaggerUI()`.
|
|
|
|
### 5.5 App settings (three files)
|
|
`appsettings.json` (base — no real secrets; placeholder only):
|
|
```json
|
|
{
|
|
"Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } },
|
|
"ConnectionStrings": {
|
|
"DefaultConnection": "Host=localhost;Port=5432;Database=ERPCore;Username=CHANGE_ME;Password=CHANGE_ME"
|
|
},
|
|
"Jwt": {
|
|
"Issuer": "ERPCore",
|
|
"Audience": "ERPCore.Clients",
|
|
"SigningKey": "CHANGE_ME_DEV_ONLY_32+_CHARS",
|
|
"AccessTokenMinutes": 120
|
|
},
|
|
"AllowedHosts": "*"
|
|
}
|
|
```
|
|
`appsettings.Development.json` (local dev — used by `dotnet run` in Development):
|
|
```json
|
|
{
|
|
"ConnectionStrings": {
|
|
"DefaultConnection": "Host=localhost;Port=5432;Database=ERPCore;Username=postgres;Password=postgres"
|
|
},
|
|
"Jwt": { "SigningKey": "dev-only-signing-key-please-change-me-0123456789" }
|
|
}
|
|
```
|
|
`appsettings.Production.json` (values injected from environment variables at deploy time):
|
|
```json
|
|
{
|
|
"ConnectionStrings": { "DefaultConnection": "" },
|
|
"Jwt": { "SigningKey": "" }
|
|
}
|
|
```
|
|
> **Secrets note (current phase):** we are on **localhost dev only**, so the Development file holds local credentials for convenience. Before any shared/staging/production use, move secrets to **User Secrets** (dev) and **environment variables** (prod), keep `appsettings.Development.json` / `appsettings.Production.json` out of git (see root `.gitignore`), and rotate any credential that was ever committed.
|
|
|
|
### 5.6 Minimal `Program.cs` wiring (outline)
|
|
```csharp
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.OpenApi;
|
|
using Serilog;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// Serilog (file sink)
|
|
builder.Host.UseSerilog((ctx, cfg) => cfg
|
|
.ReadFrom.Configuration(ctx.Configuration)
|
|
.WriteTo.File("logs/erpcore-.log", rollingInterval: RollingInterval.Day));
|
|
|
|
builder.Services.AddControllers();
|
|
|
|
// EF Core + PostgreSQL
|
|
builder.Services.AddDbContext<ErpDbContext>(o =>
|
|
o.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
|
|
|
|
// ProblemDetails (RFC 7807)
|
|
builder.Services.AddProblemDetails();
|
|
|
|
// JWT bearer auth (RBAC deferred; identity used for audit stamp)
|
|
builder.Services.AddAuthentication(/* JwtBearer options from config */);
|
|
builder.Services.AddAuthorization();
|
|
|
|
// Health checks (EF Core DB)
|
|
builder.Services.AddHealthChecks().AddDbContextCheck<ErpDbContext>();
|
|
|
|
// Swagger
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddSwaggerGen(o => o.SwaggerDoc("v1", new() { Title = "ERPCore API", Version = "v1" }));
|
|
|
|
// DI: register UoW, repositories, services, ICurrentUser, FifoCostingService here
|
|
|
|
var app = builder.Build();
|
|
|
|
if (app.Environment.IsDevelopment())
|
|
{
|
|
app.UseSwagger();
|
|
app.UseSwaggerUI();
|
|
}
|
|
app.UseExceptionHandler(); // maps to ProblemDetails
|
|
app.UseAuthentication();
|
|
app.UseAuthorization();
|
|
app.MapControllers();
|
|
app.MapHealthChecks("/health");
|
|
app.Run();
|
|
```
|
|
|
|
### 5.7 Create the database and run
|
|
```bash
|
|
# ensure the ERPCore database exists in your local Postgres, then:
|
|
dotnet ef migrations add InitialCreate -o Infra/Persistence/Migrations
|
|
dotnet ef database update
|
|
dotnet run
|
|
```
|
|
**Verify:**
|
|
- Swagger UI at `https://localhost:<port>/swagger`
|
|
- Health at `https://localhost:<port>/health` → `Healthy`
|
|
|
|
Entity/DbContext modeling (the 42 entities, configurations, enums) is specified in `10-BACKEND-PHASE1.md`. Do not invent the schema here — follow that file.
|
|
|
|
---
|
|
|
|
## 6. Running the frontend
|
|
|
|
The Frontend is already initialized. Point it at the backend:
|
|
```bash
|
|
cd Frontend
|
|
cp .env.local.example .env.local # set NEXT_PUBLIC_API_BASE_URL=https://localhost:<port>
|
|
npm install
|
|
npm run dev
|
|
```
|
|
All frontend work is governed by `20-FRONTEND.md`.
|
|
|
|
---
|
|
|
|
## 7. Routing — where to go next
|
|
|
|
**Every task starts here, then jumps to the right doc.** Do not work from memory; open the target doc.
|
|
|
|
| If you are working on… | Go to |
|
|
|---|---|
|
|
| Requirements, business rules, entities, ER model, data types, architecture detail (Phase 1: Inventory & Supply Chain) | **`10-BACKEND-PHASE1.md`** |
|
|
| API endpoints, request/response shapes, error catalog, enums (Phase 1) | **`11-BACKEND-PHASE1.md`** |
|
|
| HRM requirements, business rules, entities, ER model (Phase 2) | **`12-BACKEND-HRM.md`** |
|
|
| HRM API endpoints, request/response shapes, error catalog (Phase 2) | **`13-BACKEND-HRM-API.md`** |
|
|
| Frontend user-flows, screen flow, architecture rules, validation posture (Phase 1) | **`20-FRONTEND.md`** |
|
|
| HRM frontend user-flows (Phase 2) | **`21-FRONTEND-HRM.md`** |
|
|
| Manufacturing requirements, business rules, entities, stock/costing integration, API (Phase 2) | **`30-BACKEND-PHASE2.md`** |
|
|
| Manufacturing frontend user-flows — template canvas, run board, run execution (Phase 2) | **`21-FRONTEND-PHASE2.md`** |
|
|
| Security risks per feature, accepted-risk register, pre-ship checklist | **`02-SECURITY.md`** |
|
|
| Understanding the doc system, reading order, tracking conventions | **`01-DOC-GUIDE.md`** |
|
|
| Recording backend changes made | **`Backend/PROGRESS.md`** |
|
|
| Recording frontend changes made | **`Frontend/PROGRESS.md`** |
|
|
|
|
Quick resolver:
|
|
- *"Where is the model / an entity defined?"* → `10-BACKEND-PHASE1.md` (Phase 1) / `12-BACKEND-HRM.md` (HRM) — schema is authoritative there.
|
|
- *"What does this endpoint accept/return?"* → `11-BACKEND-PHASE1.md` (Phase 1) / `13-BACKEND-HRM-API.md` (HRM).
|
|
- *"How should the UI flow / what do I validate where?"* → `20-FRONTEND.md` (Phase 1) / `21-FRONTEND-HRM.md` (HRM).
|
|
- *"What security risks / checks apply to this feature?"* → `02-SECURITY.md`.
|
|
|
|
---
|
|
|
|
## 8. Progress tracking (mandatory)
|
|
|
|
Two checklists track what has actually been built, and travel with code via git:
|
|
- **`Backend/PROGRESS.md`** — backend changes
|
|
- **`Frontend/PROGRESS.md`** — frontend changes
|
|
|
|
These are **Claude-maintained**: whenever a change is made on either side, the corresponding `PROGRESS.md` must be updated (tick items, add entries). The format and rules for these files are defined in **`01-DOC-GUIDE.md` §Tracking**. Both files must exist before feature work begins.
|
|
|
|
> **Security gate:** before ticking any data-mutating feature `[x]`, run its checklist in **`02-SECURITY.md`** (Part C) plus the foundational controls (Part B). Accepted Phase-1 exposures are recorded in `02-SECURITY.md` Part A — do not "fix" them ad-hoc.
|
|
|
|
---
|
|
|
|
## 9. Documentation maintenance rule
|
|
|
|
There is **one source of truth** per topic. The SRS and API content live **inside** the docs above (not in separate scattered files). When a requirement or endpoint changes, edit it **in place** in `10-`/`11-BACKEND-PHASE1.md` — do not fork copies. See `01-DOC-GUIDE.md` for the full maintenance and navigation rules.
|
|
|
|
---
|
|
|
|
*End of 00-CORE.md — the hub. Next: `01-DOC-GUIDE.md`.*
|