Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X
This commit is contained in:
@@ -142,6 +142,13 @@ public class ErpPurchasePlanController extends BaseController {
|
|||||||
return R.ok(iErpPurchasePlanService.queryDeliveryList(planId));
|
return R.ok(iErpPurchasePlanService.queryDeliveryList(planId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 刷新到货:拿已上传卷号去 WMS 钢卷表实时复核,签收入库的自动翻为已到货(无需重传) */
|
||||||
|
@PutMapping("/{planId}/refreshArrival")
|
||||||
|
public R<Void> refreshArrival(@PathVariable Long planId) {
|
||||||
|
iErpPurchasePlanService.refreshProgress(planId);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
/** 某计划的到货上传批次(每次上传一条,可回看) */
|
/** 某计划的到货上传批次(每次上传一条,可回看) */
|
||||||
@GetMapping("/{planId}/deliveryBatches")
|
@GetMapping("/{planId}/deliveryBatches")
|
||||||
public R<List<ErpPurchasePlanDeliveryBatchVo>> deliveryBatches(@PathVariable Long planId) {
|
public R<List<ErpPurchasePlanDeliveryBatchVo>> deliveryBatches(@PathVariable Long planId) {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import java.util.Collection;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -340,7 +341,31 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
|
|||||||
if (valid.isEmpty()) {
|
if (valid.isEmpty()) {
|
||||||
throw new ServiceException("未解析到有效到货数据,请检查文件内容或列名是否与模板一致");
|
throw new ServiceException("未解析到有效到货数据,请检查文件内容或列名是否与模板一致");
|
||||||
}
|
}
|
||||||
// 2) kg→t 单位判定(文件级:单卷重量最大值超阈值视为 kg)
|
// 2) 牌号校验:到货表里的牌号必须都在本计划「采购要求」的牌号范围内
|
||||||
|
List<ErpPurchasePlanItem> planItems = itemMapper.selectList(Wrappers.lambdaQuery(ErpPurchasePlanItem.class)
|
||||||
|
.eq(ErpPurchasePlanItem::getPlanId, planId));
|
||||||
|
Set<String> reqGrades = planItems.stream()
|
||||||
|
.map(it -> normCoil(it.getGrade()))
|
||||||
|
.filter(StringUtils::isNotBlank)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
if (!reqGrades.isEmpty()) {
|
||||||
|
Set<String> badGrades = new LinkedHashSet<>();
|
||||||
|
for (ErpPurchasePlanDeliveryImportVo r : valid) {
|
||||||
|
String g = normCoil(r.getGrade());
|
||||||
|
if (StringUtils.isBlank(g)) {
|
||||||
|
badGrades.add("(空牌号)");
|
||||||
|
} else if (!reqGrades.contains(g)) {
|
||||||
|
badGrades.add(r.getGrade().trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!badGrades.isEmpty()) {
|
||||||
|
String allow = planItems.stream().map(ErpPurchasePlanItem::getGrade)
|
||||||
|
.filter(StringUtils::isNotBlank).map(String::trim).distinct().collect(Collectors.joining("、"));
|
||||||
|
throw new ServiceException("到货表中的牌号 [" + String.join("、", badGrades)
|
||||||
|
+ "] 不在本计划采购要求的牌号范围内(仅允许:" + allow + "),请核对后重新上传");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 3) kg→t 单位判定(文件级:单卷重量最大值超阈值视为 kg)
|
||||||
BigDecimal maxCoil = valid.stream()
|
BigDecimal maxCoil = valid.stream()
|
||||||
.map(ErpPurchasePlanDeliveryImportVo::getCoilWeight)
|
.map(ErpPurchasePlanDeliveryImportVo::getCoilWeight)
|
||||||
.filter(w -> w != null)
|
.filter(w -> w != null)
|
||||||
@@ -348,7 +373,7 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
|
|||||||
.orElse(BigDecimal.ZERO);
|
.orElse(BigDecimal.ZERO);
|
||||||
boolean kgConverted = maxCoil.compareTo(KG_THRESHOLD) > 0;
|
boolean kgConverted = maxCoil.compareTo(KG_THRESHOLD) > 0;
|
||||||
|
|
||||||
// 3) 卷号去 WMS 钢卷表校验:存在且 data_type<>10 即视为已实际到货入库
|
// 4) 卷号去 WMS 钢卷表校验:存在且 data_type<>10 即视为已实际到货入库
|
||||||
List<String> uploadCoilNos = valid.stream()
|
List<String> uploadCoilNos = valid.stream()
|
||||||
.map(ErpPurchasePlanDeliveryImportVo::getCoilNo)
|
.map(ErpPurchasePlanDeliveryImportVo::getCoilNo)
|
||||||
.filter(StringUtils::isNotBlank)
|
.filter(StringUtils::isNotBlank)
|
||||||
@@ -358,13 +383,13 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
|
|||||||
: baseMapper.selectExistingSupplierCoilNos(uploadCoilNos).stream()
|
: baseMapper.selectExistingSupplierCoilNos(uploadCoilNos).stream()
|
||||||
.map(this::normCoil).collect(Collectors.toSet());
|
.map(this::normCoil).collect(Collectors.toSet());
|
||||||
|
|
||||||
// 4) 先建批次(每次上传存档,可随时回看)
|
// 5) 先建批次(每次上传存档,可随时回看)
|
||||||
ErpPurchasePlanDeliveryBatch batch = new ErpPurchasePlanDeliveryBatch();
|
ErpPurchasePlanDeliveryBatch batch = new ErpPurchasePlanDeliveryBatch();
|
||||||
batch.setPlanId(planId);
|
batch.setPlanId(planId);
|
||||||
batch.setFileName(StringUtils.isNotBlank(fileName) ? fileName : "到货表");
|
batch.setFileName(StringUtils.isNotBlank(fileName) ? fileName : "到货表");
|
||||||
deliveryBatchMapper.insert(batch);
|
deliveryBatchMapper.insert(batch);
|
||||||
|
|
||||||
// 5) 合并单元格向下填充 + 单位换算 + 落库 + WMS到货标记
|
// 6) 合并单元格向下填充 + 单位换算 + 落库 + WMS到货标记
|
||||||
String lastTruckNo = null;
|
String lastTruckNo = null;
|
||||||
BigDecimal lastTruckWeight = null;
|
BigDecimal lastTruckWeight = null;
|
||||||
Integer lastPieceCount = null;
|
Integer lastPieceCount = null;
|
||||||
@@ -401,10 +426,10 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
|
|||||||
matched++;
|
matched++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 6) 汇总刷新进度
|
// 7) 汇总刷新进度
|
||||||
refreshProgress(planId);
|
refreshProgress(planId);
|
||||||
|
|
||||||
// 7) 回填批次统计(行数、WMS确认到货卷数、上传后进度快照)
|
// 8) 回填批次统计(行数、WMS确认到货卷数、上传后进度快照)
|
||||||
ErpPurchasePlan after = baseMapper.selectById(planId);
|
ErpPurchasePlan after = baseMapper.selectById(planId);
|
||||||
batch.setRowCount(count);
|
batch.setRowCount(count);
|
||||||
batch.setMatchedCount(matched);
|
batch.setMatchedCount(matched);
|
||||||
@@ -492,13 +517,29 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
|
|||||||
if (plan == null) {
|
if (plan == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 到货 = 累计所有上传批次中 WMS 已确认到货(arrived=1)的卷
|
// 到货 = 累计所有上传批次中 WMS 已确认到货的卷。
|
||||||
|
// 每次刷新都拿卷号去 WMS 钢卷表实时复核:之前未到、后来签收入库的,这里会自动翻成已到货,无需重新上传。
|
||||||
List<ErpPurchasePlanDelivery> deliveries = deliveryMapper.selectList(Wrappers.lambdaQuery(ErpPurchasePlanDelivery.class)
|
List<ErpPurchasePlanDelivery> deliveries = deliveryMapper.selectList(Wrappers.lambdaQuery(ErpPurchasePlanDelivery.class)
|
||||||
.eq(ErpPurchasePlanDelivery::getPlanId, planId));
|
.eq(ErpPurchasePlanDelivery::getPlanId, planId));
|
||||||
|
List<String> coilNos = deliveries.stream()
|
||||||
|
.map(ErpPurchasePlanDelivery::getCoilNo)
|
||||||
|
.filter(StringUtils::isNotBlank)
|
||||||
|
.map(String::trim)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
Set<String> wmsArrivedSet = coilNos.isEmpty() ? new HashSet<>()
|
||||||
|
: baseMapper.selectExistingSupplierCoilNos(coilNos).stream()
|
||||||
|
.map(this::normCoil).collect(Collectors.toSet());
|
||||||
|
|
||||||
int arrivedCount = 0;
|
int arrivedCount = 0;
|
||||||
BigDecimal arrivedWeight = BigDecimal.ZERO;
|
BigDecimal arrivedWeight = BigDecimal.ZERO;
|
||||||
for (ErpPurchasePlanDelivery d : deliveries) {
|
for (ErpPurchasePlanDelivery d : deliveries) {
|
||||||
if (d.getArrived() != null && d.getArrived() == 1) {
|
int nowArrived = StringUtils.isNotBlank(d.getCoilNo()) && wmsArrivedSet.contains(normCoil(d.getCoilNo())) ? 1 : 0;
|
||||||
|
// 状态有变化才回写,减少无谓更新
|
||||||
|
if (d.getArrived() == null || d.getArrived() != nowArrived) {
|
||||||
|
d.setArrived(nowArrived);
|
||||||
|
deliveryMapper.updateById(d);
|
||||||
|
}
|
||||||
|
if (nowArrived == 1) {
|
||||||
arrivedCount++;
|
arrivedCount++;
|
||||||
arrivedWeight = arrivedWeight.add(d.getCoilWeight() == null ? BigDecimal.ZERO : d.getCoilWeight());
|
arrivedWeight = arrivedWeight.add(d.getCoilWeight() == null ? BigDecimal.ZERO : d.getCoilWeight());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,6 +124,14 @@ export function listDeliveryPlans(query) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 刷新到货(拿已上传卷号去 WMS 实时复核,签收的自动翻为已到货)
|
||||||
|
export function refreshArrival(planId) {
|
||||||
|
return request({
|
||||||
|
url: `/erp/purchasePlan/${planId}/refreshArrival`,
|
||||||
|
method: 'put'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 某计划的到货上传批次(每次上传一条)
|
// 某计划的到货上传批次(每次上传一条)
|
||||||
export function listDeliveryBatches(planId) {
|
export function listDeliveryBatches(planId) {
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@@ -59,16 +59,19 @@
|
|||||||
<span class="pd-d-title">{{ current.planNo }}</span>
|
<span class="pd-d-title">{{ current.planNo }}</span>
|
||||||
<span class="pd-badge" :class="current.planStatus === '1' ? 'p1' : 'p0'">{{ current.planStatus === '1' ? '已到齐' : '到货中' }}</span>
|
<span class="pd-badge" :class="current.planStatus === '1' ? 'p1' : 'p0'">{{ current.planStatus === '1' ? '已到齐' : '到货中' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<el-upload
|
<div class="pd-head-act">
|
||||||
:headers="upload.headers"
|
<el-button size="small" icon="el-icon-refresh" :loading="refreshing" @click="doRefreshArrival">刷新到货</el-button>
|
||||||
:action="uploadUrl"
|
<el-upload
|
||||||
:show-file-list="false"
|
:headers="upload.headers"
|
||||||
accept=".xlsx,.xls"
|
:action="uploadUrl"
|
||||||
:on-success="handleUploadSuccess"
|
:show-file-list="false"
|
||||||
:on-error="handleUploadError"
|
accept=".xlsx,.xls"
|
||||||
>
|
:on-success="handleUploadSuccess"
|
||||||
<el-button type="primary" size="small" icon="el-icon-upload2">上传到货表格</el-button>
|
:on-error="handleUploadError"
|
||||||
</el-upload>
|
>
|
||||||
|
<el-button type="primary" size="small" icon="el-icon-upload2">上传到货表格</el-button>
|
||||||
|
</el-upload>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pd-meta">
|
<div class="pd-meta">
|
||||||
@@ -169,7 +172,8 @@ import {
|
|||||||
getPurchasePlan,
|
getPurchasePlan,
|
||||||
listDeliveryPlans,
|
listDeliveryPlans,
|
||||||
listDeliveryBatches,
|
listDeliveryBatches,
|
||||||
listDeliveryByBatch
|
listDeliveryByBatch,
|
||||||
|
refreshArrival
|
||||||
} from '@/api/erp/purchasePlan'
|
} from '@/api/erp/purchasePlan'
|
||||||
import { getToken } from '@/utils/auth'
|
import { getToken } from '@/utils/auth'
|
||||||
|
|
||||||
@@ -188,6 +192,7 @@ export default {
|
|||||||
currentBatch: {},
|
currentBatch: {},
|
||||||
batchRows: [],
|
batchRows: [],
|
||||||
batchRowsLoading: false,
|
batchRowsLoading: false,
|
||||||
|
refreshing: false,
|
||||||
upload: { headers: { Authorization: 'Bearer ' + getToken() } },
|
upload: { headers: { Authorization: 'Bearer ' + getToken() } },
|
||||||
progressColor: '#5b8db8'
|
progressColor: '#5b8db8'
|
||||||
}
|
}
|
||||||
@@ -222,7 +227,11 @@ export default {
|
|||||||
this.current = { ...p }
|
this.current = { ...p }
|
||||||
this.currentBatch = {}
|
this.currentBatch = {}
|
||||||
this.batchRows = []
|
this.batchRows = []
|
||||||
this.refreshDetail()
|
// 打开即静默复核一次 WMS 到货状态,保证看到的是最新
|
||||||
|
const planId = p.planId
|
||||||
|
refreshArrival(planId).catch(() => {}).finally(() => {
|
||||||
|
if (this.current.planId === planId) this.refreshDetail()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
refreshDetail() {
|
refreshDetail() {
|
||||||
const planId = this.current.planId
|
const planId = this.current.planId
|
||||||
@@ -230,6 +239,16 @@ export default {
|
|||||||
getPurchasePlan(planId).then(res => { this.current = { ...this.current, ...(res.data || {}) } })
|
getPurchasePlan(planId).then(res => { this.current = { ...this.current, ...(res.data || {}) } })
|
||||||
this.loadBatches()
|
this.loadBatches()
|
||||||
},
|
},
|
||||||
|
doRefreshArrival() {
|
||||||
|
if (!this.current.planId) return
|
||||||
|
this.refreshing = true
|
||||||
|
refreshArrival(this.current.planId).then(() => {
|
||||||
|
this.$modal.msgSuccess('已按钢卷表刷新到货状态')
|
||||||
|
this.refreshDetail()
|
||||||
|
if (this.currentBatch.batchId) this.viewBatch(this.currentBatch)
|
||||||
|
this.getList(true)
|
||||||
|
}).finally(() => { this.refreshing = false })
|
||||||
|
},
|
||||||
loadBatches() {
|
loadBatches() {
|
||||||
this.batchLoading = true
|
this.batchLoading = true
|
||||||
listDeliveryBatches(this.current.planId).then(res => {
|
listDeliveryBatches(this.current.planId).then(res => {
|
||||||
@@ -302,6 +321,7 @@ $sub: #909399;
|
|||||||
p { font-size: 13px; }
|
p { font-size: 13px; }
|
||||||
}
|
}
|
||||||
.pd-d-head { display: flex; justify-content: space-between; align-items: center; padding: 14px 18px; border-bottom: 1px solid $line; }
|
.pd-d-head { display: flex; justify-content: space-between; align-items: center; padding: 14px 18px; border-bottom: 1px solid $line; }
|
||||||
|
.pd-head-act { display: flex; gap: 10px; align-items: center; ::v-deep .el-button { margin: 0; } }
|
||||||
.pd-d-title { font-size: 15px; font-weight: 600; color: $ink; margin-right: 8px; }
|
.pd-d-title { font-size: 15px; font-weight: 600; color: $ink; margin-right: 8px; }
|
||||||
.pd-badge {
|
.pd-badge {
|
||||||
font-size: 11px; line-height: 16px; padding: 0 6px; border-radius: 2px; border: 1px solid #dcdfe6; color: $sub; background: #fafafa;
|
font-size: 11px; line-height: 16px; padding: 0 6px; border-radius: 2px; border: 1px solid #dcdfe6; color: $sub; background: #fafafa;
|
||||||
|
|||||||
Reference in New Issue
Block a user