From 55d694aaae4e421b5e55cd941500e08f85cb5d4d Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期四, 27 八月 2026 18:21:33 +0800
Subject: [PATCH] feat(sales): 添加框架合同订单功能并优化销售台账管理
---
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java | 183 ++++++++++++++++++++++++++++++++++++---------
1 files changed, 146 insertions(+), 37 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 75ee5a6..3f223ca 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -1,6 +1,7 @@
package com.ruoyi.sales.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
@@ -38,8 +39,6 @@
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysDeptMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
-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.CommonFileMapper;
@@ -51,6 +50,7 @@
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.pojo.ShippingInfo;
import com.ruoyi.sales.service.ISalesLedgerService;
+import com.ruoyi.sales.vo.FrameworkOrderVo;
import com.ruoyi.sales.vo.SalesLedgerVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -66,7 +66,6 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.io.InputStream;
-import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
@@ -121,9 +120,6 @@
@Autowired
private ProductionProductMainService productionProductMainService;
@Autowired
- private PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
- ;
- @Autowired
private SysUserMapper sysUserMapper;
@Override
@@ -148,17 +144,11 @@
productWrapper.eq(SalesLedgerProduct::getType, type.getCode());
List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(productWrapper);
if (type.equals(SaleEnum.PURCHASE)) {
- // 鏌ヨ閫�璐т俊鎭�
- List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getProductModelId).collect(Collectors.toList());
- List<SimpleReturnOrderGroupDto> groupListByProductIds = new ArrayList<>();
- if(CollectionUtils.isNotEmpty(productIds)){
- groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds);
- }
- Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getProductModelId, SimpleReturnOrderGroupDto::getSumReturnQuantity));
salesLedgerProducts.forEach(item -> {
- BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getProductModelId(), BigDecimal.ZERO);
- item.setReturnQuality(returnQuality);
- item.setAvailableQuality(item.getQuantity().subtract(returnQuality));
+ BigDecimal returnQuantity = item.getReturnQuantity() == null ? BigDecimal.ZERO : item.getReturnQuantity();
+ item.setReturnQuantity(returnQuantity);
+ BigDecimal quantity = item.getQuantity() == null ? BigDecimal.ZERO : item.getQuantity();
+ item.setAvailableQuality(quantity.subtract(returnQuantity));
});
}
return salesLedgerProducts;
@@ -396,6 +386,7 @@
salesLedger.setContractAmount(salesLedgerProductImportDtos.stream()
.map(SalesLedgerProductImportDto::getTaxInclusiveTotalPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add));
+ salesLedger.setNetContractAmount(salesLedger.getContractAmount());
salesLedgerMapper.insert(salesLedger);
@@ -431,8 +422,7 @@
salesLedgerProduct.setApproveStatus(0);
salesLedgerProduct.setIsProduction(salesLedgerProductImportDto.getIsProduction() == 1);
salesLedgerProductMapper.insert(salesLedgerProduct);
- // 娣诲姞鐢熶骇鏁版嵁
- salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
+ addProductionDataIfNeeded(salesLedgerProduct);
}
}
@@ -518,6 +508,11 @@
if (CollectionUtils.isEmpty(idList)) {
return 0;
}
+ long childCount = salesLedgerMapper.selectCount(new LambdaQueryWrapper<SalesLedger>()
+ .in(SalesLedger::getParentContractId, idList));
+ if (childCount > 0) {
+ throw new BaseException("妗嗘灦鍚堝悓瀛樺湪妗嗘灦璁㈠崟锛屼笉鑳藉垹闄�");
+ }
// 鍒犻櫎閿�鍞鐞嗘暟鎹�
LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SalesLedgerProduct::getSalesLedgerId, idList)
@@ -561,6 +556,10 @@
@Override
@Transactional(rollbackFor = Exception.class)
public int addOrUpdateSalesLedger(SalesLedgerDto salesLedgerDto) {
+ log.info("addOrUpdateSalesLedger 鏀跺埌 contractType={}, parentContractId={}, id={}",
+ salesLedgerDto == null ? null : salesLedgerDto.getContractType(),
+ salesLedgerDto == null ? null : salesLedgerDto.getParentContractId(),
+ salesLedgerDto == null ? null : salesLedgerDto.getId());
// 1. 鏍¢獙瀹㈡埛淇℃伅
Customer customer = customerMapper.selectById(salesLedgerDto.getCustomerId());
if (customer == null) {
@@ -569,19 +568,27 @@
// 2. DTO杞珽ntity
SalesLedger salesLedger = convertToEntity(salesLedgerDto);
+ log.info("convertToEntity 鍚� contractType={}", salesLedger.getContractType());
salesLedger.setCustomerName(customer.getCustomerName());
salesLedger.setTenantId(customer.getTenantId());
+ // 褰曞叆浜猴細濡傛灉鏈紶鍒欎娇鐢ㄥ綋鍓嶇櫥褰曠敤鎴�
+ if (StringUtils.isEmpty(salesLedger.getEntryPerson())) {
+ salesLedger.setEntryPerson(String.valueOf(SecurityUtils.getUserId()));
+ }
// 3. 鏂板鎴栨洿鏂颁富琛�
if (salesLedger.getId() == null) {
String contractNo = salesLedger.getSalesContractNo();
if (StringUtils.isEmpty(contractNo)) {
- contractNo = generateSalesContractNo();
+ contractNo = generateSalesContractNo(salesLedgerDto.getEntryDate());
}
salesLedger.setSalesContractNo(contractNo);
salesLedgerMapper.insert(salesLedger);
} else {
salesLedgerMapper.updateById(salesLedger);
}
+ // 璇婃柇锛歩nsert/update 鍚庡洖鏌ユ暟鎹簱瀹為檯鍐欏叆鐨� contract_type
+ SalesLedger dbCheckLedger = salesLedgerMapper.selectById(salesLedger.getId());
+ log.info("DB 瀹為檯 contract_type={}, id={}", dbCheckLedger == null ? null : dbCheckLedger.getContractType(), salesLedger.getId());
// 4. 澶勭悊瀛愯〃鏁版嵁
@@ -597,10 +604,101 @@
);
}
- // 5. 淇濆瓨閿�鍞彴璐﹂檮浠�
+ // 5. 鍏滃簳锛氱‘淇濆疄闄呭悎鍚岄噾棰濇湁鍒濆鍊肩瓑浜庡悎鍚岄噾棰�
+ if (salesLedger.getNetContractAmount() == null) {
+ SalesLedger dbLedger = salesLedgerMapper.selectById(salesLedger.getId());
+ if (dbLedger != null && dbLedger.getNetContractAmount() == null && dbLedger.getContractAmount() != null) {
+ SalesLedger updateEntity = new SalesLedger();
+ updateEntity.setId(salesLedger.getId());
+ updateEntity.setNetContractAmount(dbLedger.getContractAmount());
+ salesLedgerMapper.updateById(updateEntity);
+ }
+ }
+
+ // 6. 淇濆瓨閿�鍞彴璐﹂檮浠�
fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.SALES_LEDGER, salesLedger.getId(), salesLedgerDto.getStorageBlobDTOs());
return 1;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int createFrameworkOrder(SalesLedgerDto dto) {
+ if (dto == null || dto.getId() == null) {
+ throw new BaseException("璇烽�夋嫨妗嗘灦鍚堝悓");
+ }
+ SalesLedger parent = salesLedgerMapper.selectById(dto.getId());
+ if (parent == null || !Objects.equals(parent.getContractType(), 2)) {
+ throw new BaseException("鐖跺彴璐︿笉鏄鏋跺悎鍚�");
+ }
+ if (CollectionUtils.isEmpty(dto.getProductData())) {
+ throw new BaseException("璇峰~鍐欐鏋惰鍗曚骇鍝�");
+ }
+ SalesLedger order = new SalesLedger();
+ order.setCustomerContractNo(parent.getCustomerContractNo());
+ order.setProjectName(parent.getProjectName());
+ order.setSalesman(parent.getSalesman());
+ order.setCustomerId(parent.getCustomerId());
+ order.setCustomerName(parent.getCustomerName());
+ order.setEntryPerson(String.valueOf(SecurityUtils.getUserId()));
+ order.setRemarks(dto.getRemarks());
+ order.setTenantId(parent.getTenantId());
+ order.setExecutionDate(parent.getExecutionDate());
+ order.setPaymentMethod(parent.getPaymentMethod());
+ order.setEntryDate(parent.getEntryDate());
+ order.setId(null);
+ order.setContractType(3);
+ order.setParentContractId(parent.getId());
+ order.setSalesContractNo(generateSalesContractNo(new Date()));
+ order.setDeliveryDate(null);
+ order.setContractAmount(BigDecimal.ZERO);
+ order.setNetContractAmount(BigDecimal.ZERO);
+ salesLedgerMapper.insert(order);
+
+ Set<Long> parentProductIds = dto.getProductData().stream()
+ .map(SalesLedgerProduct::getParentProductId)
+ .collect(Collectors.toSet());
+ if (parentProductIds.contains(null) || parentProductIds.size() != dto.getProductData().size()) {
+ throw new BaseException("妗嗘灦璁㈠崟浜у搧蹇呴』鍏宠仈涓嶅悓鐨勭埗浜у搧");
+ }
+ Map<Long, SalesLedgerProduct> parentProducts = salesLedgerProductMapper.selectBatchIds(parentProductIds).stream()
+ .collect(Collectors.toMap(SalesLedgerProduct::getId, Function.identity()));
+ for (SalesLedgerProduct requestProduct : dto.getProductData()) {
+ if (requestProduct.getDeliveryDate() == null) {
+ throw new BaseException("妗嗘灦璁㈠崟浜у搧蹇呴』鍏宠仈鐖朵骇鍝佸苟濉啓浜よ揣鏃ユ湡");
+ }
+ SalesLedgerProduct parentProduct = parentProducts.get(requestProduct.getParentProductId());
+ if (parentProduct == null || !Objects.equals(parentProduct.getSalesLedgerId(), parent.getId())
+ || !Objects.equals(parentProduct.getType(), SaleEnum.SALE.getCode())) {
+ throw new BaseException("妗嗘灦璁㈠崟浜у搧涓嶅睘浜庤妗嗘灦鍚堝悓");
+ }
+ SalesLedgerProduct product = new SalesLedgerProduct();
+ BeanUtils.copyProperties(parentProduct, product);
+ product.setId(null);
+ product.setSalesLedgerId(order.getId());
+ product.setParentProductId(parentProduct.getId());
+ product.setQuantity(null);
+ product.setDeliveryDate(requestProduct.getDeliveryDate());
+ product.setIsProduction(false);
+ product.setType(SaleEnum.SALE.getCode());
+ if (product.getTaxRate() == null) {
+ product.setTaxRate(BigDecimal.ZERO);
+ }
+ salesLedgerProductMapper.insert(product);
+ // 妗嗘灦璁㈠崟鍒涘缓鏃剁敓鎴愮敓浜ц鍒掞紙鏁伴噺鐣欑┖锛屼笅鍙戞椂濉啓锛�
+ salesLedgerProductServiceImpl.addProductionData(product);
+ }
+ return 1;
+ }
+
+ @Override
+ public List<FrameworkOrderVo> listFrameworkOrders(Long parentContractId) {
+ return salesLedgerMapper.listFrameworkOrders(parentContractId);
+ }
+
+ @Override
+ public BigDecimal getFrameworkContractShippedQuantity(Long parentContractId) {
+ return salesLedgerMapper.sumShippedByParentContract(parentContractId);
}
@Override
@@ -624,10 +722,20 @@
if (!insertList.isEmpty()) {
for (SalesLedgerProduct salesLedgerProduct : insertList) {
salesLedgerProduct.setType(type.getCode());
+ if (salesLedgerProduct.getTaxRate() == null) {
+ salesLedgerProduct.setTaxRate(BigDecimal.ZERO);
+ }
salesLedgerProductMapper.insert(salesLedgerProduct);
- // 娣诲姞鐢熶骇鏁版嵁
- salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
+ addProductionDataIfNeeded(salesLedgerProduct);
}
+ }
+ }
+
+ private void addProductionDataIfNeeded(SalesLedgerProduct product) {
+ SalesLedger ledger = salesLedgerMapper.selectById(product.getSalesLedgerId());
+ if (ledger != null && !Objects.equals(ledger.getContractType(), 2)
+ && !Objects.equals(ledger.getContractType(), 3)) {
+ salesLedgerProductServiceImpl.addProductionData(product);
}
}
@@ -638,8 +746,8 @@
}
@Transactional(readOnly = true)
- public String generateSalesContractNo() {
- LocalDate currentDate = LocalDate.now();
+ public String generateSalesContractNo(Date entryDate) {
+ LocalDate currentDate = entryDate != null ? DateUtils.toLocalDate(entryDate) : LocalDate.now();
String datePart = currentDate.format(DateTimeFormatter.BASIC_ISO_DATE);
String lockKey = LOCK_PREFIX + datePart;
String lockValue = Thread.currentThread().getId() + "-" + System.nanoTime(); // 鍞竴鏍囪瘑閿佹寔鏈夎��
@@ -724,21 +832,22 @@
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
- // 鏋勯�犱富琛ㄦ洿鏂板璞�
+ // 浠呮洿鏂伴噾棰濆垪锛岄伩鍏嶆暣瀹炰綋 updateById 鎶婂叾瀹冮潪绌哄瓧娈碉紙濡� contract_type 榛樿鍊� 1锛変竴骞惰鐩�
+ UpdateWrapper<S> wrapper = Wrappers.update();
+ wrapper.eq("id", mainId)
+ .set("contract_amount", totalAmount);
+ // 瀹為檯鍚堝悓閲戦鍒濆鍊肩瓑浜庡悎鍚岄噾棰�
+ boolean hasNetAmount;
try {
- S entity = mainEntityClass.getDeclaredConstructor().newInstance();
- Field idField = mainEntityClass.getDeclaredField("id");
- idField.setAccessible(true);
- idField.set(entity, mainId);
-
- Field amountField = mainEntityClass.getDeclaredField("contractAmount");
- amountField.setAccessible(true);
- amountField.set(entity, totalAmount);
-
- mainMapper.updateById(entity);
- } catch (Exception e) {
- throw new RuntimeException("鍔ㄦ�佹洿鏂颁富琛ㄩ噾棰濆け璐�", e);
+ mainEntityClass.getDeclaredField("netContractAmount");
+ hasNetAmount = true;
+ } catch (NoSuchFieldException e) {
+ hasNetAmount = false;
}
+ if (hasNetAmount) {
+ wrapper.set("net_contract_amount", totalAmount);
+ }
+ mainMapper.update(null, wrapper);
}
// 鍐呴儴绫荤敤浜庡瓨鍌ㄨ仛鍚堢粨鏋�
--
Gitblit v1.9.3