""" 数据模型 - 库销比 """ from dataclasses import dataclass from decimal import Decimal from datetime import datetime from typing import Optional @dataclass class PartRatio: """配件库销比数据""" id: int group_id: int brand_id: Optional[int] = None brand_grouping_id: Optional[int] = None supplier_id: Optional[int] = None supplier_name: Optional[str] = None area_id: Optional[int] = None area_name: Optional[str] = None shop_id: int = 0 shop_name: Optional[str] = None part_id: Optional[int] = None part_code: str = "" part_name: Optional[str] = None part_biz_type: Optional[str] = None unit_price: Decimal = Decimal("0") cost_price: Decimal = Decimal("0") storage_total_cnt: Decimal = Decimal("0") in_stock_unlocked_cnt: Decimal = Decimal("0") has_plan_cnt: Decimal = Decimal("0") on_the_way_cnt: Decimal = Decimal("0") out_stock_cnt: Decimal = Decimal("0") storage_locked_cnt: Decimal = Decimal("0") out_stock_ongoing_cnt: Decimal = Decimal("0") buy_cnt: int = 0 transfer_cnt: int = 0 gen_transfer_cnt: int = 0 part_tag: Optional[int] = None stock_age: Optional[int] = None unit: Optional[str] = None out_times: Optional[int] = None statistics_date: str = "" @property def valid_storage_cnt(self) -> Decimal: """有效库存数量 = 在库未锁 + 在途 + 计划数 + 主动调拨在途 + 自动调拨在途""" return (self.in_stock_unlocked_cnt + self.on_the_way_cnt + self.has_plan_cnt + Decimal(str(self.transfer_cnt)) + Decimal(str(self.gen_transfer_cnt))) @property def valid_storage_amount(self) -> Decimal: """有效库存金额""" return self.valid_storage_cnt * self.cost_price @property def avg_sales_cnt(self) -> Decimal: """平均销量 (90天出库数 + 未关单已锁 + 未关单出库 + 订件) / 3""" total = (self.out_stock_cnt or Decimal("0")) + self.storage_locked_cnt + self.out_stock_ongoing_cnt + Decimal(str(self.buy_cnt)) return total / Decimal("3") @property def avg_sales_amount(self) -> Decimal: """平均销量金额""" return self.avg_sales_cnt * self.cost_price @property def current_ratio(self) -> Decimal: """当前库销比""" if self.avg_sales_cnt == 0: return Decimal("999") return self.valid_storage_cnt / self.avg_sales_cnt @classmethod def from_dict(cls, data: dict) -> "PartRatio": """从字典创建""" return cls( id=data.get("id", 0), group_id=data.get("group_id", 0), brand_id=data.get("brand_id"), brand_grouping_id=data.get("brand_grouping_id"), supplier_id=data.get("supplier_id"), supplier_name=data.get("supplier_name"), area_id=data.get("area_id"), area_name=data.get("area_name"), shop_id=data.get("shop_id", 0), shop_name=data.get("shop_name"), part_id=data.get("part_id"), part_code=data.get("part_code", ""), part_name=data.get("part_name"), part_biz_type=data.get("part_biz_type"), unit_price=Decimal(str(data.get("unit_price", 0))), cost_price=Decimal(str(data.get("cost_price", 0))), storage_total_cnt=Decimal(str(data.get("storage_total_cnt", 0))), in_stock_unlocked_cnt=Decimal(str(data.get("in_stock_unlocked_cnt", 0))), has_plan_cnt=Decimal(str(data.get("has_plan_cnt", 0))), on_the_way_cnt=Decimal(str(data.get("on_the_way_cnt", 0))), out_stock_cnt=Decimal(str(data.get("out_stock_cnt", 0))), storage_locked_cnt=Decimal(str(data.get("storage_locked_cnt", 0))), out_stock_ongoing_cnt=Decimal(str(data.get("out_stock_ongoing_cnt", 0))), buy_cnt=int(data.get("buy_cnt", 0)), transfer_cnt=int(data.get("transfer_cnt", 0)), gen_transfer_cnt=int(data.get("gen_transfer_cnt", 0)), part_tag=data.get("part_tag"), stock_age=data.get("stock_age"), unit=data.get("unit"), out_times=data.get("out_times"), statistics_date=data.get("statistics_date", ""), )