feat(prd): transfer finished goods and repost posted 261 rows
Add 102+101 shop-order transfer for 101 completions, allow posting-date driven reverse/repost, and reset posted consume qty through 262 then 261.
This commit is contained in:
parent
778142b570
commit
25b3c216b0
@ -22,4 +22,5 @@ public class CompleteCorrectionRequestDTO {
|
||||
private String storageLocation;
|
||||
private LocalDate postingDate;
|
||||
private String reason;
|
||||
private Boolean forceSap;
|
||||
}
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
package com.foreverwin.iep.prd.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Data
|
||||
public class CompleteTransferRequestDTO {
|
||||
private String transactionSid;
|
||||
private String targetShopOrder;
|
||||
private LocalDate postingDate;
|
||||
}
|
||||
@ -11,6 +11,7 @@ import com.foreverwin.iep.prd.dto.ZLotMaterialTransactionResponseDTO;
|
||||
import com.foreverwin.iep.prd.dto.ZLotMaterialTransactionResponseExportDTO;
|
||||
import com.foreverwin.iep.prd.dto.ZLotMaterialTransactionResponseExportDetailDTO;
|
||||
import com.foreverwin.iep.prd.dto.CompleteCorrectionRequestDTO;
|
||||
import com.foreverwin.iep.prd.dto.CompleteTransferRequestDTO;
|
||||
import com.foreverwin.iep.prd.entity.ZLotMaterialCompleteTransaction;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialCompleteCorrectionService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialCompleteTransactionService;
|
||||
@ -109,6 +110,15 @@ public class ZLotMaterialCompleteTransactionController {
|
||||
return R.ok(zLotMaterialCompleteCorrectionService.repost101(sid));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "成品调整至其他工单", notes = "S走102+101,N/E只转MES流水")
|
||||
@SysLog("成品调整至其他工单")
|
||||
@PostMapping("/transfer-shop-order")
|
||||
@PreAuthorize("@pms.hasPermission('bg_finished_warehousing_off_btn')")
|
||||
public R transferShopOrder(@RequestBody List<CompleteTransferRequestDTO> requests) {
|
||||
zLotMaterialCompleteCorrectionService.transferShopOrder(requests);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询完工入库事务表
|
||||
*
|
||||
|
||||
@ -99,7 +99,7 @@ public class ZLotMaterialConsumptionTransactionController {
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "待过账或失败的261重新过账", notes = "可改数量,成功后按差额回写WMS库存")
|
||||
@ApiOperation(value = "261重新过账", notes = "N/E直接261;S先262再按目标数量261,目标为0则只262并改为N")
|
||||
@SysLog("物料消耗重新过账261")
|
||||
@PostMapping("/repost-261")
|
||||
public R repost261(@RequestBody List<ConsumptionRepostRequestDTO> requests) {
|
||||
|
||||
@ -2,8 +2,12 @@ package com.foreverwin.iep.prd.service;
|
||||
|
||||
import com.foreverwin.iep.prd.dto.CompleteCorrectionRequestDTO;
|
||||
import com.foreverwin.iep.prd.dto.CompleteCorrectionResultDTO;
|
||||
import com.foreverwin.iep.prd.dto.CompleteTransferRequestDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ZLotMaterialCompleteCorrectionService {
|
||||
CompleteCorrectionResultDTO correct(CompleteCorrectionRequestDTO request);
|
||||
CompleteCorrectionResultDTO repost101(String sid);
|
||||
void transferShopOrder(List<CompleteTransferRequestDTO> requests);
|
||||
}
|
||||
|
||||
@ -6,14 +6,19 @@ import com.foreverwin.iep.integration.feign.RemoteGetSapBatchNoService;
|
||||
import com.foreverwin.iep.integration.feign.RemoteInvokeService;
|
||||
import com.foreverwin.iep.prd.dto.CompleteCorrectionRequestDTO;
|
||||
import com.foreverwin.iep.prd.dto.CompleteCorrectionResultDTO;
|
||||
import com.foreverwin.iep.prd.dto.CompleteTransferRequestDTO;
|
||||
import com.foreverwin.iep.prd.entity.Item;
|
||||
import com.foreverwin.iep.prd.entity.ShopOrder;
|
||||
import com.foreverwin.iep.prd.entity.ZLotMaterialCompleteTransaction;
|
||||
import com.foreverwin.iep.prd.entity.ZLotMaterialCompleteTransactionOff;
|
||||
import com.foreverwin.iep.prd.service.ItemService;
|
||||
import com.foreverwin.iep.prd.service.ShopOrderService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialCompleteCorrectionService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialCompleteTransactionOffService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialCompleteTransactionService;
|
||||
import com.foreverwin.iep.wip.domain.ShopOrderReleaseItemInfo;
|
||||
import com.foreverwin.iep.wip.entity.LotBasis;
|
||||
import com.foreverwin.iep.wip.service.LotBasisService;
|
||||
import com.foreverwin.iep.wip.service.NlvLotStartService;
|
||||
import com.foreverwin.mom.common.core.constant.SecurityConstants;
|
||||
import com.foreverwin.mom.common.core.exception.BusinessException;
|
||||
@ -27,6 +32,7 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -43,6 +49,8 @@ public class ZLotMaterialCompleteCorrectionServiceImpl implements ZLotMaterialCo
|
||||
private final ItemService itemService;
|
||||
private final NlvLotStartService nlvLotStartService;
|
||||
private final RemoteGetSapBatchNoService remoteGetSapBatchNoService;
|
||||
private final ShopOrderService shopOrderService;
|
||||
private final LotBasisService lotBasisService;
|
||||
|
||||
@Override
|
||||
public CompleteCorrectionResultDTO correct(CompleteCorrectionRequestDTO request) {
|
||||
@ -62,9 +70,12 @@ public class ZLotMaterialCompleteCorrectionServiceImpl implements ZLotMaterialCo
|
||||
prepareOutFields(source, request);
|
||||
boolean sapChanged = sapChanged(source, request);
|
||||
boolean localChanged = localChanged(source, request);
|
||||
if (!sapChanged && !localChanged) {
|
||||
if (!sapChanged && !localChanged && !Boolean.TRUE.equals(request.getForceSap())) {
|
||||
throw BusinessException.build("没有可保存的变更");
|
||||
}
|
||||
if (Boolean.TRUE.equals(request.getForceSap())) {
|
||||
sapChanged = true;
|
||||
}
|
||||
ZLotMaterialCompleteTransaction before = new ZLotMaterialCompleteTransaction();
|
||||
BeanUtils.copyProperties(source, before);
|
||||
if (!sapChanged) {
|
||||
@ -110,6 +121,7 @@ public class ZLotMaterialCompleteCorrectionServiceImpl implements ZLotMaterialCo
|
||||
source.setDateUpdate(LocalDateTime.now());
|
||||
if (zeroQty(request)) {
|
||||
source.setErpReverse("Y");
|
||||
source.setSyncStatus("C");
|
||||
completeService.updateById(source);
|
||||
return result(source.getSid(), "SAP", "SUCCESS",
|
||||
reversed102 ? "数量为0,已发102冲销,不再报101" : "数量为0,已同步MES库存,不再报101");
|
||||
@ -140,6 +152,137 @@ public class ZLotMaterialCompleteCorrectionServiceImpl implements ZLotMaterialCo
|
||||
return result(sid, "SAP", "SUCCESS", "已重报101并同步WMS库存");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferShopOrder(List<CompleteTransferRequestDTO> requests) {
|
||||
if (requests == null || requests.isEmpty()) {
|
||||
throw BusinessException.build("请选择要调整到其他工单的成品行");
|
||||
}
|
||||
for (CompleteTransferRequestDTO request : requests) {
|
||||
transferOne(request);
|
||||
}
|
||||
}
|
||||
|
||||
private void transferOne(CompleteTransferRequestDTO request) {
|
||||
if (request == null || isBlank(request.getTransactionSid()) || isBlank(request.getTargetShopOrder())) {
|
||||
throw BusinessException.build("成品事务和目标工单不能为空");
|
||||
}
|
||||
ZLotMaterialCompleteTransaction source = completeService.getById(request.getTransactionSid());
|
||||
if (source == null) {
|
||||
throw BusinessException.build("成品事务不存在");
|
||||
}
|
||||
if (!"101".equals(source.getProductType())) {
|
||||
throw BusinessException.build("仅支持101成品调整到其他工单");
|
||||
}
|
||||
if ("Y".equals(source.getErpReverse()) || "C".equals(source.getSyncStatus())) {
|
||||
throw BusinessException.build("已冲销或已结案的记录不能调整到其他工单");
|
||||
}
|
||||
if (!"S".equals(source.getSyncStatus()) && !"N".equals(source.getSyncStatus()) && !"E".equals(source.getSyncStatus())) {
|
||||
throw BusinessException.build("只支持成功、待过账或失败的成品行调整到其他工单");
|
||||
}
|
||||
if (request.getTargetShopOrder().equals(source.getShopOrder())) {
|
||||
throw BusinessException.build("目标工单不能与原工单相同");
|
||||
}
|
||||
ShopOrder targetOrder = shopOrderService.getOne(Wrappers.<ShopOrder>lambdaQuery()
|
||||
.eq(ShopOrder::getSite, source.getSite())
|
||||
.eq(ShopOrder::getShopOrder, request.getTargetShopOrder()));
|
||||
if (targetOrder == null) {
|
||||
throw BusinessException.build("目标工单不存在");
|
||||
}
|
||||
assertItemAllowedOnOrder(source.getSite(), targetOrder.getShopOrder(), source.getItem());
|
||||
if ("S".equals(source.getSyncStatus())) {
|
||||
if (request.getPostingDate() == null) {
|
||||
throw BusinessException.build("已过账记录调整到其他工单时请选择过账日期");
|
||||
}
|
||||
String reverseSid = UUID.randomUUID().toString();
|
||||
JSONObject sapRequest = new JSONObject();
|
||||
sapRequest.put("transaction", source);
|
||||
sapRequest.put("reverseSid", reverseSid);
|
||||
sapRequest.put("postingDate", request.getPostingDate().toString());
|
||||
JSONObject response = remoteInvokeService.reverseComplete102(sapRequest, SecurityConstants.FROM_IN);
|
||||
if (response == null || !"S".equals(response.getString("RESULT"))) {
|
||||
throw BusinessException.build(response == null ? "SAP未返回结果" : response.getString("MESSAGE"));
|
||||
}
|
||||
saveOff(source, reverseSid, response);
|
||||
closeComplete(source);
|
||||
ZLotMaterialCompleteTransaction target = createTargetComplete(source, targetOrder, request.getPostingDate());
|
||||
moveLotBasis(source, targetOrder);
|
||||
CompleteCorrectionResultDTO posted = repost101(target.getSid());
|
||||
if (!"SUCCESS".equals(posted.getStatus())) {
|
||||
throw BusinessException.build(posted.getMessage() == null ? "目标工单101过账失败" : posted.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
closeComplete(source);
|
||||
createTargetComplete(source, targetOrder, request.getPostingDate());
|
||||
moveLotBasis(source, targetOrder);
|
||||
}
|
||||
|
||||
private void assertItemAllowedOnOrder(String site, String shopOrder, String item) {
|
||||
List<ShopOrderReleaseItemInfo> allowed = nlvLotStartService.firstOpReleaseItemList(
|
||||
site, null, Collections.singletonList(shopOrder));
|
||||
boolean ok = allowed != null && allowed.stream().anyMatch(info -> eq(item, info.getItem()));
|
||||
if (!ok) {
|
||||
throw BusinessException.build("物料" + item + "不是工单" + shopOrder + "允许的产出物料");
|
||||
}
|
||||
}
|
||||
|
||||
private ZLotMaterialCompleteTransaction createTargetComplete(ZLotMaterialCompleteTransaction source,
|
||||
ShopOrder targetOrder, LocalDate postingDate) {
|
||||
String newSid = UUID.randomUUID().toString();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String user = currentUser();
|
||||
ZLotMaterialCompleteTransaction target = new ZLotMaterialCompleteTransaction();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
target.setSid(newSid);
|
||||
target.setShopOrder(targetOrder.getShopOrder());
|
||||
target.setSapBatchNo(nextSapBatchNo(source.getItem(), targetOrder.getShopOrder(), source.getQcGrade()));
|
||||
target.setSyncStatus("N");
|
||||
target.setSyncVoucherNo(null);
|
||||
target.setSyncMsgNo(null);
|
||||
target.setSyncMsgText(null);
|
||||
target.setSyncMsgId(null);
|
||||
target.setSyncTransBatch(null);
|
||||
target.setSyncTransDate(null);
|
||||
target.setSyncPostingDate(postingDate);
|
||||
target.setErpFlag("N");
|
||||
target.setErpReverse(null);
|
||||
target.setCreator(user);
|
||||
target.setDateCreate(now);
|
||||
target.setUpdater(user);
|
||||
target.setDateUpdate(now);
|
||||
completeService.save(target);
|
||||
return target;
|
||||
}
|
||||
|
||||
private void closeComplete(ZLotMaterialCompleteTransaction source) {
|
||||
ZLotMaterialCompleteTransaction latest = completeService.getById(source.getSid());
|
||||
latest.setSyncStatus("C");
|
||||
if ("S".equals(source.getSyncStatus())) {
|
||||
latest.setErpReverse("Y");
|
||||
}
|
||||
latest.setUpdater(currentUser());
|
||||
latest.setDateUpdate(LocalDateTime.now());
|
||||
completeService.updateById(latest);
|
||||
}
|
||||
|
||||
private void moveLotBasis(ZLotMaterialCompleteTransaction source, ShopOrder targetOrder) {
|
||||
if (isBlank(source.getLotNo())) {
|
||||
return;
|
||||
}
|
||||
LotBasis lot = lotBasisService.getById(LotBasis.genHandle(source.getSite(), source.getLotNo()));
|
||||
if (lot == null) {
|
||||
return;
|
||||
}
|
||||
lot.setShopOrderBo(targetOrder.getHandle());
|
||||
lot.setUpdater(currentUser());
|
||||
lot.setDateUpdate(LocalDateTime.now());
|
||||
lotBasisService.updateById(lot);
|
||||
}
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
private void prepareOutFields(ZLotMaterialCompleteTransaction source, CompleteCorrectionRequestDTO request) {
|
||||
request.setShopOrder(source.getShopOrder());
|
||||
request.setLotNo(source.getLotNo());
|
||||
@ -215,7 +358,7 @@ public class ZLotMaterialCompleteCorrectionServiceImpl implements ZLotMaterialCo
|
||||
return;
|
||||
}
|
||||
InventoryQtyAdjustRequest inventoryRequest = new InventoryQtyAdjustRequest();
|
||||
inventoryRequest.setRequestId(before.getSid() + ":fgq:" + oldQty.toPlainString() + ":" + newQty.toPlainString());
|
||||
inventoryRequest.setRequestId(before.getSid() + ":" + System.currentTimeMillis());
|
||||
inventoryRequest.setInventoryBo(inventory.getHandle());
|
||||
inventoryRequest.setDeltaQty(delta);
|
||||
inventoryRequest.setExpectedMaterialLot(inventory.getInventoryId());
|
||||
@ -280,7 +423,8 @@ public class ZLotMaterialCompleteCorrectionServiceImpl implements ZLotMaterialCo
|
||||
return !eq(source.getItem(), request.getItem())
|
||||
|| !qtyEq(source.getMainQty(), request.getMainQty())
|
||||
|| !eq(source.getQcGrade(), request.getQcGrade())
|
||||
|| !eq(source.getSapBatchNo(), request.getSapBatchNo());
|
||||
|| !eq(source.getSapBatchNo(), request.getSapBatchNo())
|
||||
|| postingDateChanged(source.getSyncPostingDate(), request.getPostingDate());
|
||||
}
|
||||
|
||||
private boolean localChanged(ZLotMaterialCompleteTransaction source, CompleteCorrectionRequestDTO request) {
|
||||
@ -339,6 +483,10 @@ public class ZLotMaterialCompleteCorrectionServiceImpl implements ZLotMaterialCo
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
private boolean postingDateChanged(LocalDate current, LocalDate next) {
|
||||
return current != null && next != null && !current.equals(next);
|
||||
}
|
||||
|
||||
private boolean zeroQty(CompleteCorrectionRequestDTO request) {
|
||||
return request.getMainQty() != null && request.getMainQty().compareTo(BigDecimal.ZERO) == 0;
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import com.foreverwin.iep.prd.service.ShopOrderService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialCancelService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialConsumptionRepostService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialConsumptionTransactionService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialQtyAdjustmentService;
|
||||
import com.foreverwin.iep.wip.dto.OperationOutBomComponentDTO;
|
||||
import com.foreverwin.iep.wip.entity.LotMaterial;
|
||||
import com.foreverwin.iep.wip.mapper.OperationOutMapper;
|
||||
@ -48,6 +49,7 @@ public class ZLotMaterialConsumptionRepostServiceImpl implements ZLotMaterialCon
|
||||
private final ShopOrderService shopOrderService;
|
||||
private final OperationOutMapper operationOutMapper;
|
||||
private final ZLotMaterialCancelService cancelService;
|
||||
private final ZLotMaterialQtyAdjustmentService qtyAdjustmentService;
|
||||
|
||||
@Override
|
||||
public void repost261(List<ConsumptionRepostRequestDTO> requests) {
|
||||
@ -86,7 +88,20 @@ public class ZLotMaterialConsumptionRepostServiceImpl implements ZLotMaterialCon
|
||||
if (request.getPostingDate() == null) {
|
||||
throw BusinessException.build("请选择过账日期");
|
||||
}
|
||||
ZLotMaterialConsumptionTransaction source = requireUnposted(request.getTransactionSid());
|
||||
ZLotMaterialConsumptionTransaction source = consumptionService.getById(request.getTransactionSid());
|
||||
if (source == null) {
|
||||
throw BusinessException.build("物料消耗事务不存在");
|
||||
}
|
||||
if ("Y".equals(source.getErpReverse()) || "C".equals(source.getSyncStatus())) {
|
||||
throw BusinessException.build("已冲销或已结案的记录不能重新过账");
|
||||
}
|
||||
if ("S".equals(source.getSyncStatus())) {
|
||||
repostPosted(source, request);
|
||||
return;
|
||||
}
|
||||
if (!"N".equals(source.getSyncStatus()) && !"E".equals(source.getSyncStatus())) {
|
||||
throw BusinessException.build("只能对成功、待过账或失败的记录重新过账");
|
||||
}
|
||||
BigDecimal oldQty = value(source.getMainQty());
|
||||
BigDecimal newQty = request.getTargetQty() == null ? oldQty : request.getTargetQty();
|
||||
if (newQty.compareTo(BigDecimal.ZERO) < 0) {
|
||||
@ -101,6 +116,67 @@ public class ZLotMaterialConsumptionRepostServiceImpl implements ZLotMaterialCon
|
||||
persistQty(source.getSid(), newQty);
|
||||
}
|
||||
|
||||
private void repostPosted(ZLotMaterialConsumptionTransaction source, ConsumptionRepostRequestDTO request) {
|
||||
if (qtyAdjustmentService.hasSuccessAdjustment(source.getSid())) {
|
||||
throw BusinessException.build("已数量调整的行请使用调整261/262");
|
||||
}
|
||||
if (StrUtil.isBlank(source.getReservedNo()) || StrUtil.isBlank(source.getReservedLine())) {
|
||||
throw BusinessException.build("原消耗缺少预留号或预留行号,不能冲销262");
|
||||
}
|
||||
BigDecimal oldQty = value(source.getMainQty());
|
||||
BigDecimal newQty = request.getTargetQty() == null ? oldQty : request.getTargetQty();
|
||||
if (newQty.compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw BusinessException.build("目标数量不能小于0");
|
||||
}
|
||||
String cancelSid = StrUtil.uuid();
|
||||
call262(source, oldQty, request.getPostingDate(), cancelSid);
|
||||
saveCancel(source, cancelSid, oldQty, request.getPostingDate());
|
||||
if (oldQty.compareTo(BigDecimal.ZERO) > 0) {
|
||||
adjustWms(source, oldQty, BigDecimal.ZERO, source.getSid() + ":rp262:" + oldQty.toPlainString(),
|
||||
source.getShopOrder() + "已过账消耗262冲销退回线边库", "MATERIAL_CONSUMPTION_REPOST_262");
|
||||
}
|
||||
persistUnposted(source.getSid(), newQty);
|
||||
if (newQty.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return;
|
||||
}
|
||||
adjustWms(source, newQty.negate(), newQty, source.getSid() + ":rp261:" + newQty.toPlainString(),
|
||||
source.getShopOrder() + "已过账消耗按新数量261", "MATERIAL_CONSUMPTION_REPOST_261");
|
||||
call261(source, newQty, request.getPostingDate(), source.getReservedNo(), source.getReservedLine());
|
||||
persistQty(source.getSid(), newQty);
|
||||
}
|
||||
|
||||
private void persistUnposted(String transactionSid, BigDecimal newQty) {
|
||||
ZLotMaterialConsumptionTransaction latest = consumptionService.getById(transactionSid);
|
||||
if (latest == null) {
|
||||
throw BusinessException.build("物料消耗事务不存在");
|
||||
}
|
||||
latest.setMainQty(newQty);
|
||||
latest.setSyncStatus("N");
|
||||
latest.setSyncVoucherNo(null);
|
||||
latest.setErpReverse(null);
|
||||
latest.setUpdater(currentUser());
|
||||
latest.setDateUpdate(LocalDateTime.now());
|
||||
consumptionService.updateById(latest);
|
||||
if (latest.getLotMaterialSid() == null) {
|
||||
return;
|
||||
}
|
||||
LotMaterial lotMaterial = lotMaterialService.getById(latest.getLotMaterialSid());
|
||||
if (lotMaterial == null) {
|
||||
return;
|
||||
}
|
||||
lotMaterial.setConsumeQty(newQty);
|
||||
lotMaterial.setQty(newQty);
|
||||
lotMaterial.setErpFlag("N");
|
||||
if (newQty.compareTo(BigDecimal.ZERO) == 0) {
|
||||
lotMaterial.setRemoved("Y");
|
||||
lotMaterial.setRemovedDate(LocalDateTime.now());
|
||||
} else {
|
||||
lotMaterial.setRemoved(null);
|
||||
lotMaterial.setRemovedDate(null);
|
||||
}
|
||||
lotMaterialService.updateById(lotMaterial);
|
||||
}
|
||||
|
||||
private void cancelOne(ConsumptionCancelRequestDTO request) {
|
||||
if (request == null || request.getTransactionSid() == null || request.getTransactionSid().isEmpty()) {
|
||||
throw BusinessException.build("消耗事务不能为空");
|
||||
|
||||
@ -3,11 +3,16 @@ package com.foreverwin.iep.prd.service.impl;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.foreverwin.iep.integration.feign.RemoteInvokeService;
|
||||
import com.foreverwin.iep.prd.dto.CompleteCorrectionRequestDTO;
|
||||
import com.foreverwin.iep.prd.dto.CompleteTransferRequestDTO;
|
||||
import com.foreverwin.iep.prd.entity.ShopOrder;
|
||||
import com.foreverwin.iep.prd.entity.ZLotMaterialCompleteTransaction;
|
||||
import com.foreverwin.iep.integration.feign.RemoteGetSapBatchNoService;
|
||||
import com.foreverwin.iep.prd.service.ItemService;
|
||||
import com.foreverwin.iep.prd.service.ShopOrderService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialCompleteTransactionOffService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialCompleteTransactionService;
|
||||
import com.foreverwin.iep.wip.entity.LotBasis;
|
||||
import com.foreverwin.iep.wip.service.LotBasisService;
|
||||
import com.foreverwin.iep.wip.service.NlvLotStartService;
|
||||
import com.foreverwin.mom.common.core.util.R;
|
||||
import com.foreverwin.mom.wms.api.feign.RemoteWmsInventoryService;
|
||||
@ -61,7 +66,8 @@ class ZLotMaterialCompleteCorrectionServiceImplTest {
|
||||
ZLotMaterialCompleteCorrectionServiceImpl service = new ZLotMaterialCompleteCorrectionServiceImpl(
|
||||
mock(ZLotMaterialCompleteTransactionService.class),
|
||||
mock(ZLotMaterialCompleteTransactionOffService.class),
|
||||
null, null, mock(ItemService.class), nlvLotStartService, mock(RemoteGetSapBatchNoService.class));
|
||||
null, null, mock(ItemService.class), nlvLotStartService, mock(RemoteGetSapBatchNoService.class),
|
||||
mock(ShopOrderService.class), mock(LotBasisService.class));
|
||||
ZLotMaterialCompleteTransaction source = source();
|
||||
source.setSite("2031");
|
||||
CompleteCorrectionRequestDTO request = requestFrom(source);
|
||||
@ -90,7 +96,9 @@ class ZLotMaterialCompleteCorrectionServiceImplTest {
|
||||
remoteWmsInventoryService,
|
||||
mock(ItemService.class),
|
||||
mock(NlvLotStartService.class),
|
||||
mock(RemoteGetSapBatchNoService.class));
|
||||
mock(RemoteGetSapBatchNoService.class),
|
||||
mock(ShopOrderService.class),
|
||||
mock(LotBasisService.class));
|
||||
|
||||
ZLotMaterialCompleteTransaction source = source();
|
||||
source.setSite("2031");
|
||||
@ -116,6 +124,8 @@ class ZLotMaterialCompleteCorrectionServiceImplTest {
|
||||
ArgumentCaptor<InventoryQtyAdjustRequest> captor = ArgumentCaptor.forClass(InventoryQtyAdjustRequest.class);
|
||||
verify(remoteWmsInventoryService).adjustQty(captor.capture());
|
||||
assertEquals(0, new BigDecimal("-2").compareTo(captor.getValue().getDeltaQty()));
|
||||
assertTrue(captor.getValue().getRequestId().startsWith("sid-1:"));
|
||||
assertTrue(captor.getValue().getRequestId().length() <= 64);
|
||||
assertEquals(0, new BigDecimal("8").compareTo(source.getMainQty()));
|
||||
verify(remoteInvokeService).repostComplete101(any(), anyString());
|
||||
}
|
||||
@ -132,7 +142,9 @@ class ZLotMaterialCompleteCorrectionServiceImplTest {
|
||||
remoteWmsInventoryService,
|
||||
mock(ItemService.class),
|
||||
mock(NlvLotStartService.class),
|
||||
mock(RemoteGetSapBatchNoService.class));
|
||||
mock(RemoteGetSapBatchNoService.class),
|
||||
mock(ShopOrderService.class),
|
||||
mock(LotBasisService.class));
|
||||
|
||||
ZLotMaterialCompleteTransaction source = source();
|
||||
source.setSite("2031");
|
||||
@ -159,6 +171,7 @@ class ZLotMaterialCompleteCorrectionServiceImplTest {
|
||||
verify(remoteInvokeService, never()).repostComplete101(any(), anyString());
|
||||
assertEquals(0, BigDecimal.ZERO.compareTo(source.getMainQty()));
|
||||
assertEquals("Y", source.getErpReverse());
|
||||
assertEquals("C", source.getSyncStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -173,7 +186,9 @@ class ZLotMaterialCompleteCorrectionServiceImplTest {
|
||||
remoteWmsInventoryService,
|
||||
mock(ItemService.class),
|
||||
mock(NlvLotStartService.class),
|
||||
mock(RemoteGetSapBatchNoService.class));
|
||||
mock(RemoteGetSapBatchNoService.class),
|
||||
mock(ShopOrderService.class),
|
||||
mock(LotBasisService.class));
|
||||
|
||||
ZLotMaterialCompleteTransaction source = source();
|
||||
source.setSite("2031");
|
||||
@ -196,13 +211,73 @@ class ZLotMaterialCompleteCorrectionServiceImplTest {
|
||||
verify(remoteInvokeService, never()).reverseComplete102(any(), anyString());
|
||||
verify(remoteInvokeService, never()).repostComplete101(any(), anyString());
|
||||
assertEquals("Y", source.getErpReverse());
|
||||
assertEquals("C", source.getSyncStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
void postingDateChangeTouchesSap() throws Exception {
|
||||
ZLotMaterialCompleteCorrectionServiceImpl service = newService();
|
||||
ZLotMaterialCompleteTransaction source = source();
|
||||
source.setSyncPostingDate(LocalDate.of(2026, 8, 1));
|
||||
CompleteCorrectionRequestDTO request = requestFrom(source);
|
||||
request.setPostingDate(LocalDate.of(2026, 9, 1));
|
||||
assertTrue((Boolean) invoke(service, "sapChanged", source, request));
|
||||
}
|
||||
|
||||
@Test
|
||||
void transferUnpostedMovesLotWithoutSap() {
|
||||
ZLotMaterialCompleteTransactionService completeService = mock(ZLotMaterialCompleteTransactionService.class);
|
||||
ShopOrderService shopOrderService = mock(ShopOrderService.class);
|
||||
LotBasisService lotBasisService = mock(LotBasisService.class);
|
||||
NlvLotStartService nlvLotStartService = mock(NlvLotStartService.class);
|
||||
RemoteGetSapBatchNoService sapBatchNoService = mock(RemoteGetSapBatchNoService.class);
|
||||
RemoteInvokeService remoteInvokeService = mock(RemoteInvokeService.class);
|
||||
ZLotMaterialCompleteCorrectionServiceImpl service = new ZLotMaterialCompleteCorrectionServiceImpl(
|
||||
completeService,
|
||||
mock(ZLotMaterialCompleteTransactionOffService.class),
|
||||
remoteInvokeService,
|
||||
mock(RemoteWmsInventoryService.class),
|
||||
mock(ItemService.class),
|
||||
nlvLotStartService,
|
||||
sapBatchNoService,
|
||||
shopOrderService,
|
||||
lotBasisService);
|
||||
|
||||
ZLotMaterialCompleteTransaction source = source();
|
||||
source.setSite("2031");
|
||||
source.setSyncStatus("N");
|
||||
when(completeService.getById("sid-1")).thenReturn(source);
|
||||
ShopOrder target = new ShopOrder();
|
||||
target.setHandle("ShopOrderBO:2031,2100014999");
|
||||
target.setShopOrder("2100014999");
|
||||
when(shopOrderService.getOne(any())).thenReturn(target);
|
||||
com.foreverwin.iep.wip.domain.ShopOrderReleaseItemInfo itemInfo =
|
||||
new com.foreverwin.iep.wip.domain.ShopOrderReleaseItemInfo();
|
||||
itemInfo.setItem("2300227");
|
||||
when(nlvLotStartService.firstOpReleaseItemList(any(), any(), any()))
|
||||
.thenReturn(Collections.singletonList(itemInfo));
|
||||
when(sapBatchNoService.getSapBatchNoNew(any())).thenReturn(R.ok("2609010001"));
|
||||
LotBasis lot = new LotBasis();
|
||||
lot.setHandle(LotBasis.genHandle("2031", "3601180036A005"));
|
||||
when(lotBasisService.getById(anyString())).thenReturn(lot);
|
||||
|
||||
CompleteTransferRequestDTO request = new CompleteTransferRequestDTO();
|
||||
request.setTransactionSid("sid-1");
|
||||
request.setTargetShopOrder("2100014999");
|
||||
service.transferShopOrder(Collections.singletonList(request));
|
||||
|
||||
verify(remoteInvokeService, never()).reverseComplete102(any(), anyString());
|
||||
verify(remoteInvokeService, never()).repostComplete101(any(), anyString());
|
||||
verify(completeService).save(any(ZLotMaterialCompleteTransaction.class));
|
||||
assertEquals("C", source.getSyncStatus());
|
||||
assertEquals("ShopOrderBO:2031,2100014999", lot.getShopOrderBo());
|
||||
}
|
||||
|
||||
private ZLotMaterialCompleteCorrectionServiceImpl newService() {
|
||||
return new ZLotMaterialCompleteCorrectionServiceImpl(
|
||||
mock(ZLotMaterialCompleteTransactionService.class),
|
||||
mock(ZLotMaterialCompleteTransactionOffService.class),
|
||||
null, null, null, null, null);
|
||||
null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
private Object invoke(ZLotMaterialCompleteCorrectionServiceImpl service, String name,
|
||||
|
||||
@ -11,6 +11,7 @@ import com.foreverwin.iep.prd.entity.ZLotMaterialConsumptionTransaction;
|
||||
import com.foreverwin.iep.prd.service.ShopOrderService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialCancelService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialConsumptionTransactionService;
|
||||
import com.foreverwin.iep.prd.service.ZLotMaterialQtyAdjustmentService;
|
||||
import com.foreverwin.iep.wip.dto.OperationOutBomComponentDTO;
|
||||
import com.foreverwin.iep.wip.entity.LotMaterial;
|
||||
import com.foreverwin.iep.wip.mapper.OperationOutMapper;
|
||||
@ -44,9 +45,10 @@ class ZLotMaterialConsumptionRepostServiceImplTest {
|
||||
private final ShopOrderService shopOrderService = mock(ShopOrderService.class);
|
||||
private final OperationOutMapper operationOutMapper = mock(OperationOutMapper.class);
|
||||
private final ZLotMaterialCancelService cancelService = mock(ZLotMaterialCancelService.class);
|
||||
private final ZLotMaterialQtyAdjustmentService qtyAdjustmentService = mock(ZLotMaterialQtyAdjustmentService.class);
|
||||
private final ZLotMaterialConsumptionRepostServiceImpl service = new ZLotMaterialConsumptionRepostServiceImpl(
|
||||
consumptionService, lotMaterialService, remoteInvokeService, remoteWmsInventoryService,
|
||||
shopOrderService, operationOutMapper, cancelService);
|
||||
shopOrderService, operationOutMapper, cancelService, qtyAdjustmentService);
|
||||
|
||||
@Test
|
||||
void decreasingQtyReturnsDifferenceToWms() {
|
||||
@ -130,6 +132,60 @@ class ZLotMaterialConsumptionRepostServiceImplTest {
|
||||
assertEquals("C", source.getSyncStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
void postedRepostDecreasesQtyWith262Then261() {
|
||||
ZLotMaterialConsumptionTransaction source = unposted("sid-s", "S", new BigDecimal("55"));
|
||||
source.setReservedNo("90001");
|
||||
source.setReservedLine("10");
|
||||
when(consumptionService.getById("sid-s")).thenReturn(source);
|
||||
when(qtyAdjustmentService.hasSuccessAdjustment("sid-s")).thenReturn(false);
|
||||
LotMaterial lotMaterial = new LotMaterial();
|
||||
lotMaterial.setSid("lm-1");
|
||||
lotMaterial.setItemBo("ItemBO:2031,A");
|
||||
when(lotMaterialService.getById("lm-1")).thenReturn(lotMaterial);
|
||||
sap261Ok();
|
||||
sap262Ok();
|
||||
when(remoteWmsInventoryService.adjustQty(any())).thenReturn(R.ok(new Inventory()));
|
||||
|
||||
ConsumptionRepostRequestDTO request = new ConsumptionRepostRequestDTO();
|
||||
request.setTransactionSid("sid-s");
|
||||
request.setTargetQty(new BigDecimal("50"));
|
||||
request.setPostingDate(LocalDate.of(2026, 9, 1));
|
||||
service.repost261(Collections.singletonList(request));
|
||||
|
||||
verify(remoteInvokeService).adjustMaterialQty(any(), anyString());
|
||||
verify(remoteInvokeService).callErpMaterial(any(), anyString());
|
||||
ArgumentCaptor<InventoryQtyAdjustRequest> captor = ArgumentCaptor.forClass(InventoryQtyAdjustRequest.class);
|
||||
verify(remoteWmsInventoryService, org.mockito.Mockito.times(2)).adjustQty(captor.capture());
|
||||
assertEquals(0, new BigDecimal("55").compareTo(captor.getAllValues().get(0).getDeltaQty()));
|
||||
assertEquals(0, new BigDecimal("-50").compareTo(captor.getAllValues().get(1).getDeltaQty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void postedRepostZeroQtyOnly262AndStaysUnposted() {
|
||||
ZLotMaterialConsumptionTransaction source = unposted("sid-0", "S", new BigDecimal("55"));
|
||||
source.setReservedNo("90001");
|
||||
source.setReservedLine("10");
|
||||
when(consumptionService.getById("sid-0")).thenReturn(source);
|
||||
when(qtyAdjustmentService.hasSuccessAdjustment("sid-0")).thenReturn(false);
|
||||
LotMaterial lotMaterial = new LotMaterial();
|
||||
lotMaterial.setSid("lm-1");
|
||||
when(lotMaterialService.getById("lm-1")).thenReturn(lotMaterial);
|
||||
sap262Ok();
|
||||
when(remoteWmsInventoryService.adjustQty(any())).thenReturn(R.ok(new Inventory()));
|
||||
|
||||
ConsumptionRepostRequestDTO request = new ConsumptionRepostRequestDTO();
|
||||
request.setTransactionSid("sid-0");
|
||||
request.setTargetQty(BigDecimal.ZERO);
|
||||
request.setPostingDate(LocalDate.of(2026, 9, 1));
|
||||
service.repost261(Collections.singletonList(request));
|
||||
|
||||
verify(remoteInvokeService).adjustMaterialQty(any(), anyString());
|
||||
verify(remoteInvokeService, never()).callErpMaterial(any(), anyString());
|
||||
assertEquals("N", source.getSyncStatus());
|
||||
assertEquals(0, BigDecimal.ZERO.compareTo(source.getMainQty()));
|
||||
}
|
||||
|
||||
private ZLotMaterialConsumptionTransaction unposted(String sid, String status, BigDecimal qty) {
|
||||
ZLotMaterialConsumptionTransaction source = new ZLotMaterialConsumptionTransaction();
|
||||
source.setSid(sid);
|
||||
@ -148,4 +204,10 @@ class ZLotMaterialConsumptionRepostServiceImplTest {
|
||||
sapOk.put("code", 0);
|
||||
when(remoteInvokeService.callErpMaterial(any(), anyString())).thenReturn(sapOk);
|
||||
}
|
||||
|
||||
private void sap262Ok() {
|
||||
JSONObject sapOk = new JSONObject();
|
||||
sapOk.put("RESULT", "S");
|
||||
when(remoteInvokeService.adjustMaterialQty(any(), anyString())).thenReturn(sapOk);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user