from sqlalchemy.ext.asyncio import AsyncSession from module_admin.dao.warehouse_receipt_dao import WarehouseReceiptDao from module_admin.dao.warehouse_sample_dao import WarehouseSampleDao from module_admin.entity.do.warehouse_receipt_do import WarehouseReceipt from module_admin.entity.do.warehouse_sample_do import WarehouseSample from module_admin.entity.vo.warehouse_receipt_vo import ( WarehouseReceiptModel, WarehouseReceiptPageQueryModel, AddWarehouseReceiptModel, EditWarehouseReceiptModel, DeleteWarehouseReceiptModel ) from module_admin.entity.vo.common_vo import CrudResponseModel from exceptions.exception import ServiceException from utils.common_util import CamelCaseUtil from datetime import datetime class WarehouseReceiptService: """ 入库单业务逻辑层 """ @classmethod async def get_receipt_list(cls, db: AsyncSession, query_object: WarehouseReceiptPageQueryModel, is_page: bool = False): """ 获取入库单列表 """ try: receipt_list = await WarehouseReceiptDao.get_receipt_list(db, query_object, is_page) # 转换为字典并添加样品数量 result_list = [] for receipt in receipt_list: receipt_dict = CamelCaseUtil.transform_result(receipt) # 获取样品数量 sample_count = await WarehouseSampleDao.get_sample_count_by_receipt(db, receipt.receipt_id) receipt_dict['sample_count'] = sample_count if sample_count else 0 result_list.append(receipt_dict) if is_page: total = await WarehouseReceiptDao.get_receipt_count(db, query_object) return {'rows': result_list, 'total': total if total else 0} else: return result_list except Exception as e: raise ServiceException(message=f'获取入库单列表失败: {str(e)}') @classmethod async def get_receipt_detail(cls, db: AsyncSession, receipt_id: int): """ 获取入库单详情 """ import sys print(f"DEBUG Service START: get_receipt_detail called with receipt_id={receipt_id}", flush=True) sys.stdout.flush() try: receipt = await WarehouseReceiptDao.get_receipt_by_id(db, receipt_id) if not receipt: raise ServiceException(message='入库单不存在') print(f"DEBUG Service: receipt found, receipt.receipt_id={receipt.receipt_id}, receipt_no={receipt.receipt_no}", flush=True) sys.stdout.flush() receipt_dict = CamelCaseUtil.transform_result(receipt) # 获取样品列表 from module_admin.entity.vo.warehouse_sample_vo import WarehouseSamplePageQueryModel # 使用 camelCase 字段名来构造查询对象 sample_query = WarehouseSamplePageQueryModel(receiptId=receipt.receipt_id, pageNum=1, pageSize=1000) # 添加日志 print(f"DEBUG: 查询入库单 {receipt_id} 的样品,receipt.receipt_id={receipt.receipt_id}", flush=True) print(f"DEBUG: sample_query.receipt_id={sample_query.receipt_id}", flush=True) sys.stdout.flush() samples = await WarehouseSampleDao.get_sample_list(db, sample_query, is_page=False) # 添加日志 print(f"DEBUG: 查询到 {len(samples) if samples else 0} 个样品", flush=True) if samples: for sample in samples[:3]: # 只打印前3个 print(f"DEBUG: 样品 ID={sample.sample_id}, receipt_id={sample.receipt_id}, SN={sample.sample_sn}", flush=True) sys.stdout.flush() # 转换样品列表 samples_list = [CamelCaseUtil.transform_result(sample) for sample in samples] if samples else [] receipt_dict['samples'] = samples_list receipt_dict['sample_count'] = len(samples_list) return receipt_dict except ServiceException: raise except Exception as e: print(f"DEBUG Service ERROR: {str(e)}", flush=True) raise ServiceException(message=f'获取入库单详情失败: {str(e)}') @classmethod async def add_receipt(cls, db: AsyncSession, receipt_model: AddWarehouseReceiptModel): """ 新增入库单(同时创建关联的样品) """ try: # 检查入库单号是否已存在 existing = await WarehouseReceiptDao.get_receipt_by_no(db, receipt_model.receipt_no) if existing: raise ServiceException(message=f'入库单号【{receipt_model.receipt_no}】已存在') # 获取样品数据 samples_data = receipt_model.samples if receipt_model.samples else [] # 创建入库单对象(排除samples字段) receipt_dict = receipt_model.model_dump(exclude_unset=True, exclude={'samples'}) receipt = WarehouseReceipt(**receipt_dict) receipt.create_time = datetime.now() receipt.update_time = datetime.now() # 保存入库单 await WarehouseReceiptDao.add_receipt(db, receipt) await db.flush() # 刷新以获取receipt_id # 创建样品对象并关联到入库单 for sample_data in samples_data: sample_dict = sample_data.model_dump(exclude_unset=True) sample = WarehouseSample(**sample_dict) sample.receipt_id = receipt.receipt_id sample.receipt_no = receipt.receipt_no sample.create_by = receipt.create_by sample.create_time = datetime.now() sample.update_time = datetime.now() await WarehouseSampleDao.add_sample(db, sample) await db.commit() return CrudResponseModel(is_success=True, message='新增成功') except ServiceException: await db.rollback() raise except Exception as e: await db.rollback() raise ServiceException(message=f'新增入库单失败: {str(e)}') @classmethod async def edit_receipt(cls, db: AsyncSession, receipt_model: EditWarehouseReceiptModel): """ 编辑入库单(同时更新关联的样品) """ try: # 检查入库单是否存在 receipt = await WarehouseReceiptDao.get_receipt_by_id(db, receipt_model.receipt_id) if not receipt: raise ServiceException(message='入库单不存在') # 如果修改了入库单号,检查新单号是否已存在 if receipt_model.receipt_no and receipt_model.receipt_no != receipt.receipt_no: existing = await WarehouseReceiptDao.get_receipt_by_no(db, receipt_model.receipt_no) if existing: raise ServiceException(message=f'入库单号【{receipt_model.receipt_no}】已存在') # 更新入库单基本信息 receipt_model.update_time = datetime.now() await WarehouseReceiptDao.edit_receipt(db, receipt_model) # 如果提供了样品列表,则同步更新样品 if receipt_model.samples is not None: # 获取现有样品列表 from module_admin.entity.vo.warehouse_sample_vo import WarehouseSamplePageQueryModel # 使用 camelCase 字段名来构造查询对象 sample_query = WarehouseSamplePageQueryModel(receiptId=receipt_model.receipt_id, pageNum=1, pageSize=1000) existing_samples = await WarehouseSampleDao.get_sample_list(db, sample_query, is_page=False) existing_sample_ids = {sample.sample_id for sample in existing_samples} if existing_samples else set() # 处理前端传来的样品 submitted_sample_ids = set() for sample_data in receipt_model.samples: sample_dict = sample_data.model_dump(exclude_unset=True) # 如果有sample_id,说明是更新现有样品 if 'sample_id' in sample_dict and sample_dict['sample_id']: sample_id = sample_dict['sample_id'] submitted_sample_ids.add(sample_id) # 更新样品 from module_admin.entity.vo.warehouse_sample_vo import EditWarehouseSampleModel edit_sample = EditWarehouseSampleModel(**sample_dict) edit_sample.update_time = datetime.now() edit_sample.update_by = receipt_model.update_by await WarehouseSampleDao.edit_sample(db, edit_sample) else: # 新增样品 sample = WarehouseSample(**sample_dict) sample.receipt_id = receipt_model.receipt_id sample.receipt_no = receipt_model.receipt_no or receipt.receipt_no sample.create_by = receipt_model.update_by sample.create_time = datetime.now() sample.update_time = datetime.now() await WarehouseSampleDao.add_sample(db, sample) # 删除前端没有提交的样品(逻辑删除) samples_to_delete = existing_sample_ids - submitted_sample_ids if samples_to_delete: await WarehouseSampleDao.delete_sample(db, list(samples_to_delete)) await db.commit() return CrudResponseModel(is_success=True, message='更新成功') except ServiceException: await db.rollback() raise except Exception as e: await db.rollback() raise ServiceException(message=f'更新入库单失败: {str(e)}') @classmethod async def delete_receipt(cls, db: AsyncSession, delete_model: DeleteWarehouseReceiptModel): """ 删除入库单(同时删除关联的样品) """ try: receipt_ids = [int(id_str) for id_str in delete_model.receipt_ids.split(',')] # 检查入库单是否存在 for receipt_id in receipt_ids: receipt = await WarehouseReceiptDao.get_receipt_by_id(db, receipt_id) if not receipt: raise ServiceException(message=f'入库单ID【{receipt_id}】不存在') # 删除入库单(级联删除样品) await WarehouseReceiptDao.delete_receipt(db, receipt_ids) await db.commit() return CrudResponseModel(is_success=True, message='删除成功') except ServiceException: await db.rollback() raise except Exception as e: await db.rollback() raise ServiceException(message=f'删除入库单失败: {str(e)}') @classmethod async def generate_receipt_no(cls, db: AsyncSession): """ 生成入库单号 """ try: year = datetime.now().year receipt_no = await WarehouseReceiptDao.generate_receipt_no(db, year) return {'receiptNo': receipt_no} except Exception as e: raise ServiceException(message=f'生成入库单号失败: {str(e)}')