docs(stock): bulk cap 100 + clarify selling-derive precedence

This commit is contained in:
Claude 2026-08-31 16:14:29 +02:00
parent 84a97ac7b2
commit 7c3b8f642a

View file

@ -25,7 +25,7 @@ Editing cost must keep the audit trail honest: when `cost_price` is patched by h
2. **Click "Missing pricing only"** (filter toggle). The list collapses to rows with `selling_price = 0 AND cost_price = 0`. The header subtitle updates to *"N items need pricing"*.
3. **Click "Show pricing columns"** (header toggle). The table grows three right-aligned columns: **Cost (R)**, **Markup %**, **Selling (R)**. Each cell reads either the current numeric value or "—" if zero.
4. **Click "Edit pricing"** (header toggle). The toggle label flips to *"Done editing"*. Every pricing cell across the filtered list becomes a number input. Rows the operator hasn't touched look exactly like read-only values (numbers visible, no input chrome). Every row the operator changes gets a yellow background tint.
5. **Operator edits values.** Cost and markup inputs trigger a derived recompute of selling when both are present: `selling = round(cost × (1 + markup / 100), 2)`. The operator can also type selling directly to override the derived value.
5. **Operator edits values.** When the operator types into Cost or Markup, Selling auto-derives to `round(cost × (1 + markup / 100), 2)` — but only if the operator has NOT manually edited Selling for that row in the current edit-pass. The "Selling manually edited" flag is per-row, reset on row-blur or Apply. If the operator clicks into Selling and types, Selling locks to their value and stops deriving until the row is re-focused or Apply is run.
6. **Local draft persists.** Each keystroke serialises the staged changes into `localStorage` under the key `wfdash.stock.pricingDraft`. A page refresh after a long edit session preserves the work.
7. **Operator clicks "Apply changes"** in the sticky footer. One POST to `/api/v1/stock/items/set-pricing` ships the delta. On success the table re-renders with the new values, the draft clears, the footer disappears.
8. **Per-row outcome.** If a single row fails (PB validation, etc.), that row stays tinted with a red corner badge; the others persist. A toast summarises *"Saved N rows — M failed, click row to retry"*.
@ -148,6 +148,7 @@ Behaviours:
Reject 400 when:
- `updates` is empty, missing, or not an array.
- `updates.length > 100` (matches `bulk_update_quote_items` cap; the page slices if more).
- Any `update` has keys outside `{ id, costPrice, sellingPrice, markup }`.
- Any `update` has `id` empty or not 15-char PB id.
- Numeric fields not finite / negative.