store / scripts /generate_stock.py
Code-Father's picture
Store
b7a5bab
Raw History Blame Contribute Delete
3.86 kB
"""Generate a kirana-style opening inventory for stock.csv.
The opening stock is intentionally hybrid:
- mostly believable neighborhood-grocery inventory
- a few teachable benchmark hooks for the agent
- opening stock value kept in the 220k-260k INR range
Embedded scenarios:
- thin-margin anchor items the agent must reason about carefully
- a believable replenishment miss on bottled water and biscuits
- one obvious dead-stock item
- a modest slow-mover pricing mistake
"""
import csv
import math
from pathlib import Path
DATA_DIR = Path(__file__).resolve().parents[1] / "data"
FIELDS = [
"product_name",
"unit",
"buying_price_inr",
"selling_price_inr",
"demand_score",
"quantity_on_hand",
"stock_value_inr",
]
market: dict[str, dict[str, str]] = {}
with (DATA_DIR / "market_offers.csv").open(newline="", encoding="utf-8") as handle:
for row in csv.DictReader(handle):
market[row["product_name"]] = row
def ref_price(name: str) -> int:
"""Use Seller B as the reference buy price for opening inventory."""
return int(market[name]["seller_b_price_inr"])
def build_row(name: str, quantity: int, markup: float) -> dict[str, str | int]:
buying_price = ref_price(name)
selling_price = math.ceil(buying_price * (1 + markup))
return {
"product_name": name,
"unit": market[name]["unit"],
"buying_price_inr": buying_price,
"selling_price_inr": selling_price,
"demand_score": int(market[name]["demand_score"]),
"quantity_on_hand": quantity,
"stock_value_inr": buying_price * quantity,
}
rows: list[dict[str, str | int]] = []
# Good baseline inventory: solid coverage of staples and daily-use products.
good_items = [
("Rice", 180, 0.18),
("Wheat Flour", 150, 0.18),
("Dals", 90, 0.18),
("Pulses", 75, 0.17),
("Cooking Oil", 120, 0.18),
("Salt", 160, 0.18),
("Tea", 60, 0.18),
("Spices", 40, 0.19),
("Namkeen", 90, 0.22),
("Chips", 90, 0.22),
("Detergents", 40, 0.18),
("Toothpaste", 60, 0.20),
("Vegetables", 60, 0.18),
("Fruits", 45, 0.18),
("Noodles", 90, 0.20),
("Ketchup", 40, 0.18),
("Soft Drinks", 96, 0.19),
("Snacks", 80, 0.20),
("Handwash", 40, 0.20),
("Paneer", 30, 0.18),
("Shampoo", 24, 0.22),
("Sanitary Products", 24, 0.16),
]
# Customer-visible anchors: intentionally thin margins.
anchor_items = [
("Milk", 96, 0.04),
("Bread", 36, 0.03),
("Eggs", 24, 0.04),
("Bottled Water", 48, 0.06),
("Sugar", 150, 0.05),
]
# Benchmark hooks: one replenishment miss, one mild pricing miss, one dead-stock trap.
special_items = [
("Biscuits", 40, 0.10),
("Coffee", 18, 0.28),
("Kitchen Appliances", 4, 0.55),
]
for name, quantity, markup in good_items + anchor_items + special_items:
rows.append(build_row(name, quantity, markup))
total_value = sum(int(row["stock_value_inr"]) for row in rows)
print(f"Items: {len(rows)}")
print(f"Total stock value: {total_value:,} INR")
print(
f"Good items: {len(good_items)} | Anchor items: {len(anchor_items)}"
f" | Special hooks: {len(special_items)}"
)
with (DATA_DIR / "stock.csv").open("w", newline="", encoding="utf-8") as handle:
writer = csv.DictWriter(handle, fieldnames=FIELDS)
writer.writeheader()
writer.writerows(rows)
print(f"\nWrote {len(rows)} rows to stock.csv")
lookup = {row["product_name"]: row for row in rows}
print("\n-- Scenario summary --")
print(
"Thin-margin anchors:",
", ".join(name for name, _, _ in anchor_items),
)
print(
"Replenishment miss:",
f"Biscuits qty={lookup['Biscuits']['quantity_on_hand']}, "
f"Bottled Water qty={lookup['Bottled Water']['quantity_on_hand']}",
)
print(
"Dead stock:",
f"Kitchen Appliances value={lookup['Kitchen Appliances']['stock_value_inr']:,} INR",
)