From 5a347be900bf045c947cdbc08167526cd44116db Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 12 十月 2026 18:18:50 +0800
Subject: [PATCH] fix(erp/crm): 单据明细单价口径由「不含税单价」改为「含税单价」
---
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java | 60 ++++++++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 46 insertions(+), 14 deletions(-)
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java
index c7bab33..e39f30e 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.crm.service.quotation;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@@ -26,6 +27,7 @@
import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -42,7 +44,7 @@
/**
* CRM 閿�鍞姤浠峰崟 Service 瀹炵幇绫�
*
- * @author 鑺嬮亾婧愮爜
+ * @author 瓒呯骇绠$悊鍛�
*/
@Service
@Validated
@@ -80,11 +82,11 @@
public Long createSaleQuotation(CrmSaleQuotationSaveReqVO createReqVO, Long userId) {
// 1.1 鏍¢獙鐗╂枡椤圭殑鏈夋晥鎬�
List<CrmSaleQuotationProductDO> quotationProducts = validateQuotationItems(createReqVO.getItems());
- // 1.2 鐢熸垚鎶ヤ环鍗曞彿锛屽苟鏍¢獙鍞竴鎬�
- String no = noRedisDAO.generate(CrmNoRedisDAO.SALE_QUOTATION_NO_PREFIX);
- if (saleQuotationMapper.selectByNo(no) != null) {
- throw exception(SALE_QUOTATION_NO_EXISTS);
- }
+ // 1.2 纭畾鎶ヤ环鍗曞彿锛堝墠绔~鍐欏垯鐢ㄨ嚜瀹氫箟鍗曞彿锛岀暀绌哄垯鑷姩鐢熸垚锛夛紝骞舵牎楠屽敮涓�鎬�
+ String customNo = StrUtil.trim(createReqVO.getNo());
+ String no = StrUtil.isBlank(customNo)
+ ? noRedisDAO.generate(CrmNoRedisDAO.SALE_QUOTATION_NO_PREFIX) : customNo;
+ validateQuotationNoUnique(no, null);
// 1.3 鏍¢獙鍏宠仈瀛楁
validateRelationDataExists(createReqVO);
@@ -122,17 +124,20 @@
// 1.4 鏍¢獙鍏宠仈瀛楁
validateRelationDataExists(updateReqVO);
- // 2.1 鏇存柊鎶ヤ环鍗�
+ // 2.1 鏇存柊鎶ヤ环鍗曪紙鎶ヤ环鍗曞彿鐣欑┖琛ㄧず淇濇寔鍘熷�硷紝濉啓鍒欐牎楠屽敮涓�鎬у悗鏇挎崲锛�
CrmSaleQuotationDO updateObj = BeanUtils.toBean(updateReqVO, CrmSaleQuotationDO.class);
+ String no = StrUtil.trim(updateReqVO.getNo());
+ if (StrUtil.isBlank(no)) {
+ updateObj.setNo(saleQuotation.getNo());
+ } else {
+ validateQuotationNoUnique(no, saleQuotation.getId());
+ updateObj.setNo(no);
+ }
calculateTotalPrice(updateObj, quotationProducts);
saleQuotationMapper.updateById(updateObj);
// 2.2 鏇存柊鎶ヤ环鏄庣粏
updateQuotationProductList(updateReqVO.getId(), quotationProducts);
- if (updateReqVO.getBlobIds() != null) {
- storageAttachmentApi.deleteAttachmentsByRecord("crm_sale_quotation", updateReqVO.getId());
- storageAttachmentApi.bindAttachments("file", "crm_sale_quotation",
- updateReqVO.getId(), updateReqVO.getBlobIds());
- }
+ storageAttachmentApi.updateAttachments("file", "crm_sale_quotation", updateReqVO.getId(), updateReqVO.getBlobIds());
}
@Override
@@ -170,6 +175,19 @@
return saleQuotation;
}
+ /**
+ * 鏍¢獙鎶ヤ环鍗曞彿鍞竴锛堝惈宸查�昏緫鍒犻櫎鐨勬姤浠峰崟锛屽洜 uk_no 鍞竴绱㈠紩瑕嗙洊宸插垹闄よ锛�
+ *
+ * @param no 鎶ヤ环鍗曞彿
+ * @param selfId 鑷韩缂栧彿锛堜慨鏀规椂鎺掗櫎鑷繁锛屾柊澧炰紶 null锛�
+ */
+ private void validateQuotationNoUnique(String no, Long selfId) {
+ CrmSaleQuotationDO exists = saleQuotationMapper.selectAnyByNo(no);
+ if (exists != null && !exists.getId().equals(selfId)) {
+ throw exception(SALE_QUOTATION_NO_EXISTS, no);
+ }
+ }
+
private List<CrmSaleQuotationProductDO> validateQuotationItems(List<CrmSaleQuotationSaveReqVO.Item> list) {
// 1. 鏍¢獙鐗╂枡瀛樺湪涓斿惎鐢�
Set<Long> itemIds = convertSet(list, CrmSaleQuotationSaveReqVO.Item::getItemId);
@@ -184,10 +202,14 @@
// 鐗╂枡鍘熶环锛屽鏋� MDM 涓病鏈夊垯榛樿涓� 0
item.setItemPrice(mdmItem.getSalesPrice() != null ? mdmItem.getSalesPrice() : BigDecimal.ZERO);
if (item.getQuotationPrice() != null && item.getCount() != null) {
- item.setTotalPrice(MoneyUtils.priceMultiply(item.getQuotationPrice(), item.getCount()));
+ // 鎶ヤ环涓哄惈绋庡崟浠凤細鍚◣閲戦 = 鍗曚环 脳 鏁伴噺锛涚◣棰� = 鍚◣閲戦 脳 绋庣巼锛涗笉鍚◣閲戦 = 鍚◣閲戦 - 绋庨
+ BigDecimal taxInclusivePrice = MoneyUtils.priceMultiply(item.getQuotationPrice(), item.getCount());
+ BigDecimal taxPrice = null;
if (item.getTaxPercent() != null) {
- item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent()));
+ taxPrice = MoneyUtils.priceMultiplyPercent(taxInclusivePrice, item.getTaxPercent());
}
+ item.setTaxPrice(taxPrice);
+ item.setTotalPrice(taxPrice != null ? taxInclusivePrice.subtract(taxPrice) : taxInclusivePrice);
}
}));
}
@@ -322,4 +344,14 @@
return contractId;
}
+ @Override
+ public CrmSaleQuotationDO getByContractId(Long id) {
+ return saleQuotationMapper.selectOne(new LambdaQueryWrapper<CrmSaleQuotationDO>().eq(CrmSaleQuotationDO::getContractId,id));
+ }
+
+ @Override
+ public void clearContractReference(Long quotationId) {
+ saleQuotationMapper.clearContractReference(quotationId);
+ }
+
}
\ No newline at end of file
--
Gitblit v1.9.3