The 3.94.0-beta.0 release PR (#859) failed its backend job on
workflowEngine.test.js: bootCrmDb() runs every core migration in
beforeAll, and with migrations 163-165 merged the setup crossed the
suite's jest.setTimeout(30000) on CI runners — the log shows migration
099 still seeding after the hook timed out. Same pass is green locally
and passed on #857's rebase minutes earlier: borderline-slow, not
deterministic.
- jest.config.js: testTimeout 120000 as the default, so bootCrmDb
suites without an explicit pin stop being time bombs as the chain
grows
- every suite-level jest.setTimeout below 120s raised to 120s — local
pins OVERRIDE the config default, so the 30s/60s ones would keep
flaking regardless of the global bump
No test logic changed anywhere.
Co-authored-by: Paul Nothaft <paul@MacStudio-von-Paul.local>
Drops the isInt({ min: 0 }) constraint on lineItems.*.unitPriceMinor
in both the adminInvoices and adminQuotes POST/PUT validators so
admins can add Treuerabatt / Frühbucherrabatt rows as standalone
negative-priced lines (matches standard DE/CH invoice practice).
A service-layer guard rejects saves whose computed total goes below
zero (INVOICE_TOTAL_NEGATIVE / QUOTE_TOTAL_NEGATIVE, both 400) so a
mis-typed discount can't accidentally mint a credit-balance invoice
that would masquerade as a regular row in dashboards. Credit notes
still belong in the Storno path (createStorno), which is unchanged.
Quote-side integration coverage is omitted for now — createQuote's
cold-require path takes ~30s under the test harness; the invoice
test exercises the same validator + guard shape.