This commit is contained in:
seb
2026-10-04 21:22:02 +02:00
parent 45369d11da
commit 3ac713732c
12 changed files with 92 additions and 92 deletions

View File

@@ -30,17 +30,17 @@ Entry: `src/index.js` → `export default class LibDashStore`. Constructor requi
- Company scoping: no `companyId` arg. `resolveSelectedCompanyAccess(provider)` reads `google_auth.selected_company` → `{ companyId, companyuserId, rootCategoryId }`. Missing → throw `No company selected`. Exceptions taking explicit `companyId`: `setSelectedCompany`, `companyuser.add`, `company.delete`, internals.
- SKU resolution: `store/article/resolveArticleBySku.js` (`RESOLVE_ARTICLE_ACCESS_BY_SKU`) checks company + membership. Throws `Article not found` / `Parent not found` / `Not authorized`.
- Errors are plain `Error` with exact message strings; HTTP mapping happens in `dashback` route `*ErrorStatus()` functions. Keep messages stable/greppable. Conflict → `409` (e.g. `EAN already in use`, `Warehouse in use in ledger`, `Stock tracking is disabled...`).
- Manifest docs (`delivery/order/quote/adjustment`): header in `manifest`, lines in `manifestarticle`, helpers in `src/store/manifestLines.js` (`normalizeLines`, `insertLines`, `parseDate`, `shapeLine`) and `manifestDoc/helpers.js`. `insertLines` rejects father articles (`A father article cannot be booked on documents (SKU)`), resolves name/pu, ensures tax.
- Manifest docs (`delivery/order/quote/adjustment`): header in `manifest`, lines in `manifestarticle`, helpers in `src/store/manifestLines.js` (`normalizeLines`, `insertLines`, `parseDate`, `shapeLine`) and `manifestDoc/helpers.js`. `insertLines` rejects parent articles (`A parent article cannot be booked on documents (SKU)`), resolves name/pu, ensures tax.
- Numbers: `store/numbers/nextNumber.js`, types `sku, entity, delivery, adjustment`.
### Ledger + stock (important)
- `ledger` is append-only, tamper-chained: `hash_version=1`, `prev_hash = SHA-512(canonical JSON of prev row)` or `TODO_TSE_BASED_INITHASH` for genesis. See `store/ledger/add.js` (`shape`, `computePrevHash`, `INIT_HASH`).
- Stock is **derived**: `SUM(ledger.amount) GROUP BY warehouse`, joined `ledger → manifestarticle → manifest`, matched on `ma.sku = article.sku OR ma.sku IN (SELECT sku FROM articlesupplier WHERE article_id = ...)`, filtered by `m.company_id`. See `providers/*/queries/article.js` (`warehousesJson`/`stock_calc`) and `posterminal.js` (`fBestand`). No `stock` column on article.
- `store/stock/adjust.js` creates implicit manifest `type='adjustment'` (number from `adjustment` scheme) + one `manifestarticle` line per item (`amount: abs(amount)`) + one `ledger` row per item (`amount: signed`) + `articlehistory` (`Bestandskorrektur ±n (text)`). Validates: father → `A father article cannot have stock (SKU)`; Stückliste (`articlelist_id != null`) → `A Stückliste cannot have manual stock adjustments (SKU)`; **`track_stock==0` → `Stock tracking is disabled for article (SKU)`** (added as bugfix; checked before number allocation/manifest write, so batch is all-or-nothing).
- `store/stock/adjust.js` creates implicit manifest `type='adjustment'` (number from `adjustment` scheme) + one `manifestarticle` line per item (`amount: abs(amount)`) + one `ledger` row per item (`amount: signed`) + `articlehistory` (`Bestandskorrektur ±n (text)`). Validates: parent → `A parent article cannot have stock (SKU)`; Stückliste (`articlelist_id != null`) → `A Stückliste cannot have manual stock adjustments (SKU)`; **`track_stock==0` → `Stock tracking is disabled for article (SKU)`** (added as bugfix; checked before number allocation/manifest write, so batch is all-or-nothing).
- `store/ledger/add.js` enforces the same guard for **any warehouse-scoped entry** (`warehouse_id != null` + line has SKU): looks up `article` by `sku` or `articlesupplier.sku` in same company, rejects if any match has `track_stock==0`. Non-warehouse entries (e.g. `PAYMENT`, memo `NOTE`) are still allowed. Guard runs before `GET_LATEST_ROW`/`INSERT_ROW`, inside the same runner/tx.
- `POST /ledger` with `warehouse_id` is therefore also blocked for untracked articles; delivery receipts booked via ledger go through the same check.
- `article.track_stock`: `BIT/INTEGER DEFAULT 1`. Managed via `article.createUnderParent({track_stock})`, `updateBySku`, `setTrackStockBySku`, `POST /article` (`track_stock`/`trackStock`, default true). `toggleFather` sets `track_stock=0` when becoming father. POS surfaces it as `use_stock '1'/'0'` (`store/posterminal/getProductList.js`).
- `article.track_stock`: `BIT/INTEGER DEFAULT 1`. Managed via `article.createUnderParent({track_stock})`, `updateBySku`, `setTrackStockBySku`, `POST /article` (`track_stock`/`trackStock`, default true). `toggleParent` sets `track_stock=0` when becoming parent. POS surfaces it as `use_stock '1'/'0'` (`store/posterminal/getProductList.js`).
## dashback (Express API)