diff --git a/inventory-backend/app/services/inbound/buy_service.py b/inventory-backend/app/services/inbound/buy_service.py index b2f14ef..8035957 100644 --- a/inventory-backend/app/services/inbound/buy_service.py +++ b/inventory-backend/app/services/inbound/buy_service.py @@ -4,6 +4,7 @@ from app.extensions import db from app.models.inbound.buy import StockBuy from app.models.inbound.product import StockProduct from app.models.base import MaterialBase +from app.models.purchase import PurchaseRequest from datetime import datetime, timedelta, timezone from sqlalchemy import or_, func, text, and_ from sqlalchemy.exc import IntegrityError @@ -153,9 +154,27 @@ class BuyInboundService: in_qty = float(data.get('in_quantity') or 0) u_price = float(data.get('unit_price') or 0) tax_rate = float(data.get('tax_rate') or 0) - - # 计算税后单价 post_tax_price = float(data.get('post_tax_unit_price') or 0) + + # [新增] 按单入库:关联采购申请单 + request_id = data.get('request_id') + + # ★ 补价:库管角色没有 inbound_purchase:unit_price / total_price 权限, + # 采购单接口(api/v1/purchase.py)会把价格字段整个 pop 掉,前端导入时 + # 因此带不出价(buy.vue 的 hasUnitPrice/hasTotalPrice 双双落空, + # 两个分支都不进)→ 入库成本被记成 0。 + # 这里在落库前从采购申请单补回:价格**不经过前端**,库管依旧看不到 + # 采购价,权限边界不变,但成本可追溯。 + # 注:采购申请单的 unit_price 存的是**含税**单价(见 purchase/index.vue + # 的列名"含税单价"),需要反算不含税单价。 + if request_id and u_price <= 0 and post_tax_price <= 0: + _req = PurchaseRequest.query.get(request_id) + if _req and float(_req.unit_price or 0) > 0: + tax_rate = float(_req.tax_rate or 0) + post_tax_price = float(_req.unit_price) + u_price = post_tax_price / (1 + tax_rate / 100) + + # 计算税后单价(保底:只给了不含税价时反推) if post_tax_price == 0 and u_price > 0: tax_multiplier = 1 + (tax_rate / 100) post_tax_price = u_price * tax_multiplier @@ -170,9 +189,6 @@ class BuyInboundService: 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 - # [新增] 按单入库:关联采购申请单 - request_id = data.get('request_id') - new_stock = StockBuy( base_id=material.id, global_print_id=next_global_id, sku=generated_sku, barcode=final_barcode, in_date=in_date_val, serial_number=data.get('serial_number'), batch_number=data.get('batch_number'), @@ -201,8 +217,10 @@ class BuyInboundService: db.session.flush() # 获取 new_stock.id # [新增] 按单入库:反写采购申请单状态为"已完成" + # 注:原先此处有一句局部 `from app.models.purchase import PurchaseRequest`, + # 它会让 Python 把 PurchaseRequest 视为本函数的局部变量,导致上方补价 + # 逻辑(在 import 之前使用)抛 UnboundLocalError。已改用文件顶部的全局导入。 if request_id: - from app.models.purchase import PurchaseRequest purchase_req = db.session.get(PurchaseRequest, request_id) if purchase_req: if purchase_req.status != 1: