feat(return): 前端退回入口与不良品在管台账看板

出库记录页(views/outbound/index.vue):
- 明细行新增「退回」列,returnable_quantity <= 0 时按钮置灰,行内显示「已退 N」
- 对话框展示 原出库数量 / 已退回数量 / 本次可退最大,默认带入可退最大值
- 退回类型用下拉单选:良品(加回库存)/ 不良品(转入异常待处理)
- 退回原因必填,提交前三重校验;按钮 :loading + 函数内 submitting 双保险防抖
- 成功后刷新列表。错误提示不重复弹——request 拦截器对 HTTP 400 已取
  data.msg 展示,对话框 catch 只收尾

配套后端(services/outbound_service.py):
- get_grouped_list 的出库明细补 id / returned_quantity / returnable_quantity。
  原先明细不带 id,退回接口无从指定 outbound_id

新增页面(views/stock/defective/index.vue,路由 /inventory/defective):
- 展示 物料名称/规格/SKU/退回时间/操作人/退回总数/剩余待处理/状态
- 顶部 alert 提示在管总量,并明确「这批实物不在库存表中,盘点请以本台账
  为准」——在管坏件对盘点不可见是本方案的固有盲区,必须在页面上主动提醒
- 仅对 remaining_qty > 0 的行提供「修复回库」「报废销毁」,终态行显示已结案
- 两个弹窗均带数量上限约束与 loading 防抖,成功后刷新

新增 api/inbound/return.ts 承载四个逆向物流接口。

侧边栏由 router/index.ts 驱动,加路由即入菜单;注意侧边栏只过滤
meta.hidden、不看 meta.permission,故菜单对所有角色可见,访问控制由后端
接口负责(与既有「维修管理」一致)。
This commit is contained in:
yueli
2026-09-16 15:45:40 +08:00
parent dda6e4c787
commit fd99d33a0d
4 changed files with 730 additions and 1 deletions

View File

@ -0,0 +1,86 @@
import request from '@/utils/request'
// ============================================================================
// 逆向物流(原单退回 + 不良品在管台账)
//
// 后端路由见 inventory-backend/app/api/v1/inbound/stock.py
// 设计要点:
// · 良品退回 → 直接加回原库存行
// · 不良品退回 → 不进库存表,转入 trans_defective_goods 在管台账,
// 修好后回库 / 无法维修则报废销毁
// ============================================================================
/**
* 原单退回。
*
* @param data {
* outbound_id: number 必填,trans_outbound.id(出库**明细行**主键,非单号)
* return_qty: number 必填,本次退回数量(>0)
* is_defective: boolean 必填,true=不良品转在管台账,false=良品加回库存
* reason: string 可选,退回原因
* }
*/
export function returnFromOutbound(data: {
outbound_id: number
return_qty: number
is_defective: boolean
reason?: string
}) {
return request({
url: '/inbound/stock/return-from-outbound',
method: 'post',
data
})
}
/**
* 不良品在管台账分页查询。
*
* @param params { page, page_size, status?, keyword?, start_date?, end_date? }
* status 传 '全部' 或留空表示不过滤
*/
export function getDefectiveList(params: {
page?: number
page_size?: number
status?: string
keyword?: string
start_date?: string
end_date?: string
company_name?: string
}) {
return request({
url: '/inbound/stock/defective',
method: 'get',
params
})
}
/**
* 修复回库:把修好的数量加回原库存行。
*
* @param id 在管台账 id
* @param data { restock_qty?: number, remark?: string }
* restock_qty 缺省 = 全部剩余在管量
*/
export function restockDefective(id: number, data: { restock_qty?: number; remark?: string }) {
return request({
url: `/inbound/stock/defective/${id}/restock`,
method: 'post',
data
})
}
/**
* 报废销毁:在管坏件确认无法维修时销毁。
*
* @param id 在管台账 id
* @param data { scrap_qty?: number, reason: string }
* reason 必填;scrap_qty 缺省 = 全部剩余在管量
*/
export function scrapDefective(id: number, data: { scrap_qty?: number; reason: string }) {
return request({
url: `/inbound/stock/defective/${id}/scrap`,
method: 'post',
data
})
}