update dashboard

This commit is contained in:
fatemeh sane
2026-10-21 16:04:07 +03:30
parent 41f93acec5
commit 8b2970cdb5
12 changed files with 1621 additions and 450 deletions
+13 -7
View File
@@ -100,12 +100,14 @@ def _what_filters(
brand_id: uuid.UUID | None,
specs_hash: str | None,
spec_id: str | None = None,
material_family: str | None = None,
) -> dict:
"""دامنه‌ی «چه چیزی» را به پارامترهای سرویس تبدیل می‌کند.
شناسه‌ی ماده اگر UUID معتبر باشد → دامنه‌ی همان ماده (همه‌ی مشخصات آن).
اگر مقدار ارسالی UUID نباشد (یعنی شناسه‌ی مشخصه فرستاده شده) یا spec_id
صریح بیاید → دامنه به همان مشخصه محدود می‌شود (specs_hash).
• شناسه‌ی ماده اگر UUID معتبر باشد → دامنه‌ی همان ماده (همه‌ی مشخصات آن).
• اگر مقدار ارسالی UUID نباشد (یعنی شناسه‌ی مشخصه فرستاده شده) یا spec_id
صریح بیاید → دامنه به همان مشخصه محدود می‌شود (specs_hash).
• material_family → همه‌ی ردیف‌های کاتالوگِ همان خانواده (سرویس حل می‌کند).
"""
resolved_material: uuid.UUID | None = None
resolved_specs = specs_hash or spec_id
@@ -119,6 +121,7 @@ def _what_filters(
"material_id": resolved_material,
"brand_id": brand_id,
"specs_hash": resolved_specs,
"material_family": (material_family or "").strip() or None,
}
@@ -136,13 +139,14 @@ async def inventory_drilldown(
brand_id: uuid.UUID | None = Query(default=None),
specs_hash: str | None = Query(default=None),
spec_id: str | None = Query(default=None, description="دامنه‌ی یک مشخصه‌ی خاص"),
material_family: str | None = Query(default=None, description="خانواده‌ی متریال (نام پایه)"),
):
"""Drill-down matrix: کل سازمان → پروژه → انبار (per-unit aggregates)."""
return await dashboard_service.inventory_drilldown(
db,
project_ids=scope.project_ids,
project_id=scope.project_id,
**_what_filters(material_id, brand_id, specs_hash, spec_id),
**_what_filters(material_id, brand_id, specs_hash, spec_id, material_family),
)
@@ -150,12 +154,13 @@ async def inventory_drilldown(
async def dead_stock(
scope: DashboardScope = Depends(dashboard_scope),
db: AsyncSession = Depends(get_db),
idle_days: int = Query(default=60, ge=1, le=365, description="آستانه رکود (روز)"),
idle_days: int = Query(default=0, ge=0, le=365, description="آستانه رکود (روز) — ۰ یعنی همه"),
limit: int = Query(default=200, ge=1, le=1000),
material_id: str | None = Query(default=None, description="UUID ماده یا شناسه‌ی مشخصه"),
brand_id: uuid.UUID | None = Query(default=None),
specs_hash: str | None = Query(default=None),
spec_id: str | None = Query(default=None, description="دامنه‌ی یک مشخصه‌ی خاص"),
material_family: str | None = Query(default=None, description="خانواده‌ی متریال (نام پایه)"),
):
"""Dead stock: موجودی مثبت بدون هیچ تراکنشی در بازه‌ی رکود."""
return await dashboard_service.dead_stock(
@@ -164,7 +169,7 @@ async def dead_stock(
project_id=scope.project_id,
idle_days=idle_days,
limit=limit,
**_what_filters(material_id, brand_id, specs_hash, spec_id),
**_what_filters(material_id, brand_id, specs_hash, spec_id, material_family),
)
@@ -179,6 +184,7 @@ async def inventory_flow(
brand_id: uuid.UUID | None = Query(default=None),
specs_hash: str | None = Query(default=None),
spec_id: str | None = Query(default=None, description="دامنه‌ی یک مشخصه‌ی خاص"),
material_family: str | None = Query(default=None, description="خانواده‌ی متریال (نام پایه)"),
):
"""Daily flow series: ورود / خروج (با لایه‌ی ضایعات) / برگشت / مانده."""
today = datetime.now(dashboard_service.TEHRAN).date()
@@ -195,7 +201,7 @@ async def inventory_flow(
date_from=datetime.combine(date_from, datetime.min.time(), tzinfo=dashboard_service.TEHRAN),
date_to=datetime.combine(date_to, datetime.min.time(), tzinfo=dashboard_service.TEHRAN),
warehouse_id=warehouse_id,
**_what_filters(material_id, brand_id, specs_hash, spec_id),
**_what_filters(material_id, brand_id, specs_hash, spec_id, material_family),
)