File size: 2,156 Bytes
63f6453
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"""Stok yönetimi: arayüz (sözleşme) testleri için örnek.

Genel API:
    Product(sku, name, price)            -> değişmez veri sınıfı
    Inventory.add(product, qty) -> int   -> yeni stok miktarı
    Inventory.remove(sku, qty) -> int    -> KeyError (yok), ValueError (yetersiz/geçersiz)
    Inventory.total_value() -> float
    Inventory.low_stock(threshold) -> list[str]  (sku listesi, sıralı)
"""
from dataclasses import dataclass, field
from typing import Dict


@dataclass(frozen=True)
class Product:
    sku: str
    name: str
    price: float

    def __post_init__(self):
        if not self.sku:
            raise ValueError("sku zorunlu")
        if self.price < 0:
            raise ValueError("fiyat negatif olamaz")


@dataclass
class Inventory:
    _items: Dict[str, Product] = field(default_factory=dict)
    _stock: Dict[str, int] = field(default_factory=dict)

    def add(self, product: Product, qty: int = 1) -> int:
        if qty <= 0:
            raise ValueError("miktar pozitif olmalı")
        existing = self._items.get(product.sku)
        if existing is not None and existing != product:
            raise ValueError("aynı sku farklı ürünle kullanılamaz")
        self._items[product.sku] = product
        self._stock[product.sku] = self._stock.get(product.sku, 0) + qty
        return self._stock[product.sku]

    def remove(self, sku: str, qty: int = 1) -> int:
        if sku not in self._stock:
            raise KeyError(sku)
        if qty <= 0:
            raise ValueError("miktar pozitif olmalı")
        if self._stock[sku] < qty:
            raise ValueError("yetersiz stok")
        self._stock[sku] -= qty
        if self._stock[sku] == 0:
            del self._stock[sku]
            del self._items[sku]
            return 0
        return self._stock[sku]

    def quantity(self, sku: str) -> int:
        return self._stock.get(sku, 0)

    def total_value(self) -> float:
        return round(sum(self._items[s].price * q for s, q in self._stock.items()), 2)

    def low_stock(self, threshold: int = 5) -> list:
        return sorted(s for s, q in self._stock.items() if q < threshold)