#!/usr/bin/env python3 """批量初始化生产物料示例数据(物料主数据 + 入库批次),已存在编码则跳过。""" from __future__ import annotations import sys from datetime import date, timedelta from decimal import Decimal from pathlib import Path ROOT = Path(__file__).resolve().parents[1] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from app.core.database import SessionLocal from app.crud import production_material as mat_svc from app.crud import production_material_stock_batch as batch_svc # (material_type, material_code, material_name, spec_model, unit, warning_qty, remark) SAMPLE_MATERIALS = [ ( "reagent", "R001", "75% 乙醇溶液", "500mL/瓶", "瓶", 10.0, "实验室常用消毒剂", ), ( "reagent", "R002", "PBS 缓冲液", "1×, pH 7.4", "瓶", 5.0, "细胞培养用磷酸盐缓冲液", ), ( "reagent", "R003", "DMEM 高糖培养基", "500mL/瓶, 含双抗", "瓶", 8.0, "细胞培养基础培养基", ), ( "consumable", "C001", "15mL 离心管", "50支/袋", "袋", 20.0, "实验室常规耗材", ), ( "consumable", "C002", "T25 细胞培养瓶", "1个/包", "包", 15.0, "贴壁细胞培养用", ), ] # 入库批次示例数据(与 SAMPLE_MATERIALS 一一对应) TODAY = date.today() BATCH_ITEMS = [ # R001: 乙醇,入库 20 瓶 dict( material_id=None, # 创建后填充 stockInNo="RK2025061501", stockInDate=TODAY.isoformat(), expireDate=(TODAY + timedelta(days=730)).isoformat(), # 2年后过期 catalogNo="SP-ETH-500", batchNo="B20250601", manufacturer="国药集团化学试剂有限公司", storageLocation="试剂柜-A-01", unitPrice=Decimal("15.00"), amount=Decimal("300.00"), qty=Decimal("20"), ), # R002: PBS,入库 10 瓶 dict( material_id=None, stockInNo="RK2025061502", stockInDate=TODAY.isoformat(), expireDate=(TODAY + timedelta(days=365)).isoformat(), catalogNo="SP-PBS-500", batchNo="B20250602", manufacturer="Gibco", storageLocation="试剂柜-B-02", unitPrice=Decimal("85.00"), amount=Decimal("850.00"), qty=Decimal("10"), ), # R003: DMEM,入库 8 瓶 dict( material_id=None, stockInNo="RK2025061503", stockInDate=TODAY.isoformat(), expireDate=(TODAY + timedelta(days=180)).isoformat(), catalogNo="SP-DMEM-500", batchNo="B20250603", manufacturer="Gibco", storageLocation="试剂柜-B-03", unitPrice=Decimal("120.00"), amount=Decimal("960.00"), qty=Decimal("8"), ), # C001: 离心管,入库 50 袋 dict( material_id=None, stockInNo="RK2025061504", stockInDate=TODAY.isoformat(), expireDate=(TODAY + timedelta(days=1825)).isoformat(), # 5年后过期 catalogNo="SC-CF15-50", batchNo="B20250604", manufacturer="Axygen", storageLocation="耗材柜-C-01", unitPrice=Decimal("45.00"), amount=Decimal("2250.00"), qty=Decimal("50"), ), # C002: 培养瓶,入库 30 包 dict( material_id=None, stockInNo="RK2025061505", stockInDate=TODAY.isoformat(), expireDate=(TODAY + timedelta(days=1095)).isoformat(), # 3年后过期 catalogNo="SC-CF25-1", batchNo="B20250605", manufacturer="Corning", storageLocation="耗材柜-D-02", unitPrice=Decimal("28.00"), amount=Decimal("840.00"), qty=Decimal("30"), ), ] def seed( tenant_no: str = "zkxw", user_id: str = "d3000000000000000000000000000001", ) -> None: db = SessionLocal() mat_created = 0 mat_skipped = 0 batch_created = 0 batch_errors = 0 try: for i, (mt, code, name, spec, unit, warn_qty, remark) in enumerate(SAMPLE_MATERIALS): exists = mat_svc.code_exists(db, code, mt, tenant_no) if exists: # 找到已有物料的 ID rows, _ = mat_svc.list_materials( db, page=1, page_size=1, keyword=code, material_type=mt, tenant_no=tenant_no ) mat_id = rows[0]["id"] if rows else None print(f" 跳过物料:{code} - {name}(已存在,ID: {mat_id})") mat_skipped += 1 if mat_id: BATCH_ITEMS[i]["material_id"] = mat_id else: try: obj = mat_svc.create_material( db, material_type=mt, material_code=code, material_name=name, spec_model=spec, unit=unit, warning_qty=Decimal(str(warn_qty)), status="1", remark=remark, tenant_no=tenant_no, user_id=user_id, ) BATCH_ITEMS[i]["material_id"] = obj.id print(f" 新增物料:{code} - {name}(ID: {obj.id})") mat_created += 1 except Exception as e: print(f" 错误(物料):{code} - {name},原因:{e}") continue # 入库批次 print("\n--- 开始入库批次 ---") for item in BATCH_ITEMS: mat_id = item.get("material_id") if not mat_id: print(f" 跳过批次:物料ID不存在") continue stock_in_no = item["stockInNo"] try: batch_svc.batch_stock_in( db, items=[item], tenant_no=tenant_no, user_id=user_id, ) print(f" 新增批次:{stock_in_no}(物料ID: {mat_id},数量: {item['qty']})") batch_created += 1 except Exception as e: print(f" 错误(批次):{stock_in_no},原因:{e}") batch_errors += 1 print( f"\n完成:物料新增 {mat_created} 条、跳过 {mat_skipped} 条;" f"批次新增 {batch_created} 条、错误 {batch_errors} 条。" ) finally: db.close() if __name__ == "__main__": seed()