fix(quotes): delivery-note quotes saved markup as 0 on every line
The DN->quote batch copied cost and selling but never wrote markup, so the approval screen showed 0% beside differing cost/selling. Write it at creation, and derive it on the approval page for older lines. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
841121097c
commit
ad4ef77bfd
2 changed files with 22 additions and 2 deletions
|
|
@ -59,6 +59,7 @@ import { quoteStatusClassName, formatQuoteStatus } from "@/lib/quote-status";
|
|||
import {
|
||||
MIN_MARKUP_PERCENT,
|
||||
applyMarkupFloor,
|
||||
markupFromCostAndSelling,
|
||||
sellingFromCostAndMarkup,
|
||||
} from "@/lib/quote-pricing";
|
||||
import { AiItemHistoryTrigger } from "@/components/ai-item-history-trigger";
|
||||
|
|
@ -366,7 +367,15 @@ export default function ApprovalReviewPage() {
|
|||
const getEffectiveMarkup = (item: QuoteItem): number => {
|
||||
const change = pendingChanges[item.id];
|
||||
if (change?.markup !== undefined) return change.markup;
|
||||
return Number(item.markup) || 0;
|
||||
// Older lines (e.g. raised from a delivery note) were saved with
|
||||
// markup 0 although cost and selling differ — derive it then.
|
||||
const stored = Number(item.markup) || 0;
|
||||
const cost = Number(item.cost_price) || 0;
|
||||
const selling = Number(item.selling_price) || 0;
|
||||
if (stored === 0 && cost > 0 && selling > cost) {
|
||||
return markupFromCostAndSelling(cost, selling);
|
||||
}
|
||||
return stored;
|
||||
};
|
||||
const getEffectiveCost = (item: QuoteItem): number =>
|
||||
Number(item.cost_price) || 0;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,10 @@ import { renderDeliveryNotePdf } from "@/lib/pdf/render";
|
|||
import { compressBuffer } from "@/lib/server/attachment-compressor";
|
||||
import { buildDeliveryNoteLine } from "@/lib/pdf/delivery-note-document";
|
||||
import { firstFileName } from "@/lib/file-fields";
|
||||
import { sellingFromCostAndMarkup } from "@/lib/quote-pricing";
|
||||
import {
|
||||
markupFromCostAndSelling,
|
||||
sellingFromCostAndMarkup,
|
||||
} from "@/lib/quote-pricing";
|
||||
import {
|
||||
DELIVERY_NOTE_LETTERHEAD_CODE,
|
||||
deliveryNoteLetterheadCode,
|
||||
|
|
@ -370,6 +373,14 @@ export async function createQuoteFromDeliveryNote(
|
|||
// Selling price is best-effort when unoverridden: copy if set,
|
||||
// otherwise 0 and pricing_source="manual" so the UI flags it.
|
||||
selling_price: sellingPrice,
|
||||
// The markup the approval screen shows. Without it every line
|
||||
// saved as 0% even though cost and selling differ.
|
||||
markup:
|
||||
costPrice > 0 && sellingPrice > 0
|
||||
? override
|
||||
? Number(override.markupPercent) || 0
|
||||
: markupFromCostAndSelling(costPrice, sellingPrice)
|
||||
: 0,
|
||||
notes: it.notes ?? "",
|
||||
sku: it.sku ?? "",
|
||||
// A line counts as PROCESSED once it has both a cost and a
|
||||
|
|
|
|||
Loading…
Reference in a new issue