电子请购单优化 库存明细页面
This commit is contained in:
@@ -10,6 +10,7 @@ import com.klp.common.core.validate.AddGroup;
|
|||||||
import com.klp.common.core.validate.EditGroup;
|
import com.klp.common.core.validate.EditGroup;
|
||||||
import com.klp.common.enums.BusinessType;
|
import com.klp.common.enums.BusinessType;
|
||||||
import com.klp.common.utils.poi.ExcelUtil;
|
import com.klp.common.utils.poi.ExcelUtil;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import com.klp.erp.domain.bo.ErpPurchaseRequisitionBo;
|
import com.klp.erp.domain.bo.ErpPurchaseRequisitionBo;
|
||||||
import com.klp.erp.domain.vo.ErpPurchaseRequisitionVo;
|
import com.klp.erp.domain.vo.ErpPurchaseRequisitionVo;
|
||||||
import com.klp.erp.service.IErpPurchaseRequisitionService;
|
import com.klp.erp.service.IErpPurchaseRequisitionService;
|
||||||
@@ -79,4 +80,28 @@ public class ErpPurchaseRequisitionController extends BaseController {
|
|||||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] reqIds) {
|
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] reqIds) {
|
||||||
return toAjax(iErpPurchaseRequisitionService.deleteWithValidByIds(Arrays.asList(reqIds), true));
|
return toAjax(iErpPurchaseRequisitionService.deleteWithValidByIds(Arrays.asList(reqIds), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 提交审批(草稿 → 审批中) */
|
||||||
|
@Log(title = "请购及采购单", businessType = BusinessType.UPDATE)
|
||||||
|
@SaCheckPermission("erp:purchaseRequisition:approve")
|
||||||
|
@PutMapping("/{reqId}/submit")
|
||||||
|
public R<Void> submitApproval(@NotNull(message = "主键不能为空") @PathVariable Long reqId) {
|
||||||
|
return toAjax(iErpPurchaseRequisitionService.submitApproval(reqId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 审批通过(审批中 → 已通过) */
|
||||||
|
@Log(title = "请购及采购单", businessType = BusinessType.UPDATE)
|
||||||
|
@SaCheckPermission("erp:purchaseRequisition:approve")
|
||||||
|
@PutMapping("/{reqId}/approve")
|
||||||
|
public R<Void> approve(@NotNull(message = "主键不能为空") @PathVariable Long reqId) {
|
||||||
|
return toAjax(iErpPurchaseRequisitionService.approve(reqId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 驳回(审批中 → 已驳回) */
|
||||||
|
@Log(title = "请购及采购单", businessType = BusinessType.UPDATE)
|
||||||
|
@SaCheckPermission("erp:purchaseRequisition:approve")
|
||||||
|
@PutMapping("/{reqId}/reject")
|
||||||
|
public R<Void> reject(@NotNull(message = "主键不能为空") @PathVariable Long reqId) {
|
||||||
|
return toAjax(iErpPurchaseRequisitionService.reject(reqId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,4 +33,13 @@ public interface IErpPurchaseRequisitionService {
|
|||||||
|
|
||||||
/** 校验并批量删除请购单 */
|
/** 校验并批量删除请购单 */
|
||||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
/** 提交审批(草稿 → 审批中) */
|
||||||
|
Boolean submitApproval(Long reqId);
|
||||||
|
|
||||||
|
/** 审批通过(审批中 → 已通过) */
|
||||||
|
Boolean approve(Long reqId);
|
||||||
|
|
||||||
|
/** 驳回(审批中 → 已驳回) */
|
||||||
|
Boolean reject(Long reqId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,22 +83,6 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public Boolean updateByBo(ErpPurchaseRequisitionBo bo) {
|
|
||||||
ErpPurchaseRequisition update = baseMapper.selectById(bo.getReqId());
|
|
||||||
if (update == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
BeanUtil.copyProperties(bo, update, "reqId", "createBy", "createTime");
|
|
||||||
baseMapper.updateById(update);
|
|
||||||
// 覆盖式重写明细
|
|
||||||
itemMapper.delete(Wrappers.lambdaQuery(ErpPurchaseRequisitionItem.class)
|
|
||||||
.eq(ErpPurchaseRequisitionItem::getReqId, bo.getReqId()));
|
|
||||||
saveItems(bo.getReqId(), bo.getItems());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveItems(Long reqId, List<ErpPurchaseRequisitionItemBo> items) {
|
private void saveItems(Long reqId, List<ErpPurchaseRequisitionItemBo> items) {
|
||||||
if (items == null || items.isEmpty()) {
|
if (items == null || items.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
@@ -120,10 +104,69 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio
|
|||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||||
for (Long reqId : ids) {
|
for (Long reqId : ids) {
|
||||||
|
ErpPurchaseRequisition entity = baseMapper.selectById(reqId);
|
||||||
|
if (entity != null && !"0".equals(entity.getFormStatus())) {
|
||||||
|
throw new RuntimeException("仅草稿状态的请购单可删除");
|
||||||
|
}
|
||||||
itemMapper.delete(Wrappers.lambdaQuery(ErpPurchaseRequisitionItem.class)
|
itemMapper.delete(Wrappers.lambdaQuery(ErpPurchaseRequisitionItem.class)
|
||||||
.eq(ErpPurchaseRequisitionItem::getReqId, reqId));
|
.eq(ErpPurchaseRequisitionItem::getReqId, reqId));
|
||||||
}
|
}
|
||||||
return baseMapper.deleteBatchIds(ids) > 0;
|
return baseMapper.deleteBatchIds(ids) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean updateByBo(ErpPurchaseRequisitionBo bo) {
|
||||||
|
ErpPurchaseRequisition update = baseMapper.selectById(bo.getReqId());
|
||||||
|
if (update == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!"0".equals(update.getFormStatus())) {
|
||||||
|
throw new RuntimeException("仅草稿状态的请购单可修改");
|
||||||
|
}
|
||||||
|
BeanUtil.copyProperties(bo, update, "reqId", "createBy", "createTime");
|
||||||
|
baseMapper.updateById(update);
|
||||||
|
// 覆盖式重写明细
|
||||||
|
itemMapper.delete(Wrappers.lambdaQuery(ErpPurchaseRequisitionItem.class)
|
||||||
|
.eq(ErpPurchaseRequisitionItem::getReqId, bo.getReqId()));
|
||||||
|
saveItems(bo.getReqId(), bo.getItems());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean submitApproval(Long reqId) {
|
||||||
|
ErpPurchaseRequisition entity = baseMapper.selectById(reqId);
|
||||||
|
if (entity == null) return false;
|
||||||
|
if (!"0".equals(entity.getFormStatus())) {
|
||||||
|
throw new RuntimeException("仅草稿状态的请购单可提交审批");
|
||||||
|
}
|
||||||
|
entity.setFormStatus("1");
|
||||||
|
return baseMapper.updateById(entity) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean approve(Long reqId) {
|
||||||
|
ErpPurchaseRequisition entity = baseMapper.selectById(reqId);
|
||||||
|
if (entity == null) return false;
|
||||||
|
if (!"1".equals(entity.getFormStatus())) {
|
||||||
|
throw new RuntimeException("仅审批中状态的请购单可通过");
|
||||||
|
}
|
||||||
|
entity.setFormStatus("2");
|
||||||
|
return baseMapper.updateById(entity) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean reject(Long reqId) {
|
||||||
|
ErpPurchaseRequisition entity = baseMapper.selectById(reqId);
|
||||||
|
if (entity == null) return false;
|
||||||
|
if (!"1".equals(entity.getFormStatus())) {
|
||||||
|
throw new RuntimeException("仅审批中状态的请购单可驳回");
|
||||||
|
}
|
||||||
|
entity.setFormStatus("5");
|
||||||
|
return baseMapper.updateById(entity) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,30 @@ export function updatePurchaseRequisition(data) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提交审批
|
||||||
|
export function submitApproval(reqId) {
|
||||||
|
return request({
|
||||||
|
url: '/erp/purchaseRequisition/' + reqId + '/submit',
|
||||||
|
method: 'put'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 审批通过
|
||||||
|
export function approvePurchase(reqId) {
|
||||||
|
return request({
|
||||||
|
url: '/erp/purchaseRequisition/' + reqId + '/approve',
|
||||||
|
method: 'put'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 驳回
|
||||||
|
export function rejectPurchase(reqId) {
|
||||||
|
return request({
|
||||||
|
url: '/erp/purchaseRequisition/' + reqId + '/reject',
|
||||||
|
method: 'put'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 删除请购单
|
// 删除请购单
|
||||||
export function delPurchaseRequisition(reqIds) {
|
export function delPurchaseRequisition(reqIds) {
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@@ -59,11 +59,15 @@
|
|||||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)" v-hasPermi="['erp:purchaseRequisition:query']">查看</el-button>
|
<div style="display:flex;flex-wrap:wrap;">
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['erp:purchaseRequisition:edit']">修改</el-button>
|
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)" v-hasPermi="['erp:purchaseRequisition:query']" style="width:50%;margin:0;text-align:center">查看</el-button>
|
||||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['erp:purchaseRequisition:remove']">删除</el-button>
|
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-if="scope.row.formStatus === '0'" v-hasPermi="['erp:purchaseRequisition:edit']" style="width:50%;margin:0;text-align:center">修改</el-button>
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-if="scope.row.formStatus === '0'" v-hasPermi="['erp:purchaseRequisition:remove']" style="width:50%;margin:0;text-align:center">删除</el-button>
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-upload2" @click="handleSubmitOne(scope.row)" v-if="scope.row.formStatus === '0'" v-hasPermi="['erp:purchaseRequisition:approve']" style="width:50%;margin:0;text-align:center">提交</el-button>
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-circle-check" style="color:#67c23a;width:50%;margin:0;text-align:center" @click="openApproval(scope.row)" v-if="scope.row.formStatus === '1'" v-hasPermi="['erp:purchaseRequisition:approve']">审批</el-button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</KLPTable>
|
</KLPTable>
|
||||||
@@ -355,10 +359,42 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button icon="el-icon-circle-check" style="color:#67c23a;float:left" @click="openApproval(viewForm)" v-if="viewForm.formStatus === '1'" v-hasPermi="['erp:purchaseRequisition:approve']">审批</el-button>
|
||||||
<el-button type="primary" icon="el-icon-download" :loading="printing" @click="exportPdf">导出PDF</el-button>
|
<el-button type="primary" icon="el-icon-download" :loading="printing" @click="exportPdf">导出PDF</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 审批弹窗 -->
|
||||||
|
<el-dialog title="审批请购单" :visible.sync="approvalOpen" width="560px" append-to-body :close-on-click-modal="false">
|
||||||
|
<div style="padding:0 8px">
|
||||||
|
<el-form size="small" label-width="90px">
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="请购部门">{{ approvalReq.reqDept || '—' }}</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="品名">{{ approvalReq.itemName || '—' }}</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="规格">{{ approvalReq.specification || '—' }}</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="请购量">{{ approvalReq.quantity || '—' }}</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-form-item label="审批意见">
|
||||||
|
<el-input v-model="approvalRemark" type="textarea" :rows="3" placeholder="请输入审批意见(可选)" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="doReject" type="danger" icon="el-icon-close" :loading="approvalLoading">驳 回</el-button>
|
||||||
|
<el-button @click="doApprove" type="primary" icon="el-icon-check" :loading="approvalLoading">通 过</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<!-- A4 打印模板(屏幕外渲染,供 html2canvas 截图) -->
|
<!-- A4 打印模板(屏幕外渲染,供 html2canvas 截图) -->
|
||||||
<div class="pr-print-wrap" v-show="printing">
|
<div class="pr-print-wrap" v-show="printing">
|
||||||
<div class="pr-print" ref="printTemplate">
|
<div class="pr-print" ref="printTemplate">
|
||||||
@@ -515,7 +551,10 @@ import {
|
|||||||
getPurchaseRequisition,
|
getPurchaseRequisition,
|
||||||
addPurchaseRequisition,
|
addPurchaseRequisition,
|
||||||
updatePurchaseRequisition,
|
updatePurchaseRequisition,
|
||||||
delPurchaseRequisition
|
delPurchaseRequisition,
|
||||||
|
submitApproval,
|
||||||
|
approvePurchase,
|
||||||
|
rejectPurchase
|
||||||
} from '@/api/erp/purchaseRequisition'
|
} from '@/api/erp/purchaseRequisition'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -545,6 +584,11 @@ export default {
|
|||||||
viewForm: {},
|
viewForm: {},
|
||||||
inspectionChecks: [],
|
inspectionChecks: [],
|
||||||
printData: {},
|
printData: {},
|
||||||
|
// 审批
|
||||||
|
approvalOpen: false,
|
||||||
|
approvalReq: {},
|
||||||
|
approvalRemark: '',
|
||||||
|
approvalLoading: false,
|
||||||
rules: {}
|
rules: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -630,6 +674,39 @@ export default {
|
|||||||
this.viewForm = res.data || {}
|
this.viewForm = res.data || {}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// 提交审批(单个操作列)
|
||||||
|
handleSubmitOne(row) {
|
||||||
|
this.$modal.confirm('确认提交该请购单进行审批?').then(() => {
|
||||||
|
return submitApproval(row.reqId)
|
||||||
|
}).then(() => {
|
||||||
|
this.$modal.msgSuccess('已提交审批')
|
||||||
|
this.getList()
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
// 打开审批弹窗
|
||||||
|
openApproval(row) {
|
||||||
|
this.approvalReq = { ...row }
|
||||||
|
this.approvalRemark = ''
|
||||||
|
this.approvalOpen = true
|
||||||
|
},
|
||||||
|
// 审批通过
|
||||||
|
doApprove() {
|
||||||
|
this.approvalLoading = true
|
||||||
|
approvePurchase(this.approvalReq.reqId).then(() => {
|
||||||
|
this.$modal.msgSuccess('审批通过')
|
||||||
|
this.approvalOpen = false
|
||||||
|
this.getList()
|
||||||
|
}).finally(() => { this.approvalLoading = false })
|
||||||
|
},
|
||||||
|
// 驳回
|
||||||
|
doReject() {
|
||||||
|
this.approvalLoading = true
|
||||||
|
rejectPurchase(this.approvalReq.reqId).then(() => {
|
||||||
|
this.$modal.msgSuccess('已驳回')
|
||||||
|
this.approvalOpen = false
|
||||||
|
this.getList()
|
||||||
|
}).finally(() => { this.approvalLoading = false })
|
||||||
|
},
|
||||||
cancel() {
|
cancel() {
|
||||||
this.open = false
|
this.open = false
|
||||||
},
|
},
|
||||||
|
|||||||
235
klp-ui/src/views/wms/stock/detail.vue
Normal file
235
klp-ui/src/views/wms/stock/detail.vue
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container" v-loading="loading">
|
||||||
|
<!-- 标题 -->
|
||||||
|
<h2 style="text-align: center; margin-bottom: 16px;">{{ title }}</h2>
|
||||||
|
|
||||||
|
<!-- 空数据 -->
|
||||||
|
<el-empty v-if="!loading && tableData.length === 0" description="暂无数据" />
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<el-table
|
||||||
|
v-if="tableData.length > 0"
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
style="width: 100%"
|
||||||
|
:header-cell-style="{ background: '#f2f2f2', fontWeight: 600, textAlign: 'center' }"
|
||||||
|
:cell-style="cellStyle"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-table-column label="业务员" prop="dimension" min-width="100" align="center" />
|
||||||
|
|
||||||
|
<el-table-column v-for="cat in CATEGORIES" :key="cat.key" :label="cat.label" align="center">
|
||||||
|
<el-table-column :label="'A/B'" :prop="cat.key + '_AB'" width="85" align="center">
|
||||||
|
<template slot-scope="{ row }">{{ formatNum(row[cat.key + '_AB']) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="'C/D/O'" :prop="cat.key + '_CDO'" width="85" align="center">
|
||||||
|
<template slot-scope="{ row }">{{ formatNum(row[cat.key + '_CDO']) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column label="合计" prop="total" width="100" align="center">
|
||||||
|
<template slot-scope="{ row }">{{ formatNum(row.total) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listCoilWithIds } from "@/api/wms/coil";
|
||||||
|
|
||||||
|
const CATEGORIES = [
|
||||||
|
{ key: '冷硬钢卷', label: '冷硬钢卷' },
|
||||||
|
{ key: '冷轧钢卷', label: '冷轧钢卷' },
|
||||||
|
{ key: '镀锌钢卷', label: '镀锌钢卷' },
|
||||||
|
{ key: '镀锌管材', label: '镀锌管材' },
|
||||||
|
{ key: '花纹板', label: '花纹板' },
|
||||||
|
{ key: '镀铬', label: '镀铬' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 品质等级 → 分组映射
|
||||||
|
* A/B → 'AB', C/D/O → 'CDO', 其他 → null
|
||||||
|
*/
|
||||||
|
function getQualityGroup(status) {
|
||||||
|
if (!status) return null
|
||||||
|
const s = String(status).toUpperCase().trim()
|
||||||
|
if (['A', 'B'].includes(s)) return 'AB'
|
||||||
|
if (['C', 'D', 'O'].includes(s)) return 'CDO'
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "StockDetail",
|
||||||
|
dicts: ['wip_pack_saleman'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
rawList: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
CATEGORIES: () => CATEGORIES,
|
||||||
|
|
||||||
|
title() {
|
||||||
|
const now = new Date()
|
||||||
|
return `${now.getMonth()+1}.${now.getDate()}.${String(now.getFullYear()).slice(-2)} 库存明细`
|
||||||
|
},
|
||||||
|
|
||||||
|
tableData() {
|
||||||
|
if (!this.rawList.length) return []
|
||||||
|
|
||||||
|
// ========== 第一层:分类聚合 ==========
|
||||||
|
// orderData: { [saleName]: { [catKey]: { AB: 0, CDO: 0 } } }
|
||||||
|
// spotData: { [catKey]: { AB: 0, CDO: 0 } }
|
||||||
|
const orderData = {}
|
||||||
|
const spotData = {}
|
||||||
|
let unmatchedCount = 0
|
||||||
|
|
||||||
|
this.rawList.forEach(item => {
|
||||||
|
// 匹配钢材品类
|
||||||
|
const cat = CATEGORIES.find(c => item.itemName && item.itemName.includes(c.key))
|
||||||
|
if (!cat) { unmatchedCount++; return }
|
||||||
|
|
||||||
|
// 品质分组
|
||||||
|
const group = getQualityGroup(item.qualityStatus)
|
||||||
|
if (!group) { unmatchedCount++; return }
|
||||||
|
|
||||||
|
const weight = Number(item.netWeight) || 0
|
||||||
|
|
||||||
|
if (Number(item.isRelatedToOrder) === 1 && item.saleName) {
|
||||||
|
// 订单相关 → 归属业务员
|
||||||
|
if (!orderData[item.saleName]) orderData[item.saleName] = {}
|
||||||
|
if (!orderData[item.saleName][cat.key]) orderData[item.saleName][cat.key] = { AB: 0, CDO: 0 }
|
||||||
|
orderData[item.saleName][cat.key][group] += weight
|
||||||
|
} else {
|
||||||
|
// 非订单相关 → 现货
|
||||||
|
if (!spotData[cat.key]) spotData[cat.key] = { AB: 0, CDO: 0 }
|
||||||
|
spotData[cat.key][group] += weight
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (unmatchedCount > 0) {
|
||||||
|
console.log(`[库存明细] 未匹配品类的钢卷数: ${unmatchedCount}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 第二层:组装行数据 ==========
|
||||||
|
// 工具函数:创建空行
|
||||||
|
const createRow = (dimension, rowType, remark = '') => {
|
||||||
|
const row = { dimension, rowType, remark, total: 0 }
|
||||||
|
CATEGORIES.forEach(c => { row[c.key + '_AB'] = 0; row[c.key + '_CDO'] = 0 })
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.1 业务员行(按字典 wip_pack_saleman 顺序)
|
||||||
|
const dictItems = this.dict.type.wip_pack_saleman || []
|
||||||
|
const personRows = dictItems.map(dictItem => {
|
||||||
|
const row = createRow(dictItem.label, 'person')
|
||||||
|
const personData = orderData[dictItem.value] || {}
|
||||||
|
CATEGORIES.forEach(cat => {
|
||||||
|
const vals = personData[cat.key] || { AB: 0, CDO: 0 }
|
||||||
|
row[cat.key + '_AB'] = vals.AB
|
||||||
|
row[cat.key + '_CDO'] = vals.CDO
|
||||||
|
row.total += vals.AB + vals.CDO
|
||||||
|
})
|
||||||
|
return row
|
||||||
|
})
|
||||||
|
|
||||||
|
// 2.2 订单小计
|
||||||
|
const makeSubtotal = () => {
|
||||||
|
const row = createRow('订单小计', 'summary')
|
||||||
|
CATEGORIES.forEach(cat => {
|
||||||
|
let ab = 0, cdo = 0
|
||||||
|
personRows.forEach(r => {
|
||||||
|
ab += r[cat.key + '_AB'] || 0
|
||||||
|
cdo += r[cat.key + '_CDO'] || 0
|
||||||
|
})
|
||||||
|
row[cat.key + '_AB'] = ab
|
||||||
|
row[cat.key + '_CDO'] = cdo
|
||||||
|
row.total += ab + cdo
|
||||||
|
})
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.3 现货
|
||||||
|
const makeSpot = () => {
|
||||||
|
const row = createRow('现货', 'summary')
|
||||||
|
CATEGORIES.forEach(cat => {
|
||||||
|
const vals = spotData[cat.key] || { AB: 0, CDO: 0 }
|
||||||
|
row[cat.key + '_AB'] = vals.AB
|
||||||
|
row[cat.key + '_CDO'] = vals.CDO
|
||||||
|
row.total += vals.AB + vals.CDO
|
||||||
|
})
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.4 合计 = 订单小计 + 现货
|
||||||
|
const makeTotal = () => {
|
||||||
|
const row = createRow('合计', 'summary')
|
||||||
|
CATEGORIES.forEach(cat => {
|
||||||
|
const ab = (orderSubtotal[cat.key + '_AB'] || 0) + (spotRow[cat.key + '_AB'] || 0)
|
||||||
|
const cdo = (orderSubtotal[cat.key + '_CDO'] || 0) + (spotRow[cat.key + '_CDO'] || 0)
|
||||||
|
row[cat.key + '_AB'] = ab
|
||||||
|
row[cat.key + '_CDO'] = cdo
|
||||||
|
row.total += ab + cdo
|
||||||
|
})
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.5 各产品小计
|
||||||
|
const makeProductSummary = () => {
|
||||||
|
const row = createRow('各产品小计', 'summary')
|
||||||
|
CATEGORIES.forEach(cat => {
|
||||||
|
const merged = (totalRow[cat.key + '_AB'] || 0) + (totalRow[cat.key + '_CDO'] || 0)
|
||||||
|
row[cat.key + '_AB'] = merged
|
||||||
|
row[cat.key + '_CDO'] = 0
|
||||||
|
row.total += merged
|
||||||
|
})
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderSubtotal = makeSubtotal()
|
||||||
|
const spotRow = makeSpot()
|
||||||
|
const totalRow = makeTotal()
|
||||||
|
|
||||||
|
return [
|
||||||
|
...personRows,
|
||||||
|
orderSubtotal,
|
||||||
|
spotRow,
|
||||||
|
totalRow,
|
||||||
|
makeProductSummary(),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatNum(val) {
|
||||||
|
if (val === null || val === undefined || isNaN(val)) return '0.00'
|
||||||
|
return Number(val).toFixed(2)
|
||||||
|
},
|
||||||
|
cellStyle({ row }) {
|
||||||
|
return row.rowType === 'summary' ? { backgroundColor: '#FFFACD' } : {}
|
||||||
|
},
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
this.rawList = []
|
||||||
|
|
||||||
|
listCoilWithIds({
|
||||||
|
status: 0,
|
||||||
|
dataType: 1,
|
||||||
|
pageSize: 99999,
|
||||||
|
pageNum: 1,
|
||||||
|
}).then(res => {
|
||||||
|
this.rawList = res.rows || []
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user