feat(woo): select multiple orders and book them with one template sweep (#1900)
* feat(woo): select multiple orders and book them with one template sweep Adds bulk booking to the orders page (issue #1880): hover-reveal checkbox column, a bulkbar with select-all/clear, and a confirm dialog that books every selected order with the standard order template (per-store payment- method mapping, optionally one override account for the whole selection). Server side, POST /api/webshop-orders/bulk-book books each order as its OWN verifikat through the exact same flow as the single-order endpoint: the guards, FX retry and race-free draft -> claim -> commit sequence are extracted to lib/webshop-orders/book-order.ts and shared by both routes, so nothing added to the single path can miss the bulk path. Partial failure is reported per order and never aborts the batch. Fixes #1880 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(woo): replace mangled NUL byte in bulk dialog grouping key with a pipe The account-group key template literal picked up a raw 0x00 byte during generation (known escape-mangling hazard), making git treat the file as binary. Same grouping semantics, plain '|' separator. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(woo): bulk sweep only books derived lines, never guessed ones (skeptic findings) The sweep has no reviewing user, so everything the single dialog relies on a human to catch is now refused per order or aborted: - empty vat_breakdown: the ratio-inferred fallback split (a 25%+6% mixed sale classified as 12%, refunds reversing zero moms via 3004) is only allowed as the single dialog's editable prefill; bulk refuses with WEBSHOP_ORDER_VAT_BREAKDOWN_MISSING - invoice-mode payment methods: booking would foreclose Skapa faktura and post a wrong clearing leg; refused with WEBSHOP_ORDER_INVOICE_MODE_METHOD (the account override does not bypass the merchant's configured flow) - 3740 residual above ore scale (gift-card gaps booked as 'oresavrundning'): refused with WEBSHOP_ORDER_RESIDUAL_TOO_LARGE - settings-fetch failure now aborts the sweep instead of silently rebooking every order to 1686 against the confirmed dialog - maxDuration 300 so a platform kill cannot strand an order between claim and commit - per-order guard details (e.g. journal_entry_id) survive into the failure envelope The dialog mirrors the skip rules up front (named order numbers, not an anonymous count) so the confirmation describes exactly what will book. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(woo): refuse non-Swedish VAT-rate buckets in the bulk sweep A foreign OSS bucket (e.g. German 19%) passes the non-empty breakdown gate with zero residual, but the rate-to-account maps would fall back to the 25% accounts and book foreign VAT as Swedish utgaende moms 2611 (skeptic finding). The sweep now refuses such orders per order with WEBSHOP_ORDER_UNSUPPORTED_VAT_RATE (details.rates names the offending rates); the dialog mirrors the rule and names the skipped orders. Only the single dialog may show that prefill, as an editable guess. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
5fc0be9ed7
commit
c634430677
@@ -3900,6 +3900,34 @@ const WEBSHOP_ORDERS: Record<string, StructuredErrorEntry> = {
|
||||
message_en:
|
||||
'The order was invoiced through a customer invoice. Handle the refund with a credit note instead of booking the refund row directly.',
|
||||
},
|
||||
WEBSHOP_ORDER_VAT_BREAKDOWN_MISSING: {
|
||||
httpStatus: 422,
|
||||
message_sv:
|
||||
'Ordern saknar momsuppdelning från butiken, så konteringen kan inte härledas säkert. Bokför ordern enskilt och granska raderna.',
|
||||
message_en:
|
||||
'The order has no VAT breakdown from the store, so the posting cannot be derived reliably. Book the order individually and review the lines.',
|
||||
},
|
||||
WEBSHOP_ORDER_INVOICE_MODE_METHOD: {
|
||||
httpStatus: 409,
|
||||
message_sv:
|
||||
'Betalsättet är markerat som fakturaflöde i butiksinställningarna. Skapa faktura från ordern i stället, eller bokför den enskilt.',
|
||||
message_en:
|
||||
'The payment method is marked as invoice flow in the store settings. Create an invoice from the order instead, or book it individually.',
|
||||
},
|
||||
WEBSHOP_ORDER_UNSUPPORTED_VAT_RATE: {
|
||||
httpStatus: 422,
|
||||
message_sv:
|
||||
'Ordern har en momssats som inte är en svensk sats (25/12/6/0 %), till exempel utländsk OSS-moms. Bokför ordern enskilt och granska raderna.',
|
||||
message_en:
|
||||
'The order has a VAT rate that is not a Swedish rate (25/12/6/0 %), for example foreign OSS VAT. Book the order individually and review the lines.',
|
||||
},
|
||||
WEBSHOP_ORDER_RESIDUAL_TOO_LARGE: {
|
||||
httpStatus: 422,
|
||||
message_sv:
|
||||
'Orderns belopp stämmer inte med momsuppdelningen (differensen är större än öresavrundning). Bokför ordern enskilt och granska raderna.',
|
||||
message_en:
|
||||
'The order total does not match its VAT breakdown (the difference is larger than öre rounding). Book the order individually and review the lines.',
|
||||
},
|
||||
WEBSHOP_ORDER_CREATE_INVOICE_CUSTOMER_FAILED: {
|
||||
httpStatus: 500,
|
||||
message_sv: 'Kunden kunde inte skapas från orderns uppgifter.',
|
||||
|
||||
Reference in New Issue
Block a user