Initial commit for push folder

This commit is contained in:
Nguyen Hong Van 2026-09-18 09:13:53 +09:00
commit c4af9fcbb5
82 changed files with 3294 additions and 0 deletions

View file

@ -0,0 +1,90 @@
"""
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']}")