Files
KCGL/inventory-web/src/api/scrap.ts
yueli 4c7f0ae47c feat(scrap): 报废记录按原因分类筛选 + Excel 导出 + 显示分类
- 记录页与审批页展示「原因分类」:分类数据一直有下发,只是前端没渲染,
  页面上一个地方都看不到。
- 记录页加分类筛选。★ 选「库存报废」时 SQL 一并兜住空值:本列上线前的
  历史台账没有分类,而它们全是 MOM 自身流程产生的;不兜会漏掉全部历史单,
  用户会以为数据丢了。
- 新增 GET /scrap/records/export 导出 xlsx:与列表同一套筛选,但导**全部
  匹配结果**而不是当前页 —— 只导当前页会让人以为数据被截断。
  金额按 scrap_list:loss_amount 权限决定可不可见(与列表同口径),
  否则导出就成了绕过字段级权限的后门。行数上限 20000 且截断会写进文件名。
2026-09-23 15:17:44 +08:00

150 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import request from '@/utils/request'
// 1. 扫码查询库存
//
// ★ requestId 必须传:在管不良品的 SKU 复制自原库存行,同一码可能同时
// 命中 stock_buy#M 与 trans_defective_goods#N —— 这是两个不同实物,
// 条码本身无法区分。带上当前申请单 id 后,后端会优先返回该单批准明细
// 指定的那一条,避免「清单里明明有、扫码却说不在批准明细中」。
export function scanBarcode(barcode: string, requestId?: number) {
return request({
url: '/v1/scrap/scan',
method: 'get',
params: { barcode, request_id: requestId }
})
}
// [已移除] 直接报废 createScrap —— 对应后端 POST /api/v1/scrap,该接口绕过
// 审批流直接写 trans_scrap 并扣库存,与系统自陈的「报废一律需审批」规则冲突,
// 构成职责分离漏洞(同一库管可自行宣告实物销毁而无人复核),已整体删除。
// 所有报废改走:submitScrapRequest → approveScrapRequest → executeScrapByRequest。
// 该函数此前已是死代码(全仓无调用方),删除无行为影响。
// 3. 报废记录列表查询
export function getScrapRecords(params: any) {
return request({
url: '/v1/scrap/records',
method: 'get',
params
})
}
// 4. 报废记录导出 Excel
//
// ★ 与列表页**同一套筛选参数**,但后端导出的是**全部匹配结果**而不是当前页 ——
// 用户点「导出」要的就是全量,只导当前页会让他以为数据被截断了。
// ★ responseType: 'blob' 不能省,否则 axios 会把二进制当文本解析,文件打不开。
// ★ 损失金额由后端按 scrap_list:loss_amount 权限决定可不可见(与列表页同口径),
// 前端不做二次处理 —— 否则导出会变成绕过字段级权限的后门。
export function exportScrapRecords(params: any) {
return request({
url: '/v1/scrap/records/export',
method: 'get',
params,
responseType: 'blob' as any,
headers: {
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
}
})
}
// 3.1 报废申请专用库存列表(独立于出库选单权限,Fail-Closed 剥离价格)
export function getScrapStockList(params: { page?: number; pageSize?: number; keyword?: string }) {
return request({
url: '/v1/scrap/stock-list',
method: 'get',
params
})
}
// ==========================================
// 报废申请/审批/执行(新流程,镜像出/借库)
// ==========================================
// 4. 提交报废申请
export function submitScrapRequest(data: {
items: Array<{
source_table: string
stock_id: number
scrap_qty: number
name?: string
spec_model?: string
sku?: string
location?: string
batch_number?: string
}>
remark?: string
approver_id?: number | null
allowed_approvers?: Array<{ type: string; value: any }>
}) {
return request({
url: '/v1/scrap/request',
method: 'post',
data
})
}
// 5. 提交前预检:所选物料是否需要审批
export function checkScrapApproval(data: { items: Array<{ name?: string; spec_model?: string; base_id?: number }> }) {
return request({
url: '/v1/scrap/request/check-approval',
method: 'post',
data
})
}
// 6. 报废申请列表(scope: mine | pending | executable | all)
export function getScrapApprovals(params: {
scope?: 'mine' | 'pending' | 'executable' | 'all'
status?: number | ''
page?: number
limit?: number
}) {
return request({
url: '/v1/scrap/request',
method: 'get',
params
})
}
// 7. 报废申请详情
export function getScrapApprovalDetail(id: number) {
return request({
url: `/v1/scrap/request/${id}`,
method: 'get'
})
}
// 8. 审批(通过/驳回)
export function approveScrapRequest(id: number, data: { action: 'approve' | 'reject'; reject_reason?: string }) {
return request({
url: `/v1/scrap/request/${id}/approve`,
method: 'patch',
data
})
}
// 9. 按单报废执行(提交实扫明细,扣减库存)
// items 必须是该申请单批准明细的子集,且累计数量不得超过批准数量
export function executeScrapByRequest(id: number, items: Array<{
source_table: string
stock_id: number
quantity: number
sku?: string
name?: string
}>) {
return request({
url: `/v1/scrap/request/${id}/execute`,
method: 'post',
data: { items }
})
}
// 10. 撤回已通过但尚未执行的报废申请(作废该单;若已接入预占则一并释放库存)
export function withdrawScrapRequest(id: number) {
return request({
url: `/v1/scrap/request/${id}/withdraw`,
method: 'post'
})
}