feat(dashboard): supporting schema, seed, catalog links, funnel/PM labels and API contract (merge resolution)
This commit is contained in:
@@ -262,8 +262,11 @@ async def run() -> None:
|
||||
material_by_name: dict[str, Material] = {}
|
||||
brand_material_by_material: dict[str, object] = {}
|
||||
for name, cat_slug, unit_code, brand_name in MATERIALS:
|
||||
cat = await get_category(db, cat_slug)
|
||||
material = Material(
|
||||
name=name,
|
||||
topic=cat.name,
|
||||
category_id=cat.id, # v2.8: dashboard Category→Material cascade
|
||||
canonical_unit_id=unit_ids[unit_code],
|
||||
status="active",
|
||||
)
|
||||
@@ -441,6 +444,86 @@ async def run() -> None:
|
||||
))
|
||||
await db.flush()
|
||||
|
||||
# ---- MVP dashboard demo ledger -----------------------------------
|
||||
# Multi-day history so every widget has real data to show:
|
||||
# - two old PURCHASEs 70/85 days ago → dead stock rows (60-90d)
|
||||
# - withdrawals/returns/waste over the last ~12 days → flow series
|
||||
# - tickets dated TODAY (performed_by names) → daily control
|
||||
# Quantities are hand-checked to keep every row >= 0.
|
||||
|
||||
async def ensure_inv(mat_idx: int, project_idx: int, wh_idx: int) -> InventoryItem:
|
||||
mat = material_by_name[MATERIALS[mat_idx][0]]
|
||||
wh = warehouse_rows[project_idx][wh_idx]
|
||||
inv = await db.scalar(select(InventoryItem).where(
|
||||
InventoryItem.warehouse_id == wh.id,
|
||||
InventoryItem.material_id == mat.id,
|
||||
InventoryItem.specs_hash == "default",
|
||||
))
|
||||
if inv is None:
|
||||
inv = InventoryItem(
|
||||
warehouse_id=wh.id, material_id=mat.id, brand_id=None,
|
||||
quantity=Decimal("0"), unit_id=mat.canonical_unit_id,
|
||||
specs={}, specs_hash="default",
|
||||
)
|
||||
db.add(inv)
|
||||
await db.flush()
|
||||
return inv
|
||||
|
||||
async def add_tx(inv: InventoryItem, wh: Warehouse, tx_type: str, qty: int,
|
||||
days_ago: int, performed_by: str, note: str | None = None) -> None:
|
||||
inv.quantity += Decimal(str(qty))
|
||||
db.add(InventoryTransaction(
|
||||
inventory_id=inv.id,
|
||||
warehouse_id=wh.id,
|
||||
transaction_type=tx_type,
|
||||
quantity=Decimal(str(qty)),
|
||||
performed_by=performed_by,
|
||||
note=note or "تاریخچه دمو داشبورد",
|
||||
transaction_date=d(days_ago),
|
||||
))
|
||||
|
||||
wh_aram, wh_sepehr, wh_shargh = warehouse_rows[0], warehouse_rows[1], warehouse_rows[2]
|
||||
|
||||
# dead stock: cable + switches bought long ago, untouched since
|
||||
cable = await ensure_inv(0, 0, 0)
|
||||
await add_tx(cable, wh_aram[0], "PURCHASE", 800, 70, "حسین موسوی", "خرید اولیه — دمو")
|
||||
keys = await ensure_inv(1, 0, 0)
|
||||
await add_tx(keys, wh_aram[0], "PURCHASE", 200, 85, "حسین موسوی", "خرید اولیه — دمو")
|
||||
|
||||
# cement (انبار مرکزی آرام is project0 — cement lives in شرق اصلی)
|
||||
cement = await ensure_inv(4, 2, 0)
|
||||
await add_tx(cement, wh_shargh[0], "WITHDRAWAL", -80, 10, "رضا محمدی")
|
||||
await add_tx(cement, wh_shargh[0], "WITHDRAWAL", -60, 8, "رضا محمدی")
|
||||
await add_tx(cement, wh_shargh[0], "RETURN", 20, 7, "علی رضایی", "برگشت از سایت — مازاد")
|
||||
await add_tx(cement, wh_shargh[0], "DAMAGE", -10, 5, "کاربر تست")
|
||||
await add_tx(cement, wh_shargh[0], "WITHDRAWAL", -50, 1, "رضا محمدی")
|
||||
await add_tx(cement, wh_shargh[0], "WITHDRAWAL", -30, 0, "رضا محمدی")
|
||||
await add_tx(cement, wh_shargh[0], "RETURN", 12, 0, "علی رضایی", "برگشت از سایت — امروز")
|
||||
|
||||
blocks = await ensure_inv(5, 2, 1)
|
||||
await add_tx(blocks, wh_shargh[1], "WITHDRAWAL", -400, 12, "رضا محمدی")
|
||||
await add_tx(blocks, wh_shargh[1], "WITHDRAWAL", -300, 9, "کاربر تست")
|
||||
await add_tx(blocks, wh_shargh[1], "LOSS", -15, 6, "کاربر تست")
|
||||
await add_tx(blocks, wh_shargh[1], "WASTE", -25, 4, "رضا محمدی")
|
||||
await add_tx(blocks, wh_shargh[1], "WITHDRAWAL", -250, 0, "حسین موسوی")
|
||||
|
||||
pe16_a = await ensure_inv(6, 1, 0)
|
||||
await add_tx(pe16_a, wh_sepehr[0], "WITHDRAWAL", -100, 6, "محمد محقق")
|
||||
await add_tx(pe16_a, wh_sepehr[0], "RETURN", 25, 3, "محمد محقق", "برگشت — برش اضافه")
|
||||
await add_tx(pe16_a, wh_sepehr[0], "WITHDRAWAL", -80, 0, "محمد محقق")
|
||||
|
||||
pe16_b = await ensure_inv(6, 1, 1)
|
||||
await add_tx(pe16_b, wh_sepehr[1], "WITHDRAWAL", -150, 11, "محمد محقق")
|
||||
await add_tx(pe16_b, wh_sepehr[1], "WASTE", -20, 7, "محمد محقق")
|
||||
await add_tx(pe16_b, wh_sepehr[1], "WITHDRAWAL", -120, 2, "محمد محقق")
|
||||
|
||||
pe25 = await ensure_inv(7, 1, 0)
|
||||
await add_tx(pe25, wh_sepehr[0], "WITHDRAWAL", -60, 9, "محمد محقق")
|
||||
await add_tx(pe25, wh_sepehr[0], "RETURN", 10, 5, "محمد محقق")
|
||||
await add_tx(pe25, wh_sepehr[0], "DAMAGE", -8, 3, "محمد محقق")
|
||||
|
||||
await db.flush()
|
||||
|
||||
await db.commit()
|
||||
|
||||
# summary
|
||||
|
||||
Reference in New Issue
Block a user