feat(stock): stok kategorileri, ürün tipleri, hareketler ve FIFO SKT

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-06 08:10:10 +03:00
parent abf2ea6dd7
commit d9de29c18d
18 changed files with 2544 additions and 1 deletions
+192
View File
@@ -929,6 +929,198 @@ export const tr = {
category: "Kategori seçin",
},
},
stock: {
title: "Ev stoğu",
description:
"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",
readOnly: "İzleyici rolündesiniz; stoğu değiştiremezsiniz.",
summary: {
products: "Ürün tipi",
low: "Azalan",
expiring: "SKT yaklaşan",
expired: "SKT geçmiş",
},
suggestions: {
title: "Alınması önerilenler",
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}`,
},
expiring: {
title: "Son kullanma tarihi",
description: "Evde kalan miktarı olan ve SKT'si 7 gün içinde dolan veya geçmiş partiler.",
expired: "Geçti",
soon: "Yaklaşıyor",
on: (date: string) => `SKT ${date}`,
},
list: {
empty: "Henüz ürün tipi yok. “Yeni ürün tipi” ile evdeki ürünleri ekleyin.",
emptyCategory: "Bu kategoride ürün yok.",
search: "Ürün ara",
onlyLow: "Yalnızca azalanlar",
noMatch: "Aramaya uyan ürün yok.",
lowBadge: "Azaldı",
outBadge: "Bitti",
of: (current: string, target: string) => `${current} / ${target}`,
quickConsume: (name: string) => `${name}: 1 azalt`,
quickDone: (name: string, rest: string) => `${name} azaltıldı, kalan ${rest}.`,
},
fields: {
name: "Ad",
namePlaceholder: "ör. Toz Deterjan, Kırmızı Mercimek",
category: "Stok kategorisi",
unit: "Temel ölçü birimi",
customUnit: "Özel birim",
customUnitOption: "Özel birim…",
customUnitPlaceholder: "ör. yıkama, tablet",
target: "Hedef (tam) stok",
targetHint: "Evde bulunmasını istediğiniz tam miktar.",
thresholdPct: "Kritik eşik (%)",
thresholdHint: "Mevcut miktar hedefin bu yüzdesinin altına düşerse ürün önerilir.",
location: "Saklama yeri",
locationPlaceholder: "Kiler, banyo dolabı…",
step: "“1 azalt” miktarı",
stepHint: "Hızlı azaltma düğmesinin düşeceği miktar.",
countEveryDays: "Sayım sıklığı (gün)",
countEveryDaysHint: "Boş bırakılırsa kategoriden devralınır.",
note: "Not",
initialQuantity: "Evdeki mevcut miktar",
initialHint: "Tahmini veya ambalaj üzerinden. Boş bırakılırsa 0 kabul edilir.",
date: "Tarih",
quantity: "Miktar",
wasteReason: "Fire nedeni",
expiryDate: "Son kullanma tarihi",
expiryHint: "İsteğe bağlı. Yaklaşınca uyarı verilir.",
actualQuantity: "Sayılan (gerçek) miktar",
expected: (q: string) => `Kayıtlara göre beklenen: ${q}`,
},
createTitle: "Yeni ürün tipi",
editTitle: "Ürün tipini düzenle",
kinds: {
purchase: "Alım",
consume: "Tüketim",
waste: "Fire / zarar",
count_adjust: "Sayım düzeltmesi",
},
actions: {
purchase: "Alım ekle",
consume: "Tüketim gir",
waste: "Fire gir",
count: "Sayım yap",
},
movementTitles: {
purchase: "Alım ekle",
consume: "Tüketim gir",
waste: "Fire / zarar gir",
},
countTitle: "Sayım yap",
countDescription:
"Evdeki gerçek miktarı girin; kayıtlarla arasındaki fark sayım düzeltmesi olarak işlenir.",
wasteReasons: {
spoiled: "Bozuldu",
expired: "Son kullanma tarihi geçti",
damaged: "Hasar / döküldü",
other: "Diğer",
},
initial: "Başlangıç miktarı",
detail: {
back: "Ev stoğuna dön",
current: "Mevcut",
target: "Hedef",
threshold: "Eşik",
suggested: "Önerilen alım",
location: "Saklama yeri",
lots: "Evdeki partiler",
lotsHint: "Çıkışlar en eski alımdan düşülür (FIFO).",
noLots: "Evde bu üründen yok.",
noExpiry: "SKT yok",
movements: "Hareketler",
noMovements: "Henüz hareket yok.",
after: (q: string) => `Sonra: ${q}`,
archive: "Arşivle",
unarchive: "Arşivden çıkar",
archived: "Arşivli",
archiveTitle: "Ürün tipi arşivlensin mi?",
archiveDescription: (name: string) =>
`“${name}” stok listesinde ve önerilerde görünmez. Hareketleri silinmez; istediğinizde arşivden çıkarabilirsiniz.`,
deleteMovement: "Hareketi sil",
deleteMovementTitle: "Hareket silinsin mi?",
deleteMovementDescription: "Mevcut miktar bu hareket olmadan yeniden hesaplanır.",
},
categories: {
title: "Stok kategorileri",
description:
"Stok kategorileri gider kategorilerinden ayrıdır. Her kategori bir gider kategorisine eşlenebilir; alışveriş tamamlanınca ürünler o gidere yazılır.",
back: "Ev stoğuna dön",
new: "Yeni kategori",
addChild: "Alt kategori ekle",
edit: "Düzenle",
archive: "Arşivle",
unarchive: "Arşivden çıkar",
showArchived: "Arşivi göster",
archived: "Arşivli",
defaultBadge: "Varsayılan",
empty: "Stok kategorisi yok.",
createTitle: "Yeni stok kategorisi",
editTitle: "Stok kategorisini düzenle",
name: "Ad",
parent: "Üst kategori",
noParent: "— Ana kategori —",
expenseCategory: "Gider kategorisi",
expenseInherit: "— Üstten devral —",
expenseHint: "Alışveriş tamamlanınca bu kategorideki ürünlerin yazılacağı gider kategorisi.",
inherited: (name: string) => `${name} (üstten)`,
noExpense: "Eşlenmedi",
countEveryDays: "Sayım sıklığı (gün)",
countEveryDaysHint: "Boş bırakılırsa üst kategoriden devralınır.",
everyDays: (n: number) => `${n} günde bir sayım`,
productCount: (n: number) => `${n} ürün`,
archiveTitle: "Stok kategorisi arşivlensin mi?",
archiveDescription: (name: string) =>
`“${name}” ve alt kategorileri yeni ürünlerde seçilemez.`,
hasProducts:
"Bu kategoride veya altında aktif ürün tipi var; önce onları başka kategoriye taşıyın veya arşivleyin.",
duplicate: "Bu düzeyde aynı adlı bir kategori zaten var.",
expenseInvalid: "Geçerli bir gider kategorisi seçin.",
},
toast: {
saved: "Kaydedildi.",
movementSaved: "Hareket kaydedildi.",
deleted: "Silindi.",
archived: "Arşivlendi.",
unarchived: "Arşivden çıkarıldı.",
counted: (diff: string) => `Sayım kaydedildi; fark ${diff}.`,
noChange: "Sayım kayıtlarla aynı; düzeltme gerekmedi.",
},
validation: {
selectCategory: "Bir stok kategorisi seçin",
quantity: "Geçerli bir miktar girin (ör. 1,5)",
countDays: "1 ile 365 arasında gün sayısı girin",
unit: "Birim 1–20 karakter olmalı",
thresholdPct: "0 ile 100 arasında tam sayı girin",
wasteReason: "Fire nedenini seçin",
expiryBeforeDate: "Son kullanma tarihi alım tarihinden önce olamaz",
notEnough: (q: string) => `Stokta yalnızca ${q} var.`,
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) =>
[
low ? `${low} ürün eşiğin altında` : null,
expiring ? `${expiring} partinin SKT'si yaklaşıyor` : null,
]
.filter(Boolean)
.join(" · "),
more: (n: number) => `+${n} ürün daha`,
open: "Ev stoğuna git",
},
},
prices: {
title: "Fiyat tablosu",
description: