implement fe with backend
This commit is contained in:
@@ -21,6 +21,7 @@ A modular ERP built in phases. **Phase 1** delivers the **Inventory & Supply Cha
|
||||
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`.
|
||||
Sales has its own API reference at `14-BACKEND-SALES-API.md`.
|
||||
|
||||
---
|
||||
|
||||
@@ -45,6 +46,7 @@ erp-monorepo/
|
||||
├── 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)
|
||||
├── 14-BACKEND-SALES-API.md # sales API reference (invoices, slips, free issues, reports)
|
||||
├── 12-GENERAL-LEDGER-INTEGRATION.md # ERPCore ↔ external General Ledger service (transport only)
|
||||
├── 20-FRONTEND.md # frontend user-flows + architecture rules + validation posture
|
||||
└── 21-GENERAL-LEDGER-FRONTEND.md # Ledgers section: reports UI + cash/bank accounts
|
||||
@@ -344,6 +346,7 @@ All frontend work is governed by `20-FRONTEND.md`.
|
||||
| HRM API endpoints, request/response shapes, error catalog (Phase 2) | **`13-BACKEND-HRM-API.md`** |
|
||||
| Connecting to the external General Ledger service (proxy, config, API key) | **`12-GENERAL-LEDGER-INTEGRATION.md`** |
|
||||
| The Ledgers frontend section (reports, cash/bank accounts) | **`21-GENERAL-LEDGER-FRONTEND.md`** |
|
||||
| Sales API endpoints, request/response shapes, error catalog, enums | **`14-BACKEND-SALES-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`** |
|
||||
@@ -356,6 +359,7 @@ All frontend work is governed by `20-FRONTEND.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).
|
||||
- *"What does the sales API accept/return?"* → `14-BACKEND-SALES-API.md`.
|
||||
- *"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`.
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
| `12-BACKEND-HRM.md` | High | HRM backend spec: SRS, ER model, HRM-specific architecture notes. Schema is **authoritative** here. | Any HRM model / business-rule / requirement work (Phase 2). | Claude + humans |
|
||||
| `13-BACKEND-HRM-API.md` | High | HRM **API reference**: every endpoint, error catalog additions, enums. | Any HRM API contract / controller work. | Claude + humans |
|
||||
| `12-GENERAL-LEDGER-INTEGRATION.md` | High | ERPCore ↔ external **General Ledger service**: connection/proxy contract, config, progress. GL's own endpoint contract lives in the GL service's own repo, not here. | Any work touching the GL proxy or a future internal GL caller. | Claude + humans |
|
||||
| `14-BACKEND-SALES-API.md` | High | Sales **API reference**: invoices, slips, free issues, reports, enums. | Any sales API contract / controller work. | Claude + humans |
|
||||
| `20-FRONTEND.md` | High | Frontend **user-flows**, architecture rules to follow, **validation posture**. | Any frontend work (Phase 1). | Claude + humans |
|
||||
| `21-FRONTEND-HRM.md` | High | HRM frontend **user-flows**, screens, validation specifics. | Any HRM frontend work. | Claude + humans |
|
||||
| `30-BACKEND-PHASE2.md` | High | Manufacturing (Production Lines) backend: SRS, ER model, status machines, stock/costing integration, **and** the full API contract — model and API in one doc, unlike Phase 1. Schema is **authoritative** here. | Any manufacturing model / rule / API work. | Claude + humans |
|
||||
@@ -197,7 +198,7 @@ Spec: docs/20-FRONTEND.md (flows + rules) · docs/11-BACKEND-PHASE1.md (API cont
|
||||
## 7. Adding future docs
|
||||
|
||||
When later phases arrive (Sales & CRM, Manufacturing, QC/QA, Accounting), follow the same scheme HRM (Phase 2) established:
|
||||
- Backend spec/API for a phase → new `1x-` files continuing the backend decade (e.g. HRM used `12-BACKEND-HRM.md` + `13-BACKEND-HRM-API.md`, mirroring the `10`/`11` SRS+ER / API-reference split), linked from the hub.
|
||||
- Backend spec/API for a phase → new `1x-` files continuing the backend decade (e.g. HRM used `12-BACKEND-HRM.md` + `13-BACKEND-HRM-API.md`; sales now uses `14-BACKEND-SALES-API.md` alongside the existing phase docs), linked from the hub.
|
||||
- Frontend additions → extend `20-FRONTEND.md` or add `2x-` files (e.g. HRM used `21-FRONTEND-HRM.md`).
|
||||
- Always register the new doc in `00-CORE.md` routing (§7) and in this index (§2).
|
||||
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
# 14 · BACKEND — Sales API Reference
|
||||
|
||||
> **Authoritative for:** sales API contracts for invoices, slips, free issues, and sales reports.
|
||||
> **Navigation:** start from `00-CORE.md`. Sales business rules live in `docs/SALES_MODULE_PLAN.md` and the sales-related backend progress is tracked in `Backend/PROGRESS.md`.
|
||||
> **Scope:** this document covers the sales endpoints currently implemented in ERPCore. Free issue is modeled as a sales-slip alias, not a separate table.
|
||||
|
||||
---
|
||||
|
||||
## 1. Conventions
|
||||
|
||||
- Base URL: `https://{host}/api/v1`
|
||||
- Authentication: same as the rest of the v1 API
|
||||
- Concurrency: `ETag` / `If-Match` on mutable resources
|
||||
- Validation: `ProblemDetails` / `ValidationProblemDetails`
|
||||
|
||||
---
|
||||
|
||||
## 2. Sales Invoices
|
||||
|
||||
### `GET /api/v1/sales-invoices`
|
||||
Query:
|
||||
- `page`
|
||||
- `pageSize`
|
||||
- `q`
|
||||
- `status`
|
||||
- `customerId`
|
||||
- `warehouseId`
|
||||
|
||||
Returns a paged list of `SalesInvoiceSummaryDto`.
|
||||
The current frontend register uses this endpoint directly for the invoice hub view.
|
||||
|
||||
### `GET /api/v1/sales-invoices/{salesInvoiceId}`
|
||||
Returns `SalesInvoiceDto`.
|
||||
The detail page shows the document template and only exposes edit actions when the invoice is `Draft`.
|
||||
|
||||
### `POST /api/v1/sales-invoices`
|
||||
Creates a draft sales invoice.
|
||||
|
||||
Request:
|
||||
```json
|
||||
{
|
||||
"customerId": 2,
|
||||
"warehouseId": 1,
|
||||
"invoiceType": "B2C",
|
||||
"lines": [
|
||||
{
|
||||
"itemId": 1,
|
||||
"uomId": 1,
|
||||
"warehouseId": 1,
|
||||
"qty": 1,
|
||||
"freeQty": 0,
|
||||
"unitPrice": 100,
|
||||
"allowManualPriceOverride": false,
|
||||
"discountMode": "Percentage",
|
||||
"discountPct": 0,
|
||||
"discountAmount": 0,
|
||||
"discountValue": 0,
|
||||
"taxPct": 0,
|
||||
"isFreeIssue": false,
|
||||
"parentLineId": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `PUT /api/v1/sales-invoices/{salesInvoiceId}`
|
||||
Updates a draft invoice. Requires `If-Match`.
|
||||
|
||||
### `POST /api/v1/sales-invoices/{salesInvoiceId}/post`
|
||||
Posts stock out and marks the invoice as `Posted`.
|
||||
Before posting, the UI calls `GET /api/v1/sales-invoices/{salesInvoiceId}/posting-check` to show shortages.
|
||||
|
||||
### `POST /api/v1/sales-invoices/{salesInvoiceId}/cancel`
|
||||
Cancels a draft invoice.
|
||||
|
||||
---
|
||||
|
||||
## 3. Sales Slips
|
||||
|
||||
### `GET /api/v1/sales-slips`
|
||||
Query:
|
||||
- `page`
|
||||
- `pageSize`
|
||||
- `q`
|
||||
- `status`
|
||||
- `customerId`
|
||||
- `warehouseId`
|
||||
|
||||
Returns a paged list of `SalesSlipSummaryDto`.
|
||||
|
||||
### `GET /api/v1/sales-slips/{salesSlipId}`
|
||||
Returns `SalesSlipDto`.
|
||||
The detail page follows the same document-style layout and draft-only edit behavior as invoices.
|
||||
|
||||
### `POST /api/v1/sales-slips`
|
||||
Creates a draft sales slip.
|
||||
|
||||
Request:
|
||||
```json
|
||||
{
|
||||
"customerId": 2,
|
||||
"warehouseId": 1,
|
||||
"cashierUserId": 1,
|
||||
"lines": [
|
||||
{
|
||||
"itemId": 1,
|
||||
"uomId": 1,
|
||||
"warehouseId": 1,
|
||||
"qty": 1,
|
||||
"freeQty": 0,
|
||||
"unitPrice": 50,
|
||||
"allowManualPriceOverride": false,
|
||||
"discountMode": "Percentage",
|
||||
"discountPct": 0,
|
||||
"discountAmount": 0,
|
||||
"discountValue": 0,
|
||||
"taxPct": 0,
|
||||
"isFreeIssue": false,
|
||||
"parentLineId": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `PUT /api/v1/sales-slips/{salesSlipId}`
|
||||
Updates a draft slip. Requires `If-Match`.
|
||||
|
||||
### `POST /api/v1/sales-slips/{salesSlipId}/post`
|
||||
Posts stock out and marks the slip as `Posted`.
|
||||
Before posting, the UI calls `GET /api/v1/sales-slips/{salesSlipId}/posting-check`.
|
||||
|
||||
### `POST /api/v1/sales-slips/{salesSlipId}/cancel`
|
||||
Cancels a draft slip.
|
||||
|
||||
---
|
||||
|
||||
## 4. Free Issues
|
||||
|
||||
Free issue is a business alias over sales slips.
|
||||
There is no separate free-issue table in the current schema.
|
||||
|
||||
### `GET /api/v1/free-issues`
|
||||
Same contract as `GET /api/v1/sales-slips`.
|
||||
|
||||
### `GET /api/v1/free-issues/{freeIssueId}`
|
||||
Same contract as `GET /api/v1/sales-slips/{salesSlipId}`.
|
||||
|
||||
### `POST /api/v1/free-issues`
|
||||
Same contract as `POST /api/v1/sales-slips`.
|
||||
|
||||
### `PUT /api/v1/free-issues/{freeIssueId}`
|
||||
Same contract as `PUT /api/v1/sales-slips/{salesSlipId}`.
|
||||
|
||||
### `POST /api/v1/free-issues/{freeIssueId}/post`
|
||||
Same contract as `POST /api/v1/sales-slips/{salesSlipId}/post`.
|
||||
|
||||
### `POST /api/v1/free-issues/{freeIssueId}/cancel`
|
||||
Same contract as `POST /api/v1/sales-slips/{salesSlipId}/cancel`.
|
||||
|
||||
Business rule:
|
||||
- free issue is represented by `IsFreeIssue=true` and/or `FreeQty>0`
|
||||
- it still posts stock out through the normal slip posting flow
|
||||
- the frontend free-issue screen is the main working page for create/list/edit/cancel
|
||||
- cancelled free-issue records are hidden from the working list view
|
||||
|
||||
---
|
||||
|
||||
## 5. Sales Reports
|
||||
|
||||
### `GET /api/v1/reports/sales`
|
||||
Returns the report catalog.
|
||||
|
||||
Response:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "daily-summary",
|
||||
"name": "Daily Summary",
|
||||
"description": "Aggregated sales by day across posted invoices and slips.",
|
||||
"supportedFilters": ["from", "to"]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### `GET /api/v1/reports/sales/{reportId}`
|
||||
Returns a single report definition by id.
|
||||
|
||||
### `POST /api/v1/reports/sales/query`
|
||||
Returns the actual report data.
|
||||
|
||||
Request:
|
||||
```json
|
||||
{
|
||||
"reportType": "item-summary",
|
||||
"from": "2026-07-01",
|
||||
"to": "2026-07-28",
|
||||
"itemId": 1,
|
||||
"customerId": null,
|
||||
"warehouseId": 1
|
||||
}
|
||||
```
|
||||
|
||||
Supported report types:
|
||||
- `daily-summary`
|
||||
- `item-summary`
|
||||
- `customer-summary`
|
||||
- `warehouse-summary`
|
||||
- `discount-summary`
|
||||
- `free-issue-summary`
|
||||
|
||||
Validation rule:
|
||||
- invalid filters for a given report type are rejected
|
||||
- unsupported report types are rejected
|
||||
- the frontend report page uses the same endpoint for all report types
|
||||
- `daily-summary` auto-loads with a default date range in the UI
|
||||
- the report results table is rendered from the backend response rows, not hardcoded data
|
||||
|
||||
---
|
||||
|
||||
## 6. Notes
|
||||
|
||||
- The sales report service reads both invoices and slips where relevant.
|
||||
- Free issue reporting is derived from the same sales document lines.
|
||||
- There is no separate free-issue table in the current schema.
|
||||
@@ -229,13 +229,15 @@ When an invoice or slip is posted:
|
||||
- `POST /api/v1/sales-slips`
|
||||
- `POST /api/v1/sales-slips/{id}/post`
|
||||
- `POST /api/v1/sales-slips/{id}/cancel`
|
||||
- `GET /api/v1/sales-reports/daily-summary`
|
||||
- `GET /api/v1/sales-reports/item-wise`
|
||||
- `GET /api/v1/sales-reports/customer-wise`
|
||||
- `GET /api/v1/sales-reports/warehouse-wise`
|
||||
- `GET /api/v1/sales-reports/discount-summary`
|
||||
- `GET /api/v1/sales-reports/free-issue-summary`
|
||||
- `GET /api/v1/sales-reports/margin-summary`
|
||||
- `GET /api/v1/free-issues`
|
||||
- `GET /api/v1/free-issues/{id}`
|
||||
- `POST /api/v1/free-issues`
|
||||
- `PUT /api/v1/free-issues/{id}`
|
||||
- `POST /api/v1/free-issues/{id}/post`
|
||||
- `POST /api/v1/free-issues/{id}/cancel`
|
||||
- `GET /api/v1/reports/sales`
|
||||
- `GET /api/v1/reports/sales/{reportId}`
|
||||
- `POST /api/v1/reports/sales/query`
|
||||
|
||||
### Phase 1 Folder / Module Plan
|
||||
- `Domain/Entities`
|
||||
@@ -264,7 +266,7 @@ When an invoice or slip is posted:
|
||||
4. Pricing resolver
|
||||
5. Discount computation
|
||||
6. Free issue handling
|
||||
7. Stock posting and ledger integration
|
||||
7. Stock posting
|
||||
8. Basic sales reports
|
||||
9. Controllers and swagger wiring
|
||||
|
||||
|
||||
Reference in New Issue
Block a user