250 lines
11 KiB
Python
250 lines
11 KiB
Python
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)}')
|
||
|
||
|
||
|