feat: 采购申请新增库管'完结'功能(仿出库审批)
- 后端:approve 接口支持 action=close(已通过→已完结 status 1→4),模型 status_text 支持已完结 - 前端:采购申请状态tab加'已完结',已通过单显示'完结'按钮(库管)
This commit is contained in:
@ -206,7 +206,7 @@ def approve_purchase_request(purchase_id):
|
|||||||
action = data.get('action', 'approve')
|
action = data.get('action', 'approve')
|
||||||
reject_reason = data.get('reject_reason')
|
reject_reason = data.get('reject_reason')
|
||||||
|
|
||||||
if action not in ('approve', 'reject'):
|
if action not in ('approve', 'reject', 'close'):
|
||||||
return jsonify({'code': 400, 'msg': '无效的审批操作'}), 400
|
return jsonify({'code': 400, 'msg': '无效的审批操作'}), 400
|
||||||
|
|
||||||
if action == 'reject' and not reject_reason:
|
if action == 'reject' and not reject_reason:
|
||||||
@ -219,7 +219,7 @@ def approve_purchase_request(purchase_id):
|
|||||||
reject_reason=reject_reason
|
reject_reason=reject_reason
|
||||||
)
|
)
|
||||||
|
|
||||||
msg = '审批通过' if action == 'approve' else '已驳回'
|
msg = '审批通过' if action == 'approve' else ('已驳回' if action == 'reject' else '已完结')
|
||||||
# ★ Fail-Closed: 审批响应剥离价格字段
|
# ★ Fail-Closed: 审批响应剥离价格字段
|
||||||
resp = purchase.to_dict()
|
resp = purchase.to_dict()
|
||||||
for k in ('unit_price', 'total_price', 'tax_rate'):
|
for k in ('unit_price', 'total_price', 'tax_rate'):
|
||||||
|
|||||||
@ -91,7 +91,7 @@ class PurchaseRequest(db.Model):
|
|||||||
'total_price': float(self.total_price) if self.total_price else 0,
|
'total_price': float(self.total_price) if self.total_price else 0,
|
||||||
'tax_rate': float(self.tax_rate) if self.tax_rate else 0,
|
'tax_rate': float(self.tax_rate) if self.tax_rate else 0,
|
||||||
'status': self.status,
|
'status': self.status,
|
||||||
'status_text': ['待审批', '已通过', '已驳回', '已完成'][self.status] if self.status in [0, 1, 2, 3] else '未知',
|
'status_text': ['待审批', '已通过', '已驳回', '已完成', '已完结'][self.status] if self.status in [0, 1, 2, 3, 4] else '未知',
|
||||||
'requester_id': self.requester_id,
|
'requester_id': self.requester_id,
|
||||||
'requester_name': self._get_user_name(self.requester_id),
|
'requester_name': self._get_user_name(self.requester_id),
|
||||||
'requester_email': self._get_user_email(self.requester_id),
|
'requester_email': self._get_user_email(self.requester_id),
|
||||||
|
|||||||
@ -145,12 +145,22 @@ class PurchaseService:
|
|||||||
if not purchase:
|
if not purchase:
|
||||||
raise ValueError("采购申请不存在")
|
raise ValueError("采购申请不存在")
|
||||||
|
|
||||||
if purchase.status != 0:
|
|
||||||
raise ValueError("当前状态不允许审批")
|
|
||||||
|
|
||||||
beijing_tz = timezone(timedelta(hours=8))
|
beijing_tz = timezone(timedelta(hours=8))
|
||||||
now = datetime.now(beijing_tz)
|
now = datetime.now(beijing_tz)
|
||||||
|
|
||||||
|
# ★ 完结:库管将「已通过(1)」的申请单置为「已完结(4)」(仿出库审批)
|
||||||
|
if action == 'close':
|
||||||
|
if purchase.status != 1:
|
||||||
|
raise ValueError("仅「已通过」的采购申请可完结")
|
||||||
|
purchase.status = 4
|
||||||
|
purchase.approver_id = user_id
|
||||||
|
purchase.approved_at = now
|
||||||
|
db.session.commit()
|
||||||
|
return purchase
|
||||||
|
|
||||||
|
if purchase.status != 0:
|
||||||
|
raise ValueError("当前状态不允许审批")
|
||||||
|
|
||||||
if action == 'approve':
|
if action == 'approve':
|
||||||
purchase.status = 1
|
purchase.status = 1
|
||||||
purchase.approver_id = user_id
|
purchase.approver_id = user_id
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
<el-radio-button :label="1">已通过</el-radio-button>
|
<el-radio-button :label="1">已通过</el-radio-button>
|
||||||
<el-radio-button :label="2">已驳回</el-radio-button>
|
<el-radio-button :label="2">已驳回</el-radio-button>
|
||||||
<el-radio-button :label="3">已完成</el-radio-button>
|
<el-radio-button :label="3">已完成</el-radio-button>
|
||||||
|
<el-radio-button :label="4">已完结</el-radio-button>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<el-button type="primary" :icon="Refresh" @click="fetchData">刷新</el-button>
|
<el-button type="primary" :icon="Refresh" @click="fetchData">刷新</el-button>
|
||||||
<el-button type="success" :icon="Plus" @click="openCreateDialog">
|
<el-button type="success" :icon="Plus" @click="openCreateDialog">
|
||||||
@ -57,6 +58,10 @@
|
|||||||
<el-button type="success" link size="small" @click="handleApprove(it)">通过</el-button>
|
<el-button type="success" link size="small" @click="handleApprove(it)">通过</el-button>
|
||||||
<el-button type="danger" link size="small" @click="openRejectDialog(it)">驳回</el-button>
|
<el-button type="danger" link size="small" @click="openRejectDialog(it)">驳回</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
<!-- ★ 已通过的采购申请:库管可手动完结 -->
|
||||||
|
<template v-else-if="it.status === 1 && canClose">
|
||||||
|
<el-button type="danger" plain link size="small" @click="handleCloseRequest(it)">完结</el-button>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -703,10 +708,16 @@ const canApprove = computed(() => {
|
|||||||
|| userStore.hasPermission('inbound_purchase:operation')
|
|| userStore.hasPermission('inbound_purchase:operation')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ★ 完结权限:超级管理员 / 库管(采购操作权限)
|
||||||
|
const canClose = computed(() => {
|
||||||
|
return userStore.role === 'SUPER_ADMIN'
|
||||||
|
|| userStore.hasPermission('inbound_purchase:operation')
|
||||||
|
})
|
||||||
|
|
||||||
// --- 工具函数 ---
|
// --- 工具函数 ---
|
||||||
const statusTagType = (status: number) => {
|
const statusTagType = (status: number) => {
|
||||||
const map: Record<number, string> = {
|
const map: Record<number, string> = {
|
||||||
0: 'warning', 1: 'success', 2: 'danger', 3: 'info'
|
0: 'warning', 1: 'success', 2: 'danger', 3: 'info', 4: 'info'
|
||||||
}
|
}
|
||||||
return map[status] ?? 'info'
|
return map[status] ?? 'info'
|
||||||
}
|
}
|
||||||
@ -1170,6 +1181,26 @@ const handleApprove = async (row: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ★ 完结已通过的采购申请(库管)
|
||||||
|
const handleCloseRequest = async (row: any) => {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(
|
||||||
|
`确定强制完结采购申请【${row.request_no}】吗?\n\n` +
|
||||||
|
`此操作将使该单从「已通过」列表中移除,且不可恢复。`,
|
||||||
|
'⚠️ 强制完结确认',
|
||||||
|
{ confirmButtonText: '确认完结', cancelButtonText: '取消', type: 'warning' }
|
||||||
|
)
|
||||||
|
} catch { return }
|
||||||
|
|
||||||
|
try {
|
||||||
|
await approvePurchase(row.id, { action: 'close' })
|
||||||
|
ElMessage.success(`采购申请 ${row.request_no} 已完结`)
|
||||||
|
await fetchData()
|
||||||
|
} catch (err: any) {
|
||||||
|
ElMessage.error(err?.msg || err?.message || '完结失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const openRejectDialog = (row: any) => {
|
const openRejectDialog = (row: any) => {
|
||||||
currentRejectRow.value = row
|
currentRejectRow.value = row
|
||||||
rejectReason.value = ''
|
rejectReason.value = ''
|
||||||
|
|||||||
Reference in New Issue
Block a user