refactor(ai): enhance AI trace integration and OCR normalization
- Add FlyerTraceSupplement type for AI trace metadata - Implement getFlyerTraceSupplements method to fetch trace supplements - Update AiTraceService to include prompt/rawOutput and counters in flyer traces - Add persistFlyerTrace method to FlyerImportService for trace persistence - Enhance AiFlyerParserService to return structured trace data with prompts and retries - Update FlyerNormalizerService with OCR typo fixes for cheese variants and spröd bakad firre - Improve Flutter admin panel with selectable text, warnings display, and tooltips - Add comprehensive tests for AI trace supplements and normalization rules
This commit is contained in:
@@ -90,4 +90,59 @@ describe('AiTraceService receipt masking', () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns flyer prompt/rawOutput and trace counters from aiTrace supplement', async () => {
|
||||
prismaMock.flyerSession.findUnique.mockResolvedValue({
|
||||
id: 101,
|
||||
userId: 7,
|
||||
createdAt: new Date('2026-05-21T12:00:00.000Z'),
|
||||
sourceFileName: 'willys.pdf',
|
||||
sourceMimeType: 'application/pdf',
|
||||
sourceFileSize: 12345,
|
||||
user: { username: 'admin', email: 'admin@example.com' },
|
||||
items: [
|
||||
{
|
||||
id: 1,
|
||||
rawName: 'Tomat',
|
||||
normalizedName: 'tomat',
|
||||
brand: null,
|
||||
categoryHint: 'Grönsaker',
|
||||
categoryId: null,
|
||||
price: null,
|
||||
priceUnit: null,
|
||||
comparisonPrice: null,
|
||||
comparisonUnit: null,
|
||||
weight: null,
|
||||
bundleWeight: null,
|
||||
isBundle: false,
|
||||
bundleItems: [],
|
||||
offerText: null,
|
||||
parseConfidence: 0.9,
|
||||
parseReasons: ['low_confidence'],
|
||||
matchedProductId: null,
|
||||
matchedProductName: null,
|
||||
matchedVia: 'none',
|
||||
matchConfidence: null,
|
||||
matchReasons: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
prismaMock.aiTrace.findMany.mockResolvedValue([
|
||||
{
|
||||
sessionId: 101,
|
||||
prompt: 'Flyer prompt med email kund@example.com',
|
||||
rawOutput: '{"ok":true}',
|
||||
normalizedOutput: { retryCount: 2, chunkCount: 4 },
|
||||
},
|
||||
]);
|
||||
|
||||
const result = await service.getTraceById('flyer-101');
|
||||
|
||||
expect(result.prompt).toContain('[MASKED]');
|
||||
expect(result.rawOutput).toContain('{"ok":true}');
|
||||
expect(result.retryCount).toBe(2);
|
||||
expect(result.chunkCount).toBe(4);
|
||||
expect(result.warnings).toContain('parse:low_confidence');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user