From b0df5c74580e531d264add0ad6612b06a9b23ba1 Mon Sep 17 00:00:00 2001 From: dxc Date: Wed, 28 Jan 2026 17:44:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8D=8A=E6=88=90=E5=93=81?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E8=BF=9B=E8=A1=8C=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inventory-backend/app/__init__.py | 55 +- .../app/api/v1/inbound/__init__.py | 16 +- inventory-backend/app/api/v1/inbound/semi.py | 91 ++ inventory-backend/app/models/__init__.py | 13 +- .../app/models/inbound/__init__.py | 0 .../app/models/{stock.py => inbound/buy.py} | 2 +- inventory-backend/app/models/inbound/semi.py | 143 +++ inventory-backend/app/models/material.py | 31 +- .../app/services/inbound/base_service.py | 96 +- .../app/services/inbound/buy_service.py | 4 +- .../app/services/inbound/semi_service.py | 339 +++++++ inventory-web/index.html | 2 +- inventory-web/public/iris.png | Bin 0 -> 85769 bytes inventory-web/public/vite.svg | 1 - inventory-web/src/api/inbound/semi.ts | 45 + .../src/views/stock/inbound/semi.vue | 882 +++++++++++++++++- 16 files changed, 1649 insertions(+), 71 deletions(-) create mode 100644 inventory-backend/app/models/inbound/__init__.py rename inventory-backend/app/models/{stock.py => inbound/buy.py} (99%) create mode 100644 inventory-backend/app/models/inbound/semi.py create mode 100644 inventory-web/public/iris.png delete mode 100644 inventory-web/public/vite.svg diff --git a/inventory-backend/app/__init__.py b/inventory-backend/app/__init__.py index 4fe4e5f..b08a057 100644 --- a/inventory-backend/app/__init__.py +++ b/inventory-backend/app/__init__.py @@ -1,38 +1,53 @@ +# 文件路径: inventory-backend/app/__init__.py from flask import Flask from config import Config from app.extensions import db, migrate, cors + def create_app(): app = Flask(__name__) app.config.from_object(Config) - # 初始化插件 + # 1. 初始化插件 db.init_app(app) migrate.init_app(app, db) - # 确保跨域配置正确,允许前端访问 + + # 确保跨域配置 cors.init_app(app, resources={r"/api/*": {"origins": "*"}}) - # --- 注册蓝图 --- + # ========================================================= + # 2. 注册蓝图 (Blueprints) + # ========================================================= - # 1. 保持原有的 stocks 模块 - try: - from app.api.v1.stocks import stocks_bp - app.register_blueprint(stocks_bp, url_prefix='/api/v1/stocks') - except ImportError as e: - print(f"⚠️ 警告: 原有 stocks 蓝图导入失败: {e}") - - # 2. 注册新的入库聚合蓝图 - # 核心:必须先导入,再注册。路径对应 app/api/v1/inbound/__init__.py + # 注册入库聚合模块 (Inbound) try: + # 指向聚合文件: app/api/v1/inbound/__init__.py from app.api.v1.inbound import inbound_bp - # 最终路径结构:/api/v1/inbound/buy/list - app.register_blueprint(inbound_bp, url_prefix='/api/v1/inbound') - print("✅ 入库模块蓝图注册成功") - except ImportError as e: - print(f"❌ 严重错误: 入库模块 inbound 蓝图导入失败: {e}") - # 打印路由映射,仅在本地调试时建议开启 - # with app.app_context(): - # print(app.url_map) + # 注册父蓝图,路由前缀为 /api/v1/inbound + # 最终路由效果: + # /api/v1/inbound + /buy/list -> /api/v1/inbound/buy/list + # /api/v1/inbound + /semi/list -> /api/v1/inbound/semi/list + app.register_blueprint(inbound_bp, url_prefix='/api/v1/inbound') + + print("✅ Inbound (Buy & Semi) 模块注册成功") + + except ImportError as e: + print(f"❌ 错误: Inbound 模块导入失败: {e}") + + # ========================================================= + # 3. 预加载数据模型 (解决 relationship 找不到模型的问题) + # ========================================================= + with app.app_context(): + try: + # ✅ 修正点:引用新路径 (不再引用 app.models.stock) + from app.models.inbound.buy import StockBuy + from app.models.inbound.semi import StockSemi + from app.models.material import MaterialBase + + # 如果是开发环境且没有迁移文件,可以取消注释下面这行来创建表 + # db.create_all() + except ImportError as e: + print(f"⚠️ 模型预加载失败: {e}") return app \ No newline at end of file diff --git a/inventory-backend/app/api/v1/inbound/__init__.py b/inventory-backend/app/api/v1/inbound/__init__.py index 883c8cb..a2c8d31 100644 --- a/inventory-backend/app/api/v1/inbound/__init__.py +++ b/inventory-backend/app/api/v1/inbound/__init__.py @@ -1,18 +1,22 @@ from flask import Blueprint -# 1. 导入同目录下的 buy 模块 (假设文件名为 buy.py) +# 1. 导入子模块蓝图 +# 注意:确保 .buy, .semi, .base 文件在同级目录下真实存在 from .buy import inbound_buy_bp +from .semi import inbound_semi_bp -# 2. 【关键修改】导入同目录下的 base 模块 -# 使用相对导入 .base,这样 Python 就会去 app/api/v1/inbound/base.py 找 +# 如果你还有 base.py 文件,就取消注释下面这行 from .base import inbound_base_bp -# 创建父级蓝图 'inbound' +# 2. 创建父级聚合蓝图 inbound_bp = Blueprint('inbound', __name__) # 3. 挂载子蓝图 -# 最终路由将是: /api/v1/inbound/buy/... +# 访问地址: /api/v1/inbound/buy/list inbound_bp.register_blueprint(inbound_buy_bp, url_prefix='/buy') -# 最终路由将是: /api/v1/inbound/base/... +# 访问地址: /api/v1/inbound/semi/list +inbound_bp.register_blueprint(inbound_semi_bp, url_prefix='/semi') + +# 如果有 base inbound_bp.register_blueprint(inbound_base_bp, url_prefix='/base') \ No newline at end of file diff --git a/inventory-backend/app/api/v1/inbound/semi.py b/inventory-backend/app/api/v1/inbound/semi.py index e69de29..1950c99 100644 --- a/inventory-backend/app/api/v1/inbound/semi.py +++ b/inventory-backend/app/api/v1/inbound/semi.py @@ -0,0 +1,91 @@ +from flask import Blueprint, request, jsonify +from app.services.inbound.semi_service import SemiInboundService +import traceback + +# 定义蓝图,url_prefix 通常在注册蓝图时指定,例如 /api/v1/inbound/semi +inbound_semi_bp = Blueprint('inbound_semi', __name__) + + +# ------------------------------------------------------------------ +# 0. 基础物料搜索 (复用逻辑) +# ------------------------------------------------------------------ +@inbound_semi_bp.route('/search-base', methods=['GET']) +def search_base(): + """ + 供前端下拉框远程搜索使用 (搜索半成品类型的基础物料) + Query Param: keyword (名称或规格) + """ + try: + keyword = request.args.get('keyword', '') + # 这里复用 Service 中的搜索逻辑 + data = SemiInboundService.search_base_material(keyword) + return jsonify({ + "code": 200, + "msg": "success", + "data": data + }) + except Exception as e: + traceback.print_exc() + return jsonify({"code": 500, "msg": str(e)}), 500 + + +# ------------------------------------------------------------------ +# 1. 获取半成品列表 +# ------------------------------------------------------------------ +@inbound_semi_bp.route('/list', methods=['GET']) +def get_list(): + try: + page = request.args.get('page', 1, type=int) + limit = request.args.get('pageSize', 15, type=int) + # 支持按关键字搜索:BOM号、工单号、SN、批号等 + keyword = request.args.get('keyword', '') + + result = SemiInboundService.get_list(page, limit, keyword) + return jsonify({"code": 200, "msg": "success", "data": result}) + except Exception as e: + traceback.print_exc() + return jsonify({"code": 500, "msg": str(e)}), 500 + + +# ------------------------------------------------------------------ +# 2. 新增半成品入库 +# ------------------------------------------------------------------ +@inbound_semi_bp.route('/submit', methods=['POST']) +def submit(): + try: + data = request.get_json() + if not data: + return jsonify({"code": 400, "msg": "No data"}), 400 + + SemiInboundService.handle_inbound(data) + return jsonify({"code": 200, "msg": "入库成功"}) + except Exception as e: + traceback.print_exc() + return jsonify({"code": 500, "msg": str(e)}), 500 + + +# ------------------------------------------------------------------ +# 3. 更新半成品入库信息 +# ------------------------------------------------------------------ +@inbound_semi_bp.route('/', methods=['PUT']) +def update_semi(id): + try: + data = request.get_json() + SemiInboundService.update_inbound(id, data) + return jsonify({"code": 200, "msg": "更新成功"}) + except Exception as e: + traceback.print_exc() + return jsonify({"code": 500, "msg": str(e)}), 500 + + +# ------------------------------------------------------------------ +# 4. 删除半成品入库记录 +# ------------------------------------------------------------------ +@inbound_semi_bp.route('/', methods=['DELETE']) +def delete_semi(id): + try: + SemiInboundService.delete_inbound(id) + return jsonify({"code": 200, "msg": "删除成功"}) + except Exception as e: + traceback.print_exc() + return jsonify({"code": 500, "msg": str(e)}), 500 \ No newline at end of file diff --git a/inventory-backend/app/models/__init__.py b/inventory-backend/app/models/__init__.py index 7071057..e4cb8dd 100644 --- a/inventory-backend/app/models/__init__.py +++ b/inventory-backend/app/models/__init__.py @@ -1,2 +1,13 @@ +# app/models/__init__.py + +# 1. 基础物料 from app.models.material import MaterialBase -from app.models.stock import StockBuy \ No newline at end of file + +# 2. 采购入库 (指向新路径) +from app.models.inbound.buy import StockBuy + +# 3. 半成品入库 (指向新路径) +from app.models.inbound.semi import StockSemi + +# 如果有其他模型 (比如 sys_user 等),保留它们 +# from app.models.sys_user import SysUser \ No newline at end of file diff --git a/inventory-backend/app/models/inbound/__init__.py b/inventory-backend/app/models/inbound/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/inventory-backend/app/models/stock.py b/inventory-backend/app/models/inbound/buy.py similarity index 99% rename from inventory-backend/app/models/stock.py rename to inventory-backend/app/models/inbound/buy.py index b71a037..d1c6ad0 100644 --- a/inventory-backend/app/models/stock.py +++ b/inventory-backend/app/models/inbound/buy.py @@ -1,4 +1,4 @@ -# app/models/stock.py +# app/models/buy.py from app.extensions import db from datetime import datetime diff --git a/inventory-backend/app/models/inbound/semi.py b/inventory-backend/app/models/inbound/semi.py new file mode 100644 index 0000000..9d8ad1b --- /dev/null +++ b/inventory-backend/app/models/inbound/semi.py @@ -0,0 +1,143 @@ +# app/models/inbound/semi.py +from app.extensions import db +from datetime import datetime + + +class StockSemi(db.Model): + """ + 半成品入库库存表 + 对应数据库表: stock_semi + """ + __tablename__ = 'stock_semi' + + # ========================================================= + # 1. 基础字段 (Strictly matching SQL Schema) + # ========================================================= + + # 主键 + id = db.Column(db.Integer, primary_key=True) + + # 外键关联 material_base 表 + base_id = db.Column(db.Integer, db.ForeignKey('material_base.id'), nullable=False) + + # 身份标识 + sku = db.Column(db.String(100)) + + # SQL字段名为 production_date, 对应前端的 "入库日期/生产日期" + production_date = db.Column(db.Date) + + barcode = db.Column(db.String(100)) # 条码 + serial_number = db.Column(db.String(100)) # 序列号 + + # 注意:提供的 SQL 中 stock_semi 没有 batch_number 字段,这里不定义,以免报错。 + # 如果后续数据库加上了该字段,请取消下方注释: + # batch_number = db.Column(db.String(100)) + + # --- 数量 --- + in_quantity = db.Column(db.Numeric(19, 4), default=0) + stock_quantity = db.Column(db.Numeric(19, 4), default=0) + available_quantity = db.Column(db.Numeric(19, 4), default=0) + + # --- 状态与位置 --- + status = db.Column(db.String(50)) # 在库/出库/损耗 + warehouse_location = db.Column(db.String(100)) # 仓库位 + + # ========================================================= + # 2. 半成品特有字段 (SQL 字段映射) + # ========================================================= + + # BOM 相关 + # 数据库列名: bom_id, Python属性: bom_code (为了适配前端习惯) + bom_code = db.Column('bom_id', db.String(100)) + bom_version = db.Column(db.String(50)) + + # 工单 相关 + # 数据库列名: work_order_id, Python属性: work_order_code + work_order_code = db.Column('work_order_id', db.String(100)) + + # 成本 相关 + raw_material_cost = db.Column(db.Numeric(19, 4), default=0) # 原材料成本 + manual_cost = db.Column(db.Numeric(19, 4), default=0) # 手动/人工成本 + + # 生产信息 + # 数据库列名: producer_name, Python属性: production_manager + production_manager = db.Column('producer_name', db.String(100)) + + # 生产起止时间 (SQL定义为 VARCHAR(255)) + production_time_range = db.Column(db.String(255)) + + # 质量与链接 + quality_status = db.Column(db.String(50)) # 质量状态 + quality_report_link = db.Column(db.Text) # 质量报告链接 + detail_link = db.Column(db.Text) # 详细信息链接 + + # ========================================================= + # 3. 关系定义 + # ========================================================= + # 建立与 MaterialBase 的关系 + # 注意:确保 MaterialBase 模型中定义了 back_populates='stock_semis' + material = db.relationship('MaterialBase', back_populates='stock_semis') + + def to_dict(self): + """ + 序列化:将模型转换为字典,供API返回JSON使用 + 在这里处理字段名称转换,确保前端能正确显示数据 + """ + # 计算单件总成本 (原料 + 人工) + raw_val = float(self.raw_material_cost or 0) + man_val = float(self.manual_cost or 0) + unit_total = raw_val + man_val + + return { + 'id': self.id, + 'base_id': self.base_id, + + # --- 级联基础信息 (防止 None 报错) --- + 'material_name': self.material.name if self.material else '', + 'spec_model': self.material.spec_model if self.material else '', + 'category': self.material.category if self.material else '', + 'unit': self.material.unit if self.material else '', + 'material_type': self.material.material_type if self.material else '', + + # --- 实体信息 --- + 'sku': self.sku, + # 将 production_date 映射回前端通用的 inbound_date + 'inbound_date': self.production_date.strftime('%Y-%m-%d') if self.production_date else '', + 'barcode': self.barcode, + 'serial_number': self.serial_number, + # 'batch_number': self.batch_number, # SQL无此字段,暂不返回 + 'warehouse_loc': self.warehouse_location, + 'status': self.status, + + # --- 数量 (转为float防止json序列化报错) --- + 'in_quantity': float(self.in_quantity or 0), + 'qty_inbound': float(self.in_quantity or 0), # 兼容字段 + 'stock_quantity': float(self.stock_quantity or 0), + 'qty_stock': float(self.stock_quantity or 0), # 兼容字段 + 'available_quantity': float(self.available_quantity or 0), + 'qty_available': float(self.available_quantity or 0), # 兼容字段 + + # --- 半成品特有数据 --- + 'bom_code': self.bom_code, + 'bom_version': self.bom_version, + 'work_order_code': self.work_order_code, + + 'raw_material_cost': raw_val, + 'manual_cost': man_val, + 'unit_total_cost': unit_total, # 前端展示总成本用 + + 'production_manager': self.production_manager, + + # 时间范围 (SQL存的是字符串,直接返回即可,或者根据需要拆分) + # 如果 service 层存的是 "Start ~ End",这里直接返回 + 'production_time_range': self.production_time_range, + # 为了兼容前端分开的时间字段(如果有): + 'production_start_time': self.production_time_range.split(' ~ ')[ + 0] if self.production_time_range and ' ~ ' in self.production_time_range else '', + 'production_end_time': self.production_time_range.split(' ~ ')[ + 1] if self.production_time_range and ' ~ ' in self.production_time_range else '', + + 'quality_status': self.quality_status, + 'quality_report_link': self.quality_report_link, + 'detail_link': self.detail_link + } \ No newline at end of file diff --git a/inventory-backend/app/models/material.py b/inventory-backend/app/models/material.py index dfc0260..17f6aa8 100644 --- a/inventory-backend/app/models/material.py +++ b/inventory-backend/app/models/material.py @@ -10,7 +10,7 @@ class MaterialBase(db.Model): """ __tablename__ = 'material_base' - # 1. 基础字段 (必须与 SQL 建表语句完全一致) + # 1. 基础字段 (保持不变) id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255), nullable=False, comment='基础信息名称') @@ -32,26 +32,31 @@ class MaterialBase(db.Model): manual_link = db.Column(db.Text, comment='通用说明书链接') product_image = db.Column(db.Text, comment='通用产品图链接') - # 启用状态 (注意:SQL中是 boolean) + # 启用状态 is_enabled = db.Column(db.Boolean, default=True, comment='是否启用') # ============================================================ - # ⚠️ 注意:你之前提供的 SQL 建表语句中【没有】下面这两个时间字段。 - # 如果数据库里没有这两列,代码运行到这里会报错 (UndefinedColumn)。 - # 我先将其注释掉。如果你确认数据库已经 Alter Table 加了这两列,请取消注释。 + # 时间字段 (保持你原本的注释状态,以免报错) # ============================================================ # create_time = db.Column(db.DateTime, default=datetime.utcnow) # update_time = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - # 【核心关联】 - # 关联采购库存表 (StockBuy),lazy='dynamic' 允许后续做 .count() 统计 - # 确保 app/models/stock.py 中有 back_populates='material' + # ============================================================ + # 关联关系区域 (修改重点) + # ============================================================ + + # 1. 关联采购库存 (StockBuy) - 保持不变 + # 注意:确保 app/models/inbound/buy.py 中的 StockBuy 定义了 back_populates='material' stock_buys = db.relationship('StockBuy', back_populates='material', lazy='dynamic') + # 2. 【新增】关联半成品库存 (StockSemi) + # 注意:确保 app/models/inbound/semi.py 中的 StockSemi 定义了 back_populates='material' + # 这样以后可以通过 material.stock_semis 来访问该物料下的所有半成品库存记录 + stock_semis = db.relationship('StockSemi', back_populates='material', lazy='dynamic') + def to_dict(self): """ 序列化方法:将模型转换为字典,供API返回JSON使用 - 这里是解决【前端表格空白】最关键的地方 """ return { 'id': self.id, @@ -59,7 +64,7 @@ class MaterialBase(db.Model): 'category': self.category, # ========================================= - # 关键映射区 (解决前后端字段名不一致问题) + # 关键映射区 (保持不变) # ========================================= # 数据库叫 material_type -> 前端叫 type 'type': self.material_type, @@ -74,11 +79,9 @@ class MaterialBase(db.Model): 'generalManual': self.manual_link, 'generalImage': self.product_image, - # 状态处理:前端 Switch 通常接受 boolean 或 1/0 - # 数据库里的 true -> 返回 1 (启用) - # 数据库里的 false/None -> 返回 0 (禁用) + # 状态处理 'isEnabled': 1 if self.is_enabled else 0, - # 如果上方注释了 create_time,这里也要注释,否则会报错 + # 时间字段保持注释 # 'createTime': self.create_time.strftime('%Y-%m-%d %H:%M:%S') if hasattr(self, 'create_time') and self.create_time else None } \ No newline at end of file diff --git a/inventory-backend/app/services/inbound/base_service.py b/inventory-backend/app/services/inbound/base_service.py index 2711cca..cb4434c 100644 --- a/inventory-backend/app/services/inbound/base_service.py +++ b/inventory-backend/app/services/inbound/base_service.py @@ -1,18 +1,62 @@ +# 文件路径: app/services/inbound/base_service.py + from app.extensions import db from app.models.material import MaterialBase -from app.models.stock import StockBuy # 需要引入库存表做删除时的依赖检查 + +# ============================================================================== +# ✅ 正确的引用方式 +# ============================================================================== +from app.models.inbound.buy import StockBuy # 引用采购库存模型 +from app.models.inbound.semi import StockSemi # 引用半成品库存模型 from sqlalchemy import or_ import traceback class MaterialBaseService: + """ + 基础物料服务层 + 负责处理 MaterialBase 的增删改查及搜索逻辑 + """ + + @staticmethod + def search_material(keyword): + """ + 根据关键字搜索已启用的基础物料 + (供 /api/v1/inbound/base/search 接口调用) + """ + try: + if not keyword: + return [] + + # 搜索名称或规格型号,且必须是启用的 + query = MaterialBase.query.filter( + MaterialBase.is_enabled == True, + or_( + MaterialBase.name.ilike(f'%{keyword}%'), + MaterialBase.spec_model.ilike(f'%{keyword}%') + ) + ).limit(20) + + results = [] + for item in query.all(): + results.append({ + 'id': item.id, + 'name': item.name, + 'spec': item.spec_model, + 'category': item.category, + 'unit': item.unit, + 'type': item.material_type, + 'status': '启用' + }) + return results + except Exception as e: + traceback.print_exc() + return [] + @staticmethod def get_list(page, limit, filters=None): """ - 获取基础信息列表 - :param page: 页码 - :param limit: 每页条数 - :param filters: 筛选条件字典 {keyword, category, type, isEnabled} + 获取基础信息列表 (带分页和筛选) """ try: query = MaterialBase.query @@ -46,7 +90,6 @@ class MaterialBaseService: except Exception as e: print(f"查询基础信息列表失败: {e}") - # 生产环境建议记录日志 return {"total": 0, "items": []} @staticmethod @@ -65,16 +108,16 @@ class MaterialBaseService: if exist: raise ValueError(f"已存在相同名称和规格的数据 (ID: {exist.id})") - # 2. 创建对象 (注意前端驼峰 -> 后端下划线映射) + # 2. 创建对象 new_material = MaterialBase( name=data['name'], - spec_model=data['spec'], # 映射 + spec_model=data['spec'], category=data.get('category'), - material_type=data.get('type'), # 映射 + material_type=data.get('type'), unit=data.get('unit'), - visibility_level=data.get('visibilityLevel'), # 映射 - manual_link=data.get('generalManual'), # 映射 - product_image=data.get('generalImage'), # 映射 + visibility_level=data.get('visibilityLevel'), + manual_link=data.get('generalManual'), + product_image=data.get('generalImage'), is_enabled=True if data.get('isEnabled', 1) == 1 else False ) @@ -94,7 +137,7 @@ class MaterialBaseService: if not material: raise ValueError("数据不存在") - # 更新字段 (仅更新传入的字段) + # 更新字段 if 'name' in data: material.name = data['name'] if 'spec' in data: material.spec_model = data['spec'] if 'category' in data: material.category = data['category'] @@ -116,19 +159,32 @@ class MaterialBaseService: @staticmethod def delete_material(m_id): - """删除基础信息 (带依赖检查)""" + """ + 删除基础信息 (带依赖检查) + ✅ 已升级:同时检查采购库(Buy)和半成品库(Semi) + """ try: material = MaterialBase.query.get(m_id) if not material: raise ValueError("数据不存在") - # 1. 依赖检查:如果该基础信息已经在库存表(StockBuy)中使用,禁止物理删除 - # 这里假设 StockBuy 表有一个外键或字段指向 MaterialBase (e.g., base_id) - usage_count = StockBuy.query.filter_by(base_id=m_id).count() - if usage_count > 0: - raise ValueError(f"无法删除:该基础信息已被 {usage_count} 条库存记录引用,请先清理库存或仅禁用此条目。") + # 1. 依赖检查:采购入库引用 + buy_usage_count = StockBuy.query.filter_by(base_id=m_id).count() - # 2. 执行删除 + # 2. 依赖检查:半成品入库引用 + semi_usage_count = StockSemi.query.filter_by(base_id=m_id).count() + + total_usage = buy_usage_count + semi_usage_count + + if total_usage > 0: + raise ValueError( + f"无法删除:该基础物料正被使用中。\n" + f"- 采购库存记录: {buy_usage_count} 条\n" + f"- 半成品库存记录: {semi_usage_count} 条\n" + f"请先清理相关库存或仅‘禁用’此条目。" + ) + + # 3. 执行删除 db.session.delete(material) db.session.commit() return True diff --git a/inventory-backend/app/services/inbound/buy_service.py b/inventory-backend/app/services/inbound/buy_service.py index 93cc2d9..0ba0a93 100644 --- a/inventory-backend/app/services/inbound/buy_service.py +++ b/inventory-backend/app/services/inbound/buy_service.py @@ -1,8 +1,8 @@ from app.extensions import db +from app.models.inbound.buy import StockBuy from app.models.material import MaterialBase -from app.models.stock import StockBuy from datetime import datetime -from sqlalchemy import or_, func # 引入 func 用于聚合计算 +from sqlalchemy import or_, func import traceback diff --git a/inventory-backend/app/services/inbound/semi_service.py b/inventory-backend/app/services/inbound/semi_service.py index e69de29..7789a81 100644 --- a/inventory-backend/app/services/inbound/semi_service.py +++ b/inventory-backend/app/services/inbound/semi_service.py @@ -0,0 +1,339 @@ +from app.extensions import db +from app.models.material import MaterialBase +from app.models.inbound.semi import StockSemi +from datetime import datetime +from sqlalchemy import or_, func +import traceback + + +class SemiInboundService: + @staticmethod + def search_base_material(keyword): + """ + 搜索基础物料,逻辑与采购入库基本一致。 + 如果需要只搜索'半成品'类型的物料,可以在 filter 中增加条件。 + """ + try: + if not keyword: + return [] + + query = MaterialBase.query.filter( + MaterialBase.is_enabled == True, + or_( + MaterialBase.name.ilike(f'%{keyword}%'), + MaterialBase.spec_model.ilike(f'%{keyword}%') + ) + ).limit(20) + + results = [] + for item in query.all(): + results.append({ + 'id': item.id, + 'name': item.name, + 'spec': item.spec_model, + 'category': item.category, + 'unit': item.unit, + 'type': item.material_type, + 'status': '启用' + }) + return results + except Exception as e: + traceback.print_exc() + return [] + + @staticmethod + def handle_inbound(data): + try: + base_id = data.get('base_id') + if not base_id: + raise ValueError("必须选择基础物料 (缺少 base_id)") + + material = MaterialBase.query.get(base_id) + if not material: + raise ValueError(f"ID为 {base_id} 的基础物料不存在") + + # 1. 处理入库日期 + in_date_val = datetime.utcnow().date() + if data.get('in_date'): + try: + date_str = str(data['in_date'])[:10] + in_date_val = datetime.strptime(date_str, '%Y-%m-%d').date() + except ValueError: + pass + + # 2. 处理生产时间 (前端传来的是字符串 "YYYY-MM-DD HH:mm:ss") + p_start = None + p_end = None + if data.get('production_start_time'): + try: + p_start = datetime.strptime(str(data['production_start_time']), '%Y-%m-%d %H:%M:%S') + except: + pass + if data.get('production_end_time'): + try: + p_end = datetime.strptime(str(data['production_end_time']), '%Y-%m-%d %H:%M:%S') + except: + pass + + # 3. 处理数值和成本 + in_qty = float(data.get('in_quantity') or 0) + raw_cost = float(data.get('raw_material_cost') or 0) + manual_cost = float(data.get('manual_cost') or 0) + + # 单件总成本 = 原料 + 人工 + unit_total_cost = raw_cost + manual_cost + # 总价值 = 单件总成本 * 数量 + total_value = unit_total_cost * in_qty + + # 4. 创建记录 + new_stock = StockSemi( + base_id=material.id, + sku=data.get('sku'), + in_date=in_date_val, + + # 标识信息 + serial_number=data.get('serial_number'), + batch_number=data.get('batch_number'), + barcode=data.get('barcode'), + + # 状态与数量 + status='在库', + quality_status=data.get('quality_status', '合格'), # 半成品使用质量状态 + in_quantity=in_qty, + stock_quantity=in_qty, + available_quantity=in_qty, + warehouse_location=data.get('warehouse_location'), + + # 生产任务信息 (半成品特有) + bom_code=data.get('bom_code'), + bom_version=data.get('bom_version'), + work_order_code=data.get('work_order_code'), + production_manager=data.get('production_manager'), + production_start_time=p_start, + production_end_time=p_end, + + # 成本信息 (半成品特有) + raw_material_cost=raw_cost, + manual_cost=manual_cost, + unit_total_cost=unit_total_cost, + total_price=total_value, # 数据库字段可能复用 total_price 或叫 total_value + + # 链接 + quality_report_link=data.get('quality_report_link'), + detail_link=data.get('detail_link'), + remark=data.get('remark') + ) + + db.session.add(new_stock) + db.session.commit() + return new_stock + + except Exception as e: + db.session.rollback() + raise e + + @staticmethod + def update_inbound(stock_id, data): + try: + print(f"----- UPDATE SEMI DEBUG: ID={stock_id} -----") + + stock = StockSemi.query.get(stock_id) + if not stock: + raise ValueError("记录不存在") + + # 1. 简单字段映射 + field_mapping = { + 'sku': 'sku', + 'barcode': 'barcode', + 'warehouse_location': 'warehouse_location', + 'serial_number': 'serial_number', + 'batch_number': 'batch_number', + 'status': 'status', + 'quality_status': 'quality_status', # 质量状态 + + # 生产信息 + 'bom_code': 'bom_code', + 'bom_version': 'bom_version', + 'work_order_code': 'work_order_code', + 'production_manager': 'production_manager', + 'quality_report_link': 'quality_report_link', + 'detail_link': 'detail_link' + } + + for frontend_key, db_attr in field_mapping.items(): + if frontend_key in data: + setattr(stock, db_attr, data[frontend_key]) + + # 2. 处理时间更新 + if 'production_start_time' in data: + try: + if data['production_start_time']: + stock.production_start_time = datetime.strptime(str(data['production_start_time']), + '%Y-%m-%d %H:%M:%S') + else: + stock.production_start_time = None + except: + pass + + if 'production_end_time' in data: + try: + if data['production_end_time']: + stock.production_end_time = datetime.strptime(str(data['production_end_time']), + '%Y-%m-%d %H:%M:%S') + else: + stock.production_end_time = None + except: + pass + + # 3. 处理数量和成本变更联动 + qty_changed = False + cost_changed = False + + # 更新数量 + if 'in_quantity' in data: + new_qty = float(data['in_quantity']) + old_qty = float(stock.in_quantity) + if new_qty != old_qty: + diff = new_qty - old_qty + stock.in_quantity = new_qty + stock.stock_quantity = float(stock.stock_quantity) + diff + stock.available_quantity = float(stock.available_quantity) + diff + qty_changed = True + + # 更新成本 (原材料 or 人工) + if 'raw_material_cost' in data: + stock.raw_material_cost = float(data['raw_material_cost']) + cost_changed = True + + if 'manual_cost' in data: + stock.manual_cost = float(data['manual_cost']) + cost_changed = True + + # 如果成本或数量变了,重新计算单价和总价 + if cost_changed: + stock.unit_total_cost = float(stock.raw_material_cost) + float(stock.manual_cost) + + if cost_changed or qty_changed: + stock.total_price = float(stock.in_quantity) * float(stock.unit_total_cost) + + db.session.commit() + print("----- UPDATE SEMI SUCCESS -----") + return stock + + except Exception as e: + db.session.rollback() + print(f"----- UPDATE SEMI FAILED: {str(e)} -----") + traceback.print_exc() + raise e + + @staticmethod + def delete_inbound(stock_id): + try: + stock = StockSemi.query.get(stock_id) + if not stock: + raise ValueError("记录不存在") + db.session.delete(stock) + db.session.commit() + return True + except Exception as e: + db.session.rollback() + raise e + + @staticmethod + def get_list(page, limit, keyword=None): + try: + # 1. 查询分页数据 + query = db.session.query(StockSemi).outerjoin(MaterialBase, StockSemi.base_id == MaterialBase.id) + + if keyword: + query = query.filter( + or_( + MaterialBase.name.ilike(f'%{keyword}%'), + MaterialBase.spec_model.ilike(f'%{keyword}%'), + StockSemi.batch_number.ilike(f'%{keyword}%'), + StockSemi.serial_number.ilike(f'%{keyword}%'), + StockSemi.sku.ilike(f'%{keyword}%'), + # 增加半成品特有的搜索字段 + StockSemi.work_order_code.ilike(f'%{keyword}%'), + StockSemi.bom_code.ilike(f'%{keyword}%') + ) + ) + + pagination = query.order_by(StockSemi.id.desc()).paginate(page=page, per_page=limit, error_out=False) + + # 2. 聚合统计 (计算该物料的总库存) + current_items = pagination.items + base_ids = list(set([item.base_id for item in current_items if item.base_id])) + + stock_map = {} + if base_ids: + aggregates = db.session.query( + StockSemi.base_id, + func.sum(StockSemi.stock_quantity).label('total_stock'), + func.sum(StockSemi.available_quantity).label('total_avail') + ).filter(StockSemi.base_id.in_(base_ids)).group_by(StockSemi.base_id).all() + + for agg in aggregates: + stock_map[agg.base_id] = { + 'total_stock': float(agg.total_stock or 0), + 'total_avail': float(agg.total_avail or 0) + } + + items = [] + for item in current_items: + mat_name = item.material.name if item.material else '未知物料' + mat_spec = item.material.spec_model if item.material else '' + mat_cat = item.material.category if item.material else '' + mat_unit = item.material.unit if item.material else '' + mat_type = item.material.material_type if item.material else '' + + stats = stock_map.get(item.base_id, {'total_stock': 0, 'total_avail': 0}) + + d = { + 'id': item.id, + 'base_id': item.base_id, + 'material_name': mat_name, + 'spec_model': mat_spec, + 'category': mat_cat, + 'unit': mat_unit, + 'material_type': mat_type, + + 'sku': item.sku, + 'inbound_date': str(item.in_date) if item.in_date else '', + 'barcode': item.barcode, + 'serial_number': item.serial_number, + 'batch_number': item.batch_number, + 'status': item.status, + 'quality_status': item.quality_status, # 半成品使用质量状态 + + 'qty_inbound': float(item.in_quantity or 0), + 'qty_stock': float(item.stock_quantity or 0), + 'qty_available': float(item.available_quantity or 0), + + 'sum_stock': stats['total_stock'], + 'sum_available': stats['total_avail'], + + 'warehouse_loc': item.warehouse_location, + + # 半成品特有字段返回 + 'bom_code': item.bom_code, + 'bom_version': item.bom_version, + 'work_order_code': item.work_order_code, + 'raw_material_cost': float(item.raw_material_cost or 0), + 'manual_cost': float(item.manual_cost or 0), + 'unit_total_cost': float(item.unit_total_cost or 0), + 'production_manager': item.production_manager, + 'production_start_time': str(item.production_start_time) if item.production_start_time else '', + 'production_end_time': str(item.production_end_time) if item.production_end_time else '', + + 'quality_report_link': item.quality_report_link, + 'detail_link': item.detail_link, + 'remark': item.remark + } + items.append(d) + + return {"total": pagination.total, "items": items} + except Exception as e: + print(f"List Error: {e}") + traceback.print_exc() + return {"total": 0, "items": []} \ No newline at end of file diff --git a/inventory-web/index.html b/inventory-web/index.html index 2411ec8..32b2392 100644 --- a/inventory-web/index.html +++ b/inventory-web/index.html @@ -2,7 +2,7 @@ - + inventory-web diff --git a/inventory-web/public/iris.png b/inventory-web/public/iris.png new file mode 100644 index 0000000000000000000000000000000000000000..1ec12c25234edba661484af3e11644e9d9213016 GIT binary patch literal 85769 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 literal 0 HcmV?d00001 diff --git a/inventory-web/public/vite.svg b/inventory-web/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/inventory-web/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/inventory-web/src/api/inbound/semi.ts b/inventory-web/src/api/inbound/semi.ts index e69de29..18c2253 100644 --- a/inventory-web/src/api/inbound/semi.ts +++ b/inventory-web/src/api/inbound/semi.ts @@ -0,0 +1,45 @@ +import request from '@/utils/request' + +// 1. 获取列表 +export function getSemiList(params: any) { + return request({ + url: '/inbound/semi/list', + method: 'get', + params + }) +} + +// 2. 新增入库 +export function createSemiInbound(data: any) { + return request({ + url: '/inbound/semi/submit', + method: 'post', + data + }) +} + +// 3. 更新入库 +export function updateSemiInbound(id: number, data: any) { + return request({ + url: `/inbound/semi/${id}`, + method: 'put', + data + }) +} + +// 4. 删除入库 +export function deleteSemiInbound(id: number) { + return request({ + url: `/inbound/semi/${id}`, + method: 'delete' + }) +} + +// 5. 搜索基础物料 +export function searchMaterialBase(keyword: string) { + return request({ + url: '/inbound/semi/search-base', + method: 'get', + params: { keyword } + }) +} \ No newline at end of file diff --git a/inventory-web/src/views/stock/inbound/semi.vue b/inventory-web/src/views/stock/inbound/semi.vue index 96c0baf..1f0c7bf 100644 --- a/inventory-web/src/views/stock/inbound/semi.vue +++ b/inventory-web/src/views/stock/inbound/semi.vue @@ -1,11 +1,883 @@ - - - \ No newline at end of file