From c7e7ed6d05cd1586b37396bcabc9f3f7e6ec589f Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期三, 21 十月 2026 16:08:51 +0800
Subject: [PATCH] feat(销售台账/产品维护): 图号必填唯一、合同号唯一、明细产品编码与导入物料编码
---
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java | 169 ++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 146 insertions(+), 23 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 6303b04..86ed7cf 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -12,16 +12,19 @@
import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
import com.ruoyi.account.pojo.sales.AccountInvoiceApplication;
import com.ruoyi.account.pojo.sales.AccountSalesCollection;
+import com.ruoyi.basic.dto.StorageAttachmentDTO;
import com.ruoyi.basic.enums.ApplicationTypeEnum;
import com.ruoyi.basic.enums.RecordTypeEnum;
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.ProductModel;
import com.ruoyi.basic.utils.FileUtil;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.enums.SaleEnum;
import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.AmountUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.EnumUtil;
import com.ruoyi.common.utils.SecurityUtils;
@@ -150,7 +153,7 @@
// 鏌ヨ閫�璐т俊鎭�
List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getProductModelId).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::getProductModelId, SimpleReturnOrderGroupDto::getSumReturnQuantity));
@@ -176,6 +179,7 @@
productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId());
productWrapper.eq(SalesLedgerProduct::getType, 1);
List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
+ AmountUtils.normalizeSalesLedgerProducts(products);
for (SalesLedgerProduct product : products) {
product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
product.setRegisterDate(LocalDateTime.now());
@@ -202,11 +206,18 @@
// 4. 杞崲 DTO
SalesLedgerDto resultDto = new SalesLedgerDto();
BeanUtils.copyProperties(salesLedger, resultDto);
+ AmountUtils.normalizeContractAmount(resultDto);
if (!products.isEmpty()) {
resultDto.setHasChildren(true);
resultDto.setProductData(products);
resultDto.setSalesLedgerFiles(salesLedgerFiles);
}
+
+ StorageAttachmentDTO attachmentQuery = new StorageAttachmentDTO();
+ attachmentQuery.setApplication(ApplicationTypeEnum.FILE.getType());
+ attachmentQuery.setRecordType(RecordTypeEnum.SALES_LEDGER.getType());
+ attachmentQuery.setRecordId(salesLedger.getId());
+ resultDto.setStorageBlobVOs(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(attachmentQuery));
return resultDto;
}
@@ -301,7 +312,7 @@
dto.setReceiptAmount(totalIncome);
//寮�绁ㄩ噾棰�
List<AccountInvoiceApplication> accountInvoiceApplications = accountInvoiceApplicationMapper.selectList(new LambdaQueryWrapper<AccountInvoiceApplication>()
- .eq(AccountInvoiceApplication::getStatus,1)
+ .eq(AccountInvoiceApplication::getStatus, 1)
.between(AccountInvoiceApplication::getApplyDate, startTime, endTime));
BigDecimal totalInvoiceAmount = Optional.of(
accountInvoiceApplications.stream()
@@ -317,7 +328,11 @@
@Override
public IPage<SalesLedgerVo> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto) {
- return salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto);
+ IPage<SalesLedgerVo> result = salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto);
+ if (!CollectionUtils.isEmpty(result.getRecords())) {
+ result.getRecords().forEach(AmountUtils::normalizeContractAmount);
+ }
+ return result;
}
@Override
@@ -347,13 +362,34 @@
// 褰曞叆浜烘暟鎹�
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) {
+ // 閿�鍞崟鍙烽噸澶嶆牎楠岋細鏂囦欢鍐呴噸澶嶆垨搴撳唴宸插瓨鍦ㄧ殑锛岀洿鎺ュけ璐ュ苟鍥炴樉鍘熸湁閿�鍞崟鍙�
+ List<String> duplicateContractNos = new ArrayList<>();
+ Set<String> importContractNos = new HashSet<>();
+ for (SalesLedgerImportDto item : salesLedgerImportDtoList) {
+ String contractNo = StringUtils.trim(item.getSalesContractNo());
+ if (StringUtils.isEmpty(contractNo)) {
continue;
}
+ if (!importContractNos.add(contractNo)) {
+ duplicateContractNos.add(contractNo);
+ }
+ }
+ if (CollectionUtils.isNotEmpty(duplicateContractNos)) {
+ return AjaxResult.error("瀵煎叆鏂囦欢涓瓨鍦ㄩ噸澶嶇殑閿�鍞崟鍙凤細" + String.join("銆�", duplicateContractNos));
+ }
+ if (CollectionUtils.isNotEmpty(importContractNos)) {
+ List<SalesLedger> existLedgers = salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>()
+ .in(SalesLedger::getSalesContractNo, importContractNos)
+ .select(SalesLedger::getId, SalesLedger::getSalesContractNo));
+ if (CollectionUtils.isNotEmpty(existLedgers)) {
+ String existNos = existLedgers.stream()
+ .map(SalesLedger::getSalesContractNo)
+ .distinct()
+ .collect(Collectors.joining("銆�"));
+ return AjaxResult.error("浠ヤ笅閿�鍞崟鍙峰凡瀛樺湪锛屼笉鑳介噸澶嶆柊澧烇細" + existNos);
+ }
+ }
+ for (SalesLedgerImportDto salesLedgerImportDto : salesLedgerImportDtoList) {
SalesLedger salesLedger = new SalesLedger();
BeanUtils.copyProperties(salesLedgerImportDto, salesLedger);
salesLedger.setExecutionDate(DateUtils.toLocalDate(salesLedgerImportDto.getExecutionDate()));
@@ -394,14 +430,29 @@
BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct);
salesLedgerProduct.setSalesLedgerId(salesLedger.getId());
salesLedgerProduct.setType(1);
+ // 鐗╂枡缂栫爜 -> 浜у搧缂栫爜
+ String materialCode = StringUtils.trim(salesLedgerProductImportDto.getMaterialCode());
+ if (StringUtils.isNotEmpty(materialCode)) {
+ salesLedgerProduct.setProductCode(materialCode);
+ }
+ AmountUtils.normalizeSalesLedgerProduct(salesLedgerProduct);
// 璁$畻涓嶅惈绋庢�讳环
- salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 2, RoundingMode.HALF_UP));
+ salesLedgerProduct.setTaxExclusiveTotalPrice(
+ AmountUtils.calcTaxExclusiveTotalPrice(
+ salesLedgerProduct.getTaxInclusiveTotalPrice(),
+ salesLedgerProduct.getTaxRate()
+ )
+ );
list.stream()
.filter(map -> Objects.equals(map.get("productName"), salesLedgerProduct.getProductCategory()) && Objects.equals(map.get("model"), salesLedgerProduct.getSpecificationModel()))
.findFirst()
.ifPresent(map -> {
salesLedgerProduct.setProductModelId(Long.parseLong(map.get("modelId").toString()));
salesLedgerProduct.setProductId(Long.parseLong(map.get("id").toString()));
+ // 鏈~鐗╂枡缂栫爜鏃讹紝鎸変骇鍝佸瀷鍙峰洖濉骇鍝佺紪鐮�
+ if (StringUtils.isEmpty(salesLedgerProduct.getProductCode()) && map.get("productCode") != null) {
+ salesLedgerProduct.setProductCode(map.get("productCode").toString());
+ }
});
// salesLedgerProduct.setProductId(productList.stream()
// .filter(product -> product.getProductName().equals(salesLedgerProduct.getProductCategory()))
@@ -416,7 +467,7 @@
salesLedgerProduct.setRegister(loginUser.getNickName());
salesLedgerProduct.setRegisterDate(LocalDateTime.now());
salesLedgerProduct.setApproveStatus(0);
- salesLedgerProduct.setIsProduction(salesLedgerProductImportDto.getIsProduction() == 1);
+ salesLedgerProduct.setIsProduction(parseProductionFlag(salesLedgerProductImportDto.getIsProduction()));
salesLedgerProductMapper.insert(salesLedgerProduct);
// 娣诲姞鐢熶骇鏁版嵁
salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
@@ -449,7 +500,7 @@
productWrapper.eq(SalesLedgerProduct::getType, 1);
List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
for (SalesLedgerProduct product : products) {
- product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
+ product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
product.setRegisterDate(LocalDateTime.now());
// 鍙戣揣淇℃伅
ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
@@ -510,6 +561,7 @@
// 鍒犻櫎閿�鍞鐞嗘暟鎹�
LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SalesLedgerProduct::getSalesLedgerId, idList)
+ .eq(SalesLedgerProduct::getType, 1)
.select(SalesLedgerProduct::getId);
List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(queryWrapper);
@@ -558,11 +610,17 @@
// 2. DTO杞珽ntity
SalesLedger salesLedger = convertToEntity(salesLedgerDto);
+ AmountUtils.normalizeContractAmount(salesLedger);
salesLedger.setCustomerName(customer.getCustomerName());
salesLedger.setTenantId(customer.getTenantId());
- // 3. 鏂板鎴栨洿鏂颁富琛�
+ // 3. 閿�鍞悎鍚屽彿鍞竴鏍¢獙锛堟敮鎸佸瓧姣嶃�佹暟瀛楀強鐗规畩瀛楃锛屼笉鍋氬瓧绗﹂泦闄愬埗锛�
+ String contractNo = StringUtils.trim(salesLedger.getSalesContractNo());
+ if (StringUtils.isNotEmpty(contractNo)) {
+ checkSalesContractNoUnique(contractNo, salesLedger.getId());
+ salesLedger.setSalesContractNo(contractNo);
+ }
+ // 4. 鏂板鎴栨洿鏂颁富琛�
if (salesLedger.getId() == null) {
- String contractNo = salesLedger.getSalesContractNo();
if (StringUtils.isEmpty(contractNo)) {
contractNo = generateSalesContractNo();
}
@@ -573,9 +631,10 @@
}
- // 4. 澶勭悊瀛愯〃鏁版嵁
+ // 5. 澶勭悊瀛愯〃鏁版嵁
List<SalesLedgerProduct> productList = salesLedgerDto.getProductData();
if (productList != null && !productList.isEmpty()) {
+ AmountUtils.normalizeSalesLedgerProducts(productList);
handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType()));
updateMainContractAmount(
salesLedger.getId(),
@@ -592,8 +651,31 @@
return 1;
}
+ /**
+ * 閿�鍞悎鍚屽彿鍞竴鏍¢獙锛堢紪杈戞椂鎺掗櫎鑷韩锛�
+ */
+ private void checkSalesContractNoUnique(String salesContractNo, Long currentId) {
+ LambdaQueryWrapper<SalesLedger> queryWrapper = new LambdaQueryWrapper<>();
+ queryWrapper.eq(SalesLedger::getSalesContractNo, salesContractNo)
+ .ne(currentId != null, SalesLedger::getId, currentId)
+ .last("limit 1");
+ SalesLedger duplicate = salesLedgerMapper.selectOne(queryWrapper);
+ if (duplicate != null) {
+ throw new BaseException("閿�鍞悎鍚屽彿" + salesContractNo + "宸插瓨鍦紙閿�鍞崟鍙凤細" + duplicate.getSalesContractNo() + "锛夛紝璇烽噸鏂板~鍐�");
+ }
+ }
+
@Override
public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) {
+ // 浜у搧缂栫爜鍏滃簳锛氬墠绔湭浼犳椂鎸変骇鍝佸瀷鍙峰洖濉�
+ products.forEach(p -> {
+ if (StringUtils.isEmpty(p.getProductCode()) && p.getProductModelId() != null) {
+ ProductModel productModel = productModelMapper.selectById(p.getProductModelId());
+ if (productModel != null) {
+ p.setProductCode(productModel.getProductCode());
+ }
+ }
+ });
// 鎸塈D鍒嗙粍锛屽尯鍒嗘柊澧炲拰鏇存柊鐨勮褰�
Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream()
.peek(p -> p.setSalesLedgerId(salesLedgerId))
@@ -605,6 +687,7 @@
// 鎵ц鏇存柊鎿嶄綔
if (!updateList.isEmpty()) {
for (SalesLedgerProduct product : updateList) {
+ AmountUtils.normalizeSalesLedgerProduct(product);
product.setType(type.getCode());
salesLedgerProductMapper.updateById(product);
}
@@ -612,12 +695,24 @@
// 鎵ц鎻掑叆鎿嶄綔
if (!insertList.isEmpty()) {
for (SalesLedgerProduct salesLedgerProduct : insertList) {
+ AmountUtils.normalizeSalesLedgerProduct(salesLedgerProduct);
salesLedgerProduct.setType(type.getCode());
salesLedgerProductMapper.insert(salesLedgerProduct);
// 娣诲姞鐢熶骇鏁版嵁
salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
}
}
+ }
+
+ /**
+ * 瑙f瀽瀵煎叆鐨勨�滄槸鍚︾敓浜р�濆垪锛氭敮鎸� 1/0銆佹槸/鍚�
+ */
+ private static boolean parseProductionFlag(String value) {
+ if (StringUtils.isEmpty(value)) {
+ return false;
+ }
+ String v = value.trim();
+ return "1".equals(v) || "鏄�".equals(v) || "true".equalsIgnoreCase(v) || "yes".equalsIgnoreCase(v);
}
private SalesLedger convertToEntity(SalesLedgerDto dto) {
@@ -656,14 +751,15 @@
}
// 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.longValue());
+// 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);
@@ -722,7 +818,7 @@
Field amountField = mainEntityClass.getDeclaredField("contractAmount");
amountField.setAccessible(true);
- amountField.set(entity, totalAmount);
+ amountField.set(entity, AmountUtils.scaleAmount(totalAmount));
mainMapper.updateById(entity);
} catch (Exception e) {
@@ -759,4 +855,31 @@
return totalAmount;
}
}
+
+ @Override
+ public Map<String, Object> getPrintData(Long id) {
+ SalesLedgerDto dto = new SalesLedgerDto();
+ dto.setId(id);
+ SalesLedgerDto ledger = getSalesLedgerWithProducts(dto);
+ if (ledger == null) {
+ return null;
+ }
+ SysDept dept = sysDeptMapper.selectDeptById(100L);
+ Map<String, Object> result = new HashMap<>();
+ result.put("companyName", dept != null ? dept.getDeptName() : "");
+ result.put("ledger", ledger);
+ return result;
+ }
+
+ @Override
+ public Map<Long, SalesLedgerEditFlagDto> getEditFlags(List<Long> ids) {
+ if (CollectionUtils.isEmpty(ids)) {
+ return new HashMap<>();
+ }
+ List<SalesLedgerEditFlagDto> flags = salesLedgerMapper.selectEditFlags(ids);
+ return flags.stream().collect(Collectors.toMap(
+ SalesLedgerEditFlagDto::getSalesLedgerId,
+ Function.identity(),
+ (existing, replacement) -> existing));
+ }
}
--
Gitblit v1.9.3