借库逻辑实现
This commit is contained in:
@ -11,7 +11,30 @@ import json
|
||||
class ProductInboundService:
|
||||
|
||||
# ============================================================
|
||||
# 1. 基础物料搜索 (已修正:完全对齐 Buy/Semi 的逻辑)
|
||||
# 0. 辅助:唯一性校验 (新增核心逻辑)
|
||||
# ============================================================
|
||||
@staticmethod
|
||||
def _check_unique(serial_number, exclude_id=None):
|
||||
"""
|
||||
校验成品的唯一性
|
||||
:param serial_number: 序列号
|
||||
:param exclude_id: 排除的ID (编辑模式用)
|
||||
"""
|
||||
from app.models.inbound.product import StockProduct
|
||||
|
||||
# 成品强校验序列号 (SN) - SN应该是全局唯一的
|
||||
if serial_number:
|
||||
query = StockProduct.query.filter(StockProduct.serial_number == serial_number)
|
||||
if exclude_id:
|
||||
query = query.filter(StockProduct.id != exclude_id)
|
||||
|
||||
exists = query.first()
|
||||
if exists:
|
||||
occupied_name = exists.material.name if (hasattr(exists, 'material') and exists.material) else "未知物料"
|
||||
raise ValueError(f"序列号【{serial_number}】已存在!被成品 [{occupied_name}] 占用,请核查。")
|
||||
|
||||
# ============================================================
|
||||
# 1. 基础物料搜索
|
||||
# ============================================================
|
||||
@staticmethod
|
||||
def search_base_material(keyword):
|
||||
@ -31,16 +54,16 @@ class ProductInboundService:
|
||||
# 3. 排序与限制:按ID倒序,取最新20条
|
||||
query = query.order_by(MaterialBase.id.desc()).limit(20)
|
||||
|
||||
# 4. 结果封装:确保字段名与前端 Vue 的 handleSelect 方法一致
|
||||
# 4. 结果封装
|
||||
results = []
|
||||
for item in query.all():
|
||||
results.append({
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'spec': item.spec_model, # 对应前端: item.spec
|
||||
'category': item.category, # 对应前端: item.category
|
||||
'unit': item.unit, # 对应前端: item.unit
|
||||
'type': item.material_type, # 对应前端: item.type
|
||||
'spec': item.spec_model,
|
||||
'category': item.category,
|
||||
'unit': item.unit,
|
||||
'type': item.material_type,
|
||||
'status': '启用'
|
||||
})
|
||||
return results
|
||||
@ -49,7 +72,7 @@ class ProductInboundService:
|
||||
return []
|
||||
|
||||
# ============================================================
|
||||
# 2. 新增入库逻辑 (强制北京时间)
|
||||
# 2. 新增入库逻辑 (强制北京时间 + 唯一性校验)
|
||||
# ============================================================
|
||||
@staticmethod
|
||||
def handle_inbound(data):
|
||||
@ -61,6 +84,11 @@ class ProductInboundService:
|
||||
material = MaterialBase.query.get(base_id)
|
||||
if not material: raise ValueError("物料不存在")
|
||||
|
||||
# --- [核心修改] 执行唯一性校验 ---
|
||||
ProductInboundService._check_unique(
|
||||
serial_number=data.get('serial_number')
|
||||
)
|
||||
|
||||
# [核心修改] 强制北京时间
|
||||
beijing_tz = timezone(timedelta(hours=8))
|
||||
current_time = datetime.now(beijing_tz).replace(tzinfo=None)
|
||||
@ -86,11 +114,14 @@ class ProductInboundService:
|
||||
time_range = f"{p_start} ~ {p_end}" if p_start or p_end else None
|
||||
|
||||
# 全局流水号
|
||||
seq_sql = text("SELECT nextval('global_print_seq')")
|
||||
result = db.session.execute(seq_sql)
|
||||
next_global_id = result.scalar()
|
||||
try:
|
||||
seq_sql = text("SELECT nextval('global_print_seq')")
|
||||
result = db.session.execute(seq_sql)
|
||||
next_global_id = result.scalar()
|
||||
except:
|
||||
next_global_id = None
|
||||
|
||||
generated_sku = str(next_global_id).zfill(10)
|
||||
generated_sku = str(next_global_id).zfill(10) if next_global_id else datetime.now().strftime('%Y%m%d%H%M%S')
|
||||
final_barcode = data.get('barcode') or generated_sku
|
||||
|
||||
photo_list = data.get('product_photo', [])
|
||||
@ -156,6 +187,13 @@ class ProductInboundService:
|
||||
stock = StockProduct.query.get(stock_id)
|
||||
if not stock: raise ValueError("记录不存在")
|
||||
|
||||
# --- [核心修改] 编辑时也要校验唯一性 ---
|
||||
if 'serial_number' in data:
|
||||
ProductInboundService._check_unique(
|
||||
serial_number=data['serial_number'],
|
||||
exclude_id=stock_id
|
||||
)
|
||||
|
||||
fields = [
|
||||
'barcode', 'serial_number', 'warehouse_location',
|
||||
'status', 'quality_status', 'bom_code', 'bom_version',
|
||||
|
||||
Reference in New Issue
Block a user