From 4f39e676277d7a66e13d172288032ce16bb18e8c Mon Sep 17 00:00:00 2001
From: zss <zss@example.com>
Date: 星期三, 22 四月 2026 17:05:30 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_河南_鹤壁天沐钢化玻璃厂' into dev_河南_鹤壁天沐钢化玻璃厂
---
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java | 2347 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 2,131 insertions(+), 216 deletions(-)
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index 570b2f5..c9e8734 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -4,17 +4,30 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+
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.service.AccountIncomeService;
+import com.ruoyi.approve.service.IApproveProcessService;
+import com.ruoyi.approve.vo.ApproveProcessVO;
+import com.ruoyi.approve.pojo.ApproveProcess;
+import com.ruoyi.common.enums.ApproveTypeEnum;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.mapper.ProductMapper;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.pojo.Customer;
+import com.ruoyi.basic.pojo.CustomerRegions;
+import com.ruoyi.basic.pojo.Product;
+import com.ruoyi.basic.pojo.ProductModel;
+import com.ruoyi.basic.service.ICustomerRegionsService;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.enums.SaleEnum;
+import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutUnQualifiedRecordTypeEnum;
+import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.EnumUtil;
@@ -22,22 +35,35 @@
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import com.ruoyi.production.mapper.*;
+import com.ruoyi.production.pojo.ProcessRoute;
+import com.ruoyi.production.pojo.ProcessRouteItem;
import com.ruoyi.production.service.ProductionProductMainService;
-import com.ruoyi.project.system.domain.SysDept;
+
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysDeptMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.sales.dto.*;
import com.ruoyi.sales.mapper.*;
import com.ruoyi.sales.pojo.*;
+import com.ruoyi.sales.service.ISalesLedgerProcessRouteService;
+import com.ruoyi.sales.service.ISalesLedgerProductProcessBindService;
+import com.ruoyi.sales.service.ISalesLedgerProductProcessService;
import com.ruoyi.sales.service.ISalesLedgerService;
+import com.ruoyi.stock.dto.StockInventoryDto;
+import com.ruoyi.stock.mapper.StockInRecordMapper;
+import com.ruoyi.stock.mapper.StockOutRecordMapper;
+import com.ruoyi.stock.pojo.StockInRecord;
+import com.ruoyi.stock.pojo.StockOutRecord;
+import com.ruoyi.stock.service.StockInRecordService;
+import com.ruoyi.stock.service.StockInventoryService;
+import com.ruoyi.stock.service.StockOutRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
@@ -62,6 +88,7 @@
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
@@ -82,6 +109,9 @@
private static final String LOCK_PREFIX = "contract_no_lock:";
private static final long LOCK_WAIT_TIMEOUT = 10; // 閿佺瓑寰呰秴鏃舵椂闂达紙绉掞級
private static final long LOCK_EXPIRE_TIME = 30; // 閿佽嚜鍔ㄨ繃鏈熸椂闂达紙绉掞級
+ private static final int INBOUND_BIZ_TYPE_WEB = 1;
+ private static final int INBOUND_BIZ_TYPE_SCAN_QUALIFIED = 2;
+ private static final int INBOUND_BIZ_TYPE_SCAN_UNQUALIFIED = 3;
private final AccountIncomeService accountIncomeService;
private final SalesLedgerMapper salesLedgerMapper;
private final CustomerMapper customerMapper;
@@ -110,6 +140,22 @@
private final ProductionProductInputMapper productionProductInputMapper;
private final QualityInspectMapper qualityInspectMapper;
private final RedisTemplate<String, String> redisTemplate;
+
+ private final ISalesLedgerProductProcessService salesLedgerProductProcessService;
+
+ private final ISalesLedgerProductProcessBindService salesLedgerProductProcessBindService;
+
+ private final ISalesLedgerProcessRouteService salesLedgerProcessRouteService;
+
+ private final StockInventoryService stockInventoryService;
+ private final StockInRecordMapper stockInRecordMapper;
+ private final StockOutRecordMapper stockOutRecordMapper;
+ private final StockInRecordService stockInRecordService;
+ private final StockOutRecordService stockOutRecordService;
+ private final StockUtils stockUtils;
+ @Autowired
+ private IApproveProcessService approveProcessService;
+
@Autowired
private SysDeptMapper sysDeptMapper;
@Value("${file.upload-dir}")
@@ -128,6 +174,8 @@
;
@Autowired
private SysUserMapper sysUserMapper;
+
+ private final ICustomerRegionsService customerRegionsService;
@Override
public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) {
@@ -154,7 +202,7 @@
// 鏌ヨ閫�璐т俊鎭�
List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList());
List<SimpleReturnOrderGroupDto> groupListByProductIds = new ArrayList<>();
- if(CollectionUtils.isNotEmpty(productIds)){
+ if (CollectionUtils.isNotEmpty(productIds)) {
groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds);
}
Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, SimpleReturnOrderGroupDto::getSumReturnQuantity));
@@ -180,6 +228,16 @@
productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId());
productWrapper.eq(SalesLedgerProduct::getType, 1);
List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
+ Map<Long, ProductModel> productModelMap = Collections.emptyMap();
+ if (CollectionUtils.isNotEmpty(products)) {
+ List<Long> productModelIds = products.stream().map(SalesLedgerProduct::getProductModelId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+ if (CollectionUtils.isNotEmpty(productModelIds)) {
+ List<ProductModel> productModels = productModelMapper.selectBatchIds(productModelIds);
+ if (CollectionUtils.isNotEmpty(productModels)) {
+ productModelMap = productModels.stream().collect(Collectors.toMap(ProductModel::getId, Function.identity()));
+ }
+ }
+ }
for (SalesLedgerProduct product : products) {
product.setOriginalNoInvoiceNum(product.getNoInvoiceNum());
// 鎻愪緵涓存椂鏈紑绁ㄦ暟锛屾湭寮�绁ㄩ噾棰濅緵鍓嶆璁$畻
@@ -188,19 +246,39 @@
product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
product.setRegisterDate(LocalDateTime.now());
// 鍙戣揣淇℃伅
- ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
- .eq(ShippingInfo::getSalesLedgerProductId, product.getId())
- .orderByDesc(ShippingInfo::getCreateTime)
- .last("limit 1"));
+ ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>().eq(ShippingInfo::getSalesLedgerProductId, product.getId()).orderByDesc(ShippingInfo::getCreateTime).last("limit 1"));
if (shippingInfo != null) {
product.setShippingStatus(shippingInfo.getStatus());
}
+ // 鍔犲伐鏄庣粏锛屽厛鏌ind琛ㄨ幏鍙栬浜у搧鍏宠仈鐨勫伐搴忓強鏁伴噺
+ List<SalesLedgerProductProcessBind> bindList = salesLedgerProductProcessBindService.list(new LambdaQueryWrapper<SalesLedgerProductProcessBind>().eq(SalesLedgerProductProcessBind::getSalesLedgerProductId, product.getId()));
+ if (!bindList.isEmpty()) {
+ List<Integer> processIds = bindList.stream().map(SalesLedgerProductProcessBind::getSalesLedgerProductProcessId).collect(Collectors.toList());
+ Map<Integer, Integer> processQuantityMap = bindList.stream().collect(Collectors.toMap(SalesLedgerProductProcessBind::getSalesLedgerProductProcessId, SalesLedgerProductProcessBind::getQuantity, (a, b) -> a));
+ List<SalesLedgerProductProcess> processList = salesLedgerProductProcessService.listByIds(processIds);
+ processList.forEach(p -> p.setQuantity(processQuantityMap.get(p.getId())));
+ product.setSalesProductProcessList(processList);
+ }
+ ProductModel productModel = productModelMap.get(product.getProductModelId());
+ if (productModel != null) {
+ product.setThickness(productModel.getThickness());
+ }
+ if (product.getWidth() != null && product.getHeight() != null) {
+ BigDecimal pieceArea = product.getWidth().multiply(product.getHeight()).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP);
+ if (product.getActualPieceArea() == null) {
+ product.setActualPieceArea(pieceArea);
+ }
+ BigDecimal quantity = product.getQuantity() == null ? BigDecimal.ZERO : product.getQuantity();
+ if (product.getActualTotalArea() == null) {
+ product.setActualTotalArea(pieceArea.multiply(quantity).setScale(2, RoundingMode.HALF_UP));
+ }
+ }
+ product.fillRemainingQuantity();
}
// 3.鏌ヨ涓婁紶鏂囦欢
LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>();
- salesLedgerFileWrapper.eq(CommonFile::getCommonId, salesLedger.getId())
- .eq(CommonFile::getType, FileNameType.SALE.getValue());
+ salesLedgerFileWrapper.eq(CommonFile::getCommonId, salesLedger.getId()).eq(CommonFile::getType, FileNameType.SALE.getValue());
List<CommonFile> salesLedgerFiles = commonFileMapper.selectList(salesLedgerFileWrapper);
// 4. 杞崲 DTO
@@ -223,11 +301,7 @@
List<Map<String, Object>> result = salesLedgerMapper.selectMaps(queryWrapper);
// 灏嗕笅鍒掔嚎鍛藉悕杞崲涓洪┘宄板懡鍚�
- return result.stream().map(map -> map.entrySet().stream()
- .collect(Collectors.toMap(
- entry -> underlineToCamel(entry.getKey()),
- Map.Entry::getValue))
- ).collect(Collectors.toList());
+ return result.stream().map(map -> map.entrySet().stream().collect(Collectors.toMap(entry -> underlineToCamel(entry.getKey()), Map.Entry::getValue))).collect(Collectors.toList());
}
@Override
@@ -243,10 +317,7 @@
// 鎵ц鏌ヨ骞惰绠楁�诲拰
List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(queryWrapper);
- BigDecimal totalContractAmount = salesLedgers.stream()
- .map(SalesLedger::getContractAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal totalContractAmount = salesLedgers.stream().map(SalesLedger::getContractAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
return totalContractAmount;
}
@@ -255,32 +326,23 @@
public List getTopFiveList() {
// 鏌ヨ鍘熷鏁版嵁
LambdaQueryWrapper<SalesLedger> queryWrapper = Wrappers.lambdaQuery();
- queryWrapper.select(SalesLedger::getCustomerId,
- SalesLedger::getCustomerName,
- SalesLedger::getContractAmount)
- .orderByDesc(SalesLedger::getContractAmount);
+ queryWrapper.select(SalesLedger::getCustomerId, SalesLedger::getCustomerName, SalesLedger::getContractAmount).orderByDesc(SalesLedger::getContractAmount);
List<SalesLedger> records = salesLedgerMapper.selectList(queryWrapper);
// 鎸夊鎴稩D鍒嗙粍骞惰仛鍚堥噾棰�
Map<Long, GroupedCustomer> groupedMap = new LinkedHashMap<>(); // 浣跨敤LinkedHashMap淇濇寔鎺掑簭
for (SalesLedger record : records) {
- groupedMap.computeIfAbsent(record.getCustomerId(),
- k -> new GroupedCustomer(record.getCustomerId(), record.getCustomerName()))
- .addAmount(record.getContractAmount());
+ groupedMap.computeIfAbsent(record.getCustomerId(), k -> new GroupedCustomer(record.getCustomerId(), record.getCustomerName())).addAmount(record.getContractAmount());
}
// 杞崲涓虹粨鏋滃垪琛ㄥ苟鍙栧墠5
- return groupedMap.values().stream()
- .sorted(Comparator.comparing(GroupedCustomer::getTotalAmount).reversed())
- .limit(5)
- .map(customer -> {
- Map<String, Object> result = new HashMap<>();
- result.put("customerId", customer.getCustomerId());
- result.put("customerName", customer.getCustomerName());
- result.put("totalAmount", customer.getTotalAmount());
- return result;
- })
- .collect(Collectors.toList());
+ return groupedMap.values().stream().sorted(Comparator.comparing(GroupedCustomer::getTotalAmount).reversed()).limit(5).map(customer -> {
+ Map<String, Object> result = new HashMap<>();
+ result.put("customerId", customer.getCustomerId());
+ result.put("customerName", customer.getCustomerName());
+ result.put("totalAmount", customer.getTotalAmount());
+ return result;
+ }).collect(Collectors.toList());
}
@Override
@@ -296,31 +358,19 @@
// 鍥炴閲戦
LambdaQueryWrapper<ReceiptPayment> receiptPaymentQuery = new LambdaQueryWrapper<>();
- receiptPaymentQuery
- .ge(ReceiptPayment::getCreateTime, startTime)
- .le(ReceiptPayment::getCreateTime, endTime);
+ receiptPaymentQuery.ge(ReceiptPayment::getCreateTime, startTime).le(ReceiptPayment::getCreateTime, endTime);
- List<ReceiptPayment> receiptPayments =
- receiptPaymentMapper.selectList(receiptPaymentQuery);
+ List<ReceiptPayment> receiptPayments = receiptPaymentMapper.selectList(receiptPaymentQuery);
- BigDecimal receiptAmount = receiptPayments.stream()
- .map(ReceiptPayment::getReceiptPaymentAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal receiptAmount = receiptPayments.stream().map(ReceiptPayment::getReceiptPaymentAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
// 寮�绁ㄩ噾棰�
LambdaQueryWrapper<InvoiceLedger> invoiceLedgerQuery = new LambdaQueryWrapper<>();
- invoiceLedgerQuery
- .ge(InvoiceLedger::getCreateTime, startTime)
- .le(InvoiceLedger::getCreateTime, endTime);
+ invoiceLedgerQuery.ge(InvoiceLedger::getCreateTime, startTime).le(InvoiceLedger::getCreateTime, endTime);
- List<InvoiceLedger> invoiceLedgers =
- invoiceLedgerMapper.selectList(invoiceLedgerQuery);
+ List<InvoiceLedger> invoiceLedgers = invoiceLedgerMapper.selectList(invoiceLedgerQuery);
- BigDecimal invoiceAmount = invoiceLedgers.stream()
- .map(InvoiceLedger::getInvoiceTotal)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal invoiceAmount = invoiceLedgers.stream().map(InvoiceLedger::getInvoiceTotal).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
MonthlyAmountDto dto = new MonthlyAmountDto();
dto.setMonth(yearMonth.format(DateTimeFormatter.ofPattern("yyyy-MM")));
@@ -335,127 +385,314 @@
@Override
public IPage<SalesLedger> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto) {
- return salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto);
+ IPage<SalesLedger> iPage = salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto);
+
+ if (CollectionUtils.isEmpty(iPage.getRecords())) {
+ return iPage;
+ }
+
+ List<Long> salesLedgerIds = iPage.getRecords().stream().map(SalesLedger::getId).collect(Collectors.toList());
+
+ boolean hasWidthHeightFilter = salesLedgerDto.getWidth() != null || salesLedgerDto.getHeight() != null;
+ Map<Long, List<SalesLedgerProduct>> matchedProductsMap = Collections.emptyMap();
+ if (hasWidthHeightFilter) {
+ LambdaQueryWrapper<SalesLedgerProduct> productQueryWrapper = new LambdaQueryWrapper<SalesLedgerProduct>().in(SalesLedgerProduct::getSalesLedgerId, salesLedgerIds).eq(SalesLedgerProduct::getType, 1);
+ if (salesLedgerDto.getWidth() != null) {
+ productQueryWrapper.eq(SalesLedgerProduct::getWidth, salesLedgerDto.getWidth());
+ }
+ if (salesLedgerDto.getHeight() != null) {
+ productQueryWrapper.eq(SalesLedgerProduct::getHeight, salesLedgerDto.getHeight());
+ }
+ List<SalesLedgerProduct> matchedProducts = salesLedgerProductMapper.selectList(productQueryWrapper);
+ matchedProductsMap = CollectionUtils.isEmpty(matchedProducts) ? Collections.emptyMap() : matchedProducts.stream().collect(Collectors.groupingBy(SalesLedgerProduct::getSalesLedgerId));
+ }
+
+ List<SalesLedgerProductTotalsDto> productTotals = salesLedgerProductMapper.selectSalesLedgerProductTotals(salesLedgerIds, 1);
+ Map<Long, SalesLedgerProductTotalsDto> productTotalsMap = CollectionUtils.isEmpty(productTotals) ? Collections.emptyMap() : productTotals.stream().filter(t -> t.getSalesLedgerId() != null).collect(Collectors.toMap(SalesLedgerProductTotalsDto::getSalesLedgerId, Function.identity(), (a, b) -> a));
+
+ List<InvoiceLedgerDto> invoiceLedgerDtoList = invoiceLedgerMapper.invoicedTotal(salesLedgerIds);
+ if (CollectionUtils.isEmpty(invoiceLedgerDtoList)) {
+ invoiceLedgerDtoList = Collections.emptyList();
+ }
+
+ Map<Long, BigDecimal> invoiceTotals = invoiceLedgerDtoList.stream().filter(dto -> dto.getSalesLedgerId() != null && dto.getInvoiceTotal() != null).collect(Collectors.toMap(dto -> dto.getSalesLedgerId().longValue(), InvoiceLedgerDto::getInvoiceTotal, BigDecimal::add));
+
+ List<ReceiptPayment> receiptPayments = Collections.emptyList();
+ if (!CollectionUtils.isEmpty(salesLedgerIds)) {
+ receiptPayments = receiptPaymentMapper.selectList(new LambdaQueryWrapper<ReceiptPayment>().in(ReceiptPayment::getSalesLedgerId, salesLedgerIds));
+ }
+
+ Map<Long, BigDecimal> receiptTotals = new HashMap<>();
+ if (!CollectionUtils.isEmpty(receiptPayments)) {
+ for (ReceiptPayment receiptPayment : receiptPayments) {
+ if (receiptPayment.getSalesLedgerId() != null && receiptPayment.getReceiptPaymentAmount() != null) {
+ receiptTotals.merge(receiptPayment.getSalesLedgerId(), receiptPayment.getReceiptPaymentAmount(), BigDecimal::add);
+ }
+ }
+ }
+
+ for (SalesLedger salesLedger : iPage.getRecords()) {
+ Long ledgerId = salesLedger.getId();
+
+ SalesLedgerProductTotalsDto totals = productTotalsMap.get(ledgerId);
+ if (totals != null) {
+ salesLedger.setProductTotalQuantity(totals.getTotalQuantity() != null ? totals.getTotalQuantity() : BigDecimal.ZERO);
+ salesLedger.setProductTotalArea(totals.getTotalArea() != null ? totals.getTotalArea() : BigDecimal.ZERO);
+ } else {
+ salesLedger.setProductTotalQuantity(BigDecimal.ZERO);
+ salesLedger.setProductTotalArea(BigDecimal.ZERO);
+ }
+ if (hasWidthHeightFilter) {
+ salesLedger.setMatchedProducts(matchedProductsMap.getOrDefault(ledgerId, Collections.emptyList()));
+ }
+
+ BigDecimal contractAmount = salesLedger.getContractAmount() == null ? BigDecimal.ZERO : salesLedger.getContractAmount();
+ BigDecimal invoiceTotal = invoiceTotals.getOrDefault(ledgerId, BigDecimal.ZERO);
+ BigDecimal receiptPaymentAmountTotal = receiptTotals.getOrDefault(ledgerId, BigDecimal.ZERO);
+
+ BigDecimal noInvoiceAmountTotal = contractAmount.subtract(invoiceTotal);
+ if (noInvoiceAmountTotal.compareTo(BigDecimal.ZERO) < 0) {
+ noInvoiceAmountTotal = BigDecimal.ZERO;
+ }
+
+ BigDecimal noReceiptPaymentAmountTotal = invoiceTotal.subtract(receiptPaymentAmountTotal);
+ if (noReceiptPaymentAmountTotal.compareTo(BigDecimal.ZERO) < 0) {
+ noReceiptPaymentAmountTotal = BigDecimal.ZERO;
+ }
+
+ salesLedger.setNoInvoiceAmountTotal(noInvoiceAmountTotal);
+ salesLedger.setInvoiceTotal(invoiceTotal);
+ salesLedger.setReceiptPaymentAmountTotal(receiptPaymentAmountTotal);
+ salesLedger.setNoReceiptAmount(noReceiptPaymentAmountTotal);
+
+ boolean hasInvoiceOperation = invoiceTotal.compareTo(BigDecimal.ZERO) > 0;
+ boolean hasReceiptOperation = receiptPaymentAmountTotal.compareTo(BigDecimal.ZERO) > 0;
+ salesLedger.setIsEdit(!(hasInvoiceOperation || hasReceiptOperation));
+ }
+
+ if (salesLedgerDto.getStatus() != null && salesLedgerDto.getStatus()) {
+ iPage.getRecords().removeIf(salesLedger -> Objects.equals(salesLedger.getNoInvoiceAmountTotal(), new BigDecimal("0.00")));
+ iPage.setTotal(iPage.getRecords().size());
+ }
+
+ return iPage;
}
@Override
@Transactional(rollbackFor = Exception.class)
- public AjaxResult importData(MultipartFile file) {
+ public void importData(MultipartFile file) {
LoginUser loginUser = SecurityUtils.getLoginUser();
- try {
- InputStream inputStream = file.getInputStream();
- ExcelUtil<SalesLedgerImportDto> salesLedgerImportDtoExcelUtil = new ExcelUtil<>(SalesLedgerImportDto.class);
- Map<String, List<SalesLedgerImportDto>> stringListMap = salesLedgerImportDtoExcelUtil.importExcelMultiSheet(Arrays.asList("閿�鍞彴璐︽暟鎹�", "閿�鍞骇鍝佹暟鎹�"), inputStream, 0);
- if (CollectionUtils.isEmpty(stringListMap)) return AjaxResult.error("閿�鍞〃鏍间负绌猴紒");
- // 涓氬姟灞傚悎骞�
- List<SalesLedgerImportDto> salesLedgerImportDtoList = stringListMap.get("閿�鍞彴璐︽暟鎹�");
- if (CollectionUtils.isEmpty(salesLedgerImportDtoList)) return AjaxResult.error("閿�鍞彴璐︽暟鎹负绌猴紒");
- List<SalesLedgerImportDto> salesLedgerProductImportDtoList = stringListMap.get("閿�鍞骇鍝佹暟鎹�");
- if (CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) return AjaxResult.error("閿�鍞骇鍝佹暟鎹负绌猴紒");
- // 瀹㈡埛鏁版嵁
- List<Customer> customers = customerMapper.selectList(new LambdaQueryWrapper<Customer>().in(Customer::getCustomerName,
- salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getCustomerName).collect(Collectors.toList())));
-// // 瑙勬牸鍨嬪彿鏁版嵁
-// List<ProductModel> productModels = productModelMapper.selectList(new LambdaQueryWrapper<ProductModel>().in(ProductModel::getModel,
-// salesLedgerProductImportDtoList.stream().map(SalesLedgerImportDto::getSpecificationModel).collect(Collectors.toList())));
-// // 浜у搧澶х被鏁版嵁
-// List<Product> productList = productMapper.selectList(new LambdaQueryWrapper<Product>().in(Product::getProductName,
-// salesLedgerProductImportDtoList.stream().map(SalesLedgerImportDto::getProductCategory).collect(Collectors.toList())));
- List<Map<String, Object>> list = productModelMapper.getProductAndModelList();
- // 褰曞叆浜烘暟鎹�
- List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getNickName,
- salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getEntryPerson).collect(Collectors.toList())));
- for (SalesLedgerImportDto salesLedgerImportDto : salesLedgerImportDtoList) {
- SalesLedger salesLedger1 = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>()
- .eq(SalesLedger::getSalesContractNo, salesLedgerImportDto.getSalesContractNo())
- .last("LIMIT 1"));
- if (salesLedger1 != null) {
- continue;
- }
- SalesLedger salesLedger = new SalesLedger();
- BeanUtils.copyProperties(salesLedgerImportDto, salesLedger);
- salesLedger.setExecutionDate(DateUtils.toLocalDate(salesLedgerImportDto.getExecutionDate()));
- // 閫氳繃瀹㈡埛鍚嶇О鏌ヨ瀹㈡埛ID锛屽鎴峰悎鍚屽彿
- salesLedger.setCustomerId(customers.stream()
- .filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName()))
- .findFirst()
- .map(Customer::getId)
- .orElse(null));
- salesLedger.setCustomerContractNo(customers.stream()
- .filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName()))
- .findFirst()
- .map(Customer::getTaxpayerIdentificationNumber)
- .orElse(null));
- Long aLong = sysUsers.stream()
- .filter(sysUser -> sysUser.getNickName().equals(salesLedger.getEntryPerson()))
- .findFirst()
- .map(SysUser::getUserId)
- .orElse(null);
- if (aLong == null)
- throw new RuntimeException("褰曞叆浜�:" + salesLedger.getEntryPerson() + ",鏃犲搴旂敤鎴凤紒");
- salesLedger.setEntryPerson(aLong.toString());
- // 閿�鍞骇鍝佹暟鎹粦瀹氾紝閫氳繃閿�鍞崟鍙疯幏鍙栧搴旈攢鍞骇鍝佹暟鎹�
- List<SalesLedgerProductImportDto> salesLedgerProductImportDtos = salesLedgerProductImportDtoList.stream()
- .filter(salesLedgerProductImportDto -> salesLedgerProductImportDto.getSalesContractNo().equals(salesLedger.getSalesContractNo()))
- .collect(Collectors.toList());
- if (CollectionUtils.isEmpty(salesLedgerProductImportDtos))
- throw new RuntimeException("閿�鍞崟鍙�:" + salesLedgerImportDto.getSalesContractNo() + ",鏃犲搴斾骇鍝佹暟鎹紒");
- salesLedger.setContractAmount(salesLedgerProductImportDtos.stream()
- .map(SalesLedgerProductImportDto::getTaxInclusiveTotalPrice)
- .reduce(BigDecimal.ZERO, BigDecimal::add));
- salesLedgerMapper.insert(salesLedger);
-
- for (SalesLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) {
- SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct();
- BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct);
- salesLedgerProduct.setSalesLedgerId(salesLedger.getId());
- salesLedgerProduct.setType(1);
- // 璁$畻涓嶅惈绋庢�讳环
- salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 2, RoundingMode.HALF_UP));
- salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
- salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxExclusiveTotalPrice());
- list.stream()
- .filter(map -> map.get("productName").equals(salesLedgerProduct.getProductCategory()) && map.get("model").equals(salesLedgerProduct.getSpecificationModel()))
- .findFirst()
- .ifPresent(map -> {
- salesLedgerProduct.setProductModelId(Long.parseLong(map.get("modelId").toString()));
- salesLedgerProduct.setProductId(Long.parseLong(map.get("id").toString()));
- });
-// salesLedgerProduct.setProductId(productList.stream()
-// .filter(product -> product.getProductName().equals(salesLedgerProduct.getProductCategory()))
-// .findFirst()
-// .map(Product::getId)
-// .orElse(null));
-// salesLedgerProduct.setProductModelId(productModels.stream()
-// .filter(productModel -> productModel.getModel().equals(salesLedgerProduct.getSpecificationModel()))
-// .findFirst()
-// .map(ProductModel::getId)
-// .orElse(null));
- salesLedgerProduct.setRegister(loginUser.getNickName());
- salesLedgerProduct.setRegisterDate(LocalDateTime.now());
- salesLedgerProduct.setApproveStatus(0);
- salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProductImportDto.getTaxInclusiveTotalPrice());
- salesLedgerProductMapper.insert(salesLedgerProduct);
- // 娣诲姞鐢熶骇鏁版嵁
- salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
- }
- }
-
- return AjaxResult.success("瀵煎叆鎴愬姛");
+ Map<String, List<SalesLedgerImportDto>> stringListMap;
+ try (InputStream inputStream = file.getInputStream()) {
+ ExcelUtil<SalesLedgerImportDto> excelUtil = new ExcelUtil<>(SalesLedgerImportDto.class);
+ stringListMap = excelUtil.importExcelMultiSheet(Arrays.asList("閿�鍞彴璐︽暟鎹�", "閿�鍞骇鍝佹暟鎹�"), inputStream, 0);
+ } catch (IOException e) {
+ log.error("閿�鍞彴璐﹀鍏ュけ璐ワ細璇诲彇/瑙f瀽Excel寮傚父", e);
+ throw new ServiceException("瀵煎叆澶辫触锛氳鍙�/瑙f瀽Excel寮傚父");
} catch (Exception e) {
- e.printStackTrace();
+ log.error("閿�鍞彴璐﹀鍏ュけ璐ワ細瑙f瀽Excel寮傚父", e);
+ throw new ServiceException("瀵煎叆澶辫触锛氳В鏋怑xcel寮傚父");
}
- return AjaxResult.success("瀵煎叆澶辫触");
+
+ if (CollectionUtils.isEmpty(stringListMap)) {
+ throw new ServiceException("瀵煎叆澶辫触,閿�鍞〃鏍间负绌�");
+ }
+ // 涓氬姟灞傚悎骞�
+ List<SalesLedgerImportDto> salesLedgerImportDtoList = stringListMap.get("閿�鍞彴璐︽暟鎹�");
+ if (CollectionUtils.isEmpty(salesLedgerImportDtoList)) {
+ throw new ServiceException("瀵煎叆澶辫触,閿�鍞彴璐︽暟鎹负绌�");
+ }
+ List<SalesLedgerImportDto> salesLedgerProductImportDtoList = stringListMap.get("閿�鍞骇鍝佹暟鎹�");
+ if (CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) {
+ throw new ServiceException("瀵煎叆澶辫触,閿�鍞骇鍝佹暟鎹负绌�");
+ }
+ // 瀹㈡埛鏁版嵁
+ List<Customer> customers = customerMapper.selectList(new LambdaQueryWrapper<Customer>().in(Customer::getCustomerName, salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getCustomerName).collect(Collectors.toList())));
+ List<Map<String, Object>> list = productModelMapper.getProductAndModelList();
+ // 褰曞叆浜烘暟鎹�
+ List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getNickName, salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getEntryPerson).collect(Collectors.toList())));
+ for (SalesLedgerImportDto salesLedgerImportDto : salesLedgerImportDtoList) {
+ SalesLedger salesLedger1 = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>().eq(SalesLedger::getSalesContractNo, salesLedgerImportDto.getSalesContractNo()).last("LIMIT 1"));
+ if (salesLedger1 != null) {
+ throw new ServiceException("瀵煎叆澶辫触锛氬悎鍚屽彿 [" + salesLedgerImportDto.getSalesContractNo() + "] 宸插瓨鍦紝璇锋鏌ュ悗閲嶆柊瀵煎叆");
+ }
+ SalesLedger salesLedger = new SalesLedger();
+ BeanUtils.copyProperties(salesLedgerImportDto, salesLedger);
+ // 鏍¢獙锛氱璁㈡棩鏈熴�佸綍鍏ユ棩鏈熶笉鑳戒负绌�
+ if (salesLedgerImportDto.getExecutionDate() == null) {
+ throw new ServiceException("瀵煎叆澶辫触锛氬悎鍚屽彿[" + salesLedgerImportDto.getSalesContractNo() + "] 绛捐鏃ユ湡涓嶈兘涓虹┖");
+ }
+ if (salesLedgerImportDto.getEntryDate() == null) {
+ throw new ServiceException("瀵煎叆澶辫触锛氬悎鍚屽彿[" + salesLedgerImportDto.getSalesContractNo() + "] 褰曞叆鏃ユ湡涓嶈兘涓虹┖");
+ }
+ salesLedger.setExecutionDate(DateUtils.toLocalDate(salesLedgerImportDto.getExecutionDate()));
+
+ LocalDate expectedDeliveryDate = DateUtils.toLocalDate(salesLedgerImportDto.getEntryDate()).plusDays(7);
+ LocalDate importDeliveryDate = salesLedgerImportDto.getDeliveryDate() == null ? null : DateUtils.toLocalDate(salesLedgerImportDto.getDeliveryDate());
+ // 浜や粯鏃ユ湡涓虹┖鍒欓粯璁ゅ彇褰曞叆鏃ユ湡鍚�7澶�
+ salesLedger.setDeliveryDate(importDeliveryDate == null ? expectedDeliveryDate : importDeliveryDate);
+ // 閫氳繃瀹㈡埛鍚嶇О鏌ヨ瀹㈡埛ID锛屽鎴峰悎鍚屽彿
+ salesLedger.setCustomerId(customers.stream().filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName())).findFirst().map(Customer::getId).orElse(null));
+ salesLedger.setCustomerContractNo(customers.stream().filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName())).findFirst().map(Customer::getTaxpayerIdentificationNumber).orElse(null));
+ Long aLong = sysUsers.stream().filter(sysUser -> sysUser.getNickName().equals(salesLedger.getEntryPerson())).findFirst().map(SysUser::getUserId).orElse(null);
+ if (aLong == null) {
+ throw new ServiceException("褰曞叆浜�:" + salesLedger.getEntryPerson() + ",鏃犲搴旂敤鎴凤紒");
+ }
+ salesLedger.setEntryPerson(aLong.toString());
+ // 閿�鍞骇鍝佹暟鎹粦瀹氾紝閫氳繃閿�鍞崟鍙疯幏鍙栧搴旈攢鍞骇鍝佹暟鎹�
+ List<SalesLedgerProductImportDto> salesLedgerProductImportDtos = salesLedgerProductImportDtoList.stream().filter(salesLedgerProductImportDto -> salesLedgerProductImportDto.getSalesContractNo().equals(salesLedger.getSalesContractNo())).collect(Collectors.toList());
+ if (CollectionUtils.isEmpty(salesLedgerProductImportDtos)) {
+ throw new ServiceException("閿�鍞崟鍙�:" + salesLedgerImportDto.getSalesContractNo() + ",鏃犲搴斾骇鍝佹暟鎹紒");
+ }
+ // 鍙戣揣鐘舵��
+ salesLedger.setDeliveryStatus(1);
+ salesLedger.setContractAmount(BigDecimal.ZERO);
+ salesLedgerMapper.insert(salesLedger);
+ BigDecimal contractAmount = BigDecimal.ZERO;
+
+ for (SalesLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) {
+ SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct();
+ BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct);
+ salesLedgerProduct.setFloorCode(salesLedgerProductImportDto.getFloorNo());
+ salesLedgerProduct.setProcessRequirement(salesLedgerProductImportDto.getProcessingRequirements());
+ salesLedgerProduct.setRemark(salesLedgerProductImportDto.getRemarks());
+ salesLedgerProduct.setSalesLedgerId(salesLedger.getId());
+ salesLedgerProduct.setType(1);
+
+ BigDecimal quantity = defaultDecimal(salesLedgerProduct.getQuantity());
+ BigDecimal width = defaultDecimal(salesLedgerProduct.getWidth());
+ BigDecimal height = defaultDecimal(salesLedgerProduct.getHeight());
+ BigDecimal taxRateRaw = salesLedgerProduct.getTaxRate();
+ BigDecimal taxRate = defaultDecimal(taxRateRaw);
+ BigDecimal unitPrice = defaultDecimal(salesLedgerProduct.getTaxInclusiveUnitPrice());
+
+ // 瀵煎叆闄愬埗锛氬/楂�/鏁伴噺/閲戦(鍗曚环)/绋庣巼 涓嶈兘涓�0鎴栬礋鏁�
+ String locate = buildImportLocate(salesLedger.getSalesContractNo(), salesLedgerProductImportDto);
+ assertPositive(quantity, "鏁伴噺", locate);
+ assertPositive(width, "瀹�(mm)", locate);
+ assertPositive(height, "楂�(mm)", locate);
+ assertPositive(unitPrice, "鍚◣鍗曚环", locate);
+ assertNonNegative(taxRateRaw, "绋庣巼", locate);
+
+ BigDecimal actualPieceArea = BigDecimal.ZERO;
+ if (width.compareTo(BigDecimal.ZERO) > 0 && height.compareTo(BigDecimal.ZERO) > 0) {
+ actualPieceArea = width.multiply(height).divide(new BigDecimal("1000000"), 4, RoundingMode.HALF_UP);
+ }
+ salesLedgerProduct.setActualPieceArea(actualPieceArea);
+ salesLedgerProduct.setActualTotalArea(actualPieceArea.multiply(quantity).setScale(4, RoundingMode.HALF_UP));
+
+ BigDecimal settlePieceArea = salesLedgerProduct.getSettlePieceArea() == null ? actualPieceArea : salesLedgerProduct.getSettlePieceArea();
+ salesLedgerProduct.setSettlePieceArea(settlePieceArea);
+ salesLedgerProduct.setSettleTotalArea(settlePieceArea.multiply(quantity).setScale(4, RoundingMode.HALF_UP));
+
+ BigDecimal perimeter = BigDecimal.ZERO;
+ if (width.compareTo(BigDecimal.ZERO) > 0 && height.compareTo(BigDecimal.ZERO) > 0) {
+ perimeter = width.add(height).multiply(new BigDecimal("2")).divide(new BigDecimal("10"), 2, RoundingMode.HALF_UP);
+ }
+ salesLedgerProduct.setPerimeter(perimeter);
+
+ BigDecimal extraProcessAmountPerPiece = BigDecimal.ZERO;
+ list.stream().filter(Objects::nonNull).filter(map -> Objects.equals(Objects.toString(map.get("productName"), null), salesLedgerProduct.getProductCategory()) && Objects.equals(Objects.toString(map.get("model"), null), salesLedgerProduct.getSpecificationModel())).findFirst().ifPresent(map -> {
+ salesLedgerProduct.setProductModelId(Long.parseLong(map.get("modelId").toString()));
+ salesLedgerProduct.setProductId(Long.parseLong(map.get("id").toString()));
+ });
+ salesLedgerProduct.setRegister(loginUser.getNickName());
+ salesLedgerProduct.setRegisterDate(LocalDateTime.now());
+ salesLedgerProduct.setApproveStatus(0);
+ salesLedgerProduct.setProductStockStatus(0);
+
+ // 澶勭悊棰濆鍔犲伐淇℃伅
+ String extraProcessing = salesLedgerProductImportDto.getExtraProcessing();
+ List<SalesLedgerProductProcess> processList = new ArrayList<>();
+ if (StringUtils.hasText(extraProcessing)) {
+ // 涓嫳鏂囧垎鍙�
+ String[] items = extraProcessing.split("[;锛沒");
+ for (String item : items) {
+ if (StringUtils.hasText(item)) {
+ String[] parts = item.split("[-鈥攡锝瀅");
+ if (parts.length >= 2) {
+ String processName = parts[0].trim();
+ String qtyStr = parts[1].trim();
+ try {
+ BigDecimal processQty = new BigDecimal(qtyStr);
+ SalesLedgerProductProcess process = salesLedgerProductProcessService.getOne(new LambdaQueryWrapper<SalesLedgerProductProcess>().eq(SalesLedgerProductProcess::getProcessName, processName).last("LIMIT 1"));
+ if (process != null) {
+ SalesLedgerProductProcess p = new SalesLedgerProductProcess();
+ p.setId(process.getId());
+ p.setQuantity(processQty.intValue());
+ processList.add(p);
+ extraProcessAmountPerPiece = extraProcessAmountPerPiece.add(defaultDecimal(process.getUnitPrice()).multiply(processQty));
+ }
+ } catch (Exception e) {
+ log.error("瑙f瀽棰濆鍔犲伐鏁伴噺澶辫触: {}", qtyStr);
+ }
+ }
+ }
+ }
+ }
+
+ // 鍚◣鎬讳环 = 鍗曚环 * 缁撶畻闈㈢Н * 鏁伴噺 + 棰濆鍔犲伐閲戦 * 鏁伴噺
+ BigDecimal taxInclusiveTotalPrice = unitPrice.multiply(settlePieceArea).multiply(quantity).add(extraProcessAmountPerPiece.multiply(quantity)).setScale(2, RoundingMode.HALF_UP);
+ salesLedgerProduct.setTaxInclusiveTotalPrice(taxInclusiveTotalPrice);
+ assertPositive(taxInclusiveTotalPrice, "鍚◣鎬讳环", locate);
+
+ // 绋庣巼鍏佽涓虹┖锛岀┖鍊兼寜0澶勭悊
+ BigDecimal taxDivisor = BigDecimal.ONE.add(taxRate.divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP));
+ salesLedgerProduct.setTaxExclusiveTotalPrice(taxInclusiveTotalPrice.divide(taxDivisor, 2, RoundingMode.HALF_UP));
+ salesLedgerProduct.setNoInvoiceNum(quantity);
+ salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxExclusiveTotalPrice());
+ salesLedgerProduct.setPendingInvoiceTotal(taxInclusiveTotalPrice);
+ salesLedgerProduct.fillRemainingQuantity();
+ salesLedgerProductMapper.insert(salesLedgerProduct);
+ if (!processList.isEmpty()) {
+ salesLedgerProductProcessBindService.updateProductProcessBind(processList, salesLedgerProduct.getId());
+ }
+ // 娣诲姞鐢熶骇鏁版嵁
+ salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
+ contractAmount = contractAmount.add(taxInclusiveTotalPrice);
+ }
+ salesLedger.setContractAmount(contractAmount);
+ salesLedgerMapper.updateById(salesLedger);
+ }
+ }
+
+ private BigDecimal defaultDecimal(BigDecimal value) {
+ return value == null ? BigDecimal.ZERO : value;
+ }
+
+ private void assertPositive(BigDecimal value, String fieldName, String locate) {
+ if (value == null || value.compareTo(BigDecimal.ZERO) <= 0) {
+ throw new ServiceException("瀵煎叆澶辫触锛�" + locate + "銆�" + fieldName + "銆戝繀椤诲ぇ浜�0");
+ }
+ }
+
+ private void assertNonNegative(BigDecimal value, String fieldName, String locate) {
+ if (value != null && value.compareTo(BigDecimal.ZERO) < 0) {
+ throw new ServiceException("瀵煎叆澶辫触锛�" + locate + "銆�" + fieldName + "銆戜笉鑳戒负璐熸暟");
+ }
+ }
+
+ private String buildImportLocate(String salesContractNo, SalesLedgerProductImportDto dto) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("閿�鍞崟鍙穂").append(salesContractNo == null ? "" : salesContractNo).append("]");
+ if (dto != null) {
+ if (StringUtils.hasText(dto.getProductCategory())) {
+ sb.append(" 浜у搧澶х被[").append(dto.getProductCategory()).append("]");
+ }
+ if (StringUtils.hasText(dto.getSpecificationModel())) {
+ sb.append(" 瑙勬牸鍨嬪彿[").append(dto.getSpecificationModel()).append("]");
+ }
+ if (StringUtils.hasText(dto.getFloorNo())) {
+ sb.append(" 妤煎眰缂栧彿[").append(dto.getFloorNo()).append("]");
+ }
+ }
+ return sb.toString();
}
@Override
public List<LossProductModelDto> getSalesLedgerWithProductsLoss(Long salesLedgerId) {
-
-
List<LossProductModelDto> lossProductModelDtos = salesLedgerProductMapper.selectProductBomStructure(salesLedgerId);
-
-
return lossProductModelDtos;
}
@@ -475,10 +712,9 @@
product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
product.setRegisterDate(LocalDateTime.now());
// 鍙戣揣淇℃伅
- ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
- .eq(ShippingInfo::getSalesLedgerProductId, product.getId())
- .orderByDesc(ShippingInfo::getCreateTime)
- .last("limit 1"));
+ ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>().eq(ShippingInfo::getSalesLedgerProductId, product.getId()).orderByDesc(ShippingInfo::getCreateTime).last("limit 1"));
+ product.setShippingCarNumber(shippingInfo.getShippingCarNumber());
+ product.setShippingDate(shippingInfo.getShippingDate());
if (shippingInfo != null) {
product.setShippingStatus(shippingInfo.getStatus());
}
@@ -493,6 +729,39 @@
return salesLedgerDtoIPage;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void saleProcessBind(SalesLedgerProcessRoute salesLedgerProcessRoute) {
+ if (salesLedgerProcessRoute == null) {
+ throw new ServiceException("缁戝畾澶辫触,鏁版嵁涓嶈兘涓虹┖");
+ }
+
+ SalesLedger salesLedger = baseMapper.selectById(salesLedgerProcessRoute.getSalesLedgerId());
+ if (salesLedger == null) {
+ throw new ServiceException("缁戝畾澶辫触,閿�鍞鍗曚笉瀛樺湪");
+ }
+ ProcessRoute processRoute = processRouteMapper.selectById(salesLedgerProcessRoute.getProcessRouteId());
+ if (processRoute == null) {
+ throw new ServiceException("缁戝畾澶辫触,宸ヨ壓璺嚎涓嶅瓨鍦�");
+ }
+ // 娓呴櫎宸茬粦瀹氱殑鏁版嵁
+ salesLedgerProcessRouteService.remove(new LambdaQueryWrapper<SalesLedgerProcessRoute>().eq(SalesLedgerProcessRoute::getSalesLedgerId, salesLedger.getId()));
+
+ // 灏嗘暟鎹縼绉诲埌sales_ledger_process_route
+ List<ProcessRouteItem> routeItems = processRouteItemMapper.selectList(new LambdaQueryWrapper<ProcessRouteItem>().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
+ SalesLedgerProcessRoute ledgerProcessRoute;
+ List<SalesLedgerProcessRoute> salesLedgerProcessRouteList = new ArrayList<>();
+ for (ProcessRouteItem routeItem : routeItems) {
+ ledgerProcessRoute = new SalesLedgerProcessRoute();
+ ledgerProcessRoute.setProcessRouteId(processRoute.getId());
+ ledgerProcessRoute.setSalesLedgerId(salesLedger.getId());
+ ledgerProcessRoute.setProcessRouteItemId(routeItem.getId());
+ ledgerProcessRoute.setDragSort(routeItem.getDragSort());
+ salesLedgerProcessRouteList.add(ledgerProcessRoute);
+ }
+ salesLedgerProcessRouteService.saveBatch(salesLedgerProcessRouteList);
}
/**
@@ -520,21 +789,16 @@
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteSalesLedgerByIds(Long[] ids) {
- List<Long> idList = Arrays.stream(ids)
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
+ List<Long> idList = Arrays.stream(ids).filter(Objects::nonNull).collect(Collectors.toList());
if (CollectionUtils.isEmpty(idList)) {
return 0;
}
// 鍒犻櫎閿�鍞鐞嗘暟鎹�
LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.in(SalesLedgerProduct::getSalesLedgerId, idList)
- .select(SalesLedgerProduct::getId);
+ queryWrapper.in(SalesLedgerProduct::getSalesLedgerId, idList).select(SalesLedgerProduct::getId);
List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(queryWrapper);
- List<Long> productIds = products.stream()
- .map(SalesLedgerProduct::getId)
- .collect(Collectors.toList());
+ List<Long> productIds = products.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList());
//鍒犻櫎鐢熶骇鏁版嵁
salesLedgerProductServiceImpl.deleteProductionData(productIds);
@@ -542,6 +806,9 @@
if (!productIds.isEmpty()) {
salesLedgerProductMapper.deleteBatchIds(productIds);
}
+
+ // 娓呴櫎浜у搧鐨勫姞宸�
+ salesLedgerProductProcessBindService.remove(new LambdaQueryWrapper<SalesLedgerProductProcessBind>().in(SalesLedgerProductProcessBind::getSalesLedgerProductId, productIds));
LambdaQueryWrapper<InvoiceRegistrationProduct> wrapper = new LambdaQueryWrapper<>();
wrapper.in(InvoiceRegistrationProduct::getSalesLedgerId, idList);
@@ -567,10 +834,18 @@
receiptPaymentMapper.delete(wrapperTree);
}
// 鍒犻櫎鍙戣揣鍙拌处璁板綍
- List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>()
- .in(ShippingInfo::getSalesLedgerId, idList));
+ List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>().in(ShippingInfo::getSalesLedgerId, idList));
if (CollectionUtils.isNotEmpty(shippingInfos)) {
shippingInfoServiceImpl.delete(shippingInfos.stream().map(ShippingInfo::getId).collect(Collectors.toList()));
+ }
+ // 鍒犻櫎鍏宠仈鐨勫叆搴�/鍑哄簱璁板綍锛堣蛋鏈嶅姟灞傚垹闄わ紝瑙﹀彂搴撳瓨鏁伴噺鍥為��锛�
+ List<Long> stockInRecordIds = stockInRecordMapper.selectList(new LambdaQueryWrapper<StockInRecord>().in(StockInRecord::getSalesLedgerId, idList).select(StockInRecord::getId)).stream().map(StockInRecord::getId).collect(Collectors.toList());
+ if (CollectionUtils.isNotEmpty(stockInRecordIds)) {
+ stockInRecordService.batchDelete(stockInRecordIds);
+ }
+ List<Long> stockOutRecordIds = stockOutRecordMapper.selectList(new LambdaQueryWrapper<StockOutRecord>().in(StockOutRecord::getSalesLedgerId, idList).select(StockOutRecord::getId)).stream().map(StockOutRecord::getId).collect(Collectors.toList());
+ if (CollectionUtils.isNotEmpty(stockOutRecordIds)) {
+ stockOutRecordService.batchDelete(stockOutRecordIds);
}
// 鍒犻櫎闄勪欢琛�
commonFileService.deleteByBusinessIds(idList, FileNameType.SALE.getValue());
@@ -605,8 +880,13 @@
if (salesLedger.getId() == null) {
String contractNo = generateSalesContractNo();
salesLedger.setSalesContractNo(contractNo);
+ salesLedger.setDeliveryStatus(1);
+ salesLedger.setStockStatus(0);
salesLedgerMapper.insert(salesLedger);
} else {
+ if (salesLedger.getDeliveryStatus() == 5) {
+ throw new ServiceException("璁㈠崟宸插彂璐�,绂佹缂栬緫");
+ }
salesLedgerMapper.updateById(salesLedger);
}
@@ -614,13 +894,7 @@
List<SalesLedgerProduct> productList = salesLedgerDto.getProductData();
if (productList != null && !productList.isEmpty()) {
handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType()));
- updateMainContractAmount(
- salesLedger.getId(),
- productList,
- SalesLedgerProduct::getTaxInclusiveTotalPrice,
- salesLedgerMapper,
- SalesLedger.class
- );
+ updateMainContractAmount(salesLedger.getId(), productList, SalesLedgerProduct::getTaxInclusiveTotalPrice, salesLedgerMapper, SalesLedger.class);
}
// 5. 杩佺Щ涓存椂鏂囦欢鍒版寮忕洰褰�
@@ -666,10 +940,7 @@
// 鏋勫缓姝e紡鏂囦欢鍚嶏紙鍖呭惈涓氬姟ID鍜屾椂闂存埑锛岄伩鍏嶅啿绐侊級
String originalFilename = tempFile.getOriginalName();
String fileExtension = FilenameUtils.getExtension(originalFilename);
- String formalFilename = businessId + "_" +
- System.currentTimeMillis() + "_" +
- UUID.randomUUID().toString().substring(0, 8) +
- (StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
+ String formalFilename = businessId + "_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8) + (StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
Path formalFilePath = formalDirPath.resolve(formalFilename);
@@ -713,9 +984,7 @@
@Override
public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) {
// 鎸塈D鍒嗙粍锛屽尯鍒嗘柊澧炲拰鏇存柊鐨勮褰�
- Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream()
- .peek(p -> p.setSalesLedgerId(salesLedgerId))
- .collect(Collectors.partitioningBy(p -> p.getId() != null));
+ Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream().peek(p -> p.setSalesLedgerId(salesLedgerId)).collect(Collectors.partitioningBy(p -> p.getId() != null));
List<SalesLedgerProduct> updateList = partitionedProducts.get(true);
List<SalesLedgerProduct> insertList = partitionedProducts.get(false);
@@ -724,7 +993,19 @@
if (!updateList.isEmpty()) {
for (SalesLedgerProduct product : updateList) {
product.setType(type.getCode());
+ SalesLedgerProduct db = salesLedgerProductMapper.selectById(product.getId());
+ if (db != null) {
+ BigDecimal stockedQty = product.getStockedQuantity() != null ? product.getStockedQuantity() : db.getStockedQuantity();
+ BigDecimal orderQty = product.getQuantity() != null ? product.getQuantity() : db.getQuantity();
+ product.setStockedQuantity(stockedQty);
+ product.setProductStockStatus(calculateProductStockStatus(stockedQty, orderQty));
+ } else {
+ product.setProductStockStatus(0);
+ }
+ product.fillRemainingQuantity();
salesLedgerProductMapper.updateById(product);
+ // 娓呯┖閿�鍞骇鍝佺粦瀹氱殑鍔犲伐
+ salesLedgerProductProcessBindService.updateProductProcessBind(product.getSalesProductProcessList(), product.getId());
}
}
// 鎵ц鎻掑叆鎿嶄綔
@@ -734,11 +1015,55 @@
salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
+ BigDecimal stockedQty = salesLedgerProduct.getStockedQuantity();
+ BigDecimal orderQty = salesLedgerProduct.getQuantity();
+ salesLedgerProduct.setProductStockStatus(calculateProductStockStatus(stockedQty, orderQty));
+ salesLedgerProduct.fillRemainingQuantity();
+ ProductModel productModel = productModelMapper.selectById(salesLedgerProduct.getProductModelId());
+ if (productModel == null) {
+ throw new ServiceException("鏂板閿�鍞彴璐﹀け璐�,閿�鍞骇鍝佷笉瀛樺湪");
+ }
+ salesLedgerProduct.setUnit(productModel.getUnit());
salesLedgerProductMapper.insert(salesLedgerProduct);
+ // 缁戝畾浜у搧棰濆鍔犲伐
+ // 娓呯┖閿�鍞骇鍝佺粦瀹氱殑鍔犲伐
+ salesLedgerProductProcessBindService.updateProductProcessBind(salesLedgerProduct.getSalesProductProcessList(), salesLedgerProduct.getId());
// 娣诲姞鐢熶骇鏁版嵁
- salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
+// salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
}
}
+ refreshSalesLedgerStockStatus(salesLedgerId);
+ }
+
+ private int calculateProductStockStatus(BigDecimal stockedQty, BigDecimal orderQty) {
+ BigDecimal stocked = stockedQty == null ? BigDecimal.ZERO : stockedQty;
+ BigDecimal order = orderQty == null ? BigDecimal.ZERO : orderQty;
+ if (stocked.compareTo(BigDecimal.ZERO) <= 0) {
+ return 0;
+ }
+ if (order.compareTo(BigDecimal.ZERO) > 0 && stocked.compareTo(order) < 0) {
+ return 1;
+ }
+ return 2;
+ }
+
+ private void refreshSalesLedgerStockStatus(Long salesLedgerId) {
+ if (salesLedgerId == null) return;
+ SalesLedger ledger = baseMapper.selectById(salesLedgerId);
+ if (ledger == null) return;
+ List<SalesLedgerProduct> allProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId).eq(SalesLedgerProduct::getType, SaleEnum.SALE.getCode()));
+ if (CollectionUtils.isEmpty(allProducts)) {
+ ledger.setStockStatus(0);
+ baseMapper.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));
+ baseMapper.updateById(ledger);
}
private SalesLedger convertToEntity(SalesLedgerDto dto) {
@@ -772,19 +1097,20 @@
}
}
- if (!redisTemplate.hasKey(lockKey)) {
+ if (Boolean.FALSE.equals(redisTemplate.hasKey(lockKey))) {
throw new RuntimeException("鑾峰彇鍚堝悓缂栧彿鐢熸垚閿佸け璐ワ細瓒呮椂");
}
// 2. 鏌ヨ褰撳ぉ/鍏徃宸插瓨鍦ㄧ殑搴忓垪鍙凤紙涓庡師閫昏緫涓�鑷达級
- Long tenantId = SecurityUtils.getLoginUser().getTenantId();
- if (null != tenantId) {
- //鑾峰彇鍏徃缂栧彿
- SysDept sysDept = sysDeptMapper.selectDeptById(tenantId.longValue());
- if (!ObjectUtils.isEmpty(sysDept)) {
- datePart = (StringUtils.isEmpty(sysDept.getDeptNick()) ? "" : sysDept.getDeptNick()) + datePart;
- }
- }
+// Long tenantId = SecurityUtils.getLoginUser().getTenantId();
+// if (null != tenantId) {
+// //鑾峰彇鍏徃缂栧彿
+// SysDept sysDept = sysDeptMapper.selectDeptById(tenantId);
+// if (!ObjectUtils.isEmpty(sysDept)) {
+// datePart = (StringUtils.isEmpty(sysDept.getDeptNick()) ? "" : sysDept.getDeptNick()) + datePart;
+// }
+// }
+ datePart = "D" + datePart;
List<Integer> existingSequences = salesLedgerMapper.selectSequencesByDate(datePart);
int nextSequence = findFirstMissingSequence(existingSequences);
@@ -792,12 +1118,495 @@
} finally {
// 3. 閲婃斁閿�
String luaScript = "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end";
- redisTemplate.execute(
- new DefaultRedisScript<>(luaScript, Long.class),
- Collections.singletonList(lockKey),
- lockValue
- );
+ redisTemplate.execute(new DefaultRedisScript<>(luaScript, Long.class), Collections.singletonList(lockKey), lockValue);
}
+ }
+
+ @Override
+ public SalesLedgerProcessRouteDto salesProcess(Long salesLedgerId) {
+ SalesLedgerProcessRouteDto dto = new SalesLedgerProcessRouteDto();
+ List<SalesLedgerProcessRoute> list = baseMapper.selectSalesProcess(salesLedgerId);
+ if (CollectionUtils.isNotEmpty(list)) {
+ Long processRouteId = list.get(0).getProcessRouteId();
+ ProcessRoute processRoute = processRouteMapper.selectById(processRouteId);
+ if (processRoute != null) {
+ dto.setRouteId(processRoute.getId());
+ dto.setRouteName(processRoute.getProcessRouteName());
+ }
+ } else {
+ // 瑕佹槸list鏌ヨ涓虹┖鐨勮瘽锛屽氨鏌ヨ榛樿鐨勫伐鑹鸿矾绾胯繑鍥�
+ ProcessRoute defaultRoute = processRouteMapper.selectOne(new LambdaQueryWrapper<ProcessRoute>().eq(ProcessRoute::getIsDefault, 1).last("limit 1"));
+ if (defaultRoute != null) {
+ dto.setRouteId(defaultRoute.getId());
+ dto.setRouteName(defaultRoute.getProcessRouteName());
+ List<ProcessRouteItem> routeItems = processRouteItemMapper.selectList(new LambdaQueryWrapper<ProcessRouteItem>().eq(ProcessRouteItem::getRouteId, defaultRoute.getId()).orderByAsc(ProcessRouteItem::getDragSort));
+ list = routeItems.stream().map(item -> {
+ SalesLedgerProcessRoute salesLedgerProcessRoute = new SalesLedgerProcessRoute();
+ salesLedgerProcessRoute.setProcessRouteId(defaultRoute.getId());
+ salesLedgerProcessRoute.setSalesLedgerId(salesLedgerId);
+ salesLedgerProcessRoute.setProcessRouteItemId(item.getId());
+ salesLedgerProcessRoute.setProcessName(item.getProcessName());
+ salesLedgerProcessRoute.setDragSort(item.getDragSort());
+ return salesLedgerProcessRoute;
+ }).collect(Collectors.toList());
+ }
+ }
+ dto.setList(list);
+ return dto;
+ }
+
+ @Override
+ public SalesProcessCardDto processCard(Long salesLedgerId) {
+ if (salesLedgerId == null) {
+ throw new ServiceException("娴佺▼鍗℃墦鍗板け璐�,鎵撳嵃閿�鍞鍗曚笉鑳戒负绌�");
+ }
+ // 鏌ヨ閿�鍞鍗�
+ SalesLedger salesLedger = baseMapper.selectById(salesLedgerId);
+ if (salesLedger == null) {
+ throw new ServiceException("娴佺▼鍗℃墦鍗板け璐�,閿�鍞鍗曚笉瀛樺湪");
+ }
+
+ SalesProcessCardDto dto = new SalesProcessCardDto();
+ dto.setSalesContractNo(salesLedger.getSalesContractNo());
+ dto.setCustomerName(salesLedger.getCustomerName());
+ dto.setDeliveryDate(salesLedger.getDeliveryDate());
+ dto.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
+ dto.setRegisterDate(LocalDateTime.now());
+ dto.setOrderProcessRequirement(salesLedger.getRemarks());
+
+ // 鏌ヨ浜у搧鍒楄〃
+ List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>().eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId));
+
+ BigDecimal totalQuantity = BigDecimal.ZERO;
+ BigDecimal totalArea = BigDecimal.ZERO;
+ List<SalesProcessCardDto.ProcessCardItemDto> itemDtos = new ArrayList<>();
+
+ for (SalesLedgerProduct p : products) {
+ SalesProcessCardDto.ProcessCardItemDto itemDto = new SalesProcessCardDto.ProcessCardItemDto();
+ itemDto.setFloorCode(p.getFloorCode());
+ // 缁勮浜у搧鎻忚堪锛氬ぇ绫� + (瑙勬牸)
+ String desc = (p.getProductCategory() != null ? p.getProductCategory() : "") + (StringUtils.isNotBlank(p.getSpecificationModel()) ? " " + p.getSpecificationModel() : "");
+ itemDto.setProductDescription(desc.trim());
+ itemDto.setWidth(p.getWidth());
+ itemDto.setHeight(p.getHeight());
+ itemDto.setQuantity(p.getQuantity());
+
+ // 闈㈢Н璁$畻(骞崇背)
+ BigDecimal area = p.getActualPieceArea() != null ? p.getActualPieceArea() : p.getSettlePieceArea();
+ if (area == null && p.getWidth() != null && p.getHeight() != null) {
+ area = p.getWidth().multiply(p.getHeight()).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP);
+ }
+ itemDto.setArea(area);
+ itemDto.setProcessRequirement(p.getProcessRequirement());
+
+ BigDecimal qty = p.getQuantity() != null ? p.getQuantity() : BigDecimal.ZERO;
+ totalQuantity = totalQuantity.add(qty);
+ if (area != null) {
+ totalArea = totalArea.add(area.multiply(qty));
+ }
+
+ itemDtos.add(itemDto);
+ }
+ dto.setItems(itemDtos);
+ dto.setTotalQuantity(totalQuantity);
+ dto.setTotalArea(totalArea.setScale(2, RoundingMode.HALF_UP));
+
+ // 宸ヨ壓璺嚎
+ List<SalesLedgerProcessRoute> salesLedgerProcessRoutes = salesLedgerProcessRouteService.list(new LambdaQueryWrapper<SalesLedgerProcessRoute>().eq(SalesLedgerProcessRoute::getSalesLedgerId, salesLedgerId).orderByAsc(SalesLedgerProcessRoute::getDragSort));
+
+ List<SalesProcessCardDto.ProcessNodeDto> nodeDtos = new ArrayList<>();
+
+ if (CollectionUtils.isEmpty(salesLedgerProcessRoutes)) {
+ // 鏃犺嚜瀹氫箟璺嚎锛氬厛鏌ヨ榛樿宸ヨ壓璺嚎锛涜嫢鏃犻粯璁わ紝鑾峰彇鍒涘缓鏃堕棿鏈�杩戠殑涓�鏉�
+ ProcessRoute fallbackRoute = processRouteMapper.selectOne(new LambdaQueryWrapper<ProcessRoute>().eq(ProcessRoute::getIsDefault, 1).last("LIMIT 1"));
+ if (fallbackRoute == null) {
+ fallbackRoute = processRouteMapper.selectOne(new LambdaQueryWrapper<ProcessRoute>().orderByDesc(ProcessRoute::getCreateTime).last("LIMIT 1"));
+ }
+ if (fallbackRoute != null) {
+ List<ProcessRouteItem> routeItems = processRouteItemMapper.selectList(new LambdaQueryWrapper<ProcessRouteItem>().eq(ProcessRouteItem::getRouteId, fallbackRoute.getId()).orderByAsc(ProcessRouteItem::getDragSort));
+ for (ProcessRouteItem i : routeItems) {
+ SalesProcessCardDto.ProcessNodeDto node = new SalesProcessCardDto.ProcessNodeDto();
+ node.setProcessRouteItemId(i.getId());
+ node.setProcessRouteItemName(i.getProcessName());
+ node.setDragSort(i.getDragSort());
+ nodeDtos.add(node);
+ }
+ }
+ } else {
+ // 浣跨敤鑷畾涔夎矾绾跨粦瀹氱殑鑺傜偣
+ List<Long> itemIds = salesLedgerProcessRoutes.stream().map(SalesLedgerProcessRoute::getProcessRouteItemId).collect(Collectors.toList());
+ List<ProcessRouteItem> rawItems = processRouteItemMapper.selectBatchIds(itemIds);
+ Map<Long, ProcessRouteItem> itemMap = rawItems.stream().collect(Collectors.toMap(ProcessRouteItem::getId, i -> i, (a, b) -> a));
+
+ for (SalesLedgerProcessRoute r : salesLedgerProcessRoutes) {
+ ProcessRouteItem pi = itemMap.get(r.getProcessRouteItemId());
+ if (pi != null) {
+ SalesProcessCardDto.ProcessNodeDto node = new SalesProcessCardDto.ProcessNodeDto();
+ node.setProcessRouteItemId(pi.getId());
+ node.setProcessRouteItemName(pi.getProcessName());
+ node.setDragSort(r.getDragSort() != null ? r.getDragSort() : pi.getDragSort());
+ node.setRemark(r.getRemark());
+ nodeDtos.add(node);
+ }
+ }
+ }
+
+ if (!nodeDtos.isEmpty()) {
+ // dragSort 杩涜鍗囧簭鎺掑簭
+ nodeDtos.sort(Comparator.comparing(SalesProcessCardDto.ProcessNodeDto::getDragSort, Comparator.nullsLast(Comparator.naturalOrder())));
+ // 閲嶆柊鐢熸垚鎺掑簭鍚庣殑璺緞鍚嶇О鍒楄〃
+ List<String> sortedPathNames = nodeDtos.stream().map(SalesProcessCardDto.ProcessNodeDto::getProcessRouteItemName).collect(Collectors.toList());
+ // 鎷兼帴瀛楃涓�
+ dto.setProcessPathDisplay(String.join(" -> ", sortedPathNames));
+ // 璁剧疆椤跺眰鑺傜偣鐨勫伐鑹鸿矾绾�
+ dto.setRouteNodes(nodeDtos);
+ }
+
+ return dto;
+ }
+
+ @Override
+ public SalesOrdersDto salesOrders(Long salesLedgerId) {
+ if (salesLedgerId == null) {
+ throw new ServiceException("鎵撳嵃閿�鍞鍗曞け璐�,閿�鍞鍗旾D涓嶈兘涓虹┖");
+ }
+ SalesLedger salesLedger = baseMapper.selectById(salesLedgerId);
+ if (salesLedger == null) {
+ throw new ServiceException("鎵撳嵃閿�鍞鍗曞け璐�,閿�鍞鍗曚笉瀛樺湪");
+ }
+
+ SalesOrdersDto dto = new SalesOrdersDto();
+ dto.setSalesContractNo(salesLedger.getSalesContractNo());
+ dto.setCustomerName(salesLedger.getCustomerName());
+ dto.setProjectName(salesLedger.getProjectName());
+ dto.setSalesman(salesLedger.getSalesman());
+ dto.setExecutionDate(salesLedger.getExecutionDate() != null ? salesLedger.getExecutionDate().atStartOfDay() : null);
+ dto.setDeliveryDate(salesLedger.getDeliveryDate());
+ dto.setRemakes(salesLedger.getRemarks());
+ dto.setCompanyName("楣ゅ澶╂矏閽㈠寲鐜荤拑鍘�");
+
+ // 閫佽揣鍦板潃
+ if (salesLedger.getCustomerId() != null) {
+ Customer customer = customerMapper.selectById(salesLedger.getCustomerId());
+ if (customer != null) {
+ StringBuilder address = new StringBuilder();
+ if (customer.getRegionsId() != null) {
+ CustomerRegions regions = customerRegionsService.getById(customer.getRegionsId());
+ if (regions != null) {
+ address.append(regions.getRegionsName());
+ }
+ }
+ if (StringUtils.isNotEmpty(customer.getCompanyAddress())) {
+ address.append(customer.getCompanyAddress());
+ }
+ dto.setCompanyAddress(address.toString());
+ }
+ }
+
+ // 鍒跺崟鍛�
+ if (StringUtils.isNotEmpty(salesLedger.getEntryPerson())) {
+ try {
+ SysUser user = sysUserMapper.selectUserById(Long.parseLong(salesLedger.getEntryPerson()));
+ if (user != null) {
+ dto.setOrderMaker(user.getNickName());
+ }
+ } catch (Exception e) {
+ log.error("鑾峰彇鍒跺崟鍛樹俊鎭け璐�: {}", e.getMessage());
+ }
+ }
+ // 鍒跺崟鏃ユ湡 (搴曢儴)
+ dto.setOrderMakerDate(salesLedger.getExecutionDate() != null ? salesLedger.getExecutionDate().atStartOfDay() : null);
+
+ // 鎵撳嵃淇℃伅
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (loginUser != null && loginUser.getUser() != null) {
+ dto.setPrintPeople(loginUser.getUser().getNickName());
+ }
+ dto.setPrintTime(LocalDateTime.now());
+
+ // 鏌ヨ浜у搧鍒楄〃
+ List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>().eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId));
+
+ if (CollectionUtils.isNotEmpty(products)) {
+ SalesLedgerProduct firstProduct = products.get(0);
+ dto.setProductName(firstProduct.getProductCategory() != null ? firstProduct.getProductCategory() : "");
+ }
+
+ List<SalesOrdersDto.SalesOrderItemDto> itemDtos = new ArrayList<>();
+ BigDecimal subtotalQuantity = BigDecimal.ZERO;
+ BigDecimal subtotalArea = BigDecimal.ZERO;
+ BigDecimal subtotalAmount = BigDecimal.ZERO;
+
+ for (SalesLedgerProduct p : products) {
+ SalesOrdersDto.SalesOrderItemDto itemDto = new SalesOrdersDto.SalesOrderItemDto();
+ itemDto.setFloorCode(p.getFloorCode());
+ String desc = (p.getProductCategory() != null ? p.getProductCategory() : "") + (StringUtils.isNotBlank(p.getSpecificationModel()) ? " " + p.getSpecificationModel() : "");
+ itemDto.setProductDescription(desc.trim());
+ itemDto.setWidth(p.getWidth());
+ itemDto.setHeight(p.getHeight());
+ itemDto.setQuantity(p.getQuantity());
+
+ // 闈㈢Н璁$畻
+ BigDecimal area = p.getSettleTotalArea() != null ? p.getSettleTotalArea() : p.getActualTotalArea();
+ if (area == null && p.getWidth() != null && p.getHeight() != null && p.getQuantity() != null) {
+ area = p.getWidth().multiply(p.getHeight()).multiply(p.getQuantity()).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP);
+ }
+ itemDto.setArea(area);
+ itemDto.setUnitPrice(p.getTaxInclusiveUnitPrice());
+ itemDto.setAmount(p.getTaxInclusiveTotalPrice());
+ itemDto.setRemark(p.getRemark());
+ itemDto.setProcessRequirement(p.getProcessRequirement());
+
+ subtotalQuantity = subtotalQuantity.add(p.getQuantity() != null ? p.getQuantity() : BigDecimal.ZERO);
+ subtotalArea = subtotalArea.add(area != null ? area : BigDecimal.ZERO);
+ subtotalAmount = subtotalAmount.add(p.getTaxInclusiveTotalPrice() != null ? p.getTaxInclusiveTotalPrice() : BigDecimal.ZERO);
+
+ itemDtos.add(itemDto);
+ }
+ dto.setItems(itemDtos);
+ dto.setSubtotalQuantity(subtotalQuantity);
+ dto.setSubtotalArea(subtotalArea.setScale(2, RoundingMode.HALF_UP));
+ dto.setSubtotalAmount(subtotalAmount);
+
+ // 澶勭悊鍏朵粬璐圭敤
+ List<Long> productIds = products.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList());
+ BigDecimal otherFeesTotal = BigDecimal.ZERO;
+ if (CollectionUtils.isNotEmpty(productIds)) {
+ List<SalesLedgerProductProcessBind> binds = salesLedgerProductProcessBindService.list(new LambdaQueryWrapper<SalesLedgerProductProcessBind>().in(SalesLedgerProductProcessBind::getSalesLedgerProductId, productIds));
+
+ if (CollectionUtils.isNotEmpty(binds)) {
+ Map<Integer, Integer> processQuantityMap = binds.stream().collect(Collectors.groupingBy(SalesLedgerProductProcessBind::getSalesLedgerProductProcessId, Collectors.summingInt(b -> b.getQuantity() != null ? b.getQuantity() : 0)));
+
+ List<Integer> processIds = new ArrayList<>(processQuantityMap.keySet());
+ List<SalesLedgerProductProcess> processes = salesLedgerProductProcessService.listByIds(processIds);
+
+ List<SalesOrdersDto.OtherFeeDto> otherFeeDtos = new ArrayList<>();
+
+ for (SalesLedgerProductProcess proc : processes) {
+ SalesOrdersDto.OtherFeeDto feeDto = new SalesOrdersDto.OtherFeeDto();
+ feeDto.setFeeName(proc.getProcessName());
+ feeDto.setUnitPrice(proc.getUnitPrice());
+ Integer qty = processQuantityMap.get(proc.getId());
+ feeDto.setQuantity(new BigDecimal(qty != null ? qty : 0));
+ BigDecimal amount = proc.getUnitPrice() != null ? proc.getUnitPrice().multiply(feeDto.getQuantity()) : BigDecimal.ZERO;
+ feeDto.setAmount(amount);
+ otherFeeDtos.add(feeDto);
+ otherFeesTotal = otherFeesTotal.add(amount);
+ }
+ dto.setOtherFees(otherFeeDtos);
+ }
+ }
+
+ dto.setTotalQuantity(subtotalQuantity);
+ dto.setTotalArea(dto.getSubtotalArea());
+ dto.setTotalAmount(subtotalAmount.add(otherFeesTotal));
+ dto.setTotalAmountDisplay(dto.getTotalAmount().setScale(2, RoundingMode.HALF_UP).toString() + "鍏�");
+
+ return dto;
+ }
+
+ @Override
+ public SalesInvoicesDto salesInvoices(List<Long> salesLedgerIds) {
+ if (CollectionUtils.isEmpty(salesLedgerIds)) {
+ throw new ServiceException("閿�鍞彂璐у崟鎵撳嵃澶辫触,閿�鍞鍗曚笉鑳戒负绌�");
+ }
+
+ List<SalesLedger> ledgers = salesLedgerMapper.selectBatchIds(salesLedgerIds);
+ if (CollectionUtils.isEmpty(ledgers)) {
+ throw new ServiceException("閿�鍞彂璐у崟鎵撳嵃澶辫触,鏈壘鍒板搴斿彴璐﹁褰�");
+ }
+
+ Long customerId = ledgers.get(0).getCustomerId();
+ for (SalesLedger ledger : ledgers) {
+ if (!Objects.equals(customerId, ledger.getCustomerId())) {
+ throw new ServiceException("閿�鍞彂璐у崟鍚堝苟鎵撳嵃鍙兘鏄悓涓�涓鎴�");
+ }
+ }
+
+ SalesInvoicesDto dto = new SalesInvoicesDto();
+
+ Customer customer = customerMapper.selectById(customerId);
+ if (customer != null) {
+ dto.setCustomerName(customer.getCustomerName());
+ dto.setContactPerson(customer.getContactPerson());
+ dto.setContactPhone(customer.getContactPhone());
+
+ StringBuilder address = new StringBuilder();
+ if (customer.getRegionsId() != null) {
+ CustomerRegions regions = customerRegionsService.getById(customer.getRegionsId());
+ if (regions != null) {
+ address.append(regions.getRegionsName());
+ }
+ }
+ if (StringUtils.isNotEmpty(customer.getCompanyAddress())) {
+ address.append(customer.getCompanyAddress());
+ }
+ dto.setCompanyAddress(address.toString());
+ }
+
+ // 鍙戣揣鍗曞彿 (XF + 鏃ユ湡 + 搴忓垪)
+ String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
+ String redisKey = "sales:delivery:seq:" + dateStr;
+ Long seq = redisTemplate.opsForValue().increment(redisKey);
+ if (seq != null && seq == 1) {
+ redisTemplate.expire(redisKey, 48, TimeUnit.HOURS);
+ }
+ dto.setDeliveryNo("XF" + dateStr + String.format("%03d", seq != null ? seq : 1));
+
+ // 瀵规柟鍗曞彿
+// dto.setExternalOrderNo(ledgers.get(0).getCustomerContractNo());
+
+ // 鏌ヨ鎵�鏈変骇鍝�
+ List<SalesLedgerProduct> allProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>().in(SalesLedgerProduct::getSalesLedgerId, salesLedgerIds).eq(SalesLedgerProduct::getType, 1));
+
+ if (CollectionUtils.isNotEmpty(allProducts)) {
+ Map<Long, SalesLedger> ledgerMap = ledgers.stream().collect(Collectors.toMap(SalesLedger::getId, Function.identity()));
+
+ List<SalesInvoicesDto.InvoiceOrderGroupDto> groups = new ArrayList<>();
+ BigDecimal totalQty = BigDecimal.ZERO;
+ BigDecimal totalArea = BigDecimal.ZERO;
+
+ Map<String, List<SalesLedgerProduct>> groupedData = new LinkedHashMap<>();
+ Map<String, Set<String>> groupOrderNos = new LinkedHashMap<>();
+ for (SalesLedgerProduct p : allProducts) {
+ String productCategory = StringUtils.defaultString(p.getProductCategory(), "");
+ String specificationModel = StringUtils.defaultString(p.getSpecificationModel(), "");
+ String groupKey = productCategory + "||" + specificationModel;
+ groupedData.computeIfAbsent(groupKey, k -> new ArrayList<>()).add(p);
+
+ SalesLedger ledger = ledgerMap.get(p.getSalesLedgerId());
+ String orderNo = ledger != null ? StringUtils.defaultString(ledger.getSalesContractNo(), "") : "";
+ if (StringUtils.isNotEmpty(orderNo)) {
+ groupOrderNos.computeIfAbsent(groupKey, k -> new LinkedHashSet<>()).add(orderNo);
+ }
+ }
+
+ for (Map.Entry<String, List<SalesLedgerProduct>> productEntry : groupedData.entrySet()) {
+ String key = productEntry.getKey();
+ String[] parts = key.split("\\|\\|", -1);
+ String productName = parts.length > 0 ? parts[0] : "";
+ String specificationModel = parts.length > 1 ? parts[1] : "";
+ List<SalesLedgerProduct> products = productEntry.getValue();
+
+ SalesInvoicesDto.InvoiceOrderGroupDto group = new SalesInvoicesDto.InvoiceOrderGroupDto();
+ Set<String> orderNos = groupOrderNos.getOrDefault(key, Collections.emptySet());
+ group.setSalesContractNo(String.join(",", orderNos));
+ group.setProductName(productName);
+ group.setSpecificationModel(specificationModel);
+
+ Map<String, SalesInvoicesDto.InvoiceItemDto> mergedItems = new LinkedHashMap<>();
+ BigDecimal groupQty = BigDecimal.ZERO;
+ BigDecimal groupArea = BigDecimal.ZERO;
+
+ for (SalesLedgerProduct p : products) {
+ String widthHeight = (p.getWidth() != null ? p.getWidth().stripTrailingZeros().toPlainString() : "0") + " * " + (p.getHeight() != null ? p.getHeight().stripTrailingZeros().toPlainString() : "0");
+ String floorCode = StringUtils.defaultString(p.getFloorCode(), "");
+ String remark = StringUtils.defaultString(p.getRemark(), "");
+ String processReq = StringUtils.defaultString(p.getProcessRequirement(), "");
+ String itemKey = floorCode + "||" + widthHeight + "||" + remark + "||" + processReq;
+
+ BigDecimal qty = p.getQuantity() != null ? p.getQuantity() : BigDecimal.ZERO;
+
+ // 闈㈢Н
+ BigDecimal area = p.getSettleTotalArea() != null ? p.getSettleTotalArea() : p.getActualTotalArea();
+ if (area == null && p.getWidth() != null && p.getHeight() != null && p.getQuantity() != null) {
+ area = p.getWidth().multiply(p.getHeight()).multiply(p.getQuantity()).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP);
+ }
+ area = area != null ? area : BigDecimal.ZERO;
+
+ SalesInvoicesDto.InvoiceItemDto item = mergedItems.get(itemKey);
+ if (item == null) {
+ item = new SalesInvoicesDto.InvoiceItemDto();
+ item.setFloorCode(floorCode);
+ item.setWidthHeight(widthHeight);
+ item.setSpecificationModel(p.getSpecificationModel());
+ item.setQuantity(qty);
+ item.setArea(area);
+ item.setRemark(remark);
+ item.setProcessRequirement(processReq);
+ mergedItems.put(itemKey, item);
+ } else {
+ item.setQuantity((item.getQuantity() != null ? item.getQuantity() : BigDecimal.ZERO).add(qty));
+ item.setArea((item.getArea() != null ? item.getArea() : BigDecimal.ZERO).add(area));
+ }
+
+ groupQty = groupQty.add(qty);
+ groupArea = groupArea.add(area);
+ }
+
+ group.setItems(new ArrayList<>(mergedItems.values()));
+ group.setGroupTotalQuantity(groupQty);
+ group.setGroupTotalArea(groupArea.setScale(2, RoundingMode.HALF_UP));
+ groups.add(group);
+
+ totalQty = totalQty.add(groupQty);
+ totalArea = totalArea.add(groupArea);
+ }
+ dto.setGroups(groups);
+ dto.setTotalQuantity(totalQty);
+ dto.setTotalArea(totalArea.setScale(2, RoundingMode.HALF_UP));
+ }
+
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (loginUser != null && loginUser.getUser() != null) {
+ dto.setOrderMaker(loginUser.getUser().getNickName());
+ }
+ dto.setExecutionDate(LocalDateTime.now());
+
+ return dto;
+ }
+
+ @Override
+ public List<SalesLabelDto> salesLabel(Long salesLedgerId) {
+ if (salesLedgerId == null) {
+ throw new ServiceException("鎵撳嵃鏍囩澶辫触,鏁版嵁涓嶈兘涓虹┖");
+ }
+ SalesLedger salesLedger = baseMapper.selectById(salesLedgerId);
+ if (salesLedger == null) {
+ throw new ServiceException("鎵撳嵃澶辫触,閿�鍞鍗曚笉瀛樺湪");
+ }
+
+ // 鏌ヨ浜у搧鍒楄〃
+ List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>().eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId));
+
+ // 鏌ヨ瀹㈡埛鍦板潃
+ String fullAddress = "";
+ if (salesLedger.getCustomerId() != null) {
+ Customer customer = customerMapper.selectById(salesLedger.getCustomerId());
+ if (customer != null) {
+ StringBuilder addressSb = new StringBuilder();
+ if (customer.getRegionsId() != null) {
+ CustomerRegions regions = customerRegionsService.getById(customer.getRegionsId());
+ if (regions != null) {
+ addressSb.append(regions.getRegionsName());
+ }
+ }
+ if (StringUtils.isNotEmpty(customer.getCompanyAddress())) {
+ addressSb.append(customer.getCompanyAddress());
+ }
+ fullAddress = addressSb.toString();
+ }
+ }
+
+ List<SalesLabelDto> list = new ArrayList<>();
+ if (CollectionUtils.isNotEmpty(products)) {
+ for (SalesLedgerProduct p : products) {
+ SalesLabelDto dto = new SalesLabelDto();
+ dto.setCustomerName(salesLedger.getCustomerName());
+ dto.setSalesContractNo(salesLedger.getSalesContractNo());
+ dto.setProductName(p.getSpecificationModel());
+
+ // 瀹�*楂�=鏁伴噺
+ String specification = (p.getWidth() != null ? p.getWidth().stripTrailingZeros().toPlainString() : "0") + "*" + (p.getHeight() != null ? p.getHeight().stripTrailingZeros().toPlainString() : "0") + "=" + (p.getQuantity() != null ? p.getQuantity().stripTrailingZeros().toPlainString() : "0");
+ dto.setSpecification(specification);
+
+ // 瀹㈡埛鍦板潃 + 妤煎眰缂栧彿
+ dto.setFloorCode(fullAddress + (StringUtils.isNotEmpty(p.getFloorCode()) ? " " + p.getFloorCode() : ""));
+ list.add(dto);
+ }
+ }
+
+ return list;
}
private int findFirstMissingSequence(List<Integer> sequences) {
@@ -817,22 +1626,14 @@
return next;
}
- public <T, S> void updateMainContractAmount(
- Long mainId,
- List<T> subList,
- Function<T, BigDecimal> amountGetter,
- BaseMapper<S> mainMapper,
- Class<S> mainEntityClass) {
+ public <T, S> void updateMainContractAmount(Long mainId, List<T> subList, Function<T, BigDecimal> amountGetter, BaseMapper<S> mainMapper, Class<S> mainEntityClass) {
if (mainId == null || subList == null || subList.isEmpty()) {
return;
}
// 璁$畻瀛愯〃閲戦鎬诲拰
- BigDecimal totalAmount = subList.stream()
- .map(amountGetter)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal totalAmount = subList.stream().map(amountGetter).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
// 鏋勯�犱富琛ㄦ洿鏂板璞�
try {
@@ -880,4 +1681,1118 @@
return totalAmount;
}
}
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void salesStock(SalesProductStockDto dto) {
+ if (dto == null || dto.getSalesLedgerId() == null) {
+ throw new NullPointerException("鍏ュ簱澶辫触,璇烽�夋嫨闇�瑕佸叆搴撶殑閿�鍞鍗�");
+ }
+ // 鏌ヨ閿�鍞鍗曟槸鍚﹀瓨鍦�
+ SalesLedger ledger = baseMapper.selectById(dto.getSalesLedgerId());
+ if (ledger == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,閿�鍞鍗曚笉瀛樺湪");
+ }
+ if (ledger.getStockStatus() == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,閿�鍞鍗曞叆搴撶姸鎬佸紓甯�");
+ }
+ if (ledger.getStockStatus() == 3) {
+ throw new ServiceException("鍏ュ簱澶辫触,璇ラ攢鍞鍗曟鍦ㄥ叆搴撳鎵逛腑,璇峰嬁閲嶅鎻愪氦");
+ }
+ if (ledger.getStockStatus() == 2) {
+ throw new ServiceException("鍏ュ簱澶辫触,璇ラ攢鍞鍗曞凡鍏ュ簱,璇峰嬁閲嶅鍏ュ簱");
+ }
+ List<Long> products = dto.getSalesLedgerProducts();
+ if (products == null || products.isEmpty()) {
+ throw new ServiceException("鍏ュ簱澶辫触,鍏ュ簱浜у搧涓嶈兘涓虹┖");
+ }
+ // 鏌ヨ閿�鍞鍗曠殑浜у搧
+ List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().in(SalesLedgerProduct::getId, products));
+ if (salesLedgerProducts == null || salesLedgerProducts.isEmpty()) {
+ throw new ServiceException("鍏ュ簱澶辫触,鏈煡璇㈠埌璇ラ攢鍞鍗曠殑閿�鍞骇鍝�");
+ }
+ String approveUserIds = resolveApproveUserIds(dto.getApproveUserIds(), ledger.getId(), INBOUND_BIZ_TYPE_WEB);
+ if (StringUtils.isEmpty(approveUserIds)) {
+ throw new ServiceException("鍏ュ簱澶辫触,璇烽�夋嫨瀹℃壒浜�");
+ }
+
+ String productIds = products.stream().map(String::valueOf).collect(Collectors.joining(","));
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ ApproveProcessVO approveProcessVO = new ApproveProcessVO();
+ approveProcessVO.setApproveType(ApproveTypeEnum.STOCK_IN.getCode());
+ approveProcessVO.setApproveDeptId(loginUser.getCurrentDeptId());
+ approveProcessVO.setApproveReason("鍏ュ簱瀹℃壒:" + ledger.getSalesContractNo());
+ approveProcessVO.setApproveRemark("salesStock:" + ledger.getId() + ":" + productIds);
+ approveProcessVO.setApproveUserIds(approveUserIds);
+ approveProcessVO.setApproveUser(loginUser.getUserId());
+ approveProcessVO.setApproveTime(LocalDate.now().toString());
+ try {
+ approveProcessService.addApprove(approveProcessVO);
+ } catch (Exception e) {
+ throw new ServiceException("鍏ュ簱瀹℃壒鍙戣捣澶辫触:" + e.getMessage());
+ }
+ // 瀹℃壒涓�
+ ledger.setStockStatus(3);
+ baseMapper.updateById(ledger);
+ }
+
+ @Override
+ public void executeSalesStockApproved(Long salesLedgerId, List<Long> products) {
+ SalesProductStockDto dto = new SalesProductStockDto();
+ dto.setSalesLedgerId(salesLedgerId);
+ dto.setSalesLedgerProducts(products);
+
+ SalesLedger ledger = baseMapper.selectById(dto.getSalesLedgerId());
+ if (ledger == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,閿�鍞鍗曚笉瀛樺湪");
+ }
+ List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().in(SalesLedgerProduct::getId, products));
+ for (SalesLedgerProduct product : salesLedgerProducts) {
+ if (!Objects.equals(product.getSalesLedgerId(), ledger.getId())) {
+ throw new ServiceException("鍏ュ簱澶辫触,瀛樺湪涓嶅睘浜庡綋鍓嶉攢鍞鍗曠殑浜у搧");
+ }
+ if (product.getProductModelId() == null) {
+ continue;
+ }
+ BigDecimal orderQty = product.getQuantity() == null ? BigDecimal.ZERO : product.getQuantity();
+ BigDecimal oldStocked = product.getStockedQuantity() == null ? BigDecimal.ZERO : product.getStockedQuantity();
+ BigDecimal inboundQty = orderQty.subtract(oldStocked);
+ if (inboundQty.compareTo(BigDecimal.ZERO) < 0) {
+ inboundQty = BigDecimal.ZERO;
+ }
+ if (inboundQty.compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ StockInventoryDto stockInventoryDto = new StockInventoryDto();
+ stockInventoryDto.setRecordId(product.getId());
+ stockInventoryDto.setRecordType(StockInQualifiedRecordTypeEnum.SALE_STOCK_IN.getCode());
+ stockInventoryDto.setQualitity(inboundQty);
+ stockInventoryDto.setProductModelId(product.getProductModelId());
+ stockInventoryDto.setSalesLedgerId(ledger.getId());
+ stockInventoryDto.setSalesLedgerProductId(product.getId());
+ stockInventoryService.addstockInventory(stockInventoryDto);
+
+ BigDecimal newStocked = oldStocked.add(inboundQty);
+ int lineStockStatus;
+ if (newStocked.compareTo(BigDecimal.ZERO) <= 0) {
+ lineStockStatus = 0;
+ } else if (orderQty.compareTo(BigDecimal.ZERO) > 0 && newStocked.compareTo(orderQty) < 0) {
+ lineStockStatus = 1;
+ } else {
+ lineStockStatus = 2;
+ }
+ product.setStockedQuantity(newStocked);
+ product.setProductStockStatus(lineStockStatus);
+ product.fillRemainingQuantity();
+ salesLedgerProductMapper.updateById(product);
+ }
+ // 鎸夐攢鍞鍗曚骇鍝佸叆搴撴儏鍐垫洿鏂颁富鍗曞叆搴撶姸鎬侊細1-閮ㄥ垎鍏ュ簱锛�2-宸插叆搴�
+ List<SalesLedgerProduct> ledgerAllProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().eq(SalesLedgerProduct::getSalesLedgerId, ledger.getId()));
+ boolean hasStocked = CollectionUtils.isNotEmpty(ledgerAllProducts) && ledgerAllProducts.stream().anyMatch(item -> {
+ BigDecimal sq = item.getStockedQuantity();
+ return sq != null && sq.compareTo(BigDecimal.ZERO) > 0;
+ });
+ boolean allStocked = CollectionUtils.isNotEmpty(ledgerAllProducts) && ledgerAllProducts.stream().allMatch(item -> {
+ BigDecimal orderQty = item.getQuantity() == null ? BigDecimal.ZERO : item.getQuantity();
+ BigDecimal stockedQty = item.getStockedQuantity() == null ? BigDecimal.ZERO : item.getStockedQuantity();
+ return orderQty.compareTo(BigDecimal.ZERO) <= 0 || stockedQty.compareTo(orderQty) >= 0;
+ });
+ ledger.setStockStatus(allStocked ? 2 : (hasStocked ? 1 : 0));
+ baseMapper.updateById(ledger);
+ }
+
+ @Override
+ public List<Customer> shippedCustomers() {
+ List<SalesLedger> ledgers = list(Wrappers.<SalesLedger>lambdaQuery().eq(SalesLedger::getDeliveryStatus, 5).isNotNull(SalesLedger::getCustomerId).select(SalesLedger::getCustomerId));
+ if (CollectionUtils.isEmpty(ledgers)) {
+ return Collections.emptyList();
+ }
+ Set<Long> customerIds = ledgers.stream().map(SalesLedger::getCustomerId).collect(Collectors.toCollection(LinkedHashSet::new));
+ return customerMapper.selectList(Wrappers.<Customer>lambdaQuery().in(Customer::getId, customerIds).orderByAsc(Customer::getCustomerName));
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void scanInbound(SalesScanInboundDto dto) {
+ if (dto == null || dto.getSalesLedgerId() == null) {
+ throw new ServiceException("閿�鍞鍗曞叆搴撳け璐�,鍏ュ簱鏁版嵁涓嶈兘涓虹┖");
+ }
+
+ SalesLedger salesLedger = baseMapper.selectById(dto.getSalesLedgerId());
+ if (salesLedger == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,閿�鍞鍗曚笉瀛樺湪");
+ }
+ if (salesLedger.getStockStatus() == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,閿�鍞鍗曠姸鎬佸紓甯�");
+ }
+ if (salesLedger.getStockStatus() == 2) {
+ throw new ServiceException("鍏ュ簱澶辫触,璇ラ攢鍞鍗曞凡鍏ㄩ儴鍏ュ簱");
+ }
+ if (salesLedger.getDeliveryStatus() == 5) {
+ throw new ServiceException("鍏ュ簱澶辫触,璇ラ攢鍞鍗曞凡鍙戣揣");
+ }
+ if (CollectionUtils.isEmpty(dto.getSalesLedgerProductList())) {
+ throw new ServiceException("閿�鍞鍗曞叆搴撳け璐�,鍏ュ簱浜у搧涓嶈兘涓虹┖");
+ }
+ // 鏈鍏ュ簱鏁伴噺鍙互澶т簬璁㈠崟鏁伴噺,浣嗕笉鑳戒负璐�
+ Map<Long, BigDecimal> inboundQtyByLineId = new LinkedHashMap<>();
+ for (SalesLedgerProduct inbound : dto.getSalesLedgerProductList()) {
+ if (inbound == null || inbound.getId() == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,閿�鍞骇鍝佷俊鎭笉瀹屾暣");
+ }
+ BigDecimal inboundQty = inbound.getStockedQuantity();
+ if (inboundQty == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,鍏ュ簱鏁伴噺涓嶈兘涓虹┖");
+ }
+ if (inboundQty.compareTo(BigDecimal.ZERO) < 0) {
+ throw new ServiceException("鍏ュ簱澶辫触,鍏ュ簱鏁伴噺涓嶈兘涓鸿礋鏁�");
+ }
+ inboundQtyByLineId.merge(inbound.getId(), inboundQty, BigDecimal::add);
+ }
+ List<SalesLedgerProduct> selectedProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().in(SalesLedgerProduct::getId, inboundQtyByLineId.keySet()));
+ if (CollectionUtils.isEmpty(selectedProducts)) {
+ throw new ServiceException("鍏ュ簱澶辫触,鏈煡璇㈠埌鍏ュ簱浜у搧");
+ }
+ if (selectedProducts.size() != inboundQtyByLineId.size()) {
+ throw new ServiceException("鍏ュ簱澶辫触,閮ㄥ垎浜у搧涓嶅瓨鍦�");
+ }
+ for (SalesLedgerProduct selectedProduct : selectedProducts) {
+ if (!Objects.equals(selectedProduct.getSalesLedgerId(), salesLedger.getId())) {
+ throw new ServiceException("鍏ュ簱澶辫触,閿�鍞骇鍝佷笌璁㈠崟涓嶅尮閰�");
+ }
+ if (!Objects.equals(selectedProduct.getType(), SaleEnum.SALE.getCode())) {
+ throw new ServiceException("鍏ュ簱澶辫触,浠呮敮鎸侀攢鍞鍗曚骇鍝佽");
+ }
+ if (selectedProduct.getProductModelId() == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,浜у搧瑙勬牸鏈淮鎶�,鏃犳硶鍏ュ簱");
+ }
+ }
+ String approveUserIds = resolveApproveUserIds(dto.getApproveUserIds(), salesLedger.getId(), INBOUND_BIZ_TYPE_SCAN_QUALIFIED);
+ if (StringUtils.isEmpty(approveUserIds)) {
+ throw new ServiceException("鍏ュ簱澶辫触,璇烽�夋嫨瀹℃壒浜�");
+ }
+ String lines = inboundQtyByLineId.entrySet().stream().map(e -> e.getKey() + "@" + e.getValue().stripTrailingZeros().toPlainString()).collect(Collectors.joining(","));
+ String reason = "閿�鍞壂鐮佸悎鏍煎叆搴撳鎵�:" + salesLedger.getSalesContractNo();
+ String remark = "scanQualified:" + salesLedger.getId() + ":" + lines;
+ ApproveProcess exist = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>().eq(ApproveProcess::getApproveType, ApproveTypeEnum.STOCK_IN.getCode()).eq(ApproveProcess::getApproveRemark, remark).eq(ApproveProcess::getApproveDelete, 0).orderByDesc(ApproveProcess::getCreateTime).last("limit 1"));
+ if (exist != null && !Objects.equals(exist.getApproveStatus(), 3)) {
+ throw new ServiceException("鍏ュ簱澶辫触,璇ョ敵璇峰凡鎻愪氦瀹℃壒");
+ }
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ ApproveProcessVO approveProcessVO = new ApproveProcessVO();
+ approveProcessVO.setApproveType(ApproveTypeEnum.STOCK_IN.getCode());
+ approveProcessVO.setApproveDeptId(loginUser.getCurrentDeptId());
+ approveProcessVO.setApproveReason(reason);
+ approveProcessVO.setApproveRemark(remark);
+ approveProcessVO.setApproveUserIds(approveUserIds);
+ approveProcessVO.setApproveUser(loginUser.getUserId());
+ approveProcessVO.setApproveTime(LocalDate.now().toString());
+ try {
+ approveProcessService.addApprove(approveProcessVO);
+ } catch (Exception e) {
+ throw new ServiceException("鍏ュ簱瀹℃壒鍙戣捣澶辫触:" + e.getMessage());
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void executeSalesScanInboundApproved(Long salesLedgerId, Map<Long, BigDecimal> inboundQtyByLineId) {
+ SalesLedger salesLedger = baseMapper.selectById(salesLedgerId);
+ if (salesLedger == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,閿�鍞鍗曚笉瀛樺湪");
+ }
+ Long ledgerId = salesLedger.getId();
+ for (Map.Entry<Long, BigDecimal> entry : inboundQtyByLineId.entrySet()) {
+ Long salesLedgerProductId = entry.getKey();
+ BigDecimal inboundThisLine = entry.getValue();
+ if (inboundThisLine == null || inboundThisLine.compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ SalesLedgerProduct dbProduct = salesLedgerProductMapper.selectById(salesLedgerProductId);
+ if (dbProduct == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,閿�鍞骇鍝佷笉瀛樺湪");
+ }
+ if (!Objects.equals(dbProduct.getSalesLedgerId(), ledgerId)) {
+ throw new ServiceException("鍏ュ簱澶辫触,閿�鍞骇鍝佷笌璁㈠崟涓嶅尮閰�");
+ }
+ if (!Objects.equals(dbProduct.getType(), SaleEnum.SALE.getCode())) {
+ throw new ServiceException("鍏ュ簱澶辫触,浠呮敮鎸侀攢鍞鍗曚骇鍝佽");
+ }
+ if (dbProduct.getProductModelId() == null) {
+ throw new ServiceException("鍏ュ簱澶辫触,浜у搧瑙勬牸鏈淮鎶�,鏃犳硶鍏ュ簱");
+ }
+ BigDecimal oldStocked = dbProduct.getStockedQuantity() == null ? BigDecimal.ZERO : dbProduct.getStockedQuantity();
+ BigDecimal newStocked = oldStocked.add(inboundThisLine);
+
+ StockInventoryDto stockInventoryDto = new StockInventoryDto();
+ stockInventoryDto.setRecordId(dbProduct.getId());
+ stockInventoryDto.setRecordType(StockInQualifiedRecordTypeEnum.SALE_SCAN_STOCK_IN.getCode());
+ stockInventoryDto.setQualitity(inboundThisLine);
+ stockInventoryDto.setProductModelId(dbProduct.getProductModelId());
+ stockInventoryDto.setSalesLedgerId(ledgerId);
+ stockInventoryDto.setSalesLedgerProductId(dbProduct.getId());
+ stockInventoryService.addstockInventory(stockInventoryDto);
+
+ BigDecimal orderQty = dbProduct.getQuantity() == null ? BigDecimal.ZERO : dbProduct.getQuantity();
+ int lineStockStatus;
+ if (newStocked.compareTo(BigDecimal.ZERO) <= 0) {
+ lineStockStatus = 0;
+ } else if (orderQty.compareTo(BigDecimal.ZERO) > 0 && newStocked.compareTo(orderQty) < 0) {
+ lineStockStatus = 1;
+ } else {
+ lineStockStatus = 2;
+ }
+ dbProduct.setStockedQuantity(newStocked);
+ dbProduct.setProductStockStatus(lineStockStatus);
+ dbProduct.fillRemainingQuantity();
+ salesLedgerProductMapper.updateById(dbProduct);
+ }
+ List<SalesLedgerProduct> ledgerAllProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().eq(SalesLedgerProduct::getSalesLedgerId, ledgerId));
+ boolean anyInbound = ledgerAllProducts.stream().anyMatch(p -> {
+ BigDecimal sq = p.getStockedQuantity();
+ return sq != null && sq.compareTo(BigDecimal.ZERO) > 0;
+ });
+ boolean allLinesFull = ledgerAllProducts.stream().allMatch(p -> Objects.equals(p.getProductStockStatus(), 2));
+ salesLedger.setStockStatus(allLinesFull ? 2 : (anyInbound ? 1 : 0));
+ baseMapper.updateById(salesLedger);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void scanInboundUnqualified(SalesScanInboundDto dto) {
+ if (dto == null || dto.getSalesLedgerId() == null) {
+ throw new ServiceException("閿�鍞鍗曚笉鍚堟牸鍏ュ簱澶辫触,鍏ュ簱鏁版嵁涓嶈兘涓虹┖");
+ }
+ SalesLedger salesLedger = baseMapper.selectById(dto.getSalesLedgerId());
+ if (salesLedger == null) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,閿�鍞鍗曚笉瀛樺湪");
+ }
+ if (salesLedger.getDeliveryStatus() != null && salesLedger.getDeliveryStatus() == 5) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,璇ラ攢鍞鍗曞凡鍙戣揣");
+ }
+ if (CollectionUtils.isEmpty(dto.getSalesLedgerProductList())) {
+ throw new ServiceException("閿�鍞鍗曚笉鍚堟牸鍏ュ簱澶辫触,鍏ュ簱浜у搧涓嶈兘涓虹┖");
+ }
+ Map<Long, BigDecimal> inboundQtyByLineId = new LinkedHashMap<>();
+ for (SalesLedgerProduct inbound : dto.getSalesLedgerProductList()) {
+ if (inbound == null || inbound.getId() == null) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,閿�鍞骇鍝佷俊鎭笉瀹屾暣");
+ }
+ BigDecimal inboundQty = inbound.getStockedQuantity();
+ if (inboundQty == null) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,鍏ュ簱鏁伴噺涓嶈兘涓虹┖");
+ }
+ if (inboundQty.compareTo(BigDecimal.ZERO) < 0) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,鍏ュ簱鏁伴噺涓嶈兘涓鸿礋鏁�");
+ }
+ inboundQtyByLineId.merge(inbound.getId(), inboundQty, BigDecimal::add);
+ }
+ List<SalesLedgerProduct> selectedProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().in(SalesLedgerProduct::getId, inboundQtyByLineId.keySet()));
+ if (CollectionUtils.isEmpty(selectedProducts)) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,鏈煡璇㈠埌鍏ュ簱浜у搧");
+ }
+ if (selectedProducts.size() != inboundQtyByLineId.size()) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,閮ㄥ垎浜у搧涓嶅瓨鍦�");
+ }
+ for (SalesLedgerProduct selectedProduct : selectedProducts) {
+ if (!Objects.equals(selectedProduct.getSalesLedgerId(), salesLedger.getId())) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,閿�鍞骇鍝佷笌璁㈠崟涓嶅尮閰�");
+ }
+ if (!Objects.equals(selectedProduct.getType(), SaleEnum.SALE.getCode())) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,浠呮敮鎸侀攢鍞鍗曚骇鍝佽");
+ }
+ if (selectedProduct.getProductModelId() == null) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,浜у搧瑙勬牸鏈淮鎶�,鏃犳硶鍏ュ簱");
+ }
+ }
+ String approveUserIds = resolveApproveUserIds(dto.getApproveUserIds(), salesLedger.getId(), INBOUND_BIZ_TYPE_SCAN_UNQUALIFIED);
+ if (StringUtils.isEmpty(approveUserIds)) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,璇烽�夋嫨瀹℃壒浜�");
+ }
+ String lines = inboundQtyByLineId.entrySet().stream().map(e -> e.getKey() + "@" + e.getValue().stripTrailingZeros().toPlainString()).collect(Collectors.joining(","));
+ String reason = "閿�鍞壂鐮佷笉鍚堟牸鍏ュ簱瀹℃壒:" + salesLedger.getSalesContractNo();
+ String remark = "scanUnqualified:" + salesLedger.getId() + ":" + lines;
+ ApproveProcess exist = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>().eq(ApproveProcess::getApproveType, ApproveTypeEnum.STOCK_IN.getCode()).eq(ApproveProcess::getApproveRemark, remark).eq(ApproveProcess::getApproveDelete, 0).orderByDesc(ApproveProcess::getCreateTime).last("limit 1"));
+ if (exist != null && !Objects.equals(exist.getApproveStatus(), 3)) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,璇ョ敵璇峰凡鎻愪氦瀹℃壒");
+ }
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ ApproveProcessVO approveProcessVO = new ApproveProcessVO();
+ approveProcessVO.setApproveType(ApproveTypeEnum.STOCK_IN.getCode());
+ approveProcessVO.setApproveDeptId(loginUser.getCurrentDeptId());
+ approveProcessVO.setApproveReason(reason);
+ approveProcessVO.setApproveRemark(remark);
+ approveProcessVO.setApproveUserIds(approveUserIds);
+ approveProcessVO.setApproveUser(loginUser.getUserId());
+ approveProcessVO.setApproveTime(LocalDate.now().toString());
+ try {
+ approveProcessService.addApprove(approveProcessVO);
+ } catch (Exception e) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳鎵瑰彂璧峰け璐�:" + e.getMessage());
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void executeSalesScanInboundUnqualifiedApproved(Long salesLedgerId, Map<Long, BigDecimal> inboundQtyByLineId) {
+ SalesLedger salesLedger = baseMapper.selectById(salesLedgerId);
+ if (salesLedger == null) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,閿�鍞鍗曚笉瀛樺湪");
+ }
+ Long ledgerId = salesLedger.getId();
+ for (Map.Entry<Long, BigDecimal> entry : inboundQtyByLineId.entrySet()) {
+ Long salesLedgerProductId = entry.getKey();
+ BigDecimal inboundThisLine = entry.getValue();
+ if (inboundThisLine == null || inboundThisLine.compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ SalesLedgerProduct dbProduct = salesLedgerProductMapper.selectById(salesLedgerProductId);
+ if (dbProduct == null) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,閿�鍞骇鍝佷笉瀛樺湪");
+ }
+ if (!Objects.equals(dbProduct.getSalesLedgerId(), ledgerId)) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,閿�鍞骇鍝佷笌璁㈠崟涓嶅尮閰�");
+ }
+ if (!Objects.equals(dbProduct.getType(), SaleEnum.SALE.getCode())) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,浠呮敮鎸侀攢鍞鍗曚骇鍝佽");
+ }
+ if (dbProduct.getProductModelId() == null) {
+ throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,浜у搧瑙勬牸鏈淮鎶�,鏃犳硶鍏ュ簱");
+ }
+ stockUtils.addUnStock(ledgerId, dbProduct.getId(), dbProduct.getProductModelId(), inboundThisLine, StockInUnQualifiedRecordTypeEnum.SALES_SCAN_UNSTOCK_IN.getCode(), dbProduct.getId());
+ BigDecimal oldUnStocked = dbProduct.getUnqualifiedStockedQuantity() == null ? BigDecimal.ZERO : dbProduct.getUnqualifiedStockedQuantity();
+ dbProduct.setUnqualifiedStockedQuantity(oldUnStocked.add(inboundThisLine));
+ dbProduct.fillRemainingQuantity();
+ salesLedgerProductMapper.updateById(dbProduct);
+ }
+ }
+
+ private String resolveApproveUserIds(String approveUserIds, Long salesLedgerId, Integer bizType) {
+ if (StringUtils.isNotEmpty(approveUserIds)) {
+ return approveUserIds;
+ }
+ LambdaQueryWrapper<ApproveProcess> wrapper = new LambdaQueryWrapper<ApproveProcess>().eq(ApproveProcess::getApproveType, ApproveTypeEnum.STOCK_IN.getCode()).eq(ApproveProcess::getApproveDelete, 0).orderByDesc(ApproveProcess::getCreateTime).last("limit 1");
+ if (Objects.equals(bizType, INBOUND_BIZ_TYPE_WEB)) {
+ wrapper.likeRight(ApproveProcess::getApproveReason, "鍏ュ簱瀹℃壒:").likeRight(ApproveProcess::getApproveRemark, "salesStock:" + salesLedgerId + ":");
+ } else if (Objects.equals(bizType, INBOUND_BIZ_TYPE_SCAN_QUALIFIED)) {
+ wrapper.likeRight(ApproveProcess::getApproveReason, "閿�鍞壂鐮佸悎鏍煎叆搴撳鎵�:").likeRight(ApproveProcess::getApproveRemark, "scanQualified:" + salesLedgerId + ":");
+ } else if (Objects.equals(bizType, INBOUND_BIZ_TYPE_SCAN_UNQUALIFIED)) {
+ wrapper.likeRight(ApproveProcess::getApproveReason, "閿�鍞壂鐮佷笉鍚堟牸鍏ュ簱瀹℃壒:").likeRight(ApproveProcess::getApproveRemark, "scanUnqualified:" + salesLedgerId + ":");
+ } else {
+ return null;
+ }
+ ApproveProcess latest = approveProcessService.getOne(wrapper);
+ return latest == null ? null : latest.getApproveUserIds();
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void scanOutbound(SalesScanInboundDto dto) {
+ if (dto == null || dto.getSalesLedgerId() == null) {
+ throw new ServiceException("閿�鍞鍗曞嚭搴撳け璐�,鍑哄簱鏁版嵁涓嶈兘涓虹┖");
+ }
+ SalesLedger salesLedger = baseMapper.selectById(dto.getSalesLedgerId());
+ if (salesLedger == null) {
+ throw new ServiceException("鍑哄簱澶辫触,閿�鍞鍗曚笉瀛樺湪");
+ }
+ if (salesLedger.getDeliveryStatus() != null && salesLedger.getDeliveryStatus() == 5) {
+ throw new ServiceException("鍑哄簱澶辫触,璇ラ攢鍞鍗曞凡鍙戣揣");
+ }
+ if (CollectionUtils.isEmpty(dto.getSalesLedgerProductList())) {
+ throw new ServiceException("閿�鍞鍗曞嚭搴撳け璐�,鍑哄簱浜у搧涓嶈兘涓虹┖");
+ }
+ int saleType = SaleEnum.SALE.getCode();
+ Map<Long, BigDecimal> outboundQtyByLineId = new LinkedHashMap<>();
+ for (SalesLedgerProduct line : dto.getSalesLedgerProductList()) {
+ if (line == null || line.getId() == null) {
+ throw new ServiceException("鍑哄簱澶辫触,閿�鍞骇鍝佷俊鎭笉瀹屾暣");
+ }
+ BigDecimal outboundQty = line.getStockedQuantity();
+ if (outboundQty == null) {
+ throw new ServiceException("鍑哄簱澶辫触,鍑哄簱鏁伴噺涓嶈兘涓虹┖");
+ }
+ if (outboundQty.compareTo(BigDecimal.ZERO) < 0) {
+ throw new ServiceException("鍑哄簱澶辫触,鍑哄簱鏁伴噺涓嶈兘涓鸿礋鏁�");
+ }
+ outboundQtyByLineId.merge(line.getId(), outboundQty, BigDecimal::add);
+ }
+ Long ledgerId = salesLedger.getId();
+ for (Map.Entry<Long, BigDecimal> entry : outboundQtyByLineId.entrySet()) {
+ Long salesLedgerProductId = entry.getKey();
+ BigDecimal outboundThisLine = entry.getValue();
+ if (outboundThisLine.compareTo(BigDecimal.ZERO) == 0) {
+ continue;
+ }
+ SalesLedgerProduct dbProduct = salesLedgerProductMapper.selectById(salesLedgerProductId);
+ if (dbProduct == null) {
+ throw new ServiceException("鍑哄簱澶辫触,閿�鍞骇鍝佷笉瀛樺湪");
+ }
+ if (!Objects.equals(dbProduct.getSalesLedgerId(), ledgerId) || !Objects.equals(dbProduct.getType(), saleType)) {
+ throw new ServiceException("鍑哄簱澶辫触,閿�鍞骇鍝佷笌璁㈠崟涓嶅尮閰�");
+ }
+ if (dbProduct.getProductModelId() == null) {
+ throw new ServiceException("鍑哄簱澶辫触,浜у搧瑙勬牸鏈淮鎶�,鏃犳硶鍑哄簱");
+ }
+ stockUtils.assertQualifiedAvailable(dbProduct.getProductModelId(), outboundThisLine);
+
+ StockInventoryDto stockInventoryDto = new StockInventoryDto();
+ stockInventoryDto.setRecordId(dbProduct.getId());
+ stockInventoryDto.setRecordType(StockOutQualifiedRecordTypeEnum.SALE_SCAN_STOCK_OUT.getCode());
+ stockInventoryDto.setQualitity(outboundThisLine);
+ stockInventoryDto.setProductModelId(dbProduct.getProductModelId());
+ stockInventoryDto.setSalesLedgerId(ledgerId);
+ stockInventoryDto.setSalesLedgerProductId(dbProduct.getId());
+ stockInventoryService.subtractStockInventory(stockInventoryDto);
+
+ BigDecimal oldShipped = dbProduct.getShippedQuantity() == null ? BigDecimal.ZERO : dbProduct.getShippedQuantity();
+ dbProduct.setShippedQuantity(oldShipped.add(outboundThisLine));
+ dbProduct.fillRemainingQuantity();
+ salesLedgerProductMapper.updateById(dbProduct);
+ }
+ List<SalesLedgerProduct> ledgerAllProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().eq(SalesLedgerProduct::getSalesLedgerId, ledgerId));
+ boolean anyInbound = ledgerAllProducts.stream().anyMatch(p -> {
+ BigDecimal sq = p.getStockedQuantity();
+ return sq != null && sq.compareTo(BigDecimal.ZERO) > 0;
+ });
+ boolean allLinesFull = ledgerAllProducts.stream().allMatch(p -> Objects.equals(p.getProductStockStatus(), 2));
+ salesLedger.setStockStatus(allLinesFull ? 2 : (anyInbound ? 1 : 0));
+ baseMapper.updateById(salesLedger);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void scanOutboundUnqualified(SalesScanInboundDto dto) {
+ if (dto == null || dto.getSalesLedgerId() == null) {
+ throw new ServiceException("閿�鍞鍗曚笉鍚堟牸鍑哄簱澶辫触,鍑哄簱鏁版嵁涓嶈兘涓虹┖");
+ }
+ SalesLedger salesLedger = baseMapper.selectById(dto.getSalesLedgerId());
+ if (salesLedger == null) {
+ throw new ServiceException("涓嶅悎鏍煎嚭搴撳け璐�,閿�鍞鍗曚笉瀛樺湪");
+ }
+ if (salesLedger.getDeliveryStatus() != null && salesLedger.getDeliveryStatus() == 5) {
+ throw new ServiceException("涓嶅悎鏍煎嚭搴撳け璐�,璇ラ攢鍞鍗曞凡鍙戣揣");
+ }
+ if (CollectionUtils.isEmpty(dto.getSalesLedgerProductList())) {
+ throw new ServiceException("閿�鍞鍗曚笉鍚堟牸鍑哄簱澶辫触,鍑哄簱浜у搧涓嶈兘涓虹┖");
+ }
+ int saleType = SaleEnum.SALE.getCode();
+ Map<Long, BigDecimal> outboundQtyByLineId = new LinkedHashMap<>();
+ for (SalesLedgerProduct line : dto.getSalesLedgerProductList()) {
+ if (line == null || line.getId() == null) {
+ throw new ServiceException("涓嶅悎鏍煎嚭搴撳け璐�,閿�鍞骇鍝佷俊鎭笉瀹屾暣");
+ }
+ BigDecimal outboundQty = line.getStockedQuantity();
+ if (outboundQty == null) {
+ throw new ServiceException("涓嶅悎鏍煎嚭搴撳け璐�,鍑哄簱鏁伴噺涓嶈兘涓虹┖");
+ }
+ if (outboundQty.compareTo(BigDecimal.ZERO) < 0) {
+ throw new ServiceException("涓嶅悎鏍煎嚭搴撳け璐�,鍑哄簱鏁伴噺涓嶈兘涓鸿礋鏁�");
+ }
+ outboundQtyByLineId.merge(line.getId(), outboundQty, BigDecimal::add);
+ }
+ Long ledgerId = salesLedger.getId();
+ for (Map.Entry<Long, BigDecimal> entry : outboundQtyByLineId.entrySet()) {
+ Long salesLedgerProductId = entry.getKey();
+ BigDecimal outboundThisLine = entry.getValue();
+ if (outboundThisLine.compareTo(BigDecimal.ZERO) == 0) {
+ continue;
+ }
+ SalesLedgerProduct dbProduct = salesLedgerProductMapper.selectById(salesLedgerProductId);
+ if (dbProduct == null) {
+ throw new ServiceException("涓嶅悎鏍煎嚭搴撳け璐�,閿�鍞骇鍝佷笉瀛樺湪");
+ }
+ if (!Objects.equals(dbProduct.getSalesLedgerId(), ledgerId) || !Objects.equals(dbProduct.getType(), saleType)) {
+ throw new ServiceException("涓嶅悎鏍煎嚭搴撳け璐�,閿�鍞骇鍝佷笌璁㈠崟涓嶅尮閰�");
+ }
+ if (dbProduct.getProductModelId() == null) {
+ throw new ServiceException("涓嶅悎鏍煎嚭搴撳け璐�,浜у搧瑙勬牸鏈淮鎶�,鏃犳硶鍑哄簱");
+ }
+ BigDecimal unStocked = dbProduct.getUnqualifiedStockedQuantity() == null ? BigDecimal.ZERO : dbProduct.getUnqualifiedStockedQuantity();
+ BigDecimal unShipped = dbProduct.getUnqualifiedShippedQuantity() == null ? BigDecimal.ZERO : dbProduct.getUnqualifiedShippedQuantity();
+ BigDecimal canUnShip = unStocked.subtract(unShipped);
+ if (outboundThisLine.compareTo(canUnShip) > 0) {
+ throw new ServiceException("涓嶅悎鏍煎嚭搴撳け璐�,鍑哄簱鏁伴噺涓嶈兘澶т簬涓嶅悎鏍煎叆搴撴暟閲�");
+ }
+ stockUtils.assertUnqualifiedAvailable(dbProduct.getProductModelId(), outboundThisLine);
+ stockUtils.subtractUnStock(ledgerId, dbProduct.getId(), dbProduct.getProductModelId(), outboundThisLine, StockOutUnQualifiedRecordTypeEnum.SALE_SCAN_UNSTOCK_OUT.getCode(), dbProduct.getId());
+
+ dbProduct.setUnqualifiedShippedQuantity(unShipped.add(outboundThisLine));
+ dbProduct.fillRemainingQuantity();
+ salesLedgerProductMapper.updateById(dbProduct);
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void shippingImport(MultipartFile file) {
+ if (file == null || file.isEmpty()) {
+ throw new ServiceException("瀵煎叆澶辫触,瀵煎叆鏂囦欢鏁版嵁涓嶈兘涓虹┖");
+ }
+ List<SalesShippingImportDto> list;
+ try {
+ ExcelUtil<SalesShippingImportDto> excelUtil = new ExcelUtil<>(SalesShippingImportDto.class);
+ list = excelUtil.importExcel(file.getInputStream());
+ } catch (Exception e) {
+ log.error("閿�鍞彂璐у巻鍙叉暟鎹鍏�-宸插彂璐у鍏ュけ璐�: {}", e.getMessage());
+ throw new ServiceException("瀵煎叆澶辫触,鏁版嵁璇诲彇寮傚父");
+ }
+ if (CollectionUtils.isEmpty(list)) {
+ throw new ServiceException("瀵煎叆澶辫触,鏂囦欢鏁版嵁涓虹┖");
+ }
+ Map<String, List<SalesShippingImportDto>> groupedByOrderNo = list.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(SalesShippingImportDto::getOrderNo, LinkedHashMap::new, Collectors.toList()));
+
+ for (Map.Entry<String, List<SalesShippingImportDto>> entry : groupedByOrderNo.entrySet()) {
+ String orderNo = entry.getKey();
+ if (!StringUtils.hasText(orderNo)) {
+ throw new ServiceException("瀵煎叆澶辫触,瀛樺湪璁㈠崟缂栧彿涓虹┖鐨勬暟鎹�");
+ }
+ List<SalesShippingImportDto> rowList = entry.getValue();
+ if (CollectionUtils.isEmpty(rowList)) {
+ continue;
+ }
+ SalesLedger ledger = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>().eq(SalesLedger::getSalesContractNo, orderNo).last("LIMIT 1"));
+ if (ledger == null) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]涓嶅瓨鍦�,鏃犳硶琛ュ綍宸插彂璐ф暟鎹�");
+ }
+ List<SalesLedgerProduct> dbProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>().eq(SalesLedgerProduct::getSalesLedgerId, ledger.getId()).eq(SalesLedgerProduct::getType, SaleEnum.SALE.getCode()));
+ if (CollectionUtils.isEmpty(dbProducts)) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]娌℃湁閿�鍞骇鍝�,鏃犳硶琛ュ綍鍙戣揣");
+ }
+ Map<String, List<SalesLedgerProduct>> productByCategory = dbProducts.stream().collect(Collectors.groupingBy(p -> StringUtils.hasText(p.getProductCategory()) ? p.getProductCategory().trim() : ""));
+ Set<String> importedRowKeys = new HashSet<>();
+
+ for (SalesShippingImportDto row : rowList) {
+ BigDecimal shipQty = defaultDecimal(row.getQuantity());
+ if (shipQty.compareTo(BigDecimal.ZERO) <= 0) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]瀛樺湪鏁伴噺灏忎簬绛変簬0鐨勬暟鎹�");
+ }
+ String rowKey = buildShippingRowKey(ledger.getId(), row);
+ if (!importedRowKeys.add(rowKey)) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]瀛樺湪閲嶅鍙戣揣鏄庣粏琛�");
+ }
+ Map<SalesLedgerProduct, BigDecimal> allocations = allocateShippingProductLines(orderNo, row, productByCategory, dbProducts);
+ for (Map.Entry<SalesLedgerProduct, BigDecimal> alloc : allocations.entrySet()) {
+ SalesLedgerProduct dbProduct = alloc.getKey();
+ BigDecimal allocQty = alloc.getValue();
+ if (dbProduct.getProductModelId() == null) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]浜у搧瑙勬牸鏈淮鎶�,鏃犳硶琛ュ綍鍑哄簱");
+ }
+ BigDecimal oldShipped = defaultDecimal(dbProduct.getShippedQuantity());
+ BigDecimal newShipped = oldShipped.add(allocQty);
+ dbProduct.setStockedQuantity(defaultDecimal(dbProduct.getQuantity()));
+ dbProduct.setShippedQuantity(newShipped);
+ updateProductStockStatus(dbProduct);
+ dbProduct.fillRemainingQuantity();
+ updateProductShipStatus(dbProduct);
+ salesLedgerProductMapper.updateById(dbProduct);
+
+ ShippingInfo shippingInfo = new ShippingInfo();
+ shippingInfo.setSalesLedgerId(ledger.getId());
+ shippingInfo.setSalesLedgerProductId(dbProduct.getId());
+ shippingInfo.setStatus("宸插彂璐�");
+ shippingInfo.setShippingNo(row.getShippingNo());
+ shippingInfo.setType("璐ц溅");
+ shippingInfo.setShippingCarNumber("鏃�");
+ shippingInfo.setShippingDate(row.getReportDate());
+ long existedShippingCount = shippingInfoMapper.selectCount(new LambdaQueryWrapper<ShippingInfo>().eq(ShippingInfo::getSalesLedgerId, ledger.getId()).eq(ShippingInfo::getSalesLedgerProductId, dbProduct.getId()).eq(StringUtils.hasText(row.getShippingNo()), ShippingInfo::getShippingNo, row.getShippingNo()).eq(row.getReportDate() != null, ShippingInfo::getShippingDate, row.getReportDate()));
+ if (existedShippingCount > 0) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]瀛樺湪閲嶅鍙戣揣璁板綍,璇峰嬁閲嶅瀵煎叆");
+ }
+ shippingInfoMapper.insert(shippingInfo);
+ }
+ }
+
+ List<SalesLedgerProduct> latestProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>().eq(SalesLedgerProduct::getSalesLedgerId, ledger.getId()).eq(SalesLedgerProduct::getType, SaleEnum.SALE.getCode()));
+ boolean allShipped = CollectionUtils.isNotEmpty(latestProducts) && latestProducts.stream().allMatch(p -> {
+ BigDecimal qty = defaultDecimal(p.getQuantity());
+ BigDecimal shipped = defaultDecimal(p.getShippedQuantity());
+ return shipped.compareTo(qty) >= 0;
+ });
+ if (allShipped && rowList.get(0).getReportDate() != null) {
+ ledger.setDeliveryDate(DateUtils.toLocalDate(rowList.get(0).getReportDate()));
+ }
+ ledger.setDeliveryStatus(allShipped ? 5 : 1);
+ salesLedgerMapper.updateById(ledger);
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void notShippingImport(MultipartFile file) {
+ if (file == null || file.isEmpty()) {
+ throw new ServiceException("瀵煎叆澶辫触,瀵煎叆鏂囦欢鏁版嵁涓嶈兘涓虹┖");
+ }
+ List<SalesNotShippingImportDto> list;
+ try {
+ ExcelUtil<SalesNotShippingImportDto> excelUtil = new ExcelUtil<>(SalesNotShippingImportDto.class);
+ list = excelUtil.importExcel(file.getInputStream());
+ } catch (Exception e) {
+ log.error("閿�鍞彂璐у巻鍙叉暟鎹鍏�-鏈彂璐у鍏ュけ璐�: {}", e.getMessage());
+ throw new ServiceException("瀵煎叆澶辫触,鏁版嵁璇诲彇寮傚父");
+ }
+ if (CollectionUtils.isEmpty(list)) {
+ throw new ServiceException("瀵煎叆澶辫触,鏂囦欢鏁版嵁涓虹┖");
+ }
+ List<SysUser> allUsers = sysUserMapper.selectList(null);
+ Map<String, SysUser> userByNickNameMap = allUsers.stream().filter(Objects::nonNull).filter(u -> StringUtils.hasText(u.getNickName())).collect(Collectors.toMap(SysUser::getNickName, Function.identity(), (a, b) -> a));
+ Map<String, SysUser> userByUserNameMap = allUsers.stream().filter(Objects::nonNull).filter(u -> StringUtils.hasText(u.getUserName())).collect(Collectors.toMap(SysUser::getUserName, Function.identity(), (a, b) -> a));
+
+ Map<String, Customer> customerNameMap = customerMapper.selectList(null).stream().filter(Objects::nonNull).filter(c -> StringUtils.hasText(c.getCustomerName())).collect(Collectors.toMap(Customer::getCustomerName, Function.identity(), (a, b) -> a));
+ List<CustomerRegions> allRegions = customerRegionsService.list();
+ CustomerRegions hebiRegion = allRegions.stream().filter(Objects::nonNull).filter(r -> "楣ゅ".equals(r.getRegionsName())).findFirst().orElseGet(() -> {
+ CustomerRegions region = new CustomerRegions();
+ region.setRegionsName("楣ゅ");
+ region.setParentId(0L);
+ customerRegionsService.save(region);
+ return region;
+ });
+ Map<String, Product> productNameMap = productMapper.selectList(null).stream().filter(Objects::nonNull).filter(p -> StringUtils.hasText(p.getProductName())).collect(Collectors.toMap(Product::getProductName, Function.identity(), (a, b) -> a));
+ Product finishedGoodsParent = productNameMap.get("鎴愬搧");
+ if (finishedGoodsParent == null || finishedGoodsParent.getId() == null) {
+ finishedGoodsParent = new Product();
+ finishedGoodsParent.setProductName("鎴愬搧");
+ finishedGoodsParent.setParentId(null);
+ productMapper.insert(finishedGoodsParent);
+ productNameMap.put("鎴愬搧", finishedGoodsParent);
+ }
+ Map<String, ProductModel> productModelKeyMap = productModelMapper.selectList(null).stream().filter(Objects::nonNull).filter(m -> m.getProductId() != null && StringUtils.hasText(m.getModel())).collect(Collectors.toMap(m -> buildProductModelKey(m.getProductId(), m.getModel()), Function.identity(), (a, b) -> a));
+
+ List<String> extraProcessNames = Arrays.asList("鎵撳瓟", "鎸栫己", "瀹夊叏瑙�", "纾ㄨ竟");
+ Map<String, SalesLedgerProductProcess> processMap = salesLedgerProductProcessService.list(new LambdaQueryWrapper<SalesLedgerProductProcess>().in(SalesLedgerProductProcess::getProcessName, extraProcessNames)).stream().filter(Objects::nonNull).filter(p -> StringUtils.hasText(p.getProcessName())).collect(Collectors.toMap(SalesLedgerProductProcess::getProcessName, Function.identity(), (a, b) -> a));
+ List<ProcessRoute> processRoutes = processRouteMapper.selectList(new LambdaQueryWrapper<ProcessRoute>().eq(ProcessRoute::getProductModelId, 0L));
+ Map<String, ProcessRoute> routeNameMap = processRoutes.stream().filter(Objects::nonNull).filter(r -> StringUtils.hasText(r.getProcessRouteName())).collect(Collectors.toMap(r -> normalizeRouteFlowKey(r.getProcessRouteName()), Function.identity(), this::chooseBetterRoute));
+ Map<Long, List<ProcessRouteItem>> routeItemMap = Collections.emptyMap();
+ List<Long> routeIds = processRoutes.stream().map(ProcessRoute::getId).filter(Objects::nonNull).collect(Collectors.toList());
+ if (CollectionUtils.isNotEmpty(routeIds)) {
+ routeItemMap = processRouteItemMapper.selectList(new LambdaQueryWrapper<ProcessRouteItem>().in(ProcessRouteItem::getRouteId, routeIds).orderByAsc(ProcessRouteItem::getDragSort).orderByAsc(ProcessRouteItem::getId)).stream().filter(Objects::nonNull).collect(Collectors.groupingBy(ProcessRouteItem::getRouteId));
+ }
+
+ Map<String, List<SalesNotShippingImportDto>> groupedByOrderNo = list.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(SalesNotShippingImportDto::getOrderNo, LinkedHashMap::new, Collectors.toList()));
+
+ for (Map.Entry<String, List<SalesNotShippingImportDto>> entry : groupedByOrderNo.entrySet()) {
+ String orderNo = entry.getKey();
+ if (!StringUtils.hasText(orderNo)) {
+ throw new ServiceException("瀵煎叆澶辫触,瀛樺湪璁㈠崟缂栧彿涓虹┖鐨勬暟鎹�");
+ }
+ List<SalesNotShippingImportDto> rowList = entry.getValue();
+ if (CollectionUtils.isEmpty(rowList)) {
+ continue;
+ }
+ SalesNotShippingImportDto first = rowList.get(0);
+ SalesLedger exists = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>().eq(SalesLedger::getSalesContractNo, orderNo).last("LIMIT 1"));
+ if (exists != null) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]宸插瓨鍦�");
+ }
+
+ SalesLedger ledger = new SalesLedger();
+ SysUser creatorUser = resolveImportUser(first.getCreator(), userByNickNameMap, userByUserNameMap, "鍒跺崟鍛�", orderNo);
+ ledger.setSalesContractNo(orderNo);
+ ledger.setCustomerContractNo(first.getContractNo());
+ ledger.setProjectName(first.getProjectName());
+ ledger.setSalesman(first.getSalesman());
+ Customer customer = getOrCreateImportCustomer(first.getCustomerName(), customerNameMap, hebiRegion.getId());
+ ledger.setCustomerName(customer.getCustomerName());
+ ledger.setRemarks(first.getRemark());
+ ledger.setEntryPerson(String.valueOf(creatorUser.getUserId()));
+ ledger.setEntryDate(first.getReportDate());
+ if (first.getReportDate() != null) {
+ ledger.setExecutionDate(DateUtils.toLocalDate(first.getReportDate()));
+ }
+ ledger.setDeliveryDate(first.getDeliveryDeadline() == null ? (first.getReportDate() == null ? LocalDate.now().plusDays(7) : DateUtils.toLocalDate(first.getReportDate()).plusDays(7)) : DateUtils.toLocalDate(first.getDeliveryDeadline()));
+ ledger.setDeliveryStatus(1);
+ ledger.setStockStatus(0);
+
+ ledger.setCustomerId(customer.getId());
+ ledger.setCustomerContractNo(StringUtils.hasText(ledger.getCustomerContractNo()) ? ledger.getCustomerContractNo() : customer.getTaxpayerIdentificationNumber());
+
+ ledger.setContractAmount(BigDecimal.ZERO);
+ salesLedgerMapper.insert(ledger);
+ bindImportProcessRoute(ledger.getId(), rowList, routeNameMap, routeItemMap);
+
+ BigDecimal contractAmount = BigDecimal.ZERO;
+ for (SalesNotShippingImportDto row : rowList) {
+ SalesLedgerProduct product = new SalesLedgerProduct();
+ product.setSalesLedgerId(ledger.getId());
+ product.setType(SaleEnum.SALE.getCode());
+ String specificationModel = buildSpecificationModel(row);
+ Product importProduct = resolveOrCreateImportProduct(row, productNameMap, finishedGoodsParent, orderNo);
+ ProductModel importProductModel = resolveOrCreateImportProductModel(importProduct, specificationModel, row.getGlassThickness(), productModelKeyMap);
+ product.setProductCategory(row.getProductSubCategory());
+ product.setSpecificationModel(specificationModel);
+ product.setProductId(importProduct.getId());
+ product.setProductModelId(importProductModel.getId());
+ product.setFloorCode(row.getFloorNo());
+ product.setWidth(defaultDecimal(row.getWidth()));
+ product.setHeight(defaultDecimal(row.getHeight()));
+ product.setQuantity(defaultDecimal(row.getQuantity()));
+ product.setActualPieceArea(defaultDecimal(row.getActualSingleArea()));
+ product.setActualTotalArea(defaultDecimal(row.getActualTotalArea()));
+ product.setSettlePieceArea(defaultDecimal(row.getSettlementSingleArea()));
+ product.setSettleTotalArea(defaultDecimal(row.getSettlementTotalArea()));
+ product.setTaxInclusiveUnitPrice(defaultDecimal(row.getUnitPrice()));
+ product.setPerimeter(defaultDecimal(row.getPerimeter()));
+ product.setHeavyBox(defaultDecimal(row.getHeavyBox()));
+ product.setProcessRequirement(row.getProcessRequirement());
+ product.setRemark(StringUtils.hasText(row.getAuditRemark()) ? row.getAuditRemark() : row.getRemark());
+ product.setApproveStatus(0);
+ product.setProductStockStatus(0);
+ product.setRegister(creatorUser.getNickName());
+ product.setRegisterDate(row.getReportDate() == null ? LocalDateTime.now() : LocalDateTime.ofInstant(row.getReportDate().toInstant(), ZoneId.systemDefault()));
+
+ BigDecimal qty = defaultDecimal(product.getQuantity());
+ if (qty.compareTo(BigDecimal.ZERO) <= 0) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]瀛樺湪鏁伴噺灏忎簬绛変簬0鐨勬暟鎹�");
+ }
+
+ BigDecimal lineAmount = defaultDecimal(row.getGlassAmount()).add(defaultDecimal(row.getOtherProcessFee()));
+ if (lineAmount.compareTo(BigDecimal.ZERO) <= 0 && product.getTaxInclusiveUnitPrice().compareTo(BigDecimal.ZERO) > 0 && product.getSettleTotalArea().compareTo(BigDecimal.ZERO) > 0) {
+ lineAmount = product.getTaxInclusiveUnitPrice().multiply(product.getSettleTotalArea()).setScale(2, RoundingMode.HALF_UP);
+ }
+ product.setTaxRate(BigDecimal.ZERO);
+ product.setTaxInclusiveTotalPrice(lineAmount);
+ product.setTaxExclusiveTotalPrice(lineAmount);
+ product.setNoInvoiceNum(qty);
+ product.setNoInvoiceAmount(lineAmount);
+ product.setPendingInvoiceTotal(lineAmount);
+ product.fillRemainingQuantity();
+ salesLedgerProductMapper.insert(product);
+
+ List<SalesLedgerProductProcess> bindProcessList = buildImportProcessBinds(row, processMap);
+ if (CollectionUtils.isNotEmpty(bindProcessList)) {
+ salesLedgerProductProcessBindService.updateProductProcessBind(bindProcessList, product.getId());
+ }
+
+ salesLedgerProductServiceImpl.addProductionData(product);
+ contractAmount = contractAmount.add(lineAmount);
+ }
+
+ ledger.setContractAmount(contractAmount);
+ salesLedgerMapper.updateById(ledger);
+ }
+ }
+
+ private List<SalesLedgerProductProcess> buildImportProcessBinds(SalesNotShippingImportDto row, Map<String, SalesLedgerProductProcess> processMap) {
+ LinkedHashMap<String, Integer> processQuantityMap = new LinkedHashMap<>();
+ mergeProcessQuantity(processQuantityMap, "鎵撳瓟", toProcessQuantity(row.getDrilling()));
+ mergeProcessQuantity(processQuantityMap, "鎸栫己", toProcessQuantity(row.getNotching()));
+ mergeProcessQuantity(processQuantityMap, "瀹夊叏瑙�", toProcessQuantity(row.getSafetyCorner()));
+ mergeProcessQuantity(processQuantityMap, "纾ㄨ竟", toProcessQuantity(row.getGrindingIrregular()));
+
+ List<SalesLedgerProductProcess> result = new ArrayList<>();
+ for (Map.Entry<String, Integer> entry : processQuantityMap.entrySet()) {
+ if (entry.getValue() == null || entry.getValue() <= 0) {
+ continue;
+ }
+ SalesLedgerProductProcess process = processMap.get(entry.getKey());
+ if (process == null || process.getId() == null) {
+ log.warn("瀵煎叆宸ヨ壓鏈壘鍒伴厤缃�, processName={}, orderNo={}", entry.getKey(), row.getOrderNo());
+ continue;
+ }
+ SalesLedgerProductProcess bind = new SalesLedgerProductProcess();
+ bind.setId(process.getId());
+ bind.setQuantity(entry.getValue());
+ result.add(bind);
+ }
+ return result;
+ }
+
+ private void bindImportProcessRoute(Long salesLedgerId, List<SalesNotShippingImportDto> rowList, Map<String, ProcessRoute> routeNameMap, Map<Long, List<ProcessRouteItem>> routeItemMap) {
+ String flowKey = rowList.stream().map(SalesNotShippingImportDto::getProcessFlow).filter(StringUtils::hasText).map(this::normalizeRouteFlowKey).filter(StringUtils::hasText).findFirst().orElse("");
+ if (!StringUtils.hasText(flowKey)) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟宸ヨ壓娴佺▼涓嶈兘涓虹┖");
+ }
+ ProcessRoute route = routeNameMap.get(flowKey);
+ if (route == null || route.getId() == null) {
+ route = createImportProcessRoute(flowKey, routeNameMap, routeItemMap);
+ }
+ List<ProcessRouteItem> routeItems = routeItemMap.getOrDefault(route.getId(), Collections.emptyList());
+ if (CollectionUtils.isEmpty(routeItems)) {
+ route = createImportProcessRoute(flowKey, routeNameMap, routeItemMap);
+ routeItems = routeItemMap.getOrDefault(route.getId(), Collections.emptyList());
+ if (CollectionUtils.isEmpty(routeItems)) {
+ throw new ServiceException("瀵煎叆澶辫触,宸ヨ壓璺嚎[" + flowKey + "]鏈厤缃伐鑹鸿妭鐐�");
+ }
+ }
+ List<SalesLedgerProcessRoute> bindList = new ArrayList<>();
+ for (ProcessRouteItem item : routeItems) {
+ SalesLedgerProcessRoute bind = new SalesLedgerProcessRoute();
+ bind.setSalesLedgerId(salesLedgerId);
+ bind.setProcessRouteId(route.getId());
+ bind.setProcessRouteItemId(item.getId());
+ bind.setDragSort(item.getDragSort());
+ bindList.add(bind);
+ }
+ salesLedgerProcessRouteService.saveBatch(bindList);
+ }
+
+ private ProcessRoute createImportProcessRoute(String flowKey, Map<String, ProcessRoute> routeNameMap, Map<Long, List<ProcessRouteItem>> routeItemMap) {
+ List<String> processNames = Arrays.stream(flowKey.split("->")).filter(StringUtils::hasText).map(String::trim).collect(Collectors.toList());
+ if (CollectionUtils.isEmpty(processNames)) {
+ throw new ServiceException("瀵煎叆澶辫触,宸ヨ壓璺嚎[" + flowKey + "]瑙f瀽澶辫触");
+ }
+ ProcessRoute route = new ProcessRoute();
+ route.setProductModelId(0L);
+ route.setProcessRouteName(flowKey);
+ route.setIsDefault(0);
+ route.setDescription("");
+ route.setProcessRouteCode("AUTO_" + System.currentTimeMillis());
+ processRouteMapper.insert(route);
+ List<ProcessRouteItem> routeItems = new ArrayList<>();
+ for (int i = 0; i < processNames.size(); i++) {
+ ProcessRouteItem item = new ProcessRouteItem();
+ item.setRouteId(route.getId());
+ item.setProductModelId(0L);
+ item.setProcessId(0L);
+ item.setProcessName(processNames.get(i));
+ item.setDragSort(i + 1);
+ item.setIsQuality(Boolean.TRUE);
+ processRouteItemMapper.insert(item);
+ routeItems.add(item);
+ }
+ routeNameMap.put(flowKey, route);
+ routeItemMap.put(route.getId(), routeItems);
+ return route;
+ }
+
+ private void mergeProcessQuantity(Map<String, Integer> processQuantityMap, String processName, Integer quantity) {
+ if (!StringUtils.hasText(processName) || quantity == null || quantity <= 0) {
+ return;
+ }
+ Integer old = processQuantityMap.get(processName);
+ if (old == null || old <= 0) {
+ processQuantityMap.put(processName, quantity);
+ }
+ }
+
+ private String normalizeRouteFlowKey(String processFlow) {
+ if (!StringUtils.hasText(processFlow)) {
+ return "";
+ }
+ return Arrays.stream(processFlow.trim().split("\\s*(?:->|鈫抾=>|锛�)\\s*")).filter(StringUtils::hasText).map(String::trim).collect(Collectors.joining("->"));
+ }
+
+ private ProcessRoute chooseBetterRoute(ProcessRoute a, ProcessRoute b) {
+ if (a == null) {
+ return b;
+ }
+ if (b == null) {
+ return a;
+ }
+ boolean aDefault = Objects.equals(a.getIsDefault(), 1);
+ boolean bDefault = Objects.equals(b.getIsDefault(), 1);
+ if (aDefault != bDefault) {
+ return aDefault ? a : b;
+ }
+ LocalDateTime aTime = a.getCreateTime();
+ LocalDateTime bTime = b.getCreateTime();
+ if (aTime == null) {
+ return b;
+ }
+ if (bTime == null) {
+ return a;
+ }
+ return bTime.isAfter(aTime) ? b : a;
+ }
+
+ private Integer toProcessQuantity(BigDecimal value) {
+ if (value == null) {
+ return null;
+ }
+ if (value.compareTo(BigDecimal.ZERO) <= 0) {
+ return 0;
+ }
+ return value.setScale(0, RoundingMode.HALF_UP).intValue();
+ }
+
+ private SysUser resolveImportUser(String rawName, Map<String, SysUser> userByNickNameMap, Map<String, SysUser> userByUserNameMap, String fieldName, String orderNo) {
+ if (!StringUtils.hasText(rawName)) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]鐨刐" + fieldName + "]涓嶈兘涓虹┖");
+ }
+ String key = rawName.trim();
+ SysUser user = userByNickNameMap.get(key);
+ if (user == null) {
+ user = userByUserNameMap.get(key);
+ }
+ if (user == null || user.getUserId() == null) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]鐨刐" + fieldName + ":" + key + "]鏈尮閰嶅埌浜哄憳");
+ }
+ return user;
+ }
+
+ private Customer getOrCreateImportCustomer(String customerName, Map<String, Customer> customerNameMap, Long hebiRegionId) {
+ if (!StringUtils.hasText(customerName)) {
+ throw new ServiceException("瀵煎叆澶辫触,瀹㈡埛鍚嶇О涓嶈兘涓虹┖");
+ }
+ String key = customerName.trim();
+ Customer exists = customerNameMap.get(key);
+ if (exists != null && exists.getId() != null) {
+ return exists;
+ }
+ Customer customer = new Customer();
+ customer.setCustomerName(key);
+ customer.setRegionsId(hebiRegionId);
+ customerMapper.insert(customer);
+ customerNameMap.put(key, customer);
+ return customer;
+ }
+
+ private Product resolveOrCreateImportProduct(SalesNotShippingImportDto row, Map<String, Product> productNameMap, Product finishedGoodsParent, String orderNo) {
+ String productName = row.getProductName();
+ if (StringUtils.hasText(productName)) {
+ Product product = productNameMap.get(productName.trim());
+ if (product != null && product.getId() != null) {
+ return product;
+ }
+ }
+ String productSubCategory = row.getProductSubCategory();
+ if (StringUtils.hasText(productSubCategory)) {
+ Product product = productNameMap.get(productSubCategory.trim());
+ if (product != null && product.getId() != null) {
+ return product;
+ }
+ }
+ String newProductName = buildCategoryProductName(row);
+ if (!StringUtils.hasText(newProductName)) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]浜у搧鍚嶇О鍜屼骇鍝佸垎绫诲潎涓虹┖");
+ }
+ Product created = new Product();
+ created.setParentId(finishedGoodsParent == null ? null : finishedGoodsParent.getId());
+ created.setProductName(newProductName);
+ productMapper.insert(created);
+ productNameMap.put(newProductName, created);
+ return created;
+ }
+
+ private ProductModel resolveOrCreateImportProductModel(Product product, String modelName, BigDecimal thickness, Map<String, ProductModel> productModelKeyMap) {
+ if (product == null || product.getId() == null || !StringUtils.hasText(modelName)) {
+ throw new ServiceException("瀵煎叆澶辫触,浜у搧瑙勬牸鏁版嵁涓嶅畬鏁�");
+ }
+ String key = buildProductModelKey(product.getId(), modelName);
+ ProductModel exists = productModelKeyMap.get(key);
+ if (exists != null && exists.getId() != null) {
+ return exists;
+ }
+ ProductModel created = new ProductModel();
+ created.setProductId(product.getId());
+ created.setModel(modelName.trim());
+ created.setThickness(thickness);
+ productModelMapper.insert(created);
+ productModelKeyMap.put(key, created);
+ return created;
+ }
+
+ private String buildSpecificationModel(SalesNotShippingImportDto row) {
+ if (StringUtils.hasText(row.getProductName())) {
+ return row.getProductName().trim();
+ }
+ if (StringUtils.hasText(row.getProductSubCategory())) {
+ return row.getProductSubCategory().trim();
+ }
+ if (StringUtils.hasText(row.getProductCategory())) {
+ return row.getProductCategory().trim();
+ }
+ return "";
+ }
+
+ private String buildCategoryProductName(SalesNotShippingImportDto row) {
+ String category = row.getProductCategory();
+ String subCategory = row.getProductSubCategory();
+ if (StringUtils.hasText(category) && StringUtils.hasText(subCategory)) {
+ return category.trim() + "-" + subCategory.trim();
+ }
+ if (StringUtils.hasText(subCategory)) {
+ return subCategory.trim();
+ }
+ if (StringUtils.hasText(category)) {
+ return category.trim();
+ }
+ return "";
+ }
+
+ private String buildProductModelKey(Long productId, String modelName) {
+ return productId + "||" + modelName.trim();
+ }
+
+ private String buildCategoryProductName(SalesShippingImportDto row) {
+ String category = row.getProductCategory();
+ String subCategory = row.getProductSubCategory();
+ if (StringUtils.hasText(category) && StringUtils.hasText(subCategory)) {
+ return category.trim() + "-" + subCategory.trim();
+ }
+ if (StringUtils.hasText(subCategory)) {
+ return subCategory.trim();
+ }
+ if (StringUtils.hasText(category)) {
+ return category.trim();
+ }
+ return "";
+ }
+
+ private Integer parseInteger(String value) {
+ if (!StringUtils.hasText(value)) {
+ return 0;
+ }
+ try {
+ return new BigDecimal(value.trim()).setScale(0, RoundingMode.HALF_UP).intValue();
+ } catch (Exception e) {
+ return 0;
+ }
+ }
+
+ private Map<SalesLedgerProduct, BigDecimal> allocateShippingProductLines(String orderNo, SalesShippingImportDto row, Map<String, List<SalesLedgerProduct>> productByCategory, List<SalesLedgerProduct> allProducts) {
+ String subCategory = StringUtils.hasText(row.getProductSubCategory()) ? row.getProductSubCategory().trim() : "";
+ List<SalesLedgerProduct> candidates = productByCategory.getOrDefault(subCategory, Collections.emptyList());
+ if (CollectionUtils.isEmpty(candidates)) {
+ candidates = allProducts;
+ }
+ BigDecimal remaining = defaultDecimal(row.getQuantity());
+ Map<SalesLedgerProduct, BigDecimal> allocations = new LinkedHashMap<>();
+ for (SalesLedgerProduct p : candidates) {
+ BigDecimal qty = defaultDecimal(p.getQuantity());
+ BigDecimal shipped = defaultDecimal(p.getShippedQuantity());
+ BigDecimal canShip = qty.subtract(shipped);
+ if (canShip.compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ BigDecimal alloc = remaining.min(canShip);
+ if (alloc.compareTo(BigDecimal.ZERO) > 0) {
+ allocations.put(p, alloc);
+ remaining = remaining.subtract(alloc);
+ }
+ if (remaining.compareTo(BigDecimal.ZERO) <= 0) {
+ return allocations;
+ }
+ }
+ if (remaining.compareTo(BigDecimal.ZERO) > 0) {
+ throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]浜у搧[" + subCategory + "]鍙戣揣鏁伴噺瓒呭嚭鍓╀綑鍙彂鏁伴噺");
+ }
+ return allocations;
+ }
+
+ private void updateProductShipStatus(SalesLedgerProduct dbProduct) {
+ BigDecimal qty = defaultDecimal(dbProduct.getQuantity());
+ BigDecimal shipped = defaultDecimal(dbProduct.getShippedQuantity());
+ if (shipped.compareTo(BigDecimal.ZERO) <= 0) {
+ dbProduct.setProductStockStatus(0);
+ return;
+ }
+ dbProduct.setProductStockStatus(shipped.compareTo(qty) >= 0 ? 2 : 1);
+ }
+
+ private void updateProductStockStatus(SalesLedgerProduct dbProduct) {
+ BigDecimal qty = defaultDecimal(dbProduct.getQuantity());
+ BigDecimal stocked = defaultDecimal(dbProduct.getStockedQuantity());
+ if (stocked.compareTo(BigDecimal.ZERO) <= 0) {
+ dbProduct.setProductStockStatus(0);
+ return;
+ }
+ dbProduct.setProductStockStatus(stocked.compareTo(qty) >= 0 ? 2 : 1);
+ }
+
+ private String buildShippingRowKey(Long ledgerId, SalesShippingImportDto row) {
+ String shippingNo = StringUtils.hasText(row.getShippingNo()) ? row.getShippingNo().trim() : "";
+ String dateStr = row.getReportDate() == null ? "" : String.valueOf(row.getReportDate().getTime());
+ String subCategory = StringUtils.hasText(row.getProductSubCategory()) ? row.getProductSubCategory().trim() : "";
+ return ledgerId + "|" + subCategory + "|" + shippingNo + "|" + dateStr + "|" + defaultDecimal(row.getQuantity());
+ }
}
--
Gitblit v1.9.3