瀏覽代碼

聚水潭,短信需求

wangxy 1 周之前
父節點
當前提交
13742266fa
共有 45 個文件被更改,包括 1664 次插入95 次删除
  1. 170 5
      fs-admin/src/main/java/com/fs/his/task/Task.java
  2. 72 60
      fs-admin/src/main/java/com/fs/web/controller/tool/TestController.java
  3. 16 0
      fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java
  4. 25 0
      fs-service/src/main/java/com/fs/common/VerifyCodeUtil.java
  5. 2 0
      fs-service/src/main/java/com/fs/common/service/ISmsService.java
  6. 82 0
      fs-service/src/main/java/com/fs/common/service/impl/SmsServiceImpl.java
  7. 10 1
      fs-service/src/main/java/com/fs/company/mapper/CompanyFsUserMapper.java
  8. 8 0
      fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java
  9. 19 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  10. 5 0
      fs-service/src/main/java/com/fs/erp/domain/ErpOrder.java
  11. 2 0
      fs-service/src/main/java/com/fs/erp/domain/ErpOrderQuery.java
  12. 4 0
      fs-service/src/main/java/com/fs/erp/dto/ErpOrderQueryRequert.java
  13. 7 0
      fs-service/src/main/java/com/fs/erp/dto/ErpOrderQueryResponse.java
  14. 4 0
      fs-service/src/main/java/com/fs/erp/http/JstErpHttpService.java
  15. 24 9
      fs-service/src/main/java/com/fs/erp/http/JstErpHttpServiceImpl.java
  16. 4 0
      fs-service/src/main/java/com/fs/erp/service/IErpOrderService.java
  17. 10 0
      fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java
  18. 12 0
      fs-service/src/main/java/com/fs/erp/service/impl/ErpOrderServiceImpl.java
  19. 10 0
      fs-service/src/main/java/com/fs/erp/service/impl/HzOMSErpOrderServiceImpl.java
  20. 269 7
      fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java
  21. 12 8
      fs-service/src/main/java/com/fs/erp/service/impl/JstTokenService.java
  22. 10 0
      fs-service/src/main/java/com/fs/erp/service/impl/K9OrderScrmServiceImpl.java
  23. 10 0
      fs-service/src/main/java/com/fs/erp/service/impl/WdtErpOrderServiceImpl.java
  24. 2 0
      fs-service/src/main/java/com/fs/his/config/FsSmsConfig.java
  25. 2 0
      fs-service/src/main/java/com/fs/his/domain/FsIntegralOrder.java
  26. 5 0
      fs-service/src/main/java/com/fs/his/domain/FsStore.java
  27. 30 0
      fs-service/src/main/java/com/fs/his/domain/FsStoreOrderItem.java
  28. 3 0
      fs-service/src/main/java/com/fs/his/domain/FsUser.java
  29. 12 0
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderMapper.java
  30. 7 0
      fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderItemMapper.java
  31. 16 0
      fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java
  32. 2 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java
  33. 2 0
      fs-service/src/main/java/com/fs/his/param/FsIntegralOrderDoPayParam.java
  34. 5 0
      fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderService.java
  35. 10 0
      fs-service/src/main/java/com/fs/his/service/IFsStoreOrderService.java
  36. 2 0
      fs-service/src/main/java/com/fs/his/service/IFsUserService.java
  37. 250 0
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java
  38. 1 0
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java
  39. 259 0
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java
  40. 6 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java
  41. 5 1
      fs-service/src/main/resources/mapper/his/FsStoreMapper.xml
  42. 41 0
      fs-service/src/main/resources/mapper/his/FsStoreOrderItemMapper.xml
  43. 3 0
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  44. 198 4
      fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java
  45. 16 0
      fs-user-app/src/main/java/com/fs/app/controller/CommonController.java

+ 170 - 5
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -68,19 +68,25 @@ import com.fs.sop.service.IQwSopTempVoiceService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.fs.system.service.ISysConfigService;
+import com.google.common.collect.Lists;
 import com.google.gson.Gson;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
 
+import java.text.ParseException;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Consumer;
@@ -107,8 +113,8 @@ public class Task {
     private IFsFollowService fsFollowService;
     @Autowired
     private IFsStoreAfterSalesService fsStoreAfterSalesService;
-    //    @Autowired
-//    IErpOrderService erpOrderService;
+    @Autowired
+    IErpOrderService erpOrderService;
     @Autowired
     FsIntegralOrderMapper integralOrderMapper;
     @Autowired
@@ -148,7 +154,7 @@ public class Task {
     IFsPackageOrderService packageOrderService;
     @Autowired
     private IFsStoreOrderLogsService fsStoreOrderLogsService;
-    org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());
+    Logger logger = LoggerFactory.getLogger(getClass());
     @Autowired
     IFsDoctorService doctorService;
     @Autowired
@@ -213,6 +219,18 @@ public class Task {
     @Autowired
     private ThreadPoolTaskExecutor threadPoolTaskExecutor;
 
+    @Autowired
+    private FsStoreMapper fsStoreMapper;
+
+    @Autowired
+    private FsIntegralOrderMapper fsIntegralOrderMapper;
+
+    @Autowired
+    private IFsIntegralOrderService fsIntegralOrderService;
+
+    @Value("${jst.shop_code:''}")
+    private String shopCode;
+
     /**
      * sop任务token消耗统计
      */
@@ -504,8 +522,8 @@ public class Task {
 
     private boolean isEarlyMorning() {
         Date now = new Date();
-        java.time.LocalDateTime localDateTime = now.toInstant()
-                .atZone(java.time.ZoneId.systemDefault())
+        LocalDateTime localDateTime = now.toInstant()
+                .atZone(ZoneId.systemDefault())
                 .toLocalDateTime();
         return localDateTime.getHour() == 0;
     }
@@ -671,6 +689,141 @@ public class Task {
         }
     }
 
+    public void deliveryOpJst() throws InterruptedException {
+        List<FsStoreOrder> orders = fsStoreOrderMapper.selectJstOmsOrderdeliveryOp();
+//        List<FsStoreOrder> jstList = new ArrayList<>();
+//        for (FsStoreOrder order : orders) {
+//            FsStore fsStore = fsStoreMapper.selectFsStoreByStoreId(order.getStoreId());
+//            Integer deliveryType = fsStore.getDeliveryType();
+//            if (deliveryType != null && deliveryType == 4) {
+//                jstList.add(order);
+//            }
+//        }
+        //聚水潭
+        ArrayList<Long> o_ids = new ArrayList<>();
+        for (FsStoreOrder fsStoreOrder : orders) {
+            o_ids.add(Long.parseLong(fsStoreOrder.getExtendOrderId()));
+        }
+        if (!CollectionUtils.isEmpty(o_ids)){
+            jstErpOrderDelivery(o_ids);
+        }
+
+    }
+
+    private void jstErpOrderDelivery(List<Long> o_ids) throws InterruptedException {
+        if (CollectionUtils.isEmpty(o_ids)) return;
+        List<List<Long>> batches = Lists.partition(o_ids, 100);
+        for (List<Long> batch : batches) {
+            int pageIndex = 1;
+            boolean has_next = false;
+            ErpOrderQueryResponse response = null;
+            do {
+                Thread.sleep(300);
+                List<FsStoreOrder> storeOrders = fsStoreOrderMapper.selectFsStoreOrderByExtendOrderId(batch);
+                if (storeOrders != null && !storeOrders.isEmpty()) {
+                    for (FsStoreOrder order : storeOrders) {
+                        FsStore fsStore = fsStoreMapper.selectFsStoreByStoreId(order.getStoreId());
+                        if (fsStore != null) {
+                            String shopId = fsStore.getShopCode(); // 获取shopId
+
+                            // 为每个订单构建独立的请求
+                            ErpOrderQueryRequert request = new ErpOrderQueryRequert();
+                            request.setPage_size(100);
+                            request.setPage_index(pageIndex);
+                            request.setShop_id(shopId);
+                            request.setO_ids(Collections.singletonList(Long.valueOf(order.getExtendOrderId())));
+
+                            // 发送请求
+                            IErpOrderService erpService = getErpService();
+                            assert erpService != null;
+                            response = erpService.getOrder(request);
+
+                            // 处理响应结果
+                            if (response.getOrders() != null) {
+                                for (ErpOrderQuery orderQuery : response.getOrders()) {
+                                    if (orderQuery.getDeliverys() != null && !orderQuery.getDeliverys().isEmpty()) {
+                                        for (ErpDeliverys delivery : orderQuery.getDeliverys()) {
+                                            if (delivery.getDelivery() && StringUtils.isNotEmpty(delivery.getMail_no())) {
+                                                // 更新订单状态,删除REDIS缓存
+                                                fsStoreOrderService.deliveryOrder(
+                                                        orderQuery.getCode(),
+                                                        delivery.getMail_no(),
+                                                        delivery.getExpress_code(),
+                                                        delivery.getExpress_name()
+                                                );
+                                                redisCache.deleteObject("delivery" + ":" + orderQuery.getO_id());
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                pageIndex++;
+                if (response != null) {
+                    has_next = response.hasNextSafe();
+                } else {
+                    has_next = false;
+                }
+            } while (has_next);
+        }
+    }
+
+    //积分订单发货状态同步
+    public void deliveryIntegralOrder() throws InterruptedException {
+        List<FsIntegralOrder> fsIntegralOrders = fsIntegralOrderMapper.selectJstOmsIntegralOrderdeliveryOp();
+
+        //聚水潭
+        ArrayList<Long> o_ids = new ArrayList<>();
+        for (FsIntegralOrder fsIntegralOrder : fsIntegralOrders) {
+            o_ids.add(Long.parseLong(fsIntegralOrder.getExtendOrderId()));
+        }
+        if (!CollectionUtils.isEmpty(o_ids)){
+//            jstErpIntegralOrderDelivery(o_ids);
+        }
+    }
+
+    private void jstErpIntegralOrderDelivery(List<Long> o_ids) throws InterruptedException {
+        if (CollectionUtils.isEmpty(o_ids)) return;
+
+        List<List<Long>> batches = Lists.partition(o_ids, 100);
+        for (List<Long> batch : batches) {
+            int pageIndex = 1;
+            boolean has_next = false;
+            do {
+                Thread.sleep(300);
+                ErpOrderQueryRequert request = new ErpOrderQueryRequert();
+                request.setPage_size(100);
+                request.setPage_index(pageIndex);
+                request.setShop_id(shopCode);
+                request.setO_ids(batch); // 设置当前批次
+                // 发送请求
+                IErpOrderService erpService = getErpService();
+                assert erpService != null;
+                ErpOrderQueryResponse response = erpService.getIntegralOrder(request,"integral");
+                has_next = response.hasNextSafe();
+
+                if (response.getOrders() != null) {
+                    for(ErpOrderQuery orderQuery : response.getOrders()){
+                        if(orderQuery.getDeliverys()!=null&& !orderQuery.getDeliverys().isEmpty()){
+                            for(ErpDeliverys delivery:orderQuery.getDeliverys()){
+                                if(delivery.getDelivery()&& StringUtils.isNotEmpty(delivery.getMail_no())){
+                                    //更新商订单状态 删除REDIS
+                                    fsIntegralOrderService.deliveryIntegralOrderOrder(orderQuery.getCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
+                                    redisCache.deleteObject("delivery"+":"+orderQuery.getO_id());
+                                }
+                            }
+
+                        }
+                    }
+                }
+                pageIndex++;
+            } while (has_next);
+        }
+    }
+
+
     public void deliveryOpScrm()
     {
         IErpOrderService erpOrderService = getErpService();
@@ -1627,5 +1780,17 @@ public class Task {
         allFutures.join(); // 等待所有任务完成
     }
 
+    //普通订单批量推送聚水潭
+    public void CreateJSTAndHis() throws Exception {
+        List<Long> omsList = fsStoreOrderMapper.selectFsJSTStoreOrderNoCreateOms();
+        fsStoreOrderService.createJSTOmsOrder(omsList);
+    }
+
+
+    //积分订单推送聚水潭
+    public void createOmsIntegralOrder() throws ParseException, InterruptedException {
+        List<Long> omsList = fsIntegralOrderMapper.selectFsIntegralOrderToJst();
+        fsIntegralOrderService.createOmsIntegralOrder(omsList);
+    }
 
 }

+ 72 - 60
fs-admin/src/main/java/com/fs/web/controller/tool/TestController.java

@@ -1,9 +1,14 @@
 package com.fs.web.controller.tool;
 
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.text.ParseException;
+import java.util.*;
+
+import com.fs.common.core.domain.R;
+import com.fs.his.mapper.FsStoreOrderMapper;
+import com.fs.his.service.IFsStoreOrderService;
+import com.fs.his.task.Task;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -24,55 +29,78 @@ import io.swagger.annotations.ApiOperation;
 
 /**
  * swagger 用户测试方法
- * 
-
+ *
  */
 @Api("用户信息管理")
 @RestController
 @RequestMapping("/test/user")
-public class TestController extends BaseController
-{
+public class TestController extends BaseController {
     private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
+
     {
         users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
         users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
     }
 
+    @Autowired
+    IFsStoreOrderService fsStoreOrderService;
+
+    @Autowired
+    FsStoreOrderMapper fsStoreOrderMapper;
+
+    @Autowired
+    private Task task;
+
     @ApiOperation("获取用户列表")
     @GetMapping("/list")
-    public AjaxResult userList()
-    {
+    public AjaxResult userList() {
         List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
         return AjaxResult.success(userList);
     }
 
+    @GetMapping("/CreateOmsAndHis")
+    public R CreateOmsAndHis() throws Exception {
+        List<Long> omsList = fsStoreOrderMapper.selectFsJSTStoreOrderNoCreateOms();
+        fsStoreOrderService.createJSTOmsOrder(omsList);
+        return R.ok();
+    }
+
+    @PostMapping("/deliveryOpJst")
+    public R executeDeliveryOpJst() throws InterruptedException {
+        task.deliveryOpJst();
+        return R.ok();
+    }
+
+    /**
+     * 测试推积分订单到聚水潭
+     */
+    @GetMapping("/pushIntegralOrderToJst")
+    public R pushIntegralOrderToJst() throws ParseException, InterruptedException {
+        task.createOmsIntegralOrder();
+        return R.ok();
+    }
+
     @ApiOperation("获取用户详细")
     @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path")
     @GetMapping("/{userId}")
-    public AjaxResult getUser(@PathVariable Integer userId)
-    {
-        if (!users.isEmpty() && users.containsKey(userId))
-        {
+    public AjaxResult getUser(@PathVariable Integer userId) {
+        if (!users.isEmpty() && users.containsKey(userId)) {
             return AjaxResult.success(users.get(userId));
-        }
-        else
-        {
+        } else {
             return error("用户不存在");
         }
     }
 
     @ApiOperation("新增用户")
     @ApiImplicitParams({
-        @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer"),
-        @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String"),
-        @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String"),
-        @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String")
+            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer"),
+            @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String"),
+            @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String"),
+            @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String")
     })
     @PostMapping("/save")
-    public AjaxResult save(UserEntity user)
-    {
-        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
-        {
+    public AjaxResult save(UserEntity user) {
+        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) {
             return error("用户ID不能为空");
         }
         return AjaxResult.success(users.put(user.getUserId(), user));
@@ -80,14 +108,11 @@ public class TestController extends BaseController
 
     @ApiOperation("更新用户")
     @PutMapping("/update")
-    public AjaxResult update(@RequestBody UserEntity user)
-    {
-        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
-        {
+    public AjaxResult update(@RequestBody UserEntity user) {
+        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) {
             return error("用户ID不能为空");
         }
-        if (users.isEmpty() || !users.containsKey(user.getUserId()))
-        {
+        if (users.isEmpty() || !users.containsKey(user.getUserId())) {
             return error("用户不存在");
         }
         users.remove(user.getUserId());
@@ -97,23 +122,18 @@ public class TestController extends BaseController
     @ApiOperation("删除用户信息")
     @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path")
     @DeleteMapping("/{userId}")
-    public AjaxResult delete(@PathVariable Integer userId)
-    {
-        if (!users.isEmpty() && users.containsKey(userId))
-        {
+    public AjaxResult delete(@PathVariable Integer userId) {
+        if (!users.isEmpty() && users.containsKey(userId)) {
             users.remove(userId);
             return success();
-        }
-        else
-        {
+        } else {
             return error("用户不存在");
         }
     }
 }
 
 @ApiModel(value = "UserEntity", description = "用户实体")
-class UserEntity
-{
+class UserEntity {
     @ApiModelProperty("用户ID")
     private Integer userId;
 
@@ -126,56 +146,48 @@ class UserEntity
     @ApiModelProperty("用户手机")
     private String mobile;
 
-    public UserEntity()
-    {
+    public UserEntity() {
 
     }
 
-    public UserEntity(Integer userId, String username, String password, String mobile)
-    {
+    public UserEntity(Integer userId, String username, String password, String mobile) {
         this.userId = userId;
         this.username = username;
         this.password = password;
         this.mobile = mobile;
     }
 
-    public Integer getUserId()
-    {
+    public Integer getUserId() {
         return userId;
     }
 
-    public void setUserId(Integer userId)
-    {
+    public void setUserId(Integer userId) {
         this.userId = userId;
     }
 
-    public String getUsername()
-    {
+    public String getUsername() {
         return username;
     }
 
-    public void setUsername(String username)
-    {
+    public void setUsername(String username) {
         this.username = username;
     }
 
-    public String getPassword()
-    {
+    public String getPassword() {
         return password;
     }
 
-    public void setPassword(String password)
-    {
+    public void setPassword(String password) {
         this.password = password;
     }
 
-    public String getMobile()
-    {
+    public String getMobile() {
         return mobile;
     }
 
-    public void setMobile(String mobile)
-    {
+    public void setMobile(String mobile) {
         this.mobile = mobile;
     }
+
+
 }

+ 16 - 0
fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java

@@ -820,6 +820,22 @@ public class CompanyUserController extends BaseController {
         return i>0?R.ok():R.error("绑定失败");
     }
 
+    /**
+     * 解绑销售和 fs_user 的关系
+     */
+    @ApiOperation("解绑销售和 fs_user 的关系")
+    @PostMapping("/unbindSaleAndFsUser")
+    public R unbindSaleAndFsUser(@RequestBody FsUserCompanyUser companyUser) {
+        try {
+            boolean result = companyUserService.unbindCompanyUserAndFsUser(companyUser.getCompanyUserId(), companyUser.getUserId());
+            return result ? R.ok("解绑成功") : R.error("解绑失败");
+        } catch (Exception e) {
+            logger.error("解绑销售和用户关系异常", e);
+            return R.error("操作失败:" + e.getMessage());
+        }
+    }
+
+
     /**
      * 获取销售绑定的fs_user
      */

+ 25 - 0
fs-service/src/main/java/com/fs/common/VerifyCodeUtil.java

@@ -0,0 +1,25 @@
+package com.fs.common;
+
+import java.security.SecureRandom;
+
+public class VerifyCodeUtil {
+
+    // 使用 SecureRandom 保证安全性
+    private static final SecureRandom random = new SecureRandom();
+
+    /**
+     * 生成随机 6 位数字验证码
+     * @return 六位验证码字符串
+     */
+    public static String generateCode() {
+        int code = 100000 + random.nextInt(900000); // 保证是六位数,范围 100000-999999
+        return String.valueOf(code);
+    }
+
+    public static void main(String[] args) {
+        // 测试
+        for (int i = 0; i < 5; i++) {
+            System.out.println(VerifyCodeUtil.generateCode());
+        }
+    }
+}

+ 2 - 0
fs-service/src/main/java/com/fs/common/service/ISmsService.java

@@ -21,4 +21,6 @@ public interface ISmsService
     R sendOrderMsg(SmsSendUserParam param);
 
     R sendPackageOrderMsg(SmsSendUserParam param);
+
+    R sendCaptcha(String phone, String captcha, String code);
 }

+ 82 - 0
fs-service/src/main/java/com/fs/common/service/impl/SmsServiceImpl.java

@@ -36,6 +36,7 @@ import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.google.gson.Gson;
 import lombok.Synchronized;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
@@ -48,6 +49,7 @@ import java.util.Date;
 import java.util.List;
 
 @Service
+@Slf4j
 public class SmsServiceImpl implements ISmsService
 {
     @Autowired
@@ -527,6 +529,86 @@ public class SmsServiceImpl implements ISmsService
         }
     }
 
+    @Override
+    public R sendCaptcha(String phone, String captcha, String code) {
+        log.info(captcha);
+        CompanySmsTemp temp = smsTempService.selectCompanySmsTempByCode(code);
+        if (temp == null) {
+            return R.error("没有模板");
+        }
+        String content = temp.getContent();
+        if (StringUtils.isNotEmpty(captcha)) {
+            content = content.replace("${sms.captcha}", captcha);
+        }
+        String urls = null;
+        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.sms");
+        FsSmsConfig sms = JSON.parseObject(sysConfig.getConfigValue(), FsSmsConfig.class);
+        if (sms.getType().equals("rf")) {
+            try {
+                content = content.replace("${sms.sign}",sms.getRfSign());
+                urls = sms.getRfUrl1() + "sms?action=send&account=" + sms.getRfAccount1() + "&password=" + sms.getRfPassword1() + "&mobile=" + phone + "&content=" + URLEncoder.encode(content, "UTF-8") + "&extno=" + sms.getRfCode1() + "&rt=json";
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+            }
+            String post = HttpRequest.get(urls)
+                    .execute().body();
+            SmsSendVO vo = JSONUtil.toBean(post, SmsSendVO.class);
+            if (vo.getStatus().equals(0)) {
+                for (SmsSendItemVO itemVO : vo.getList()) {
+                    if (itemVO.getResult().equals("0")) {
+                        CompanySmsLogs logs = new CompanySmsLogs();
+                        logs.setContent(content);
+                        logs.setTempCode(temp.getTempCode());
+                        logs.setTempId(temp.getTempId());
+                        logs.setPhone(phone);
+                        logs.setSendTime(new Date());
+                        logs.setStatus(0);
+                        logs.setType(sms.getType());
+                        logs.setMid(itemVO.getMid());
+                        Integer counts = logs.getContent().length() / 67;
+                        if (logs.getContent().length() % 67 > 0) {
+                            counts = counts + 1;
+                        }
+                        if (counts == 0) {
+                            counts = 1;
+                        }
+                        logs.setNumber(counts);
+                        smsLogsService.insertCompanySmsLogs(logs);
+                    }
+                }
+            }
+        } else if (sms.getType().equals("dh")) {
+            SendSmsReturn sendSmsReturn = null;
+            content = content.replace("${sms.sign}",sms.getDhSign());
+            sendSmsReturn = smsTService.sendSms(sms.getDhAccount1(), sms.getDhPassword1(), content, phone);
+            if (sendSmsReturn != null) {
+                if (sendSmsReturn.getResult() != null && sendSmsReturn.getResult().equals("0")) {
+                    CompanySmsLogs logs = new CompanySmsLogs();
+                    logs.setContent(content);
+                    logs.setTempCode(temp.getTempCode());
+                    logs.setTempId(temp.getTempId());
+                    logs.setPhone(phone);
+                    logs.setSendTime(new Date());
+                    logs.setStatus(0);
+                    logs.setType(sms.getType());
+                    logs.setMid(sendSmsReturn.getMsgid());
+                    Integer counts = logs.getContent().length() / 67;
+                    if (logs.getContent().length() % 67 > 0) {
+                        counts = counts + 1;
+                    }
+                    if (counts == 0) {
+                        counts = 1;
+                    }
+                    logs.setNumber(counts);
+                    smsLogsService.insertCompanySmsLogs(logs);
+                }
+            }
+        }
+
+
+        return R.ok();
+    }
+
 
     @Override
     @Synchronized

+ 10 - 1
fs-service/src/main/java/com/fs/company/mapper/CompanyFsUserMapper.java

@@ -3,6 +3,9 @@ package com.fs.company.mapper;
 import com.fs.company.domain.CompanyFsUser;
 import com.fs.his.domain.FsUser;
 import com.fs.his.vo.CompanyUserBindUserVO;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 
 import java.util.List;
 
@@ -40,5 +43,11 @@ public interface CompanyFsUserMapper {
     /**
      * 根据销售id 查询绑定的用户
      */
-   String selectUserListBySalesId(Long companyUserId);
+    String selectUserListBySalesId(Long companyUserId);
+
+    @Select("select * from company_fs_user where company_user_id=#{companyUserId} and fs_user_id=#{userId}")
+    CompanyFsUser selectByCompanyUserIdAndUserId(@Param("companyUserId") Long companyUserId, @Param("userId") Long userId);
+
+    @Delete("delete from company_fs_user WHERE id=#{id}")
+    int deleteById(Long id);
 }

+ 8 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java

@@ -282,6 +282,14 @@ public interface ICompanyUserService {
      */
     int  bindCompanyUserAndFsUser(Long companyUserId, Long fsUserId);
 
+    /**
+     * 解绑销售和 fs_user 的关系
+     * @param companyUserId 销售 ID
+     * @param userId 用户 ID
+     * @return 是否删除成功
+     */
+    boolean unbindCompanyUserAndFsUser(Long companyUserId, Long userId);
+
     /**
      * 获取销售绑定的fs_user
      */

+ 19 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java

@@ -1353,6 +1353,25 @@ public class CompanyUserServiceImpl implements ICompanyUserService
         return companyFsUserMapper.insertCompanyFsUser(companyFsUser);
     }
 
+    @Override
+    public boolean unbindCompanyUserAndFsUser(Long companyUserId, Long userId) {
+        // 校验参数
+        if (companyUserId == null || userId == null) {
+            throw new IllegalArgumentException("销售 ID 或用户 ID 不能为空");
+        }
+
+        // 查询是否存在绑定关系
+        CompanyFsUser relation = companyFsUserMapper.selectByCompanyUserIdAndUserId(companyUserId, userId);
+        if (relation == null) {
+            throw new RuntimeException("未找到销售与用户之间的绑定关系");
+        }
+
+        // 删除绑定关系
+        int rows = companyFsUserMapper.deleteById(relation.getId());
+        return rows > 0;
+    }
+
+
     @Override
     public List<CompanyUserBindUserVO> getFsUserByCompanyUserId(FsUser fsUser) {
         //加密手机号

+ 5 - 0
fs-service/src/main/java/com/fs/erp/domain/ErpOrder.java

@@ -35,4 +35,9 @@ public class ErpOrder {
 
     String buyer_account;
     Boolean isIntegralOrder;
+    //卖家备注
+    String remark;
+    String parent_code;
+    Integer orderNum = 0;
+
 }

+ 2 - 0
fs-service/src/main/java/com/fs/erp/domain/ErpOrderQuery.java

@@ -27,6 +27,8 @@ public class ErpOrderQuery {
     String receiver_mobile;
     String receiver_address;
     Integer delivery_state;
+    Integer o_id;
+    String so_id;
 
 
 

+ 4 - 0
fs-service/src/main/java/com/fs/erp/dto/ErpOrderQueryRequert.java

@@ -3,6 +3,7 @@ package com.fs.erp.dto;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.List;
 
 @Data
 public class ErpOrderQueryRequert implements Serializable {
@@ -10,4 +11,7 @@ public class ErpOrderQueryRequert implements Serializable {
     Integer page_no;
     Integer page_size;
     String platform_code;
+    String shop_id;
+    Integer page_index;
+    List<Long> o_ids;
 }

+ 7 - 0
fs-service/src/main/java/com/fs/erp/dto/ErpOrderQueryResponse.java

@@ -1,5 +1,6 @@
 package com.fs.erp.dto;
 
+import cn.hutool.core.annotation.Alias;
 import com.fs.erp.domain.ErpOrderQuery;
 import lombok.Data;
 
@@ -8,5 +9,11 @@ import java.util.List;
 @Data
 public class ErpOrderQueryResponse extends BaseResponse {
     List<ErpOrderQuery> orders;
+    @Alias("has_next")
+    private Boolean hasNext;
+
+    public boolean hasNextSafe() {
+        return Boolean.TRUE.equals(hasNext);
+    }
 
 }

+ 4 - 0
fs-service/src/main/java/com/fs/erp/http/JstErpHttpService.java

@@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSONObject;
 import com.fs.erp.dto.*;
 import com.fs.ybPay.dto.RefundOrderDTO;
 
+import java.util.List;
+
 /**
  * JST ERP 接口服务类
  */
@@ -49,6 +51,8 @@ public interface JstErpHttpService {
      */
     ErpOrderResponseDTO upload(ShopOrderDTO dto);
 
+    ErpOrderResponseDTO batchUpload(List<ShopOrderDTO> dtos);
+
     /**
      * 订单查询(自有商城、跨境线下)
      * @param dto 请求参数

+ 24 - 9
fs-service/src/main/java/com/fs/erp/http/JstErpHttpServiceImpl.java

@@ -12,6 +12,8 @@ import com.alibaba.fastjson.serializer.SerializeConfig;
 import com.fs.erp.dto.*;
 import com.fs.erp.service.impl.JstTokenService;
 import com.fs.erp.utils.SignUtil;
+import com.fs.his.config.FsSysConfig;
+import com.fs.his.utils.ConfigUtil;
 import com.fs.ybPay.dto.RefundOrderDTO;
 import com.hc.openapi.tool.util.ObjectUtils;
 import lombok.extern.slf4j.Slf4j;
@@ -20,10 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 
 @Slf4j
 @Service
@@ -53,11 +52,14 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
 //     */
 //    private static final String REFRESH_TOKEN_URL = BASE_URL + "openWebIsv/auth/refreshToken;
 
-    @Value("${jst.app_key:''}")
-    private String appKey;
+//    @Value("${jst.app_key:''}")
+//    private String appKey;
+//
+//    @Value("${jst.app_secret:''}")
+//    private String appSecret;
 
-    @Value("${jst.app_secret:''}")
-    private String appSecret;
+    @Autowired
+    private ConfigUtil configUtil;
 
     @Autowired
     private JstTokenService jstTokenService;
@@ -108,6 +110,15 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
         return parseResponse(response, new TypeReference<CommonResponse<ErpOrderResponseDTO>>() {});
     }
 
+    @Override
+    public ErpOrderResponseDTO batchUpload(List<ShopOrderDTO> dtos) {
+        String url = BASE_URL + "open/jushuitan/orders/upload";
+        log.info("上传订单信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dtos));
+
+        HttpResponse response = executeJsonPost(url, dtos);
+        return parseResponse(response, new TypeReference<CommonResponse<ErpOrderResponseDTO>>() {});
+    }
+
     @Override
     public OrderQueryResponseDTO query(OrderQueryRequestDTO dto) {
         String url = BASE_URL + "open/orders/single/query";
@@ -166,12 +177,14 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
             String accessToken = jstTokenService.getAccessToken();
             map.put("access_token", accessToken);
         }
-
+        FsSysConfig sysConfig = configUtil.getSysConfig();
+        String appKey = sysConfig.getErpJstAppKey();
         map.put("app_key", appKey);
         map.put("timestamp", System.currentTimeMillis() / 1000);
         map.put("version", "2");
         map.put("charset", "utf-8");
         map.put("biz", jsonBody);
+        String appSecret = sysConfig.getErpJstAppsecret();
         map.put("sign", SignUtil.getSignNew(appSecret, map));
         Map<String, String> headers = MapUtil.builder(new HashMap<String, String>())
                 .put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
@@ -202,6 +215,8 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
 
         String accessToken = jstTokenService.getAccessToken();
 
+        String appKey = configUtil.getSysConfig().getErpJstAppKey();
+        String appSecret = configUtil.getSysConfig().getErpJstAppsecret();
         map.put("access_token",accessToken);
         map.put("app_key",appKey);
         map.put("timestamp",System.currentTimeMillis()/1000);

+ 4 - 0
fs-service/src/main/java/com/fs/erp/service/IErpOrderService.java

@@ -7,6 +7,8 @@ import com.fs.his.domain.FsStoreOrder;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
 import com.fs.live.domain.LiveOrder;
 
+import java.util.List;
+
 public interface IErpOrderService
 {
 
@@ -22,6 +24,7 @@ public interface IErpOrderService
     ErpOrderResponse refundLiveOrder(ErpRefundOrder order);
     ErpDeliverysResponse getDeliver(ErpDeliverysRequest param);
     ErpOrderQueryResponse getOrder(ErpOrderQueryRequert param);
+    ErpOrderQueryResponse  getIntegralOrder(ErpOrderQueryRequert param,String type);
     ErpOrderQueryResponse getScrmOrder(ErpOrderQueryRequert param);
     ErpOrderQueryResponse getLiveOrder(ErpOrderQueryRequert param);
     BaseResponse refundUpdate(ErpRefundUpdateRequest param);
@@ -34,5 +37,6 @@ public interface IErpOrderService
 
     void getOrderScrmDeliveryStatus(FsStoreOrderScrm order);
     void getOrderLiveDeliveryStatus(LiveOrder order);
+    ErpOrderResponse batchAddIntegralCartOrder(List<ErpOrder> erpOrders) throws InterruptedException;
 }
 

+ 10 - 0
fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java

@@ -523,6 +523,11 @@ public class DfOrderServiceImpl implements IErpOrderService {
         return response;
     }
 
+    @Override
+    public ErpOrderQueryResponse getIntegralOrder(ErpOrderQueryRequert param, String type) {
+        return null;
+    }
+
     @Override
     public ErpOrderQueryResponse getScrmOrder(ErpOrderQueryRequert param) {
         ErpOrderQueryResponse response = new ErpOrderQueryResponse();
@@ -1020,6 +1025,11 @@ public class DfOrderServiceImpl implements IErpOrderService {
         }
     }
 
+    @Override
+    public ErpOrderResponse batchAddIntegralCartOrder(List<ErpOrder> erpOrders) throws InterruptedException {
+        return null;
+    }
+
     private void cancelOrderLive(LiveOrder order) {
         Integer deliveryStatus = order.getDeliveryStatus();
         if (deliveryStatus == null || deliveryStatus == 0) {

+ 12 - 0
fs-service/src/main/java/com/fs/erp/service/impl/ErpOrderServiceImpl.java

@@ -19,6 +19,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 @Service
 public class ErpOrderServiceImpl implements IErpOrderService
 {
@@ -138,6 +140,11 @@ public class ErpOrderServiceImpl implements IErpOrderService
         return response;
     }
 
+    @Override
+    public ErpOrderQueryResponse getIntegralOrder(ErpOrderQueryRequert param, String type) {
+        return null;
+    }
+
     @Override
     public ErpOrderQueryResponse getScrmOrder(ErpOrderQueryRequert param) {
         return null;
@@ -193,4 +200,9 @@ public class ErpOrderServiceImpl implements IErpOrderService
     public void getOrderLiveDeliveryStatus(LiveOrder order) {
 
     }
+
+    @Override
+    public ErpOrderResponse batchAddIntegralCartOrder(List<ErpOrder> erpOrders) throws InterruptedException {
+        return null;
+    }
 }

+ 10 - 0
fs-service/src/main/java/com/fs/erp/service/impl/HzOMSErpOrderServiceImpl.java

@@ -241,6 +241,11 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public ErpOrderQueryResponse getIntegralOrder(ErpOrderQueryRequert param, String type) {
+        return null;
+    }
+
     @Override
     public ErpOrderQueryResponse getScrmOrder(ErpOrderQueryRequert param) {
         return null;
@@ -345,6 +350,11 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
 
     }
 
+    @Override
+    public ErpOrderResponse batchAddIntegralCartOrder(List<ErpOrder> erpOrders) throws InterruptedException {
+        return null;
+    }
+
     /**
      * 构建瀚智创建订单参数
      *

+ 269 - 7
fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java

@@ -4,6 +4,9 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.erp.constant.AfterSalesOrderStatusEnum;
 import com.fs.erp.constant.ErpQueryOrderStatusEnum;
@@ -17,10 +20,9 @@ import com.fs.erp.mapper.FsJstAftersalePushScrmMapper;
 import com.fs.erp.mapper.FsJstCodPushMapper;
 import com.fs.erp.mapper.FsJstCodPushScrmMapper;
 import com.fs.erp.service.IErpOrderService;
-import com.fs.his.domain.FsStoreOrder;
-import com.fs.his.domain.FsStoreOrderItem;
-import com.fs.his.domain.FsStoreProduct;
-import com.fs.his.mapper.FsStoreAfterSalesMapper;
+import com.fs.his.domain.*;
+import com.fs.his.mapper.*;
+import com.fs.his.service.IFsIntegralOrderService;
 import com.fs.his.service.IFsStoreOrderItemService;
 import com.fs.his.service.IFsStoreOrderService;
 import com.fs.his.service.IFsStoreProductService;
@@ -84,6 +86,25 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
     @Autowired
     private LiveOrderItemMapper liveOrderItemMapper;
 
+    @Autowired
+    RedisCache redisCache;
+
+    @Autowired
+    private FsStoreOrderItemMapper fsStoreOrderItemMapper;
+
+    @Autowired
+    private FsStoreOrderMapper fsStoreOrderMapper;
+
+    @Autowired
+    private FsIntegralOrderMapper fsIntegralOrderMapper;
+    @Autowired
+    private IFsIntegralOrderService fsIntegralOrderService;
+
+    @Autowired
+    private FsIntegralGoodsMapper fsIntegralGoodsMapper;
+
+
+
     @Override
     public ErpOrderResponse addOrder(ErpOrder order) {
         FsStoreOrder fsStoreOrder = fsStoreOrderService.selectFsStoreOrderByOrderCode(order.getPlatform_code());
@@ -200,8 +221,29 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
             log.info("推送ERP返回结果: {}",upload);
             throw new IllegalArgumentException("推送ERP返回数不应该为0");
         }
-        ErpOrderResponseDTO.OrderData orderData = upload.getDatas().get(0);
 
+        for (ErpOrderResponseDTO.OrderData data : upload.getDatas()) {
+            if (data!=null&&data.getIssuccess()) {
+                FsStoreOrder storeOrder = fsStoreOrderService.selectFsStoreOrderByOrderCode(data.getSoId());
+                //普通订单
+                if (storeOrder!=null&&StringUtils.isEmpty(storeOrder.getExtendOrderId())){
+                    //支付成功后 将订单号写入待发货的REDIS中
+                    redisCache.setCacheObject("delivery" + ":" + data.getOId(), storeOrder.getOrderCode());
+                    //写入外部订单号
+                    storeOrder.setExtendOrderId(data.getOId().toString());
+                    storeOrder.setUpdateTime(DateUtils.getNowDate());
+                    fsStoreOrderMapper.updateFsStoreOrder(storeOrder);
+                }else if (storeOrder!=null&& storeOrder.getExtendOrderId().equals("BATCH")){
+                    //分批订单
+                    FsStoreOrderItem oneItem = fsStoreOrderItemMapper.selectFsStoreOrderItemByOrderCode(data.getSoId());
+                    redisCache.setCacheObject("delivery" + ":" + data.getOId(), oneItem.getOrderCode());
+                    //写入外部订单号
+                    oneItem.setExtendOrderId(data.getOId().toString());
+                    fsStoreOrderItemMapper.updateFsStoreOrderItemBatch(oneItem);
+                }
+            }
+        }
+        ErpOrderResponseDTO.OrderData orderData = upload.getDatas().get(0);
         ErpOrderResponse erpOrderResponse = new ErpOrderResponse();
         erpOrderResponse.setSuccess(true);
         erpOrderResponse.setCode(String.valueOf(orderData.getOId()));
@@ -481,8 +523,14 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
     public ErpOrderQueryResponse getOrder(ErpOrderQueryRequert param) {
         // 1. 构建查询请求DTO
         OrderQueryRequestDTO requestDTO = new OrderQueryRequestDTO();
-        requestDTO.setOIds(Collections.singletonList(Long.valueOf(param.getCode())));
-
+        if(StringUtils.isNotEmpty(param.getCode())) {
+            requestDTO.setOIds(Collections.singletonList(Long.valueOf(param.getCode())));
+        }else {
+            requestDTO.setOIds(param.getO_ids());
+            requestDTO.setShopId(Integer.parseInt(param.getShop_id()));
+            requestDTO.setPageIndex(param.getPage_index());
+            requestDTO.setPageSize(param.getPage_size());
+        }
 
         // 2. 调用ERP服务查询订单
         OrderQueryResponseDTO query = jstErpHttpService.query(requestDTO);
@@ -506,6 +554,115 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         return response;
     }
 
+    @Override
+    public ErpOrderQueryResponse getIntegralOrder(ErpOrderQueryRequert param, String type) {
+        // 1. 构建查询请求DTO
+        OrderQueryRequestDTO requestDTO = new OrderQueryRequestDTO();
+        if(StringUtils.isNotEmpty(param.getCode())) {
+            requestDTO.setOIds(Collections.singletonList(Long.valueOf(param.getCode())));
+        }else {
+            requestDTO.setOIds(param.getO_ids());
+            requestDTO.setShopId(Integer.parseInt(param.getShop_id()));
+            requestDTO.setPageIndex(param.getPage_index());
+            requestDTO.setPageSize(param.getPage_size());
+        }
+        // 2. 调用ERP服务查询订单
+        OrderQueryResponseDTO query = jstErpHttpService.query(requestDTO);
+
+        // 3. 构建响应对象
+        ErpOrderQueryResponse response = new ErpOrderQueryResponse();
+
+        // 4. 设置基本响应信息
+
+        // 5. 转换订单数据
+        if (query.getOrders() != null && !query.getOrders().isEmpty()) {
+            List<ErpOrderQuery> erpOrders = query.getOrders().stream()
+                    .map(this::convertToErpIntegralOrderQuery)
+                    .collect(Collectors.toList());
+            response.setOrders(erpOrders);
+            response.setHasNext(query.getHasNext());
+        } else {
+            response.setOrders(Collections.emptyList());
+        }
+
+        return response;
+    }
+
+    private  ErpOrderQuery  convertToErpIntegralOrderQuery(OrderQueryResponseDTO.Order order) {
+        ErpOrderQuery erpOrder = new ErpOrderQuery();
+
+        FsIntegralOrder fsIntegralOrder = fsIntegralOrderMapper.selectFsIntegralOrderByOrderCode(order.getSoId());
+        Asserts.notNull(fsIntegralOrder,"该订单号没有找到!");
+
+        // 设置基本订单信息
+        erpOrder.setCode(order.getSoId());
+
+        // 计算订单总数量
+        if (order.getItems() != null && !order.getItems().isEmpty()) {
+            int totalQty = order.getItems().stream()
+                    .mapToInt(OrderQueryResponseDTO.OrderItem::getQty)
+                    .sum();
+            erpOrder.setQty(totalQty);
+        }
+
+        // 设置金额相关信息
+        erpOrder.setAmount(order.getAmount() != null ? order.getAmount().doubleValue() : null);
+        erpOrder.setPayment(order.getPaidAmount() != null ? order.getPaidAmount().doubleValue() : null);
+
+        // 设置其他订单属性
+        erpOrder.setCod(order.getIsCod());
+        erpOrder.setPlatform_code(order.getOrderFrom());
+
+        // 尝试解析创建时间
+        try {
+            if (order.getCreated() != null) {
+                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                erpOrder.setCreatetime(formatter.parse(order.getCreated()));
+            }
+        } catch (Exception e) {
+            // 日期解析异常处理
+            // 可以记录日志或保持为null
+        }
+
+        // 设置店铺信息
+        erpOrder.setShop_name(order.getShopName());
+        erpOrder.setShop_code(String.valueOf(order.getShopId()));
+
+        // 设置物流信息
+        erpOrder.setExpress_name(order.getLogisticsCompany());
+        erpOrder.setExpress_code(order.getLId());
+
+        // 设置收件人信息
+//        erpOrder.setReceiver_name(fsStoreOrder.getRealName());
+        erpOrder.setReceiver_name(fsIntegralOrder.getUserName());
+        erpOrder.setReceiver_phone(fsIntegralOrder.getUserPhone());
+        erpOrder.setReceiver_mobile(fsIntegralOrder.getUserPhone());
+
+        // 构建完整地址
+        erpOrder.setReceiver_address(fsIntegralOrder.getUserAddress());
+
+        // 如果是已发货
+        if(ObjectUtil.equal(order.getStatus(), ErpQueryOrderStatusEnum.SENT.getCode())){
+            List<ErpDeliverys> deliverysList = new ArrayList<>();
+
+            ErpDeliverys delivery = new ErpDeliverys();
+            delivery.setMail_no(order.getLId());
+            delivery.setExpress_code(order.getLcId());
+            delivery.setExpress_name(order.getLogisticsCompany());
+            delivery.setDelivery(true);
+            delivery.setCode(order.getSoId());
+
+            deliverysList.add(delivery);
+            erpOrder.setDeliverys(deliverysList);
+
+            // 设置发货状态,假设有物流单号就是已发货状态
+            erpOrder.setDelivery_state(1);
+        } else {
+            erpOrder.setDelivery_state(0);
+        }
+
+        return erpOrder;
+    }
 
     @Override
     public ErpOrderQueryResponse getScrmOrder(ErpOrderQueryRequert param) {
@@ -924,5 +1081,110 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
     public void getOrderLiveDeliveryStatus(LiveOrder order) {
 
     }
+
+    @Override
+    public ErpOrderResponse batchAddIntegralCartOrder(List<ErpOrder> erpOrders) throws InterruptedException {
+        List<ShopOrderDTO> normalOrders = new ArrayList<>();  // 普通订单
+        for (ErpOrder order : erpOrders) {
+            FsIntegralOrder fsIntegralOrder = fsIntegralOrderMapper.selectFsIntegralOrderByOrderCode(order.getPlatform_code());
+            log.info("ERP订单号: {}, 订单信息: {}", order.getPlatform_code(), JSON.toJSONString(fsIntegralOrder));
+            if (!CollectionUtils.isEmpty(order.getPayments())) {
+                ErpOrderPayment erpOrderPayment = order.getPayments().get(0);
+            }
+            ShopOrderDTO shopOrderDTO = new ShopOrderDTO();
+            shopOrderDTO.setShopId(Long.valueOf(order.getShop_code()));
+            shopOrderDTO.setSoId(order.getPlatform_code());
+            shopOrderDTO.setOrderDate(order.getDeal_datetime());
+            shopOrderDTO.setShopStatus(OrderStatusEnum.WAIT_SELLER_SEND_GOODS.name());
+            shopOrderDTO.setShopBuyerId(order.getBuyer_account());
+            shopOrderDTO.setReceiverState(order.getReceiver_province());
+            shopOrderDTO.setReceiverCity(order.getReceiver_city());
+            shopOrderDTO.setReceiverDistrict(order.getReceiver_district());
+            shopOrderDTO.setReceiverAddress(order.getReceiver_address());
+            shopOrderDTO.setReceiverName(order.getReceiver_name());
+            shopOrderDTO.setReceiverPhone(order.getReceiver_mobile());
+            shopOrderDTO.setPayAmount(0.00);
+            shopOrderDTO.setRemark(order.getRemark());
+            shopOrderDTO.setFreight(Double.valueOf("0.00"));
+            shopOrderDTO.setBuyerMessage(order.getBuyer_memo());
+            // 订单商品项列表
+            List<OrderItemDTO> itemDTOList = new ArrayList<>();
+            OrderItemDTO orderItemDTO = new OrderItemDTO();
+            JSONObject jsonObject = JSON.parseObject(fsIntegralOrder.getItemJson());
+            String barCode = jsonObject.getString("barCode");
+            String productName = jsonObject.getString("goodsName");
+            //String sku = jsonObject.getString("sku");
+            orderItemDTO.setSkuId(barCode);
+            orderItemDTO.setShopSkuId(barCode);
+            orderItemDTO.setName(productName);
+            orderItemDTO.setShopIId(orderItemDTO.getSkuId());
+            //orderItemDTO.setPropertiesValue(sku);
+            FsIntegralGoods goodsId = fsIntegralGoodsMapper.selectFsIntegralGoodsByGoodsId(Long.parseLong(jsonObject.getString("goodsId")));
+            orderItemDTO.setAmount(new BigDecimal(0));
+            orderItemDTO.setPic(goodsId.getImgUrl());
+            orderItemDTO.setPrice(new BigDecimal(0));
+            orderItemDTO.setQty(1);
+            orderItemDTO.setOuterOiId(String.format("%s", fsIntegralOrder.getOrderCode()));
+            itemDTOList.add(orderItemDTO);
+            shopOrderDTO.setItems(itemDTOList);
+            // 实际支付金额
+            PaymentDTO paymentDTO = new PaymentDTO();
+            paymentDTO.setAmount(0.00);
+            paymentDTO.setOuterPayId(order.getPlatform_code());
+            paymentDTO.setPayDate(order.getDeal_datetime());
+            paymentDTO.setPayment("积分支付");
+            paymentDTO.setBuyerAccount(order.getBuyer_account());
+            paymentDTO.setSellerAccount("平台销售");
+            shopOrderDTO.setPay(paymentDTO);
+            if (order.getOrderNum() > 1) {
+                shopOrderDTO.setPayAmount(0.00);
+                shopOrderDTO.setPay(null);
+            }
+            // 添加普通订单
+            normalOrders.add(shopOrderDTO);
+        }
+        // 批量推送普通订单(每50条一批)
+        int batchSize = 50;  // 修正为50
+        ErpOrderResponseDTO lastResponse = null;
+        // 推送普通订单
+        for (int i = 0; i < normalOrders.size(); i += batchSize) {
+            int endIndex = Math.min(i + batchSize, normalOrders.size());
+            List<ShopOrderDTO> batch = new ArrayList<>(normalOrders.subList(i, endIndex));
+            lastResponse = jstErpHttpService.batchUpload(batch);
+            List<ErpOrderResponseDTO.OrderData> datas = lastResponse.getDatas();
+            for (ErpOrderResponseDTO.OrderData data : datas) {
+                if (data != null && data.getIssuccess()) {
+                    FsIntegralOrder fsIntegralOrder1 = fsIntegralOrderMapper.selectFsIntegralOrderByOrderCode(data.getSoId());
+                    //普通订单
+                    if (fsIntegralOrder1 != null && StringUtils.isEmpty(fsIntegralOrder1.getExtendOrderId())) {
+                        //支付成功后 将订单号写入待发货的REDIS中
+                        redisCache.setCacheObject("delivery" + ":" + data.getOId(), fsIntegralOrder1.getOrderCode());
+                        //写入外部订单号
+                        fsIntegralOrder1.setExtendOrderId(data.getOId().toString());
+                        fsIntegralOrderService.updateFsIntegralOrder(fsIntegralOrder1);
+                    }
+                }
+            }
+            log.info("批量推送普通订单,数量: {}", batch.size());
+            Thread.sleep(600);
+        }
+        // 返回最后一次推送的结果
+        if (lastResponse != null && CollectionUtils.isEmpty(lastResponse.getDatas())) {
+            log.info("推送ERP返回结果: {}", lastResponse);
+            throw new IllegalArgumentException("推送ERP返回数不应该为0");
+        }
+        // 如果没有任何订单推送,创建一个默认响应
+        if (lastResponse == null) {
+            lastResponse = new ErpOrderResponseDTO();
+            ErpOrderResponseDTO.OrderData data = new ErpOrderResponseDTO.OrderData();
+            data.setOId(0);
+            lastResponse.setDatas(Collections.singletonList(data));
+        }
+        ErpOrderResponseDTO.OrderData orderData = lastResponse.getDatas().get(0);
+        ErpOrderResponse erpOrderResponse = new ErpOrderResponse();
+        erpOrderResponse.setSuccess(true);
+        erpOrderResponse.setCode(String.valueOf(orderData.getOId()));
+        return erpOrderResponse;
+    }
 }
 

+ 12 - 8
fs-service/src/main/java/com/fs/erp/service/impl/JstTokenService.java

@@ -27,14 +27,14 @@ public class JstTokenService {
     private static final String JST_REFRESH_TOKEN_KEY = "jst:refresh_token";
     private static final String JST_TOKEN_EXPIRE_KEY = "jst:token_expire";
 
-    @Value("${jst.app_key:''}")
-    private String appKey;
+//    @Value("${jst.app_key:''}")
+//    private String appKey;
+//
+//    @Value("${jst.app_secret:''}")
+//    private String appSecret;
 
-    @Value("${jst.app_secret:''}")
-    private String appSecret;
-
-    @Value("${jst.authorization_code:''}")
-    private String authorizationCode;
+//    @Value("${jst.authorization_code:''}")
+//    private String authorizationCode;
 
     @Autowired
     private JstErpHttpService httpService;
@@ -88,10 +88,12 @@ public class JstTokenService {
      */
     private String initToken() {
         GetInitTokenRequestDTO requestDTO = new GetInitTokenRequestDTO();
+        String appKey = configUtil.getSysConfig().getErpJstAppKey();
+        String appSecret = configUtil.getSysConfig().getErpJstAppsecret();
         requestDTO.setApp_key(appKey);
         requestDTO.setGrant_type("authorization_code");
         requestDTO.setCharset("utf-8");
-        requestDTO.setCode(authorizationCode);
+        requestDTO.setCode("yyyyyy");
         requestDTO.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
 
         // 计算签名
@@ -118,6 +120,8 @@ public class JstTokenService {
      */
     private String refreshTokenWithApi(String refreshToken) {
         RefreshTokenRequestDTO requestDTO = new RefreshTokenRequestDTO();
+        String appKey = configUtil.getSysConfig().getErpJstAppKey();
+        String appSecret = configUtil.getSysConfig().getErpJstAppsecret();
         requestDTO.setApp_key(appKey);
         requestDTO.setGrant_type("refresh_token");
         requestDTO.setCharset("utf-8");

+ 10 - 0
fs-service/src/main/java/com/fs/erp/service/impl/K9OrderScrmServiceImpl.java

@@ -294,6 +294,11 @@ public class K9OrderScrmServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public ErpOrderQueryResponse getIntegralOrder(ErpOrderQueryRequert param, String type) {
+        return null;
+    }
+
     @Override
     public ErpOrderQueryResponse getScrmOrder(ErpOrderQueryRequert param) {
         return null;
@@ -636,4 +641,9 @@ public class K9OrderScrmServiceImpl implements IErpOrderService {
     public void getOrderLiveDeliveryStatus(LiveOrder order) {
 
     }
+
+    @Override
+    public ErpOrderResponse batchAddIntegralCartOrder(List<ErpOrder> erpOrders) throws InterruptedException {
+        return null;
+    }
 }

+ 10 - 0
fs-service/src/main/java/com/fs/erp/service/impl/WdtErpOrderServiceImpl.java

@@ -1023,6 +1023,11 @@ public class WdtErpOrderServiceImpl implements IErpOrderService {
         }
     }
 
+    @Override
+    public ErpOrderQueryResponse getIntegralOrder(ErpOrderQueryRequert param, String type) {
+        return null;
+    }
+
     @Override
     public ErpOrderQueryResponse getScrmOrder(ErpOrderQueryRequert param) {
         return null;
@@ -1309,6 +1314,11 @@ public class WdtErpOrderServiceImpl implements IErpOrderService {
 
     }
 
+    @Override
+    public ErpOrderResponse batchAddIntegralCartOrder(List<ErpOrder> erpOrders) throws InterruptedException {
+        return null;
+    }
+
     public static String convertToSnakeCase(Object obj) {
         SerializeConfig config = new SerializeConfig();
         config.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;

+ 2 - 0
fs-service/src/main/java/com/fs/his/config/FsSmsConfig.java

@@ -21,4 +21,6 @@ public class FsSmsConfig {
     private String dhPassword2;
     private String dhSign;
 
+    private Integer isSmsVerification; //是否开启短信验证
+
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/domain/FsIntegralOrder.java

@@ -130,4 +130,6 @@ public class FsIntegralOrder
     private Integer deliveryStatus;
 
     private String deliveryType;
+
+    private String extendOrderId;
 }

+ 5 - 0
fs-service/src/main/java/com/fs/his/domain/FsStore.java

@@ -107,4 +107,9 @@ public class FsStore extends BaseEntity
 
     private String sendPhone;
 
+    /**
+     * 店铺编号
+     */
+    private String shopCode;
+
 }

+ 30 - 0
fs-service/src/main/java/com/fs/his/domain/FsStoreOrderItem.java

@@ -1,11 +1,14 @@
 package com.fs.his.domain;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import lombok.Data;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 
+import java.util.Date;
+
 /**
  * 订单详情对象 fs_store_order_item
  *
@@ -59,4 +62,31 @@ public class FsStoreOrderItem extends BaseEntity
     private Integer isGift;
 
     private Integer isDrug;
+
+    private String orderCode;
+    //分批扩展订单ID
+    private String extendOrderId;
+    //快递公司编号
+    private String deliveryCode;
+    //快递名称
+    private String deliveryName;
+    //快递单号
+    private String deliverySn;
+    //发货时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date deliveryTime;
+    //分批批次号
+    private Integer batchNum;
+    //预计发货时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private String expectDeliveryTime;
+    //分批订单信息
+    private String splitOrderItemJson;
+    //物流状态
+    private Integer deliveryStatus;
+    //物流跟踪状态
+    private String deliveryType;
+    //物流更新时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date deliveryUpdateTime;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/his/domain/FsUser.java

@@ -126,6 +126,9 @@ public class FsUser extends BaseEntity
 
     private Integer isBuy;
 
+    /** app登录后不为null(表示是否下载app) */
+    private String historyApp;
+
     private String jpushId;
     private Integer isVip;
     private Date  vipStartDate;

+ 12 - 0
fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderMapper.java

@@ -116,4 +116,16 @@ public interface FsIntegralOrderMapper extends BaseMapper<FsIntegralOrder>
     List<FsIntegralOrder> findOrderByIds(@Param("orderIds") List<Long> orderIds);
 
     List<FsIntegralOrderListVO> selectFsIntegralOrderListJn(FsIntegralOrderParam fsIntegralOrder);
+
+
+    //查询可推送到聚水潭的积分订单
+    @Select("select order_id from fs_integral_order where status = 1 and extend_order_id is null and create_time > '2026-01-10 00:00:00'")
+//    @Select("select order_id from fs_integral_order where order_code =  2010898431911919616")
+    List<Long> selectFsIntegralOrderToJst();
+
+    //查询待同步发货状态的积分订单
+    @Select("select order_code,extend_order_id from fs_integral_order where extend_order_id is not null and `status`=1 and create_time > '2026-01-10 00:00:00'")
+    List<FsIntegralOrder> selectJstOmsIntegralOrderdeliveryOp();
+
+
 }

+ 7 - 0
fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderItemMapper.java

@@ -57,6 +57,11 @@ public interface FsStoreOrderItemMapper
      */
     public int deleteFsStoreOrderItemByItemId(String itemId);
 
+    int updateFsStoreOrderItemBatch(FsStoreOrderItem fsStoreOrderItem);
+
+    @Select("select * from fs_store_order_item where order_code = #{orderCode} limit 1")
+    FsStoreOrderItem selectFsStoreOrderItemByOrderCode(String orderCode);
+
     /**
      * 批量删除订单详情
      *
@@ -74,5 +79,7 @@ public interface FsStoreOrderItemMapper
     @Select("select product_id,json_info,num from fs_store_order_item where order_id=#{orderId}")
     List<FsStoreOrderItemListDVO> selectFsStoreOrderItemListDVOByOrderId(Long orderId);
 
+    @Select(" select * from fs_store_order_item where order_code=#{orderCode} ")
+    List<FsStoreOrderItem> getFsStoreOrderItemByOrderCode(@Param("orderCode")String orderCode);
     List<FsStoreOrderItem> selectFsStoreOrderItemListByItemIds(@Param("itemIds") List<Long> itemIds);
 }

+ 16 - 0
fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java

@@ -79,6 +79,9 @@ public interface FsStoreOrderMapper
     public int deleteFsStoreOrderByOrderIds(String[] orderIds);
     @Select("select order_id from fs_store_order where status = 3 and delivery_status = 0  and DATE(create_time)<='2024-3-1' ")
     List<Long> selectSyncExpressIds();
+
+    @Select("select order_id from fs_store_order WHERE `status`= 2 and store_id in (select store_id from fs_store where delivery_type=4) and  extend_order_id is null ")
+    List<Long> selectFsJSTStoreOrderNoCreateOms();
 //    @Select({"<script> " +
 //            "select so.*,st.store_name,us.nick_name,us.phone,d.doctor_name,p.patient_name,p.prescribe_code,c.company_name,cu.nick_name company_user_name " +
 //            " FROM fs_store_order so LEFT JOIN fs_store st ON so.store_id =st.store_id " +
@@ -672,6 +675,16 @@ public interface FsStoreOrderMapper
     @Select("select * from fs_store_order WHERE `status`>0 and DATE(follow_time) = CURDATE() ")
     List<FsStoreOrder> selectStoreOrderIdByFollow();
 
+    @Select({
+            "<script>",
+            "SELECT * FROM fs_store_order WHERE extend_order_id IN ",
+            "<foreach collection='extendOrderIds' item='id' open='(' separator=',' close=')'>",
+            "#{id}",
+            "</foreach>",
+            "</script>"
+    })
+    List<FsStoreOrder> selectFsStoreOrderByExtendOrderId(@Param("extendOrderIds") List<Long> extendOrderIds);
+
     @Select({"<script> " +
             "select so.*,u.nick_name,u.phone,p.patient_name ,TIMESTAMPDIFF(YEAR, pat.birthday, CURDATE()) AS age,pat.sex ,p.prescribe_code,d.doctor_name,pat.relation,CONCAT(u.nick_name, '(',  LEFT(u.phone, 3),  '****',  RIGHT(u.phone, 4),  ')') AS `user`, c.company_name ,cu.nick_name as company_user_nick_name ,cts.name as schedule_name,st.store_name , csc.name miniProgramName" +
             " from fs_store_order so  " +
@@ -1198,4 +1211,7 @@ public interface FsStoreOrderMapper
     FsStoreOrderAmountStatsVo selectFsStoreOrderAmountStats(FsStoreOrderAmountStatsQueryDto queryDto);
 
     List<FsStoreOrder> selectOutTimeOrderList(@Param("unPayTime")Integer unPayTime);
+
+    @Select("select order_code,extend_order_id,store_id from fs_store_order where extend_order_id is not null and extend_order_id != 'BATCH' and store_id in (select store_id from fs_store where delivery_type = 4) and `status`=2 ")
+    List<FsStoreOrder> selectJstOmsOrderdeliveryOp();
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java

@@ -505,4 +505,6 @@ public interface FsUserMapper
      * 项目会员导出数据
      */
     List<FsUserPageListExportVO> FsUserPageListExportVO(FsUserPageListExportParam param);
+
+    void updatePasswordByPhone(@Param("password")String password, @Param("encryptPhone")String encryptPhone);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/param/FsIntegralOrderDoPayParam.java

@@ -10,4 +10,6 @@ public class FsIntegralOrderDoPayParam {
     private Long orderId;
 
     private Long userId;
+
+    private  String appId;
 }

+ 5 - 0
fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderService.java

@@ -10,6 +10,7 @@ import com.fs.his.vo.FsIntegralOrderListVO;
 import com.fs.his.vo.FsIntegralOrderPVO;
 import com.fs.his.vo.FsStoreProductDeliverExcelVO;
 
+import java.text.ParseException;
 import java.util.List;
 
 /**
@@ -109,4 +110,8 @@ public interface IFsIntegralOrderService
     int mandatoryRefunds(String orderCode);
 
     int finishOrder(String orderCode);
+
+    void createOmsIntegralOrder(List<Long> orderIds) throws ParseException, InterruptedException;
+
+    void deliveryIntegralOrderOrder(String orderCode, String deliveryId, String deliverCode, String deliverName);
 }

+ 10 - 0
fs-service/src/main/java/com/fs/his/service/IFsStoreOrderService.java

@@ -298,4 +298,14 @@ public interface IFsStoreOrderService
      * @return
      */
     int approveOrder(List<Long> orderId);
+
+    /**
+     * 聚水潭订单
+     * @param orderIds
+     * @throws ParseException
+     * @throws InterruptedException
+     */
+    void createJSTOmsOrder(List<Long> orderIds) throws Exception;
+
+    void deliveryOrderItem(String orderCode, String deliveryId, String deliverCode, String deliverName, String itemOrderCode);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserService.java

@@ -267,4 +267,6 @@ public interface IFsUserService
      * 销售分享app下载链接给用户
      */
     Boolean  bindUserToSales(Long userId, String inviteCode);
+
+    R updatePasswordByPhone(String password, String encryptPhone);
 }

+ 250 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java

@@ -23,10 +23,16 @@ import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.company.util.WechatApi;
 import com.fs.core.utils.OrderCodeUtils;
+import com.fs.erp.domain.ErpOrder;
+import com.fs.erp.domain.ErpOrderPayment;
+import com.fs.erp.dto.ErpOrderResponse;
+import com.fs.erp.service.IErpOrderService;
 import com.fs.event.TemplateBean;
 import com.fs.event.TemplateEvent;
 import com.fs.event.TemplateListenEnum;
+import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.*;
+import com.fs.his.dto.ErpRemarkDTO;
 import com.fs.his.enums.BusinessTypeEnum;
 import com.fs.his.enums.FsInquiryOrderStatusEnum;
 import com.fs.his.enums.FsUserIntegralLogTypeEnum;
@@ -34,6 +40,7 @@ import com.fs.his.enums.PaymentMethodEnum;
 import com.fs.his.mapper.*;
 import com.fs.his.param.*;
 import com.fs.his.service.*;
+import com.fs.his.utils.ConfigUtil;
 import com.fs.his.utils.PhoneUtil;
 import com.fs.his.vo.FsIntegralOrderListUVO;
 import com.fs.his.vo.FsIntegralOrderListVO;
@@ -55,18 +62,25 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
+import javax.annotation.PostConstruct;
 import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
+import static com.fs.his.utils.PhoneUtil.decryptPhone;
+
 /**
  * 积分商品订单Service业务层处理
  *
@@ -123,6 +137,55 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
     @Autowired
     private ApplicationEventPublisher publisher;
 
+    @Autowired
+    private ConfigUtil configUtil;
+
+    @Autowired
+    private IFsExpressService expressService;
+
+    @Value("${jst.shop_code:''}")
+    private String shopCode;
+
+    @Autowired
+    private IErpOrderService jstErpOrderService;
+
+    @Autowired
+    @Qualifier("erpOrderServiceImpl")
+    private IErpOrderService gyOrderService;
+
+    @Autowired
+    @Qualifier("wdtErpOrderServiceImpl")
+    private IErpOrderService wdtOrderService;
+
+    @Autowired
+    @Qualifier("hzOMSErpOrderServiceImpl")
+    private IErpOrderService hzOMSOrderService;
+
+    @Autowired
+    @Qualifier("dfOrderServiceImpl")
+    private IErpOrderService dfOrderService;
+
+    @Autowired
+    @Qualifier("JSTErpOrderServiceImpl")
+    private IErpOrderService jSTOrderService;
+    @Autowired
+    @Qualifier("k9OrderScrmServiceImpl")
+    private IErpOrderService k9OrderService;
+
+    //ERP 类型到服务的映射
+    private Map<Integer, IErpOrderService> erpServiceMap;
+
+    @PostConstruct
+    public void initErpServiceMap() {
+        erpServiceMap = new HashMap<>();
+        erpServiceMap.put(1, gyOrderService);      // 管易
+        erpServiceMap.put(2, wdtOrderService);     // 旺店通
+        erpServiceMap.put(3, hzOMSOrderService);   // 瀚智OMS
+        erpServiceMap.put(4, dfOrderService);      // 代服
+        erpServiceMap.put(5, jSTOrderService);     // 聚水潭
+        erpServiceMap.put(6, k9OrderService);      // K9
+    }
+
     /**
      * 查询积分商品订单
      *
@@ -548,6 +611,7 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
         }
 
         PayOrderParam payOrderParam = buildPayOrderParam(paymentMethod, order);
+        payOrderParam.setAppId(param.getAppId());
         return storePaymentService.processPayment(payOrderParam);
     }
 
@@ -827,6 +891,192 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
         return fsIntegralOrderMapper.finishOrder(fsIntegralOrder.getOrderId(), fsIntegralOrder.getStatus());
     }
 
+    @Override
+    public void createOmsIntegralOrder(List<Long> orderIds) throws ParseException, InterruptedException {
+        List<ErpOrder> erpOrders = new ArrayList<>();
+
+        // 1. 检查 ERP 是否开启
+        FsSysConfig sysConfig = configUtil.getSysConfig();
+        Integer erpOpen = sysConfig.getErpOpen();
+        if (erpOpen == null || erpOpen == 0) {
+            log.info("ERP未开启,跳过同步");
+            return;
+        }
+        Integer erpType = sysConfig.getErpType();
+        if (erpType == null || !erpServiceMap.containsKey(erpType)) {
+            log.info("ERP类型配置无效: {}", erpType);
+            return;
+        }
+        for (Long orderId : orderIds) {
+            FsIntegralOrder fsIntegralOrder = fsIntegralOrderMapper.selectFsIntegralOrderByOrderId(orderId);
+            if (fsIntegralOrder != null && StringUtils.isEmpty(fsIntegralOrder.getExtendOrderId()) && fsIntegralOrder.getStatus() != 1) {
+                return;
+            }
+            if (fsIntegralOrder == null) {
+                return;
+            }
+            ErpOrder erpOrder = new ErpOrder();
+            erpOrder.setVip_code(fsIntegralOrder.getUserId().toString());
+            erpOrder.setPlatform_code(fsIntegralOrder.getOrderCode());
+//        if(order.getStoreHouseCode()==null){
+//            erpOrder.setWarehouse_code("CQDS001");
+//        }else{
+//            erpOrder.setWarehouse_code(order.getStoreHouseCode());
+//        }
+            erpOrder.setShop_code(sysConfig.getErpShopCode());
+            erpOrder.setSeller_memo(fsIntegralOrder.getRemark());
+            List<ErpOrderPayment> payments = new ArrayList<>();
+            ErpOrderPayment payment = new ErpOrderPayment();
+            payment.setPay_type_code("weixin");
+            payment.setPayment(0.00);
+            erpOrder.setBuyer_account(fsIntegralOrder.getUserName());
+            erpOrder.setRemark(fsIntegralOrder.getRemark());
+            if (fsIntegralOrder.getCreateTime() != null) {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                String timeString = sdf.format(fsIntegralOrder.getCreateTime());
+                Date date = sdf.parse(timeString); // 时间格式转为时间戳
+                long timeLong = date.getTime();
+                payment.setPaytime(new Timestamp(timeLong));
+            }
+            payments.add(payment);
+
+            FsExpress express = expressService.selectFsExpressByOmsCode("YUNDA");
+            erpOrder.setExpress_code(express.getOmsCode());
+            fsIntegralOrder.setDeliveryName(express.getName());
+            fsIntegralOrder.setDeliveryCode(express.getCode());
+            erpOrder.setPayments(payments);
+
+            BigDecimal bigDecimal = new BigDecimal(0);
+            ErpRemarkDTO remarkDTO = new ErpRemarkDTO();
+            remarkDTO.setTotalPrice(bigDecimal);
+            remarkDTO.setPayPrice(bigDecimal);
+            remarkDTO.setDeliveryMoney(bigDecimal);
+            remarkDTO.setPayMoney(bigDecimal);
+            remarkDTO.setCouponMoney(bigDecimal);
+            remarkDTO.setOrderId(fsIntegralOrder.getOrderCode());
+            remarkDTO.setYdMoney(bigDecimal);
+            if (fsIntegralOrder.getCreateTime() != null) {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                String format = sdf.format(fsIntegralOrder.getCreateTime());
+                remarkDTO.setPayTime(format);
+            }
+            erpOrder.setSeller_memo(erpOrder.getSeller_memo() + JSONUtil.toJsonStr(remarkDTO));
+            erpOrder.setRemark(erpOrder.getRemark() + JSONUtil.toJsonStr(remarkDTO));
+            erpOrder.setOrder_type_code("order");
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            erpOrder.setDeal_datetime(sdf.format(new Date()));
+            erpOrder.setReceiver_name(fsIntegralOrder.getUserName().replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9]", ""));
+            if (fsIntegralOrder.getUserPhone().length() > 11) {
+                String phone = decryptPhone(fsIntegralOrder.getUserPhone());
+                erpOrder.setReceiver_mobile(phone);
+            } else {
+                erpOrder.setReceiver_mobile(fsIntegralOrder.getUserPhone());
+            }
+            if (StringUtils.isNotEmpty(fsIntegralOrder.getUserAddress())){
+                erpOrder.setReceiver_address(fsIntegralOrder.getUserAddress());
+            }
+//            String[] address = fsIntegralOrder.getUserAddress().split(" ");
+//            if (address.length < 3) {
+//                String kdnAddress = fsUserAddressService.getKdnAddress(fsIntegralOrder.getUserAddress());
+//                Map<String, Object> addDAta = (Map<String, Object>) JSON.parse(kdnAddress);
+//                Map<String, String> add = (Map<String, String>) addDAta.get("Data");
+//                erpOrder.setReceiver_province(add.get("ProvinceName"));
+//                erpOrder.setReceiver_city(add.get("CityName"));
+//                erpOrder.setReceiver_district(add.get("ExpAreaName"));
+//                erpOrder.setReceiver_address(add.get("StreetName") + add.get("Address"));
+//            } else {
+//                erpOrder.setReceiver_province(address[0]);
+//                erpOrder.setReceiver_city(address[1]);
+//                erpOrder.setReceiver_district(address[2]);
+//                //处理地址多空隔问题
+//                if (address.length > 3) {
+//                    StringBuffer addrs = new StringBuffer();
+//                    for (int i = 3; i < address.length; i++) {
+//                        addrs.append(address[i]);
+//                    }
+//                    erpOrder.setReceiver_address(addrs.toString());
+//                } else if (address.length == 3) {
+//                    erpOrder.setReceiver_address(address[2]);
+//                }
+//            }
+//            erpOrder.setReceiver_address(erpOrder.getReceiver_address().replace("+", "加"));
+//            erpOrder.setReceiver_address(erpOrder.getReceiver_address().replace("\n", ""));
+
+            // 处方图片生成
+//            String s = fsPrescribeService.PrescribeImg(order.getPrescribeId());
+//            erpOrder.setSeller_memo(erpOrder.getSeller_memo() + "||" + s + "||");
+//            erpOrder.setRemark(erpOrder.getRemark() + "||" + s + "||");
+            erpOrder.setShop_code(shopCode);
+            erpOrders.add(erpOrder);
+            fsIntegralOrderMapper.updateFsIntegralOrder(fsIntegralOrder);
+        }
+
+        ErpOrderResponse response = new ErpOrderResponse();
+        //推送聚水潭
+        IErpOrderService erpService = erpServiceMap.get(erpType);
+        response = erpService.batchAddIntegralCartOrder(erpOrders);
+        //写入日志
+    }
+
+    @Override
+    public void deliveryIntegralOrderOrder(String orderCode, String deliveryId, String deliverCode, String deliverName) {
+        FsIntegralOrder fsIntegralOrder = fsIntegralOrderMapper.selectFsIntegralOrderByOrderCode(orderCode);
+        if (fsIntegralOrder != null && fsIntegralOrder.getStatus() == 1) {
+            FsExpress express = expressService.selectFsExpressByOmsCode(deliverCode);
+            if (express != null) {
+                fsIntegralOrder.setDeliveryName(deliverName);
+                fsIntegralOrder.setDeliveryCode(express.getCode());
+            }
+            fsIntegralOrder.setStatus(2);
+            fsIntegralOrder.setDeliverySn(deliveryId);
+            fsIntegralOrder.setDeliveryTime(DateUtils.getNowDate());
+            fsIntegralOrderMapper.updateFsIntegralOrder(fsIntegralOrder);
+//            fsStoreOrderLogsService.create(order.getOrderId(), FsStoreOrderLogEnum.DELIVERY_GOODS.getValue(), FsStoreOrderLogEnum.DELIVERY_GOODS.getDesc());
+//            if (order.getCompanyId() != null && order.getCompanyId() > 0) {
+//                companyService.subtractCompanyMoney(order);
+//            }
+
+//            FsStore store = fsStoreMapper.selectFsStoreByStoreId(order.getStoreId());
+//            //订阅物流回调
+//            String lastFourNumber = "";
+//            if (order.getDeliveryCode().equals(ShipperCodeEnum.SF.getValue())) {
+//                if (store != null && store.getSendPhone() != null) {
+//                    lastFourNumber = store.getSendPhone();
+//                } else {
+//                    lastFourNumber = order.getUserPhone();
+//                }
+//                if (lastFourNumber.length() == 11) {
+//                    lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
+//                }
+//            }
+            expressService.subscribeEspress(fsIntegralOrder.getOrderCode(), fsIntegralOrder.getDeliveryCode(), fsIntegralOrder.getDeliverySn(), fsIntegralOrder.getUserPhone());
+//            List<FsStorePayment> fsStorePayments;
+
+            // 同步微信物流
+//            if (order.getPackageOrderId()!= null){
+//                fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentByPackageOrderId(String.valueOf(order.getPackageOrderId()));
+//            } else {
+//                fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentByOrderId(order.getOrderId().toString());
+//            }
+//
+//            if(CollectionUtils.isNotEmpty(fsStorePayments)){
+//                FsStorePayment fsStorePayment = fsStorePayments.get(0);
+//                FsWxExpressTask fsWxExpressTask = new FsWxExpressTask();
+//                fsWxExpressTask.setUserId(order.getUserId());
+//                fsWxExpressTask.setStatus(0);
+//                fsWxExpressTask.setRetryCount(0);
+//                fsWxExpressTask.setCreateTime(LocalDateTime.now());
+//                fsWxExpressTask.setUpdateTime(LocalDateTime.now());
+//                fsWxExpressTask.setOrderCode(order.getOrderCode());
+//                fsWxExpressTask.setExpressCompany(express.getCode());
+//                fsWxExpressTask.setExpressNo(deliveryId);
+//                fsWxExpressTask.setAppid(fsStorePayment.getAppid());
+//                fsWxExpressTaskMapper.insert(fsWxExpressTask);
+//            }
+
+        }
+    }
+
     /**
      * 处理手机号脱敏
      */

+ 1 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java

@@ -573,6 +573,7 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService {
                 request.setOrdAmt(reMoney.toString());
                 request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
                 request.setReqSeqId("refund-" + payment.getPayCode());
+                request.setAppId(payment.getAppId());
                 Map<String, Object> extendInfoMap = new HashMap<>();
                 extendInfoMap.put("org_req_seq_id", orderType + "-" + payment.getPayCode());
 

+ 259 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java

@@ -314,6 +314,8 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
     private FsUserInformationCollectionMapper fsUserInformationCollectionMapper;
     @Autowired
     private OpenIMService openIMService;
+    @Autowired
+    private IErpOrderService erpService;
 
     //ERP 类型到服务的映射
     private Map<Integer, IErpOrderService> erpServiceMap;
@@ -4637,4 +4639,261 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
         return i;
     }
 
+    @Override
+    public void createJSTOmsOrder(List<Long> orderIds) throws Exception {
+        // 1. 检查 ERP 是否开启
+        FsSysConfig sysConfig = configUtil.getSysConfig();
+        Integer erpOpen = sysConfig.getErpOpen();
+        if (erpOpen == null || erpOpen == 0) {
+            log.info("ERP未开启,跳过同步");
+            return;
+        }
+        Integer erpType = sysConfig.getErpType();
+        if (erpType == null || !erpServiceMap.containsKey(erpType)) {
+            log.info("ERP类型配置无效: {}", erpType);
+            return;
+        }
+        for (Long orderId : orderIds) {
+            FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderByOrderId(orderId);
+            if (order != null && StringUtils.isEmpty(order.getExtendOrderId()) && order.getStatus() != 2) {
+                return;
+            }
+            if (order == null) {
+                return;
+            }
+            ErpOrder erpOrder = new ErpOrder();
+            if (order.getCompanyId() != null) {
+                erpOrder.setVip_code(order.getUserId().toString() + order.getCompanyId().toString());
+            } else {
+                erpOrder.setVip_code(order.getUserId().toString());
+            }
+            erpOrder.setPlatform_code(order.getOrderCode());
+//        if(order.getStoreHouseCode()==null){
+//            erpOrder.setWarehouse_code("CQDS001");
+//        }else{
+//            erpOrder.setWarehouse_code(order.getStoreHouseCode());
+//        }
+//            FsSysConfig sysConfig = configUtil.getSysConfig();
+            FsStore fsStore = fsStoreMapper.selectFsStoreByStoreId(order.getStoreId());
+            erpOrder.setShop_code(fsStore.getShopCode());
+            erpOrder.setSeller_memo(order.getRemark());
+            List<ErpOrderPayment> payments = new ArrayList<>();
+            ErpOrderPayment payment = new ErpOrderPayment();
+            payment.setPay_type_code("weixin");
+            payment.setPayment(order.getPayMoney().doubleValue());
+
+            erpOrder.setBuyer_account(order.getUserName());
+            erpOrder.setRemark(order.getRemark());
+            if (order.getPayTime() != null) {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                String timeString = sdf.format(order.getPayTime());
+                Date date = sdf.parse(timeString); // 时间格式转为时间戳
+                long timeLong = date.getTime();
+                payment.setPaytime(new Timestamp(timeLong));
+            }
+            payments.add(payment);
+
+
+            //物流代收都发 互联网医院顺丰
+            if (order.getPayRemain().compareTo(new BigDecimal(0)) == 0) {
+                //没有物流代收
+                //大于100发发顺丰云配
+                if (order.getPayMoney().compareTo(new BigDecimal(100)) > 0) {
+                    //发互联网医院SF.0235488558_241101
+                    FsExpress express = expressService.selectFsExpressByOmsCode("SF.0235488558_241101");
+                    erpOrder.setExpress_code(express.getOmsCode());
+                    order.setDeliveryName(express.getName());
+                    order.setDeliveryCode(express.getCode());
+                } else {
+                    //发ztpdd
+                    FsExpress express = expressService.selectFsExpressByOmsCode("CDYJFYD.400011111705_241230");
+                    if(express != null){
+                        erpOrder.setExpress_code(express.getOmsCode());
+                        order.setDeliveryName(express.getName());
+                        order.setDeliveryCode(express.getCode());
+                    }
+                }
+            } else {
+                FsExpress express = new FsExpress();
+                if (order.getCompanyId() != null) {
+                    Company company = companyService.selectCompanyById(order.getCompanyId());
+                    if (company != null && StringUtils.isNotEmpty(company.getOmsCode())) {
+                        express = expressService.selectFsExpressByOmsCode(company.getOmsCode());
+                    } else {
+                        express = expressService.selectFsExpressByOmsCode("SF.0235469535");
+                    }
+                } else {
+                    express = expressService.selectFsExpressByOmsCode("SF.0235469535");
+                }
+                //物流代发互联网医院顺
+                erpOrder.setExpress_code(express.getOmsCode());
+                order.setDeliveryName(express.getName());
+                order.setDeliveryCode(express.getCode());
+                //物流代收金额
+                ErpOrderPayment codPayment = new ErpOrderPayment();
+                codPayment.setPay_type_code("cod");
+                BigDecimal toal = order.getPayRemain();
+                codPayment.setPayment(toal.doubleValue());
+                payments.add(codPayment);
+                erpOrder.setCod(true);
+
+            }
+
+            erpOrder.setPayments(payments);
+            if (order.getCompanyId() != null) {
+                Company company = companyService.selectCompanyById(order.getCompanyId());
+                if (company != null) {
+                    erpOrder.setSeller_memo(company.getCompanyName());
+                    erpOrder.setRemark(company.getCompanyName());
+                }
+            }
+            if (order.getCompanyUserId() != null) {
+                CompanyUser companyUser = companyUserService.selectCompanyUserById(order.getCompanyUserId());
+                if (companyUser != null) {
+                    CompanyDept dept = companyDeptService.selectCompanyDeptById(companyUser.getDeptId());
+                    if (dept != null) {
+                        List<String> names = companyDeptService.selectCompanyDeptNamesByIds(dept.getAncestors());
+                        if (names != null && names.size() > 0) {
+                            //写备注
+                            erpOrder.setSeller_memo(erpOrder.getSeller_memo() + "-" + StringUtils.join(names, ",") + "," + dept.getDeptName());
+                            erpOrder.setRemark(erpOrder.getRemark() + "-" + StringUtils.join(names, ",") + "," + dept.getDeptName());
+                        }
+                    }
+                    erpOrder.setSeller_memo(erpOrder.getSeller_memo() + "-" + companyUser.getNickName());
+                    erpOrder.setRemark(erpOrder.getRemark() + "-" + companyUser.getNickName());
+                }
+            }
+
+            ErpRemarkDTO remarkDTO = new ErpRemarkDTO();
+            remarkDTO.setTotalPrice(order.getTotalPrice());
+            remarkDTO.setPayPrice(order.getPayPrice());
+            remarkDTO.setDeliveryMoney(order.getPayDelivery());
+            remarkDTO.setPayMoney(order.getPayMoney());
+            remarkDTO.setCouponMoney(order.getDiscountMoney());
+            remarkDTO.setOrderId(order.getOrderCode());
+            remarkDTO.setYdMoney(order.getPayPrice().subtract(order.getPayMoney().subtract(order.getPayDelivery())));
+            if (order.getPayTime() != null) {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                String format = sdf.format(order.getPayTime());
+                remarkDTO.setPayTime(format);
+            }
+            erpOrder.setSeller_memo(erpOrder.getSeller_memo() + JSONUtil.toJsonStr(remarkDTO));
+            erpOrder.setRemark(erpOrder.getRemark() + JSONUtil.toJsonStr(remarkDTO));
+            erpOrder.setOrder_type_code("order");
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            erpOrder.setDeal_datetime(sdf.format(new Date()));
+            FsStoreOrderItem itemMap = new FsStoreOrderItem();
+            itemMap.setOrderId(order.getOrderId());
+            List<FsStoreOrderItem> orderItems = storeOrderItemService.selectFsStoreOrderItemList(itemMap);
+            List<ErpOrderItem> details = new ArrayList<>();
+            for (FsStoreOrderItem orderItem : orderItems) {
+                FsStoreCartDTO cartDTO = JSONUtil.toBean(orderItem.getJsonInfo(), FsStoreCartDTO.class);
+                ErpOrderItem item = new ErpOrderItem();
+                item.setItem_code(cartDTO.getBarCode().trim());
+                item.setPrice(cartDTO.getPrice().toString());
+                item.setQty(cartDTO.getNum());
+                item.setRefund(0);
+                details.add(item);
+            }
+            erpOrder.setDetails(details);
+            erpOrder.setReceiver_name(order.getUserName().replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9]", ""));
+            if (order.getUserPhone().length() > 11) {
+                String phone = decryptPhone(order.getUserPhone());
+                erpOrder.setReceiver_mobile(phone);
+            } else {
+                erpOrder.setReceiver_mobile(order.getUserPhone());
+            }
+
+            String[] address = order.getUserAddress().split(" ");
+            if (address.length < 3) {
+                String kdnAddress = fsUserAddressService.getKdnAddress(order.getUserAddress());
+                Map<String, Object> addDAta = (Map<String, Object>) JSON.parse(kdnAddress);
+                Map<String, String> add = (Map<String, String>) addDAta.get("Data");
+                erpOrder.setReceiver_province(add.get("ProvinceName"));
+                erpOrder.setReceiver_city(add.get("CityName"));
+                erpOrder.setReceiver_district(add.get("ExpAreaName"));
+                erpOrder.setReceiver_address(add.get("StreetName") + add.get("Address"));
+            } else {
+                erpOrder.setReceiver_province(address[0]);
+                erpOrder.setReceiver_city(address[1]);
+                erpOrder.setReceiver_district(address[2]);
+                //处理地址多空隔问题
+                if (address.length > 3) {
+                    StringBuffer addrs = new StringBuffer();
+                    for (int i = 3; i < address.length; i++) {
+                        addrs.append(address[i]);
+                    }
+                    erpOrder.setReceiver_address(addrs.toString());
+                } else if (address.length == 3) {
+                    erpOrder.setReceiver_address(address[2]);
+                }
+            }
+            erpOrder.setReceiver_address(erpOrder.getReceiver_address().replace("+", "加"));
+            erpOrder.setReceiver_address(erpOrder.getReceiver_address().replace("\n", ""));
+
+            // 处方图片生成
+//            String s = fsPrescribeService.PrescribeImg(order.getPrescribeId());
+//            erpOrder.setSeller_memo(erpOrder.getSeller_memo() + "||" + s + "||");
+//            erpOrder.setRemark(erpOrder.getRemark() + "||" + s + "||");
+//            erpOrder.setShop_code(fsStore.getShopCode());
+            fsStoreOrderMapper.updateFsStoreOrder(order);
+            //推送聚水潭
+            // 5. 调用对应 ERP 服务(当前是聚水潭ERP)
+            IErpOrderService erpService = erpServiceMap.get(erpType);
+            erpService.addOrder(erpOrder);
+        }
+    }
+
+    @Override
+    public void deliveryOrderItem(String orderCode, String deliveryId, String deliverCode, String deliverName, String itemOrderCode) {
+        FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderByOrderCode(orderCode);
+        List<FsStoreOrderItem> fsStoreOrderItemByOrderCode = fsStoreOrderItemMapper.getFsStoreOrderItemByOrderCode(itemOrderCode);
+        if (null == fsStoreOrderItemByOrderCode || fsStoreOrderItemByOrderCode.isEmpty()) {
+            return;
+        }
+        FsStoreOrderItem firstItem = fsStoreOrderItemByOrderCode.get(0);
+        FsExpress express = expressService.selectFsExpressByOmsCode(deliverCode);
+        if (express != null) {
+            firstItem.setDeliveryName(deliverName);
+            firstItem.setDeliveryCode(express.getCode());
+
+        }
+        firstItem.setDeliverySn(deliveryId);
+        firstItem.setDeliveryTime(DateUtils.getNowDate());
+        fsStoreOrderItemMapper.updateFsStoreOrderItemBatch(firstItem);
+        //订阅物流回调
+        FsStore store = fsStoreMapper.selectFsStoreByStoreId(order.getStoreId());
+        String lastFourNumber = "";
+        if (order.getDeliveryCode().equals(ShipperCodeEnum.SF.getValue())) {
+            if (store != null && store.getSendPhone() != null) {
+                lastFourNumber = store.getSendPhone();
+            } else {
+                lastFourNumber = order.getUserPhone();
+            }
+            if (lastFourNumber.length() == 11) {
+                lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
+            }
+        }
+        expressService.subscribeEspress(firstItem.getOrderCode(), firstItem.getDeliveryCode(), firstItem.getDeliverySn(), lastFourNumber);
+
+        if (order != null && order.getStatus() == 2) {
+            //ai向客户发送发货物流信息
+            requestExpressInfo(order.getOrderId());
+
+            if (express != null) {
+                order.setDeliveryName(deliverName);
+                order.setDeliveryCode(express.getCode());
+            }
+            order.setStatus(3);
+            order.setDeliverySn(deliveryId);
+            order.setDeliverySendTime(DateUtils.getNowDate());
+            fsStoreOrderMapper.updateFsStoreOrder(order);
+            fsStoreOrderLogsService.create(order.getOrderId(), FsStoreOrderLogEnum.DELIVERY_GOODS.getValue(), FsStoreOrderLogEnum.DELIVERY_GOODS.getDesc());
+            if (order.getCompanyId() != null && order.getCompanyId() > 0) {
+                companyService.subtractCompanyMoney(order);
+            }
+//            expressService.subscribeEspress(order.getOrderCode(), order.getDeliveryCode(), order.getDeliverySn(), lastFourNumber);
+        }
+    }
+
 }

+ 6 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java

@@ -1864,4 +1864,10 @@ public class FsUserServiceImpl implements IFsUserService {
         return fsUserMapper.updateFsUser(fsUser)>0;
     }
 
+    @Override
+    public R updatePasswordByPhone(String password, String encryptPhone) {
+        fsUserMapper.updatePasswordByPhone(password, encryptPhone);
+        return R.ok();
+    }
+
 }

+ 5 - 1
fs-service/src/main/resources/mapper/his/FsStoreMapper.xml

@@ -34,10 +34,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="refundConsignee"    column="refund_consignee"    />
         <result property="deliveryType"    column="delivery_type"    />
         <result property="sendPhone"    column="send_phone"    />
+        <result property="shopCode"    column="shop_code"    />
     </resultMap>
 
     <sql id="selectFsStoreVo">
-        select store_id,full_name,delivery_type,send_phone, brokerage_rate,refund_phone,refund_address,refund_consignee,city_ids, store_name, descs, brokerage_type,logo_url, address, lng, lat, phone, license_images, product_count, status, create_time, update_time, sales_count, balance, total_money, is_audit, account, password, shipping_type from fs_store
+        select store_id,full_name,delivery_type,send_phone, brokerage_rate,refund_phone,refund_address,refund_consignee,city_ids, store_name, descs, brokerage_type,logo_url, address, lng, lat, phone, license_images, product_count, status, create_time, update_time, sales_count, balance, total_money, is_audit, account, password, shipping_type, shop_code from fs_store
     </sql>
 
     <select id="selectFsStoreList" parameterType="FsStore" resultMap="FsStoreResult">
@@ -89,6 +90,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="refundConsignee != null">refund_consignee,</if>
             <if test="deliveryType != null">delivery_type,</if>
             <if test="sendPhone != null">send_phone,</if>
+            <if test="shopCode != null">shop_code,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="cityIds != null">#{cityIds},</if>
@@ -119,6 +121,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="refundConsignee != null">#{refundConsignee},</if>
             <if test="deliveryType != null">#{deliveryType},</if>
             <if test="sendPhone != null">#{sendPhone},</if>
+            <if test="shopCode != null">#{shopCode},</if>
         </trim>
     </insert>
 
@@ -153,6 +156,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="refundConsignee != null">refund_consignee = #{refundConsignee},</if>
             <if test="deliveryType != null">delivery_type = #{deliveryType},</if>
             <if test="sendPhone != null">send_phone = #{sendPhone},</if>
+            <if test="shopCode != null">shop_code = #{shopCode},</if>
         </trim>
         where store_id = #{storeId}
     </update>

+ 41 - 0
fs-service/src/main/resources/mapper/his/FsStoreOrderItemMapper.xml

@@ -62,6 +62,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="storeId != null">store_id,</if>
             <if test="isGift != null">is_gift,</if>
             <if test="isDrug != null">is_drug,</if>
+            <if test="orderCode != null">order_code,</if>
+            <if test="extendOrderId != null">extend_order_id,</if>
+            <if test="deliveryCode != null">delivery_code,</if>
+            <if test="deliveryName != null">delivery_name,</if>
+            <if test="deliverySn != null">delivery_sn,</if>
+            <if test="deliveryTime != null">delivery_time,</if>
+            <if test="batchNum != null">batch_num,</if>
+            <if test="expectDeliveryTime != null">expect_delivery_time,</if>
+            <if test="splitOrderItemJson != null">split_order_item_json,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="orderId != null and orderId != ''">#{orderId},</if>
@@ -75,6 +84,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="storeId != null">#{storeId},</if>
             <if test="isGift != null">#{isGift},</if>
             <if test="isDrug != null">#{isDrug},</if>
+            <if test="orderCode != null">#{orderCode},</if>
+            <if test="extendOrderId != null">#{extendOrderId},</if>
+            <if test="deliveryCode != null">#{deliveryCode},</if>
+            <if test="deliveryName != null">#{deliveryName},</if>
+            <if test="deliverySn != null">#{deliverySn},</if>
+            <if test="deliveryTime != null">#{deliveryTime},</if>
+            <if test="batchNum != null">#{batchNum},</if>
+            <if test="expectDeliveryTime != null">#{expectDeliveryTime},</if>
+            <if test="splitOrderItemJson != null">#{splitOrderItemJson},</if>
         </trim>
     </insert>
 
@@ -92,9 +110,32 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="storeId != null">store_id = #{storeId},</if>
             <if test="isGift != null">is_gift = #{isGift},</if>
             <if test="isDrug != null">is_drug = #{isDrug},</if>
+            <if test="orderCode != null">order_code = #{orderCode},</if>
+            <if test="extendOrderId != null">extend_order_id = #{extendOrderId},</if>
+            <if test="deliveryCode != null">delivery_code = #{deliveryCode},</if>
+            <if test="deliveryName != null">delivery_name = #{deliveryName},</if>
+            <if test="deliverySn != null">delivery_sn = #{deliverySn},</if>
+            <if test="deliveryTime != null">delivery_time = #{deliveryTime},</if>
+            <if test="batchNum != null">batch_num = #{batchNum},</if>
+            <if test="expectDeliveryTime != null">expect_delivery_time = #{expectDeliveryTime},</if>
+            <if test="splitOrderItemJson != null">split_order_item_json = #{splitOrderItemJson},</if>
         </trim>
         where item_id = #{itemId}
     </update>
+    <update id="updateFsStoreOrderItemBatch">
+        update fs_store_order_item
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="extendOrderId != null and extendOrderId != ''">extend_order_id = #{extendOrderId},</if>
+            <if test="deliveryCode != null and deliveryCode != ''">delivery_code = #{deliveryCode},</if>
+            <if test="deliveryName != null and deliveryName != ''">delivery_name = #{deliveryName},</if>
+            <if test="deliverySn != null and deliverySn != '' ">delivery_sn = #{deliverySn},</if>
+            <if test="deliveryTime != null">delivery_time = #{deliveryTime},</if>
+            <if test="deliveryStatus != null">delivery_status = #{deliveryStatus},</if>
+            <if test="deliveryType != null">delivery_type = #{deliveryType},</if>
+            <if test="deliveryUpdateTime != null">delivery_update_time = #{deliveryUpdateTime},</if>
+        </trim>
+        where order_code = #{orderCode}
+    </update>
 
     <delete id="deleteFsStoreOrderItemByItemId" parameterType="String">
         delete from fs_store_order_item where item_id = #{itemId}

+ 3 - 0
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -752,6 +752,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             user_id = #{userId}
         </foreach>
     </update>
+    <update id="updatePasswordByPhone">
+        update fs_user set password = #{password} where phone = #{encryptPhone}
+    </update>
 
     <select id="selectUserListByMap" resultType="com.fs.his.vo.OptionsVO">
         select

+ 198 - 4
fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java

@@ -1,13 +1,17 @@
 package com.fs.app.controller;
 
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateTime;
 import com.fs.app.annotation.Login;
 import com.fs.app.param.*;
 import com.fs.app.utils.WxUtil;
+import com.fs.common.VerifyCodeUtil;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.exception.ServiceException;
+import com.fs.common.service.ISmsService;
 import com.fs.common.utils.sign.Md5Utils;
 import com.fs.core.config.WxOpenProperties;
 import com.fs.his.config.FsSysConfig;
@@ -34,15 +38,15 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
 import java.time.LocalDateTime;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 import static com.fs.his.utils.PhoneUtil.encryptPhone;
 
+
 @Api("app登录接口")
 @RestController
 @RequestMapping(value="/app/app")
@@ -60,6 +64,9 @@ public class AppLoginController extends AppBaseController{
 
     @Autowired
     private RedisCache redisCache;
+
+    @Autowired
+    private ISmsService smsService;
     @ApiOperation("注册app用户")
     @PostMapping("/register")
     @RepeatSubmit
@@ -424,4 +431,191 @@ public class AppLoginController extends AppBaseController{
             return R.error("用户不存在!");
         }
     }
+
+    @PostMapping("/sendCode")
+    public R sendCode(@RequestBody Map<String, String> body){
+        String phone = body.get("phone");
+        String encryptPhone = encryptPhone(phone);
+        List<FsUser> user = userService.selectFsUserListByPhone(encryptPhone);
+        if(CollectionUtil.isEmpty(user)){
+            user = userService.selectFsUserListByPhone(encryptPhoneOldKey(phone));
+        }
+        if (CollectionUtil.isEmpty(user)){
+            return R.error("此电话号码未绑定用户");
+        }
+
+        // 验证码 key(3分钟有效)
+        String smsCodeKey = "sms:code:" + phone;
+        // 冷却 key(60秒内不能重复发送)
+        String smsCooldownKey = "sms:cooldown:" + phone;
+
+        // 判断是否在 60 秒冷却期
+        if (redisCache.getCacheObject(smsCooldownKey) != null) {
+            return R.error("验证码已发送,请稍后再试");
+        }
+
+        // 生成新验证码
+        String smsCode = VerifyCodeUtil.generateCode();
+
+        // 发送短信
+        smsService.sendCaptcha(phone, smsCode, "验证码");
+
+        // 缓存验证码(3分钟有效)
+        redisCache.setCacheObject(smsCodeKey, smsCode, 180, TimeUnit.SECONDS);
+        // 设置冷却时间(60秒内不能再发)
+        redisCache.setCacheObject(smsCooldownKey, "1", 60, TimeUnit.SECONDS);
+
+        return R.ok("验证码已发送");
+    }
+
+    /**
+     * 用于查询 使用老的数据加密
+     * @param text
+     * @return
+     */
+    private static String OLD_KEY = "2c8d1a7f4e9b3c6ae6d5c4b3a291f8c9";
+    public static String encryptPhoneOldKey(String text) {
+        String encryptedText=null;
+        try {
+            SecretKeySpec secretKey = new SecretKeySpec(OLD_KEY.getBytes(), "AES");
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+            // Encryption
+            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+            byte[] encryptedBytes = cipher.doFinal(text.getBytes());
+            encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return encryptedText;
+    }
+
+    @PostMapping("/loginByPhone")
+    public R loginByPhone(@RequestBody Map<String,String> map){
+        String phone = map.get("phone");
+        String code = map.get("code");
+        String encryptPhone = encryptPhone(phone);
+        List<FsUser> user = userService.selectFsUserListByPhone(encryptPhone);
+        if (CollectionUtil.isEmpty(user)){
+            user = userService.selectFsUserListByPhone(encryptPhoneOldKey(phone));
+        }
+        if (CollectionUtil.isEmpty(user)){
+            return R.error("此电话号码未绑定用户");
+        }
+        if (user.size()>1){
+            //如果出现了一个手机号多个用户的情况,找出登陆过app的那个用户
+            user.removeIf(fsUser -> StringUtils.isEmpty(fsUser.getHistoryApp()));
+        }
+        String redisCode = redisCache.getCacheObject("sms:code:" + phone);
+        if (StringUtils.isEmpty(redisCode)){
+            return R.error("验证码已过期,请重新发送");
+        }
+        if (!redisCode.equals(code)) {
+            return R.error("验证码错误");
+        }
+        updateExistingUserJpushId(user.get(0), map.get("jpushId"));
+        return generateTokenAndReturn(user.get(0));
+    }
+
+    @PostMapping("/registerSendCode")
+    public R registerSendCode(@RequestBody Map<String, String> body){
+        String phone = body.get("phone");
+        String encryptPhone = encryptPhone(phone);
+        List<FsUser> user = userService.selectFsUserListByPhone(encryptPhone);
+        if(CollectionUtil.isEmpty(user)){
+            user = userService.selectFsUserListByPhone(encryptPhoneOldKey(phone));
+        }
+        if (!CollectionUtil.isEmpty(user)){
+            return R.error("此电话号码已注册");
+        }
+
+        // 验证码 key(存验证码,3分钟有效)
+        String smsCodeKey = "sms:code:" + phone;
+        // 发送冷却 key(限制60秒内不能再次发送)
+        String smsCooldownKey = "sms:cooldown:" + phone;
+
+        // 判断是否在60秒冷却时间内
+        if (redisCache.getCacheObject(smsCooldownKey) != null) {
+            return R.error("验证码已发送,请稍后再试");
+        }
+
+        // 生成新的验证码
+        String smsCode = VerifyCodeUtil.generateCode();
+
+        // 发送短信
+        smsService.sendCaptcha(phone, smsCode, "验证码");
+
+        // 缓存验证码(3分钟有效)
+        redisCache.setCacheObject(smsCodeKey, smsCode, 180, TimeUnit.SECONDS);
+        // 设置冷却时间(60秒内不能再发)
+        redisCache.setCacheObject(smsCooldownKey, "1", 60, TimeUnit.SECONDS);
+
+        return R.ok("验证码已发送");
+    }
+
+    @PostMapping("/registerByPhone")
+    public R registerByPhone(@RequestBody Map<String,String> map){
+        String phone = map.get("phone");
+        String code = map.get("code");
+        String password = map.get("password");
+        String encryptPhone = encryptPhone(phone);
+        List<FsUser> users = userService.selectFsUserListByPhone(encryptPhone);
+        if (users == null || CollectionUtil.isEmpty(users)){
+            String s = encryptPhoneOldKey(phone);
+            users = userService.selectFsUserListByPhone(s);
+        }
+        if (!CollectionUtil.isEmpty(users)){
+            return R.error("此账号已经注册");
+        }
+        String redisCode = redisCache.getCacheObject("sms:code:" + phone);
+        if (StringUtils.isEmpty(redisCode)){
+            return R.error("验证码已过期,请重新发送");
+        }
+        if (!redisCode.equals(code)) {
+            return R.error("验证码错误");
+        }
+        FsUser user = new FsUser();
+        // 创建新用户
+        user.setPhone(phone);
+        user.setJpushId(map.get("jpushId"));
+        user.setSource(map.get("source"));
+        user.setNickName("app用户" + phone.substring(phone.length() - 4));
+        user.setStatus(1);
+        user.setAvatar("https://cos.his.cdwjyyh.com/fs/20240926/420728ee06e54575ba82665dedb4756b.png");
+        user.setPassword(Md5Utils.hash(password));
+        user.setCreateTime(new Date());
+        if (userService.insertFsUser(user) > 0) {
+            return R.ok("注册成功");
+        } else {
+            return R.error("注册失败");
+        }
+    }
+
+    @PostMapping("/resetPassword")
+    public R resetPassword(@RequestBody Map<String, String> body){
+        String phone = body.get("phone");
+        String code = body.get("code");
+        String newPassword = body.get("newPassword");
+        String confirmPassword = body.get("confirmPassword");
+        if (!newPassword.equals(confirmPassword)){
+            throw new ServiceException("两次输入密码不一致,请检查");
+        }
+        String encryptPhone = encryptPhone(phone);
+        List<FsUser> user = userService.selectFsUserListByPhone(encryptPhone);
+        if (CollectionUtil.isEmpty(user)){
+            user = userService.selectFsUserListByPhone(encryptPhoneOldKey(phone));
+        }
+        if (CollectionUtil.isEmpty(user)){
+            return R.error("此电话号码未绑定用户");
+        }
+        String redisCode = redisCache.getCacheObject("sms:code:" + phone);
+        if (StringUtils.isEmpty(redisCode)){
+            return R.error("验证码已过期,请重新发送");
+        }
+        if (!redisCode.equals(code)) {
+            return R.error("验证码错误");
+        }
+        String password = Md5Utils.hash(newPassword);
+        return userService.updatePasswordByPhone(password,encryptPhone);
+    }
+
 }

+ 16 - 0
fs-user-app/src/main/java/com/fs/app/controller/CommonController.java

@@ -36,6 +36,7 @@ import com.fs.event.TemplateEvent;
 import com.fs.event.TemplateListenEnum;
 import com.fs.event.WeixinTemplateService;
 import com.fs.framework.config.ServerConfig;
+import com.fs.his.config.FsSmsConfig;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.*;
 import com.fs.his.param.FsInquiryOrderFinishParam;
@@ -625,4 +626,19 @@ public class CommonController {
 			return "您已取消订阅授权";
 		}
 	}
+    @GetMapping(value = "/isSmsVerification")
+    @ApiOperation("获取app是否短信验证配置")
+    public R isSmsVerification()
+    {
+        String config=configService.selectConfigByKey("his.sms");
+        if (StringUtils.isBlank(config)){
+            return  R.ok().put("isSmsVerification",0);
+        }
+        FsSmsConfig sms = JSON.parseObject(config, FsSmsConfig.class);
+        if (sms != null && sms.getIsSmsVerification() != null){
+            return R.ok().put("isSmsVerification",sms.getIsSmsVerification());
+        }
+        return  R.ok().put("isSmsVerification",0);
+
+    }
 }