diff --git a/src/lib/intake-blocks.ts b/src/lib/intake-blocks.ts index e591477..7dbb811 100644 --- a/src/lib/intake-blocks.ts +++ b/src/lib/intake-blocks.ts @@ -155,7 +155,12 @@ export function askCard(c: CardInput): { blocks: Block[]; text: string } { export function duplicateCard(c: { merchant: string | null; total: number | null; transactionId: number | null; captureId: number | null; batchId: string | null; currency?: string | null }): { blocks: Block[]; text: string } { const where = c.transactionId ? `transaction ${c.transactionId}` : c.captureId ? `pantry capture ${c.captureId}` : c.batchId ? `batch ${esc(c.batchId)}` : "an earlier upload"; - const text = `Already handled — ${esc(c.merchant) || "this order"} ${c.total !== null ? money(c.total, c.currency) : ""} is ${where}. Nothing was changed.`.replace(/\s+/g, " "); + // The header (merchant, date, total) IS the identity of a purchase here, so a + // genuine SECOND identical purchase — two of the same coffee, one day, one shop + // — reads as a re-share and is refused. That is the right default (a re-share is + // far commoner than a repeat) but it is a dead end without this sentence: the + // card must say what to do instead, or the ledger quietly loses the second one. + const text = `Already handled — ${esc(c.merchant) || "this order"} ${c.total !== null ? money(c.total, c.currency) : ""} is ${where}. Nothing was changed — if this really is a second, separate purchase, add it in the app.`.replace(/\s+/g, " "); return { text, blocks: [section(`:repeat: ${text}`)] }; }