package cn.iocoder.yudao.module.mes.service.wm.scrap;
|
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
|
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
|
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.scrap.MesWmScrapSaleDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.scrap.MesWmScrapSaleLineDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock.MesWmMaterialStockMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.scrap.MesWmScrapReceiptMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.scrap.MesWmScrapSaleLineMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.scrap.MesWmScrapSaleMapper;
|
import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
|
import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
|
import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
|
import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
|
import jakarta.annotation.Resource;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import java.math.BigDecimal;
|
import java.util.Comparator;
|
import java.util.Objects;
|
import java.util.Map;
|
|
@Service
|
public class MesWmScrapSaleService {
|
public static final String PROCESS_KEY = "wm_scrap_sale_finance";
|
@Resource private MesWmScrapSaleMapper saleMapper;
|
@Resource private MesWmScrapSaleLineMapper lineMapper;
|
@Resource private MesWmScrapReceiptMapper receiptMapper;
|
@Resource private MesWmMaterialStockMapper stockMapper;
|
@Resource private MesWmTransactionService transactionService;
|
@Resource private BpmProcessInstanceApi processApi;
|
|
@Transactional(rollbackFor = Exception.class)
|
public void submit(Long id, Long userId) {
|
MesWmScrapSaleDO sale = saleMapper.lockById(id);
|
if (sale == null || !Objects.equals(sale.getStatus(), 0)) throw new ServiceException(400, "仅草稿可提交审批");
|
var lines = lineMapper.selectBySaleId(id);
|
if (lines.isEmpty()) throw new ServiceException(400, "出售单没有明细");
|
// 财务审核不可被全局免审批绕过。
|
if (processApi.isGlobalAutoApprove()) throw new ServiceException(400, "全局免审批已开启,废料出售必须经过财务审核");
|
MesWmScrapSaleDO update = new MesWmScrapSaleDO();
|
update.setId(id);
|
update.setStatus(1);
|
saleMapper.updateById(update);
|
String processId = processApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO()
|
.setProcessDefinitionKey(PROCESS_KEY).setBusinessKey(String.valueOf(id))
|
.setVariables(Map.of("saleCode", sale.getCode(), "buyer", sale.getBuyer(),
|
"totalAmount", lines.stream().map(line -> line.getQuantity().multiply(line.getUnitPrice()))
|
.reduce(BigDecimal.ZERO, BigDecimal::add))));
|
MesWmScrapSaleDO processUpdate = new MesWmScrapSaleDO();
|
processUpdate.setId(id);
|
processUpdate.setProcessInstanceId(processId);
|
saleMapper.updateById(processUpdate);
|
}
|
|
@Transactional(rollbackFor = Exception.class)
|
public void onApproval(Long id, String processId, Integer status) {
|
MesWmScrapSaleDO sale = saleMapper.lockById(id);
|
if (sale == null || !Objects.equals(sale.getStatus(), 1)) return;
|
if (sale.getProcessInstanceId() != null && !sale.getProcessInstanceId().equals(processId)) return;
|
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
|
var lines = lineMapper.selectBySaleId(id);
|
lines.sort(Comparator.comparing(MesWmScrapSaleLineDO::getMaterialStockId));
|
for (MesWmScrapSaleLineDO line : lines) {
|
var stock = stockMapper.lockById(line.getMaterialStockId());
|
if (stock == null || receiptMapper.countByStockId(line.getMaterialStockId()) == 0)
|
throw new ServiceException(400, "废料库存不存在或已变动");
|
BigDecimal available = zero(stock.getQuantity()).subtract(zero(stock.getFrozenQuantity())).subtract(zero(stock.getReservedQuantity()));
|
if (available.compareTo(line.getQuantity()) < 0) throw new ServiceException(400, "废料可用库存不足,无法出库");
|
Long transactionId = transactionService.createTransaction(new MesWmTransactionSaveReqDTO()
|
.setType(MesWmTransactionTypeEnum.OUT.getType()).setBizType(MesBizTypeConstants.WM_SCRAP_SALE)
|
.setBizId(id).setBizCode(sale.getCode()).setBizLineId(line.getId())
|
.setMaterialStockId(stock.getId()).setItemId(stock.getItemId()).setQuantity(line.getQuantity().negate())
|
.setWarehouseId(stock.getWarehouseId()).setLocationId(stock.getLocationId()).setAreaId(stock.getAreaId())
|
.setBatchId(stock.getBatchId()).setBatchCode(stock.getBatchCode()));
|
MesWmScrapSaleLineDO updateLine = new MesWmScrapSaleLineDO();
|
updateLine.setId(line.getId());
|
updateLine.setTransactionId(transactionId);
|
lineMapper.updateById(updateLine);
|
}
|
setStatus(id, 2);
|
} else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) {
|
setStatus(id, 3);
|
} else if (Objects.equals(status, BpmProcessInstanceStatusEnum.CANCEL.getStatus())) {
|
setStatus(id, 4);
|
}
|
}
|
|
private void setStatus(Long id, int status) {
|
MesWmScrapSaleDO update = new MesWmScrapSaleDO();
|
update.setId(id);
|
update.setStatus(status);
|
saleMapper.updateById(update);
|
}
|
private BigDecimal zero(BigDecimal value) { return value == null ? BigDecimal.ZERO : value; }
|
}
|