Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 60056b94bf | |||
| 60ab2465aa |
@@ -295,9 +295,13 @@ export class ReceiptImportService {
|
|||||||
? this.applyContradictionGuard(signalText || item.rawName, nextSuggestion, categories)
|
? this.applyContradictionGuard(signalText || item.rawName, nextSuggestion, categories)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
const finalSuggestion = guardedSuggestion
|
||||||
|
? this.applyHardCategoryOverrides(signalText || item.rawName, guardedSuggestion, categories)
|
||||||
|
: null;
|
||||||
|
|
||||||
enriched.push(
|
enriched.push(
|
||||||
guardedSuggestion
|
finalSuggestion
|
||||||
? { ...item, categorySuggestion: guardedSuggestion }
|
? { ...item, categorySuggestion: finalSuggestion }
|
||||||
: item,
|
: item,
|
||||||
);
|
);
|
||||||
} catch {
|
} catch {
|
||||||
@@ -309,6 +313,43 @@ export class ReceiptImportService {
|
|||||||
return enriched;
|
return enriched;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private applyHardCategoryOverrides(
|
||||||
|
signalText: string,
|
||||||
|
suggestion: CategorySuggestion,
|
||||||
|
categories: Awaited<ReturnType<CategoriesService['findFlattened']>>,
|
||||||
|
): CategorySuggestion {
|
||||||
|
const normalized = normalizeForRules(signalText);
|
||||||
|
const hasBaconLikeSignal =
|
||||||
|
/\bbacon\b/.test(normalized) ||
|
||||||
|
/\bbacn\b/.test(normalized) ||
|
||||||
|
/\bbaco\b/.test(normalized) ||
|
||||||
|
/\bbac[a-z]{1,3}\b/.test(normalized) ||
|
||||||
|
/\bsidflask\b/.test(normalized) ||
|
||||||
|
/\bpancetta\b/.test(normalized);
|
||||||
|
|
||||||
|
if (!hasBaconLikeSignal) return suggestion;
|
||||||
|
|
||||||
|
const l3Pork = categories.find(
|
||||||
|
(c) =>
|
||||||
|
c.name.toLowerCase() === 'fläsk' &&
|
||||||
|
c.path.toLowerCase().startsWith('kött, chark & fågel > kött > '),
|
||||||
|
);
|
||||||
|
if (!l3Pork) return suggestion;
|
||||||
|
|
||||||
|
if (suggestion.categoryId === l3Pork.id) return suggestion;
|
||||||
|
|
||||||
|
this.logger.log(
|
||||||
|
`Hard-override: "${signalText}" remappas från "${suggestion.path}" till "${l3Pork.path}"`,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
categoryId: l3Pork.id,
|
||||||
|
categoryName: l3Pork.name,
|
||||||
|
path: l3Pork.path,
|
||||||
|
confidence: 'high',
|
||||||
|
usedFallback: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private ruleBasedCategorySuggestion(
|
private ruleBasedCategorySuggestion(
|
||||||
rawName: string,
|
rawName: string,
|
||||||
categories: Awaited<ReturnType<CategoriesService['findFlattened']>>,
|
categories: Awaited<ReturnType<CategoriesService['findFlattened']>>,
|
||||||
|
|||||||
@@ -63,7 +63,23 @@ bool _isPackageLikeUnit(String? unit) {
|
|||||||
required double? quantity,
|
required double? quantity,
|
||||||
required String? unit,
|
required String? unit,
|
||||||
}) {
|
}) {
|
||||||
if (quantity == null || unit == null) {
|
final normalizedUnit = unit?.trim().toLowerCase();
|
||||||
|
final safeCount = (quantity != null && quantity > 0) ? quantity : 1.0;
|
||||||
|
final extracted = _extractPackageSizeFromRawName(rawName);
|
||||||
|
|
||||||
|
// If the receipt name contains size (e.g. "5dl"), prefer it when unit is
|
||||||
|
// missing/unknown or when OCR reports package-like count units (st/pkt/etc).
|
||||||
|
if (extracted != null && (normalizedUnit == null || normalizedUnit.isEmpty || _isPackageLikeUnit(normalizedUnit))) {
|
||||||
|
return (
|
||||||
|
packQuantity: extracted.packQuantity,
|
||||||
|
packUnit: extracted.packUnit,
|
||||||
|
packageCount: safeCount,
|
||||||
|
totalQuantity: extracted.packQuantity * safeCount,
|
||||||
|
totalUnit: extracted.packUnit,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quantity == null || normalizedUnit == null || normalizedUnit.isEmpty) {
|
||||||
return (
|
return (
|
||||||
packQuantity: null,
|
packQuantity: null,
|
||||||
packUnit: null,
|
packUnit: null,
|
||||||
@@ -73,8 +89,7 @@ bool _isPackageLikeUnit(String? unit) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final looksLikePackage = _isPackageLikeUnit(unit);
|
final looksLikePackage = _isPackageLikeUnit(normalizedUnit);
|
||||||
final extracted = _extractPackageSizeFromRawName(rawName);
|
|
||||||
|
|
||||||
if (looksLikePackage && extracted != null) {
|
if (looksLikePackage && extracted != null) {
|
||||||
return (
|
return (
|
||||||
@@ -88,10 +103,10 @@ bool _isPackageLikeUnit(String? unit) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
packQuantity: quantity,
|
packQuantity: quantity,
|
||||||
packUnit: unit,
|
packUnit: normalizedUnit,
|
||||||
packageCount: 1,
|
packageCount: 1,
|
||||||
totalQuantity: quantity,
|
totalQuantity: quantity,
|
||||||
totalUnit: unit,
|
totalUnit: normalizedUnit,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user