Browse Source

Merge remote-tracking branch 'origin/xiaoman' into xiaoman

1018653686@qq.com 1 năm trước cách đây
mục cha
commit
34aabc04ae
52 tập tin đã thay đổi với 1633 bổ sung138 xóa
  1. 5 0
      code/src/test/java/DataSourceInfo.java
  2. 3 3
      code/src/test/java/SaleDataSource.java
  3. 1 1
      hx-admin/src/main/resources/application-test.yml
  4. 9 0
      hx-common/src/main/java/com/fjhx/common/enums/CodingRuleEnum.java
  5. 1 0
      hx-customer/src/main/java/com/fjhx/customer/contants/XiaomanContant.java
  6. 10 0
      hx-customer/src/main/java/com/fjhx/customer/controller/customer/CustomerController.java
  7. 0 7
      hx-customer/src/main/java/com/fjhx/customer/initializers/XiaomanInitializers.java
  8. 4 3
      hx-customer/src/main/java/com/fjhx/customer/mapper/customer/CustomerMapper.java
  9. 1 0
      hx-customer/src/main/java/com/fjhx/customer/service/customer/CustomerService.java
  10. 27 6
      hx-customer/src/main/java/com/fjhx/customer/service/customer/impl/CustomerServiceImpl.java
  11. 4 3
      hx-customer/src/main/java/com/fjhx/customer/service/xiaoman/XiaomanApiService.java
  12. 104 13
      hx-customer/src/main/java/com/fjhx/customer/service/xiaoman/impl/XiaomanApiServiceImpl.java
  13. 42 31
      hx-customer/src/main/java/com/fjhx/customer/service/xiaoman/impl/XiaomanCustomerServiceImpl.java
  14. 13 0
      hx-customer/src/main/resources/mapper/customer/CustomerMapper.xml
  15. 68 0
      hx-sale/src/main/java/com/fjhx/sale/controller/after/AfterSalesController.java
  16. 34 0
      hx-sale/src/main/java/com/fjhx/sale/controller/after/AfterSalesDetailController.java
  17. 49 0
      hx-sale/src/main/java/com/fjhx/sale/controller/after/AfterSalesRecordsController.java
  18. 11 1
      hx-sale/src/main/java/com/fjhx/sale/controller/contract/ContractProductController.java
  19. 17 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesDetailDto.java
  20. 17 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesDetailSelectDto.java
  21. 28 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesDto.java
  22. 25 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesRecordsDto.java
  23. 17 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesRecordsSelectDto.java
  24. 25 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesSelectDto.java
  25. 90 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/po/AfterSales.java
  26. 70 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/po/AfterSalesDetail.java
  27. 43 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/po/AfterSalesRecords.java
  28. 52 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/vo/AfterSalesDetailVo.java
  29. 22 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/vo/AfterSalesRecordsVo.java
  30. 24 0
      hx-sale/src/main/java/com/fjhx/sale/entity/after/vo/AfterSalesVo.java
  31. 19 0
      hx-sale/src/main/java/com/fjhx/sale/entity/contract/vo/ContractBudgetVo.java
  32. 2 0
      hx-sale/src/main/java/com/fjhx/sale/entity/contract/vo/ContractVo.java
  33. 148 0
      hx-sale/src/main/java/com/fjhx/sale/flow/AfterSalesFlow.java
  34. 7 0
      hx-sale/src/main/java/com/fjhx/sale/flow/ContractFlow.java
  35. 26 0
      hx-sale/src/main/java/com/fjhx/sale/mapper/after/AfterSalesDetailMapper.java
  36. 28 0
      hx-sale/src/main/java/com/fjhx/sale/mapper/after/AfterSalesMapper.java
  37. 23 0
      hx-sale/src/main/java/com/fjhx/sale/mapper/after/AfterSalesRecordsMapper.java
  38. 27 0
      hx-sale/src/main/java/com/fjhx/sale/service/after/AfterSalesDetailService.java
  39. 39 0
      hx-sale/src/main/java/com/fjhx/sale/service/after/AfterSalesRecordsService.java
  40. 42 0
      hx-sale/src/main/java/com/fjhx/sale/service/after/AfterSalesService.java
  41. 61 0
      hx-sale/src/main/java/com/fjhx/sale/service/after/impl/AfterSalesDetailServiceImpl.java
  42. 52 0
      hx-sale/src/main/java/com/fjhx/sale/service/after/impl/AfterSalesRecordsServiceImpl.java
  43. 156 0
      hx-sale/src/main/java/com/fjhx/sale/service/after/impl/AfterSalesServiceImpl.java
  44. 29 30
      hx-sale/src/main/java/com/fjhx/sale/service/contract/impl/ContractProductServiceImpl.java
  45. 37 3
      hx-sale/src/main/java/com/fjhx/sale/service/contract/impl/ContractServiceImpl.java
  46. 16 0
      hx-sale/src/main/java/com/fjhx/sale/service/purchase/impl/EhsdPurchaseServiceImpl.java
  47. 1 2
      hx-sale/src/main/java/com/fjhx/sale/service/sample/impl/SampleServiceImpl.java
  48. 10 0
      hx-sale/src/main/resources/mapper/after/AfterSalesDetailMapper.xml
  49. 39 0
      hx-sale/src/main/resources/mapper/after/AfterSalesMapper.xml
  50. 9 0
      hx-sale/src/main/resources/mapper/after/AfterSalesRecordsMapper.xml
  51. 35 18
      hx-sale/src/main/resources/mapper/contract/ContractMapper.xml
  52. 11 17
      hx-sale/src/main/resources/mapper/contract/ContractProductMapper.xml

+ 5 - 0
code/src/test/java/DataSourceInfo.java

@@ -0,0 +1,5 @@
+public class DataSourceInfo {
+    public final static String URL = "jdbc:mysql://121.37.194.75:30102/%s?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=Asia/Shanghai";
+    public final static String USER_NAME = "root";
+    public final static String PASSWORD = "5fWD*oa^nso@kmKa";
+}

+ 3 - 3
code/src/test/java/SaleDataSource.java

@@ -4,9 +4,9 @@ public class SaleDataSource {
 
     public static void main(String[] args) {
         GeneratorApplication.builder()
-                .url("jdbc:mysql://36.134.91.96:12333/bytesailing_sale?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true")
-                .username("root")
-                .password("Fjhx@pwd123")
+                .url(String.format(DataSourceInfo.URL, "bytesailing_sale"))
+                .username(DataSourceInfo.USER_NAME)
+                .password(DataSourceInfo.PASSWORD)
                 .port(9989)
                 .module("hx-sale")
                 .parent("com.fjhx.sale")

+ 1 - 1
hx-admin/src/main/resources/application-test.yml

@@ -104,7 +104,7 @@ server:
 
 mail:
     # 调用邮箱服务url前缀
-    urlPrefix: http://localhost:8089/mailService/
+    urlPrefix:
     abroadUrlPrefix:
 
 hx:

+ 9 - 0
hx-common/src/main/java/com/fjhx/common/enums/CodingRuleEnum.java

@@ -116,6 +116,15 @@ public enum CodingRuleEnum {
             getDefaultRule(RuleTypeEnum.DATE_FORMAT, "yyyyMM-"),
             getDefaultRule(RuleTypeEnum.AUTOINCREMENT, "3")
     )),
+
+    /**
+     * 售后
+     */
+    AFTER_SALES("AFTER_SALES", "售后管理", Arrays.asList(
+            getDefaultRule(RuleTypeEnum.CUSTOMIZE, "AS-"),
+            getDefaultRule(RuleTypeEnum.DATE_FORMAT, "yyyyMM-"),
+            getDefaultRule(RuleTypeEnum.AUTOINCREMENT, "3")
+    )),
     ;
 
     /**

+ 1 - 0
hx-customer/src/main/java/com/fjhx/customer/contants/XiaomanContant.java

@@ -29,4 +29,5 @@ public class XiaomanContant {
 
     /**小满redis缓存key**/
     public static final String TOKEN_KEY = "xiaoman_token_key";
+    public static final String ALL_CUSTOMER_PAGE_INDEX_KEY = "all_customer_page_index_key";
 }

+ 10 - 0
hx-customer/src/main/java/com/fjhx/customer/controller/customer/CustomerController.java

@@ -7,8 +7,11 @@ import com.fjhx.customer.entity.customer.dto.CustomerDto;
 import com.fjhx.customer.entity.customer.dto.CustomerSelectDto;
 import com.fjhx.customer.entity.customer.vo.CustomerVo;
 import com.fjhx.customer.service.customer.CustomerService;
+import com.fjhx.customer.service.xiaoman.XiaomanApiService;
 import com.ruoyi.common.core.domain.BaseSelectDto;
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -25,6 +28,7 @@ import java.util.Map;
  * @author
  * @since 2023-04-04
  */
+@Slf4j
 @DS(SourceConstant.CUSTOMER)
 @RestController
 @RequestMapping("/customer")
@@ -80,6 +84,12 @@ public class CustomerController {
     @PostMapping("/edit")
     public void edit(@RequestBody CustomerDto customerDto) {
         customerService.edit(customerDto);
+
+        try {
+            SpringUtils.getBean(XiaomanApiService.class).updateXiaomanData(customerDto);
+        } catch (Exception e) {
+            log.error("将客户信息 更新到小满失败!", e);
+        }
     }
 
     /**

+ 0 - 7
hx-customer/src/main/java/com/fjhx/customer/initializers/XiaomanInitializers.java

@@ -2,26 +2,19 @@ package com.fjhx.customer.initializers;
 
 import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.util.HashUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.crypto.digest.DigestUtil;
 import com.fjhx.customer.entity.xiaoman.po.XiaomanConfig;
-import com.fjhx.customer.entity.xiaoman.vo.XiaomanUpdateInfoVO;
-import com.fjhx.customer.handle.HandleXiaomanData;
 import com.fjhx.customer.service.xiaoman.XiaomanApiService;
 import com.fjhx.customer.service.xiaoman.XiaomanConfigService;
-import com.ruoyi.common.utils.sign.Md5Utils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Date;
-import java.util.List;
 
 @Component
 @Slf4j

+ 4 - 3
hx-customer/src/main/java/com/fjhx/customer/mapper/customer/CustomerMapper.java

@@ -1,11 +1,10 @@
 package com.fjhx.customer.mapper.customer;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.fjhx.customer.entity.customer.dto.CustomerDto;
-import com.fjhx.customer.entity.customer.po.Customer;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.customer.entity.customer.dto.CustomerDto;
+import com.fjhx.customer.entity.customer.po.Customer;
 import com.fjhx.customer.entity.customer.vo.CustomerFollowRecordsVo;
 import com.fjhx.customer.entity.customer.vo.CustomerVo;
 import com.ruoyi.common.utils.wrapper.IWrapper;
@@ -58,4 +57,6 @@ public interface CustomerMapper extends BaseMapper<Customer> {
      * 跟进记录获取
      */
     List<CustomerFollowRecordsVo> getFollowUp(@Param("id") Long id, @Param("tenantId") String tenantId);
+
+    List<Customer> sourceCount(@Param("ew") QueryWrapper<Customer> wrapper);
 }

+ 1 - 0
hx-customer/src/main/java/com/fjhx/customer/service/customer/CustomerService.java

@@ -95,4 +95,5 @@ public interface CustomerService extends BaseService<Customer> {
      * 根据客户id获取客户信息
      */
     List<CustomerVo> getCustomerInfoByIds(List<Long> customerIds);
+
 }

+ 27 - 6
hx-customer/src/main/java/com/fjhx/customer/service/customer/impl/CustomerServiceImpl.java

@@ -108,7 +108,10 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
         IWrapper<CustomerVo> wrapper = IWrapper.getWrapper();
 
         // 客户来源查询
-        wrapper.eq("c", Customer::getSource, dto.getSource());
+        String source = dto.getSource();
+        if (ObjectUtil.isNotEmpty(source)) {
+            wrapper.apply("FIND_IN_SET( {0}, c.source )", source);
+        }
         // 客户类型查询
         wrapper.eq("c", Customer::getStatus, dto.getStatus());
         // 国家ID查询
@@ -316,6 +319,7 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
     @Transactional(rollbackFor = {Exception.class})
     public void delete(Long id) {
         //删除客户表的数据
+        this.update(q -> q.eq(Customer::getId, id).set(Customer::getCompanyId, null));
         this.removeById(id);
         //删除客户-联系人表的数据
         customerUserService.remove(Wrappers.<CustomerUser>lambdaQuery().eq(CustomerUser::getCustomerId, id));
@@ -381,17 +385,21 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
                 query.and(wrapper1 -> wrapper1.isNull("user_id").or().eq("user_id", ""));
             }
         }
-        if (customerDto.getStatisticsType() == 1) {// 来源统计
-            query.groupBy("source");
-            query.select("count(*) count,source");
-        } else if (customerDto.getStatisticsType() == 2) {// 数据类型统计
+        if (customerDto.getStatisticsType() == 2) {// 数据类型统计
             query.groupBy("status");
             query.select("count(*) count,status");
         } else if (customerDto.getStatisticsType() == 3) {// 业务员统计
             query.groupBy("user_id");
             query.select("count(*) count,user_id");
         }
-        List<Customer> customerList = baseMapper.selectList(query);
+
+        List<Customer> customerList;
+        if (customerDto.getStatisticsType() == 1) {// 来源统计
+            query.eq("dcd.dict_code", "customer_source");
+            customerList = baseMapper.sourceCount(query);
+        } else {
+            customerList = baseMapper.selectList(query);
+        }
 
         UserUtil.assignmentNickName(customerList, Customer::getUserId, Customer::setUserName);
 
@@ -557,4 +565,17 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
 
         return customerVos;
     }
+
+//    /**
+//     * 小满绑定/解绑
+//     */
+//    public void xiaomanBinding(CustomerDto dto) {
+//        this.update(q -> q
+//                .eq(Customer::getId, dto.getId())
+//                .set(Customer::getCompanyId, dto.getCompanyId())
+//                .set(BasePo::getUpdateTime, new Date())
+//                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
+//        );
+//    }
+
 }

+ 4 - 3
hx-customer/src/main/java/com/fjhx/customer/service/xiaoman/XiaomanApiService.java

@@ -1,6 +1,6 @@
 package com.fjhx.customer.service.xiaoman;
 
-import com.baomidou.dynamic.datasource.annotation.DSTransactional;
+import com.fjhx.customer.entity.customer.dto.CustomerDto;
 import com.fjhx.customer.entity.xiaoman.vo.XiaomanUpdateInfoVO;
 
 public interface XiaomanApiService {
@@ -20,10 +20,11 @@ public interface XiaomanApiService {
 
     void updateList(int hours);
 
-    @DSTransactional
     void getSelectorData();
 
     void updateXiaomanData(XiaomanUpdateInfoVO xiaomanUpdateInfoVO);
 
-    void dealCustomerTagDict(String label,String key);
+    void dealCustomerTagDict(String label, String key);
+
+    void updateXiaomanData(CustomerDto dto);
 }

+ 104 - 13
hx-customer/src/main/java/com/fjhx/customer/service/xiaoman/impl/XiaomanApiServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
@@ -14,6 +15,8 @@ import com.baomidou.dynamic.datasource.annotation.DSTransactional;
 import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
 import com.fjhx.common.constant.SourceConstant;
 import com.fjhx.customer.contants.XiaomanContant;
+import com.fjhx.customer.entity.customer.dto.CustomerDto;
+import com.fjhx.customer.entity.customer.po.CustomerUser;
 import com.fjhx.customer.entity.xiaoman.dto.XiaomanCustomerSelectDto;
 import com.fjhx.customer.entity.xiaoman.po.XiaomanConfig;
 import com.fjhx.customer.entity.xiaoman.vo.CustomerListApiVo;
@@ -27,6 +30,7 @@ import com.fjhx.tenant.entity.dict.dto.DictTenantDataSelectDto;
 import com.fjhx.tenant.entity.dict.po.DictTenantData;
 import com.fjhx.tenant.entity.dict.vo.DictTenantDataVo;
 import com.fjhx.tenant.service.dict.DictTenantDataService;
+import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.utils.SecurityUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.data.redis.core.StringRedisTemplate;
@@ -49,24 +53,29 @@ public class XiaomanApiServiceImpl implements XiaomanApiService {
     XiaomanCustomerService xiaomanCustomerService;
     @Resource
     DictTenantDataService dictTenantDataService;
+    @Resource
+    RedisCache redisCache;
 
 //    @DSTransactional
     @Override
     @Async
     public void initAllList() {
-        boolean result = setNxWithExpiration(XiaomanContant.TASK_STATUS_KEY, XiaomanContant.TASK_STATUS_VALUE, XiaomanContant.DELAY_DELETE_KEY_TIME);
-        if (!result) {
-            String mes = stringRedisTemplate.opsForValue().get(XiaomanContant.TASK_STATUS_DESC_KEY);
-            throw new RuntimeException(StrUtil.isBlank(mes)? "全量更新正在进行中" : mes);
-        }
-        stringRedisTemplate.opsForValue().set(XiaomanContant.TASK_STATUS_DESC_KEY, "全量更新正在进行中");
+//        boolean result = setNxWithExpiration(XiaomanContant.TASK_STATUS_KEY, XiaomanContant.TASK_STATUS_VALUE, XiaomanContant.DELAY_DELETE_KEY_TIME);
+//        if (!result) {
+//            String mes = stringRedisTemplate.opsForValue().get(XiaomanContant.TASK_STATUS_DESC_KEY);
+//            throw new RuntimeException(StrUtil.isBlank(mes)? "全量更新正在进行中" : mes);
+//        }
+//        stringRedisTemplate.opsForValue().set(XiaomanContant.TASK_STATUS_DESC_KEY, "全量更新正在进行中");
         try {
             getSelectorData();
 
 
             List<XiaomanCustomerVo> list = xiaomanCustomerService.getList(new XiaomanCustomerSelectDto());
             Set<Long> collect = list.stream().map(XiaomanCustomerVo::getCompanyId).collect(Collectors.toSet());
-            int pageIndex = 1;
+            int pageIndex = redisCache.getCacheObject(XiaomanContant.ALL_CUSTOMER_PAGE_INDEX_KEY);
+            if (!NumberUtil.isValidNumber(pageIndex)) {
+                pageIndex = 1;
+            }
             int totalPage;
             do {
                 XiaomanConfig config = xiaomanConfigService.getCache();
@@ -77,15 +86,16 @@ public class XiaomanApiServiceImpl implements XiaomanApiService {
                 int totalItem = customerListApiVo.getTotalItem();
                 totalPage = (totalItem / XiaomanContant.PAGE_SIZE) + (totalItem % XiaomanContant.PAGE_SIZE > 0 ? 1 : 0);
                 pageIndex++;
+                redisCache.setCacheObject(XiaomanContant.ALL_CUSTOMER_PAGE_INDEX_KEY, pageIndex);
             } while (pageIndex <= totalPage);
         } catch (Exception e) {
             e.printStackTrace();
-            stringRedisTemplate.delete(XiaomanContant.TASK_STATUS_KEY);
-            stringRedisTemplate.opsForValue().set(XiaomanContant.TASK_STATUS_DESC_KEY, "全量更新出现异常,已停止");
-            return;
+//            stringRedisTemplate.delete(XiaomanContant.TASK_STATUS_KEY);
+//            stringRedisTemplate.opsForValue().set(XiaomanContant.TASK_STATUS_DESC_KEY, "全量更新出现异常,已停止");
+//            return;
         }
-        stringRedisTemplate.delete(XiaomanContant.TASK_STATUS_KEY);
-        stringRedisTemplate.opsForValue().set(XiaomanContant.TASK_STATUS_DESC_KEY, "全量更新完成,完成时间:" + DateUtil.now());
+//        stringRedisTemplate.delete(XiaomanContant.TASK_STATUS_KEY);
+//        stringRedisTemplate.opsForValue().set(XiaomanContant.TASK_STATUS_DESC_KEY, "全量更新完成,完成时间:" + DateUtil.now());
     }
 
     /**
@@ -128,12 +138,13 @@ public class XiaomanApiServiceImpl implements XiaomanApiService {
 
     /**
      * 客户更新列表
+     *
      * @author hj
      * @date 2024/4/6 21:54
      */
     @Override
     @Async
-    public void updateList(int hours){
+    public void updateList(int hours) {
         try {
             //先更新一下数据字典
             getSelectorData();
@@ -337,4 +348,84 @@ public class XiaomanApiServiceImpl implements XiaomanApiService {
         DynamicDataSourceContextHolder.poll();
 
     }
+
+    /**
+     * 推送客户数据到小满
+     */
+    @DSTransactional
+    @Override
+    public void updateXiaomanData(CustomerDto dto) {
+        if (ObjectUtil.isEmpty(dto.getCompanyId())) {
+            return;
+        }
+        XiaomanUpdateInfoVO xVo = new XiaomanUpdateInfoVO();
+        List<XiaomanUpdateInfoVO.Customer> xiaomanCustomerUserList = new ArrayList<>();
+
+        //=========================
+        List<CustomerUser> customerUserList = dto.getCustomerUserList();
+        for (CustomerUser cu : customerUserList) {
+            String contactJsonStr = cu.getContactJson();
+            log.info("->" + contactJsonStr + "<-");
+            JSONArray contactJsonArr = ObjectUtil.isEmpty(contactJsonStr) ? new JSONArray() : JSONArray.parseArray(contactJsonStr);
+
+            XiaomanUpdateInfoVO.Customer xCU = new XiaomanUpdateInfoVO.Customer();
+            xCU.setName(cu.getName());//联系人名称
+            xCU.setEmail(cu.getEmail());//客户简称
+            xCU.setRemark(dto.getRemark());//客户联系人备注
+            xCU.setTelAreaCode(Long.parseLong(dto.getTelAreaCode())); //客户联系人电话区号
+
+            //更多联系方式
+            for (int i = 0; i < contactJsonArr.size(); i++) {
+                JSONObject contactJson = contactJsonArr.getJSONObject(i);
+                String contactNo = contactJson.getString("contactNo");
+                switch (contactJson.getString("type")) {
+                    case "mobile":
+                        xCU.setTel(contactJson.getLong("contactNo"));//客户联系人电话
+                        break;
+                    case "qq":
+                        xCU.setQq(contactNo);//客户联系人QQ
+                        break;
+                    case "LinkedIn":
+                        xCU.setLinkedin(contactNo);//客户联系人LinkedIn
+                        break;
+                    case "Skype":
+                        xCU.setSkype(contactNo);//客户联系人Skype
+                        break;
+                    case "wa":
+                        xCU.setWhatsapp(contactNo);//客户联系人Whatsapp
+                        break;
+                    case "Facebook":
+                        xCU.setFacebook(contactNo);//客户联系人Facebook
+                        break;
+                    case "wechat":
+                        xCU.setWechat(contactNo);//客户联系人Wechat
+                        break;
+                    case "twitter":
+                        xCU.setTwitter(contactNo);//客户联系人Twitter
+                        break;
+                }
+            }
+
+            xiaomanCustomerUserList.add(xCU);
+        }
+        //=========================
+        xVo.setCompanyId(dto.getCompanyId());//公司客户ID (创建时无需设置,更新时需要设置)
+        xVo.setSerialId(dto.getCustomerCode());//客户编号id->客户表customer_code
+        xVo.setName(dto.getName());//客户名称
+        xVo.setShortName(dto.getShortName());//客户简称
+        xVo.setHomepage(dto.getHomepage());//网站主页
+        xVo.setFax(Long.parseLong(dto.getFax()));//传真
+        xVo.setTelAreaCode(Long.parseLong(dto.getTelAreaCode()));//客户电话区号
+        xVo.setTel(Long.parseLong(dto.getTel()));//客户电话
+        xVo.setAddress(dto.getAddress());//地址
+        xVo.setRemark(dto.getRemark());//备注
+        xVo.setCustomers(xiaomanCustomerUserList);//客户联系人
+        //客户来源ID
+        List<Long> originList = Arrays.stream(dto.getSource().split(",")).map(Long::valueOf).collect(Collectors.toList());
+        xVo.setOriginList(originList);
+        xVo.setTrailStatus(Long.parseLong(dto.getStatus()));//客户状态ID
+        //=========================
+
+        updateXiaomanData(xVo);
+    }
 }

+ 42 - 31
hx-customer/src/main/java/com/fjhx/customer/service/xiaoman/impl/XiaomanCustomerServiceImpl.java

@@ -124,44 +124,48 @@ public class XiaomanCustomerServiceImpl extends ServiceImpl<XiaomanCustomerMappe
     @Override
     public void handleSaveOrUpdate(List<CustomerApiVo> customerApiVoList, Set<Long> allCustomer,boolean flag) {
         List<XiaomanCustomer> xiaomanCustomerList = new ArrayList<>(customerApiVoList);
-        for (XiaomanCustomer customer : xiaomanCustomerList){
-            try {
-                if (allCustomer.contains(customer.getCompanyId())){
-
-                    String customerDetailJson = xiaomanApiService.getCustomerDetail(customer.getCompanyId());
-                    XiaomanCustomerInfoJson xiaomanCustomerInfoJson = new XiaomanCustomerInfoJson();
-                    xiaomanCustomerInfoJson.setCompanyId(customer.getCompanyId());
-                    xiaomanCustomerInfoJson.setJson(customerDetailJson);
-                    xiaomanCustomerInfoJsonService.updateById(xiaomanCustomerInfoJson);
-                    CustomerInfoVo infoVo = HandleXiaomanData.handleDate(customerDetailJson, new TypeReference<R<CustomerInfoVo>>() {
-                    });
-                    //true 全量更新
-                    Long s = flag ? customerConversionAll(infoVo): customerConversionUpdate(infoVo);
-                    customer.setCustomerId(s);
-                    updateById(customer);
-                }else {
+        for (XiaomanCustomer customer : xiaomanCustomerList) {
+                if (allCustomer.contains(customer.getCompanyId())) {
+                    processCustomer(customer, true,flag);
+                } else {
+                    processCustomer(customer, false,flag);
+                }
+        }
+    }
 
-                    String customerDetailJson = xiaomanApiService.getCustomerDetail(customer.getCompanyId());
-                    XiaomanCustomerInfoJson xiaomanCustomerInfoJson = new XiaomanCustomerInfoJson();
-                    xiaomanCustomerInfoJson.setCompanyId(customer.getCompanyId());
-                    xiaomanCustomerInfoJson.setJson(customerDetailJson);
+
+    private void processCustomer(XiaomanCustomer customer, boolean isUpdate,boolean flag) {
+
+            // 如果不是同时全量更新且需要修改,则执行以下逻辑
+            if (!(isUpdate && flag)) {
+                String customerDetailJson = xiaomanApiService.getCustomerDetail(customer.getCompanyId());
+                XiaomanCustomerInfoJson xiaomanCustomerInfoJson = new XiaomanCustomerInfoJson();
+                xiaomanCustomerInfoJson.setCompanyId(customer.getCompanyId());
+                xiaomanCustomerInfoJson.setJson(customerDetailJson);
+
+                if (isUpdate) {
+                    xiaomanCustomerInfoJsonService.updateById(xiaomanCustomerInfoJson);
+                } else {
                     xiaomanCustomerInfoJsonService.save(xiaomanCustomerInfoJson);
+                }
 
-                    CustomerInfoVo infoVo = HandleXiaomanData.handleDate(customerDetailJson, new TypeReference<R<CustomerInfoVo>>() {
-                    });
-                    //小满客户 =》 客户
-                    //true 全量更新
-                    Long s = flag ? customerConversionAll(infoVo): customerConversionUpdate(infoVo);
-                    customer.setCustomerId(s);
+                CustomerInfoVo infoVo = HandleXiaomanData.handleDate(customerDetailJson, new TypeReference<R<CustomerInfoVo>>() {
+                });
+                Long s = flag ? customerConversionAll(infoVo) : customerConversionUpdate(infoVo);
+                customer.setCustomerId(s);
+                if (isUpdate) {
+                    updateById(customer);
+                } else {
                     save(customer);
-                    System.out.println("2");
                 }
-            }catch (Exception e){
-                e.printStackTrace();
+
+
             }
-        }
+
+
     }
 
+
     /**
      * 小满客户 =》 客户
      * @param vo
@@ -178,7 +182,13 @@ public class XiaomanCustomerServiceImpl extends ServiceImpl<XiaomanCustomerMappe
 
         //联系人
         if (!vo.getCustomers().isEmpty()){
-            for (CustomerInfoVo.Customer cus  :vo.getCustomers()){
+           List<CustomerInfoVo.Customer> newCistomer  = new ArrayList<>();
+             vo.getCustomers().stream().collect(Collectors.groupingBy(CustomerInfoVo.Customer::getEmail)).forEach((k,v)->{
+                CustomerInfoVo.Customer customer1 = v.get(v.size() - 1);
+                 newCistomer.add(customer1);
+            });
+
+            for (CustomerInfoVo.Customer cus  : newCistomer){
                 if (StringUtils.isNotEmpty(cus.getEmail())){
                     CustomerUser customerUser = new CustomerUser();
                     customerUser.setCustomerId(customer.getId());
@@ -201,6 +211,7 @@ public class XiaomanCustomerServiceImpl extends ServiceImpl<XiaomanCustomerMappe
                     customerUser.setPhone(cus.getTel());
                     customerUser.setContactJson(JSON.toJSONString(maps));
                     customerUserService.save(customerUser);
+
                 }
 
             }

+ 13 - 0
hx-customer/src/main/resources/mapper/customer/CustomerMapper.xml

@@ -128,5 +128,18 @@
                WHERE cfr.customer_id = #{id})) t1
         ORDER BY t1.date DESC LIMIT 3
     </select>
+    <select id="sourceCount" resultType="com.fjhx.customer.entity.customer.vo.CustomerVo">
+        SELECT
+        COUNT( 1 ) AS `count`,
+        dcd.dict_key AS `source`
+        FROM
+        customer c
+        JOIN bytesailing_base.dict_tenant_data dcd ON FIND_IN_SET( dcd.dict_key, c.source )
+        <where>
+            ${ew.sqlSegment}
+        </where>
+        GROUP BY
+        dcd.dict_key
+    </select>
 
 </mapper>

+ 68 - 0
hx-sale/src/main/java/com/fjhx/sale/controller/after/AfterSalesController.java

@@ -0,0 +1,68 @@
+package com.fjhx.sale.controller.after;
+
+import org.springframework.web.bind.annotation.*;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.sale.entity.after.vo.AfterSalesVo;
+import com.fjhx.sale.entity.after.dto.AfterSalesSelectDto;
+import com.fjhx.sale.entity.after.dto.AfterSalesDto;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import com.fjhx.sale.service.after.AfterSalesService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+/**
+ * <p>
+ * 售后管理 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@RestController
+@RequestMapping("/afterSales")
+public class AfterSalesController {
+
+    @Autowired
+    private AfterSalesService afterSalesService;
+
+    /**
+     * 售后管理分页
+     */
+    @PostMapping("/page")
+    public Page<AfterSalesVo> page(@RequestBody AfterSalesSelectDto dto) {
+        return afterSalesService.getPage(dto);
+    }
+
+    /**
+     * 售后管理明细
+     */
+    @PostMapping("/detail")
+    public AfterSalesVo detail(@RequestBody BaseSelectDto dto) {
+        return afterSalesService.detail(dto.getId());
+    }
+
+    /**
+     * 售后管理新增
+     */
+    @PostMapping("/add")
+    public void add(@RequestBody AfterSalesDto afterSalesDto) {
+        afterSalesService.addOrEdit(afterSalesDto);
+    }
+
+    /**
+     * 售后管理编辑
+     */
+    @PostMapping("/edit")
+    public void edit(@RequestBody AfterSalesDto afterSalesDto) {
+        afterSalesService.addOrEdit(afterSalesDto);
+    }
+
+    /**
+     * 售后管理删除
+     */
+    @PostMapping("/delete")
+    public void delete(@RequestBody BaseSelectDto dto) {
+        afterSalesService.delete(dto.getId());
+    }
+
+}

+ 34 - 0
hx-sale/src/main/java/com/fjhx/sale/controller/after/AfterSalesDetailController.java

@@ -0,0 +1,34 @@
+package com.fjhx.sale.controller.after;
+
+import org.springframework.web.bind.annotation.*;
+import com.fjhx.sale.entity.after.vo.AfterSalesDetailVo;
+import com.fjhx.sale.entity.after.dto.AfterSalesDetailSelectDto;
+import com.fjhx.sale.service.after.AfterSalesDetailService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 售后明细 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@RestController
+@RequestMapping("/afterSalesDetail")
+public class AfterSalesDetailController {
+
+    @Autowired
+    private AfterSalesDetailService afterSalesDetailService;
+
+    /**
+     * 售后明细列表
+     */
+    @PostMapping("/list")
+    public List<AfterSalesDetailVo> list(@RequestBody AfterSalesDetailSelectDto dto) {
+        return afterSalesDetailService.getList(dto);
+    }
+
+}

+ 49 - 0
hx-sale/src/main/java/com/fjhx/sale/controller/after/AfterSalesRecordsController.java

@@ -0,0 +1,49 @@
+package com.fjhx.sale.controller.after;
+
+import org.springframework.web.bind.annotation.*;
+import com.fjhx.sale.entity.after.dto.AfterSalesRecordsDto;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import com.fjhx.sale.service.after.AfterSalesRecordsService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+/**
+ * <p>
+ * 售后跟进记录 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@RestController
+@RequestMapping("/afterSalesRecords")
+public class AfterSalesRecordsController {
+
+    @Autowired
+    private AfterSalesRecordsService afterSalesRecordsService;
+
+    /**
+     * 售后跟进记录新增
+     */
+    @PostMapping("/add")
+    public void add(@RequestBody AfterSalesRecordsDto afterSalesRecordsDto) {
+        afterSalesRecordsService.add(afterSalesRecordsDto);
+    }
+
+    /**
+     * 售后跟进记录编辑
+     */
+    @PostMapping("/edit")
+    public void edit(@RequestBody AfterSalesRecordsDto afterSalesRecordsDto) {
+        afterSalesRecordsService.edit(afterSalesRecordsDto);
+    }
+
+    /**
+     * 售后跟进记录删除
+     */
+    @PostMapping("/delete")
+    public void delete(@RequestBody BaseSelectDto dto) {
+        afterSalesRecordsService.delete(dto.getId());
+    }
+
+}

+ 11 - 1
hx-sale/src/main/java/com/fjhx/sale/controller/contract/ContractProductController.java

@@ -34,13 +34,23 @@ public class ContractProductController {
     public Page<ContractProductVo> page(@RequestBody ContractProductSelectDto dto) {
         return contractProductService.getPage(dto);
     }
+
+    /**
+     * 售后合同产品分页
+     */
+    @PostMapping("/afterSalesPage")
+    public Page<ContractProductVo> AfterSalesPage(@RequestBody ContractProductSelectDto dto) {
+        return contractProductService.getPage(dto);
+    }
+
     /**
      * 根据合同ID和客户ID查询未包装的产品
      */
     @GetMapping("/getNoPackContractProductById")
-    public List<ContractProductVo> getNoPackContractProductById(@RequestParam("customerId")String customerId, @RequestParam("contractIds")String contractIds) {
+    public List<ContractProductVo> getNoPackContractProductById(@RequestParam("customerId") String customerId, @RequestParam("contractIds") String contractIds) {
         return contractProductService.getNoPackContractProductById(customerId, contractIds);
     }
+
     /**
      * 外销合同-产品ID集合查询产品
      */

+ 17 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesDetailDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.sale.entity.after.dto;
+
+import com.fjhx.sale.entity.after.po.AfterSalesDetail;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 售后明细新增编辑入参实体
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+public class AfterSalesDetailDto extends AfterSalesDetail {
+
+}

+ 17 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesDetailSelectDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.sale.entity.after.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 售后明细列表查询入参实体
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+public class AfterSalesDetailSelectDto extends BaseSelectDto {
+
+}

+ 28 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesDto.java

@@ -0,0 +1,28 @@
+package com.fjhx.sale.entity.after.dto;
+
+import com.fjhx.file.entity.ObsFile;
+import com.fjhx.sale.entity.after.po.AfterSales;
+import com.fjhx.sale.entity.after.po.AfterSalesDetail;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 售后管理新增编辑入参实体
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+public class AfterSalesDto extends AfterSales {
+
+    List<AfterSalesDetail> afterSalesDetailList;
+
+    /**
+     * 附件列表
+     */
+    private List<ObsFile> fileList;
+
+}

+ 25 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesRecordsDto.java

@@ -0,0 +1,25 @@
+package com.fjhx.sale.entity.after.dto;
+
+import com.fjhx.file.entity.ObsFile;
+import com.fjhx.sale.entity.after.po.AfterSalesRecords;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 售后跟进记录新增编辑入参实体
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+public class AfterSalesRecordsDto extends AfterSalesRecords {
+
+    /**
+     * 附件信息
+     */
+    private List<ObsFile> fileList;
+
+}

+ 17 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesRecordsSelectDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.sale.entity.after.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 售后跟进记录列表查询入参实体
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+public class AfterSalesRecordsSelectDto extends BaseSelectDto {
+
+}

+ 25 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/dto/AfterSalesSelectDto.java

@@ -0,0 +1,25 @@
+package com.fjhx.sale.entity.after.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 售后管理列表查询入参实体
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+public class AfterSalesSelectDto extends BaseSelectDto {
+    /**
+     * 售后类型 字典
+     */
+    private String type;
+
+    /**
+     * 售后状态 0进行中1关闭
+     */
+    private Integer status;
+}

+ 90 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/po/AfterSales.java

@@ -0,0 +1,90 @@
+package com.fjhx.sale.entity.after.po;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.domain.BasePo;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * <p>
+ * 售后管理
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+@TableName("after_sales")
+public class AfterSales extends BasePo {
+
+    /**
+     * 售后单号
+     */
+    private String code;
+
+    /**
+     * 售后类型 字典
+     */
+    private String type;
+
+    /**
+     * 说明
+     */
+    private String remark;
+
+    /**
+     * 原因
+     */
+    private String reason;
+
+    /**
+     * 售后金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 初判责任方
+     */
+    private String dutyParty;
+
+    /**
+     * 联系人名称
+     */
+    private String contactName;
+
+    /**
+     * 联系人电话
+     */
+    private String contactTel;
+
+    /**
+     * 开户行
+     */
+    private String accountBank;
+
+    /**
+     * 账户名
+     */
+    private String accountName;
+
+    /**
+     * 账号
+     */
+    private String accountNumber;
+
+    /**
+     * 售后状态 0进行中1关闭
+     */
+    private Integer status;
+
+    private Long flowId;
+
+    /**
+     * 销售合同id
+     */
+    private Long contractId;
+
+}

+ 70 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/po/AfterSalesDetail.java

@@ -0,0 +1,70 @@
+package com.fjhx.sale.entity.after.po;
+
+import com.ruoyi.common.core.domain.BasePo;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 售后明细
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+@TableName("after_sales_detail")
+public class AfterSalesDetail extends BasePo {
+
+    /**
+     * 售后id
+     */
+    private Long afterSalesId;
+
+    /**
+     * 产品id
+     */
+    private Long productId;
+
+    /**
+     * 售后数量
+     */
+    private BigDecimal quantity;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 合同产品明细id
+     */
+    private Long contractProductId;
+
+    /**
+     * 单价
+     */
+    private BigDecimal price;
+
+    /**
+     * 金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 售后状态 0进行中1关闭
+     */
+    private Integer status;
+
+    /**
+     * 合同id
+     */
+    private Long contractId;
+
+}

+ 43 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/po/AfterSalesRecords.java

@@ -0,0 +1,43 @@
+package com.fjhx.sale.entity.after.po;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.domain.BasePo;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * <p>
+ * 售后跟进记录
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+@TableName("after_sales_records")
+public class AfterSalesRecords extends BasePo {
+
+    /**
+     * 售后id
+     */
+    private Long afterSalesId;
+
+    /**
+     * 跟进时间
+     */
+    private Date followUpTime;
+
+    /**
+     * 跟进用户id
+     */
+    private Long followUpUserId;
+
+    /**
+     * 说明
+     */
+    private String remark;
+
+}

+ 52 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/vo/AfterSalesDetailVo.java

@@ -0,0 +1,52 @@
+package com.fjhx.sale.entity.after.vo;
+
+import com.fjhx.sale.entity.after.po.AfterSalesDetail;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 售后明细列表查询返回值实体
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+public class AfterSalesDetailVo extends AfterSalesDetail {
+
+
+    /**
+     * 所属类型
+     */
+    private String productType;
+
+    /**
+     * 货品编码
+     */
+    private String productCode;
+
+    /**
+     * 货品名称
+     */
+    private String productName;
+
+    /**
+     * 规格型号
+     */
+    private String productSpec;
+
+    /**
+     * 单位
+     */
+    private String productUnit;
+
+    /**
+     * 商品型号
+     */
+    private String productModel;
+
+    private BigDecimal contractQuantity;
+
+}

+ 22 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/vo/AfterSalesRecordsVo.java

@@ -0,0 +1,22 @@
+package com.fjhx.sale.entity.after.vo;
+
+import com.fjhx.sale.entity.after.po.AfterSalesRecords;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 售后跟进记录列表查询返回值实体
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+public class AfterSalesRecordsVo extends AfterSalesRecords {
+
+    /**
+     * 跟进用户id
+     */
+    private String followUpUserName;
+
+}

+ 24 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/after/vo/AfterSalesVo.java

@@ -0,0 +1,24 @@
+package com.fjhx.sale.entity.after.vo;
+
+import com.fjhx.sale.entity.after.po.AfterSales;
+import com.fjhx.sale.entity.after.po.AfterSalesRecords;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 售后管理列表查询返回值实体
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Getter
+@Setter
+public class AfterSalesVo extends AfterSales {
+
+    List<AfterSalesRecordsVo> afterSalesRecordsList;
+    List<AfterSalesDetailVo> afterSalesDetailList;
+    private String contractCode;
+
+}

+ 19 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/contract/vo/ContractBudgetVo.java

@@ -228,6 +228,11 @@ public class ContractBudgetVo extends Contract {
         private BigDecimal gross;
 
         /**
+         * 毛利率
+         */
+        private BigDecimal grossRate;
+
+        /**
          * 类型 1销售合同 2采购合同
          */
         private Integer type;
@@ -236,6 +241,20 @@ public class ContractBudgetVo extends Contract {
          * 父采购id
          */
         private Long oldPurchaseId;
+
+        /**
+         * 对比上一版本
+         */
+        private BigDecimal compareLastGross;
+
+        /**
+         * 合同id
+         */
+        private Long contractId;
+        /**
+         * 采购id
+         */
+        private Long purchaseId;
     }
 
 }

+ 2 - 0
hx-sale/src/main/java/com/fjhx/sale/entity/contract/vo/ContractVo.java

@@ -233,5 +233,7 @@ public class ContractVo extends Contract {
     @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
     private Date shipmentTime;
 
+    private Integer notPack;
+
 }
 

+ 148 - 0
hx-sale/src/main/java/com/fjhx/sale/flow/AfterSalesFlow.java

@@ -0,0 +1,148 @@
+package com.fjhx.sale.flow;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.account.entity.account.dto.AccountPaymentDto;
+import com.fjhx.account.entity.account.enums.PaymentStatusEnum;
+import com.fjhx.account.service.account.AccountPaymentService;
+import com.fjhx.common.enums.CodingRuleEnum;
+import com.fjhx.common.enums.FlowStatusEnum1;
+import com.fjhx.common.service.coding.CodingRuleService;
+import com.fjhx.flow.core.FlowDelegate;
+import com.fjhx.flow.entity.flow.dto.InitiateDto;
+import com.fjhx.flow.enums.FlowStatusEnum;
+import com.fjhx.flow.service.flow.FlowProcessService;
+import com.fjhx.sale.entity.after.dto.AfterSalesDto;
+import com.fjhx.sale.entity.after.po.AfterSales;
+import com.fjhx.sale.entity.after.po.AfterSalesDetail;
+import com.fjhx.sale.entity.contract.dto.ContractDto;
+import com.fjhx.sale.entity.contract.po.ContractProduct;
+import com.fjhx.sale.service.after.AfterSalesDetailService;
+import com.fjhx.sale.service.after.AfterSalesService;
+import com.fjhx.sale.service.contract.ContractService;
+import com.fjhx.tenant.utils.DictUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class AfterSalesFlow extends FlowDelegate {
+
+    @Autowired
+    private AfterSalesService afterSalesService;
+    @Autowired
+    private AfterSalesDetailService afterSalesDetailService;
+    @Autowired
+    private CodingRuleService codingRuleService;
+    @Autowired
+    private AccountPaymentService accountPaymentService;
+    @Autowired
+    private ContractService contractService;
+    @Autowired
+    private FlowProcessService flowProcessService;
+
+    @Override
+    public String getFlowKey() {
+        return "after_sales_flow";
+    }
+
+    @Override
+    public Long start(Long flowId, JSONObject submitData) {
+        AfterSalesDto afterSalesDto = submitData.toJavaObject(AfterSalesDto.class);
+
+        afterSalesDto.setFlowId(flowId);
+        afterSalesDto.setStatus(FlowStatusEnum1.UNDER_REVIEW.getKey());
+        afterSalesDto.setCode(codingRuleService.createCode(CodingRuleEnum.AFTER_SALES.getKey(), null));
+        afterSalesService.addOrEdit(afterSalesDto);
+
+        return afterSalesDto.getId();
+    }
+
+    @Override
+    public void end(Long flowId, Long businessId, JSONObject submitData) {
+        afterSalesService.update(q -> q
+                .eq(AfterSales::getId, businessId)
+                .set(AfterSales::getStatus, FlowStatusEnum1.PASS.getKey())
+                .set(AfterSales::getUpdateTime, new Date())
+                .set(AfterSales::getUpdateUser, SecurityUtils.getUserId())
+        );
+
+        AfterSales afterSales = afterSalesService.getById(businessId);
+        Map<String, String> dictMap = DictUtils.getDictMap("after_sales_type");
+        String type = afterSales.getType();
+        type += dictMap.getOrDefault(type, "");
+        //(1)如果审批通过,且售后类型=退货退款:后续跟进补充运单号,自动生成财务打款数据
+        //(2)如果审批通过,且售后类型=仅退款:自动生成财务打款数据
+        if (type.contains("退货退款") || type.contains("仅退款")) {
+            AccountPaymentDto accountPayment = new AccountPaymentDto();
+//            accountPayment.setDepartmentId(accountRequestFunds.getDepartmentId());
+//            accountPayment.setCorporationId(accountRequestFunds.getCorporationId());
+            accountPayment.setBusinessId(afterSales.getId());
+            accountPayment.setPaymentTime(new Date());
+            accountPayment.setCurrency("CNY");
+            accountPayment.setStatus(PaymentStatusEnum.UNDER_REVIEW.getKey());
+            accountPayment.setType("40");//售后
+//            accountPayment.setPaymentRemark();
+            accountPayment.setPaymentMethod("bank");
+            accountPayment.setIncomeAmount(afterSales.getAmount());
+            accountPayment.setName(afterSales.getAccountName());
+//            accountPayment.setBusinessManagementId(accountRequestFunds.getAccountManagementId());
+            accountPayment.setOpeningBank(afterSales.getAccountBank());
+            accountPayment.setAccountOpening(afterSales.getAccountNumber());
+//            accountPayment.setInterbankNumber(accountRequestFunds.getInterbankNumber());
+            accountPayment.setDataUser(afterSales.getCreateUser());
+            accountPayment.setAmount(BigDecimal.ZERO);
+            accountPaymentService.save(accountPayment);
+        }
+        //(3)如果审批通过,且售后类型=补发/换货:自动生成订单,单价=0
+        if (type.contains("补发") || type.contains("换货")) {
+            ContractDto contractDto = BeanUtil.copyProperties(contractService.getById(afterSales.getContractId()), ContractDto.class);
+            contractDto.setId(null);
+            contractDto.setAmount(BigDecimal.ZERO);
+            List<AfterSalesDetail> afterSalesDetailList = afterSalesDetailService.list(q -> q.eq(AfterSalesDetail::getAfterSalesId, afterSales.getId()));
+            List<ContractProduct> contractProductList = new ArrayList<>();
+            for (AfterSalesDetail afterSalesDetail : afterSalesDetailList) {
+                ContractProduct contractProduct = new ContractProduct();
+                contractProduct.setProductId(afterSalesDetail.getProductId());
+                contractProduct.setPrice(BigDecimal.ZERO);
+                contractProduct.setAmount(BigDecimal.ZERO);
+                contractProduct.setQuantity(afterSalesDetail.getQuantity());
+                contractProductList.add(contractProduct);
+            }
+            contractDto.setContractProductList(contractProductList);
+
+            //生成合同审批数据
+            InitiateDto initiateDto = new InitiateDto();
+            initiateDto.setFlowKey("contract_flow");
+            initiateDto.setData(JSONObject.parseObject(JSONObject.toJSONString(contractDto)));
+            flowProcessService.initiate(initiateDto);
+        }
+    }
+
+    @Override
+    public void relaunch(Long flowId, Long businessId, FlowStatusEnum flowStatus, JSONObject submitData) {
+        AfterSalesDto afterSalesDto = submitData.toJavaObject(AfterSalesDto.class);
+        afterSalesService.addOrEdit(afterSalesDto);
+    }
+
+    @Override
+    public void reject(Long flowId, Long businessId, FlowStatusEnum flowStatus) {
+        afterSalesService.update(q -> q
+                .eq(AfterSales::getId, businessId)
+                .set(AfterSales::getStatus, FlowStatusEnum1.REJECT.getKey())
+                .set(AfterSales::getUpdateTime, new Date())
+                .set(AfterSales::getUpdateUser, SecurityUtils.getUserId())
+        );
+    }
+
+    @Override
+    public void cancellation(Long flowId, Long businessId, FlowStatusEnum flowStatus) {
+        afterSalesService.cancellation(businessId);
+    }
+}

+ 7 - 0
hx-sale/src/main/java/com/fjhx/sale/flow/ContractFlow.java

@@ -30,6 +30,7 @@ import com.ruoyi.common.utils.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
@@ -139,6 +140,9 @@ public class ContractFlow extends FlowDelegate {
 
         // 保存收费项目
         List<ContractProject> contractProjectList = contract.getContractProjectList();
+        if (ObjectUtils.isNull(contractProjectList)) {
+            contractProjectList = new ArrayList<>();
+        }
         //重新发起删除被删掉的收费项目
         contractProjectService.editLinked(contractProjectList, ContractProject::getContractId, contract.getId());
         if (CollectionUtils.isNotEmpty(contractProjectList)) {
@@ -150,6 +154,9 @@ public class ContractFlow extends FlowDelegate {
 
         // 保存自定义出货
         List<ContractShipment> contractShipmentList = contract.getContractShipmentList();
+        if (ObjectUtils.isNull(contractShipmentList)) {
+            contractShipmentList = new ArrayList<>();
+        }
         //重新发起删除被删掉的出货计划
         contractShipmentService.editLinked(contractShipmentList, ContractShipment::getContractId, contract.getId());
         if (CollectionUtils.isNotEmpty(contractShipmentList)) {

+ 26 - 0
hx-sale/src/main/java/com/fjhx/sale/mapper/after/AfterSalesDetailMapper.java

@@ -0,0 +1,26 @@
+package com.fjhx.sale.mapper.after;
+
+import com.fjhx.sale.entity.after.po.AfterSalesDetail;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.sale.entity.after.vo.AfterSalesDetailVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 售后明细 Mapper 接口
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+public interface AfterSalesDetailMapper extends BaseMapper<AfterSalesDetail> {
+
+    /**
+     * 售后明细列表
+     */
+    List<AfterSalesDetailVo> getList(@Param("ew") IWrapper<AfterSalesDetail> wrapper);
+
+}

+ 28 - 0
hx-sale/src/main/java/com/fjhx/sale/mapper/after/AfterSalesMapper.java

@@ -0,0 +1,28 @@
+package com.fjhx.sale.mapper.after;
+
+import com.fjhx.sale.entity.after.po.AfterSales;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.sale.entity.after.vo.AfterSalesVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
+
+
+/**
+ * <p>
+ * 售后管理 Mapper 接口
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+public interface AfterSalesMapper extends BaseMapper<AfterSales> {
+
+    /**
+     * 售后管理分页
+     */
+    Page<AfterSalesVo> getPage(@Param("page") Page<Object> page, @Param("ew") IWrapper<AfterSales> wrapper);
+
+    AfterSalesVo detail(@Param("ew") IWrapper<Object> wrapper);
+
+}

+ 23 - 0
hx-sale/src/main/java/com/fjhx/sale/mapper/after/AfterSalesRecordsMapper.java

@@ -0,0 +1,23 @@
+package com.fjhx.sale.mapper.after;
+
+import com.fjhx.sale.entity.after.po.AfterSalesRecords;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.sale.entity.after.vo.AfterSalesRecordsVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+
+/**
+ * <p>
+ * 售后跟进记录 Mapper 接口
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+public interface AfterSalesRecordsMapper extends BaseMapper<AfterSalesRecords> {
+
+    List<AfterSalesRecordsVo> getList(@Param("ew") IWrapper wrapper);
+}

+ 27 - 0
hx-sale/src/main/java/com/fjhx/sale/service/after/AfterSalesDetailService.java

@@ -0,0 +1,27 @@
+package com.fjhx.sale.service.after;
+
+import com.fjhx.sale.entity.after.po.AfterSalesDetail;
+import com.ruoyi.common.core.service.BaseService;
+import com.fjhx.sale.entity.after.vo.AfterSalesDetailVo;
+import com.fjhx.sale.entity.after.dto.AfterSalesDetailSelectDto;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 售后明细 服务类
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+public interface AfterSalesDetailService extends BaseService<AfterSalesDetail> {
+
+    /**
+     * 售后明细列表
+     */
+    List<AfterSalesDetailVo> getList(AfterSalesDetailSelectDto dto);
+
+    List<AfterSalesDetailVo> getList(IWrapper wrapper);
+}

+ 39 - 0
hx-sale/src/main/java/com/fjhx/sale/service/after/AfterSalesRecordsService.java

@@ -0,0 +1,39 @@
+package com.fjhx.sale.service.after;
+
+import com.fjhx.sale.entity.after.dto.AfterSalesRecordsDto;
+import com.fjhx.sale.entity.after.po.AfterSalesRecords;
+import com.fjhx.sale.entity.after.vo.AfterSalesRecordsVo;
+import com.ruoyi.common.core.service.BaseService;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+
+import java.util.List;
+
+
+/**
+ * <p>
+ * 售后跟进记录 服务类
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+public interface AfterSalesRecordsService extends BaseService<AfterSalesRecords> {
+
+    List<AfterSalesRecordsVo> getList(IWrapper wrapper);
+
+    /**
+     * 售后跟进记录新增
+     */
+    void add(AfterSalesRecordsDto afterSalesRecordsDto);
+
+    /**
+     * 售后跟进记录编辑
+     */
+    void edit(AfterSalesRecordsDto afterSalesRecordsDto);
+
+    /**
+     * 售后跟进记录删除
+     */
+    void delete(Long id);
+
+}

+ 42 - 0
hx-sale/src/main/java/com/fjhx/sale/service/after/AfterSalesService.java

@@ -0,0 +1,42 @@
+package com.fjhx.sale.service.after;
+
+import com.fjhx.sale.entity.after.po.AfterSales;
+import com.ruoyi.common.core.service.BaseService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.sale.entity.after.vo.AfterSalesVo;
+import com.fjhx.sale.entity.after.dto.AfterSalesSelectDto;
+import com.fjhx.sale.entity.after.dto.AfterSalesDto;
+
+
+/**
+ * <p>
+ * 售后管理 服务类
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+public interface AfterSalesService extends BaseService<AfterSales> {
+
+    /**
+     * 售后管理分页
+     */
+    Page<AfterSalesVo> getPage(AfterSalesSelectDto dto);
+
+    /**
+     * 售后管理明细
+     */
+    AfterSalesVo detail(Long id);
+
+    /**
+     * 售后管理新增
+     */
+    void addOrEdit(AfterSalesDto afterSalesDto);
+
+    /**
+     * 售后管理删除
+     */
+    void delete(Long id);
+
+    void cancellation(Long businessId);
+}

+ 61 - 0
hx-sale/src/main/java/com/fjhx/sale/service/after/impl/AfterSalesDetailServiceImpl.java

@@ -0,0 +1,61 @@
+package com.fjhx.sale.service.after.impl;
+
+import com.alibaba.druid.sql.visitor.functions.Concat;
+import com.fjhx.item.service.product.ProductInfoService;
+import com.fjhx.sale.entity.after.po.AfterSalesDetail;
+import com.fjhx.sale.mapper.after.AfterSalesDetailMapper;
+import com.fjhx.sale.service.after.AfterSalesDetailService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.sale.service.contract.ContractProductService;
+import com.fjhx.wms.entity.arrival.vo.ArrivalStockRecordsDetailsVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fjhx.sale.entity.after.vo.AfterSalesDetailVo;
+import com.fjhx.sale.entity.after.dto.AfterSalesDetailSelectDto;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 售后明细 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Service
+public class AfterSalesDetailServiceImpl extends ServiceImpl<AfterSalesDetailMapper, AfterSalesDetail> implements AfterSalesDetailService {
+    @Autowired
+    private ProductInfoService productInfoService;
+    @Autowired
+    private ContractProductService contractProductService;
+
+    @Override
+    public List<AfterSalesDetailVo> getList(AfterSalesDetailSelectDto dto) {
+        IWrapper<AfterSalesDetail> wrapper = getWrapper();
+        wrapper.orderByDesc("asd", AfterSalesDetail::getId);
+        List<AfterSalesDetailVo> list = this.getList(wrapper);
+        return list;
+    }
+
+    @Override
+    public List<AfterSalesDetailVo> getList(IWrapper wrapper) {
+        List<AfterSalesDetailVo> list = this.baseMapper.getList(wrapper);
+        //赋值产品信息
+        productInfoService.attributeAssign(list, AfterSalesDetailVo::getProductId, (item, productInfo) -> {
+            item.setProductName(productInfo.getName());
+            item.setProductType(productInfo.getType());
+            item.setProductCode(productInfo.getCustomCode());
+            item.setProductUnit(productInfo.getUnit());
+            item.setProductSpec(productInfo.getSpec());
+        });
+        //赋值产品信息
+        contractProductService.attributeAssign(list, AfterSalesDetailVo::getContractProductId, (item, contractProduct) -> {
+            item.setProductModel(contractProduct.getProductModel());
+            item.setContractQuantity(contractProduct.getQuantity());
+        });
+        return list;
+    }
+
+}

+ 52 - 0
hx-sale/src/main/java/com/fjhx/sale/service/after/impl/AfterSalesRecordsServiceImpl.java

@@ -0,0 +1,52 @@
+package com.fjhx.sale.service.after.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.file.utils.ObsFileUtil;
+import com.fjhx.sale.entity.after.dto.AfterSalesRecordsDto;
+import com.fjhx.sale.entity.after.po.AfterSalesRecords;
+import com.fjhx.sale.entity.after.vo.AfterSalesRecordsVo;
+import com.fjhx.sale.mapper.after.AfterSalesRecordsMapper;
+import com.fjhx.sale.service.after.AfterSalesRecordsService;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import com.ruoyi.system.utils.UserUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+
+/**
+ * <p>
+ * 售后跟进记录 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Service
+public class AfterSalesRecordsServiceImpl extends ServiceImpl<AfterSalesRecordsMapper, AfterSalesRecords> implements AfterSalesRecordsService {
+
+    @Override
+    public List<AfterSalesRecordsVo> getList(IWrapper wrapper) {
+        List<AfterSalesRecordsVo> list = baseMapper.getList(wrapper);
+        UserUtil.assignmentNickName(list, AfterSalesRecords::getFollowUpUserId, AfterSalesRecordsVo::setFollowUpUserName);
+        return list;
+    }
+
+    @Override
+    public void add(AfterSalesRecordsDto afterSalesRecordsDto) {
+        this.save(afterSalesRecordsDto);
+        ObsFileUtil.saveFile(afterSalesRecordsDto.getFileList(), afterSalesRecordsDto.getId());
+    }
+
+    @Override
+    public void edit(AfterSalesRecordsDto afterSalesRecordsDto) {
+        this.updateById(afterSalesRecordsDto);
+        ObsFileUtil.editFile(afterSalesRecordsDto.getFileList(), afterSalesRecordsDto.getId());
+    }
+
+    @Override
+    public void delete(Long id) {
+        this.removeById(id);
+    }
+
+}

+ 156 - 0
hx-sale/src/main/java/com/fjhx/sale/service/after/impl/AfterSalesServiceImpl.java

@@ -0,0 +1,156 @@
+package com.fjhx.sale.service.after.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.dynamic.datasource.annotation.DSTransactional;
+import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.common.constant.SourceConstant;
+import com.fjhx.common.enums.FlowStatusEnum1;
+import com.fjhx.file.utils.ObsFileUtil;
+import com.fjhx.flow.entity.flow.po.FlowExample;
+import com.fjhx.flow.enums.FlowStatusEnum;
+import com.fjhx.flow.service.flow.FlowExampleService;
+import com.fjhx.sale.entity.after.dto.AfterSalesDto;
+import com.fjhx.sale.entity.after.dto.AfterSalesSelectDto;
+import com.fjhx.sale.entity.after.po.AfterSales;
+import com.fjhx.sale.entity.after.po.AfterSalesDetail;
+import com.fjhx.sale.entity.after.po.AfterSalesRecords;
+import com.fjhx.sale.entity.after.vo.AfterSalesDetailVo;
+import com.fjhx.sale.entity.after.vo.AfterSalesRecordsVo;
+import com.fjhx.sale.entity.after.vo.AfterSalesVo;
+import com.fjhx.sale.mapper.after.AfterSalesMapper;
+import com.fjhx.sale.service.after.AfterSalesDetailService;
+import com.fjhx.sale.service.after.AfterSalesRecordsService;
+import com.fjhx.sale.service.after.AfterSalesService;
+import com.fjhx.sale.service.contract.ContractProductService;
+import com.ruoyi.common.core.domain.BasePo;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import com.ruoyi.common.utils.wrapper.SqlField;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+/**
+ * <p>
+ * 售后管理 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2024-04-07
+ */
+@Service
+public class AfterSalesServiceImpl extends ServiceImpl<AfterSalesMapper, AfterSales> implements AfterSalesService {
+
+    @Autowired
+    private ContractProductService contractProductService;
+    @Autowired
+    private AfterSalesDetailService afterSalesDetailService;
+    @Autowired
+    private FlowExampleService flowExampleService;
+    @Autowired
+    private AfterSalesRecordsService afterSalesRecordsService;
+
+    @Override
+    public Page<AfterSalesVo> getPage(AfterSalesSelectDto dto) {
+        IWrapper<AfterSales> wrapper = getWrapper();
+
+        wrapper.keyword(dto.getKeyword(), new SqlField("c.code"));
+
+        wrapper.eq("as1", AfterSales::getStatus, dto.getStatus());
+        wrapper.eq("as1", AfterSales::getType, dto.getType());
+
+        wrapper.orderByDesc("as1", AfterSales::getId);
+        Page<AfterSalesVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
+        List<AfterSalesVo> records = page.getRecords();
+        setInfo(records);
+        return page;
+    }
+
+    private void setInfo(List<AfterSalesVo> records) {
+        if (ObjectUtil.isEmpty(records)) {
+            return;
+        }
+        List<Long> asIds = records.stream().map(AfterSales::getId).collect(Collectors.toList());
+        //赋值跟进记录
+        List<AfterSalesRecordsVo> afterSalesRecordList = afterSalesRecordsService.getList(IWrapper.getWrapper().in(AfterSalesRecords::getAfterSalesId, asIds));
+        Map<Long, List<AfterSalesRecordsVo>> collect = afterSalesRecordList.stream().collect(Collectors.groupingBy(AfterSalesRecords::getAfterSalesId));
+        for (AfterSalesVo record : records) {
+            record.setAfterSalesRecordsList(collect.getOrDefault(record.getId(), new ArrayList<>()));
+        }
+    }
+
+    private void setDetail(List<AfterSalesVo> records) {
+        if (ObjectUtil.isEmpty(records)) {
+            return;
+        }
+        List<Long> asIds = records.stream().map(AfterSales::getId).collect(Collectors.toList());
+        //赋值明细
+        List<AfterSalesDetailVo> afterSalesDetailVos = afterSalesDetailService.getList(IWrapper.getWrapper().in("asd", AfterSalesDetail::getAfterSalesId, asIds));
+        Map<Long, List<AfterSalesDetailVo>> collect = afterSalesDetailVos.stream().collect(Collectors.groupingBy(AfterSalesDetail::getAfterSalesId));
+        for (AfterSalesVo record : records) {
+            record.setAfterSalesDetailList(collect.getOrDefault(record.getId(), new ArrayList<>()));
+        }
+    }
+
+    @Override
+    public AfterSalesVo detail(Long id) {
+        AfterSalesVo result = baseMapper.detail(IWrapper.getWrapper().eq("as1", AfterSales::getId, id));
+
+        setInfo(Arrays.asList(result));
+        setDetail(Arrays.asList(result));
+        return result;
+    }
+
+    @DSTransactional
+    @Override
+    public void addOrEdit(AfterSalesDto dto) {
+        List<AfterSalesDetail> afterSalesDetailList = dto.getAfterSalesDetailList();
+        contractProductService.attributeAssign(afterSalesDetailList, AfterSalesDetail::getContractProductId, (item, contractProduct) -> {
+            item.setContractId(contractProduct.getContractId());
+        });
+
+        this.saveOrUpdate(dto);
+
+        //售后附件
+        ObsFileUtil.editFile(dto.getFileList(), dto.getId());
+
+        for (AfterSalesDetail afterSalesDetail : afterSalesDetailList) {
+            afterSalesDetail.setAfterSalesId(dto.getId());
+        }
+        afterSalesDetailService.editLinked(afterSalesDetailList, AfterSalesDetail::getAfterSalesId, dto.getId());
+    }
+
+    @Override
+    public void delete(Long id) {
+        this.removeById(id);
+    }
+
+    @DSTransactional
+    @Override
+    public void cancellation(Long id) {
+        AfterSales afterSales = getById(id);
+        this.update(q -> q
+                .eq(AfterSales::getId, id)
+                .set(AfterSales::getStatus, FlowStatusEnum1.CANCELLATION.getKey())
+                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
+                .set(BasePo::getUpdateTime, new Date())
+        );
+
+        //销毁审批中的流程
+        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
+        flowExampleService.update(q -> q
+                .eq(FlowExample::getId, afterSales.getFlowId())
+                .in(FlowExample::getStatus, FlowStatusEnum.READY_START.getKey(), FlowStatusEnum.IN_PROGRESS.getKey())
+                .set(FlowExample::getStatus, FlowStatusEnum.CANCELLATION.getKey())
+                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
+                .set(BasePo::getUpdateTime, new Date())
+        );
+        DynamicDataSourceContextHolder.poll();
+    }
+
+}

+ 29 - 30
hx-sale/src/main/java/com/fjhx/sale/service/contract/impl/ContractProductServiceImpl.java

@@ -93,21 +93,23 @@ public class ContractProductServiceImpl extends ServiceImpl<ContractProductMappe
     @Override
     public Page<ContractProductVo> getPage(ContractProductSelectDto dto) {
         IWrapper<ContractProduct> wrapper = getWrapper();
-        wrapper.orderByDesc("t1", ContractProduct::getCreateTime);
-        wrapper.ne("t1", ContractProduct::getExpendQuantity, 0);
-        wrapper.between("t2", Contract::getStatus, FlowStatusEnum1.PASS.getKey(), FlowStatusEnum1.CANCELLATION.getKey() - 1);
-        if (ObjectUtil.isNotEmpty(dto.getDataType()) && dto.getDataType() == 0) {//合同交接单
-            wrapper.ne("t1", ContractProduct::getExpendQuantity, BigDecimal.ZERO);
-        }
-        if (ObjectUtil.isNotEmpty(dto.getPurchaseStatus()) && dto.getPurchaseStatus() == 2) {//已采购
-            wrapper.eq("t1", ContractProduct::getExpendQuantity, BigDecimal.ZERO);
-        } else if (ObjectUtil.isNotEmpty(dto.getPurchaseStatus()) && dto.getPurchaseStatus() == 1) {//部分采购
-            wrapper.gt("t1", ContractProduct::getExpendQuantity, BigDecimal.ZERO);
-            wrapper.apply("t1.expend_quantity <t1.quantity");
-        } else if (ObjectUtil.isNotEmpty(dto.getPurchaseStatus()) && dto.getPurchaseStatus() == 0) {//未采购
-            wrapper.apply("t1.expend_quantity = t1.quantity");
-        }
-        wrapper.eq("t2", Contract::getIssue, 1);
+//        wrapper.ne("t1", ContractProduct::getExpendQuantity, 0);
+//        wrapper.between("t2", Contract::getStatus, FlowStatusEnum1.PASS.getKey(), FlowStatusEnum1.CANCELLATION.getKey() - 1);
+//        if (ObjectUtil.isNotEmpty(dto.getDataType()) && dto.getDataType() == 0) {//合同交接单
+//            wrapper.ne("t1", ContractProduct::getExpendQuantity, BigDecimal.ZERO);
+//        }
+//        if (ObjectUtil.isNotEmpty(dto.getPurchaseStatus()) && dto.getPurchaseStatus() == 2) {//已采购
+//            wrapper.eq("t1", ContractProduct::getExpendQuantity, BigDecimal.ZERO);
+//        } else if (ObjectUtil.isNotEmpty(dto.getPurchaseStatus()) && dto.getPurchaseStatus() == 1) {//部分采购
+//            wrapper.gt("t1", ContractProduct::getExpendQuantity, BigDecimal.ZERO);
+//            wrapper.apply("t1.expend_quantity <t1.quantity");
+//        } else if (ObjectUtil.isNotEmpty(dto.getPurchaseStatus()) && dto.getPurchaseStatus() == 0) {//未采购
+//            wrapper.apply("t1.expend_quantity = t1.quantity");
+//        }
+//        wrapper.eq("t2", Contract::getIssue, 1);
+
+        wrapper.in("t2", Contract::getStatus, 10, 30, 60);
+
         if (StringUtils.isNotEmpty(dto.getKeyword())) {
             wrapper.keyword(dto.getKeyword(), new SqlField("t2.`code`"), new SqlField("t2.`user_name`"));
         }
@@ -120,35 +122,32 @@ public class ContractProductServiceImpl extends ServiceImpl<ContractProductMappe
             }
             wrapper.in("t2.contract_template_id", ctIds);
         }
-        //是否到账过滤
-        if (ObjectUtil.isNotEmpty(dto.getIsReceived())) {
-            if (1 == dto.getIsReceived()) {
-                wrapper.isNotNull("co.id");
-            } else {
-                wrapper.isNull("co.id");
-            }
-        }
-        wrapper.groupBy("t1.id");
+//        //是否到账过滤
+//        if (ObjectUtil.isNotEmpty(dto.getIsReceived())) {
+//            if (1 == dto.getIsReceived()) {
+//                wrapper.isNotNull("co.id");
+//            } else {
+//                wrapper.isNull("co.id");
+//            }
+//        }
+
+//        wrapper.groupBy("t1.id");
+        wrapper.orderByDesc("t1", ContractProduct::getCreateTime);
         Page<ContractProductVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
         List<ContractProductVo> list = page.getRecords();
-        List<Long> idList = list.stream().map(ContractProductVo::getId).collect(Collectors.toList());
         if (list.size() == 0) {
             return page;
         }
 
         // 赋值产品属性
         productInfoService.attributeAssign(list, ContractProductVo::getProductId, (item, product) -> {
-            item.setProductCode(product.getCode());
+            item.setProductCode(product.getCustomCode());
             item.setProductUnit(product.getUnit());
             item.setProductType(product.getType());
             item.setProductName(product.getName());
             item.setProductSpec(product.getSpec());
             item.setProductCategoryId(product.getProductClassifyId());
         });
-        //赋值已发起采购数量
-//        List<PurchaseDetailVo> purchaseDetailVoList = purchaseDetailService.getSumCountByDataResourceId(idList);
-//        Map<Long,BigDecimal> pMap = purchaseDetailVoList.stream().collect(Collectors.toMap(PurchaseDetailVo::getDataResourceId,PurchaseDetailVo::getSumCount));
-//        list.forEach(i -> i.setStartPurchaseCount(MapUtils.isNotEmpty(pMap)?BigDecimal.ZERO:pMap.getOrDefault(i.getId(),BigDecimal.ZERO)));
         // 赋值产品分类名称
         productClassifyService.attributeAssign(list, ContractProductVo::getProductCategoryId, (item, productClassify) -> {
             item.setProductCategory(productClassify.getName());

+ 37 - 3
hx-sale/src/main/java/com/fjhx/sale/service/contract/impl/ContractServiceImpl.java

@@ -597,11 +597,14 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract>
                     .sorted(Comparator.comparing(ContractBudgetVo.GrossProfitInfo::getCreateTime)).collect(Collectors.toList());
 
             //计数采购价格
+            Long lastContractId = null;
             BigDecimal lastContractAmount = BigDecimal.ZERO;
             String lastContractCurrency = "";
             BigDecimal lastContractRmbAmount = BigDecimal.ZERO;
+            Long lastPurchaseId = null;
             BigDecimal lastPurchaseAmount = BigDecimal.ZERO;
-            for (ContractBudgetVo.GrossProfitInfo grossProfitInfo : grossProfitInfoList) {
+            for (int i = 0; i < grossProfitInfoList.size(); i++) {
+                ContractBudgetVo.GrossProfitInfo grossProfitInfo = grossProfitInfoList.get(i);
                 if (grossProfitInfo.getType() == 2) {
                     //如果是采购节点
                     BigDecimal purchaseAmount = BigDecimal.ZERO;
@@ -633,12 +636,22 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract>
 
                     grossProfitInfo.setPurchaseAmount(purchaseAmount);
                     lastPurchaseAmount = purchaseAmount;
+
+                    lastPurchaseId = grossProfitInfo.getId();
+
+                    grossProfitInfo.setPurchaseId(grossProfitInfo.getId());
+                    grossProfitInfo.setContractId(lastContractId);
                 } else {
                     //销售合同节点
                     lastContractAmount = grossProfitInfo.getContractAmount();
                     lastContractRmbAmount = grossProfitInfo.getContractRmbAmount();
                     lastContractCurrency = grossProfitInfo.getContractCurrency();
                     grossProfitInfo.setPurchaseAmount(lastPurchaseAmount);
+
+                    lastContractId = grossProfitInfo.getId();
+
+                    grossProfitInfo.setPurchaseId(lastPurchaseId);
+                    grossProfitInfo.setContractId(grossProfitInfo.getId());
                 }
 //            }
 //
@@ -665,7 +678,10 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract>
                 //计数毛利
 
                 //退税金额
-                BigDecimal refundableAmount = contractBudgetVo.getRefundableAmount();
+                ContractBudgetVo cb1 = new ContractBudgetVo();
+                cb1.setEhsdSumAmount(grossProfitInfo.getPurchaseAmount());
+                handleRefundTax(cb1);
+                BigDecimal refundableAmount = cb1.getRefundableAmount();
                 //总收入
                 BigDecimal incomeAmount = grossProfitInfo.getContractRmbAmount().add(refundableAmount);
 
@@ -682,6 +698,21 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract>
                 BigDecimal grossProfit = incomeAmount.subtract(expenditureAmount);
                 grossProfitInfo.setGross(grossProfit.setScale(2, BigDecimal.ROUND_HALF_UP));
 
+                //毛利率(毛利/合同金额*100%)
+                grossProfitInfo.setGrossRate(BigDecimal.ZERO);
+                if (BigDecimal.ZERO.compareTo(grossProfitInfo.getContractRmbAmount()) != 0) {
+                    BigDecimal grossRate = grossProfitInfo.getGross()
+                            .divide(grossProfitInfo.getContractRmbAmount(), 2, BigDecimal.ROUND_HALF_UP)
+                            .multiply(BigDecimal.valueOf(100));
+                    grossProfitInfo.setGrossRate(grossRate);
+                }
+                //对比上一版本利润
+                grossProfitInfo.setCompareLastGross(BigDecimal.ZERO);
+                if ((i - 1) >= 0) {
+                    ContractBudgetVo.GrossProfitInfo lastGrossProfitInfo = grossProfitInfoList.get(i - 1);
+                    BigDecimal subtract = lastGrossProfitInfo.getGross().subtract(grossProfitInfo.getGross());
+                    grossProfitInfo.setCompareLastGross(subtract);
+                }
             }
             contractBudgetVo.setGrossProfitInfoList(grossProfitInfoList);
         }
@@ -861,7 +892,10 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract>
             //计算毛利 收入-支出
             v.setGross(v.getIncomeAmount().subtract(v.getExpenditureAmount()));
             //计算毛利率 毛利/收入
-            v.setGrossRate(v.getGross().divide(v.getIncomeAmount(), RoundingMode.CEILING).multiply(new BigDecimal("100")));
+            v.setGrossRate(BigDecimal.ZERO);
+            if (BigDecimal.ZERO.compareTo(v.getIncomeAmount()) != 0) {
+                v.setGrossRate(v.getGross().divide(v.getIncomeAmount(), RoundingMode.CEILING).multiply(new BigDecimal("100")));
+            }
         }
     }
 

+ 16 - 0
hx-sale/src/main/java/com/fjhx/sale/service/purchase/impl/EhsdPurchaseServiceImpl.java

@@ -560,6 +560,17 @@ public class EhsdPurchaseServiceImpl extends ServiceImpl<EhsdPurchaseMapper, Ehs
         Map<Long, List<EhsdPurchaseProductVo>> purchaseProductMap =
                 purchaseProductList.stream().collect(Collectors.groupingBy(EhsdPurchaseProductVo::getProductId));
 
+        //产品近30天采购价格
+        List<EhsdPurchaseProductVo> purchaseProductList1 = baseMapper.getProductPriceInfo(IWrapper.getWrapper()
+                .in("epp.product_id", productIds)
+                .apply("epp.create_time >= CURDATE() - INTERVAL 30 DAY")
+                .groupBy("DATE_FORMAT( epp.create_time, '%Y-%m-%d' ) ")
+                .orderByDesc(EhsdPurchase::getCreateTime)
+                .orderByDesc(EhsdPurchase::getId)
+        );
+        Map<Long, List<EhsdPurchaseProductVo>> purchaseProductMap1 =
+                purchaseProductList1.stream().collect(Collectors.groupingBy(EhsdPurchaseProductVo::getProductId));
+
         //按价格升序 获取前10供应商
         List<SupplierPriceVo> topPriceList = supplierPriceService.getTopPriceList(productIds, 10);
         Map<Long, List<SupplierPriceVo>> topPriceMap = topPriceList.stream().collect(Collectors.groupingBy(SupplierPrice::getProductInfoId));
@@ -575,6 +586,11 @@ public class EhsdPurchaseServiceImpl extends ServiceImpl<EhsdPurchaseMapper, Ehs
             //前10供应商价格
             data.put("topPriceList", topPriceMap.getOrDefault(productId, new ArrayList<>()));
 
+            //进n天最高/最低采购价
+            List<EhsdPurchaseProductVo> orDefault = purchaseProductMap1.getOrDefault(productId, new ArrayList<>());
+            data.put("maxPurchasePrice", orDefault.stream().map(EhsdPurchaseProductVo::getPrice).max(BigDecimal::compareTo).orElse(null));
+            data.put("minPurchasePrice", orDefault.stream().map(EhsdPurchaseProductVo::getPrice).min(BigDecimal::compareTo).orElse(null));
+
             reData.put(productId, data);
         }
 

+ 1 - 2
hx-sale/src/main/java/com/fjhx/sale/service/sample/impl/SampleServiceImpl.java

@@ -222,8 +222,7 @@ public class SampleServiceImpl extends ServiceImpl<SampleMapper, Sample> impleme
         }
         //买方信息
         Customer customer = customerService.getById(result.getBuyCorporationId());
-        if (ObjectUtil.isNotEmpty(corporation)) {
-            result.setSellCorporationName(corporation.getName());
+        if (ObjectUtil.isNotEmpty(customer)) {
             result.setBuyCorporationName(customer.getName());
         }
         //买方地址信息

+ 10 - 0
hx-sale/src/main/resources/mapper/after/AfterSalesDetailMapper.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.sale.mapper.after.AfterSalesDetailMapper">
+    <select id="getList" resultType="com.fjhx.sale.entity.after.vo.AfterSalesDetailVo">
+        select asd.*
+        from after_sales_detail asd
+            ${ew.customSqlSegment}
+    </select>
+
+</mapper>

+ 39 - 0
hx-sale/src/main/resources/mapper/after/AfterSalesMapper.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.sale.mapper.after.AfterSalesMapper">
+    <sql id="list">
+        SELECT as1.id,
+               as1.customer_id,
+               as1.contract_id,
+               as1.contract_ids,
+               as1.code,
+               as1.type,
+               as1.remark,
+               as1.reason,
+               as1.amount,
+               as1.duty_party,
+               as1.contact_name,
+               as1.contact_tel,
+               as1.account_bank,
+               as1.account_name,
+               as1.account_number,
+               as1.`status`,
+               as1.flow_id,
+               as1.create_user,
+               as1.create_time,
+               as1.update_user,
+               as1.update_time,
+               c.`code` as contractCode
+        FROM after_sales as1
+                 left join contract c on c.id = as1.contract_id
+    </sql>
+    <select id="getPage" resultType="com.fjhx.sale.entity.after.vo.AfterSalesVo">
+        <include refid="list"/>
+        ${ew.customSqlSegment}
+    </select>
+    <select id="detail" resultType="com.fjhx.sale.entity.after.vo.AfterSalesVo">
+        <include refid="list"/>
+        ${ew.customSqlSegment}
+    </select>
+
+</mapper>

+ 9 - 0
hx-sale/src/main/resources/mapper/after/AfterSalesRecordsMapper.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.sale.mapper.after.AfterSalesRecordsMapper">
+    <select id="getList" resultType="com.fjhx.sale.entity.after.vo.AfterSalesRecordsVo">
+        SELECT asr.*
+        FROM after_sales_records asr
+            ${ew.customSqlSegment}
+    </select>
+</mapper>

+ 35 - 18
hx-sale/src/main/resources/mapper/contract/ContractMapper.xml

@@ -20,10 +20,23 @@
                             FROM claim_contract cc
                                      left join claim c on cc.claim_id = c.id
                                      LEFT JOIN bytesailing_account.account_running_water arw on c.business_id = arw.id
-                            WHERE cc.contract_id = t1.id) AS sumClaimMoney
+                            WHERE cc.contract_id = t1.id) AS sumClaimMoney,
+                           pa.notPack
                     FROM contract t1
                              left join bytesailing_customer.customer c on t1.buy_corporation_id = c.id
-                             left join bytesailing_base.sys_user us on c.user_id = us.user_id) t1
+                             left join bytesailing_base.sys_user us on c.user_id = us.user_id
+                             left join (SELECT pack.*,
+                                               (sumPackQuantity &lt; cpQuantity) notPack
+                                        FROM (SELECT t1.id                                   AS contractId,
+                                                     t2.quantity                             AS cpQuantity,
+                                                     (SELECT IFNULL(SUM(pd.pack_quantity * pdd.quantity), 0)
+                                                      FROM pack_detail_product pdd
+                                                               LEFT JOIN pack_detail pd ON pdd.pack_detail_id = pd.id
+                                                      WHERE pdd.contract_product_id = t2.id) AS sumPackQuantity
+                                              FROM contract t1
+                                                       LEFT JOIN contract_product t2 ON t1.id = t2.contract_id
+                                              WHERE t1.`status` = 30
+                                              GROUP BY t1.id) pack) pa on pa.contractId = t1.id) t1
               GROUP BY t1.id) t1
             ${ew.customSqlSegment}
     </select>
@@ -147,26 +160,30 @@
 
     <select id="getNoPackContractByCustomerId" resultType="com.fjhx.sale.entity.contract.vo.ContractVo">
         SELECT
-        *
-        FROM
-        (
-        SELECT
         t1.*,
         t2.quantity AS cpQuantity,
-        ( SELECT IFNULL( SUM( pd.pack_quantity * pdd.quantity ), 0 ) FROM pack_detail_product pdd LEFT JOIN pack_detail
-        pd ON pdd.pack_detail_id = pd.id WHERE pdd.contract_product_id = t2.id ) AS sumPackQuantity
+        IFNULL( sp.sumPackQuantity, 0 ) sumPackQuantity
         FROM
         contract t1
-        LEFT JOIN contract_product t2 ON t1.id = t2.contract_id
-        <where>
-            <if test="customerId neq null and customerId neq '' ">
-                buy_corporation_id = #{customerId}
-            </if>
-        </where>
-        ) t1
-        WHERE t1.sumPackQuantity &lt; t1.cpQuantity
-        AND t1.`status`=30
-        GROUP BY t1.id
+        JOIN contract_product t2 ON t1.id = t2.contract_id
+        LEFT JOIN (
+        SELECT
+        pdd.contract_product_id,
+        IFNULL( SUM( pd.pack_quantity * pdd.quantity ), 0 ) AS sumPackQuantity
+        FROM
+        pack_detail_product pdd
+        JOIN pack_detail pd ON pdd.pack_detail_id = pd.id
+        GROUP BY
+        pdd.contract_product_id
+        ) sp ON sp.contract_product_id = t2.id
+        WHERE
+        t1.`status` = 30
+        AND IFNULL( sp.sumPackQuantity, 0 ) &lt; t2.quantity
+        <if test="customerId neq null and customerId neq '' ">
+            and buy_corporation_id = #{customerId}
+        </if>
+        GROUP BY
+        t1.id
     </select>
 
     <select id="getSalesTotal" resultType="com.fjhx.sale.entity.contract.vo.ContractVo">

+ 11 - 17
hx-sale/src/main/resources/mapper/contract/ContractProductMapper.xml

@@ -4,26 +4,20 @@
 
     <select id="getPage" resultType="com.fjhx.sale.entity.contract.vo.ContractProductVo">
         SELECT t1.id,
-               t2.create_time AS contractTime,
+               t2.create_time          AS contractTime,
                t1.contract_id,
                t1.product_id,
-               t2.`code`          AS contractCode,
-               t2.user_name       AS userName,
-               t2.create_user     AS salesmanId,
-               t2.version         AS contractVersion,
-               t1.expend_quantity AS expendQuantity,
-               (SELECT create_time
-                FROM claim_contract
-                WHERE contract_id = t2.id
-                ORDER BY create_time DESC
-                                     LIMIT 1)               AS claimTime,
-               t2.contract_template_id AS contractTemplateId,
-               t1.quantity
+               t1.product_model,
+               t1.quantity,
+               t1.price,
+               t1.expend_quantity      AS expendQuantity,
+               t2.`code`               AS contractCode,
+               t2.user_name            AS userName,
+               t2.create_user          AS salesmanId,
+               t2.version              AS contractVersion,
+               t2.contract_template_id AS contractTemplateId
         FROM contract_product t1
-            LEFT JOIN contract t2
-            LEFT JOIN claim_contract co
-        on co.contract_id = t2.id
-            ON t1.contract_id = t2.id
+                 JOIN contract t2 ON t1.contract_id = t2.id
             ${ew.customSqlSegment}
     </select>