Add company-scoped unit list/upsert/delete and article unit patches.
Units are isolated per company; article detail exposes full unit shape, and unused units can be deleted safely via FK NO ACTION.
This commit is contained in:
43
README.md
43
README.md
@@ -117,6 +117,38 @@ Backend mapping:
|
||||
|
||||
---
|
||||
|
||||
## `unit`
|
||||
|
||||
| Method | Signature | Returns |
|
||||
| --- | --- | --- |
|
||||
| `list` | `(googleAuthId, companyId)` | `{ si, basesi, basesifactor, symbol, name }[]` |
|
||||
| `upsert` | `(googleAuthId, companyId, { si, basesi, basesifactor, symbol, name })` | `{ si, basesi, basesifactor, symbol, name }` |
|
||||
| `delete` | `(googleAuthId, companyId, si)` | `void` |
|
||||
|
||||
Shape (überall):
|
||||
|
||||
```js
|
||||
{ si, basesi, basesifactor, symbol, name }
|
||||
```
|
||||
|
||||
`symbol` / `name` come from `unittext` in the company default language (`LEFT JOIN`; missing → `null`). Sorted by `symbol`, `name`, `si`. Units are **company-scoped** (`unit.company_id`); Unique is `(company_id, si)`.
|
||||
|
||||
### `list`
|
||||
|
||||
Auth via `resolveCompanyAccess` (like `getTreeForCompany`). Returns only units of that company. Errors: `Company not found`, `Not authorized`.
|
||||
|
||||
### `upsert`
|
||||
|
||||
Match key `(companyId, si)`. Inserts `unit` + `unittext`, or updates `basesi` / `basesifactor` and upserts `unittext` for the company language. `basesifactor` must be finite and `> 0`. Errors: `Company not found`, `Not authorized`, `Invalid unit`.
|
||||
|
||||
Default article unit `pc` is ensured **per company** on article create (with `unittext` symbol/name `pc` / `Piece` for the company language).
|
||||
|
||||
### `delete`
|
||||
|
||||
Deletes the unit for `(companyId, si)`. Blocked by FK if any article still references it (`Unit in use`). Missing → `Unit not found`. Errors: `Company not found`, `Not authorized`, `Unit not found`, `Unit in use`.
|
||||
|
||||
---
|
||||
|
||||
## `category`
|
||||
|
||||
| Method | Signature | Returns |
|
||||
@@ -143,7 +175,7 @@ Backend mapping:
|
||||
| --- | --- | --- |
|
||||
| `createUnderParent` | `({ googleAuthId, parentId, name })` | `{ id, parentId, name, sku }` |
|
||||
| `getBySku` | `(googleAuthId, sku)` | detail object (see below) |
|
||||
| `updateBySku` | `(googleAuthId, sku, { name })` | same shape as `getBySku` |
|
||||
| `updateBySku` | `(googleAuthId, sku, { name?, unitamount?, unitSi? })` | same shape as `getBySku` |
|
||||
| `setPricesBySku` | `(googleAuthId, sku, [{ price, tax, minmultiplier? }])` | same shape as `getBySku` |
|
||||
| `addImage` | `(googleAuthId, sku, imageBuffer)` | image result (see below) |
|
||||
| `deleteImage` | `(googleAuthId, sku, fullHash)` | `void` |
|
||||
@@ -171,7 +203,7 @@ Backend mapping:
|
||||
{
|
||||
id, sku, name, slug,
|
||||
unitamount, weight,
|
||||
unit: { si },
|
||||
unit: { si, basesi, basesifactor, symbol, name },
|
||||
brand: { name, thumbW, thumbH, thumbHash } | null,
|
||||
categoryIds: number[],
|
||||
photos: { sort, fullHash, thumbW, thumbH, thumbHash }[],
|
||||
@@ -188,7 +220,7 @@ Backend mapping:
|
||||
|
||||
Auth via the article's `categoryarticle` category + `resolveCategoryAccess`. Errors: `Article not found`, `Not authorized`.
|
||||
|
||||
`updateBySku` updates `articletext` (company default language) in a transaction (`name` + slugified `slug`), then returns the same object as `getBySku`. Errors: `Article not found`, `Not authorized`, `Name required`.
|
||||
`updateBySku` patches article fields in a transaction. At least one of `name`, `unitamount`, `unitSi` required. `name` → `articletext` (slugified `slug`); empty name → `Name required`. `unitSi` → existing `unit.si` lookup (no silent ensure); unknown → `Unit not found`. `unitamount` must be finite and `> 0` → `Invalid unitamount`. Returns the same object as `getBySku`. Errors: `Article not found`, `Not authorized`, `Name required`, `Unit not found`, `Invalid unitamount`.
|
||||
|
||||
`setPricesBySku` replaces all `price` rows for the article’s company `poscustomergroup_id` in one transaction. Each entry: `price` → `net`, `tax` → tax rate (ensured via `tax.ensure`), `minmultiplier` defaults to `1`. Empty array clears all POS prices. Returns the same object as `getBySku`. Errors: `Article not found`, `Not authorized`, `POS customer group required`, `Invalid prices`.
|
||||
|
||||
@@ -237,9 +269,12 @@ res.set('Content-Type', thumb.contentType).send(thumb.buffer);
|
||||
| `GET /api/category/tree?companyId=` | `category.getTreeForCompany(googleAuthId, companyId)` |
|
||||
| `POST /api/category` | `category.createUnderParent({ googleAuthId, parentId, name })` |
|
||||
| `DELETE /api/category/:id` | `category.delete({ googleAuthId, id })` |
|
||||
| `GET /api/unit?companyId=` | `unit.list(googleAuthId, companyId)` |
|
||||
| `PUT /api/unit` | `unit.upsert(googleAuthId, companyId, { si, basesi, basesifactor, symbol, name })` |
|
||||
| `DELETE /api/unit` | `unit.delete(googleAuthId, companyId, si)` |
|
||||
| `POST /api/article` | `article.createUnderParent({ googleAuthId, parentId, name })` |
|
||||
| `GET /api/article/:sku` | `article.getBySku(googleAuthId, sku)` |
|
||||
| `PATCH /api/article/:sku` | `article.updateBySku(googleAuthId, sku, { name })` |
|
||||
| `PATCH /api/article/:sku` | `article.updateBySku(googleAuthId, sku, { name?, unitamount?, unitSi? })` |
|
||||
| `PUT /api/article/:sku/prices` | `article.setPricesBySku(googleAuthId, sku, [{ price, tax, minmultiplier? }])` |
|
||||
| `DELETE /api/article/:sku` | `article.delete(googleAuthId, sku)` |
|
||||
| `POST /api/article/:sku/image` | `article.addImage(googleAuthId, sku, imageBuffer)` |
|
||||
|
||||
Reference in New Issue
Block a user