feat(shopping): alışveriş listeleri, stok eşiği önerileri ve akıllı mağaza önerisi motoru

- shoppingLists koleksiyonu (ürün tipi / marka / serbest metin kalemleri), migration 015
- planShopping saf fonksiyonu: paket yuvarlama, zahmet ve hacimli cezası, teslimat, yemek kartı önceliği, ek mağaza eşiği
- eşik önerileri onay/red (red stok yenilenene kadar), ürün tipine hacimli işareti
- fiyat servisinde ortak loadTypeOffers; seed listeleri ve testler

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-06 23:28:54 +03:00
parent 0b7de17b5c
commit 8ab2244755
21 changed files with 2325 additions and 16 deletions
+28
View File
@@ -0,0 +1,28 @@
import { describe, expect, it } from "vitest";
import { requiredQuantity, suggestionHidden } from "./shopping";
describe("requiredQuantity", () => {
it("ürün tipi kaleminde girilen miktar; boşsa 0", () => {
expect(requiredQuantity({ kind: "type", quantity: 2500 }, null)).toBe(2500);
expect(requiredQuantity({ kind: "type", quantity: null }, null)).toBe(0);
});
it("ürün kaleminde paket adedi × paketin tip karşılığı; boşsa 1 paket", () => {
// 2 paket × 50 yıkama
expect(requiredQuantity({ kind: "product", quantity: 2000 }, 50_000)).toBe(100_000);
expect(requiredQuantity({ kind: "product", quantity: null }, 500)).toBe(500);
expect(requiredQuantity({ kind: "product", quantity: 2000 }, null)).toBe(0);
});
});
describe("suggestionHidden", () => {
const d = (s: string) => new Date(s);
it("reddedilmemişse görünür", () => {
expect(suggestionHidden(null, null)).toBe(false);
});
it("redden sonra alım yoksa gizli, alım gelince yeniden görünür", () => {
expect(suggestionHidden(d("2026-11-01"), null)).toBe(true);
expect(suggestionHidden(d("2026-11-01"), d("2026-10-20"))).toBe(true);
expect(suggestionHidden(d("2026-11-01"), d("2026-11-03"))).toBe(false);
});
});