From b874abdeead386d24e0939b2e99e6d3bbbd4ec46 Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期五, 31 七月 2026 14:32:39 +0800
Subject: [PATCH] 商机金额修改

---
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java                    |   63 ++++++++++++++++++---
 docs/business_price_field_unification.md                                                                                   |   72 ++++++++++++++++++++++++
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java |   12 ++++
 3 files changed, 138 insertions(+), 9 deletions(-)

diff --git a/docs/business_price_field_unification.md b/docs/business_price_field_unification.md
new file mode 100644
index 0000000..099d2a7
--- /dev/null
+++ b/docs/business_price_field_unification.md
@@ -0,0 +1,72 @@
+# 鍟嗘満 price 瀛楁缁熶竴涓� businessPrice 鈥� 鍓嶇鑱旇皟鏂规
+
+## 闂鑳屾櫙
+
+鍓嶇浜у搧缂栬緫琛ㄤ娇鐢� `contractPrice` 浣滀负浠锋牸瀛楁鍙戦�佺粰鍚庣锛屼絾鍚庣浣跨敤鐨勬槸 `businessPrice`锛堝晢鏈轰环鏍硷級銆備袱鑰呮槸鍚屼竴涓蹇碉紝闇�瑕佺粺涓�涓� `businessPrice`銆�
+
+## 娑夊強椤甸潰
+
+- 鍟嗘満鏂板/缂栬緫寮圭獥锛坄src/views/crm/business/modules/form.vue`锛�
+- 浜у搧缂栬緫琛ㄧ粍浠讹紙`src/views/crm/product/components/edit-table.vue`锛�
+- 浜у搧缂栬緫琛ㄥ垪瀹氫箟锛坄src/views/crm/product/components/data.ts`锛�
+
+## API 璇存槑
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| PUT | `/crm/business/update` | 鏇存柊鍟嗘満 |
+| POST | `/crm/business/create` | 鏂板鍟嗘満 |
+
+**璇锋眰浣撳瓧娈靛彉鏇达紙`products[]` 鍐咃級锛�**
+
+| 瀛楁 | 鍙樻洿 | 璇存槑 |
+|------|------|------|
+| `contractPrice` | 鉂� 绉婚櫎 | 鏀逛负 `businessPrice` |
+| `businessPrice` | 鉁� 缁熶竴浣跨敤 | 鍟嗘満浠锋牸 |
+| `totalProductPrice` | 鉁� 宸叉湁 | 浜у搧鎬讳环锛堝悗绔凡鏂板鏀寔锛� |
+| `totalPrice` | 鉁� 宸叉湁 | 鍟嗘満鎬讳环锛堟姌鍚庯級锛堝悗绔凡鏂板鏀寔锛� |
+
+## 鍓嶇淇敼鐐�
+
+### 1. `edit-table.vue` 鈥� 瀛楁鍚� `contractPrice` 鈫� `businessPrice`
+
+鏂囦欢锛歚src/views/crm/product/components/edit-table.vue`
+
+娑夊強 6 澶勶細
+
+| 琛屽彿 | 淇敼 |
+|------|------|
+| 55 | `row.contractPrice` 鈫� `row.businessPrice` |
+| 57 | `row.contractPrice` 鈫� `row.businessPrice` |
+| 63 | `row.contractPrice` 鈫� `row.businessPrice` |
+| 70 | `row.contractPrice` 鈫� `row.businessPrice` |
+| 132 | `contractPrice` 鈫� `businessPrice`锛坱emplate slot name锛� |
+| 134 | `row.contractPrice` 鈫� `row.businessPrice`锛坴-model锛� |
+
+### 2. `data.ts` 鈥� 缂栬緫琛ㄥ垪瀹氫箟
+
+鏂囦欢锛歚src/views/crm/product/components/data.ts`
+
+绗� 91-95 琛岋紝缂栬緫琛紙闈� business 瑙嗗浘锛夌殑鍒楀畾涔夛細
+
+```
+field: 'contractPrice'  鈫�  field: 'businessPrice'
+title: '鍚堝悓浠凤紙鍏冿級'    鈫�  title: '鍟嗘満浠锋牸锛堝厓锛�'
+slots: { default: 'contractPrice' }  鈫�  slots: { default: 'businessPrice' }
+```
+
+## 涓氬姟瑙勫垯璇存槑
+
+| 鍦烘櫙 | 瑙勫垯 |
+|------|------|
+| 鏇存柊鍟嗘満鏃朵骇鍝� `businessPrice` 涓� null | 鍚庣鑷姩鐢ㄦ棫鏁版嵁鐨� `businessPrice` merge锛堟棤闇�鍓嶇澶勭悊锛� |
+| 鏂板鍟嗘満鏃� | `businessPrice` 蹇呭~锛屼笉鍙负 null |
+| 浜у搧 `totalPrice` | 鍓嶇鍙洿鎺ヤ紶璁$畻濂界殑鍊硷紝鍚庣浼樺厛浣跨敤锛涙湭浼犳椂鍚庣鐢� `businessPrice * count` 鑷姩璁$畻 |
+| 澶寸骇 `totalProductPrice` / `totalPrice` | 鍓嶇鍙洿鎺ヤ紶锛屽悗绔笉鍐嶈鐩� |
+
+## 娉ㄦ剰浜嬮」
+
+- **涓嶆秹鍙婄殑鏂囦欢**锛歚contract`銆乣statistics`銆乣report`銆乣saleTrace` 涓殑 `contractPrice` 鏄叾浠栦笟鍔℃蹇碉紝涓嶇敤鏀�
+- 浜у搧 `id` 瀛楁鍚庣宸叉柊澧炴敮鎸侊紝鏇存柊鏃朵紶 `id` 鍗冲彲鏍囪瘑宸叉湁浜у搧
+- 鍓嶇 `businessPrice` 鐨勫垵濮嬪寲鍊兼潵鑷� `product.salesPrice`锛堥�変腑浜у搧鏃剁殑榛樿浠凤級
+- 鏇存柊鏃跺彧闇�浼犺淇敼鐨勫瓧娈碉紝鏈紶瀛楁鍚庣鑷姩浠庢棫鏁版嵁缁ф壙
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java
index 13ab5bc..53059be 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java
@@ -58,6 +58,12 @@
     @NotNull(message = "鏁村崟鎶樻墸涓嶈兘涓虹┖")
     private BigDecimal discountPercent;
 
+    @Schema(description = "浜у搧鎬讳环", example = "12000.00")
+    private BigDecimal totalProductPrice;
+
+    @Schema(description = "鍟嗘満鎬讳环锛堟姌鍚庯級", example = "11280.00")
+    private BigDecimal totalPrice;
+
     @Schema(description = "澶囨敞", example = "闅忎究")
     @DiffLogField(name = "澶囨敞")
     private String remark;
@@ -73,6 +79,9 @@
     @NoArgsConstructor
     @AllArgsConstructor
     public static class BusinessProduct {
+
+        @Schema(description = "浜у搧鍏宠仈缂栧彿", example = "5")
+        private Long id;
 
         @Schema(description = "MDM 鐗╂枡缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529")
         @NotNull(message = "鐗╂枡缂栧彿涓嶈兘涓虹┖")
@@ -94,6 +103,9 @@
         @NotNull(message = "鏁伴噺涓嶈兘涓虹┖")
         private BigDecimal count;
 
+        @Schema(description = "鎬昏浠锋牸锛坆usinessPrice * count锛�", example = "12000.00")
+        private BigDecimal totalPrice;
+
     }
 
 }
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
index 263b383..0aaa4ec 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
@@ -134,8 +134,9 @@
         updateReqVO.setOwnerUserId(null).setStatusTypeId(null); // 涓嶅厑璁告洿鏂扮殑瀛楁
         // 1.1 鏍¢獙瀛樺湪
         CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId());
-        // 1.2 鏍¢獙浜у搧椤圭殑鏈夋晥鎬�
-        List<CrmBusinessProductDO> businessProducts = validateBusinessProducts(updateReqVO.getProducts());
+        // 1.2 鏍¢獙浜у搧椤圭殑鏈夋晥鎬э紙浼犲叆鏃т骇鍝佸垪琛ㄧ敤浜庡悎骞� null 瀛楁锛�
+        List<CrmBusinessProductDO> oldProducts = businessProductMapper.selectListByBusinessId(updateReqVO.getId());
+        List<CrmBusinessProductDO> businessProducts = validateBusinessProducts(updateReqVO.getProducts(), oldProducts);
         // 1.3 鏍¢獙鍏宠仈瀛楁
         validateRelationDataExists(updateReqVO);
 
@@ -147,7 +148,7 @@
         updateBusinessProduct(updateObj.getId(), businessProducts);
 
         // 3. 璁板綍鎿嶄綔鏃ュ織涓婁笅鏂�
-        updateReqVO.setOwnerUserId(oldBusiness.getOwnerUserId()); // 閬垮厤鎿嶄綔鏃ュ織鍑虹幇鈥滃垹闄よ礋璐d汉鈥濈殑鎯呭喌
+        updateReqVO.setOwnerUserId(oldBusiness.getOwnerUserId()); // 閬垮厤鎿嶄綔鏃ュ織鍑虹幇"鍒犻櫎璐熻矗浜�"鐨勬儏鍐�
         LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldBusiness, CrmBusinessSaveReqVO.class));
         LogRecordContext.putVariable("businessName", oldBusiness.getName());
     }
@@ -216,6 +217,18 @@
     }
 
     private List<CrmBusinessProductDO> validateBusinessProducts(List<CrmBusinessSaveReqVO.BusinessProduct> list) {
+        return validateBusinessProducts(list, Collections.emptyList());
+    }
+
+    /**
+     * 鏍¢獙浜у搧椤圭殑鏈夋晥鎬э紙鏇存柊鍦烘櫙鍚堝苟鏃ф暟鎹級
+     *
+     * @param list       鍓嶇浼犲叆鐨勪骇鍝佸垪琛�
+     * @param oldProducts 宸叉湁浜у搧鍒楄〃锛堢敤浜庡悎骞� null 瀛楁锛�
+     * @return 澶勭悊鍚庣殑浜у搧 DO 鍒楄〃
+     */
+    private List<CrmBusinessProductDO> validateBusinessProducts(List<CrmBusinessSaveReqVO.BusinessProduct> list,
+                                                                  List<CrmBusinessProductDO> oldProducts) {
         // 1. 鏍¢獙鐗╂枡瀛樺湪
         Set<Long> itemIds = convertSet(list, CrmBusinessSaveReqVO.BusinessProduct::getItemId);
         Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(itemIds);
@@ -224,15 +237,47 @@
                 throw exception(PRODUCT_NOT_EXISTS);
             }
         }
-        // 2. 杞寲涓� CrmBusinessProductDO 鍒楄〃
-        return convertList(list, o -> BeanUtils.toBean(o, CrmBusinessProductDO.class,
-                item -> item.setTotalPrice(MoneyUtils.priceMultiply(item.getBusinessPrice(), item.getCount()))));
+        // 2. 鏋勫缓鏃т骇鍝� Map锛堟寜 id 绱㈠紩锛�
+        Map<Long, CrmBusinessProductDO> oldProductMap = convertMap(oldProducts, CrmBusinessProductDO::getId);
+        // 3. 杞寲涓� CrmBusinessProductDO 鍒楄〃锛堝悎骞舵棫鏁版嵁锛�
+        return convertList(list, o -> {
+            CrmBusinessProductDO product = BeanUtils.toBean(o, CrmBusinessProductDO.class);
+            // 鏇存柊鍦烘櫙锛氬鏋滀骇鍝佸凡鏈� id 涓旀湁鏃ф暟鎹紝鍒欏悎骞� null 瀛楁
+            if (o.getId() != null && oldProductMap.containsKey(o.getId())) {
+                CrmBusinessProductDO old = oldProductMap.get(o.getId());
+                if (product.getBusinessPrice() == null) {
+                    product.setBusinessPrice(old.getBusinessPrice());
+                }
+                if (product.getItemPrice() == null) {
+                    product.setItemPrice(old.getItemPrice());
+                }
+                if (product.getCount() == null) {
+                    product.setCount(old.getCount());
+                }
+                if (product.getItemUnitId() == null) {
+                    product.setItemUnitId(old.getItemUnitId());
+                }
+            }
+            // 浼樺厛浣跨敤鍓嶇浼犲叆鐨� totalPrice锛屽惁鍒欓�氳繃 businessPrice * count 璁$畻
+            if (o.getTotalPrice() != null) {
+                product.setTotalPrice(o.getTotalPrice());
+            } else {
+                product.setTotalPrice(MoneyUtils.priceMultiply(product.getBusinessPrice(), product.getCount()));
+            }
+            return product;
+        });
     }
 
     private void calculateTotalPrice(CrmBusinessDO business, List<CrmBusinessProductDO> businessProducts) {
-        business.setTotalProductPrice(getSumValue(businessProducts, CrmBusinessProductDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO));
-        BigDecimal discountPrice = MoneyUtils.priceMultiplyPercent(business.getTotalProductPrice(), business.getDiscountPercent());
-        business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice));
+        // totalProductPrice锛氫紭鍏堜娇鐢ㄥ墠绔紶鍏ュ�硷紝鍚﹀垯浠庝骇鍝佹眹鎬�
+        if (business.getTotalProductPrice() == null) {
+            business.setTotalProductPrice(getSumValue(businessProducts, CrmBusinessProductDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO));
+        }
+        // totalPrice锛氫紭鍏堜娇鐢ㄥ墠绔紶鍏ュ�硷紝鍚﹀垯鎸夋姌鎵h绠�
+        if (business.getTotalPrice() == null) {
+            BigDecimal discountPrice = MoneyUtils.priceMultiplyPercent(business.getTotalProductPrice(), business.getDiscountPercent());
+            business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice));
+        }
     }
 
     @Override

--
Gitblit v1.9.3