fix(orders): clamp the AI fill's markup at 0 like every other order line
A line that sells below the quote's cost produced a negative markup. Every other write to an order line's markup stores Math.max(0, computedMarkup), so the fill now does the same. The margin chip is unaffected — it works from cost and selling, not from this field, so a loss-making line still shows its real margin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
34d3422586
commit
0294015ba2
2 changed files with 18 additions and 1 deletions
|
|
@ -550,6 +550,19 @@ describe("buildOrderLineFillPatch", () => {
|
|||
expect(patch?.markup_percent).toBe(50);
|
||||
});
|
||||
|
||||
it("clamps a loss-making markup at 0, like every other order-line write", () => {
|
||||
// The customer's price is below the quote's cost. The margin chip
|
||||
// shows the real margin from cost + selling; the stored markup
|
||||
// follows the app's convention of never going negative.
|
||||
const patch = buildOrderLineFillPatch(
|
||||
fillLine({ selling_price: 8 }),
|
||||
fillQuoteLine({ cost_price: 10, selling_price: 12 }),
|
||||
FILL_CTX,
|
||||
);
|
||||
expect(patch?.markup).toBe(0);
|
||||
expect(patch?.markup_percent).toBe(0);
|
||||
});
|
||||
|
||||
it("adds the price doubt when the customer price differs by more than 5%", () => {
|
||||
const patch = buildOrderLineFillPatch(
|
||||
fillLine({ selling_price: 16.64 }),
|
||||
|
|
|
|||
|
|
@ -260,7 +260,11 @@ export function buildOrderLineFillPatch(
|
|||
// The resulting selling price: the customer's own price when there is
|
||||
// one, otherwise the quoted price.
|
||||
const selling = customerPrice > 0 ? customerPrice : quotedPrice;
|
||||
const markup = cost > 0 && selling > 0 ? round2(((selling - cost) / cost) * 100) : 0;
|
||||
// Clamped at 0, like every other write to an order line's markup
|
||||
// (`orders-service.ts` stores `Math.max(0, computedMarkup)`). A line
|
||||
// that sells below cost still shows its true margin on screen, because
|
||||
// the margin chip works from cost and selling, not from this field.
|
||||
const markup = cost > 0 && selling > 0 ? Math.max(0, round2(((selling - cost) / cost) * 100)) : 0;
|
||||
|
||||
const supplier = (line.supplier ?? "").trim() || (quoteLine.supplier ?? "");
|
||||
const sku = (line.sku ?? "").trim() || (quoteLine.sku ?? "");
|
||||
|
|
|
|||
Loading…
Reference in a new issue