24282 1 vuosi sitten
vanhempi
commit
9d7af02cdd
48 muutettua tiedostoa jossa 1877 lisäystä ja 6 poistoa
  1. 1 1
      code-generation/pom.xml
  2. 9 2
      pom.xml
  3. 1 1
      sd-business/pom.xml
  4. 38 0
      sd-business/src/main/java/com/sd/business/controller/sku/SkuClassifyController.java
  5. 71 0
      sd-business/src/main/java/com/sd/business/controller/sku/SkuController.java
  6. 71 0
      sd-business/src/main/java/com/sd/business/controller/sku/SkuSpecController.java
  7. 17 0
      sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuClassifyDto.java
  8. 22 0
      sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuClassifySelectDto.java
  9. 17 0
      sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuDto.java
  10. 17 0
      sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuSelectDto.java
  11. 17 0
      sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuSpecDto.java
  12. 17 0
      sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuSpecSelectDto.java
  13. 96 0
      sd-business/src/main/java/com/sd/business/entity/sku/po/Sku.java
  14. 46 0
      sd-business/src/main/java/com/sd/business/entity/sku/po/SkuClassify.java
  15. 113 0
      sd-business/src/main/java/com/sd/business/entity/sku/po/SkuSpec.java
  16. 25 0
      sd-business/src/main/java/com/sd/business/entity/sku/vo/SkuClassifyVo.java
  17. 17 0
      sd-business/src/main/java/com/sd/business/entity/sku/vo/SkuSpecVo.java
  18. 17 0
      sd-business/src/main/java/com/sd/business/entity/sku/vo/SkuVo.java
  19. 16 0
      sd-business/src/main/java/com/sd/business/mapper/sku/SkuClassifyMapper.java
  20. 16 0
      sd-business/src/main/java/com/sd/business/mapper/sku/SkuMapper.java
  21. 16 0
      sd-business/src/main/java/com/sd/business/mapper/sku/SkuSpecMapper.java
  22. 26 0
      sd-business/src/main/java/com/sd/business/service/sku/SkuClassifyService.java
  23. 46 0
      sd-business/src/main/java/com/sd/business/service/sku/SkuService.java
  24. 46 0
      sd-business/src/main/java/com/sd/business/service/sku/SkuSpecService.java
  25. 39 0
      sd-business/src/main/java/com/sd/business/service/sku/impl/SkuClassifyServiceImpl.java
  26. 68 0
      sd-business/src/main/java/com/sd/business/service/sku/impl/SkuServiceImpl.java
  27. 68 0
      sd-business/src/main/java/com/sd/business/service/sku/impl/SkuSpecServiceImpl.java
  28. 5 0
      sd-business/src/main/resources/mapper/sku/SkuClassifyMapper.xml
  29. 5 0
      sd-business/src/main/resources/mapper/sku/SkuMapper.xml
  30. 5 0
      sd-business/src/main/resources/mapper/sku/SkuSpecMapper.xml
  31. 1 1
      sd-framework/pom.xml
  32. 11 0
      sd-framework/src/main/java/com/sd/framework/util/tree/Tree.java
  33. 9 0
      sd-framework/src/main/java/com/sd/framework/util/tree/TreeId.java
  34. 63 0
      sd-framework/src/main/java/com/sd/framework/util/tree/TreeUtil.java
  35. 6 1
      sd-starter/pom.xml
  36. 29 0
      sd-wln/pom.xml
  37. 20 0
      sd-wln/src/main/java/com/sd/wln/constants/WlnConstant.java
  38. 35 0
      sd-wln/src/main/java/com/sd/wln/controller/WlnController.java
  39. 38 0
      sd-wln/src/main/java/com/sd/wln/entity/GoodsSpecParam.java
  40. 15 0
      sd-wln/src/main/java/com/sd/wln/entity/ResynchronizationDto.java
  41. 75 0
      sd-wln/src/main/java/com/sd/wln/entity/Signature.java
  42. 15 0
      sd-wln/src/main/java/com/sd/wln/entity/SkuClassifyParam.java
  43. 56 0
      sd-wln/src/main/java/com/sd/wln/entity/StockParam.java
  44. 90 0
      sd-wln/src/main/java/com/sd/wln/entity/TradesParam.java
  45. 34 0
      sd-wln/src/main/java/com/sd/wln/scheduled/WlnSyncTask.java
  46. 7 0
      sd-wln/src/main/java/com/sd/wln/service/WlnSkuService.java
  47. 198 0
      sd-wln/src/main/java/com/sd/wln/service/impl/WlnSkuServiceImpl.java
  48. 207 0
      sd-wln/src/main/java/com/sd/wln/util/WlnUtil.java

+ 1 - 1
code-generation/pom.xml

@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.sd</groupId>
         <artifactId>sdhy_project</artifactId>
-        <version>1.0</version>
+        <version>2.0</version>
     </parent>
 
     <artifactId>code-generation</artifactId>

+ 9 - 2
pom.xml

@@ -6,7 +6,7 @@
 
     <groupId>com.sd</groupId>
     <artifactId>sdhy_project</artifactId>
-    <version>1.0</version>
+    <version>2.0</version>
 
     <packaging>pom</packaging>
 
@@ -14,7 +14,7 @@
         <maven.compiler.source>8</maven.compiler.source>
         <maven.compiler.target>8</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <sd.version>1.0</sd.version>
+        <sd.version>2.0</sd.version>
         <base.version>1.0.2</base.version>
     </properties>
 
@@ -23,6 +23,7 @@
         <module>sd-framework</module>
         <module>sd-business</module>
         <module>code-generation</module>
+        <module>sd-wln</module>
     </modules>
 
     <parent>
@@ -53,6 +54,12 @@
                 <version>${sd.version}</version>
             </dependency>
 
+            <dependency>
+                <groupId>com.sd</groupId>
+                <artifactId>sd-wln</artifactId>
+                <version>${sd.version}</version>
+            </dependency>
+
         </dependencies>
     </dependencyManagement>
 

+ 1 - 1
sd-business/pom.xml

@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.sd</groupId>
         <artifactId>sdhy_project</artifactId>
-        <version>1.0</version>
+        <version>2.0</version>
     </parent>
 
     <artifactId>sd-business</artifactId>

+ 38 - 0
sd-business/src/main/java/com/sd/business/controller/sku/SkuClassifyController.java

@@ -0,0 +1,38 @@
+package com.sd.business.controller.sku;
+
+import com.sd.business.entity.sku.dto.SkuClassifySelectDto;
+import com.sd.business.entity.sku.vo.SkuClassifyVo;
+import com.sd.business.service.sku.SkuClassifyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+
+/**
+ * <p>
+ * sku分类 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@RestController
+@RequestMapping("/skuClassify")
+public class SkuClassifyController {
+
+    @Autowired
+    private SkuClassifyService skuClassifyService;
+
+    /**
+     * sku树形列表
+     */
+    @PostMapping("/tree")
+    public List<SkuClassifyVo> tree(@RequestBody SkuClassifySelectDto dto) {
+        return skuClassifyService.getTree(dto);
+    }
+
+}

+ 71 - 0
sd-business/src/main/java/com/sd/business/controller/sku/SkuController.java

@@ -0,0 +1,71 @@
+package com.sd.business.controller.sku;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import com.sd.business.entity.sku.dto.SkuDto;
+import com.sd.business.entity.sku.dto.SkuSelectDto;
+import com.sd.business.entity.sku.vo.SkuVo;
+import com.sd.business.service.sku.SkuService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * <p>
+ * sku 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@RestController
+@RequestMapping("/sku")
+public class SkuController {
+
+    @Autowired
+    private SkuService skuService;
+
+    /**
+     * sku分页
+     */
+    @PostMapping("/page")
+    public Page<SkuVo> page(@RequestBody SkuSelectDto dto) {
+        return skuService.getPage(dto);
+    }
+
+    /**
+     * sku明细
+     */
+    @PostMapping("/detail")
+    public SkuVo detail(@RequestBody BaseSelectDto dto) {
+        return skuService.detail(dto.getId());
+    }
+
+    /**
+     * sku新增
+     */
+    @PostMapping("/add")
+    public void add(@RequestBody SkuDto dto) {
+        skuService.add(dto);
+    }
+
+    /**
+     * sku编辑
+     */
+    @PostMapping("/edit")
+    public void edit(@RequestBody SkuDto dto) {
+        skuService.edit(dto);
+    }
+
+    /**
+     * sku删除
+     */
+    @PostMapping("/delete")
+    public void delete(@RequestBody BaseSelectDto dto) {
+        skuService.delete(dto.getId());
+    }
+
+}

+ 71 - 0
sd-business/src/main/java/com/sd/business/controller/sku/SkuSpecController.java

@@ -0,0 +1,71 @@
+package com.sd.business.controller.sku;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import com.sd.business.entity.sku.dto.SkuSpecDto;
+import com.sd.business.entity.sku.dto.SkuSpecSelectDto;
+import com.sd.business.entity.sku.vo.SkuSpecVo;
+import com.sd.business.service.sku.SkuSpecService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * <p>
+ * sku规格 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@RestController
+@RequestMapping("/skuSpec")
+public class SkuSpecController {
+
+    @Autowired
+    private SkuSpecService skuSpecService;
+
+    /**
+     * sku规格分页
+     */
+    @PostMapping("/page")
+    public Page<SkuSpecVo> page(@RequestBody SkuSpecSelectDto dto) {
+        return skuSpecService.getPage(dto);
+    }
+
+    /**
+     * sku规格明细
+     */
+    @PostMapping("/detail")
+    public SkuSpecVo detail(@RequestBody BaseSelectDto dto) {
+        return skuSpecService.detail(dto.getId());
+    }
+
+    /**
+     * sku规格新增
+     */
+    @PostMapping("/add")
+    public void add(@RequestBody SkuSpecDto dto) {
+        skuSpecService.add(dto);
+    }
+
+    /**
+     * sku规格编辑
+     */
+    @PostMapping("/edit")
+    public void edit(@RequestBody SkuSpecDto dto) {
+        skuSpecService.edit(dto);
+    }
+
+    /**
+     * sku规格删除
+     */
+    @PostMapping("/delete")
+    public void delete(@RequestBody BaseSelectDto dto) {
+        skuSpecService.delete(dto.getId());
+    }
+
+}

+ 17 - 0
sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuClassifyDto.java

@@ -0,0 +1,17 @@
+package com.sd.business.entity.sku.dto;
+
+import com.sd.business.entity.sku.po.SkuClassify;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * sku分类新增编辑入参实体
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+public class SkuClassifyDto extends SkuClassify {
+
+}

+ 22 - 0
sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuClassifySelectDto.java

@@ -0,0 +1,22 @@
+package com.sd.business.entity.sku.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * sku分类列表查询入参实体
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+public class SkuClassifySelectDto extends BaseSelectDto {
+
+    /**
+     * 分类名称
+     */
+    private String name;
+
+}

+ 17 - 0
sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuDto.java

@@ -0,0 +1,17 @@
+package com.sd.business.entity.sku.dto;
+
+import com.sd.business.entity.sku.po.Sku;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * sku新增编辑入参实体
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+public class SkuDto extends Sku {
+
+}

+ 17 - 0
sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuSelectDto.java

@@ -0,0 +1,17 @@
+package com.sd.business.entity.sku.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * sku列表查询入参实体
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+public class SkuSelectDto extends BaseSelectDto {
+
+}

+ 17 - 0
sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuSpecDto.java

@@ -0,0 +1,17 @@
+package com.sd.business.entity.sku.dto;
+
+import com.sd.business.entity.sku.po.SkuSpec;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * sku规格新增编辑入参实体
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+public class SkuSpecDto extends SkuSpec {
+
+}

+ 17 - 0
sd-business/src/main/java/com/sd/business/entity/sku/dto/SkuSpecSelectDto.java

@@ -0,0 +1,17 @@
+package com.sd.business.entity.sku.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * sku规格列表查询入参实体
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+public class SkuSpecSelectDto extends BaseSelectDto {
+
+}

+ 96 - 0
sd-business/src/main/java/com/sd/business/entity/sku/po/Sku.java

@@ -0,0 +1,96 @@
+package com.sd.business.entity.sku.po;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.domain.BasePo;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * sku
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+@TableName("sku")
+public class Sku extends BasePo {
+
+    /**
+     * 万里牛uid
+     */
+    private String wlnUid;
+
+    /**
+     * 万里牛分类id
+     */
+    private String wlnCatagoryId;
+
+    /**
+     * 类型 0非集团SKU 1集团SKU
+     */
+    private Integer type;
+
+    /**
+     * 来源 1自定义添加 2万里牛
+     */
+    private Integer source;
+
+    /**
+     * 类目id
+     */
+    private Long skuClassifyId;
+
+    /**
+     * 条码
+     */
+    private String barCode;
+
+    /**
+     * 群组品号
+     */
+    private String groupItemNumber;
+
+    /**
+     * 编码
+     */
+    private String code;
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 品牌
+     */
+    private String brand;
+
+    /**
+     * 材质
+     */
+    private String material;
+
+    /**
+     * 型号
+     */
+    private String modelNumber;
+
+    /**
+     * 工艺产线id
+     */
+    private Long craftProductionLineId;
+
+    /**
+     * 产品主图
+     */
+    private String mainImgUrl;
+
+    /**
+     * 详细描述
+     */
+    private String detailText;
+
+}

+ 46 - 0
sd-business/src/main/java/com/sd/business/entity/sku/po/SkuClassify.java

@@ -0,0 +1,46 @@
+package com.sd.business.entity.sku.po;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.domain.BasePo;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * sku分类
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+@TableName("sku_classify")
+public class SkuClassify extends BasePo {
+
+    /**
+     * 上级分类id
+     */
+    private Long parentId;
+
+    /**
+     * 分类名称
+     */
+    private String name;
+
+    /**
+     * 万里牛catagoryId
+     */
+    private String wlnCatagoryId;
+
+    /**
+     * 万里牛parentId
+     */
+    private String wlnParentId;
+
+    /**
+     * 排序
+     */
+    private Integer sort;
+
+}

+ 113 - 0
sd-business/src/main/java/com/sd/business/entity/sku/po/SkuSpec.java

@@ -0,0 +1,113 @@
+package com.sd.business.entity.sku.po;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.domain.BasePo;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * <p>
+ * sku规格
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+@TableName("sku_spec")
+public class SkuSpec extends BasePo {
+
+    /**
+     * 万里牛id
+     */
+    private String wlnUid;
+
+    /**
+     * sku id
+     */
+    private Long skuId;
+
+    /**
+     * 图稿id
+     */
+    private Long artworkLibraryId;
+
+    /**
+     * 规格图
+     */
+    private String specImgUrl;
+
+    /**
+     * 品号
+     */
+    private String code;
+
+    /**
+     * 品名
+     */
+    private String name;
+
+    /**
+     * 条码
+     */
+    private String barCode;
+
+    /**
+     * e10 品号
+     */
+    private String erpCode;
+
+    /**
+     * e10  c2品号
+     */
+    private String erpCodeC2;
+
+    /**
+     * e10 特征码
+     */
+    private String featureCode;
+
+    /**
+     * e10 c2特征码
+     */
+    private String featureCodeC2;
+
+    /**
+     * 加工面板 字典:charge_item
+     */
+    private String machinedPanel;
+
+    /**
+     * 长 cm
+     */
+    private BigDecimal length;
+
+    /**
+     * 宽 cm
+     */
+    private BigDecimal width;
+
+    /**
+     * 高 cm
+     */
+    private BigDecimal height;
+
+    /**
+     * 净重 g
+     */
+    private BigDecimal netWeight;
+
+    /**
+     * bom id
+     */
+    private Long bomSpecId;
+
+    /**
+     * 描述
+     */
+    private String remark;
+
+}

+ 25 - 0
sd-business/src/main/java/com/sd/business/entity/sku/vo/SkuClassifyVo.java

@@ -0,0 +1,25 @@
+package com.sd.business.entity.sku.vo;
+
+import com.sd.business.entity.sku.po.SkuClassify;
+import com.sd.framework.util.tree.Tree;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * sku分类列表查询返回值实体
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+public class SkuClassifyVo extends SkuClassify implements Tree<SkuClassifyVo> {
+
+    /**
+     * 子节点
+     */
+    private List<SkuClassifyVo> children;
+
+}

+ 17 - 0
sd-business/src/main/java/com/sd/business/entity/sku/vo/SkuSpecVo.java

@@ -0,0 +1,17 @@
+package com.sd.business.entity.sku.vo;
+
+import com.sd.business.entity.sku.po.SkuSpec;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * sku规格列表查询返回值实体
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+public class SkuSpecVo extends SkuSpec {
+
+}

+ 17 - 0
sd-business/src/main/java/com/sd/business/entity/sku/vo/SkuVo.java

@@ -0,0 +1,17 @@
+package com.sd.business.entity.sku.vo;
+
+import com.sd.business.entity.sku.po.Sku;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * sku列表查询返回值实体
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Getter
+@Setter
+public class SkuVo extends Sku {
+
+}

+ 16 - 0
sd-business/src/main/java/com/sd/business/mapper/sku/SkuClassifyMapper.java

@@ -0,0 +1,16 @@
+package com.sd.business.mapper.sku;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sd.business.entity.sku.po.SkuClassify;
+
+/**
+ * <p>
+ * sku分类 Mapper 接口
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+public interface SkuClassifyMapper extends BaseMapper<SkuClassify> {
+
+}

+ 16 - 0
sd-business/src/main/java/com/sd/business/mapper/sku/SkuMapper.java

@@ -0,0 +1,16 @@
+package com.sd.business.mapper.sku;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sd.business.entity.sku.po.Sku;
+
+/**
+ * <p>
+ * sku Mapper 接口
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+public interface SkuMapper extends BaseMapper<Sku> {
+
+}

+ 16 - 0
sd-business/src/main/java/com/sd/business/mapper/sku/SkuSpecMapper.java

@@ -0,0 +1,16 @@
+package com.sd.business.mapper.sku;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sd.business.entity.sku.po.SkuSpec;
+
+/**
+ * <p>
+ * sku规格 Mapper 接口
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+public interface SkuSpecMapper extends BaseMapper<SkuSpec> {
+
+}

+ 26 - 0
sd-business/src/main/java/com/sd/business/service/sku/SkuClassifyService.java

@@ -0,0 +1,26 @@
+package com.sd.business.service.sku;
+
+import com.ruoyi.common.core.service.BaseService;
+import com.sd.business.entity.sku.dto.SkuClassifySelectDto;
+import com.sd.business.entity.sku.po.SkuClassify;
+import com.sd.business.entity.sku.vo.SkuClassifyVo;
+
+import java.util.List;
+
+
+/**
+ * <p>
+ * sku分类 服务类
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+public interface SkuClassifyService extends BaseService<SkuClassify> {
+
+    /**
+     * sku树形列表
+     */
+    List<SkuClassifyVo> getTree(SkuClassifySelectDto dto);
+
+}

+ 46 - 0
sd-business/src/main/java/com/sd/business/service/sku/SkuService.java

@@ -0,0 +1,46 @@
+package com.sd.business.service.sku;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.service.BaseService;
+import com.sd.business.entity.sku.dto.SkuDto;
+import com.sd.business.entity.sku.dto.SkuSelectDto;
+import com.sd.business.entity.sku.po.Sku;
+import com.sd.business.entity.sku.vo.SkuVo;
+
+
+/**
+ * <p>
+ * sku 服务类
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+public interface SkuService extends BaseService<Sku> {
+
+    /**
+     * sku分页
+     */
+    Page<SkuVo> getPage(SkuSelectDto dto);
+
+    /**
+     * sku明细
+     */
+    SkuVo detail(Long id);
+
+    /**
+     * sku新增
+     */
+    void add(SkuDto dto);
+
+    /**
+     * sku编辑
+     */
+    void edit(SkuDto dto);
+
+    /**
+     * sku删除
+     */
+    void delete(Long id);
+
+}

+ 46 - 0
sd-business/src/main/java/com/sd/business/service/sku/SkuSpecService.java

@@ -0,0 +1,46 @@
+package com.sd.business.service.sku;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.service.BaseService;
+import com.sd.business.entity.sku.dto.SkuSpecDto;
+import com.sd.business.entity.sku.dto.SkuSpecSelectDto;
+import com.sd.business.entity.sku.po.SkuSpec;
+import com.sd.business.entity.sku.vo.SkuSpecVo;
+
+
+/**
+ * <p>
+ * sku规格 服务类
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+public interface SkuSpecService extends BaseService<SkuSpec> {
+
+    /**
+     * sku规格分页
+     */
+    Page<SkuSpecVo> getPage(SkuSpecSelectDto dto);
+
+    /**
+     * sku规格明细
+     */
+    SkuSpecVo detail(Long id);
+
+    /**
+     * sku规格新增
+     */
+    void add(SkuSpecDto dto);
+
+    /**
+     * sku规格编辑
+     */
+    void edit(SkuSpecDto dto);
+
+    /**
+     * sku规格删除
+     */
+    void delete(Long id);
+
+}

+ 39 - 0
sd-business/src/main/java/com/sd/business/service/sku/impl/SkuClassifyServiceImpl.java

@@ -0,0 +1,39 @@
+package com.sd.business.service.sku.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sd.business.entity.sku.dto.SkuClassifySelectDto;
+import com.sd.business.entity.sku.po.SkuClassify;
+import com.sd.business.entity.sku.vo.SkuClassifyVo;
+import com.sd.business.mapper.sku.SkuClassifyMapper;
+import com.sd.business.service.sku.SkuClassifyService;
+import com.sd.framework.util.sql.Sql;
+import com.sd.framework.util.tree.TreeUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+
+/**
+ * <p>
+ * sku分类 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Service
+public class SkuClassifyServiceImpl extends ServiceImpl<SkuClassifyMapper, SkuClassify> implements SkuClassifyService {
+
+    @Override
+    public List<SkuClassifyVo> getTree(SkuClassifySelectDto dto) {
+
+        List<SkuClassifyVo> list = Sql.create(SkuClassifyVo.class)
+                .selectAll(SkuClassify.class)
+                .from(SkuClassify.class)
+                .like(SkuClassify::getName, dto.getName())
+                .orderByAsc(SkuClassify::getSort)
+                .list();
+
+        return TreeUtil.build(list);
+    }
+}

+ 68 - 0
sd-business/src/main/java/com/sd/business/service/sku/impl/SkuServiceImpl.java

@@ -0,0 +1,68 @@
+package com.sd.business.service.sku.impl;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sd.business.entity.sku.dto.SkuDto;
+import com.sd.business.entity.sku.dto.SkuSelectDto;
+import com.sd.business.entity.sku.po.Sku;
+import com.sd.business.entity.sku.vo.SkuVo;
+import com.sd.business.mapper.sku.SkuMapper;
+import com.sd.business.service.sku.SkuService;
+import com.sd.framework.util.Assert;
+import com.sd.framework.util.sql.Sql;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * <p>
+ * sku 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Service
+public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements SkuService {
+
+    @Override
+    public Page<SkuVo> getPage(SkuSelectDto dto) {
+
+        Page<SkuVo> page = Sql.create(SkuVo.class)
+                .selectAll(Sku.class)
+                .from(Sku.class)
+                .orderByDesc(Sku::getId)
+                .page(dto.getPage());
+
+        return page;
+    }
+
+    @Override
+    public SkuVo detail(Long id) {
+
+        SkuVo vo = Sql.create(SkuVo.class)
+                .selectAll(Sku.class)
+                .from(Sku.class)
+                .eq(Sku::getId, id)
+                .one();
+
+        Assert.notNull(vo, "未知数据");
+
+        return vo;
+    }
+
+    @Override
+    public void add(SkuDto dto) {
+        save(dto);
+    }
+
+    @Override
+    public void edit(SkuDto dto) {
+        updateById(dto);
+    }
+
+    @Override
+    public void delete(Long id) {
+        removeById(id);
+    }
+
+}

+ 68 - 0
sd-business/src/main/java/com/sd/business/service/sku/impl/SkuSpecServiceImpl.java

@@ -0,0 +1,68 @@
+package com.sd.business.service.sku.impl;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sd.business.entity.sku.dto.SkuSpecDto;
+import com.sd.business.entity.sku.dto.SkuSpecSelectDto;
+import com.sd.business.entity.sku.po.SkuSpec;
+import com.sd.business.entity.sku.vo.SkuSpecVo;
+import com.sd.business.mapper.sku.SkuSpecMapper;
+import com.sd.business.service.sku.SkuSpecService;
+import com.sd.framework.util.Assert;
+import com.sd.framework.util.sql.Sql;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * <p>
+ * sku规格 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2023-11-09
+ */
+@Service
+public class SkuSpecServiceImpl extends ServiceImpl<SkuSpecMapper, SkuSpec> implements SkuSpecService {
+
+    @Override
+    public Page<SkuSpecVo> getPage(SkuSpecSelectDto dto) {
+
+        Page<SkuSpecVo> page = Sql.create(SkuSpecVo.class)
+                .selectAll(SkuSpec.class)
+                .from(SkuSpec.class)
+                .orderByDesc(SkuSpec::getId)
+                .page(dto.getPage());
+
+        return page;
+    }
+
+    @Override
+    public SkuSpecVo detail(Long id) {
+
+        SkuSpecVo vo = Sql.create(SkuSpecVo.class)
+                .selectAll(SkuSpec.class)
+                .from(SkuSpec.class)
+                .eq(SkuSpec::getId, id)
+                .one();
+
+        Assert.notNull(vo, "未知数据");
+
+        return vo;
+    }
+
+    @Override
+    public void add(SkuSpecDto dto) {
+        save(dto);
+    }
+
+    @Override
+    public void edit(SkuSpecDto dto) {
+        updateById(dto);
+    }
+
+    @Override
+    public void delete(Long id) {
+        removeById(id);
+    }
+
+}

+ 5 - 0
sd-business/src/main/resources/mapper/sku/SkuClassifyMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.sd.business.mapper.sku.SkuClassifyMapper">
+
+</mapper>

+ 5 - 0
sd-business/src/main/resources/mapper/sku/SkuMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.sd.business.mapper.sku.SkuMapper">
+
+</mapper>

+ 5 - 0
sd-business/src/main/resources/mapper/sku/SkuSpecMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.sd.business.mapper.sku.SkuSpecMapper">
+
+</mapper>

+ 1 - 1
sd-framework/pom.xml

@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.sd</groupId>
         <artifactId>sdhy_project</artifactId>
-        <version>1.0</version>
+        <version>2.0</version>
     </parent>
 
     <artifactId>sd-framework</artifactId>

+ 11 - 0
sd-framework/src/main/java/com/sd/framework/util/tree/Tree.java

@@ -0,0 +1,11 @@
+package com.sd.framework.util.tree;
+
+import java.util.List;
+
+public interface Tree<T extends Tree<T>> extends TreeId {
+
+    List<T> getChildren();
+
+    void setChildren(List<T> list);
+
+}

+ 9 - 0
sd-framework/src/main/java/com/sd/framework/util/tree/TreeId.java

@@ -0,0 +1,9 @@
+package com.sd.framework.util.tree;
+
+public interface TreeId {
+
+    Long getId();
+
+    Long getParentId();
+
+}

+ 63 - 0
sd-framework/src/main/java/com/sd/framework/util/tree/TreeUtil.java

@@ -0,0 +1,63 @@
+package com.sd.framework.util.tree;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class TreeUtil {
+
+    /**
+     * 构件树形集合
+     *
+     * @param list 所有节点
+     * @return 树形集合
+     */
+    public static <T extends Tree<T>> List<T> build(List<T> list) {
+        // 获取节点id列表
+        List<Long> parentIdList = list.stream().map(Tree::getId).collect(Collectors.toList());
+        return list.stream()
+                // 过滤非顶级节点
+                .filter(item -> !parentIdList.contains(item.getParentId()))
+                // 赋值顶级节点子节点
+                .peek(item -> item.setChildren(findChildNodes(item.getId(), list)))
+                // 收集数据
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 获取子节点id列表
+     *
+     * @param id   父节点id
+     * @param list 所有节点id列表
+     * @return 子节点id列表
+     */
+    public static <T extends TreeId> List<Long> getChildrenIdList(Long id, List<T> list) {
+        List<Long> result = list.stream()
+                .filter(item -> Objects.equals(id, item.getParentId()))
+                .flatMap(item -> getChildrenIdList(item.getId(), list).stream())
+                .distinct()
+                .collect(Collectors.toList());
+
+        result.add(0, id);
+
+        return result;
+    }
+
+    /**
+     * 查找子节点集合
+     *
+     * @param id   节点id
+     * @param list 所有节点
+     * @return 子节点结果集
+     */
+    private static <T extends Tree<T>> List<T> findChildNodes(Long id, List<T> list) {
+        return list.stream()
+                // 过滤非子节点
+                .filter(item -> Objects.equals(id, item.getParentId()))
+                // 递归赋值子节点的子节点
+                .peek(item -> item.setChildren(findChildNodes(item.getId(), list)))
+                // 收集数据
+                .collect(Collectors.toList());
+    }
+
+}

+ 6 - 1
sd-starter/pom.xml

@@ -7,7 +7,7 @@
     <parent>
         <groupId>com.sd</groupId>
         <artifactId>sdhy_project</artifactId>
-        <version>1.0</version>
+        <version>2.0</version>
     </parent>
 
     <artifactId>sd-starter</artifactId>
@@ -25,6 +25,11 @@
         </dependency>
 
         <dependency>
+            <groupId>com.sd</groupId>
+            <artifactId>sd-wln</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
             <scope>test</scope>

+ 29 - 0
sd-wln/pom.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sd</groupId>
+        <artifactId>sdhy_project</artifactId>
+        <version>2.0</version>
+    </parent>
+
+    <artifactId>sd-wln</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>com.sd</groupId>
+            <artifactId>sd-business</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 20 - 0
sd-wln/src/main/java/com/sd/wln/constants/WlnConstant.java

@@ -0,0 +1,20 @@
+package com.sd.wln.constants;
+
+public class WlnConstant {
+
+    /**
+     * key
+     */
+    public static final String APP_KEY = "3923521627";
+
+    /**
+     * secret
+     */
+    public static final String APP_SECRET = "ee6f90783e1c3ba72098137e9a6e8ec3";
+
+    /**
+     * 公司id(具体可以咨询下万里牛客服)
+     */
+    public static final String COM_UID = "22768050183124";
+
+}

+ 35 - 0
sd-wln/src/main/java/com/sd/wln/controller/WlnController.java

@@ -0,0 +1,35 @@
+package com.sd.wln.controller;
+
+import com.sd.wln.service.WlnSkuService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+@RestController
+@RequestMapping("/wln")
+public class WlnController {
+
+    public static final Lock syncSkuLock = new ReentrantLock();
+
+    @Autowired
+    private WlnSkuService wlnSkuService;
+
+    /**
+     * 重新同步订单
+     */
+    @PostMapping("/syncSku")
+    public void syncSku() {
+        if (syncSkuLock.tryLock()) {
+            try {
+                wlnSkuService.sync();
+            } finally {
+                WlnController.syncSkuLock.unlock();
+            }
+        }
+    }
+
+}

+ 38 - 0
sd-wln/src/main/java/com/sd/wln/entity/GoodsSpecParam.java

@@ -0,0 +1,38 @@
+package com.sd.wln.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 商品分类参数实体类
+ */
+@Getter
+@Setter
+public class GoodsSpecParam extends Signature {
+
+    /**
+     * 规格编码
+     */
+    private String spec_code;
+
+    /**
+     * 商品编码
+     */
+    private String item_code;
+
+    /**
+     * 规格修改时间
+     */
+    private Long modify_time;
+
+    /**
+     * 条码
+     */
+    private String bar_code;
+
+    /**
+     * 是否需要查询商品自定义属性(默认不传为false)
+     */
+    private String need_properties;
+
+}

+ 15 - 0
sd-wln/src/main/java/com/sd/wln/entity/ResynchronizationDto.java

@@ -0,0 +1,15 @@
+package com.sd.wln.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ResynchronizationDto {
+
+    /**
+     * 万里牛编号
+     */
+    private String wlnCode;
+
+}

+ 75 - 0
sd-wln/src/main/java/com/sd/wln/entity/Signature.java

@@ -0,0 +1,75 @@
+package com.sd.wln.entity;
+
+import com.ruoyi.common.utils.sign.Md5Utils;
+import com.sd.wln.constants.WlnConstant;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * 签名参数实体类
+ */
+@Getter
+@Setter
+public class Signature implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 请求键值
+     */
+    private String _app;
+
+    /**
+     * 时间戳
+     */
+    private Long _t;
+
+    /**
+     * 签名方法,支持 md5 和 hmac,默认 md5
+     */
+    private String _sign_kind;
+
+    /**
+     * 请求签名
+     */
+    private String _sign;
+
+    /**
+     * 授权码
+     */
+    private String _s;
+
+    /**
+     * 当前页码,从1开始
+     */
+    private Integer page;
+
+    /**
+     * 每页大小,最大200
+     */
+    private Integer limit;
+
+    /**
+     * 每页大小,最大200
+     */
+    private Long start_time;
+
+    /**
+     * 生成签名
+     */
+    public void generateSign(String param) {
+        long time = System.currentTimeMillis();
+        String str = WlnConstant.APP_SECRET
+                + "_app=" + WlnConstant.APP_KEY + "&"
+                + "_t=" + time + "&"
+                + param
+                + WlnConstant.APP_SECRET;
+
+        _app = WlnConstant.APP_KEY;
+        _sign = Md5Utils.hash(str);
+        _t = time;
+    }
+
+}

+ 15 - 0
sd-wln/src/main/java/com/sd/wln/entity/SkuClassifyParam.java

@@ -0,0 +1,15 @@
+package com.sd.wln.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class SkuClassifyParam extends Signature {
+
+    /**
+     * 公司id(具体可以咨询下万里牛客服)
+     */
+    private String com_uid;
+
+}

+ 56 - 0
sd-wln/src/main/java/com/sd/wln/entity/StockParam.java

@@ -0,0 +1,56 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.sd.wln.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 查询订单参数实体类
+ */
+@Getter
+@Setter
+public class StockParam extends Signature {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 单据编码
+     */
+    private String bill_code;
+
+    /**
+     * 单据编码
+     */
+    private String trade_code;
+
+    /**
+     * 单据修改时间,仅支持近3个月的日期查询
+     */
+    private Long modify_time;
+
+    /**
+     * 单据修改结束时间,仅支持近3个月的日期查询
+     */
+    private Long modify_end_time;
+
+    /**
+     * 是否拆分组合商品
+     */
+    private Boolean is_split;
+
+}

+ 90 - 0
sd-wln/src/main/java/com/sd/wln/entity/TradesParam.java

@@ -0,0 +1,90 @@
+package com.sd.wln.entity;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 查询订单参数实体类
+ */
+@Getter
+@Setter
+public class TradesParam extends Signature {
+
+    /**
+     * 单据编码
+     */
+    private String bill_code;
+
+    /**
+     * 单据创建时间,修改时间为空是使用,仅支持近3个月的日期查询
+     */
+    private Long create_time;
+
+    /**
+     * 单据审核时间,时间戳毫秒格式
+     */
+    private Long approve_time;
+
+    /**
+     * 单据修改时间,仅支持近3个月的日期查询
+     */
+    private Long modify_time;
+
+    /**
+     * 发货时间,创建时间为空时使用,仅支持近3个月的日期查询
+     */
+    private Long send_goods_time;
+
+    /**
+     * 完成时间,发货时间为空时使用,仅支持近3个月的日期查询
+     */
+    private Long finish_time;
+
+    /**
+     * 查询结束时间;仅支持开始时间与结束时间间隔7天之内
+     */
+    private Long end_time;
+
+    /**
+     * 付款时间,仅支持近3个月的日期查询
+     */
+    private Long pay_time;
+
+    /**
+     * 仓库编码
+     */
+    private String storage_code;
+
+    /**
+     * 是否拆分组合商品
+     */
+    private Boolean is_split;
+
+    /**
+     * 手机
+     */
+    private String mobile;
+
+    /**
+     * 订单状态0:审核 1:打单配货 2:验货3:称重4:待发货5:财审8:已发货9:完成10:关闭13:配货中15:打包 PS:分销商订单不支持状态查询,支持多状态查询,中间使用英文逗号隔开,如1,2,3
+     */
+    private String trade_status;
+
+    /**
+     * 扩展字段 为JSON格式
+     * {"query_exchange_only":true}
+     */
+    private JSONObject query_extend;
+
+    /**
+     * 是否查询无数据也进行删除
+     */
+    private Boolean flag;
+
+    /**
+     * 手动导入
+     */
+    private Boolean manualImport;
+
+}

+ 34 - 0
sd-wln/src/main/java/com/sd/wln/scheduled/WlnSyncTask.java

@@ -0,0 +1,34 @@
+package com.sd.wln.scheduled;
+
+import com.sd.wln.controller.WlnController;
+import com.sd.wln.service.WlnSkuService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+/**
+ * 同步万里牛数据(本地环境不执行同步逻辑)
+ */
+@Profile({"test", "prod"})
+@Component
+public class WlnSyncTask {
+
+    @Autowired
+    private WlnSkuService wlnSkuService;
+
+    /**
+     * 同步sku信息
+     */
+    @Scheduled(cron = "0 0 1 * * ?")
+    public void syncSku() {
+        if (WlnController.syncSkuLock.tryLock()) {
+            try {
+                wlnSkuService.sync();
+            } finally {
+                WlnController.syncSkuLock.unlock();
+            }
+        }
+    }
+
+}

+ 7 - 0
sd-wln/src/main/java/com/sd/wln/service/WlnSkuService.java

@@ -0,0 +1,7 @@
+package com.sd.wln.service;
+
+public interface WlnSkuService {
+
+    void sync();
+
+}

+ 198 - 0
sd-wln/src/main/java/com/sd/wln/service/impl/WlnSkuServiceImpl.java

@@ -0,0 +1,198 @@
+package com.sd.wln.service.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.ruoyi.common.core.domain.BaseIdPo;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.framework.mybatis.holder.LogicHolder;
+import com.sd.business.entity.sku.po.Sku;
+import com.sd.business.entity.sku.po.SkuClassify;
+import com.sd.business.entity.sku.po.SkuSpec;
+import com.sd.business.service.sku.SkuClassifyService;
+import com.sd.business.service.sku.SkuService;
+import com.sd.business.service.sku.SkuSpecService;
+import com.sd.wln.service.WlnSkuService;
+import com.sd.wln.util.WlnUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class WlnSkuServiceImpl implements WlnSkuService {
+
+    @Autowired
+    private SkuClassifyService skuClassifyService;
+
+    @Autowired
+    private SkuService skuService;
+
+    @Autowired
+    private SkuSpecService skuSpecService;
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void sync() {
+        syncSkuClassify();
+        syncSku();
+    }
+
+    private void syncSkuClassify() {
+        List<JSONObject> list;
+
+        // 查询万里牛sku分类
+        try {
+            list = WlnUtil.getSkuClassifyList();
+        } catch (Exception e) {
+            log.error("sku分类同步失败", e);
+            throw new ServiceException("sku分类同步失败");
+        }
+
+        // 查询数据库sku分类
+        LogicHolder.setLogicHolder(true);
+        Map<String, SkuClassify> skuClassifyMap = skuClassifyService.mapKEntity(SkuClassify::getWlnCatagoryId, null);
+        LogicHolder.clear();
+
+        // 去重合并
+        List<SkuClassify> skuClassifyList = new ArrayList<>();
+        for (int i = 0; i < list.size(); i++) {
+            JSONObject item = list.get(i);
+
+            String catagoryid = item.getString("catagoryid");
+            String name = item.getString("catagory_name");
+            String parentId = item.getString("parentid");
+
+            SkuClassify skuClassify = skuClassifyMap.get(catagoryid);
+            if (skuClassify == null) {
+                skuClassify = new SkuClassify();
+                skuClassify.setId(IdWorker.getId());
+            }
+            skuClassify.setWlnCatagoryId(catagoryid);
+            skuClassify.setName(name);
+            skuClassify.setWlnParentId(parentId);
+            skuClassify.setSort(i);
+            skuClassifyList.add(skuClassify);
+        }
+
+        // 赋值parentId
+        Map<String, Long> map = skuClassifyList.stream().collect(
+                Collectors.toMap(SkuClassify::getWlnCatagoryId, SkuClassify::getId, (t1, t2) -> t1));
+        for (SkuClassify skuClassify : skuClassifyList) {
+            skuClassify.setParentId(map.getOrDefault(skuClassify.getWlnParentId(), 0L));
+        }
+
+        // 更新数据库
+        skuClassifyService.saveOrUpdateBatch(skuClassifyList);
+    }
+
+    private void syncSku() {
+        int page = 1;
+        int size;
+        List<JSONObject> wlnSkuList = new ArrayList<>();
+        do {
+            try {
+                List<JSONObject> itemList = WlnUtil.getSkuList(page, 200);
+                page++;
+                size = itemList.size();
+                wlnSkuList.addAll(itemList);
+            } catch (Exception e) {
+                log.error("sku同步失败", e);
+                throw new ServiceException("sku同步失败");
+            }
+        } while (size >= 200);
+
+        LogicHolder.setLogicHolder(true);
+
+        // 产品分类map
+        Map<String, Long> skuClassifyMap = skuClassifyService.mapKV(SkuClassify::getWlnCatagoryId, BaseIdPo::getId, null);
+
+        // 产品map
+        Map<String, Sku> skuMap = skuService.mapKEntity(Sku::getWlnUid, null);
+
+        // 产品规格map
+        Map<Long, Map<String, SkuSpec>> specMap = skuSpecService.list(q -> q.isNotNull(SkuSpec::getWlnUid))
+                .stream()
+                .collect(Collectors.groupingBy(SkuSpec::getSkuId, Collectors.toMap(SkuSpec::getWlnUid, Function.identity())));
+
+        LogicHolder.clear();
+
+        List<Sku> newSkuList = new ArrayList<>();
+        List<SkuSpec> newSkuSpecList = new ArrayList<>();
+
+        for (JSONObject wlnSku : wlnSkuList) {
+            Sku sku = skuMap.get(wlnSku.getString("sys_goods_uid"));
+            if (sku == null) {
+                sku = createSku(wlnSku, skuClassifyMap);
+                if (sku == null) {
+                    continue;
+                }
+                newSkuList.add(sku);
+            }
+
+            List<JSONObject> specList = wlnSku.getJSONArray("specs").toJavaList(JSONObject.class);
+            for (JSONObject wlnSkuSpec : specList) {
+                Map<String, SkuSpec> skuSpecMap = specMap.get(sku.getId());
+                if (skuSpecMap != null && skuSpecMap.get(wlnSkuSpec.getString("sys_spec_uid")) != null) {
+                    continue;
+                }
+                newSkuSpecList.add(createSkuSpec(wlnSkuSpec, sku));
+            }
+        }
+
+        skuService.saveBatch(newSkuList);
+        skuSpecService.saveBatch(newSkuSpecList);
+    }
+
+    private Sku createSku(JSONObject wlnSku, Map<String, Long> skuClassifyMap) {
+
+        String catagoryId = wlnSku.getString("catagory_id");
+        if (StrUtil.isBlank(catagoryId)) {
+            return null;
+        }
+
+        Long skuClassifyId = skuClassifyMap.get(catagoryId);
+        if (skuClassifyId == null) {
+            return null;
+        }
+
+        Sku sku = new Sku();
+        sku.setId(IdWorker.getId());
+        sku.setWlnCatagoryId(catagoryId);
+        sku.setWlnUid(wlnSku.getString("sys_goods_uid"));
+        sku.setSource(2);
+        sku.setSkuClassifyId(skuClassifyId);
+        sku.setCode(wlnSku.getString("goods_code"));
+        sku.setName(wlnSku.getString("goods_name"));
+        sku.setBrand(wlnSku.getString("brand_name"));
+        sku.setMainImgUrl(wlnSku.getString("pic"));
+        sku.setType(Objects.equals(sku.getBrand(), "胜德科技") ? 1 : 0);
+        return sku;
+    }
+
+    private SkuSpec createSkuSpec(JSONObject wlnSku, Sku sku) {
+        SkuSpec skuSpec = new SkuSpec();
+        skuSpec.setId(IdWorker.getId());
+        skuSpec.setWlnUid(wlnSku.getString("sys_spec_uid"));
+        skuSpec.setSkuId(sku.getId());
+        skuSpec.setSpecImgUrl(wlnSku.getString("pic"));
+        skuSpec.setCode(wlnSku.getString("spec_code"));
+        skuSpec.setName(sku.getName() + ":" + wlnSku.getString("spec1") + wlnSku.getString("spec2"));
+        skuSpec.setBarCode(wlnSku.getString("barcode"));
+        skuSpec.setLength(wlnSku.getBigDecimal("length"));
+        skuSpec.setWidth(wlnSku.getBigDecimal("width"));
+        skuSpec.setHeight(wlnSku.getBigDecimal("height"));
+        skuSpec.setNetWeight(wlnSku.getBigDecimal("weight"));
+        skuSpec.setRemark(wlnSku.getString("spec1") + wlnSku.getString("spec2"));
+        return skuSpec;
+    }
+
+}

+ 207 - 0
sd-wln/src/main/java/com/sd/wln/util/WlnUtil.java

@@ -0,0 +1,207 @@
+package com.sd.wln.util;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.MapUtil;
+import com.sd.wln.constants.WlnConstant;
+import com.sd.wln.entity.GoodsSpecParam;
+import com.sd.wln.entity.SkuClassifyParam;
+import com.sd.wln.entity.StockParam;
+import com.sd.wln.entity.TradesParam;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+import java.io.IOException;
+import java.util.List;
+
+public class WlnUtil {
+
+    /**
+     * 万里牛路径前缀
+     */
+    private static final String PREFIX = "https://open-api.hupun.com/api/";
+
+    /**
+     * 获取sku分类
+     */
+    public static List<JSONObject> getSkuClassifyList() throws Exception {
+        SkuClassifyParam param = new SkuClassifyParam();
+        param.setCom_uid(WlnConstant.COM_UID);
+        String linkString = MapUtil.createLinkString(MapUtil.beanToMap(param));
+        param.generateSign(linkString);
+
+        String result = send(PREFIX + "erp/goods/catagory/query", param);
+        JSONObject json = JSONObject.parseObject(result);
+        Integer code = json.getInteger("code");
+        if (code != 0) {
+            throw new ServiceException(result);
+        }
+        return json.getJSONArray("data").toJavaList(JSONObject.class);
+    }
+
+    /**
+     * 获取sku列表
+     */
+    public static List<JSONObject> getSkuList(Integer page, Integer limit) throws Exception {
+        GoodsSpecParam param = new GoodsSpecParam();
+        param.setPage(page);
+        param.setLimit(limit);
+        param.setModify_time(965381503L);
+        param.generateSign(MapUtil.createLinkString(MapUtil.beanToMap(param)));
+        String result = send(PREFIX + "erp/goods/spec/open/query/goodswithspeclist", MapUtil.beanToMap(param));
+        JSONObject json = JSONObject.parseObject(result);
+        Integer code = json.getInteger("code");
+        if (code != 0) {
+            throw new ServiceException(result);
+        }
+        return json.getJSONArray("data").toJavaList(JSONObject.class);
+    }
+
+    /**
+     * 获取订单
+     */
+    public static List<JSONObject> getOrderList(Integer page, Integer limit, Long startTime, Long endTime, String warehouseCode) throws Exception {
+        TradesParam param = new TradesParam();
+        param.setPage(page);
+        param.setLimit(limit);
+        param.setModify_time(startTime);
+        param.setEnd_time(endTime);
+        param.setStorage_code(warehouseCode);
+        param.setIs_split(true);
+        param.setManualImport(false);
+        param.generateSign(MapUtil.createLinkString(MapUtil.beanToMap(param)));
+
+        String result = send(PREFIX + "erp/opentrade/list/trades", MapUtil.beanToMap(param));
+        JSONObject json = JSONObject.parseObject(result);
+        Integer code = json.getInteger("code");
+        if (code != 0) {
+            throw new ServiceException(result);
+        }
+        return json.getJSONArray("data").toJavaList(JSONObject.class);
+    }
+
+    /**
+     * 获取订单
+     */
+    public static JSONObject getOrderByWlnCode(String wlnCode) throws Exception {
+        TradesParam param = new TradesParam();
+        param.setBill_code(wlnCode);
+        param.setPage(1);
+        param.setLimit(10);
+        param.setIs_split(true);
+        param.setManualImport(false);
+        param.generateSign(MapUtil.createLinkString(MapUtil.beanToMap(param)));
+        String result = send(PREFIX + "erp/opentrade/list/trades", MapUtil.beanToMap(param));
+        JSONObject json = JSONObject.parseObject(result);
+        Integer code = json.getInteger("code");
+        if (code != 0) {
+            throw new ServiceException(result);
+        }
+        List<JSONObject> list = json.getJSONArray("data").toJavaList(JSONObject.class);
+
+        if (list.isEmpty()) {
+            throw new ServiceException("未能通过万里牛订单编号找到订单");
+        }
+        if (list.size() > 1) {
+            throw new ServiceException("通过万里牛订单编号找到多条订单");
+        }
+        return list.get(0);
+    }
+
+    /**
+     * 获取出库单
+     */
+    public static List<JSONObject> getOutboundOrder(Integer page, Integer limit, Long startTime, Long endTime) throws IOException {
+        StockParam param = new StockParam();
+        param.setPage(page);
+        param.setLimit(limit);
+        param.setModify_time(startTime);
+        param.setModify_end_time(endTime);
+        param.setIs_split(true);
+        param.generateSign(MapUtil.createLinkString(MapUtil.beanToMap(param)));
+
+        String result = send(PREFIX + "erp/sale/stock/out/query", MapUtil.beanToMap(param));
+        JSONObject json = JSONObject.parseObject(result);
+        Integer code = json.getInteger("code");
+        if (code != 0) {
+            throw new ServiceException(result);
+        }
+        return json.getJSONArray("data").toJavaList(JSONObject.class);
+    }
+
+//    public static void main(String[] args) throws Exception {
+//         List<JSONObject> skuList = getSkuList(1, 200);
+//         System.out.println();
+//
+//         List<JSONObject> skuClassifyList = getSkuClassifyList();
+//         System.out.println();
+//
+//         long endTime = System.currentTimeMillis();
+//         long startTime = endTime - 1000 * 60 * 60 * 24;
+//         List<JSONObject> orderList = getOrderList(1, 50, startTime, endTime, "B012");
+//         System.out.println();
+
+//        String a = "[\"XD231026000939\",\"XD231026000908\",\"XD231026001177\",\"XD231026001036\",\"XD231026001184\",\"XD231026001229\",\"XD231026001432\",\"XD231026001431\",\"XD231026001310\",\"XD231026001572\",\"XD231026001441\",\"XD231026001205\",\"XD231026001215\",\"XD231026001602\",\"XD231026001419\",\"XD231026001632\",\"XD231026001662\",\"XD231026001459\",\"XD231026001414\",\"XD231026001235\",\"XD231026001268\",\"XD231026001298\",\"XD231026001481\",\"XD231026001265\",\"XD231026001376\",\"XD231026001683\",\"XD231026001559\",\"XD231026001589\",\"XD231026001325\",\"XD231026001511\",\"XD231026001497\",\"XD231026001507\",\"XD231026001506\",\"XD231026001365\",\"XD231026001742\",\"XD231026001574\",\"XD231026001551\",\"XD231026001620\",\"XD231026001614\",\"XD231026001762\",\"XD231026001455\",\"XD231026001680\",\"XD231026001684\",\"XD231026001641\",\"XD231026001704\",\"XD231026001724\",\"XD231026001667\",\"XD231026001606\",\"XD231026001852\",\"XD231026001872\",\"XD231026001710\",\"XD231026001677\",\"XD231026001681\",\"XD231026001892\",\"XD231026001749\",\"XD231026001701\",\"XD231026001721\",\"XD231026001750\",\"XD231026001666\",\"XD231026002062\"]";
+//        List<String> strings = JSON.parseArray(a, String.class);
+//        String collect = String.join(",", strings);
+//        List<JSONObject> orderList = getOrderListByWlnCodeList(collect);
+//        System.out.println(orderList.toString());
+
+//         long endTime = System.currentTimeMillis();
+//         long startTime = endTime - 1000 * 60 * 60 * 24 * 7;
+//         List<JSONObject> outboundOrder = getOutboundOrder(0, 200, 1690367461000L, 1690367461000L);
+//         System.out.println();
+//    }
+
+    /**
+     * post请求
+     */
+    private static String send(String url, Object param) throws IOException {
+        String params = JSONUtil.toJsonStr(param);
+        StringEntity entity = new StringEntity(params, "UTF-8");
+
+        HttpPost httpPost = new HttpPost(url);
+        httpPost.setHeader("Accept", "application/json");
+        httpPost.setHeader("Content-Type", "application/json");
+        httpPost.setHeader("User-Agent", "PostmanRuntime/7.29.2");
+        httpPost.setHeader("Accept", "*/*");
+        httpPost.setEntity(entity);
+        CloseableHttpClient httpclient = HttpClients.createDefault();
+        CloseableHttpResponse response = null;
+        try {
+            response = httpclient.execute(httpPost);
+            HttpEntity responseEntity = response.getEntity();
+            return EntityUtils.toString(responseEntity);
+        } finally {
+            IoUtil.close(response);
+            IoUtil.close(httpclient);
+        }
+    }
+
+
+    /**
+     * 获取订单
+     */
+    public static List<JSONObject> getOrderListByWlnCodeList(String wlnCodeListStr) throws Exception {
+        TradesParam param = new TradesParam();
+        param.setBill_code(wlnCodeListStr);
+        param.setPage(1);
+        param.setLimit(200);
+        param.generateSign(MapUtil.createLinkString(MapUtil.beanToMap(param)));
+        String result = send(PREFIX + "erp/opentrade/list/trades", MapUtil.beanToMap(param));
+        JSONObject json = JSONObject.parseObject(result);
+        Integer code = json.getInteger("code");
+        if (code != 0) {
+            throw new ServiceException(result);
+        }
+        return json.getJSONArray("data").toJavaList(JSONObject.class);
+    }
+
+}