diff --git a/deploy.tar.gz b/deploy.tar.gz index 941444c..ef9cee9 100644 Binary files a/deploy.tar.gz and b/deploy.tar.gz differ diff --git a/deploy_code.sh b/deploy_code.sh old mode 100755 new mode 100644 diff --git a/inventory-backend/app/models/transaction.py b/inventory-backend/app/models/transaction.py index d1cda8e..a8403eb 100644 --- a/inventory-backend/app/models/transaction.py +++ b/inventory-backend/app/models/transaction.py @@ -81,6 +81,9 @@ class TransRepair(db.Model): # SKU 保留 sku = db.Column(db.String(100)) + # 物料名称 (独立录入时使用,非关联base_id) + material_name = db.Column(db.String(200)) + # 序列号SN (新增,用于单台追溯) serial_number = db.Column(db.String(100), nullable=True) @@ -114,6 +117,12 @@ class TransRepair(db.Model): # 客户名/来源 related_contract_id = db.Column(db.String(100)) + # 客户名称 (新增) + customer_name = db.Column(db.String(100)) + + # 客户所在地 (新增) + customer_location = db.Column(db.String(255)) + # 成本与售价 cost_price = db.Column(db.Numeric(19, 4)) sale_price = db.Column(db.Numeric(19, 4)) @@ -130,6 +139,7 @@ class TransRepair(db.Model): 'repair_no': self.repair_no, 'base_id': self.base_id, 'sku': self.sku, + 'material_name': self.material_name, 'serial_number': self.serial_number, 'source_table': self.source_table, 'stock_id': self.stock_id, @@ -140,6 +150,8 @@ class TransRepair(db.Model): 'is_self_made': self.is_self_made, 'related_product_id': self.related_product_id, 'related_contract_id': self.related_contract_id, + 'customer_name': self.customer_name, + 'customer_location': self.customer_location, 'repair_manager': self.repair_manager, 'fault_description': self.fault_description, 'repair_result': self.repair_result, diff --git a/inventory-backend/app/services/inbound/repair_service.py b/inventory-backend/app/services/inbound/repair_service.py index f720f8d..cca14ff 100644 --- a/inventory-backend/app/services/inbound/repair_service.py +++ b/inventory-backend/app/services/inbound/repair_service.py @@ -3,8 +3,7 @@ from app.extensions import db from app.models.transaction import TransRepair from app.models.base import MaterialBase from datetime import datetime, timezone -import random -import string +from sqlalchemy import text class RepairInboundService: @@ -13,27 +12,42 @@ class RepairInboundService: def _generate_repair_no(): """ 生成唯一的维修单号 - 格式: REP-YYYYMMDD-XXXX (X为随机大写字母或数字) - 防重复策略: - 1. 先尝试生成4位随机序列 - 2. 检查数据库中是否存在该单号 - 3. 如果冲突,重试最多10次 - 4. 如果10次都冲突,加入时间戳毫秒数确保唯一 + 格式: REP-YYYYMMDD-0001 (按天递增) + 策略: 查询当天最大的repair_no,提取流水号+1 """ - for _ in range(10): - date_str = datetime.now().strftime('%Y%m%d') - random_str = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4)) - repair_no = f"REP-{date_str}-{random_str}" - - # 检查是否已存在 - exists = TransRepair.query.filter_by(repair_no=repair_no).first() - if not exists: - return repair_no + today = datetime.now().strftime('%Y%m%d') + prefix = f"REP-{today}-" - # 兜底策略:使用时间戳毫秒 - timestamp = int(datetime.now().timestamp() * 1000) % 100000 - date_str = datetime.now().strftime('%Y%m%d') - return f"REP-{date_str}-{timestamp:05d}" + # 查询当天最大的维修单号 + latest = TransRepair.query.filter( + TransRepair.repair_no.like(f"{prefix}%") + ).order_by(TransRepair.repair_no.desc()).first() + + if latest and latest.repair_no: + try: + # 提取最后的流水号 + last_seq = int(latest.repair_no.split('-')[-1]) + new_seq = last_seq + 1 + except (ValueError, IndexError): + new_seq = 1 + else: + new_seq = 1 + + return f"{prefix}{new_seq:04d}" + + @staticmethod + def _generate_sku(): + """ + 获取全局自增序列号,生成10位SKU + 格式: str(seq).zfill(10) + """ + try: + seq_sql = text("SELECT nextval('global_print_seq')") + result = db.session.execute(seq_sql) + next_global_id = result.scalar() + return str(next_global_id).zfill(10) if next_global_id else None + except: + return None @staticmethod def get_list(params): @@ -57,10 +71,15 @@ class RepairInboundService: if params.get('repair_status'): query = query.filter(TransRepair.repair_status == params['repair_status']) - # 关联 MaterialBase 查询物料名称 + # 关联 MaterialBase 查询物料名称 或 直接搜索 TransRepair.material_name if params.get('material_name'): - query = query.join(MaterialBase, TransRepair.base_id == MaterialBase.id).filter( - MaterialBase.name.ilike(f"%{params['material_name']}%") + material_name_filter = params['material_name'] + # 优先搜索直接存储的 material_name,其次搜索关联的 base.name + query = query.outerjoin(MaterialBase, TransRepair.base_id == MaterialBase.id).filter( + db.or_( + TransRepair.material_name.ilike(f"%{material_name_filter}%"), + MaterialBase.name.ilike(f"%{material_name_filter}%") + ) ) # 按创建时间倒序 @@ -92,28 +111,35 @@ class RepairInboundService: """ 新增维修单 核心要求: - 1. 生成以 REP- 打头的自增维修单号 - 2. 支持自动获取传入的 base_id 获取基础物料名称 + 1. 生成以 REP- 打头的自增维修单号 (按天递增) + 2. 从全局序列获取10位SKU (global_print_seq) + 3. 支持不关联 base_id (独立录入模式) + 4. 新增客户名称和客户所在地字段 """ # 生成维修单号 repair_no = RepairInboundService._generate_repair_no() - # 获取物料信息 - material_name = None - company_name = None + # 获取全局SKU sku = data.get('sku') + if not sku: + sku = RepairInboundService._generate_sku() + + # 获取物料信息 (可选) + material_name = data.get('material_name') + company_name = None if data.get('base_id'): base = MaterialBase.query.get(data['base_id']) if base: - material_name = base.name + material_name = base.name or material_name company_name = base.company_name if not sku: sku = base.code - + repair = TransRepair( repair_no=repair_no, base_id=data.get('base_id'), - sku=sku or data.get('sku'), + sku=sku, + material_name=material_name, serial_number=data.get('serial_number'), arrival_date=data.get('arrival_date'), repair_status=data.get('repair_status', '待检测'), @@ -123,6 +149,9 @@ class RepairInboundService: repair_manager=data.get('repair_manager'), shipping_date=data.get('shipping_date'), related_contract_id=data.get('related_contract_id'), + # 新增客户字段 + customer_name=data.get('customer_name'), + customer_location=data.get('customer_location'), cost_price=data.get('cost_price'), sale_price=data.get('sale_price'), company_id=data.get('company_id'), @@ -151,10 +180,10 @@ class RepairInboundService: # 可更新字段 updatable_fields = [ - 'base_id', 'sku', 'serial_number', 'arrival_date', 'repair_status', + 'base_id', 'sku', 'material_name', 'serial_number', 'arrival_date', 'repair_status', 'fault_description', 'expected_repair_time', 'repair_result', 'repair_manager', 'shipping_date', 'related_contract_id', - 'cost_price', 'sale_price', 'company_id' + 'customer_name', 'customer_location', 'cost_price', 'sale_price', 'company_id' ] for field in updatable_fields: diff --git a/inventory-web/src/views/stock/inbound/repair.vue b/inventory-web/src/views/stock/inbound/repair.vue index cb5b83d..b929c55 100644 --- a/inventory-web/src/views/stock/inbound/repair.vue +++ b/inventory-web/src/views/stock/inbound/repair.vue @@ -37,18 +37,23 @@ + - + + - - + + + + + + + + +
+ 打印预览 +
+

打印机 IP: 192.168.9.205

+
+ 打印份数: + +
+ +