implement fe with backend
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user