From 6d3a76f894052209cad136ec9bff6ddcd43fc4e7 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期一, 20 四月 2026 17:55:48 +0800
Subject: [PATCH] feat: 扫码时做限制,若采购台账已全部质检入库,APP扫码 入库时提示已入库。并且联动质检
---
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java | 256 +++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 229 insertions(+), 27 deletions(-)
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
index ba32270..2afc5dc 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -6,7 +6,10 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.mapper.ProductModelMapper;
+import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.procurementrecord.utils.StockUtils;
@@ -14,7 +17,9 @@
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.pojo.*;
import com.ruoyi.production.service.impl.ProductOrderServiceImpl;
+import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.pojo.QualityInspect;
@@ -28,6 +33,9 @@
import com.ruoyi.sales.service.ISalesLedgerProductProcessBindService;
import com.ruoyi.sales.service.ISalesLedgerProductService;
import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.mapper.StockInRecordMapper;
+import com.ruoyi.stock.dto.StockInventoryDto;
+import com.ruoyi.stock.pojo.StockInRecord;
import com.ruoyi.stock.pojo.StockInventory;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
@@ -61,6 +69,7 @@
private SalesLedgerMapper salesLedgerMapper;
private PurchaseLedgerMapper purchaseLedgerMapper;
+ private PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
private ProductOrderMapper productOrderMapper;
@@ -72,6 +81,7 @@
private ProcessRouteMapper processRouteMapper;
private ProductProcessRouteMapper productProcessRouteMapper;
+ private ProductModelMapper productModelMapper;
private ProductWorkOrderMapper productWorkOrderMapper;
private ProductionProductMainMapper productionProductMainMapper;
@@ -82,6 +92,8 @@
private ShippingInfoServiceImpl shippingInfoService;
private StockUtils stockUtils;
+
+ private StockInRecordMapper stockInRecordMapper;
private final ISalesLedgerProductProcessBindService salesLedgerProductProcessBindService;
@@ -94,7 +106,11 @@
@Override
public SalesLedgerProduct selectSalesLedgerProductById(Long id) {
- return salesLedgerProductMapper.selectById(id);
+ SalesLedgerProduct row = salesLedgerProductMapper.selectById(id);
+ if (row != null) {
+ row.fillRemainingQuantity();
+ }
+ return row;
}
@Override
@@ -103,50 +119,112 @@
// queryWrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerProduct.getSalesLedgerId())
// .eq(SalesLedgerProduct::getType, salesLedgerProduct.getType());
List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectSalesLedgerProductList(salesLedgerProduct);
- if (!CollectionUtils.isEmpty(salesLedgerProducts)) {
- salesLedgerProducts.forEach(item -> {
- // 鍙戣揣淇℃伅
- ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
- .eq(ShippingInfo::getSalesLedgerProductId, item.getId())
- .orderByDesc(ShippingInfo::getCreateTime)
- .last("limit 1"));
- if (shippingInfo != null) {
- item.setShippingDate(shippingInfo.getShippingDate());
- item.setShippingCarNumber(shippingInfo.getShippingCarNumber());
- item.setShippingStatus(shippingInfo.getStatus());
- item.setExpressCompany(shippingInfo.getExpressCompany());
- item.setExpressNumber(shippingInfo.getExpressNumber());
- }
- });
- // 寮�绁�
+ if (CollectionUtils.isEmpty(salesLedgerProducts)) {
+ return salesLedgerProducts;
+ }
+
+ salesLedgerProducts.forEach(item -> {
+ ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
+ .eq(ShippingInfo::getSalesLedgerProductId, item.getId())
+ .orderByDesc(ShippingInfo::getCreateTime)
+ .last("limit 1"));
+ if (shippingInfo != null) {
+ item.setShippingDate(shippingInfo.getShippingDate());
+ item.setShippingCarNumber(shippingInfo.getShippingCarNumber());
+ item.setShippingStatus(shippingInfo.getStatus());
+ item.setExpressCompany(shippingInfo.getExpressCompany());
+ item.setExpressNumber(shippingInfo.getExpressNumber());
+ }
+ });
+
+ if (salesLedgerProduct.getSalesLedgerId() != null) {
InvoiceRegistrationProductDto invoiceRegistrationProductDto = new InvoiceRegistrationProductDto();
invoiceRegistrationProductDto.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId().intValue());
List<InvoiceRegistrationProductDto> invoiceRegistrationProductDtoList = invoiceRegistrationProductMapper.invoiceRegistrationProductList(invoiceRegistrationProductDto);
- // 缁熻寮�绁ㄧ櫥璁颁骇鍝佺殑宸插紑绁ㄦ暟/宸插紑绁ㄩ噾棰�
if (!CollectionUtils.isEmpty(invoiceRegistrationProductDtoList)) {
for (SalesLedgerProduct ledgerProduct : salesLedgerProducts) {
BigDecimal invoiceNum = BigDecimal.ZERO;
BigDecimal invoiceAmount = BigDecimal.ZERO;
- BigDecimal noInvoiceNum = BigDecimal.ZERO;
- BigDecimal noInvoiceAmount = BigDecimal.ZERO;
for (InvoiceRegistrationProductDto registrationProductDto : invoiceRegistrationProductDtoList) {
if (ledgerProduct.getId().intValue() == registrationProductDto.getSalesLedgerProductId()) {
invoiceNum = invoiceNum.add(registrationProductDto.getInvoiceNum());
invoiceAmount = invoiceAmount.add(registrationProductDto.getInvoiceAmount());
}
}
- noInvoiceNum = ledgerProduct.getQuantity().subtract(invoiceNum);
- noInvoiceAmount = ledgerProduct.getTaxInclusiveTotalPrice().subtract(invoiceAmount);
+ BigDecimal ledgerQuantity = ledgerProduct.getQuantity() == null ? BigDecimal.ZERO : ledgerProduct.getQuantity();
+ BigDecimal ledgerTotalPrice = ledgerProduct.getTaxInclusiveTotalPrice() == null ? BigDecimal.ZERO : ledgerProduct.getTaxInclusiveTotalPrice();
ledgerProduct.setInvoiceNum(invoiceNum);
ledgerProduct.setInvoiceAmount(invoiceAmount);
- ledgerProduct.setNoInvoiceNum(noInvoiceNum);
- ledgerProduct.setNoInvoiceAmount(noInvoiceAmount);
-
-
+ ledgerProduct.setNoInvoiceNum(ledgerQuantity.subtract(invoiceNum));
+ ledgerProduct.setNoInvoiceAmount(ledgerTotalPrice.subtract(invoiceAmount));
}
}
-
}
+
+ List<Long> productIds = salesLedgerProducts.stream()
+ .map(SalesLedgerProduct::getId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ Map<Long, BigDecimal> returnOrderGroupDtoMap = Collections.emptyMap();
+ if (!CollectionUtils.isEmpty(productIds)) {
+ List<SimpleReturnOrderGroupDto> groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds);
+ if (!CollectionUtils.isEmpty(groupListByProductIds)) {
+ returnOrderGroupDtoMap = groupListByProductIds.stream()
+ .collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId,
+ SimpleReturnOrderGroupDto::getSumReturnQuantity,
+ BigDecimal::add));
+ }
+ }
+
+ List<Long> productModelIds = salesLedgerProducts.stream()
+ .map(SalesLedgerProduct::getProductModelId)
+ .filter(Objects::nonNull)
+ .distinct()
+ .collect(Collectors.toList());
+ Map<Long, ProductModel> productModelMap = Collections.emptyMap();
+ if (!CollectionUtils.isEmpty(productModelIds)) {
+ List<ProductModel> productModels = productModelMapper.selectBatchIds(productModelIds);
+ if (!CollectionUtils.isEmpty(productModels)) {
+ productModelMap = productModels.stream()
+ .collect(Collectors.toMap(ProductModel::getId, Function.identity()));
+ }
+ }
+
+ Map<Long, BigDecimal> finalReturnOrderGroupDtoMap = returnOrderGroupDtoMap;
+ Map<Long, ProductModel> finalProductModelMap = productModelMap;
+ salesLedgerProducts.forEach(item -> {
+ if (item.getFutureTickets() == null || item.getFutureTickets().compareTo(BigDecimal.ZERO) == 0) {
+ item.setFutureTickets(BigDecimal.ZERO);
+ }
+ if (item.getFutureTicketsAmount() == null || item.getFutureTicketsAmount().compareTo(BigDecimal.ZERO) == 0) {
+ item.setFutureTicketsAmount(BigDecimal.ZERO);
+ }
+ BigDecimal returnQuality = finalReturnOrderGroupDtoMap.getOrDefault(item.getId(), BigDecimal.ZERO);
+ item.setReturnQuality(returnQuality);
+ BigDecimal quantity = item.getQuantity() == null ? BigDecimal.ZERO : item.getQuantity();
+ BigDecimal shipped = item.getShippedQuantity() == null ? BigDecimal.ZERO : item.getShippedQuantity();
+ BigDecimal available = quantity.subtract(returnQuality).subtract(shipped);
+ item.setAvailableQuality(available.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : available);
+ item.fillRemainingQuantity();
+ if (item.getApproveStatus() == null || item.getApproveStatus() != 2) {
+ BigDecimal remainingShipped = item.getRemainingShippedQuantity() == null ? BigDecimal.ZERO : item.getRemainingShippedQuantity();
+ boolean hasOutbound = shipped.compareTo(BigDecimal.ZERO) > 0;
+ if (hasOutbound && remainingShipped.compareTo(BigDecimal.ZERO) <= 0) {
+ item.setApproveStatus(0);
+ } else {
+ Integer hasSufficientStock = item.getHasSufficientStock();
+ if (hasSufficientStock != null && hasSufficientStock == 0) {
+ item.setApproveStatus(0);
+ } else {
+ item.setApproveStatus(1);
+ }
+ }
+ }
+ ProductModel productModel = finalProductModelMap.get(item.getProductModelId());
+ if (productModel != null) {
+ item.setThickness(productModel.getThickness());
+ }
+ });
return salesLedgerProducts;
}
@@ -216,14 +294,38 @@
int result;
Long salesLedgerId = salesLedgerProduct.getSalesLedgerId();
+ salesLedgerProduct.fillRemainingQuantity();
if (salesLedgerProduct.getId() == null) {
salesLedgerProduct.setRegisterDate(LocalDateTime.now());
result = salesLedgerProductMapper.insert(salesLedgerProduct);
addProductionData(salesLedgerProduct);
} else {
+ SalesLedgerProduct dbBefore = salesLedgerProductMapper.selectById(salesLedgerProduct.getId());
+ if (dbBefore == null) {
+ throw new RuntimeException("閿�鍞骇鍝佷笉瀛樺湪锛屾棤娉曠紪杈�");
+ }
+ // 涓嶈兘鎶婅鍗曟暟閲忔敼鍒板皬浜庡凡鍙戣揣鏁伴噺锛屽惁鍒欒处瀹炰笉涓�鑷�
+ BigDecimal shipped = dbBefore.getShippedQuantity() == null ? BigDecimal.ZERO : dbBefore.getShippedQuantity();
+ BigDecimal newOrderQty = salesLedgerProduct.getQuantity() == null ? BigDecimal.ZERO : salesLedgerProduct.getQuantity();
+ if (newOrderQty.compareTo(shipped) < 0) {
+ throw new RuntimeException("缂栬緫澶辫触,璁㈠崟鏁伴噺涓嶈兘灏忎簬宸插彂璐ф暟閲�");
+ }
//鏌ヨ鍘熸湰鐨勪骇鍝佸瀷鍙穒d
salesLedgerProduct.setFutureTickets(salesLedgerProduct.getQuantity());
result = salesLedgerProductMapper.updateById(salesLedgerProduct);
+
+ // 鍏佽鈥滃鍏ュ簱鈥濓細褰撹鍗曟暟閲忚涓嬭皟鏃讹紝鍙洖閫�鈥滀笅璋冨樊棰濃�濆搴旂殑鍏ュ簱鏁伴噺
+ // 渚嬶細鍘熻鍗�100锛屽凡鍏ュ簱120锛涙敼涓�50 -> 鍙洖閫�50锛屾渶缁堝凡鍏ュ簱70锛堜笉寮哄帇鍒�50锛�
+ BigDecimal oldOrderQty = dbBefore.getQuantity() == null ? BigDecimal.ZERO : dbBefore.getQuantity();
+ BigDecimal stocked = dbBefore.getStockedQuantity() == null ? BigDecimal.ZERO : dbBefore.getStockedQuantity();
+ BigDecimal reduced = oldOrderQty.subtract(newOrderQty);
+ if (reduced.compareTo(BigDecimal.ZERO) > 0) {
+ BigDecimal rollbackQty = stocked.min(reduced);
+ if (rollbackQty.compareTo(BigDecimal.ZERO) > 0) {
+ rollbackExcessStockIn(dbBefore, rollbackQty);
+ }
+ }
+
/*鍒犻櫎瀵瑰簲鐨勭敓浜ф暟鎹苟閲嶆柊鏂板*/
deleteProductionData(Arrays.asList(salesLedgerProduct.getId()));
// 鍒犻櫎鐢熶骇鏍哥畻鏁版嵁
@@ -260,8 +362,106 @@
// 娓呯┖閿�鍞骇鍝佺粦瀹氱殑鍔犲伐
salesLedgerProductProcessBindService.updateProductProcessBind(salesLedgerProduct.getSalesProductProcessList(), salesLedgerProduct.getId());
+
+ // 鏂板/缂栬緫浜у搧鍚庯紝鍒锋柊閿�鍞富鍗曞叆搴撶姸鎬侊紙閬垮厤鍥犳柊澧炴湭鍏ュ簱琛屽鑷寸姸鎬佷笉鍑嗭級
+ refreshSalesLedgerStockStatus(salesLedgerId);
}
return result;
+ }
+
+ private void rollbackExcessStockIn(SalesLedgerProduct dbBefore, BigDecimal rollbackQtyTotal) {
+ if (dbBefore == null || rollbackQtyTotal == null || rollbackQtyTotal.compareTo(BigDecimal.ZERO) <= 0) {
+ return;
+ }
+ if (dbBefore.getProductModelId() == null) {
+ throw new RuntimeException("鍥為��鍏ュ簱澶辫触,浜у搧瑙勬牸鏈淮鎶�");
+ }
+ Long productId = dbBefore.getId();
+ // 鍊掑簭鍥為��锛氫紭鍏堝洖閫�鈥滄壂鐮佸叆搴撯�濓紝鍐嶅洖閫�鈥滄墜鍔ㄥ叆搴撯��
+ List<String> recordTypes = Arrays.asList(
+ StockInQualifiedRecordTypeEnum.SALE_SCAN_STOCK_IN.getCode(),
+ StockInQualifiedRecordTypeEnum.SALE_STOCK_IN.getCode()
+ );
+ List<StockInRecord> records = stockInRecordMapper.selectList(new LambdaQueryWrapper<StockInRecord>()
+ .eq(StockInRecord::getSalesLedgerProductId, productId)
+ .eq(StockInRecord::getType, "0")
+ .in(StockInRecord::getRecordType, recordTypes)
+ .orderByDesc(StockInRecord::getCreateTime));
+ BigDecimal remaining = rollbackQtyTotal;
+ for (StockInRecord r : records) {
+ if (remaining.compareTo(BigDecimal.ZERO) <= 0) {
+ break;
+ }
+ BigDecimal inNum = r.getStockInNum() == null ? BigDecimal.ZERO : r.getStockInNum();
+ if (inNum.compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ BigDecimal rollbackQty = inNum.min(remaining);
+
+ StockInventoryDto stockInventoryDto = new StockInventoryDto();
+ stockInventoryDto.setProductModelId(dbBefore.getProductModelId());
+ stockInventoryDto.setQualitity(rollbackQty);
+ int affectRows = stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
+ if (affectRows <= 0) {
+ throw new RuntimeException("鍥為��鍏ュ簱澶辫触,褰撳墠搴撳瓨涓嶈冻,鏃犳硶鎵e洖瓒呭叆搴撴暟閲�");
+ }
+
+ BigDecimal newInNum = inNum.subtract(rollbackQty);
+ if (newInNum.compareTo(BigDecimal.ZERO) <= 0) {
+ stockInRecordMapper.deleteById(r.getId());
+ } else {
+ r.setStockInNum(newInNum);
+ stockInRecordMapper.updateById(r);
+ }
+ remaining = remaining.subtract(rollbackQty);
+ }
+ if (remaining.compareTo(BigDecimal.ZERO) > 0) {
+ throw new RuntimeException("鍥為��鍏ュ簱澶辫触,鏈壘鍒拌冻澶熺殑鍏ュ簱璁板綍鐢ㄤ簬鎵e洖瓒呭叆搴撴暟閲�");
+ }
+
+ // 鍥炲啓浜у搧琛屽凡鍏ュ簱鏁伴噺涓庣姸鎬�
+ SalesLedgerProduct fresh = salesLedgerProductMapper.selectById(dbBefore.getId());
+ if (fresh == null) {
+ return;
+ }
+ BigDecimal newStocked = (fresh.getStockedQuantity() == null ? BigDecimal.ZERO : fresh.getStockedQuantity()).subtract(rollbackQtyTotal);
+ if (newStocked.compareTo(BigDecimal.ZERO) < 0) {
+ newStocked = BigDecimal.ZERO;
+ }
+ BigDecimal orderQty = fresh.getQuantity() == null ? BigDecimal.ZERO : fresh.getQuantity();
+ int stockStatus;
+ if (newStocked.compareTo(BigDecimal.ZERO) <= 0) stockStatus = 0;
+ else if (orderQty.compareTo(BigDecimal.ZERO) > 0 && newStocked.compareTo(orderQty) < 0) stockStatus = 1;
+ else stockStatus = 2;
+ fresh.setStockedQuantity(newStocked);
+ fresh.setProductStockStatus(stockStatus);
+ fresh.fillRemainingQuantity();
+ salesLedgerProductMapper.updateById(fresh);
+ }
+
+ private void refreshSalesLedgerStockStatus(Long salesLedgerId) {
+ if (salesLedgerId == null) {
+ return;
+ }
+ SalesLedger ledger = salesLedgerMapper.selectById(salesLedgerId);
+ if (ledger == null) {
+ return;
+ }
+ List<SalesLedgerProduct> allProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+ .eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId)
+ .eq(SalesLedgerProduct::getType, 1));
+ if (CollectionUtils.isEmpty(allProducts)) {
+ ledger.setStockStatus(0);
+ salesLedgerMapper.updateById(ledger);
+ return;
+ }
+ boolean anyInbound = allProducts.stream().anyMatch(p -> {
+ BigDecimal sq = p.getStockedQuantity();
+ return sq != null && sq.compareTo(BigDecimal.ZERO) > 0;
+ });
+ boolean allFull = allProducts.stream().allMatch(p -> Objects.equals(p.getProductStockStatus(), 2));
+ ledger.setStockStatus(allFull ? 2 : (anyInbound ? 1 : 0));
+ salesLedgerMapper.updateById(ledger);
}
/**
@@ -438,6 +638,7 @@
} else {
item.setStatusName("鏈畬鎴愪粯娆�");
}
+ item.fillRemainingQuantity();
});
return salesLedgerProductDtoIPage;
}
@@ -452,6 +653,7 @@
} else {
item.setStatusName("鏈畬鎴愪粯娆�");
}
+ item.fillRemainingQuantity();
});
return salesLedgerProductDtoIPage;
}
--
Gitblit v1.9.3