ETest-Vue-FastAPI/ruoyi-fastapi-backend/module_admin/service/warehouse_receipt_service.py

250 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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)}')