From 684e4306a08feeae188070f264148e6765da8dcf Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期日, 20 九月 2026 19:25:15 +0800
Subject: [PATCH] feat(account): 更新往来付款回款流水表及接口
---
src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java | 542 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 539 insertions(+), 3 deletions(-)
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
index 3e2d0f2..1445d45 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
@@ -1,10 +1,52 @@
package com.ruoyi.stock.service.impl;
-import com.ruoyi.stock.pojo.StockOutRecord;
-import com.ruoyi.stock.mapper.StockOutRecordMapper;
-import com.ruoyi.stock.service.StockOutRecordService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.mapper.sales.AccountInvoiceApplicationMapper;
+import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
+import com.ruoyi.basic.pojo.Vehicle;
+import com.ruoyi.basic.service.IVehicleService;
+import com.ruoyi.common.enums.ReviewStatusEnum;
+import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.EnumUtil;
+import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.outsourcing.enums.OutsourcingOrderStatusEnum;
+import com.ruoyi.outsourcing.mapper.OutsourcingOrderMapper;
+import com.ruoyi.outsourcing.mapper.OutsourcingOrderProductMapper;
+import com.ruoyi.outsourcing.pojo.OutsourcingOrder;
+import com.ruoyi.outsourcing.pojo.OutsourcingOrderProduct;
+
+import java.time.LocalDateTime;
+import com.ruoyi.stock.dto.OilOutAvailableDto;
+import com.ruoyi.stock.dto.StockInventoryDto;
+import com.ruoyi.stock.dto.StockOutRecordDto;
+import com.ruoyi.stock.dto.StockUninventoryDto;
+import com.ruoyi.stock.execl.StockOutRecordExportData;
+import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.mapper.StockOutRecordMapper;
+import com.ruoyi.stock.mapper.StockUninventoryMapper;
+import com.ruoyi.stock.pojo.StockInventory;
+import com.ruoyi.stock.pojo.StockOutRecord;
+import com.ruoyi.stock.pojo.StockUninventory;
+import com.ruoyi.stock.service.StockOutRecordService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
/**
* <p>
@@ -15,6 +57,500 @@
* @since 2026-01-21 05:27:04
*/
@Service
+@RequiredArgsConstructor
public class StockOutRecordServiceImpl extends ServiceImpl<StockOutRecordMapper, StockOutRecord> implements StockOutRecordService {
+ /**
+ * 鍑哄簱绫诲埆锛氶攢鍞�傞攢鍞被娌瑰搧鍑哄簱鍦ㄥ鎵归�氳繃鏃舵寜鎵规鎵e噺搴撳瓨
+ */
+ private static final String OUT_CATEGORY_SALE = "閿�鍞�";
+ private final StockOutRecordMapper stockOutRecordMapper;
+ private final IVehicleService vehicleService;
+ private final StockInventoryMapper stockInventoryMapper;
+ private final StockUninventoryMapper stockUninventoryMapper;
+ private final AccountSalesCollectionMapper accountSalesCollectionMapper;
+ private final AccountInvoiceApplicationMapper accountInvoiceApplicationMapper;
+ private final OutsourcingOrderProductMapper outsourcingOrderProductMapper;
+ private final OutsourcingOrderMapper outsourcingOrderMapper;
+
+ @Override
+ public IPage<StockOutRecordDto> listPage(Page page, StockOutRecordDto stockOutRecordDto) {
+ return stockOutRecordMapper.listPage(page, stockOutRecordDto);
+ }
+
+ @Override
+ public int add(StockOutRecordDto stockOutRecordDto) {
+ if (OUT_CATEGORY_SALE.equals(stockOutRecordDto.getOutCategory())) {
+ // 閿�鍞被娌瑰搧鍑哄簱瀹℃壒閫氳繃鏃惰鎸夋壒娆℃墸鍑忓簱瀛橈紝鎵规涓嶈兘涓虹┖
+ if (StringUtils.isEmpty(stockOutRecordDto.getBatchNo())) {
+ throw new BaseException("閿�鍞被鍑哄簱蹇呴』閫夋嫨鍑哄簱鎵规");
+ }
+ resolveVehicle(stockOutRecordDto);
+ checkSaleOutAvailable(stockOutRecordDto);
+ }
+ LocalDateTime createTime = stockOutRecordDto.getCreateTime();
+ if (createTime == null) {
+ createTime = LocalDateTime.now();
+ }
+ String no = OrderUtils.countTodayByCreateTime(stockOutRecordMapper, "CK","outbound_batches", createTime);
+ stockOutRecordDto.setOutboundBatches(no);
+ stockOutRecordDto.setCreateTime(createTime);
+ if (StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode().equals(stockOutRecordDto.getRecordType())){
+ stockOutRecordDto.setApprovalStatus(3);
+ }
+ return stockOutRecordMapper.insert(stockOutRecordDto);
+ }
+
+ @Override
+ public int update(Long id, StockOutRecordDto stockOutRecordDto) {
+ // 鍒ゆ柇瀵硅薄鏄惁瀛樺湪
+ StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
+ if (stockOutRecord == null){
+ throw new BaseException("璇ュ嚭搴撹褰曚笉瀛樺湪,鏃犳硶鏇存柊!!!");
+ }
+
+ String[] ignoreProperties = {"id", "outbound_batches"};//鎺掗櫎id灞炴��
+ BeanUtils.copyProperties(stockOutRecordDto, stockOutRecord, ignoreProperties);
+ return stockOutRecordMapper.updateById(stockOutRecord);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int batchDelete(List<Long> ids) {
+ //todo 濡傛灉鍑哄簱涓庡紑绁ㄦ敹娆炬湁鍏宠仈鍒欐棤娉曞垹闄�
+ if (accountSalesCollectionMapper.existsByStockOutRecordId(ids) ||
+ accountInvoiceApplicationMapper.existsByStockOutRecordId(ids)) {
+ throw new BaseException("鍑哄簱璁板綍瀛樺湪寮�绁ㄦ敹娆惧叧鑱旀暟鎹�,鏃犳硶鍒犻櫎!!!");
+ }
+ for (Long id : ids) {
+ StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
+ if (stockOutRecord.getType().equals("0")) {
+ LambdaQueryWrapper<StockInventory> wrapper = new LambdaQueryWrapper<StockInventory>()
+ .eq(StockInventory::getProductModelId, stockOutRecord.getProductModelId());
+ if (StringUtils.isEmpty(stockOutRecord.getBatchNo())) {
+ wrapper.isNull(StockInventory::getBatchNo);
+ } else {
+ wrapper.eq(StockInventory::getBatchNo, stockOutRecord.getBatchNo());
+ }
+ StockInventory stockInventory = stockInventoryMapper.selectOne(wrapper);
+ if (stockInventory == null) {
+ throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶鍒犻櫎!!!");
+ }else {
+ StockInventoryDto stockInRecordDto = new StockInventoryDto();
+ stockInRecordDto.setProductModelId(stockInventory.getProductModelId());
+ stockInRecordDto.setQualitity(stockOutRecord.getStockOutNum());
+ stockInRecordDto.setBatchNo(stockInventory.getBatchNo());
+ stockInventoryMapper.updateAddStockInventory(stockInRecordDto);
+ }
+ }
+ else if (stockOutRecord.getType().equals("1")) {
+ LambdaQueryWrapper<StockUninventory> wrapper = new LambdaQueryWrapper<StockUninventory>()
+ .eq(StockUninventory::getProductModelId, stockOutRecord.getProductModelId());
+ if (StringUtils.isEmpty(stockOutRecord.getBatchNo())) {
+ wrapper.isNull(StockUninventory::getBatchNo);
+ } else {
+ wrapper.eq(StockUninventory::getBatchNo, stockOutRecord.getBatchNo());
+ }
+ StockUninventory stockUninventory = stockUninventoryMapper.selectOne(wrapper);
+ if (stockUninventory == null) {
+ throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶鍒犻櫎!!!");
+ }else {
+ StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
+ stockUninventoryDto.setProductModelId(stockUninventory.getProductModelId());
+ stockUninventoryDto.setQualitity(stockOutRecord.getStockOutNum());
+ stockUninventoryDto.setBatchNo(stockUninventory.getBatchNo());
+ stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
+ }
+ }
+ else if (OUT_CATEGORY_SALE.equals(stockOutRecord.getOutCategory())) {
+ // 閿�鍞被娌瑰搧鍑哄簱鍙湁瀹℃壒閫氳繃鏃舵墠鎵h繃搴撳瓨锛屽垹闄ゅ凡閫氳繃鐨勮褰曢渶鎸夊悓鎵规褰掕繕
+ returnSaleOilOutStock(stockOutRecord);
+ }
+ }
+ return stockOutRecordMapper.deleteBatchIds(ids);
+ }
+
+ /**
+ * 閿�鍞被娌瑰搧鍑哄簱褰掕繕搴撳瓨锛屼粎瀵瑰鎵归�氳繃锛堝嵆鎵h繃搴撳瓨锛夌殑璁板綍鐢熸晥銆�
+ * 褰掕繕閲忓彇 deduct_quantity锛堝疄闄呮墸鍑忛噺锛夛紱鏀归�犲墠瀹℃壒閫氳繃鐨勮褰曟病鏈夎鍊硷紝鎸夊叏棰濆綊杩�
+ */
+ private void returnSaleOilOutStock(StockOutRecord stockOutRecord) {
+ if (!ReviewStatusEnum.APPROVED.getCode().equals(stockOutRecord.getApprovalStatus())
+ || StringUtils.isEmpty(stockOutRecord.getBatchNo())
+ || stockOutRecord.getStockOutNum() == null) {
+ return;
+ }
+ BigDecimal returnQuantity = stockOutRecord.getDeductQuantity() != null
+ ? stockOutRecord.getDeductQuantity()
+ : stockOutRecord.getStockOutNum();
+ if (returnQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+ return;
+ }
+ StockInventoryDto stockInventoryDto = new StockInventoryDto();
+ stockInventoryDto.setProductModelId(stockOutRecord.getProductModelId());
+ stockInventoryDto.setBatchNo(stockOutRecord.getBatchNo());
+ stockInventoryDto.setQualitity(returnQuantity);
+ stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
+ }
+
+ @Override
+ public void exportStockOutRecord(HttpServletResponse response, StockOutRecordDto stockOutRecordDto) {
+ List<StockOutRecordExportData> list = stockOutRecordMapper.listStockOutRecordExportData(stockOutRecordDto);
+ for (StockOutRecordExportData stockInRecordExportData : list) {
+ if (stockInRecordExportData.getType().equals("0")) {
+ stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockOutQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
+ }else {
+ stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockInQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
+ }
+ }
+ ExcelUtil<StockOutRecordExportData> util = new ExcelUtil<>(StockOutRecordExportData.class);
+ util.exportExcel(response,list, "鍑哄簱璁板綍淇℃伅");
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int batchDeletePending(List<Long> ids) {
+ for (Long id : ids) {
+ StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
+ if (stockOutRecord == null) {
+ throw new BaseException("鍑哄簱璁板綍涓嶅瓨鍦�,鏃犳硶鍒犻櫎!!!");
+ }
+ if (stockOutRecord.getApprovalStatus() != null && !ReviewStatusEnum.PENDING_REVIEW.getCode().equals(stockOutRecord.getApprovalStatus())) {
+ throw new BaseException("鍙湁寰呭鎵圭姸鎬佺殑璁板綍鎵嶈兘鍒犻櫎,鍑哄簱鎵规:" + stockOutRecord.getOutboundBatches());
+ }
+ }
+ return stockOutRecordMapper.deleteBatchIds(ids);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int batchApprove(List<Long> ids, Integer approvalStatus) {
+ if (CollectionUtils.isEmpty(ids)) {
+ throw new BaseException("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+ }
+ if (approvalStatus == null || (!ReviewStatusEnum.APPROVED.getCode().equals(approvalStatus) && !ReviewStatusEnum.REJECTED.getCode().equals(approvalStatus))) {
+ throw new BaseException("瀹℃壒鐘舵�佸�兼棤鏁�");
+ }
+ for (Long id : ids) {
+ StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
+ if (stockOutRecord == null) {
+ throw new BaseException("鍑哄簱璁板綍涓嶅瓨鍦�,鏃犳硶瀹℃壒!!!");
+ }
+ if (stockOutRecord.getApprovalStatus() != null && !ReviewStatusEnum.PENDING_REVIEW.getCode().equals(stockOutRecord.getApprovalStatus())) {
+ throw new BaseException("鍙湁寰呭鎵圭姸鎬佺殑璁板綍鎵嶈兘瀹℃壒,鍑哄簱鎵规:" + stockOutRecord.getOutboundBatches());
+ }
+ // 瀹℃壒閫氳繃鏃跺厛鎵e噺搴撳瓨锛屾墸鍑忛噺锛坉educt_quantity锛夎闅忓鎵圭姸鎬佷竴璧疯惤搴擄紝鎵�浠ユ斁鍦ㄦ洿鏂颁箣鍓�
+ if (ReviewStatusEnum.APPROVED.getCode().equals(approvalStatus)) {
+ if ("0".equals(stockOutRecord.getType())) {
+ // 鍚堟牸鍑哄簱 -> 鍏堟煡搴撳瓨鏄惁瀛樺湪锛屽瓨鍦ㄦ墠鎵e噺
+ StockInventory stockInventory = getStockInventory(stockOutRecord.getProductModelId(), stockOutRecord.getBatchNo());
+ if (stockInventory == null) {
+ throw new BaseException("鍚堟牸搴撳瓨璁板綍涓嶅瓨鍦�,鍑哄簱鎵规:" + stockOutRecord.getOutboundBatches());
+ }
+ StockInventoryDto stockInventoryDto = new StockInventoryDto();
+ stockInventoryDto.setProductModelId(stockOutRecord.getProductModelId());
+ stockInventoryDto.setBatchNo(stockOutRecord.getBatchNo());
+ stockInventoryDto.setQualitity(stockOutRecord.getStockOutNum());
+ stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
+ } else if ("1".equals(stockOutRecord.getType())) {
+ // 涓嶅悎鏍煎嚭搴� -> 鍏堟煡搴撳瓨鏄惁瀛樺湪锛屽瓨鍦ㄦ墠鎵e噺
+ StockUninventory stockUninventory = getStockUninventory(stockOutRecord.getProductModelId(), stockOutRecord.getBatchNo());
+ if (stockUninventory == null) {
+ throw new BaseException("涓嶅悎鏍煎簱瀛樿褰曚笉瀛樺湪,鍑哄簱鎵规:" + stockOutRecord.getOutboundBatches());
+ }
+ StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
+ stockUninventoryDto.setProductModelId(stockOutRecord.getProductModelId());
+ stockUninventoryDto.setBatchNo(stockOutRecord.getBatchNo());
+ stockUninventoryDto.setQualitity(stockOutRecord.getStockOutNum());
+ stockUninventoryMapper.updateSubtractStockUnInventory(stockUninventoryDto);
+ } else if (OUT_CATEGORY_SALE.equals(stockOutRecord.getOutCategory())) {
+ // 閿�鍞被娌瑰搧鍑哄簱锛坱ype 涓虹┖锛夊鎵归�氳繃鏃舵寜鎵规鎵e噺搴撳瓨
+ deductSaleOilOutStock(stockOutRecord);
+ }
+ }
+ stockOutRecord.setApprovalStatus(approvalStatus);
+ stockOutRecordMapper.updateById(stockOutRecord);
+ if (ReviewStatusEnum.APPROVED.getCode().equals(approvalStatus)
+ && StockOutQualifiedRecordTypeEnum.OUTSOURCING_SCRAP_OUT.getCode()
+ .equals(stockOutRecord.getRecordType())) {
+ tryCompleteOutsourcingOrder(stockOutRecord);
+ }
+ }
+ return ids.size();
+ }
+
+ /**
+ * 濮斿鎶ュ簾鍝佸嚭搴撳鎵归�氳繃鍚庯紝鑻ヨ濮斿璁㈠崟鐨勬姤搴熷搧閫夋枡琛屽凡<b>鍏ㄩ儴</b>鍑哄簱瀹℃壒閫氳繃锛�
+ * 鑷姩鎶婅鍗曚粠銆屽凡纭銆嶆帹鍒般�屽凡瀹屾垚銆嶏紝鐪佹帀浜哄伐鍐嶇偣涓�娆″畬鎴愩��
+ *
+ * <p>鐩存帴鐢� mapper 鑰屼笉鏄� {@code IOutsourcingOrderService#complete}锛氬悗鑰呬緷璧栨湰鏈嶅姟锛�
+ * 涓よ竟閮借蛋鏋勯�犲櫒娉ㄥ叆浼氬舰鎴愬惊鐜緷璧栥�傞┏鍥�/鍙嶅涓嶅洖閫�璁㈠崟鐘舵�侊紙澶勭悊閿欒瀹℃壒璧颁汉宸ラ噸鏂板鎵癸級銆�</p>
+ */
+ private void tryCompleteOutsourcingOrder(StockOutRecord record) {
+ if (record.getRecordId() == null) {
+ return;
+ }
+ OutsourcingOrderProduct line = outsourcingOrderProductMapper.selectById(record.getRecordId());
+ if (line == null || line.getOutsourcingOrderId() == null) {
+ return;
+ }
+ Long orderId = line.getOutsourcingOrderId();
+ // isScrap 鍦� Java 渚ц繃婊わ紝涓庡澶栨ā鍧楄嚜宸辩殑 scrapLineIds 涓�鑷达紝涓嶄緷璧� Boolean 瀛楁鐨勫垪鍚嶆帹鏂�
+ List<Long> lineIds = outsourcingOrderProductMapper.selectList(
+ Wrappers.<OutsourcingOrderProduct>lambdaQuery()
+ .eq(OutsourcingOrderProduct::getOutsourcingOrderId, orderId))
+ .stream()
+ .filter(item -> Boolean.TRUE.equals(item.getIsScrap()))
+ .map(OutsourcingOrderProduct::getId)
+ .toList();
+ if (lineIds.isEmpty()) {
+ return;
+ }
+ // 鍑哄簱璁板綍涓�鏉″搴斾竴琛屾槑缁嗭紱缂鸿褰曪紙琚弽瀹″垹闄ょ瓑锛夊氨涓嶅畬鎴愶紝涓庝汉宸ュ畬鎴愮殑鏍¢獙鍙e緞涓�鑷�
+ long approvedCount = listByRecordIds(lineIds, record.getRecordType()).stream()
+ .filter(item -> ReviewStatusEnum.APPROVED.getCode().equals(item.getApprovalStatus()))
+ .count();
+ if (approvedCount < lineIds.size()) {
+ return;
+ }
+ // 鏉′欢鏇存柊锛屽彧鏈夈�屽凡纭銆嶈兘鎺ㄨ繘锛涘凡浣滃簾/宸插畬鎴愮殑璁㈠崟涓嶅姩
+ outsourcingOrderMapper.update(null, Wrappers.<OutsourcingOrder>lambdaUpdate()
+ .eq(OutsourcingOrder::getId, orderId)
+ .eq(OutsourcingOrder::getStatus, OutsourcingOrderStatusEnum.CONFIRMED.getCode())
+ .set(OutsourcingOrder::getStatus, OutsourcingOrderStatusEnum.COMPLETED.getCode()));
+ }
+
+ /**
+ * 閿�鍞被娌瑰搧鍑哄簱鎵e噺搴撳瓨銆傚嚭搴撴暟閲忔槸鏈瑁呰溅鎬婚噺锛岃溅涓婁笂娆″墿鐨勬补鏈缁х画鐢紝
+ * 鎵�浠ュ彧浠庡簱瀛樿ˉ瓒炽�屽嚭搴撴暟閲� 鈭� 涓婃鍓╀綑娌归噺銆嶇殑宸銆�
+ * updateSubtractStockInventory 鑷甫 qualitity >= 鏁伴噺 鐨勫畧鍗紝褰卞搷琛屾暟涓� 0 鍗冲簱瀛樹笉瓒筹紝
+ * 鎶涢敊鐢卞灞備簨鍔″洖婊�
+ */
+ private void deductSaleOilOutStock(StockOutRecord stockOutRecord) {
+ String suffix = ",鍑哄簱鎵规:" + stockOutRecord.getOutboundBatches();
+ if (StringUtils.isEmpty(stockOutRecord.getBatchNo())) {
+ throw new BaseException("閿�鍞被鍑哄簱蹇呴』閫夋嫨鍑哄簱鎵规" + suffix);
+ }
+ BigDecimal quantity = stockOutRecord.getStockOutNum();
+ if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
+ throw new BaseException("閿�鍞被鍑哄簱鏁伴噺蹇呴』澶т簬0" + suffix);
+ }
+ BigDecimal lastResidual = getLastResidualOil(stockOutRecord.getVehicleId(), stockOutRecord.getProductModelId(), stockOutRecord.getId());
+ if (lastResidual.compareTo(quantity) > 0) {
+ throw new BaseException("鍑哄簱鏁伴噺涓嶈兘灏忎簬璇ヨ溅涓婃鍓╀綑娌归噺" + toPlain(lastResidual) + suffix);
+ }
+ BigDecimal deduct = quantity.subtract(lastResidual);
+ if (deduct.compareTo(BigDecimal.ZERO) > 0) {
+ StockInventoryDto stockInventoryDto = new StockInventoryDto();
+ stockInventoryDto.setProductModelId(stockOutRecord.getProductModelId());
+ stockInventoryDto.setBatchNo(stockOutRecord.getBatchNo());
+ stockInventoryDto.setQualitity(deduct);
+ if (stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto) == 0) {
+ throw new BaseException("搴撳瓨涓嶈冻鏃犳硶鍑哄簱" + suffix);
+ }
+ }
+ // 杞︿笂鍓╂补鍒氬ソ澶燂紙deduct=0锛夋椂涓嶆秹鍙婂簱瀛樻洿鏂帮紝鍚屾牱钀藉簱渚夸簬鍒犻櫎鏃舵寜瀹為檯鎵e噺閲忓綊杩�
+ stockOutRecord.setDeductQuantity(deduct);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int batchReAudit(List<Long> ids) {
+ if (CollectionUtils.isEmpty(ids)) {
+ throw new BaseException("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+ }
+ for (Long id : ids) {
+ StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
+ if (stockOutRecord == null) {
+ throw new BaseException("鍑哄簱璁板綍涓嶅瓨鍦�,鏃犳硶閲嶆柊瀹℃牳!!!");
+ }
+ if (!ReviewStatusEnum.REJECTED.getCode().equals(stockOutRecord.getApprovalStatus())) {
+ throw new BaseException("鍙湁椹冲洖鐘舵�佺殑璁板綍鎵嶈兘閲嶆柊瀹℃牳,鍑哄簱鎵规:" + stockOutRecord.getOutboundBatches());
+ }
+ stockOutRecord.setApprovalStatus(ReviewStatusEnum.PENDING_REVIEW.getCode());
+ stockOutRecordMapper.updateById(stockOutRecord);
+ }
+ return ids.size();
+ }
+
+ @Override
+ public int updateResidualOil(Long id, BigDecimal residualOil) {
+ StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
+ if (stockOutRecord == null) {
+ throw new BaseException("璇ュ嚭搴撹褰曚笉瀛樺湪,鏃犳硶鏇存柊!!!");
+ }
+ if (residualOil == null || residualOil.compareTo(BigDecimal.ZERO) < 0) {
+ throw new BaseException("鍓╀綑娌归噺涓嶈兘涓虹┖涓斾笉鑳藉皬浜�0");
+ }
+ if (stockOutRecord.getStockOutNum() != null && residualOil.compareTo(stockOutRecord.getStockOutNum()) > 0) {
+ throw new BaseException("鍓╀綑娌归噺涓嶈兘澶т簬鍑哄簱鏁伴噺" + toPlain(stockOutRecord.getStockOutNum()));
+ }
+ StockOutRecord update = new StockOutRecord();
+ update.setId(id);
+ update.setResidualOil(residualOil);
+ return stockOutRecordMapper.updateById(update);
+ }
+
+ private StockInventory getStockInventory(Long productModelId, String batchNo) {
+ LambdaQueryWrapper<StockInventory> eq = new LambdaQueryWrapper<>();
+ eq.eq(StockInventory::getProductModelId, productModelId);
+ if (StringUtils.isEmpty(batchNo)) {
+ eq.isNull(StockInventory::getBatchNo);
+ } else {
+ eq.eq(StockInventory::getBatchNo, batchNo);
+ }
+ return stockInventoryMapper.selectOne(eq);
+ }
+
+ private StockUninventory getStockUninventory(Long productModelId, String batchNo) {
+ LambdaQueryWrapper<StockUninventory> eq = new LambdaQueryWrapper<>();
+ eq.eq(StockUninventory::getProductModelId, productModelId);
+ if (StringUtils.isEmpty(batchNo)) {
+ eq.isNull(StockUninventory::getBatchNo);
+ } else {
+ eq.eq(StockUninventory::getBatchNo, batchNo);
+ }
+ return stockUninventoryMapper.selectOne(eq);
+ }
+
+ /**
+ * 杞﹁締鍥炲~锛氬墠绔彲浠ョ洿鎺ヤ紶 vehicleId锛屼篃鍙互鍙紶杞︾墝鍙凤紝
+ * 鍚庤�呮寜杞﹁締涓绘暟鎹弽鏌ュ洖濉�備袱鑰呴兘鎷夸笉鍒板氨鏃犳硶瀹氫綅銆屼笂娆″墿浣欐补閲忋�嶏紝鐩存帴鎶ラ敊
+ */
+ private void resolveVehicle(StockOutRecordDto stockOutRecordDto) {
+ if (stockOutRecordDto.getVehicleId() != null) {
+ return;
+ }
+ if (StringUtils.isEmpty(stockOutRecordDto.getTruckPlateNo())) {
+ throw new BaseException("閿�鍞被鍑哄簱蹇呴』閫夋嫨杞﹁締");
+ }
+ LambdaQueryWrapper<Vehicle> wrapper = new LambdaQueryWrapper<Vehicle>()
+ .eq(Vehicle::getPlateNumber, stockOutRecordDto.getTruckPlateNo());
+ Vehicle vehicle = vehicleService.getOne(wrapper, false);
+ if (vehicle == null) {
+ throw new BaseException("杞︾墝鍙� " + stockOutRecordDto.getTruckPlateNo() + " 涓嶅湪杞﹁締绠$悊涓紝璇峰厛鍒拌溅杈嗙鐞嗘坊鍔�");
+ }
+ stockOutRecordDto.setVehicleId(vehicle.getId());
+ }
+
+ /**
+ * 鍑哄簱鏁伴噺鏄湰娆¤杞︽�婚噺锛屽繀椤昏惤鍦ㄣ�屼笂娆″墿浣欐补閲� ~ 涓婃鍓╀綑娌归噺 + 搴撳瓨銆嶅尯闂村唴
+ */
+ private void checkSaleOutAvailable(StockOutRecordDto stockOutRecordDto) {
+ String suffix = ",鍑哄簱鎵规:" + stockOutRecordDto.getOutboundBatches();
+ BigDecimal quantity = stockOutRecordDto.getStockOutNum();
+ if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
+ throw new BaseException("閿�鍞被鍑哄簱鏁伴噺蹇呴』澶т簬0" + suffix);
+ }
+ BigDecimal lastResidual = getLastResidualOil(stockOutRecordDto.getVehicleId(), stockOutRecordDto.getProductModelId(), null);
+ if (lastResidual.compareTo(quantity) > 0) {
+ throw new BaseException("鍑哄簱鏁伴噺涓嶈兘灏忎簬璇ヨ溅涓婃鍓╀綑娌归噺" + toPlain(lastResidual) + suffix);
+ }
+ BigDecimal stockQuantity = getStockQuantity(stockOutRecordDto.getProductModelId(), stockOutRecordDto.getBatchNo());
+ BigDecimal availableQty = lastResidual.add(stockQuantity);
+ if (quantity.compareTo(availableQty) > 0) {
+ throw new BaseException("鍑哄簱鏁伴噺瓒呭嚭鍙敤閲�(涓婃鍓╀綑" + toPlain(lastResidual)
+ + ",搴撳瓨" + toPlain(stockQuantity) + ",鍙敤" + toPlain(availableQty) + ")" + suffix);
+ }
+ }
+
+ /**
+ * 璇ヨ溅璇ヨ鏍间笂娆¢�佸畬璐у悗鍓╀綑鐨勬补閲忥紝鍙栨渶杩戜竴鏉″~杩囨畫娌逛笖宸插鎵圭殑璁板綍銆�
+ * excludeId 鐢ㄤ簬鎺掗櫎銆屾湰娆¤瀹℃壒鐨勮繖鏉¤嚜宸便�嶁�斺�斿畠鑷繁鐨� residual_oil 鏄�佸畬涔嬪悗鐨勫�硷紝涓嶈兘鐢ㄦ潵绠楁湰娆℃墸鍑�
+ */
+ private BigDecimal getLastResidualOil(Long vehicleId, Long productModelId, Long excludeId) {
+ if (vehicleId == null || productModelId == null) {
+ return BigDecimal.ZERO;
+ }
+ LambdaQueryWrapper<StockOutRecord> wrapper = new LambdaQueryWrapper<StockOutRecord>()
+ .eq(StockOutRecord::getVehicleId, vehicleId)
+ .eq(StockOutRecord::getProductModelId, productModelId)
+ .isNotNull(StockOutRecord::getResidualOil)
+ .eq(StockOutRecord::getApprovalStatus, ReviewStatusEnum.APPROVED.getCode());
+ if (excludeId != null) {
+ wrapper.lt(StockOutRecord::getId, excludeId);
+ }
+ wrapper.orderByDesc(StockOutRecord::getId).last("limit 1");
+ StockOutRecord last = stockOutRecordMapper.selectOne(wrapper);
+ return last == null || last.getResidualOil() == null ? BigDecimal.ZERO : last.getResidualOil();
+ }
+
+ /**
+ * 褰撳墠搴撳瓨閲忥紝鎸夎鏍煎悎璁★紱浼犱簡鎵规鍙峰啀鍙犲姞鎵规鏉′欢
+ */
+ private BigDecimal getStockQuantity(Long productModelId, String batchNo) {
+ if (productModelId == null) {
+ return BigDecimal.ZERO;
+ }
+ LambdaQueryWrapper<StockInventory> wrapper = new LambdaQueryWrapper<StockInventory>()
+ .eq(StockInventory::getProductModelId, productModelId);
+ if (!StringUtils.isEmpty(batchNo)) {
+ wrapper.eq(StockInventory::getBatchNo, batchNo);
+ }
+ return stockInventoryMapper.selectList(wrapper).stream()
+ .map(StockInventory::getQualitity)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ }
+
+ @Override
+ public OilOutAvailableDto getOilOutAvailableQty(StockOutRecordDto query) {
+ if (query == null || query.getVehicleId() == null || query.getProductModelId() == null) {
+ throw new BaseException("璇峰厛閫夋嫨杞﹁締鍜屼骇鍝佽鏍�");
+ }
+ BigDecimal lastResidualOil = getLastResidualOil(query.getVehicleId(), query.getProductModelId(), query.getId());
+ BigDecimal stockQuantity = getStockQuantity(query.getProductModelId(), query.getBatchNo());
+ OilOutAvailableDto result = new OilOutAvailableDto();
+ result.setLastResidualOil(lastResidualOil);
+ result.setStockQuantity(stockQuantity);
+ result.setAvailableQty(lastResidualOil.add(stockQuantity));
+ return result;
+ }
+
+ private String toPlain(BigDecimal value) {
+ return value == null ? "0" : value.stripTrailingZeros().toPlainString();
+ }
+
+ @Override
+ public List<StockOutRecord> listByRecordIds(List<Long> recordIds, String recordType) {
+ if (CollectionUtils.isEmpty(recordIds) || StringUtils.isEmpty(recordType)) {
+ return Collections.emptyList();
+ }
+ return stockOutRecordMapper.selectByRecordIds(recordIds, recordType);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int releaseByRecordIds(List<Long> recordIds, String recordType) {
+ List<StockOutRecord> records = listByRecordIds(recordIds, recordType);
+ if (records.isEmpty()) {
+ return 0;
+ }
+ for (StockOutRecord record : records) {
+ if (!ReviewStatusEnum.APPROVED.getCode().equals(record.getApprovalStatus())) {
+ continue;
+ }
+ // type=0 褰掕繕鍚堟牸搴撳瓨锛坰tock_inventory锛夛紝type=1 褰掕繕涓嶅悎鏍煎簱瀛橈紙stock_uninventory锛�
+ if ("0".equals(record.getType())) {
+ StockInventoryDto stockInventoryDto = new StockInventoryDto();
+ stockInventoryDto.setProductModelId(record.getProductModelId());
+ stockInventoryDto.setBatchNo(record.getBatchNo());
+ stockInventoryDto.setQualitity(record.getStockOutNum());
+ if (stockInventoryMapper.updateAddStockInventory(stockInventoryDto) == 0) {
+ throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶褰掕繕,鍑哄簱鎵规:" + record.getOutboundBatches());
+ }
+ } else if ("1".equals(record.getType())) {
+ StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
+ stockUninventoryDto.setProductModelId(record.getProductModelId());
+ stockUninventoryDto.setBatchNo(record.getBatchNo());
+ stockUninventoryDto.setQualitity(record.getStockOutNum());
+ if (stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto) == 0) {
+ throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶褰掕繕,鍑哄簱鎵规:" + record.getOutboundBatches());
+ }
+ } else {
+ throw new BaseException("鍑哄簱璁板綍绫诲瀷寮傚父锛屾棤娉曞綊杩樺簱瀛�,鍑哄簱鎵规:" + record.getOutboundBatches());
+ }
+ }
+ return stockOutRecordMapper.deleteBatchIds(records.stream().map(StockOutRecord::getId).toList());
+ }
}
--
Gitblit v1.9.3