Files
geMoldInsight/src/inventory/services/dashboard_service.py
T

72 lines
3.0 KiB
Python
Raw Normal View History

"""仪表盘聚合业务服务层
将 dashboard_routes 中的聚合查询与统计编排下沉到此,
路由层只做依赖注入与响应返回。
"""
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from inventory.models import Customer, Inventory, Product, PurchaseOrder, SalesOrder, Supplier, Warehouse
class DashboardService:
"""仪表盘统计服务"""
@staticmethod
async def get_dashboard(db_session: AsyncSession) -> dict:
material_count = await db_session.scalar(
select(func.count(Product.id)).where(Product.is_active == True, Product.item_type == "material")
) or 0
finished_product_count = await db_session.scalar(
select(func.count(Product.id)).where(Product.is_active == True, Product.item_type == "finished")
) or 0
supplier_count = await db_session.scalar(select(func.count(Supplier.id)).where(Supplier.is_active == True)) or 0
customer_count = await db_session.scalar(select(func.count(Customer.id)).where(Customer.is_active == True)) or 0
warehouse_count = await db_session.scalar(select(func.count(Warehouse.id)).where(Warehouse.is_active == True)) or 0
total_stock = await db_session.scalar(
select(func.sum(Inventory.quantity))
.join(Product, Inventory.product_id == Product.id)
.where(Product.item_type == "material")
) or 0
total_value = await db_session.scalar(
select(func.sum(Inventory.quantity * Product.cost_price))
.join(Product, Inventory.product_id == Product.id)
.where(Product.item_type == "material")
) or 0
pending_purchase = await db_session.scalar(
select(func.count(PurchaseOrder.id)).where(PurchaseOrder.status == "pending")
) or 0
pending_sales = await db_session.scalar(
select(func.count(SalesOrder.id)).where(SalesOrder.status == "pending")
) or 0
low_stock_products = await db_session.execute(
select(Product, Inventory)
.join(Inventory, Product.id == Inventory.product_id)
.where(Product.item_type == "material")
.where(Inventory.quantity <= Product.min_stock)
.limit(10)
)
low_stock = [
{"id": p.id, "name": p.name, "sku": p.sku, "quantity": i.quantity, "min_stock": p.min_stock}
for p, i in low_stock_products.all()
]
return {
"finished_product_count": finished_product_count,
"material_count": material_count,
"supplier_count": supplier_count,
"customer_count": customer_count,
"warehouse_count": warehouse_count,
"total_stock": total_stock,
"total_value": round(total_value, 2),
"pending_purchase": pending_purchase,
"pending_sales": pending_sales,
"low_stock_products": low_stock,
}
dashboard_service = DashboardService()