半成品图像上传初实现,支持多图,检测报告的图片以及链接上传
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
# app/models/inbound/semi.py
|
# app/models/inbound/semi.py
|
||||||
from app.extensions import db
|
from app.extensions import db
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
class StockSemi(db.Model):
|
class StockSemi(db.Model):
|
||||||
@ -41,11 +42,17 @@ class StockSemi(db.Model):
|
|||||||
production_time_range = db.Column(db.String(255))
|
production_time_range = db.Column(db.String(255))
|
||||||
|
|
||||||
quality_status = db.Column(db.String(50))
|
quality_status = db.Column(db.String(50))
|
||||||
|
|
||||||
|
# [修改] 质量报告 (存储 JSON 字符串: 图片列表 + 链接)
|
||||||
quality_report_link = db.Column(db.Text)
|
quality_report_link = db.Column(db.Text)
|
||||||
|
|
||||||
|
# [新增] 到货图片 (存储 JSON 字符串)
|
||||||
|
arrival_photo = db.Column(db.Text)
|
||||||
|
|
||||||
detail_link = db.Column(db.Text)
|
detail_link = db.Column(db.Text)
|
||||||
remark = db.Column(db.Text)
|
remark = db.Column(db.Text)
|
||||||
|
|
||||||
# [新增] 全局打印流水号 (请务必确保数据库已添加此列)
|
# [新增] 全局打印流水号
|
||||||
global_print_id = db.Column(db.Integer)
|
global_print_id = db.Column(db.Integer)
|
||||||
|
|
||||||
# 关系定义
|
# 关系定义
|
||||||
@ -56,6 +63,18 @@ class StockSemi(db.Model):
|
|||||||
man_val = float(self.manual_cost or 0)
|
man_val = float(self.manual_cost or 0)
|
||||||
unit_total = raw_val + man_val
|
unit_total = raw_val + man_val
|
||||||
|
|
||||||
|
# 辅助解析函数:将数据库存储的 JSON 字符串转为 List
|
||||||
|
def parse_img_list(json_str):
|
||||||
|
if not json_str:
|
||||||
|
return []
|
||||||
|
try:
|
||||||
|
# 兼容旧数据:如果不是 JSON 格式(比如是单个 URL),则包装成 list
|
||||||
|
if not json_str.startswith('['):
|
||||||
|
return [json_str]
|
||||||
|
return json.loads(json_str)
|
||||||
|
except:
|
||||||
|
return []
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'id': self.id,
|
'id': self.id,
|
||||||
'base_id': self.base_id,
|
'base_id': self.base_id,
|
||||||
@ -86,14 +105,19 @@ class StockSemi(db.Model):
|
|||||||
'raw_material_cost': raw_val,
|
'raw_material_cost': raw_val,
|
||||||
'manual_cost': man_val,
|
'manual_cost': man_val,
|
||||||
'unit_total_cost': unit_total,
|
'unit_total_cost': unit_total,
|
||||||
|
'total_price': float(self.total_price or 0),
|
||||||
|
|
||||||
'production_manager': self.production_manager,
|
'production_manager': self.production_manager,
|
||||||
'production_time_range': self.production_time_range,
|
'production_time_range': self.production_time_range,
|
||||||
|
|
||||||
'production_start_time': str(self.production_start_time) if self.production_start_time else '',
|
'production_start_time': str(self.production_start_time) if self.production_start_time else '',
|
||||||
'production_end_time': str(self.production_end_time) if self.production_end_time else '',
|
'production_end_time': str(self.production_end_time) if self.production_end_time else '',
|
||||||
|
|
||||||
'quality_status': self.quality_status,
|
'quality_status': self.quality_status,
|
||||||
'quality_report_link': self.quality_report_link,
|
|
||||||
|
# [修改] 解析 JSON 字符串为数组返回给前端
|
||||||
|
'quality_report_link': parse_img_list(self.quality_report_link),
|
||||||
|
'arrival_photo': parse_img_list(self.arrival_photo),
|
||||||
|
|
||||||
'detail_link': self.detail_link,
|
'detail_link': self.detail_link,
|
||||||
'remark': self.remark,
|
'remark': self.remark,
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
# app/services/inbound/semi_service.py
|
# app/services/inbound/semi_service.py
|
||||||
from app.extensions import db
|
from app.extensions import db
|
||||||
from app.models.base import MaterialBase
|
from app.models.base import MaterialBase
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# ❌ 头部禁止导入 StockSemi,防止 Circular Import
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from sqlalchemy import or_, func, text
|
from sqlalchemy import or_, func, text
|
||||||
import traceback
|
import traceback
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
class SemiInboundService:
|
class SemiInboundService:
|
||||||
@ -42,7 +40,7 @@ class SemiInboundService:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_inbound(data):
|
def handle_inbound(data):
|
||||||
# ✅ 【关键修复】局部导入 Model,解决循环引用
|
# 局部导入 Model,解决循环引用
|
||||||
from app.models.inbound.semi import StockSemi
|
from app.models.inbound.semi import StockSemi
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -79,7 +77,6 @@ class SemiInboundService:
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# ✅ 优化:处理 time_range 字符串,防止前端传数组导致存入 None
|
|
||||||
time_range_str = None
|
time_range_str = None
|
||||||
raw_range = data.get('production_time_range')
|
raw_range = data.get('production_time_range')
|
||||||
if isinstance(raw_range, list):
|
if isinstance(raw_range, list):
|
||||||
@ -94,9 +91,7 @@ class SemiInboundService:
|
|||||||
unit_total_cost = raw_cost + manual_cost
|
unit_total_cost = raw_cost + manual_cost
|
||||||
total_value = unit_total_cost * in_qty
|
total_value = unit_total_cost * in_qty
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# 4. 获取全局打印流水号
|
||||||
# 4. 获取全局打印流水号 (跨表唯一)
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
next_global_id = 0
|
next_global_id = 0
|
||||||
try:
|
try:
|
||||||
seq_sql = text("SELECT nextval('global_print_seq')")
|
seq_sql = text("SELECT nextval('global_print_seq')")
|
||||||
@ -106,22 +101,25 @@ class SemiInboundService:
|
|||||||
print("❌ 数据库序列 global_print_seq 不存在,请执行SQL创建!")
|
print("❌ 数据库序列 global_print_seq 不存在,请执行SQL创建!")
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# 5. 自动生成 SKU
|
||||||
# 5. 自动生成 SKU (格式: 00000001)
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
generated_sku = str(next_global_id).zfill(10)
|
generated_sku = str(next_global_id).zfill(10)
|
||||||
final_sku = data.get('sku')
|
final_sku = data.get('sku')
|
||||||
if not final_sku:
|
if not final_sku:
|
||||||
final_sku = generated_sku
|
final_sku = generated_sku
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# 6. 条码逻辑处理
|
# 6. 条码逻辑处理
|
||||||
# ------------------------------------------------------------------
|
|
||||||
final_barcode = data.get('barcode')
|
final_barcode = data.get('barcode')
|
||||||
if not final_barcode:
|
if not final_barcode:
|
||||||
final_barcode = final_sku
|
final_barcode = final_sku
|
||||||
|
|
||||||
# 7. 创建记录
|
# 7. 图片列表转 JSON 字符串处理
|
||||||
|
arrival_list = data.get('arrival_photo', [])
|
||||||
|
quality_report_list = data.get('quality_report_link', [])
|
||||||
|
|
||||||
|
if not isinstance(arrival_list, list): arrival_list = []
|
||||||
|
if not isinstance(quality_report_list, list): quality_report_list = []
|
||||||
|
|
||||||
|
# 8. 创建记录
|
||||||
new_stock = StockSemi(
|
new_stock = StockSemi(
|
||||||
base_id=material.id,
|
base_id=material.id,
|
||||||
global_print_id=next_global_id,
|
global_print_id=next_global_id,
|
||||||
@ -152,7 +150,10 @@ class SemiInboundService:
|
|||||||
manual_cost=manual_cost,
|
manual_cost=manual_cost,
|
||||||
total_price=total_value,
|
total_price=total_value,
|
||||||
|
|
||||||
quality_report_link=data.get('quality_report_link'),
|
# [核心修改] 将列表转为 JSON 字符串存储
|
||||||
|
arrival_photo=json.dumps(arrival_list),
|
||||||
|
quality_report_link=json.dumps(quality_report_list),
|
||||||
|
|
||||||
detail_link=data.get('detail_link'),
|
detail_link=data.get('detail_link'),
|
||||||
remark=data.get('remark')
|
remark=data.get('remark')
|
||||||
)
|
)
|
||||||
@ -190,7 +191,6 @@ class SemiInboundService:
|
|||||||
'bom_version': 'bom_version',
|
'bom_version': 'bom_version',
|
||||||
'work_order_code': 'work_order_code',
|
'work_order_code': 'work_order_code',
|
||||||
'production_manager': 'production_manager',
|
'production_manager': 'production_manager',
|
||||||
'quality_report_link': 'quality_report_link',
|
|
||||||
'detail_link': 'detail_link',
|
'detail_link': 'detail_link',
|
||||||
'remark': 'remark'
|
'remark': 'remark'
|
||||||
}
|
}
|
||||||
@ -199,6 +199,17 @@ class SemiInboundService:
|
|||||||
if frontend_key in data:
|
if frontend_key in data:
|
||||||
setattr(stock, db_attr, data[frontend_key])
|
setattr(stock, db_attr, data[frontend_key])
|
||||||
|
|
||||||
|
# [核心修改] 图片字段更新 (List -> JSON String)
|
||||||
|
if 'arrival_photo' in data:
|
||||||
|
imgs = data['arrival_photo']
|
||||||
|
if isinstance(imgs, list):
|
||||||
|
stock.arrival_photo = json.dumps(imgs)
|
||||||
|
|
||||||
|
if 'quality_report_link' in data:
|
||||||
|
imgs = data['quality_report_link']
|
||||||
|
if isinstance(imgs, list):
|
||||||
|
stock.quality_report_link = json.dumps(imgs)
|
||||||
|
|
||||||
# 时间处理
|
# 时间处理
|
||||||
if 'production_start_time' in data:
|
if 'production_start_time' in data:
|
||||||
try:
|
try:
|
||||||
@ -317,11 +328,9 @@ class SemiInboundService:
|
|||||||
items = []
|
items = []
|
||||||
for item in current_items:
|
for item in current_items:
|
||||||
stats = stock_map.get(item.base_id, {'total_stock': 0, 'total_avail': 0})
|
stats = stock_map.get(item.base_id, {'total_stock': 0, 'total_avail': 0})
|
||||||
|
|
||||||
d = item.to_dict()
|
d = item.to_dict()
|
||||||
d['sum_stock'] = stats['total_stock']
|
d['sum_stock'] = stats['total_stock']
|
||||||
d['sum_available'] = stats['total_avail']
|
d['sum_available'] = stats['total_avail']
|
||||||
|
|
||||||
items.append(d)
|
items.append(d)
|
||||||
|
|
||||||
return {"total": pagination.total, "items": items}
|
return {"total": pagination.total, "items": items}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user