feat(stock): sayım oturumları, fire ayarlı öneri motoru ve tüketim analizi

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-06 10:58:06 +03:00
parent 5e0f1b5901
commit 814bdbbc2a
12 changed files with 1219 additions and 69 deletions
+77 -2
View File
@@ -935,6 +935,67 @@ export const tr = {
"Evdeki ürünlerin miktarı, kritik eşik ve son kullanma tarihleri. Stok ürün tipi düzeyinde tutulur.",
newProduct: "Yeni ürün tipi",
categoriesLink: "Stok kategorileri",
countLink: "Sayım",
analysisLink: "Tüketim analizi",
countNote: "Sayım",
countDue: {
title: "Sayımı gelenler",
description:
"Sayım sıklığı dolan kategoriler. Sıklık ürün tipinde veya stok kategorisinde ayarlanır.",
products: (n: number) => `${n} ürün`,
overdue: (days: number) => (days > 0 ? `${days} gün gecikti` : "Bugün"),
start: "Sayıma başla",
},
count: {
title: "Sayım",
description:
"Evdeki gerçek miktarları girin. Kayıtlarla arasındaki fark sayım düzeltmesi olur; eksiğin bir kısmını fire olarak işaretleyebilirsiniz. Boş bıraktığınız ürünler sayılmaz.",
back: "Ev stoğuna dön",
allCategories: "Tüm stok",
category: "Kategori",
dueCount: (n: number) => `${n} sayımı gelen`,
onlyDue: "Yalnızca sayımı gelenler",
expected: "Beklenen",
actual: "Sayılan",
diff: "Fark",
same: "Aynı",
markWaste: "Eksiğin bir kısmı fire",
wasteQuantity: "Fire miktarı",
wasteMax: (q: string) => `En çok ${q}`,
dueBadge: (days: number) => (days > 0 ? `Sayım ${days} gün gecikti` : "Sayım bugün"),
lastCount: (date: string) => `Son sayım ${date}`,
neverCounted: "Hiç sayılmadı",
fillExpected: "Beklenenle doldur",
fillExpectedHint: "Sayılmayan satırlara beklenen miktarı yazar; değişenleri düzeltin.",
clear: "Temizle",
note: "Not",
counted: (n: number) => `${n} ürün sayılacak`,
submit: "Sayımı kaydet",
empty: "Bu kategoride sayılacak ürün yok.",
done: (counted: number, adjusted: number) =>
adjusted
? `${counted} ürün sayıldı; ${adjusted} üründe fark düzeltildi.`
: `${counted} ürün sayıldı; kayıtlarla aynı.`,
},
analysis: {
title: "Tüketim analizi",
description:
"Ürün tipi başına aylık tüketim ve fire. Tüketim: girilen tüketimler ve sayımda çıkan eksikler. Maliyet, ürün fiyatları (Faz 12) gelince eklenecek.",
back: "Ev stoğuna dön",
product: "Ürün tipi",
avgUsed: "Aylık ort. tüketim",
avgWasted: "Aylık ort. fire",
wastePct: "Fire oranı",
thisMonth: "Bu ay",
trend: (n: number) => `Son ${n} ay`,
noData: "—",
empty: "Analiz için ürün tipi yok.",
chartLabel: (name: string) => `${name}: aylık tüketim`,
monthValue: (month: string, used: string, wasted: string) =>
`${month}: tüketim ${used}, fire ${wasted}`,
highWaste: "Fire oranı yüksek",
table: "Tablo",
},
readOnly: "İzleyici rolündesiniz; stoğu değiştiremezsiniz.",
summary: {
products: "Ürün tipi",
@@ -947,6 +1008,10 @@ export const tr = {
description: "Kritik eşiğin altına düşen ürünler ve hedefe tamamlamak için gereken miktar.",
empty: "Eşiğin altına düşen ürün yok.",
suggested: (q: string) => `Öneri: ${q}`,
wasteReduced: (purchases: number, pct: number) =>
`Son ${purchases} alımda %${pct} fire, miktar azaltıldı.`,
roundedByUsage: (week: string) => `Haftalık tüketime (${week}) göre yuvarlandı.`,
covers: (days: number) => `Mevcutla birlikte yaklaşık ${days} gün yeter.`,
},
expiring: {
title: "Son kullanma tarihi",
@@ -1031,6 +1096,13 @@ export const tr = {
target: "Hedef",
threshold: "Eşik",
suggested: "Önerilen alım",
usage: "Tüketim hızı",
perWeek: (q: string) => `Haftada ~${q}`,
noUsage: "Henüz yeterli geçmiş yok",
countSchedule: "Periyodik sayım",
countEvery: (n: number) => `${n} günde bir`,
nextCount: (date: string) => `Sonraki sayım ${date}`,
noCountSchedule: "Sayım sıklığı ayarlanmadı",
location: "Saklama yeri",
lots: "Evdeki partiler",
lotsHint: "Çıkışlar en eski alımdan düşülür (FIFO).",
@@ -1103,17 +1175,20 @@ export const tr = {
wasteReason: "Fire nedenini seçin",
expiryBeforeDate: "Son kullanma tarihi alım tarihinden önce olamaz",
notEnough: (q: string) => `Stokta yalnızca ${q} var.`,
nothingCounted: "En az bir ürünün sayılan miktarını girin.",
wasteOverShortage: (q: string) => `Fire, sayımda çıkan eksikten (${q}) fazla olamaz.`,
emptyStock: "Stok zaten boş.",
duplicate: "Bu adla bir ürün tipi zaten var.",
categoryArchived: "Seçilen stok kategorisi arşivli veya bulunamadı.",
archived: "Ürün tipi arşivli.",
},
dashboard: {
title: "Azalan stoklar",
description: (low: number, expiring: number) =>
title: "Stok uyarıları",
description: (low: number, expiring: number, countDue = 0) =>
[
low ? `${low} ürün eşiğin altında` : null,
expiring ? `${expiring} partinin SKT'si yaklaşıyor` : null,
countDue ? `${countDue} kategoride sayım zamanı` : null,
]
.filter(Boolean)
.join(" · "),