feat(borrow,outbound): 申请预检按需显示审批人——默认不显示,命中需审批才出现并必选
- 后端新增 /borrow/request/check-approval 与 /outbound/request/check-approval 预检接口 - 申请弹窗默认隐藏审批人;提交前预检:命中需审批→显示审批人并红字列物料、未选拦截;未命中→隐藏并直接提交(approver=null) - 申请 items 补传 base_id 供后端 ID 精确判定
This commit is contained in:
@ -429,6 +429,28 @@ def create_outbound_request():
|
||||
return jsonify({'code': 500, 'msg': f'服务器内部错误: {str(e)}'}), 500
|
||||
|
||||
|
||||
# --------------------------------------------------------
|
||||
# 4.1 出库申请预检(判断所选物料是否需审批,驱动前端是否显示审批人)
|
||||
# POST /api/v1/outbound/request/check-approval
|
||||
# --------------------------------------------------------
|
||||
@outbound_bp.route('/request/check-approval', methods=['POST'])
|
||||
@jwt_required()
|
||||
@permission_required('outbound_selection')
|
||||
def check_outbound_approval():
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
items = data.get('items', []) or []
|
||||
from app.services.approval_control import resolve_approval_control
|
||||
need_approval, flagged = resolve_approval_control(items)
|
||||
return jsonify({
|
||||
"code": 200, "msg": "success",
|
||||
"data": {"need_approval": need_approval, "materials": flagged}
|
||||
}), 200
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
return jsonify({"code": 500, "msg": f"预检失败: {str(e)}"}), 500
|
||||
|
||||
|
||||
# --------------------------------------------------------
|
||||
# 5. 审批出库申请
|
||||
# PATCH /api/v1/outbound/request/<id>/approve
|
||||
|
||||
@ -311,6 +311,25 @@ def close_borrow_request(request_id):
|
||||
return jsonify({'code': 500, 'msg': f'服务器内部错误: {str(e)}'}), 500
|
||||
|
||||
|
||||
# --- 借库申请预检(判断所选物料是否需审批,驱动前端是否显示审批人) ---
|
||||
@trans_bp.route('/borrow/request/check-approval', methods=['POST'])
|
||||
@jwt_required()
|
||||
@permission_required('op_borrow_apply')
|
||||
def check_borrow_approval():
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
items = data.get('items', []) or []
|
||||
from app.services.approval_control import resolve_approval_control
|
||||
need_approval, flagged = resolve_approval_control(items)
|
||||
return jsonify({
|
||||
"code": 200, "msg": "success",
|
||||
"data": {"need_approval": need_approval, "materials": flagged}
|
||||
}), 200
|
||||
except Exception as e:
|
||||
import traceback; traceback.print_exc()
|
||||
return jsonify({"code": 500, "msg": f"预检失败: {str(e)}"}), 500
|
||||
|
||||
|
||||
# --- 获取借库审批单列表 ---
|
||||
@trans_bp.route('/borrow/request', methods=['GET'])
|
||||
@jwt_required()
|
||||
|
||||
@ -99,6 +99,15 @@ export function submitOutboundRequest(data: {
|
||||
})
|
||||
}
|
||||
|
||||
// 出库申请预检:判断所选物料是否需审批
|
||||
export function checkOutboundApproval(data: { items: Array<{ name?: string; spec_model?: string }> }) {
|
||||
return request({
|
||||
url: '/v1/outbound/request/check-approval',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取出库审批申请单列表
|
||||
* @param params 支持 status, page, limit
|
||||
|
||||
@ -149,6 +149,15 @@ export function submitBorrowRequest(data: {
|
||||
})
|
||||
}
|
||||
|
||||
// 借库申请预检:判断所选物料是否需审批
|
||||
export function checkBorrowApproval(data: { items: Array<{ name?: string; spec_model?: string }> }) {
|
||||
return request({
|
||||
url: '/v1/transactions/borrow/request/check-approval',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取借库审批申请单列表
|
||||
* @param params 支持 status, page, limit
|
||||
|
||||
@ -394,7 +394,10 @@
|
||||
</el-table>
|
||||
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="* 指定审批人" required>
|
||||
<el-form-item v-if="approvalNeedVisible" label="指定审批人">
|
||||
<div v-if="approvalNeedText" style="color:#E6A23C; font-size:12px; line-height:1.4; margin-bottom:4px;">
|
||||
以下物料需审批出库/借库:{{ approvalNeedText }},请选择审批人
|
||||
</div>
|
||||
<el-select
|
||||
v-model="requestApproverId"
|
||||
placeholder="请选择审批人"
|
||||
@ -518,7 +521,7 @@ import { Printer, Search, Plus, Download, List } from '@element-plus/icons-vue'
|
||||
import { ElMessage, ElTable, ElMessageBox } from 'element-plus'
|
||||
import { printSelectionList } from '@/api/inbound/stock'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { submitBorrowRequest, getBorrowStockList } from '@/api/transaction'
|
||||
import { submitBorrowRequest, getBorrowStockList, checkBorrowApproval } from '@/api/transaction'
|
||||
import { bomMatchStock } from '@/api/outbound'
|
||||
import { getApproversList } from '@/api/auth'
|
||||
import { getBomList, getBomDetail, getBomWithStock } from '@/api/bom'
|
||||
@ -554,6 +557,9 @@ const requestIndefinite = ref(false)
|
||||
const requestApproverId = ref<number | null>(null)
|
||||
const approvers = ref<any[]>([])
|
||||
const requestSubmitting = ref(false)
|
||||
// 是否需审批(由提交前预检驱动,需审批才显示审批人输入框)
|
||||
const approvalNeedVisible = ref(false)
|
||||
const approvalNeedText = ref('')
|
||||
|
||||
const stockList = ref<any[]>([])
|
||||
const stockTotal = ref(0)
|
||||
@ -1052,6 +1058,8 @@ const openRequestDialog = () => {
|
||||
requestApproverId.value = null
|
||||
requestExpectedReturn.value = ''
|
||||
requestIndefinite.value = false
|
||||
approvalNeedVisible.value = false // 打开时默认隐藏审批人,命中需审批时由预检显示
|
||||
approvalNeedText.value = ''
|
||||
loadApprovers()
|
||||
requestDialogVisible.value = true
|
||||
}
|
||||
@ -1096,23 +1104,44 @@ const buildRemarkWithShortage = (baseRemark: string): string => {
|
||||
const confirmSubmitRequest = async () => {
|
||||
requestSubmitting.value = true
|
||||
try {
|
||||
const payload = {
|
||||
items: validSelectedItems.value.map((item: any) => ({
|
||||
const items = validSelectedItems.value.map((item: any) => ({
|
||||
base_id: item.base_id ?? null,
|
||||
name: item.name || '',
|
||||
spec_model: item.standard || '',
|
||||
warehouse_location: item.warehouse_location || '',
|
||||
quantity: item.export_quantity || 0,
|
||||
expected_return_time: requestIndefinite.value ? null : requestExpectedReturn.value,
|
||||
is_indefinite: requestIndefinite.value
|
||||
})),
|
||||
}))
|
||||
|
||||
// ★ 提交前预检:判断所选物料是否需审批 → 只有需审批才显示并必选审批人
|
||||
let needApproval = false
|
||||
let flagged: any[] = []
|
||||
try {
|
||||
const chk: any = await checkBorrowApproval({ items })
|
||||
needApproval = !!chk?.data?.need_approval
|
||||
flagged = chk?.data?.materials || []
|
||||
} catch (e) { needApproval = false; flagged = [] }
|
||||
approvalNeedVisible.value = needApproval
|
||||
approvalNeedText.value = flagged.map((m: any) => `${m.name}(${m.spec_model || '-'})`).join(';')
|
||||
|
||||
if (needApproval && !requestApproverId.value) {
|
||||
ElMessage.warning(`以下物料需审批出库/借库:${approvalNeedText.value}。请先选择审批人`)
|
||||
return
|
||||
}
|
||||
|
||||
const payload = {
|
||||
items,
|
||||
remark: buildRemarkWithShortage(requestRemark.value.trim()),
|
||||
approver_id: requestApproverId.value
|
||||
approver_id: needApproval ? requestApproverId.value : null
|
||||
}
|
||||
|
||||
await submitBorrowRequest(payload)
|
||||
|
||||
requestDialogVisible.value = false
|
||||
selectedItems.value = []
|
||||
approvalNeedVisible.value = false
|
||||
approvalNeedText.value = ''
|
||||
ElMessage.success('借库申请已提交(含需审批物料时将进入审批,否则直接交库管执行)')
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err?.message || err?.msg || '提交申请失败,请重试')
|
||||
|
||||
@ -409,7 +409,10 @@
|
||||
<el-option label="维修出库" value="REPAIR" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="* 指定审批人" required>
|
||||
<el-form-item v-if="approvalNeedVisible" label="指定审批人">
|
||||
<div v-if="approvalNeedText" style="color:#E6A23C; font-size:12px; line-height:1.4; margin-bottom:4px;">
|
||||
以下物料需审批出库/借库:{{ approvalNeedText }},请选择审批人
|
||||
</div>
|
||||
<el-select
|
||||
v-model="requestApproverId"
|
||||
placeholder="请选择审批人"
|
||||
@ -519,7 +522,7 @@ import { ElMessage, ElTable, ElMessageBox } from 'element-plus'
|
||||
import { getStockList, printSelectionList } from '@/api/inbound/stock'
|
||||
import { getBomList, getBomDetail, getBomWithStock } from '@/api/bom'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { submitOutboundRequest, bomMatchStock } from '@/api/outbound'
|
||||
import { submitOutboundRequest, bomMatchStock, checkOutboundApproval } from '@/api/outbound'
|
||||
import { getApproversList } from '@/api/auth'
|
||||
|
||||
const userStore = useUserStore()
|
||||
@ -551,6 +554,9 @@ const requestOutboundType = ref('') // 申请时必选出库类型,扫码出
|
||||
const requestApproverId = ref<number | null>(null)
|
||||
const approvers = ref<any[]>([])
|
||||
const requestSubmitting = ref(false)
|
||||
// 是否需审批(由提交前预检驱动,需审批才显示审批人输入框)
|
||||
const approvalNeedVisible = ref(false)
|
||||
const approvalNeedText = ref('')
|
||||
|
||||
const stockList = ref<any[]>([]) // 服务端分页数据
|
||||
const stockTotal = ref(0)
|
||||
@ -1079,6 +1085,8 @@ const openRequestDialog = () => {
|
||||
}
|
||||
requestRemark.value = ''
|
||||
requestApproverId.value = null
|
||||
approvalNeedVisible.value = false // 打开时默认隐藏审批人,命中需审批时由预检显示
|
||||
approvalNeedText.value = ''
|
||||
loadApprovers()
|
||||
requestDialogVisible.value = true
|
||||
}
|
||||
@ -1100,7 +1108,6 @@ const confirmSubmitRequest = async () => {
|
||||
ElMessage.warning('请填写申请原因')
|
||||
return
|
||||
}
|
||||
// 审批人改为可选:默认不审批时无需选择;所选物料命中“需审批”但未选审批人时,后端会提示补选
|
||||
if (!requestOutboundType.value) {
|
||||
ElMessage.warning('请选择出库类型')
|
||||
return
|
||||
@ -1108,17 +1115,36 @@ const confirmSubmitRequest = async () => {
|
||||
|
||||
requestSubmitting.value = true
|
||||
try {
|
||||
const payload: any = {
|
||||
items: validSelectedItems.value.map(item => ({
|
||||
const items = validSelectedItems.value.map(item => ({
|
||||
material_type: item.typeLabel || item.type || '',
|
||||
base_id: item.base_id ?? null,
|
||||
name: item.name || '',
|
||||
spec_model: item.standard || '',
|
||||
warehouse_location: item.warehouse_location || '',
|
||||
quantity: item.export_quantity || 0
|
||||
})),
|
||||
}))
|
||||
|
||||
// ★ 提交前预检:判断所选物料是否需审批 → 只有需审批才显示并必选审批人
|
||||
let needApproval = false
|
||||
let flagged: any[] = []
|
||||
try {
|
||||
const chk: any = await checkOutboundApproval({ items })
|
||||
needApproval = !!chk?.data?.need_approval
|
||||
flagged = chk?.data?.materials || []
|
||||
} catch (e) { needApproval = false; flagged = [] }
|
||||
approvalNeedVisible.value = needApproval
|
||||
approvalNeedText.value = flagged.map((m: any) => `${m.name}(${m.spec_model || '-'})`).join(';')
|
||||
|
||||
if (needApproval && !requestApproverId.value) {
|
||||
ElMessage.warning(`以下物料需审批出库/借库:${approvalNeedText.value}。请先选择审批人`)
|
||||
return
|
||||
}
|
||||
|
||||
const payload: any = {
|
||||
items,
|
||||
remark: buildRemarkWithShortage(trimmed),
|
||||
outbound_type: requestOutboundType.value,
|
||||
approver_id: requestApproverId.value
|
||||
approver_id: needApproval ? requestApproverId.value : null
|
||||
}
|
||||
|
||||
await submitOutboundRequest(payload)
|
||||
@ -1126,6 +1152,8 @@ const confirmSubmitRequest = async () => {
|
||||
// 成功:关闭弹窗、清空列表、提示
|
||||
requestDialogVisible.value = false
|
||||
selectedItems.value = []
|
||||
approvalNeedVisible.value = false
|
||||
approvalNeedText.value = ''
|
||||
ElMessage.success('出库申请已提交(含需审批物料时将进入审批,否则直接交库管执行)')
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err?.message || err?.msg || '提交申请失败,请重试')
|
||||
|
||||
Reference in New Issue
Block a user