product-recognition-demo/recognization/code/inventory.py
2026-09-18 09:13:53 +09:00

90 lines
3.4 KiB
Python

"""
Inventory Management Module
Handles reading and querying product metadata from stock.csv.
"""
import os
import sys
import csv
from typing import Dict, Optional, Any, List
if sys.platform.startswith('win'):
try:
sys.stdout.reconfigure(encoding='utf-8')
except Exception:
pass
class InventoryManager:
def __init__(self, stock_dir: str = "stock", csv_filename: str = "stock.csv"):
self.stock_dir = stock_dir
self.csv_path = os.path.join(stock_dir, csv_filename)
self.products: Dict[str, Dict[str, Any]] = {}
self.load_inventory()
def load_inventory(self) -> None:
"""Loads inventory data from the CSV file."""
if not os.path.exists(self.csv_path):
print(f"[Warning] Inventory CSV not found at: {self.csv_path}")
return
with open(self.csv_path, mode="r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
sku_id = row.get("SKU_ID", "").strip()
if not sku_id:
continue
# Locate the corresponding template image in stock_dir
local_image = self._find_template_image(sku_id)
self.products[sku_id] = {
"sku_id": sku_id,
"product_name": row.get("product_name", "").strip(),
"receipt_date": row.get("receipt_date", "").strip(),
"expiration_date": row.get("expiration_date", "").strip(),
"number_in": int(row.get("number_in", 0) or 0),
"number_out": int(row.get("number_out", 0) or 0),
"number_on": int(row.get("number_on", 0) or 0),
"price": float(row.get("price", 0) or 0),
"raw_image_link": row.get("image_link", "").strip(),
"local_image_path": local_image
}
def _find_template_image(self, sku_id: str) -> Optional[str]:
"""Finds the local image file for the given SKU_ID."""
extensions = [".jpeg", ".jpg", ".png"]
for ext in extensions:
candidate = os.path.join(self.stock_dir, f"{sku_id}{ext}")
if os.path.exists(candidate):
return candidate
return None
def get_product(self, sku_id: str) -> Optional[Dict[str, Any]]:
"""Retrieves product information for a given SKU_ID."""
return self.products.get(sku_id)
def list_all_skus(self) -> List[str]:
"""Returns all available SKU IDs."""
return list(self.products.keys())
def update_stock(self, sku_id: str, quantity_delta: int) -> bool:
"""Updates the on-shelf quantity (e.g., when purchased or restocked)."""
if sku_id in self.products:
current = self.products[sku_id]["number_on"]
new_val = max(0, current + quantity_delta)
self.products[sku_id]["number_on"] = new_val
if quantity_delta < 0:
self.products[sku_id]["number_out"] += abs(quantity_delta)
else:
self.products[sku_id]["number_in"] += quantity_delta
return True
return False
if __name__ == "__main__":
inv = InventoryManager("stock")
print(f"Loaded {len(inv.products)} products.")
for sku in inv.list_all_skus():
p = inv.get_product(sku)
print(f"[{sku}] {p['product_name']} | Price: {p['price']} | In-Stock: {p['number_on']} | Image: {p['local_image_path']}")