opt:采购单回传逻辑统一走回传单

This commit is contained in:
zhaoyf
2026-06-15 13:39:25 +08:00
parent 3307fff9ca
commit 591dad0806
11 changed files with 76 additions and 173 deletions

View File

@@ -1,10 +0,0 @@
package org.nl.wms.ext_manage.purchase.service;
import org.nl.wms.pm_manage.purchase.service.dao.Purchasemst;
public interface InboundEasAuditService {
void auditCompletedBills();
void auditSingleBill(Purchasemst mst);
}

View File

@@ -1,125 +0,0 @@
package org.nl.wms.ext_manage.purchase.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.nl.wms.pm_manage.purchase.service.enums.PurchaseBillStatus;
import org.nl.wms.ext_manage.purchase.service.InboundEasAuditService;
import org.nl.wms.pm_manage.purchase.service.dao.Purchasedtl;
import org.nl.wms.pm_manage.purchase.service.dao.Purchasemst;
import org.nl.wms.pm_manage.purchase.service.dao.mapper.PurchasedtlMapper;
import org.nl.wms.pm_manage.purchase.service.dao.mapper.PurchasemstMapper;
import org.nl.wms.ext_manage.purchase.service.dto.EasAuditRequestDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class InboundEasAuditServiceImpl implements InboundEasAuditService {
@Value("${eas.webservice.wsdl:http://192.168.100.100:8080/ormrpc/services/WSNLWQFacade?wsdl}")
private String easWsdlUrl;
@Autowired
private PurchasemstMapper purchasemstMapper;
@Autowired
private PurchasedtlMapper purchasedtlMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public void auditCompletedBills() {
log.info("开始扫描已完成未审核的采购入库单...");
List<Purchasemst> billList = purchasemstMapper.selectList(
new QueryWrapper<Purchasemst>()
.eq("bill_status", PurchaseBillStatus.COMPLETED.getCode())
);
if (ObjectUtil.isEmpty(billList)) {
log.info("没有需要审核的采购入库单");
return;
}
log.info("找到{}个需要审核的采购入库单", billList.size());
for (Purchasemst mst : billList) {
try {
auditSingleBill(mst);
} catch (Exception e) {
log.error("审核采购入库单失败, billId: {}", mst.getBill_id(), e);
purchasemstMapper.update(null, new LambdaUpdateWrapper<Purchasemst>()
.eq(Purchasemst::getBill_id, mst.getBill_id())
.set(Purchasemst::getAudit_msg, e.getMessage()));
}
}
}
@Override
public void auditSingleBill(Purchasemst mst) {
log.info("开始审核采购入库单, billId: {}, orderNo: {}", mst.getBill_id(), mst.getOrder_no());
List<Purchasedtl> dtlList = purchasedtlMapper.selectList(
new QueryWrapper<Purchasedtl>().eq("bill_id", mst.getBill_id())
);
EasAuditRequestDto requestDto = new EasAuditRequestDto();
requestDto.setType("WMS");
requestDto.setMethod("DealBill");
EasAuditRequestDto.EasAuditDataDto dataDto = new EasAuditRequestDto.EasAuditDataDto();
dataDto.setBillNo(mst.getOrder_no());
List<EasAuditRequestDto.EasAuditEntryDto> entrys = new ArrayList<>();
for (Purchasedtl dtl : dtlList) {
EasAuditRequestDto.EasAuditEntryDto entry = new EasAuditRequestDto.EasAuditEntryDto();
entry.setSeq(Integer.valueOf(dtl.getItem_no()));
entrys.add(entry);
}
dataDto.setEntrys(entrys);
requestDto.setData(dataDto);
String requestJson = JSON.toJSONString(requestDto);
log.info("审核请求参数: {}", requestJson);
try {
String responseMsg = HttpRequest.post(easWsdlUrl)
.body(requestJson)
.execute().body();
log.info("审核响应结果: {}", responseMsg);
JSONObject response = JSONObject.parseObject(responseMsg);
LambdaUpdateWrapper<Purchasemst> updateWrapper = new LambdaUpdateWrapper<Purchasemst>()
.eq(Purchasemst::getBill_id, mst.getBill_id());
Integer status = response.getInteger("status");
if (status != null && status == 200) {
updateWrapper.set(Purchasemst::getBill_status, PurchaseBillStatus.AUDIT_SUCCESS.getCode())
.set(Purchasemst::getAudit_msg, "审核成功");
log.info("采购入库单审核成功, billId: {}", mst.getBill_id());
} else {
updateWrapper.set(Purchasemst::getBill_status, PurchaseBillStatus.AUDIT_FAIL.getCode())
.set(Purchasemst::getAudit_msg, response.getString("message"));
log.warn("采购入库单审核失败, billId: {}, message: {}", mst.getBill_id(), response.getString("message"));
}
purchasemstMapper.update(null, updateWrapper);
} catch (Exception e) {
log.error("调用EAS审核接口异常, billId: {}", mst.getBill_id(), e);
purchasemstMapper.update(null, new LambdaUpdateWrapper<Purchasemst>()
.eq(Purchasemst::getBill_id, mst.getBill_id())
.set(Purchasemst::getBill_status, PurchaseBillStatus.AUDIT_FAIL.getCode())
.set(Purchasemst::getAudit_msg, "调用EAS审核接口异常: "));
}
}
}

View File

@@ -148,7 +148,7 @@ public class InboundPdaServiceImpl implements InboundPdaService {
List<PdaGroupPlateDto.GroupPlateDtlDto> detailList = dto.getDetailList();
detailList.forEach((item)->{
List<PurchaseMatInfoVo> purchaseMatInfoVos = purchaseService.selectPdaInMat(MapOf.of("orderNo", item.getOrder_no(),
"materialCode", item.getSku_code()));
"itemNo", item.getItem_no()));
if (purchaseMatInfoVos.isEmpty()){
throw new BadRequestException("组盘失败:单据:"+item.getOrder_no()+"物料:"+item.getSku_code()+"不存在");
}
@@ -207,7 +207,10 @@ public class InboundPdaServiceImpl implements InboundPdaService {
}
Map<String, Object> parseMap = parseCode(code);
List<PurchaseMatInfoVo> purchaseMatInfoVos = purchaseService.selectPdaInMat(MapOf.of("orderNo", parseMap.get("orderNo"),
"materialCode", parseMap.get("materialCode")));
"itemNo", parseMap.get("itemNo")));
if (purchaseMatInfoVos.isEmpty()){
throw new BadRequestException("获取单据失败:未找到该物料信息");
}
if (purchaseMatInfoVos.size() > 1){
throw new BadRequestException("同一个采购单有重复物料");
}
@@ -455,6 +458,9 @@ public class InboundPdaServiceImpl implements InboundPdaService {
PurchaseListenerParams.DetailItem detailItem = new PurchaseListenerParams.DetailItem();
detailItem.setMaterialCode(plateDao.getMaterial_code());
detailItem.setQty(plateDao.getQty());
List<PurchaseListenerParams.DetailItem> detailItemList = new ArrayList<>();
detailItemList.add(detailItem);
purchaseListenerParams.setDetailItem(detailItemList);
pushEvent(purchaseListenerParams);
}

View File

@@ -57,10 +57,10 @@ public class PurchaseController {
return new ResponseEntity<>(HttpStatus.OK);
}
@PutMapping("/forceAudit")
@Log("强制回传EAS审核")
public ResponseEntity<Object> forceAudit(@RequestBody Set<String> ids) {
purchaseService.forceAudit(ids);
@PutMapping("/issueReturnBill")
@Log("下发回传单")
public ResponseEntity<Object> issueReturnBill(@RequestBody Set<String> ids) {
purchaseService.issueReturnBill(ids);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@@ -26,7 +26,7 @@ public interface PurchaseService extends IService<Purchasemst> {
void deleteAll(Set<String> ids);
void forceAudit(Set<String> ids);
void issueReturnBill(Set<String> ids);
List<PurchaseMatInfoVo> pdaInboundSelectMatInfo(Map whereJson);

View File

@@ -76,7 +76,7 @@
LEFT JOIN st_ivt_purchasedtl d ON m.bill_id = d.bill_id
WHERE 1=1
AND m.order_no = #{param.orderNo}
AND d.sku_code = #{param.materialCode}
AND d.item_no = #{param.itemNo}
AND m.status = 0
ORDER BY m.create_time DESC, d.item_no ASC
</select>

View File

@@ -12,7 +12,8 @@ import org.nl.common.domain.query.PageQuery;
import org.nl.common.exception.BadRequestException;
import org.nl.common.utils.SecurityUtils;
import org.nl.wms.pda_manage.ios_manage.purchase.service.vo.PurchaseMatInfoVo;
import org.nl.wms.ext_manage.purchase.service.InboundEasAuditService;
import com.alibaba.fastjson.JSON;
import org.nl.common.utils.IdUtil;
import org.nl.wms.pm_manage.purchase.service.PurchaseService;
import org.nl.wms.pm_manage.purchase.service.dao.Purchasedtl;
import org.nl.wms.pm_manage.purchase.service.dao.Purchasemst;
@@ -20,6 +21,11 @@ import org.nl.wms.pm_manage.purchase.service.dao.mapper.PurchasedtlMapper;
import org.nl.wms.pm_manage.purchase.service.dao.mapper.PurchasemstMapper;
import org.nl.wms.pm_manage.purchase.service.dto.PurchaseDto;
import org.nl.wms.pm_manage.purchase.service.vo.PurchasemstListVo;
import org.nl.wms.ext_manage.purchase.service.dto.EasAuditRequestDto;
import org.nl.wms.warehouse_manage.enums.IOSEnum;
import org.nl.wms.warehouse_manage.stockReturn.service.IPmStockReturnService;
import org.nl.wms.warehouse_manage.stockReturn.service.dao.PmStockReturn;
import org.nl.wms.warehouse_manage.stockReturn.service.enums.StockReturnStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -37,7 +43,7 @@ public class PurchaseServiceImpl extends ServiceImpl<PurchasemstMapper, Purchase
private PurchasedtlMapper purchasedtlMapper;
@Autowired
private InboundEasAuditService inboundEasAuditService;
private IPmStockReturnService pmStockReturnService;
@Override
public IPage<PurchasemstListVo> queryAll(Map whereJson, PageQuery page) {
@@ -126,18 +132,47 @@ public class PurchaseServiceImpl extends ServiceImpl<PurchasemstMapper, Purchase
}
@Override
public void forceAudit(Set<String> ids) {
@Transactional(rollbackFor = Exception.class)
public void issueReturnBill(Set<String> ids) {
List<Purchasemst> mstList = purchasemstMapper.selectBatchIds(ids);
if (ObjectUtil.isEmpty(mstList)) {
throw new BadRequestException("未找到选中的单据");
}
for (Purchasemst mst : mstList) {
log.info("强制回传EAS审核, billId: {}, 当前状态: {}", mst.getBill_id(), mst.getBill_status());
try {
inboundEasAuditService.auditSingleBill(mst);
} catch (Exception e) {
log.error("强制回传EAS审核失败, billId: {}", mst.getBill_id(), e);
List<Purchasedtl> dtlList = purchasedtlMapper.selectList(
new LambdaQueryWrapper<Purchasedtl>()
.eq(Purchasedtl::getBill_id, mst.getBill_id()));
// boolean allMatch = dtlList.stream()
// .allMatch(d -> d.getQty() != null && d.getInstock_qty() != null
// && d.getQty().compareTo(d.getInstock_qty()) == 0);
// if (!allMatch) {
// continue;
// }
List<EasAuditRequestDto.EasAuditEntryDto> entryList = new ArrayList<>();
for (Purchasedtl dtl : dtlList) {
EasAuditRequestDto.EasAuditEntryDto entry = new EasAuditRequestDto.EasAuditEntryDto();
entry.setSeq(Integer.parseInt(dtl.getItem_no()));
entry.setQty(dtl.getInstock_qty());
entry.setEntryId(dtl.getEntry_id());
entryList.add(entry);
}
EasAuditRequestDto dto = new EasAuditRequestDto();
dto.setType("WMS");
dto.setMethod("DealBill");
EasAuditRequestDto.EasAuditDataDto data = new EasAuditRequestDto.EasAuditDataDto();
data.setBillType(mst.getOrder_type());
data.setBillNo(mst.getOrder_no());
data.setEntrys(entryList);
dto.setData(data);
PmStockReturn stockReturn = new PmStockReturn();
stockReturn.setRequest_Id(IdUtil.getStringId());
stockReturn.setCreate_time(cn.hutool.core.date.DateUtil.now());
stockReturn.setRequest_type(IOSEnum.BILL_TYPE.code("采购入库"));
stockReturn.setStatus(StockReturnStatusEnum.TODO.getCode());
stockReturn.setRequest_data(JSON.toJSONString(dto));
pmStockReturnService.save(stockReturn);
log.info("下发回传单成功, billId: {}, requestId: {}, 明细数: {}", mst.getBill_id(), stockReturn.getRequest_Id(), dtlList.size());
}
}

View File

@@ -33,8 +33,8 @@ spring:
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:wms_nlwq}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true&allowPublicKeyRetrieval=true
url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:wms_standardv2}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true&allowPublicKeyRetrieval=true
url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:wms_nlwq}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true&allowPublicKeyRetrieval=true
# url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:wms_standardv2}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true&allowPublicKeyRetrieval=true
username: ${DB_USER:root}
password: ${DB_PWD:123456}
druid:
@@ -56,7 +56,8 @@ spring:
validation-query: SELECT 1 # MySQL 用 SELECT 1Oracle 才用 select 1 from dual
# 监控统计(连接池层面的监控)
filters: stat,wall # 修正stat是监控统计wall是SQL防火墙
filters:
DruidFilter,stat # 修正stat是监控统计wall是SQL防火墙
log-abandoned: false
eas:
driver-class-name: com.mysql.cj.jdbc.Driver
@@ -70,7 +71,8 @@ spring:
test-while-idle: true
validation-query: SELECT 1 # 修正MySQL 用 SELECT 1
# 如果 eas 也需要监控,添加下面两行(可选)
filters: stat,wall
filters:
DruidFilter,stat
log-abandoned: false
redis:
#数据库索引
@@ -156,9 +158,3 @@ sa-token:
lucene:
index:
path: D:\lms\lucene\index
eas:
webservice:
wsdl: http://192.168.100.100:8080/ormrpc/services/WSNLWQFacade?wsdl
namespace: http://ws.eas.kingdee.com/
inbound:
liku-codes: LK01

View File

@@ -27,7 +27,7 @@
</el-form>
</div>
<crudOperation :permission="permission">
<el-button slot="right" class="filter-item" type="warning" icon="el-icon-s-promotion" size="mini" :disabled="audit_flag" @click="forceAudit">强制回传</el-button>
<el-button slot="right" class="filter-item" type="warning" icon="el-icon-s-promotion" size="mini" :disabled="audit_flag" @click="issueReturnBill">下发回传</el-button>
</crudOperation>
<el-table ref="table" v-loading="crud.loading" size="mini" :data="crud.data" highlight-current-row style="width: 100%;" @selection-change="crud.selectionChangeHandler" @current-change="handleCurrentChange" @select="handleSelectionChange">
<el-table-column type="selection" width="55" />
@@ -60,8 +60,8 @@
{{ formatDate(scope.row.modify_date) }}
</template>
</el-table-column>
<el-table-column prop="status" :formatter="auditStatusFormat" width="100" label="审核状态" />
<el-table-column show-overflow-tooltip prop="audit_msg" width="150" label="审核信息" />
<!-- <el-table-column prop="status" :formatter="auditStatusFormat" width="100" label="审核状态" />-->
<!-- <el-table-column show-overflow-tooltip prop="audit_msg" width="150" label="审核信息" />-->
</el-table>
<pagination />
</div>
@@ -164,7 +164,7 @@ export default {
querytable() {
this.crud.toQuery()
},
forceAudit() {
issueReturnBill() {
const selections = this.crud.selections
if (!selections || selections.length === 0) {
this.crud.notify('请至少选择一条单据', CRUD.NOTIFICATION_TYPE.INFO)
@@ -172,16 +172,16 @@ export default {
}
const ids = selections.map(s => s.id)
const billIds = selections.map(s => s.bill_id).join('、')
this.$confirm('确认以下单据强制回传EAS审核\n' + billIds, '提示', {
this.$confirm('确认下发以下单据的回传单\n' + billIds, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
crudPurchase.forceAudit(ids).then(() => {
this.crud.notify('回传完成', CRUD.NOTIFICATION_TYPE.SUCCESS)
crudPurchase.issueReturnBill(ids).then(() => {
this.crud.notify('下发成功', CRUD.NOTIFICATION_TYPE.SUCCESS)
this.crud.toQuery()
}).catch(() => {
this.crud.notify('回传失败', CRUD.NOTIFICATION_TYPE.ERROR)
this.crud.notify('下发失败', CRUD.NOTIFICATION_TYPE.ERROR)
})
}).catch(() => {})
}

View File

@@ -31,12 +31,12 @@ export function get(id) {
})
}
export function forceAudit(data) {
export function issueReturnBill(data) {
return request({
url: '/api/purchasemst/forceAudit',
url: '/api/purchasemst/issueReturnBill',
method: 'put',
data
})
}
export default { add, edit, del, get, forceAudit }
export default { add, edit, del, get, issueReturnBill }

View File

@@ -184,6 +184,7 @@ async function onSubmit() {
order_no: item.order_no,
sku_code: item.sku_code,
batch_no: item.batch_no,
item_no: item.item_no,
qty: item.qty,
}))
submitting.value = true