lfx 1 год назад
Родитель
Сommit
372c333563
20 измененных файлов с 1119 добавлено и 64 удалено
  1. 11 12
      mjava-kuaikeli/pom.xml
  2. 4 1
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/controller/CdTestController.java
  3. 131 0
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/controller/KKLController.java
  4. 17 3
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/controller/SupplierMaterialController.java
  5. 150 0
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/entity/MaterialDetail.java
  6. 30 0
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/entity/Pricing.java
  7. 12 0
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/entity/SupplierMaterial.java
  8. 19 11
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/listener/SupplierMaterialDataListener.java
  9. 11 0
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/mapper/MaterialDetailMapper.java
  10. 7 0
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/mapper/SupplierMaterialMapper.java
  11. 55 0
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/schedule/ScheduleTask.java
  12. 21 0
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/service/KKLService.java
  13. 14 1
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/service/SupplierMaterialService.java
  14. 336 0
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/service/impl/KKLImplService.java
  15. 214 31
      mjava-kuaikeli/src/main/java/com/malk/kuaikeli/service/impl/SupplierMaterialServiceImpl.java
  16. 2 2
      mjava-kuaikeli/src/main/resources/application-dev.yml
  17. 30 0
      mjava-kuaikeli/src/main/resources/application-prod.yml
  18. 1 1
      mjava-kuaikeli/src/main/resources/application.yml
  19. 51 0
      mjava-kuaikeli/src/main/resources/mapper/SupplierMaterialMapper.xml
  20. 3 2
      mjava-kuaikeli/src/test/java/com/malk/kuaikeli/DdTest.java

+ 11 - 12
mjava-kuaikeli/pom.xml

@@ -4,22 +4,16 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.2.0.RELEASE</version> <!-- 使用最新的稳定版或其他适用版本 -->
+    </parent>
+
     <groupId>com.malk</groupId>
     <artifactId>mjava-kuaikeli</artifactId>
     <version>1.0-SNAPSHOT</version>
 
-    <dependencyManagement>
-        <dependencies>
-            <!-- SpringBoot 依赖 -->
-            <dependency>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-dependencies</artifactId>
-                <version>2.2.13.RELEASE</version>
-                <type>pom</type>
-                <scope>import</scope>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
     <dependencies>
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -49,6 +43,11 @@
             <artifactId>base</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>io.github.biezhi</groupId>
+            <artifactId>TinyPinyin</artifactId>
+            <version>2.0.3.RELEASE</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 4 - 1
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/controller/CdTestController.java

@@ -12,6 +12,7 @@ import com.malk.service.aliwork.YDService;
 import com.malk.service.dingtalk.DDClient;
 import com.malk.utils.UtilMap;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -26,10 +27,12 @@ public class CdTestController {
     private DDClient ddClient;
     @Autowired
     private YDClient ydClient;
+    @Value("${server.port}")
+    private String port;
 
     @GetMapping("/hello")
     public McR hello(){
-        return McR.success("Hello");
+        return McR.success("Hello "+ port);
     }
 
     @GetMapping("/dd")

+ 131 - 0
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/controller/KKLController.java

@@ -0,0 +1,131 @@
+package com.malk.kuaikeli.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.malk.kuaikeli.service.KKLService;
+import com.malk.server.common.McR;
+import com.malk.utils.UtilServlet;
+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;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+/**
+ * 错误抛出与拦截详见 CatchException
+ */
+@Slf4j
+@RestController
+@RequestMapping()
+public class KKLController {
+
+    @Autowired
+    private KKLService kklService;
+
+    /**
+     * [动态] 发起单据, 分供应商进行流程推送
+     */
+    @PostMapping("supplier")
+    McR supplier(HttpServletRequest request) {
+
+        Map data = UtilServlet.getParamMap(request);
+        log.info("supplier, {}", JSON.toJSONString(data));
+
+        kklService.matchSupplier(data);
+        return McR.success();
+    }
+
+    /**
+     * 菜单计划, 编辑校验
+     * -
+     * 前端提交动作: 校验是否审批通过, 是否当日之前计划, 是否当日且在16点及以后时间, 均不允许提交
+     * 后端校验返回、加任何产品都要走审批,减少20%以内直接过,每一个原材料
+     */
+    @PostMapping("validate")
+    McR validate(@RequestBody Map data) {
+
+        log.info("validate, {}", JSON.toJSONString(data));
+
+        kklService.validateApprove(data);
+        return McR.success();
+    }
+
+    /**
+     * 定价单: 项目点 & 供应商大类, 数据匹配
+     */
+    @PostMapping("service")
+    McR service(HttpServletRequest request) {
+
+        Map data = UtilServlet.getParamMap(request);
+        log.info("service, {}", JSON.toJSONString(data));
+
+        kklService.serviceRate(data);
+        return McR.success();
+    }
+
+    /**
+     * 物料档案: 价格调整
+     */
+    @PostMapping("adjust")
+    McR adjust(HttpServletRequest request) {
+
+        Map data = UtilServlet.getParamMap(request);
+        log.info("adjust, {}", JSON.toJSONString(data));
+
+        kklService.adjustCost(data);
+        return McR.success();
+    }
+
+    /**
+     * 供应商原材料档案: 新增匹配
+     * 更新定价单
+     */
+    @PostMapping("addition")
+    McR addition(HttpServletRequest request) {
+
+        Map data = UtilServlet.getParamMap(request);
+        log.info("addition, {}", JSON.toJSONString(data));
+
+        kklService.adjustCost(data);
+        return McR.success();
+    }
+
+
+    /***
+     * 新增定价单
+     * @param request
+     * @return
+     */
+    @PostMapping("updateDjd")
+    McR updateDjd(HttpServletRequest request) {
+
+        Map data = UtilServlet.getParamMap(request);
+        log.info("addition, {}", JSON.toJSONString(data));
+
+        kklService.additionMaterial(data);
+        return McR.success();
+    }
+
+
+    /**
+     * 周日同步更新价格
+     */
+    @PostMapping("sync")
+    McR sync() {
+        log.info("sync price");
+        kklService.syncPrice();
+        return McR.success();
+    }
+
+    
+    @PostMapping("test")
+    McR test(HttpServletRequest request) {
+        Map data = UtilServlet.getParamMap(request);
+        log.info("xxxx, {}", data);
+        return McR.success();
+    }
+
+}

+ 17 - 3
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/controller/SupplierMaterialController.java

@@ -5,9 +5,11 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.malk.kuaikeli.entity.SupplierMaterial;
 import com.malk.kuaikeli.listener.SupplierMaterialDataListener;
+import com.malk.kuaikeli.mapper.SupplierMaterialMapper;
 import com.malk.kuaikeli.service.SupplierMaterialService;
 import com.malk.server.common.McR;
 import com.malk.server.common.Page;
+import com.malk.utils.PublicUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -16,6 +18,9 @@ import java.io.IOException;
 import java.util.List;
 import java.util.Map;
 
+/***
+ * 供应商原材料
+ */
 @RestController
 @RequestMapping("/suppliermaterial")
 public class SupplierMaterialController {
@@ -31,13 +36,22 @@ public class SupplierMaterialController {
         if(!file.getOriginalFilename().endsWith("xlsx")&&!file.getOriginalFilename().endsWith("xls")) {
             return McR.errorParam("文件格式错误!");
         }
-        EasyExcel.read(file.getInputStream(), SupplierMaterial.class, new SupplierMaterialDataListener(supplierMaterialService)).sheet().doRead();
+        supplierMaterialService.uploadData(file);
         return McR.success();
     }
 
     @GetMapping("/sync")
-    public McR sync(String startDateTime){
-        supplierMaterialService.sync(startDateTime);
+    public McR sync(){
+        supplierMaterialService.sync();
+        return McR.success();
+    }
+
+    @PostMapping("/projectSupplierChange")
+    public McR projectSupplierChange(@RequestBody JSONObject param) throws IOException {
+        if(PublicUtil.isNull(param,"projectId","oldId","newId","newName")){
+            return McR.errorNullPointer();
+        }
+        supplierMaterialService.projectSupplierChange(param.getString("projectId"),param.getString("oldId"),param.getString("newId"),param.getString("newName"));
         return McR.success();
     }
 

+ 150 - 0
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/entity/MaterialDetail.java

@@ -0,0 +1,150 @@
+package com.malk.kuaikeli.entity;
+
+import cn.hutool.core.annotation.Alias;
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.malk.utils.UtilDateTime;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Map;
+
+@Data
+@EqualsAndHashCode
+@TableName("t_material_detail")
+public class MaterialDetail {
+
+    // ID
+//    @TableId(value = "id",type = IdType.INPUT)
+//    private String id;
+
+    // 供应商编号
+    @Alias("textField_llzzbyj1")
+    private String supplierId;
+
+    // 供应商名称
+    @Alias("textField_lmsli3bq")
+    private String supplierName;
+
+    // 项目编号
+    @Alias("textField_llm1vtjm")
+    private String projectId;
+
+    // 项目名称
+    @Alias("textField_loy1ep8r")
+    private String projectName;
+
+    // 物品名称
+    @Alias("textField_llkb7kd1")
+    private String materialName;
+
+    // 物品编号
+    @Alias("textField_llkb7kd2")
+    private String materialId;
+
+    // 单位
+    @Alias("textField_llkb7kd3")
+    private String unit;
+
+    // 规格
+    @Alias("textField_llkb7kd4")
+    private String specs;
+
+    // 第一分类
+    @Alias("selectField_llkb7kd5")
+    private String classifyOne;
+
+    // 第二分类
+    @Alias("selectField_llkk6cms")
+    private String classifyTwo;
+
+    // 服务费率
+    @Alias("numberField_llkb7kcy")
+    private String rate;
+
+    // 成本单价
+    @Alias("numberField_llkknd6g")
+    private String unitPrice;
+
+    // 供货价
+    @Alias("numberField_llkknd6h")
+    private String supplyPrice;
+
+    // 下周服务费率
+    @Alias("numberField_lpalgz04")
+    private String rateNext;
+
+    // 下周成本单价
+    @Alias("numberField_lpalgz05")
+    private String unitPriceNext;
+
+    // 下周供货价
+    @Alias("numberField_lpalgz0a")
+    private String supplyPriceNext;
+
+    // 其他信息
+    @Alias("textareaField_lllnl6yr")
+    private String otherInfo;
+
+    // 图片
+//    @Alias("imageField_lllnl6ys")
+    private String img;
+
+    // 品牌
+    @Alias("textField_lmkfg67e")
+    private String brand;
+
+    // 状态
+    @Alias("textField_lm4lxur8")
+    private String state="已启用";
+
+    // 期限
+    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
+    @Alias("dateField_lm4lxur7")
+    private String term;
+
+    // 包装数量
+    @Alias("numberField_lnrzzg03")
+    private String packingNumber;
+
+    // 包装单位
+    @Alias("textField_lnrzzg04")
+    private String packingUnit;
+
+    // 创建日期
+    private String createDateTime;
+
+    // 更新日期
+    private String updateDateTime;
+
+    private String formInstId;
+
+    public MaterialDetail(){}
+
+    public static MaterialDetail toBean(Map yidaFormData){
+        MaterialDetail materialDetail=BeanUtil.mapToBean(yidaFormData,MaterialDetail.class,false);
+        materialDetail.setTerm(UtilDateTime.getLocalDateTimeFromTimestamp(Long.parseLong(materialDetail.getTerm())).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+        return materialDetail;
+    }
+
+    public Map toYidaFormDataMap(){
+        Map map=BeanUtil.beanToMap(this);
+        // 时间处理
+        map.put("dateField_lm4lxur7", UtilDateTime.getLocalDateTimeTimeStamp(UtilDateTime.parseLocalDateTime(this.term)));
+        return map;
+    }
+
+    public MaterialDetail create(){
+        this.createDateTime = (LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
+        return this;
+    }
+
+    public MaterialDetail update(){
+        this.updateDateTime = (LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
+        return this;
+    }
+
+}

+ 30 - 0
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/entity/Pricing.java

@@ -0,0 +1,30 @@
+package com.malk.kuaikeli.entity;
+
+
+import cn.hutool.core.annotation.Alias;
+import lombok.Data;
+
+import java.util.Map;
+
+/***
+ * 定价单
+ */
+@Data
+public class Pricing {
+
+    // 供应商编号
+    @Alias("textField_llzzbai8")
+    private String supplierId;
+
+    // 项目编号
+    @Alias("textField_lllovku7")
+    private String projectId;
+
+    // 项目名称
+    @Alias("textField_loy1ep8r")
+    private String projectName;
+
+    // 相关信息
+    private Map<String,String> rateMap;
+
+}

+ 12 - 0
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/entity/SupplierMaterial.java

@@ -118,12 +118,23 @@ public class SupplierMaterial {
     @Alias("dateField_lpt4h37y")
     private String qualificationExpireDate;
 
+    private String formInstId;
+
+    // 是否需要同步到宜搭
+    private String isNeedSyncYd;
+
+    // 同步到中间表数量
+    private String materialDetailNumber;
+
     // 创建日期
     private String createDateTime;
 
     // 更新日期
     private String updateDateTime;
 
+    // 错误消息
+    private String errorMsg;
+
     public SupplierMaterial(){}
 
     public static SupplierMaterial toBean(Map yidaFormData){
@@ -142,6 +153,7 @@ public class SupplierMaterial {
     }
 
     public SupplierMaterial create(){
+        this.isNeedSyncYd="是";
         this.createDateTime = (LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
         return this;
     }

+ 19 - 11
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/listener/SupplierMaterialDataListener.java

@@ -21,7 +21,7 @@ public class SupplierMaterialDataListener extends AnalysisEventListener<Supplier
     private static final int BATCH_COUNT = 5;
     List<SupplierMaterial> list = new ArrayList<SupplierMaterial>();
 
-    private SupplierMaterialService supplierMaterialService;
+    private SupplierMaterialMapper supplierMaterialMapper;
 
     public SupplierMaterialDataListener() {
     }
@@ -29,8 +29,8 @@ public class SupplierMaterialDataListener extends AnalysisEventListener<Supplier
     /**
      * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
      */
-    public SupplierMaterialDataListener(SupplierMaterialService supplierMaterialService) {
-        this.supplierMaterialService = supplierMaterialService;
+    public SupplierMaterialDataListener(SupplierMaterialMapper supplierMaterialMapper) {
+        this.supplierMaterialMapper = supplierMaterialMapper;
     }
 
     /**
@@ -69,14 +69,22 @@ public class SupplierMaterialDataListener extends AnalysisEventListener<Supplier
      */
     private void saveData() {
         log.info("{}条数据,开始存储数据库!", list.size());
-        supplierMaterialService.saveOrUpdateBatch(list);
-//        for(SupplierMaterial supplierMaterial:list){
-//            if(supplierMaterialMapper.selectById(supplierMaterial.getMaterialId())!=null){
-//                supplierMaterialMapper.updateById(supplierMaterial.update());
-//            }else{
-//                supplierMaterialMapper.insert(supplierMaterial.create());
-//            }
-//        }
+//        supplierMaterialService.saveOrUpdateBatch(list);
+        for(SupplierMaterial supplierMaterial:list){
+            SupplierMaterial old = supplierMaterialMapper.selectById(supplierMaterial.getMaterialId());
+            if(old!=null){
+                if(!old.getUnitPrice().equals(supplierMaterial.getUnitPrice())){
+                    old.setIsNeedSyncYd("是");
+                    old.setUnitPrice(supplierMaterial.getUnitPrice());
+                    log.info("成本单价修改。数据:{}",old);
+                    supplierMaterialMapper.updateById(supplierMaterial.update());
+                }else{
+                    log.info("成本单价相同,跳过。数据:{}",supplierMaterial);
+                }
+            }else{
+                supplierMaterialMapper.insert(supplierMaterial.create());
+            }
+        }
         log.info("存储数据库成功!");
     }
 }

+ 11 - 0
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/mapper/MaterialDetailMapper.java

@@ -0,0 +1,11 @@
+package com.malk.kuaikeli.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.malk.kuaikeli.entity.MaterialDetail;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Repository
+@Mapper
+public interface MaterialDetailMapper extends BaseMapper<MaterialDetail> {
+}

+ 7 - 0
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/mapper/SupplierMaterialMapper.java

@@ -3,10 +3,17 @@ package com.malk.kuaikeli.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.malk.kuaikeli.entity.SupplierMaterial;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 @Repository
 @Mapper
 public interface SupplierMaterialMapper extends BaseMapper<SupplierMaterial> {
 
+    int updateUnitPrice();
+
+    List<SupplierMaterial> selectListForCopy(@Param("project_id") String project_id,@Param("supplier_id") String supplier_id);
+
 }

+ 55 - 0
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/schedule/ScheduleTask.java

@@ -0,0 +1,55 @@
+package com.malk.kuaikeli.schedule;
+
+import com.malk.kuaikeli.service.KKLService;
+import com.malk.kuaikeli.service.SupplierMaterialService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+/**
+ * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
+ */
+@Slf4j
+@Configuration
+@EnableScheduling
+@ConditionalOnProperty(name = {"enable.scheduling"})
+public class ScheduleTask {
+
+//    @Autowired
+//    private KKLService kklService;
+
+    @Autowired
+    private SupplierMaterialService supplierMaterialService;
+
+    /**
+     * 周一凌晨1点同步 (即周日后生效)
+     */
+    @Scheduled(cron = "0 0 1 * * ?")
+    public void syncDingTalkFailedList() {
+        log.info("开始同步原材料下周单价到本周");
+        try {
+//            kklService.syncPrice();
+            supplierMaterialService.syncPrice();
+        } catch (Exception e) {
+            // 记录错误信息
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 每10分钟同步
+     */
+    @Scheduled(cron = "0 0/10 * * * ?")
+    public void sync() {
+        log.info("开始同步供应商原材料");
+        try {
+            supplierMaterialService.sync();
+        } catch (Exception e) {
+            // 记录错误信息
+            e.printStackTrace();
+        }
+    }
+}

+ 21 - 0
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/service/KKLService.java

@@ -0,0 +1,21 @@
+package com.malk.kuaikeli.service;
+
+import org.springframework.scheduling.annotation.Async;
+
+import java.util.Map;
+
+public interface KKLService {
+
+    void matchSupplier(Map data);
+
+    void validateApprove(Map data);
+
+    @Async
+    void serviceRate(Map data);
+
+    void adjustCost(Map data);
+
+    void additionMaterial(Map data);
+
+    void syncPrice();
+}

+ 14 - 1
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/service/SupplierMaterialService.java

@@ -9,8 +9,21 @@ public interface SupplierMaterialService extends IService<SupplierMaterial> {
 
     void uploadData(MultipartFile file);
 
-    void sync(String startDateTime);
+    /***
+     * 同步
+     */
+    void sync();
 
+    /***
+     * 查询列表
+     * @param current
+     * @param size
+     * @return
+     */
     McR getList(Integer current,Integer size);
 
+    void syncPrice();
+
+    void projectSupplierChange(String projectId,String oldId,String newId,String newName);
+
 }

+ 336 - 0
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/service/impl/KKLImplService.java

@@ -0,0 +1,336 @@
+package com.malk.kuaikeli.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.malk.kuaikeli.service.KKLService;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.aliwork.YDService;
+import com.malk.utils.UtilMap;
+import com.malk.utils.UtilMc;
+import com.malk.utils.UtilNumber;
+import lombok.SneakyThrows;
+import lombok.Synchronized;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class KKLImplService implements KKLService {
+
+    @Autowired
+    private YDService ydService;
+
+    /**
+     * [动态] 发起单据, 分供应商进行流程推送
+     */
+    @Override
+    public void matchSupplier(Map data) {
+
+        // ppExt: 供应商区分发起: 当前表:供应供子表组件ID,子表内供应商编号,名称,负责人
+        String[] compIds_supplier = String.valueOf(data.get("compId_supplier")).split(", ");
+        String compId_supplier = compIds_supplier[1];
+
+        Map formData = (Map) JSON.parse(String.valueOf(data.get("formData")));
+        List<Map> details = (List<Map>) formData.get(compIds_supplier[0]);
+
+        // 供应商编号, 数据去重: 提取数据区分供应商发起
+        List<Map> suppliers = UtilMc.distinctByKey(details, compId_supplier);
+        for (Map supplier : suppliers) {
+            List<Map> dataList = details.stream().filter(item -> supplier.get(compId_supplier).equals(item.get(compId_supplier))).collect(Collectors.toList());
+            formData.put(compIds_supplier[0], dataList);
+            // ppExt: 参数传递, 目标表组件ID, 对照当前表子表内的子表内供应商编号,名称,负责人已放置主表字段, 此处公共内容提前首条数据进行赋值
+            for (int i = 1; i < compIds_supplier.length; i++) {
+                formData.put(compIds_supplier[i], YDConf.getDataByCompId(dataList.get(0), compIds_supplier[i]));
+            }
+            data.put("formData", JSON.toJSONString(formData));
+            ydService.copyFormData(data); // 发起流程
+        }
+    }
+
+    @Autowired
+    private YDClient ydClient;
+
+    /**
+     * 菜单计划, 编辑校验
+     * -
+     * 前端提交动作: 校验是否审批通过, 是否当日之前计划, 是否当日且在16点及以后时间, 均不允许提交
+     * 后端校验返回、加任何产品都要走审批,减少20%以内直接过,每一个原材料
+     */
+    @Override
+    public void validateApprove(Map data) {
+
+        boolean approve = false;
+        List<Map> dataList = UtilMap.getList(data, "list");
+        for (Map row : dataList) {
+
+            // 匹配切配工作单, 采购
+            List<Map> formList = (List<Map>) ydClient.queryData(YDParam.builder()
+                            .formUuid("FORM-RK966E71T0LDSTW39WFHE9OQ5GU23FKRRDNLL2")
+                            .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_lmsuq8am, textField_lm8zta2z, textField_ln1ez5li", data.get("name"), data.get("area"), row.get("textField_ln1ez5li"))))
+                            .build(),
+                    YDConf.FORM_QUERY.retrieve_search_form).getData();
+
+            if (formList.size() == 0) {
+                approve = true;
+                break;
+            }
+            Map formData = (Map) formList.get(0).get("formData");
+            float cur = UtilMap.getFloat(row, "numberField_lmym5628");
+            float src = UtilMap.getFloat(formData, "numberField_lnrkgimz");
+            if (cur > src || (src - cur) / src > 0.2f) {
+                approve = true;
+                break;
+            }
+        }
+        if (approve) {
+            // 发起菜单审批
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-UP96637100HD036TA1M05B74GHLV3DRS54NLLC")
+                    .processCode("TPROC--UP96637100HD036TA1M05B74GHLV3ERS54NLLD")
+                    .formDataJson(JSON.toJSONString(data.get("form"))) // 前端数据组装
+                    .userId(data.get("user").toString())
+                    .build(), YDConf.FORM_OPERATION.start);
+
+            // 更新计划状态
+            ydService.operateData(YDParam.builder()
+                    .formInstanceId(data.get("poid").toString())
+                    .updateFormDataJson(JSON.toJSONString(UtilMap.map("textField_lm8znr9n", "执行中")))
+                    .build(), YDConf.FORM_OPERATION.update);
+        }
+    }
+
+    /**
+     * 定价单: 项目点 & 供应商大类, 数据匹配
+     */
+    @Override
+    @SneakyThrows
+    @Synchronized
+    public void serviceRate(Map data) {
+
+        // todo: 宜搭更新,校验的超时等待在3s, 因此方法修改为异步. 容错定时任务?匹配不一致数据
+        String supperCode = String.valueOf(data.get("code"));
+        List<String> types = (List<String>) JSON.parse(String.valueOf(data.get("type")));
+        List<String> rates = (List<String>) JSON.parse(String.valueOf(data.get("rate")));
+        List<String> rates2 = (List<String>) JSON.parse(String.valueOf(data.get("rate2")));
+        List<String> status = (List<String>) JSON.parse(String.valueOf(data.get("status")));
+
+        for (int i = 0; i < types.size(); i++) {
+
+            List<Map> materials = supperMaterials(supperCode, types.get(i));
+            List<Map> records = projectMaterials(supperCode, types.get(i));
+            log.info("定价单同步, {}, {}", materials.size(), records.size());
+            for (Map material : materials) {
+
+                // 数据处理: 服务费率与供货价, 项目信息
+                double rate = Double.valueOf(rates.get(i));
+                double rate2 = Double.valueOf(rates2.get(i));
+                material.putAll(UtilMap.map("numberField_llkb7kcy, numberField_lpalgz04, textField_lm4lxur8", rate, rate2, status.get(i)));
+                double price1 = UtilNumber.formatPrecisionValue(UtilMap.getDouble(material, "numberField_llkknd6g") * (rate + 100) / 100f);
+                double price2 = UtilNumber.formatPrecisionValue(UtilMap.getDouble(material, "numberField_lpalgz05") * (100 + rate2) / 100f);
+                material.putAll(UtilMap.map("numberField_llkknd6h, numberField_lpalgz0a", price1, price2));
+                material.putAll(UtilMap.map("textField_llm1vtjm, textField_loy1ep8r", data.get("proCode"), data.get("proName")));
+
+                YDParam ydParam = YDParam.builder()
+                        .formUuid("FORM-E6766M811CKD2PIXEAKOM9S2DKBM2PBQU1MLL5")
+                        .formDataJson(JSON.toJSONString(material))
+                        .build();
+                YDConf.FORM_OPERATION operation = YDConf.FORM_OPERATION.create;
+                // ppExt: 提交校验逻辑, 匹配定价单数若存在则匹配服务费率, 不一致执行更新
+                if (records.size() > 0) {
+                    Optional optional = records.stream().filter(item -> item.get("textField_llkb7kd2").equals(material.get("textField_llkb7kd2"))).findAny();
+                    if (optional.isPresent()) {
+                        ydParam.setUpdateFormDataJson(JSON.toJSONString(material));
+                        ydParam.setFormInstanceId(String.valueOf(((Map) optional.get()).get("formInstanceId")));
+                        operation = YDConf.FORM_OPERATION.update;
+                    }
+                }
+                ydClient.operateData(ydParam, operation);
+            }
+        }
+    }
+
+
+
+    /// 原材料: 供应商第一分类下物料
+    List<Map> supperMaterials(String code, String type) {
+        List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
+                .formUuid("FORM-12EB6BCE3C264630824721E7BBABCC03L8U9")
+                .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_llzzbyj1, selectField_llkb7kd5", code, type)))
+                .build());
+        log.info("supperMaterials, {}", dataList.size());
+        return dataList;
+    }
+
+    /// 定价单: 供应商第一分类下物料
+    List<Map> projectMaterials(String code, String type) {
+        List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
+                .formUuid("FORM-E6766M811CKD2PIXEAKOM9S2DKBM2PBQU1MLL5")
+                .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_llzzbyj1, selectField_llkb7kd5", code, type)))
+                .build());
+        log.info("projectMaterials, {}", dataList.size());
+        return dataList;
+    }
+
+
+    /**
+     * 物料档案: 价格调整
+     */
+    @Override
+    public void adjustCost(Map data) {
+
+        double cost1 = UtilMap.getDouble(data, "costPrice");
+        double cost2 = UtilMap.getDouble(data, "nextCostPrice");
+        String cost3 = UtilMap.getString(data,"timeLimit");
+
+        // todo: 服务执行, 周日凌晨更新价格前, 是否重新匹配数据?
+        List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
+                .formUuid("FORM-E6766M811CKD2PIXEAKOM9S2DKBM2PBQU1MLL5")
+                .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_llkb7kd2", data.get("itemNumber"))))
+                .build());
+        log.info("adjustCost, {}", dataList.size());
+
+        for (Map record : dataList) {
+//            if (cost1 == UtilMap.getDouble(record, "numberField_llkknd6g") && cost2 == UtilMap.getDouble(record, "numberField_lpalgz05")) {
+//                continue;
+//            }
+            double rate = UtilMap.getDouble(record, "numberField_llkb7kcy");
+            double rate2 = UtilMap.getDouble(record, "numberField_lpalgz04");
+            double price1 = UtilNumber.formatPrecisionValue(cost1 * (rate + 100) / 100f);
+            double price2 = UtilNumber.formatPrecisionValue(cost2 * (100 + rate2) / 100f);
+
+            Map update = UtilMap.map("numberField_llkknd6h, numberField_lpalgz0a", price1, price2);
+            update.putAll(UtilMap.map("numberField_llkknd6g, numberField_lpalgz05, dateField_lm4lxur7", cost1, cost2, cost3 ));
+            ydClient.operateData(YDParam.builder()
+                    .formInstanceId(String.valueOf(record.get("formInstanceId")))
+                    .updateFormDataJson(JSON.toJSONString(update))
+                    .build(), YDConf.FORM_OPERATION.update);
+        }
+    }
+
+    /**
+     * 供应商原材料档案: 新增匹配
+     */
+    @Override
+    public void additionMaterial(Map data) {
+
+        // 通过供应商编号 查询项目
+        List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
+                .formUuid("FORM-W2A66Z91B4KDWDIAA7SI1BRBRTKM3XL87BKLL0")
+                .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_llzzbai8", data.get("gysNumber"))))
+                .build());
+        dataList.forEach(dataItem -> {
+            List<Map> mapList = (List<Map>) dataItem.get("tableField_llq74mwk");
+            // 这里对比第二分类  selectField_llq74mwl ==> selectField_lv3v3911
+            List<Map> maps =  mapList.stream().filter(items -> items.get("selectField_lv3v3911").equals(data.get("firstName"))).collect(Collectors.toList());
+            if(maps.size()>0){
+
+                List<Map> goodList = ydService.queryFormData_all(YDParam.builder()
+                        .formUuid("FORM-12EB6BCE3C264630824721E7BBABCC03L8U9")
+                        .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_llkb7kd2", data.get("goodNumber"))))
+                        .build());
+                Map goodMap = goodList.get(0);
+
+                Map hashMap = new HashMap();
+                hashMap.put("textField_llzzbyj1",data.get("gysNumber"));   //供应商编号
+                hashMap.put("textField_lmsli3bq",dataItem.get("textField_lmsli3bq")); //供应商名称
+                hashMap.put("textField_llm1vtjm",dataItem.get("textField_lllovku7"));  //项目编号
+                hashMap.put("textField_loy1ep8r",dataItem.get("textField_loy1ep8r"));//项目名称
+                hashMap.put("textField_llkb7kd2",data.get("goodNumber"));   //物品编号
+                hashMap.put("textField_llkb7kd1",goodMap.get("textField_llkb7kd1"));  //物品名称
+
+                hashMap.put("textField_llkb7kd3",goodMap.get("textField_llkb7kd3"));  //单位
+                hashMap.put("textField_llkb7kd4",goodMap.get("textField_llkb7kd4"));  //规格
+                hashMap.put("selectField_llkb7kd5",data.get("firstName"));              //第一分类
+                hashMap.put("selectField_llkk6cms",goodMap.get("selectField_llkk6cms"));              //第二分类
+
+
+                double rate = UtilMap.getDouble(maps.get(0), "numberField_llq74mwm");  //本周费率
+                double rate2 = UtilMap.getDouble(maps.get(0), "numberField_lpplr3im"); //下周费率
+
+                double pce1 = UtilMap.getDouble(goodMap, "numberField_llkknd6g");  //成本单价
+                double pce2 = UtilMap.getDouble(goodMap, "numberField_lpalgz05");   //下周成本单价
+
+                double price1 = UtilNumber.formatPrecisionValue(pce1 * (rate + 100) / 100f);  //下周成本价
+                double price2 = UtilNumber.formatPrecisionValue(pce2 * (rate2 + 100 ) / 100f); //下周供货价
+
+                hashMap.put("numberField_llkb7kcy",rate);       //服务费率
+                hashMap.put("numberField_lpalgz04",rate2);   //下周服务费率
+
+                hashMap.put("numberField_llkknd6g",pce1);   //成本单价
+                hashMap.put("numberField_lpalgz05",pce2);   //下周成本单价
+
+                hashMap.put("numberField_llkknd6h",price1);  //供货价
+                hashMap.put("numberField_lpalgz0a",price2); //下周供货价
+
+                hashMap.put("dateField_lm4lxur7",goodMap.get("dateField_lm4lxur7"));  //期限
+                hashMap.put("textField_lm4lxur8","已启用");  //状态
+                hashMap.put("numberField_lnrzzg03",goodMap.get("numberField_lnrzzg03")); //包装数量
+                hashMap.put("textField_lnrzzg04",goodMap.get("textField_lnrzzg04")); //包装单位
+
+
+                log.info("hashMap,{}", JSON.toJSONString(hashMap));
+
+                ydClient.operateData(YDParam.builder()
+                        .formUuid("FORM-E6766M811CKD2PIXEAKOM9S2DKBM2PBQU1MLL5")
+                        .formDataJson(JSON.toJSONString(hashMap))
+                        .build(), YDConf.FORM_OPERATION.create);
+            }
+        });
+
+
+
+
+    }
+
+    /**
+     * 周日同步更新价格
+     */
+    @Override
+    @SneakyThrows
+    public void syncPrice() {
+
+        // 定价单明细表
+        List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
+                .formUuid("FORM-E6766M811CKD2PIXEAKOM9S2DKBM2PBQU1MLL5")
+                .build());
+        for (Map record : dataList) {
+
+            double price1 = UtilMap.getDouble(record, "numberField_llkknd6h");
+            double price2 = UtilMap.getDouble(record, "numberField_lpalgz0a");
+            if (price1 == price2) {
+                continue;
+            }
+            // 本质上是对比供货价差异, 下周全覆盖
+            Map update = UtilMap.map("numberField_llkknd6h, numberField_llkb7kcy, numberField_llkknd6g", price2, record.get("numberField_lpalgz04"), record.get("numberField_lpalgz05"));
+            ydClient.operateData(YDParam.builder()
+                    .formInstanceId(String.valueOf(record.get("formInstanceId")))
+                    .updateFormDataJson(JSON.toJSONString(update))
+                    .build(), YDConf.FORM_OPERATION.update);
+        }
+        // 供应商原材料表
+        List<Map> dataList2 = ydService.queryFormData_all(YDParam.builder()
+                .formUuid("FORM-12EB6BCE3C264630824721E7BBABCC03L8U9")
+                .build());
+        for (Map record : dataList2) {
+
+            double cost1 = UtilMap.getDouble(record, "numberField_llkknd6g");
+            double cost2 = UtilMap.getDouble(record, "numberField_lpalgz05");
+            if (cost1 == cost2) {
+                continue;
+            }
+            Map update = UtilMap.map("numberField_llkknd6g", cost2);
+            ydClient.operateData(YDParam.builder()
+                    .formInstanceId(String.valueOf(record.get("formInstanceId")))
+                    .updateFormDataJson(JSON.toJSONString(update))
+                    .build(), YDConf.FORM_OPERATION.update);
+        }
+    }
+}

+ 214 - 31
mjava-kuaikeli/src/main/java/com/malk/kuaikeli/service/impl/SupplierMaterialServiceImpl.java

@@ -1,5 +1,9 @@
 package com.malk.kuaikeli.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.pinyin.PinyinUtil;
 import com.alibaba.excel.EasyExcel;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
@@ -7,41 +11,51 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.malk.kuaikeli.entity.MaterialDetail;
+import com.malk.kuaikeli.entity.Pricing;
 import com.malk.kuaikeli.entity.SupplierMaterial;
 import com.malk.kuaikeli.listener.SupplierMaterialDataListener;
+import com.malk.kuaikeli.mapper.MaterialDetailMapper;
 import com.malk.kuaikeli.mapper.SupplierMaterialMapper;
 import com.malk.kuaikeli.service.SupplierMaterialService;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.server.common.McR;
 import com.malk.service.aliwork.YDClient;
+import com.malk.utils.PublicUtil;
 import com.malk.utils.UtilEnv;
 import com.malk.utils.UtilMap;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.xmlbeans.impl.xb.xsdschema.Public;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 @Service
 @Slf4j
 public class SupplierMaterialServiceImpl extends ServiceImpl<SupplierMaterialMapper,SupplierMaterial> implements SupplierMaterialService {
 
-    @Autowired
-    private SupplierMaterialMapper supplierMaterialMapper;
     @Autowired
     private YDClient ydClient;
+    @Autowired
+    private MaterialDetailMapper materialDetailMapper;
 
     String _matchFormUuid(String code) {
         Map<String, String> formUuid = UtilMap.empty();
         if (UtilEnv.getActiveProfile().equals(UtilEnv.ENV_PROD)) {
             formUuid.put("SUPPLIERMATERIAL", "FORM-12EB6BCE3C264630824721E7BBABCC03L8U9"); // 供应商原材料档案
+            formUuid.put("PRICING", "FORM-W2A66Z91B4KDWDIAA7SI1BRBRTKM3XL87BKLL0"); // 定价单
+            formUuid.put("MATERIALDETAIL", "FORM-E6766M811CKD2PIXEAKOM9S2DKBM2PBQU1MLL5"); // 定价单明细中间表
+            formUuid.put("FOOD", "FORM-GP666M71DIGDE0ZADDLZ85VEFBD128OUH1MLLF"); // 菜品管理
             formUuid.put("DOMAIN", "https://dcuvl8.aliwork.com/"); // 宜搭域名
         } else {
-            formUuid.put("SUPPLIERMATERIAL", "FORM-0CE39021E25E4F64AD56434209A95F55ZTJD"); // 供应商原材料档案_复制
+            formUuid.put("SUPPLIERMATERIAL", "FORM-2ADD5797EFB94A5CA18C5E553B420AA7BO75"); // 供应商原材料档案_复制
+            formUuid.put("PRICING", "FORM-W2A66Z91B4KDWDIAA7SI1BRBRTKM3XL87BKLL0"); // 定价单
+            formUuid.put("MATERIALDETAIL", "FORM-96ED86E480CB4E19851729D055474965FYAL"); // 定价单明细中间表
+            formUuid.put("FOOD", "FORM-GP666M71DIGDE0ZADDLZ85VEFBD128OUH1MLLF"); // 菜品管理
             formUuid.put("DOMAIN", "https://dcuvl8.aliwork.com/");
         }
         return formUuid.get(code);
@@ -49,39 +63,117 @@ public class SupplierMaterialServiceImpl extends ServiceImpl<SupplierMaterialMap
 
     @Override
     public void uploadData(MultipartFile file) {
-//        try {
-//            EasyExcel.read(file.getInputStream(), SupplierMaterial.class, new SupplierMaterialDataListener(baseMapper)).sheet().doRead();
-//        } catch (IOException e) {
-//            e.printStackTrace();
-//        }
+        try {
+            EasyExcel.read(file.getInputStream(), SupplierMaterial.class, new SupplierMaterialDataListener(baseMapper)).sheet().doRead();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
     }
 
+    /***
+     * 同步服务  只查新数据(isNeedSyncYd==是)
+     * 1.保存原材料到宜搭表单
+     * 2.查询定价单组装数据保存到定价明细中间表
+     */
     @Override
-    public void sync(String startDateTime) {
+    public void sync() {
         QueryWrapper<SupplierMaterial> queryWrapper = new QueryWrapper<>();
-        queryWrapper.lambda()
-                .ge(SupplierMaterial::getCreateDateTime,startDateTime)
-                .or().ge(SupplierMaterial::getUpdateDateTime,startDateTime);
-        // 时间判断增量同步
+        queryWrapper.lambda().eq(SupplierMaterial::getIsNeedSyncYd,"是");
         List<SupplierMaterial> list=baseMapper.selectList(queryWrapper);
         for (SupplierMaterial supplierMaterial:list){
-            // 同步到宜搭
-            List<Map> yidaList= (List<Map>) ydClient.queryData(YDParam.builder().formUuid(_matchFormUuid("SUPPLIERMATERIAL")).searchCondition(
-                    JSONObject.toJSONString(UtilMap.map("textField_llkb7kd2",supplierMaterial.getMaterialId())))
-                    .build(),YDConf.FORM_QUERY.retrieve_list).getData();
-            YDParam ydParam = YDParam.builder()
-                    .formUuid(_matchFormUuid("SUPPLIERMATERIAL"))
-                    .useLatestVersion(true)
-                    .build();
-            Map formData=supplierMaterial.toYidaFormDataMap();
-            if(yidaList!=null&&yidaList.size()>0){
-                ydParam.setUpdateFormDataJson(JSON.toJSONString(formData));
-                ydParam.setFormInstanceId(String.valueOf(yidaList.get(0).get("instanceId")));
-                ydClient.operateData(ydParam,YDConf.FORM_OPERATION.update);
+            try {
+                syncSupplierMaterial(supplierMaterial);
+            }catch (Exception e){
+                log.error("同步出现异常:{}",e.getMessage());
+                e.printStackTrace();
+                supplierMaterial.setIsNeedSyncYd("异常");// 更新是否需要同步到宜搭
+                supplierMaterial.setErrorMsg(e.getMessage());
+                baseMapper.updateById(supplierMaterial);
+            }
+        }
+    }
+
+    public void syncSupplierMaterial(SupplierMaterial supplierMaterial){
+        // 同步到宜搭
+        YDParam ydParam = YDParam.builder().formUuid(_matchFormUuid("SUPPLIERMATERIAL"))
+                .useLatestVersion(true).build();
+        Map formData=supplierMaterial.toYidaFormDataMap();
+        // 查询定价单数据
+        List<Pricing> pricings=getPricings(supplierMaterial.getSupplierId());
+        if(!PublicUtil.isNull(supplierMaterial.getFormInstId())){
+            // 更新
+            ydParam.setUpdateFormDataJson(JSON.toJSONString(formData));
+            ydParam.setFormInstanceId(String.valueOf(supplierMaterial.getFormInstId()));
+            ydClient.operateData(ydParam,YDConf.FORM_OPERATION.update);
+            for (Pricing pricing:pricings){
+                upsertMaterialDetail(pricing,supplierMaterial,formData);
+            }
+        }else{
+            // 新增
+            ydParam.setFormDataJson(JSON.toJSONString(formData));
+            String formInstId=(String) ydClient.operateData(ydParam,YDConf.FORM_OPERATION.create);
+            int st=0;
+            for (Pricing pricing:pricings){
+                upsertMaterialDetail(pricing,supplierMaterial,formData);
+                st++;
+            }
+            supplierMaterial.setMaterialDetailNumber(String.valueOf(st));
+            supplierMaterial.setIsNeedSyncYd("否");// 更新是否需要同步到宜搭
+            supplierMaterial.setFormInstId(formInstId);// 更新实例编号
+            baseMapper.updateById(supplierMaterial);
+        }
+    }
+
+    private void upsertMaterialDetail(Pricing pricing,SupplierMaterial supplierMaterial,Map formData){
+        YDParam ydParam2 = YDParam.builder().formUuid(_matchFormUuid("MATERIALDETAIL"))
+                .useLatestVersion(true).build();
+        QueryWrapper<MaterialDetail> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(MaterialDetail::getSupplierId,supplierMaterial.getSupplierId())
+                .eq(MaterialDetail::getProjectId,pricing.getProjectId())
+                .eq(MaterialDetail::getMaterialId,supplierMaterial.getMaterialId());
+        List<MaterialDetail> materialDetails =materialDetailMapper.selectList(queryWrapper);
+        if(materialDetails!=null&&materialDetails.size()>0){
+            MaterialDetail materialDetail=materialDetails.get(0);
+            String rate;// 服务费率
+            if(pricing.getRateMap().containsKey(materialDetail.getClassifyTwo())){// 第二分类优先匹配
+                rate=pricing.getRateMap().get(materialDetail.getClassifyTwo());
+            }else if(pricing.getRateMap().containsKey(materialDetail.getClassifyOne())){// 第一分类匹配
+                rate=pricing.getRateMap().get(materialDetail.getClassifyOne());
+            }else{
+                return;
+            }
+            String[] rates=rate.split("_");
+            materialDetail.setRate(rates[0]);
+            materialDetail.setRateNext(rates[1]);
+            materialDetail.setSupplyPrice(cal(materialDetail.getUnitPrice(),rates[0]));
+            materialDetail.setSupplyPriceNext(cal(materialDetail.getUnitPriceNext(),rates[0]));
+            // 更新明细中间表数据库
+            materialDetailMapper.updateById(materialDetail);
+            // 更新明细中间表宜搭数据
+            ydParam2.setUpdateFormDataJson(JSONObject.toJSONString(materialDetail.toYidaFormDataMap()));
+            ydParam2.setFormInstanceId(String.valueOf(materialDetail.getFormInstId()));
+            ydClient.operateData(ydParam2,YDConf.FORM_OPERATION.update);
+        }else{
+            MaterialDetail materialDetail=MaterialDetail.toBean(formData);
+            String rate;// 服务费率
+            if(pricing.getRateMap().containsKey(materialDetail.getClassifyTwo())){// 第二分类优先匹配
+                rate=pricing.getRateMap().get(materialDetail.getClassifyTwo());
+            }else if(pricing.getRateMap().containsKey(materialDetail.getClassifyOne())){// 第一分类匹配
+                rate=pricing.getRateMap().get(materialDetail.getClassifyOne());
             }else{
-                ydParam.setFormDataJson(JSON.toJSONString(formData));
-                ydClient.operateData(ydParam,YDConf.FORM_OPERATION.create);
+                return;
             }
+            String[] rates=rate.split("_");
+            materialDetail.setRate(rates[0]);
+            materialDetail.setRateNext(rates[1]);
+            materialDetail.setSupplyPrice(cal(materialDetail.getUnitPrice(),rates[0]));
+            materialDetail.setSupplyPriceNext(cal(materialDetail.getUnitPriceNext(),rates[0]));
+            materialDetail.setProjectId(pricing.getProjectId());
+            materialDetail.setProjectName(pricing.getProjectName());
+            ydParam2.setFormDataJson(JSONObject.toJSONString(materialDetail.toYidaFormDataMap()));
+            String priFormInstId=(String) ydClient.operateData(ydParam2,YDConf.FORM_OPERATION.create);
+            materialDetail.setFormInstId(priFormInstId);
+            materialDetailMapper.insert(materialDetail.create());
         }
     }
 
@@ -89,7 +181,6 @@ public class SupplierMaterialServiceImpl extends ServiceImpl<SupplierMaterialMap
         // 构造查询条件(可选)
         QueryWrapper<SupplierMaterial> queryWrapper = new QueryWrapper<>();
         // ... 根据params设置查询条件 ...
-
         // 执行分页查询
         return baseMapper.selectPage(page, queryWrapper);
     }
@@ -100,4 +191,96 @@ public class SupplierMaterialServiceImpl extends ServiceImpl<SupplierMaterialMap
         IPage iPage = getProducts(page,null);
         return McR.success(iPage);
     }
+
+    @Override
+    public void syncPrice() {
+        // 每周同步  ==> 直接修改数据库供应商原材料表 成本单价为下周成本单价、同步标识为“是”。通过供应商原材料更新业务逻辑实现同步
+        baseMapper.updateUnitPrice();
+    }
+
+    @Override
+    public void projectSupplierChange(String projectId, String oldId, String newId,String newName) {
+        Map<String,String> ID_MAP=new HashMap<>();
+        // 1.复制原材料数据到数据库?
+        List<SupplierMaterial> supplierMaterials=baseMapper.selectListForCopy(projectId,oldId);
+        int no = 1;
+        String name= PinyinUtil.getFirstLetter(newName.replace("供应商",""),"").toUpperCase();
+        for (SupplierMaterial supplierMaterial:supplierMaterials){
+            supplierMaterial.create();
+            supplierMaterial.setSupplierId(newId);
+            supplierMaterial.setSupplierName(newName);
+            String id=name+String.format("%05d",no);
+            ID_MAP.put(supplierMaterial.getMaterialId(),id);
+            supplierMaterial.setMaterialId(id);// 原材料编号怎么处理
+            baseMapper.insert(supplierMaterial);
+            no++;
+        }
+        // 等待同步
+        sync();
+        // 2.宜搭菜品管理表单  替换供应商原材料编号、供应商名称
+        List<Map> yidaList= (List<Map>) ydClient.queryData(YDParam.builder().formUuid(_matchFormUuid("FOOD")).searchCondition(
+                JSONObject.toJSONString(UtilMap.map("textField_lln3lmn1",projectId)))
+                .build(),YDConf.FORM_QUERY.retrieve_list_all).getData();
+        for (Map map:yidaList){
+            Map formData=UtilMap.getMap(map,"formData");
+            String formInstId=UtilMap.getString(map,"formInstId");
+            List<Map> list=UtilMap.getList(formData,"tableField_llm1i9yy");// 材料清单
+            for (int i = 0; i < list.size(); i++) {
+                // 查询数据库
+                String nId=ID_MAP.get(list.get(i).get("textField_lmk94yf5"));
+                QueryWrapper<MaterialDetail> queryWrapper = new QueryWrapper<>();
+                queryWrapper.lambda().eq(MaterialDetail::getSupplierId,newId)
+                        .eq(MaterialDetail::getProjectId,projectId)
+                        .eq(MaterialDetail::getMaterialId,nId);
+                List<MaterialDetail> materialDetails =materialDetailMapper.selectList(queryWrapper);
+                if(materialDetails!=null&&materialDetails.size()>0){
+                    list.get(i).put("associationFormField_lln3lmmv", Arrays.asList(UtilMap.map("title, instanceId, appType, formUuid, formType",
+                            materialDetails.get(0).getMaterialName(),materialDetails.get(0).getFormInstId(),
+                            "APP_OHSG8KMIP9SGXV32XUQJ",_matchFormUuid("MATERIALDETAIL"),"receipt")));// 关联中间表
+                }
+                list.get(i).put("textField_lmk94yf5",nId);// 原材料编号
+            }
+            YDParam ydParam = YDParam.builder().formUuid(_matchFormUuid("MATERIALDETAIL"))
+                    .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("tableField_llm1i9yy",list)))
+                    .formInstanceId(formInstId)
+                    .useLatestVersion(true).build();
+            ydClient.operateData(ydParam,YDConf.FORM_OPERATION.update);
+        }
+    }
+
+    // 缓存
+    private static Map<String,List<Pricing>> SUPPLIER_PRICING_MAP=new HashMap<>();
+    // 获取定价单
+    private List<Pricing> getPricings(String supplierId){
+        if(SUPPLIER_PRICING_MAP.containsKey(supplierId)){
+            return SUPPLIER_PRICING_MAP.get(supplierId);
+        }
+        List<Pricing> list=new ArrayList<>();
+        List<Map> yidaList= (List<Map>) ydClient.queryData(YDParam.builder().formUuid(_matchFormUuid("PRICING")).searchCondition(
+                JSONObject.toJSONString(UtilMap.map("textField_llzzbai8",supplierId)))
+                .build(),YDConf.FORM_QUERY.retrieve_list_all).getData();
+        for(Map map:yidaList){
+            Map formData=UtilMap.getMap(map,"formData");
+            Pricing pricing= BeanUtil.mapToBean(formData,Pricing.class,false);
+            List<Map> detailList= (List<Map>) formData.get("tableField_llq74mwk");
+            Map<String,String> data=new HashMap();
+            for(Map detailMap:detailList){
+                if("已启用".equals(String.valueOf(detailMap.get("selectField_lpw1n0af")))){
+                    data.put(String.valueOf(detailMap.get(!PublicUtil.isNull(detailMap.get("selectField_lv3v3911"))?"selectField_lv3v3911":"selectField_llq74mwl")),
+                            String.valueOf(detailMap.get("numberField_llq74mwm")).concat("_").concat(String.valueOf(detailMap.get("numberField_lpplr3im"))));
+                }
+            }
+            pricing.setRateMap(data);
+            log.info("pricing:{}",JSONObject.toJSONString(pricing));
+            list.add(pricing);
+        }
+        SUPPLIER_PRICING_MAP.put(supplierId,list);
+        return list;
+    }
+
+    private String cal(String unitPrice,String rate){
+        return NumberUtil.roundStr(NumberUtil.div(NumberUtil.mul(unitPrice,NumberUtil.add(rate,"100").toString()).toString(),"100").toString(),2);
+    }
+
+
 }

+ 2 - 2
mjava-kuaikeli/src/main/resources/application-dev.yml

@@ -1,7 +1,7 @@
 server:
-  port: 9020
+  port: 9021
   servlet:
-    context-path: /kkl
+    context-path: /api/kuaikeli
 spring:
   datasource:
     url: jdbc:mysql://localhost:3306/floe?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC

+ 30 - 0
mjava-kuaikeli/src/main/resources/application-prod.yml

@@ -0,0 +1,30 @@
+server:
+  port: 9020
+  servlet:
+    context-path: /api/kuaikeli
+spring:
+  datasource:
+    url: jdbc:mysql://127.0.0.1:3306/dingtalk?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
+    username: root
+    password: cp-root@2024++
+    driver-class-name: com.mysql.cj.jdbc.Driver
+enable:
+  scheduling: true
+logging:
+  config: classpath:logback-spring.xml
+  path: /home/server/kuaikeli/log/
+  level:
+    com.malk.*: info
+
+# dingtalk
+dingtalk:
+  agentId: 2691784047
+  appKey: dinghbynhnd2dbgypmsa
+  appSecret: Kl5Xw8x0TlEIlvcJuUkYZD18UTTShJmfdKrAIpY8oX-Q_tazyUKA28nQh7dG5-mq
+  corpId: dingcc1b1ffad0d5ca1d
+  aesKey:
+  token:
+# aliwork
+aliwork:
+  appType: APP_OHSG8KMIP9SGXV32XUQJ
+  systemToken: 9F766B81QHGDDLQ89X17X5GXVPYM20V729KLLPH

+ 1 - 1
mjava-kuaikeli/src/main/resources/application.yml

@@ -1,6 +1,6 @@
 spring:
   profiles:
-    active: dev
+    active: prod
   servlet:
     multipart:
       max-file-size: 100MB

+ 51 - 0
mjava-kuaikeli/src/main/resources/mapper/SupplierMaterialMapper.xml

@@ -0,0 +1,51 @@
+<?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.malk.kuaikeli.mapper.SupplierMaterialMapper">
+    <update id="updateUnitPrice">
+        UPDATE t_supplier_material
+        SET unit_price = unit_price_next,
+        is_need_sync_yd = '是'
+        WHERE
+        unit_price &lt;&gt; unit_price_next
+    </update>
+
+    <select id="selectListForCopy" resultType="com.malk.kuaikeli.entity.SupplierMaterial" parameterType="java.lang.String">
+          SELECT
+            supplier,
+            supplier_id,
+            supplier_name,
+            material_name,
+            material_id,
+            unit,
+            specs,
+            classify_one,
+            classify_two,
+            unit_price,
+            unit_price_next,
+            other_info,
+            img,
+            brand,
+            state,
+            term,
+            packing_number,
+            packing_unit,
+            need_qualification,
+            provide_qualification,
+            qualification,
+            qualification_expire_date
+        FROM
+            t_supplier_material
+        WHERE
+            material_id IN (
+                SELECT
+                    material_id
+                FROM
+                    t_material_detail
+                WHERE
+                    project_id = #{project_id}
+                AND supplier_id = #{supplier_id}
+            )
+    </select>
+</mapper>

+ 3 - 2
mjava-kuaikeli/src/test/java/com/malk/kuaikeli/DdTest.java

@@ -26,8 +26,8 @@ public class DdTest {
 
     @Test
     public void create(){
-        String time="20240410114941";
-        supplierMaterialService.sync(time);
+//        supplierMaterialService.sync();
+        supplierMaterialService.syncPrice();
     }
 
     @Test
@@ -39,4 +39,5 @@ public class DdTest {
                 .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
         System.out.println(JSONObject.toJSONString(form));
     }
+
 }