refactor(purchase): 批次概念改为基于 request_no 前缀推导,撤销数据库字段
按用户反馈:不需要新增数据库字段,现有 request_no (PUR-20260831-1021-0001)
本身就能推导批次——去掉末尾4位流水号即为批次前缀。
- 撤销 purchase_request.batch_no 字段(模型/数据库)
- 撤销 create 接口的 batch_no 参数与 generate_batch_no
- 批次标识 = request_no 去掉末尾 -XXXX 段
getBatchKey('PUR-20260831-1021-0001') = 'PUR-20260831-1021'
- 按批次查询/批量审批接口改用 batch_key (request_no LIKE 前缀)
- 前端列表批次号列、整批弹窗、一键审批本批均基于前缀推导
- 零数据库迁移,历史数据立即可用
This commit is contained in:
@ -158,18 +158,18 @@ def get_purchase_detail(purchase_id):
|
||||
|
||||
|
||||
# --------------------------------------------------------
|
||||
# 3.5 按批次查询采购申请(同一批提交的多条记录)
|
||||
# GET /api/v1/purchase/batch/<batch_no>
|
||||
# 3.5 按批次查询采购申请(同一批提交的多条记录,批次=request_no去掉末尾流水号)
|
||||
# GET /api/v1/purchase/batch/<batch_key>
|
||||
# --------------------------------------------------------
|
||||
@purchase_bp.route('/batch/<path:batch_no>', methods=['GET'])
|
||||
@purchase_bp.route('/batch/<path:batch_key>', methods=['GET'])
|
||||
@jwt_required()
|
||||
def get_purchase_by_batch(batch_no):
|
||||
"""按批次号查询同一批提交的所有采购申请记录"""
|
||||
def get_purchase_by_batch(batch_key):
|
||||
"""按批次前缀(request_no 去掉末尾4位流水号)查询同一批的所有记录"""
|
||||
try:
|
||||
from app.models.purchase import PurchaseRequest
|
||||
records = PurchaseRequest.query.filter(
|
||||
PurchaseRequest.batch_no == batch_no
|
||||
).order_by(PurchaseRequest.id.asc()).all()
|
||||
PurchaseRequest.request_no.like(f"{batch_key}-%")
|
||||
).order_by(PurchaseRequest.request_no.asc()).all()
|
||||
|
||||
user_id = get_current_user_id()
|
||||
has_perm = _user_has_purchase_perm()
|
||||
@ -183,7 +183,7 @@ def get_purchase_by_batch(batch_no):
|
||||
d.pop(k, None)
|
||||
items.append(d)
|
||||
|
||||
return jsonify({'code': 200, 'msg': '获取成功', 'data': {'batch_no': batch_no, 'items': items}}), 200
|
||||
return jsonify({'code': 200, 'msg': '获取成功', 'data': {'batch_key': batch_key, 'items': items}}), 200
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
return jsonify({'code': 500, 'msg': str(e)}), 500
|
||||
@ -248,7 +248,7 @@ def batch_approve_purchase():
|
||||
{
|
||||
"ids": [1, 2, 3], // 按 ID 列表审批
|
||||
或
|
||||
"batch_no": "BATCH-xxx", // 按批次号审批整批(同一批提交的记录)
|
||||
"batch_key": "PUR-20260831-1021", // 按批次前缀审批整批(同批流水号连续)
|
||||
"action": "approve" | "reject",
|
||||
"reject_reason": "驳回原因(reject 时必填)"
|
||||
}
|
||||
@ -257,15 +257,15 @@ def batch_approve_purchase():
|
||||
user_id = get_current_user_id()
|
||||
data = request.get_json() or {}
|
||||
ids = data.get('ids', [])
|
||||
batch_no = data.get('batch_no')
|
||||
batch_key = data.get('batch_key')
|
||||
action = data.get('action', 'approve')
|
||||
reject_reason = data.get('reject_reason')
|
||||
|
||||
# 若传 batch_no,则查出该批次的所有待审批记录 ID
|
||||
if batch_no:
|
||||
# 若传 batch_key(request_no 去掉末尾流水号的前缀),查出该批次所有待审批记录
|
||||
if batch_key:
|
||||
from app.models.purchase import PurchaseRequest
|
||||
records = PurchaseRequest.query.filter(
|
||||
PurchaseRequest.batch_no == batch_no,
|
||||
PurchaseRequest.request_no.like(f"{batch_key}-%"),
|
||||
PurchaseRequest.status == 0
|
||||
).all()
|
||||
ids = [r.id for r in records]
|
||||
@ -273,7 +273,7 @@ def batch_approve_purchase():
|
||||
return jsonify({'code': 400, 'msg': '该批次没有待审批的记录'}), 400
|
||||
|
||||
if not ids or not isinstance(ids, list):
|
||||
return jsonify({'code': 400, 'msg': 'ids 或 batch_no 不能为空'}), 400
|
||||
return jsonify({'code': 400, 'msg': 'ids 或 batch_key 不能为空'}), 400
|
||||
if action not in ('approve', 'reject'):
|
||||
return jsonify({'code': 400, 'msg': '无效的审批操作'}), 400
|
||||
if action == 'reject' and not reject_reason:
|
||||
|
||||
@ -11,8 +11,6 @@ class PurchaseRequest(db.Model):
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
request_no = db.Column(db.String(100), unique=True, nullable=False, index=True)
|
||||
# [新增] 采购批次号:同一批循环提交的多条记录共享,用于分组查看/统计
|
||||
batch_no = db.Column(db.String(100), index=True, comment='采购批次号(同一批提交的多条记录共享)')
|
||||
# [新增] 硬关联基础物料表,打通"按单入库"链路
|
||||
base_id = db.Column(db.Integer, db.ForeignKey('material_base.id'), index=True, comment='关联基础物料ID')
|
||||
name = db.Column(db.String(255), nullable=False, comment='采购名称')
|
||||
@ -81,7 +79,6 @@ class PurchaseRequest(db.Model):
|
||||
return {
|
||||
'id': self.id,
|
||||
'request_no': self.request_no,
|
||||
'batch_no': self.batch_no or '',
|
||||
'base_id': self.base_id,
|
||||
'name': self.name,
|
||||
'spec_model': self.spec_model or '',
|
||||
|
||||
@ -20,18 +20,6 @@ class PurchaseService:
|
||||
.filter(PurchaseRequest.request_no.like(f"{prefix}%")).scalar()
|
||||
return f"{prefix}{(existing_count + 1):04d}"
|
||||
|
||||
@staticmethod
|
||||
def generate_batch_no():
|
||||
"""生成采购批次号: BATCH-yyyyMMdd-HHmm-当日流水(4位)
|
||||
同一批循环提交的多条记录共享同一 batch_no"""
|
||||
import uuid
|
||||
beijing_tz = timezone(timedelta(hours=8))
|
||||
now = datetime.now(beijing_tz)
|
||||
date_str = now.strftime('%Y%m%d')
|
||||
time_str = now.strftime('%H%M')
|
||||
# 用时间戳 + 随机段确保唯一
|
||||
return f"BATCH-{date_str}-{time_str}-{uuid.uuid4().hex[:4].upper()}"
|
||||
|
||||
@staticmethod
|
||||
def auto_fill_from_material(keyword: str):
|
||||
"""
|
||||
@ -79,12 +67,8 @@ class PurchaseService:
|
||||
if material:
|
||||
base_id = material.id
|
||||
|
||||
# [新增] 批次号:前端同一批循环提交时传入同一 batch_no,无则自动生成
|
||||
batch_no = data.get('batch_no') or PurchaseService.generate_batch_no()
|
||||
|
||||
purchase = PurchaseRequest(
|
||||
request_no=request_no,
|
||||
batch_no=batch_no, # [新增]
|
||||
base_id=base_id, # [新增]
|
||||
name=data['name'],
|
||||
spec_model=data.get('spec_model', ''),
|
||||
|
||||
Reference in New Issue
Block a user