fix(inventory): robustare dedup vid skann + borttag pa startsidan
Dedup vid /v1/scans/:id/confirm matchade bara pa exakt (skiftlageskansligt) namn eller identiskt katalog-id, sa omfotografering av samma hylla skapade dubbletter. Ny normalizeItemName (gemener, accenter, storlek bort; behaller fetthalt-siffror) + matchning pa katalog-id ELLER normaliserat namn mot aktivt hushallslager. Mobil: 'Ta bort' fanns bara i Ditt kok. Lade borttag pa startsidans lager-rader (befintlig DELETE /v1/inventory/items/:id). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WZdew6cWn1MeHqoYWFfxzo
This commit is contained in:
@@ -21,6 +21,27 @@ export interface DedupCandidate {
|
||||
|
||||
const WINDOW_MS = 3 * 86_400_000; // 3 dygn
|
||||
|
||||
/**
|
||||
* Normaliserar ett produktnamn för dubblett-matchning: gemener, bort med
|
||||
* accenter/å/ä/ö, storleksangivelser (500 g, 1 l) och skiljetecken — men
|
||||
* BEHÅLL sifferskillnader som skiljer varianter (mjölk 3 % vs 1,5 %).
|
||||
* "Mjölk", "mjölk", "MJÖLK 1L" → "mjolk"; "Mjölk 3%" → "mjolk 3".
|
||||
*/
|
||||
export function normalizeItemName(name: string): string {
|
||||
return name
|
||||
.normalize("NFC")
|
||||
.toLowerCase()
|
||||
.replace(/[àáâãäå]/g, "a")
|
||||
.replace(/[èéêë]/g, "e")
|
||||
.replace(/[ìíîï]/g, "i")
|
||||
.replace(/[òóôõö]/g, "o")
|
||||
.replace(/[ùúûü]/g, "u")
|
||||
.replace(/\b\d+(?:[.,]\d+)?\s*(?:kg|g|ml|cl|dl|l|st|pack)\b/g, " ")
|
||||
.replace(/[^a-z0-9 ]+/g, " ")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dubblettkandidater mellan kvitto, streckkod och bilder (spec §9).
|
||||
* Ren heuristik – användaren fattar alltid beslutet. AI-baserad
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
findDuplicateCandidates,
|
||||
forecastDepletion,
|
||||
normalizeDelta,
|
||||
normalizeItemName,
|
||||
} from "../src/index.js";
|
||||
|
||||
const TODAY = new Date("2026-08-02T00:00:00Z"); // UTC – testet ska vara sant i alla tidszoner
|
||||
@@ -217,3 +218,14 @@ describe("pantry forecast (spec §40)", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("normalizeItemName (dubblett-matchning vid omfoto)", () => {
|
||||
it("slår ihop skiftläge, accenter och storlek", () => {
|
||||
expect(normalizeItemName("Mjölk")).toBe(normalizeItemName("mjölk"));
|
||||
expect(normalizeItemName("MJÖLK 1L")).toBe(normalizeItemName("Mjölk"));
|
||||
expect(normalizeItemName("Vispgrädde 5 dl")).toBe(normalizeItemName("vispgrädde"));
|
||||
});
|
||||
it("håller isär olika fetthalt/varianter", () => {
|
||||
expect(normalizeItemName("Mjölk 3%")).not.toBe(normalizeItemName("Mjölk 1,5%"));
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user