fix(kvitto): visa produkter fran kvittoscanning (mappa lines -> items)

Gemini laste kvittot korrekt men resultatet ('lines') slangdes bort: hela
bekraftelseflodet (app scan-review + API extractProposals/annotate) forvantar
sig 'items' i foto-format. Darfor blev VARJE kvitto tomt. Mappar nu icke-
rabattrader till items och kor samma kanoniska namnmatchning som for foton.
This commit is contained in:
Claude
2026-08-19 19:01:14 +00:00
parent bde08a0d2f
commit c13edae2fa
+23
View File
@@ -67,6 +67,29 @@ export async function processScanJob(ctx: WorkerContext, scanJobId: string): Pro
output = await mapDetectedItemsToCanonical(ctx, output);
}
// Kvitto (READ_RECEIPT) ger 'lines', men hela bekräftelseflödet (app-vyn
// scan-review + API:ts extractProposals/annotateScanDuplicates) förväntar sig
// 'items' i samma format som kylskåps-/skafferiscanning. Utan mappning blev
// varje kvitto TOMT trots att Gemini läste alla rader. Mappa icke-rabattrader
// till items och kör samma kanoniska namnmatchning som för foton.
if (job.jobType === "READ_RECEIPT" && Array.isArray((output as { lines?: unknown }).lines)) {
const lines = (output as { lines: Array<Record<string, unknown>> }).lines;
(output as Record<string, unknown>).items = lines
.filter((l) => l.isDiscount !== true && (l.normalizedName ?? l.rawText))
.map((l, idx) => ({
tempId: String(idx),
detectedName: String(l.normalizedName ?? l.rawText ?? ""),
canonicalIngredientId: (l.canonicalIngredientId as string | null) ?? null,
brand: null,
estimatedQuantity: typeof l.quantity === "number" ? l.quantity : null,
unit: (l.unit as string | null) ?? null,
bestBeforeDate: null,
confidence: typeof l.confidence === "number" ? l.confidence : 0.5,
requiresConfirmation: true,
}));
output = await mapDetectedItemsToCanonical(ctx, output);
}
await ctx.db
.update(schema.scanJobs)
.set({