From cb84f5453ad54f710e76fc9d1edf6a2c2113ac13 Mon Sep 17 00:00:00 2001
From: buhuazhen <hua100783@gmail.com>
Date: 星期一, 09 三月 2026 17:29:23 +0800
Subject: [PATCH] feat(projectManagement): 新增项目管理核心模块和相关实体实现

---
 src/main/java/com/ruoyi/projectManagement/service/impl/handle/ShippingAddressHandleService.java |   36 +
 src/main/java/com/ruoyi/projectManagement/mapper/ShippingAddressMapper.java                     |   18 
 src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java            |   99 ++++
 src/main/java/com/ruoyi/projectManagement/dto/PlanStageDto.java                                 |   22 +
 src/main/java/com/ruoyi/projectManagement/service/PlanService.java                              |    3 
 src/main/resources/mapper/projectManagement/ContractInfoMapper.xml                              |   38 +
 src/main/java/com/ruoyi/projectManagement/service/impl/handle/ContractInfoHandleService.java    |   36 +
 src/main/java/com/ruoyi/projectManagement/service/impl/InfoServiceImpl.java                     |   37 +
 src/main/resources/mapper/projectManagement/ShippingAddressMapper.xml                           |   24 +
 pom.xml                                                                                         |    5 
 src/main/java/com/ruoyi/projectManagement/mapper/ContractInfoMapper.java                        |   18 
 src/main/java/com/ruoyi/projectManagement/pojo/ShippingAddress.java                             |   75 +++
 src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpFileServiceImpl.java                 |    3 
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java                          |   11 
 src/main/resources/mapper/projectManagement/InfoMapper.xml                                      |   51 ++
 src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java                     |    7 
 src/main/java/com/ruoyi/projectManagement/controller/InfoController.java                        |   33 +
 src/main/java/com/ruoyi/projectManagement/dto/ContractInfoDto.java                              |   91 ++++
 src/main/java/com/ruoyi/projectManagement/dto/ShippingAddressDto.java                           |   37 +
 src/main/java/com/ruoyi/common/enums/SaleEnum.java                                              |   23 +
 src/main/java/com/ruoyi/common/config/MybatisHandler.java                                       |    3 
 src/main/java/com/ruoyi/projectManagement/vo/SaveInfoVo.java                                    |   35 +
 src/main/java/com/ruoyi/projectManagement/mapper/InfoMapper.java                                |   18 
 src/main/java/com/ruoyi/projectManagement/dto/TeamDto.java                                      |   35 +
 src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java                                    |    5 
 src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java                                  |    4 
 src/main/java/com/ruoyi/common/enums/ReviewStatusEnum.java                                      |   27 +
 src/main/java/com/ruoyi/projectManagement/service/InfoService.java                              |   15 
 src/main/java/com/ruoyi/projectManagement/dto/SaveInfoDto.java                                  |   82 +++
 src/main/java/com/ruoyi/common/enums/PlanStageEnum.java                                         |   26 +
 src/main/java/com/ruoyi/projectManagement/pojo/Info.java                                        |  210 ++++++++++
 src/main/java/com/ruoyi/projectManagement/pojo/ContractInfo.java                                |  132 ++++++
 32 files changed, 1,249 insertions(+), 10 deletions(-)

diff --git a/pom.xml b/pom.xml
index c001bf7..553dbf2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -328,7 +328,10 @@
             <artifactId>hutool-all</artifactId>
             <version>5.8.43</version>
         </dependency>
-
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
 
     </dependencies>
 
diff --git a/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpFileServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpFileServiceImpl.java
index 6d4d4e5..f0e4716 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpFileServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpFileServiceImpl.java
@@ -64,7 +64,8 @@
             if (StrUtil.isNotBlank(attachmentIds)) {
                 List<SimpleFileVo> fileVos = Arrays.stream(attachmentIds.split(","))
                         .map(Long::valueOf)
-                        .map(it->collectMap.getOrDefault(it, (SimpleFileVo) Collections.emptyList()))
+                        .map(it->collectMap.getOrDefault(it, null))
+                        .filter(Objects::nonNull)
                         .collect(Collectors.toList());
                 setAttachmentList.accept(t, fileVos);
             }
diff --git a/src/main/java/com/ruoyi/common/config/MybatisHandler.java b/src/main/java/com/ruoyi/common/config/MybatisHandler.java
index adfaf53..2acd7ba 100644
--- a/src/main/java/com/ruoyi/common/config/MybatisHandler.java
+++ b/src/main/java/com/ruoyi/common/config/MybatisHandler.java
@@ -6,6 +6,7 @@
 import org.springframework.stereotype.Component;
 
 import java.time.LocalDateTime;
+import java.util.Optional;
 
 @Component
 public class MybatisHandler implements MetaObjectHandler {
@@ -22,6 +23,8 @@
         this.strictInsertFill(metaObject, "updateTime",  LocalDateTime.class, LocalDateTime.now());
         this.strictInsertFill(metaObject, "createUser", Integer.class, userId);
         this.strictInsertFill(metaObject, "updateUser", Integer.class, userId);
+        this.strictInsertFill(metaObject, "createUser", Long.class, Optional.ofNullable(userId).orElse(0).longValue());
+        this.strictInsertFill(metaObject, "updateUser", Long.class, Optional.ofNullable(userId).orElse(0).longValue());
         this.strictInsertFill(metaObject, "tenantId", Long.class, tenantId);
     }
 
diff --git a/src/main/java/com/ruoyi/common/enums/PlanStageEnum.java b/src/main/java/com/ruoyi/common/enums/PlanStageEnum.java
new file mode 100644
index 0000000..e7aedb9
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/enums/PlanStageEnum.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.enums;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import lombok.Getter;
+
+import java.io.Serializable;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Getter
+public enum PlanStageEnum implements BaseEnum<Integer>, Serializable {
+    TO_BEGIN(1, "寰呭紑濮�"),
+    ON_GOING(2, "杩涜涓�"),
+    ENDED(3, "宸茬粨鏉�");
+
+    private final Integer code;
+    private final String value;
+
+    PlanStageEnum(Integer code, String value) {
+        this.code = code;
+        this.value = value;
+    }
+}
diff --git a/src/main/java/com/ruoyi/common/enums/ReviewStatusEnum.java b/src/main/java/com/ruoyi/common/enums/ReviewStatusEnum.java
new file mode 100644
index 0000000..9fefc7a
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/enums/ReviewStatusEnum.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.enums;
+
+import lombok.Getter;
+
+import java.io.Serializable;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Getter
+public enum ReviewStatusEnum implements BaseEnum<Integer>, Serializable {
+    PENDING_REVIEW(0, "寰呭鏍�"),
+    APPROVED(1, "宸插鏍�"),
+    REJECTED(2, "瀹℃牳鏈�氳繃");
+
+    private final Integer code;
+    private final String value;
+
+    ReviewStatusEnum(Integer code, String value) {
+        this.code = code;
+        this.value = value;
+    }
+
+
+}
diff --git a/src/main/java/com/ruoyi/common/enums/SaleEnum.java b/src/main/java/com/ruoyi/common/enums/SaleEnum.java
new file mode 100644
index 0000000..381a766
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/enums/SaleEnum.java
@@ -0,0 +1,23 @@
+package com.ruoyi.common.enums;
+
+import lombok.Getter;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Getter
+public enum SaleEnum implements BaseEnum<Integer>{
+    SALE(1, "閿�鍞�"),
+    PURCHASE(2, "閲囪喘"),
+    MANAGEMENT(3, "椤圭洰");
+
+    private final Integer code;
+    private final String value;
+
+    SaleEnum(Integer code, String value) {
+        this.code = code;
+        this.value = value;
+    }
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/controller/InfoController.java b/src/main/java/com/ruoyi/projectManagement/controller/InfoController.java
new file mode 100644
index 0000000..23af4cc
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/controller/InfoController.java
@@ -0,0 +1,33 @@
+package com.ruoyi.projectManagement.controller;
+
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.projectManagement.service.InfoService;
+import com.ruoyi.projectManagement.vo.SaveInfoVo;
+import io.swagger.annotations.Api;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@RestController
+@RequestMapping("/projectManagement/info")
+@Api(value = "InfoController", tags = "椤圭洰绠$悊淇℃伅琛�(椤圭洰绠$悊绫诲瀷)")
+@RequiredArgsConstructor
+public class InfoController {
+
+    private final InfoService infoService;
+
+    @PostMapping("/save")
+    public AjaxResult save(@RequestBody @Valid SaveInfoVo saveInfoVo) {
+        infoService.save(saveInfoVo);
+        return AjaxResult.success();
+    }
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/dto/ContractInfoDto.java b/src/main/java/com/ruoyi/projectManagement/dto/ContractInfoDto.java
new file mode 100644
index 0000000..8a6a641
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/dto/ContractInfoDto.java
@@ -0,0 +1,91 @@
+package com.ruoyi.projectManagement.dto;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ContractInfoDto implements Serializable {
+    /**
+     *
+     */
+    private Long id;
+
+    /**
+     * 鍚嶇О
+     */
+    private String name;
+
+    /**
+     * 鎬у埆
+     */
+    private String sex;
+
+    /**
+     * 鐢熸棩
+     */
+    private String birthday;
+
+    /**
+     * 閮ㄩ棬
+     */
+    private String department;
+
+    /**
+     * 鑱屽姟
+     */
+    private String job;
+
+    /**
+     * 鎵嬫満鍙�
+     */
+    private String phoneNumber;
+
+    /**
+     * 閭
+     */
+    private String email;
+
+    /**
+     * QQ
+     */
+    private String qq;
+
+    /**
+     * 鍥哄畾鍙风爜
+     */
+    private String lineaFissa;
+
+    /**
+     * 寰俊
+     */
+    private String wx;
+
+    /**
+     * 绫嶈疮
+     */
+    private String origineEtnica;
+
+    /**
+     * 娉曚汉浠h〃
+     */
+    private String rappresentanteLegale;
+
+    /**
+     * 瀵瑰簲椤圭洰绠$悊淇℃伅id
+     */
+    private Long projectManagementInfoId;
+
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/dto/PlanStageDto.java b/src/main/java/com/ruoyi/projectManagement/dto/PlanStageDto.java
new file mode 100644
index 0000000..45c310a
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/dto/PlanStageDto.java
@@ -0,0 +1,22 @@
+package com.ruoyi.projectManagement.dto;
+
+import com.ruoyi.common.enums.PlanStageEnum;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class PlanStageDto implements Serializable {
+    private Long id;
+    private String name;
+    private PlanStageEnum planStageEnum;
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/dto/SaveInfoDto.java b/src/main/java/com/ruoyi/projectManagement/dto/SaveInfoDto.java
new file mode 100644
index 0000000..aa1d99c
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/dto/SaveInfoDto.java
@@ -0,0 +1,82 @@
+package com.ruoyi.projectManagement.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class SaveInfoDto implements Serializable {
+    private Long id;
+    private String no;
+    @NotBlank
+    private String title;
+    private Long clientId;
+    private String clientName;
+    // 寮曠敤鐨勭埗id
+    private Long projectManagementInfoParentId;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate establishTime;
+    // 椤圭洰绫诲瀷 id
+    @NotNull
+    private Long projectManagementPlanId;
+
+    private String source;
+
+    private Long managerId;
+    private String managerName;
+    private Long salesmanId;
+        private String salesmanName;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate planStartTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate planEndTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate actualStartTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate actualEndTime;
+
+    // 椤圭洰鐘舵��
+    private Integer status;
+
+    private Long departmentId;
+    private String departmentName;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate orderDate;
+
+
+    private String orderAmount;
+
+    private String remark;
+
+    private List<String> attachmentIds; // 闄勪欢ids
+
+    private List<TeamDto> teamList;
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/dto/ShippingAddressDto.java b/src/main/java/com/ruoyi/projectManagement/dto/ShippingAddressDto.java
new file mode 100644
index 0000000..4af844b
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/dto/ShippingAddressDto.java
@@ -0,0 +1,37 @@
+package com.ruoyi.projectManagement.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ShippingAddressDto implements Serializable {
+
+    private Long id;
+
+    /**
+     * 鏀惰揣浜�
+     */
+    private String consignee;
+
+    /**
+     * 鑱旂郴鏂瑰紡
+     */
+    private String contract;
+
+    /**
+     * 鍦板潃
+     */
+    private String address;
+
+
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/dto/TeamDto.java b/src/main/java/com/ruoyi/projectManagement/dto/TeamDto.java
new file mode 100644
index 0000000..89b0ee9
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/dto/TeamDto.java
@@ -0,0 +1,35 @@
+package com.ruoyi.projectManagement.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.util.Date;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class TeamDto implements Serializable {
+
+    private Integer userId;
+    private String userName;
+    private String userRoleId;
+    private String userRoleName;
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date joinTime;
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date departTime;
+    private String contact;
+    private String remark;
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/mapper/ContractInfoMapper.java b/src/main/java/com/ruoyi/projectManagement/mapper/ContractInfoMapper.java
new file mode 100644
index 0000000..2b9acec
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/mapper/ContractInfoMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.projectManagement.mapper;
+
+import com.ruoyi.projectManagement.pojo.ContractInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author buhuazhen
+* @description 閽堝琛ㄣ�恜roject_management_contract_info(椤圭洰鑱旂郴淇℃伅)銆戠殑鏁版嵁搴撴搷浣淢apper
+* @createDate 2026-03-09 16:38:09
+* @Entity com.ruoyi.projectManagement.pojo.ContractInfo
+*/
+public interface ContractInfoMapper extends BaseMapper<ContractInfo> {
+
+}
+
+
+
+
diff --git a/src/main/java/com/ruoyi/projectManagement/mapper/InfoMapper.java b/src/main/java/com/ruoyi/projectManagement/mapper/InfoMapper.java
new file mode 100644
index 0000000..6a23232
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/mapper/InfoMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.projectManagement.mapper;
+
+import com.ruoyi.projectManagement.pojo.Info;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author buhuazhen
+* @description 閽堝琛ㄣ�恜roject_management_info(椤圭洰绠$悊淇℃伅)銆戠殑鏁版嵁搴撴搷浣淢apper
+* @createDate 2026-03-09 13:57:50
+* @Entity com.ruoyi.projectManagement.pojo.Info
+*/
+public interface InfoMapper extends BaseMapper<Info> {
+
+}
+
+
+
+
diff --git a/src/main/java/com/ruoyi/projectManagement/mapper/ShippingAddressMapper.java b/src/main/java/com/ruoyi/projectManagement/mapper/ShippingAddressMapper.java
new file mode 100644
index 0000000..7cdecbf
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/mapper/ShippingAddressMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.projectManagement.mapper;
+
+import com.ruoyi.projectManagement.pojo.ShippingAddress;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author buhuazhen
+* @description 閽堝琛ㄣ�恜roject_management_shipping_address(鏀惰揣鍦板潃)銆戠殑鏁版嵁搴撴搷浣淢apper
+* @createDate 2026-03-09 16:28:07
+* @Entity com.ruoyi.projectManagement.pojo.ShippingAddress
+*/
+public interface ShippingAddressMapper extends BaseMapper<ShippingAddress> {
+
+}
+
+
+
+
diff --git a/src/main/java/com/ruoyi/projectManagement/pojo/ContractInfo.java b/src/main/java/com/ruoyi/projectManagement/pojo/ContractInfo.java
new file mode 100644
index 0000000..aab582f
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/pojo/ContractInfo.java
@@ -0,0 +1,132 @@
+package com.ruoyi.projectManagement.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.Data;
+
+/**
+ * 椤圭洰鑱旂郴淇℃伅
+ * @TableName project_management_contract_info
+ */
+@TableName(value ="project_management_contract_info")
+@Data
+public class ContractInfo implements Serializable {
+    /**
+     * 
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 鍚嶇О
+     */
+    @TableField(value = "name")
+    private String name;
+
+    /**
+     * 鎬у埆
+     */
+    @TableField(value = "sex")
+    private String sex;
+
+    /**
+     * 鐢熸棩
+     */
+    @TableField(value = "birthday")
+    private String birthday;
+
+    /**
+     * 閮ㄩ棬
+     */
+    @TableField(value = "department")
+    private String department;
+
+    /**
+     * 鑱屽姟
+     */
+    @TableField(value = "job")
+    private String job;
+
+    /**
+     * 鎵嬫満鍙�
+     */
+    @TableField(value = "phone_number")
+    private String phoneNumber;
+
+    /**
+     * 閭
+     */
+    @TableField(value = "email")
+    private String email;
+
+    /**
+     * QQ
+     */
+    @TableField(value = "qq")
+    private String qq;
+
+    /**
+     * 鍥哄畾鍙风爜
+     */
+    @TableField(value = "linea_fissa")
+    private String lineaFissa;
+
+    /**
+     * 寰俊
+     */
+    @TableField(value = "wx")
+    private String wx;
+
+    /**
+     * 绫嶈疮
+     */
+    @TableField(value = "origine_etnica")
+    private String origineEtnica;
+
+    /**
+     * 娉曚汉浠h〃
+     */
+    @TableField(value = "rappresentante_legale")
+    private String rappresentanteLegale;
+
+    /**
+     * 瀵瑰簲椤圭洰绠$悊淇℃伅id
+     */
+    @TableField(value = "project_management_info_id")
+    private Long projectManagementInfoId;
+
+    /**
+     * 
+     */
+    @TableField(value = "is_delete")
+    private Integer isDelete;
+
+    /**
+     * 
+     */
+    @TableField(value = "create_user", fill = FieldFill.INSERT)
+    private Long createUser;
+
+    /**
+     * 
+     */
+    @TableField(value = "update_user", fill = FieldFill.INSERT_UPDATE)
+    private Long updateUser;
+
+    /**
+     * 
+     */
+    @TableField(value = "create_time", fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    /**
+     * 
+     */
+    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/projectManagement/pojo/Info.java b/src/main/java/com/ruoyi/projectManagement/pojo/Info.java
new file mode 100644
index 0000000..a6e8ed5
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/pojo/Info.java
@@ -0,0 +1,210 @@
+package com.ruoyi.projectManagement.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.ruoyi.projectManagement.dto.PlanStageDto;
+import com.ruoyi.projectManagement.dto.TeamDto;
+import lombok.Data;
+
+/**
+ * 椤圭洰绠$悊淇℃伅
+ * @TableName project_management_info
+ */
+@TableName(value ="project_management_info",autoResultMap = true)
+@Data
+public class Info implements Serializable {
+    /**
+     * 
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 椤圭洰缂栧彿
+     */
+    @TableField(value = "no")
+    private String no;
+
+    /**
+     * 涓婚
+     */
+    @TableField(value = "title")
+    private String title;
+
+    /**
+     * 瀹㈡埛id
+     */
+    @TableField(value = "client_id")
+    private Long clientId;
+
+    /**
+     * 瀹㈡埛鍚嶇О
+     */
+    @TableField(value = "client_name")
+    private String clientName;
+
+    /**
+     * 绱㈠紩鐨勭埗椤圭洰id
+     */
+    @TableField(value = "project_management_info_parent_id")
+    private Long projectManagementInfoParentId;
+
+    /**
+     * 绔嬮」鏃堕棿
+     */
+    @TableField(value = "establish_time")
+    private LocalDate establishTime;
+
+    /**
+     * 椤圭洰闃舵id
+     */
+    @TableField(value = "project_management_plan_id")
+    private Long projectManagementPlanId;
+
+    /**
+     * 鏉ユ簮
+     */
+    @TableField(value = "source")
+    private String source;
+
+    /**
+     * 椤圭洰缁忕悊id
+     */
+    @TableField(value = "manager_id")
+    private Long managerId;
+
+    /**
+     * 椤圭洰缁忕悊鍚嶅瓧
+     */
+    @TableField(value = "manager_name")
+    private String managerName;
+
+    /**
+     * 涓氬姟鍛榠d
+     */
+    @TableField(value = "salesman_id")
+    private Long salesmanId;
+
+    /**
+     * 涓氬姟鍛樺悕瀛�
+     */
+    @TableField(value = "salesman_name")
+    private String salesmanName;
+
+    /**
+     * 
+     */
+    @TableField(value = "is_delete")
+    private Integer isDelete;
+
+    /**
+     * 
+     */
+    @TableField(value = "create_time",fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    /**
+     * 
+     */
+    @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    /**
+     * 
+     */
+    @TableField(value = "create_user",fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    /**
+     * 
+     */
+    @TableField(value = "update_user",fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    /**
+     * 璁″垝寮�濮嬫椂闂�
+     */
+    @TableField(value = "plan_start_time")
+    private LocalDate planStartTime;
+
+    /**
+     * 璁″垝缁撴潫鏃堕棿
+     */
+    @TableField(value = "plan_end_time")
+    private LocalDate planEndTime;
+
+    /**
+     * 瀹為檯寮�濮嬫椂闂�
+     */
+    @TableField(value = "actual_start_time")
+    private LocalDate actualStartTime;
+
+    /**
+     * 瀹為檯缁撴潫鏃ユ湡
+     */
+    @TableField(value = "actual_end_time")
+    private LocalDate actualEndTime;
+
+    /**
+     * 瀹℃牳鐘舵��
+     */
+    @TableField(value = "review_status")
+    private Integer reviewStatus;
+
+    /**
+     * 椤圭洰鐘舵��
+     */
+    @TableField(value = "status")
+    private Integer status;
+
+    /**
+     * 閮ㄩ棬id
+     */
+    @TableField(value = "department_id")
+    private Long departmentId;
+
+    /**
+     * 閮ㄩ棬鍚嶅瓧
+     */
+    @TableField(value = "department_name")
+    private String departmentName;
+
+    /**
+     * 璁㈠崟鏃ユ湡
+     */
+    @TableField(value = "order_date")
+    private LocalDate orderDate;
+
+    /**
+     * 璁㈠崟閲戦
+     */
+    @TableField(value = "order_amount")
+    private String orderAmount;
+
+    /**
+     * 澶囨敞
+     */
+    @TableField(value = "remark")
+    private String remark;
+
+    /**
+     * 闄勪欢
+     */
+    @TableField(value = "attachment")
+    private String attachment;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    @TableField(value = "plan_stage",typeHandler = JacksonTypeHandler.class)
+    private List<PlanStageDto> planStage;
+
+    @TableField(value = "team",typeHandler = JacksonTypeHandler.class)
+    private List<TeamDto> team;
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/projectManagement/pojo/ShippingAddress.java b/src/main/java/com/ruoyi/projectManagement/pojo/ShippingAddress.java
new file mode 100644
index 0000000..9b4a527
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/pojo/ShippingAddress.java
@@ -0,0 +1,75 @@
+package com.ruoyi.projectManagement.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.Data;
+
+/**
+ * 鏀惰揣鍦板潃
+ * @TableName project_management_shipping_address
+ */
+@TableName(value ="project_management_shipping_address")
+@Data
+public class ShippingAddress implements Serializable {
+    /**
+     * 
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 鏀惰揣浜�
+     */
+    @TableField(value = "consignee")
+    private String consignee;
+
+    /**
+     * 鑱旂郴鏂瑰紡
+     */
+    @TableField(value = "contract")
+    private String contract;
+
+    /**
+     * 鍦板潃
+     */
+    @TableField(value = "address")
+    private String address;
+
+    /**
+     * 
+     */
+    @TableField(value = "is_delete")
+    private Integer isDelete;
+
+    /**
+     * 
+     */
+    @TableField(value = "create_time",fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    /**
+     * 
+     */
+    @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    /**
+     * 
+     */
+    @TableField(value = "create_user",fill = FieldFill.INSERT)
+    private Long createUser;
+
+    /**
+     * 
+     */
+    @TableField(value = "update_user",fill = FieldFill.INSERT_UPDATE)
+    private Long updateUser;
+
+    @TableField(value = "project_management_info_id")
+    private Long projectManagementInfoId;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/projectManagement/service/InfoService.java b/src/main/java/com/ruoyi/projectManagement/service/InfoService.java
new file mode 100644
index 0000000..b796533
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/service/InfoService.java
@@ -0,0 +1,15 @@
+package com.ruoyi.projectManagement.service;
+
+import com.ruoyi.projectManagement.vo.SaveInfoVo;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+public interface InfoService {
+    void save(@NotNull SaveInfoVo saveInfoVo);
+
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/service/PlanService.java b/src/main/java/com/ruoyi/projectManagement/service/PlanService.java
index de2d38a..c0a8161 100644
--- a/src/main/java/com/ruoyi/projectManagement/service/PlanService.java
+++ b/src/main/java/com/ruoyi/projectManagement/service/PlanService.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.ruoyi.projectManagement.pojo.Plan;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.projectManagement.pojo.PlanNode;
 import com.ruoyi.projectManagement.vo.PlanVo;
 import com.ruoyi.projectManagement.vo.SavePlanNodeVo;
 import com.ruoyi.projectManagement.vo.SavePlanVo;
@@ -33,6 +34,8 @@
      */
     void savePlanNode(@NotNull Long planId,@Nullable List<SavePlanNodeVo> savePlanNodeVos);
 
+    List<PlanNode> getPlanNodeByPlanId(@NotNull Long planId);
+
     /**
      * 鍒犻櫎椤圭洰绠$悊璁″垝
      * @param id
diff --git a/src/main/java/com/ruoyi/projectManagement/service/impl/InfoServiceImpl.java b/src/main/java/com/ruoyi/projectManagement/service/impl/InfoServiceImpl.java
new file mode 100644
index 0000000..e6bd8c5
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/service/impl/InfoServiceImpl.java
@@ -0,0 +1,37 @@
+package com.ruoyi.projectManagement.service.impl;
+
+import com.ruoyi.common.enums.SaleEnum;
+import com.ruoyi.projectManagement.service.InfoService;
+import com.ruoyi.projectManagement.service.impl.handle.ContractInfoHandleService;
+import com.ruoyi.projectManagement.service.impl.handle.InfoHandleService;
+import com.ruoyi.projectManagement.service.impl.handle.ShippingAddressHandleService;
+import com.ruoyi.projectManagement.vo.SaveInfoVo;
+import com.ruoyi.sales.service.ISalesLedgerService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Service
+@RequiredArgsConstructor
+@Transactional(readOnly = true)
+public class InfoServiceImpl implements InfoService {
+    private final InfoHandleService infoHandleService;
+    private final ContractInfoHandleService contractInfoHandleService;
+    private final ShippingAddressHandleService shippingAddressHandleService;
+    private final ISalesLedgerService salesLedgerService;
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void save(SaveInfoVo saveInfoVo) {
+        // 淇濆瓨涓讳俊鎭�
+        Long infoId = infoHandleService.save(saveInfoVo.getInfo());
+        shippingAddressHandleService.save(infoId, saveInfoVo.getShippingAddress());
+        contractInfoHandleService.save(infoId, saveInfoVo.getContractInfo());
+        salesLedgerService.handleSalesLedgerProducts(infoId, saveInfoVo.getSalesLedgerProductList(), SaleEnum.MANAGEMENT);
+    }
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java b/src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java
index 0a32691..fd5f028 100644
--- a/src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java
+++ b/src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java
@@ -93,16 +93,17 @@
         });
     }
 
-    private List<PlanNode> getPlanNodeByPlanId(Long planId) {
+    @Override
+    public List<PlanNode> getPlanNodeByPlanId(Long planId) {
         return planNodeMapper.selectList(new LambdaQueryWrapper<PlanNode>()
                 .eq(PlanNode::getIsDelete, 0)
-                .eq(PlanNode::getProjectManagementPlanId, planId));
+                .eq(PlanNode::getProjectManagementPlanId, planId).orderByAsc(PlanNode::getSort));
     }
 
     private List<PlanNode> getPlanNodeByPlanIds(List<Long> planIds) {
         return planNodeMapper.selectList(new LambdaQueryWrapper<PlanNode>()
                 .eq(PlanNode::getIsDelete, 0)
-                .in(PlanNode::getProjectManagementPlanId, planIds));
+                .in(PlanNode::getProjectManagementPlanId, planIds).orderByAsc(PlanNode::getSort));
     }
 
 
diff --git a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ContractInfoHandleService.java b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ContractInfoHandleService.java
new file mode 100644
index 0000000..899bbf3
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ContractInfoHandleService.java
@@ -0,0 +1,36 @@
+package com.ruoyi.projectManagement.service.impl.handle;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.ruoyi.projectManagement.dto.ContractInfoDto;
+import com.ruoyi.projectManagement.mapper.ContractInfoMapper;
+import com.ruoyi.projectManagement.pojo.ContractInfo;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Nullable;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Component
+@RequiredArgsConstructor
+@Transactional(rollbackFor = Exception.class,readOnly = true)
+public class ContractInfoHandleService{
+
+    private final ContractInfoMapper contractInfoMapper;
+
+    @Transactional(rollbackFor = Exception.class)
+    public void save(@Nullable Long id, @NotNull ContractInfoDto contractInfoDto) {
+        ContractInfo contractInfo = BeanUtil.copyProperties(contractInfoDto, ContractInfo.class);
+        contractInfo.setProjectManagementInfoId(id);
+        if (contractInfoDto.getId() == null) {
+            contractInfoMapper.insert(contractInfo);
+        } else {
+            contractInfoMapper.updateById(contractInfo);
+        }
+    }
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java
new file mode 100644
index 0000000..74c392d
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java
@@ -0,0 +1,99 @@
+package com.ruoyi.projectManagement.service.impl.handle;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.common.enums.PlanStageEnum;
+import com.ruoyi.common.enums.ReviewStatusEnum;
+import com.ruoyi.common.utils.EnumUtil;
+import com.ruoyi.projectManagement.dto.PlanStageDto;
+import com.ruoyi.projectManagement.dto.SaveInfoDto;
+import com.ruoyi.projectManagement.mapper.InfoMapper;
+import com.ruoyi.projectManagement.pojo.Info;
+import com.ruoyi.projectManagement.pojo.PlanNode;
+import com.ruoyi.projectManagement.service.PlanService;
+import com.ruoyi.projectManagement.service.impl.PlanServiceImpl;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.validation.constraints.NotNull;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Component
+@RequiredArgsConstructor
+@Transactional(rollbackFor = Exception.class,readOnly = true)
+public class InfoHandleService {
+
+    private static final String GENERATE_SERIAL_NUMBER_PREFIX = "XM";
+
+    private final InfoMapper infoMapper;
+
+    private final PlanService planService;
+
+    @Transactional(rollbackFor = Exception.class)
+    public Long save(@NotNull SaveInfoDto saveInfoDto){
+        Info info = BeanUtil.copyProperties(saveInfoDto, Info.class);
+
+        // 闄勪欢鐗规畩澶勭悊
+        String attachmentIds = StrUtil.join(",", Optional.ofNullable(saveInfoDto.getAttachmentIds()).orElse(Collections.emptyList()));
+        info.setAttachment(attachmentIds);
+
+        // 鐢熸垚搴忓彿 (濡傛灉闇�瑕佽嚜鍔ㄧ敓鎴愮殑璇�)
+        if(StrUtil.isBlank(info.getNo())){
+            info.setNo(generateSerialNumber());
+        }
+        info.setTeam(saveInfoDto.getTeamList());
+        if(info.getId() == null){
+            // 鐢熸垚瀵瑰簲鐨勯樁娈靛叧绯绘暟鎹�
+            info.setPlanStage(getPlanStageList(info.getProjectManagementPlanId()));
+            // 鎻掑叆榛樿鐘舵��
+            info.setStatus(PlanStageEnum.TO_BEGIN.getCode());
+            info.setReviewStatus(ReviewStatusEnum.PENDING_REVIEW.getCode());
+            infoMapper.insert(info);
+        }else {
+            infoMapper.updateById(info);
+        }
+        return info.getId();
+    }
+
+
+    private List<PlanStageDto> getPlanStageList(@NotNull Long planId) {
+        List<PlanNode> planNodeByPlanId = planService.getPlanNodeByPlanId(planId);
+        return planNodeByPlanId.stream().map(it-> new PlanStageDto(it.getId(), it.getName(), PlanStageEnum.TO_BEGIN)).collect(Collectors.toList());
+    }
+
+
+    /**
+     * 鐢熸垚椤圭洰缂栧彿
+     * @return
+     */
+    private String generateSerialNumber() {
+        // 鑾峰彇褰撳墠鏃ユ湡
+        String date = DateUtil.format(DateUtil.date(), "yyyyMMdd");
+
+        // 鏌ヨ浠婂ぉ宸茬粡鐢熸垚鐨勬暟閲�
+        LambdaQueryWrapper<Info> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.likeRight(Info::getNo, GENERATE_SERIAL_NUMBER_PREFIX + date);
+
+        Long count = infoMapper.selectCount(queryWrapper);
+
+        // 搴忓彿 +1
+        Long serial = count + 1;
+
+        // 3浣嶈ˉ0
+        String serialStr = String.format("%03d", serial);
+
+        return GENERATE_SERIAL_NUMBER_PREFIX + date + serialStr;
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ShippingAddressHandleService.java b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ShippingAddressHandleService.java
new file mode 100644
index 0000000..6dba016
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ShippingAddressHandleService.java
@@ -0,0 +1,36 @@
+package com.ruoyi.projectManagement.service.impl.handle;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.ruoyi.projectManagement.dto.ShippingAddressDto;
+import com.ruoyi.projectManagement.mapper.ShippingAddressMapper;
+import com.ruoyi.projectManagement.pojo.ShippingAddress;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Nullable;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Component
+@RequiredArgsConstructor
+@Transactional(rollbackFor = Exception.class,readOnly = true)
+public class ShippingAddressHandleService {
+
+    private final ShippingAddressMapper shippingAddressMapper;
+
+    @Transactional(rollbackFor = Exception.class)
+    public void save(@Nullable Long infoId,@NotNull ShippingAddressDto shippingAddressDto){
+        ShippingAddress shippingAddress = BeanUtil.copyProperties(shippingAddressDto, ShippingAddress.class);
+        shippingAddress.setProjectManagementInfoId(infoId);
+        if (shippingAddressDto.getId() == null) {
+            shippingAddressMapper.insert(shippingAddress);
+        }else {
+            shippingAddressMapper.updateById(shippingAddress);
+        }
+    }
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoVo.java b/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoVo.java
new file mode 100644
index 0000000..749de19
--- /dev/null
+++ b/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoVo.java
@@ -0,0 +1,35 @@
+package com.ruoyi.projectManagement.vo;
+
+import com.ruoyi.projectManagement.dto.ContractInfoDto;
+import com.ruoyi.projectManagement.dto.SaveInfoDto;
+import com.ruoyi.projectManagement.dto.ShippingAddressDto;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.Valid;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/9
+ * @email 3038525872@qq.com
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class SaveInfoVo implements Serializable {
+
+    @Valid
+    private SaveInfoDto info;
+
+    @Valid
+    private ShippingAddressDto shippingAddress;
+
+    @Valid
+    private ContractInfoDto contractInfo;
+
+    private List<SalesLedgerProduct> salesLedgerProductList;
+}
diff --git a/src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java b/src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java
index 906184b..380c14d 100644
--- a/src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java
+++ b/src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java
@@ -1,5 +1,7 @@
 package com.ruoyi.projectManagement.vo;
 
+
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -22,7 +24,7 @@
     private Long id;
     @NotBlank
     private String name;
-    @NotBlank
+//    @NotBlank
     private String description;
 
     private List<String> attachmentIds;
@@ -30,4 +32,5 @@
     @Valid
     private List<SavePlanNodeVo> savePlanNodeList;
 
+
 }
diff --git a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
index c359fd3..f70bd01 100644
--- a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
+++ b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -4,11 +4,13 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.aftersalesservice.pojo.AfterSalesService;
+import com.ruoyi.common.enums.SaleEnum;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.sales.dto.LossProductModelDto;
 import com.ruoyi.sales.dto.MonthlyAmountDto;
 import com.ruoyi.sales.dto.SalesLedgerDto;
 import com.ruoyi.sales.pojo.SalesLedger;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.math.BigDecimal;
@@ -28,6 +30,8 @@
 
     int addOrUpdateSalesLedger(SalesLedgerDto salesLedgerDto);
 
+    void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type);
+
     SalesLedgerDto getSalesLedgerWithProducts(SalesLedgerDto salesLedgerDto);
 
     List getSalesNo();
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index 03635b4..9158fe3 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -15,8 +15,10 @@
 import com.ruoyi.basic.mapper.ProductModelMapper;
 import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.common.enums.FileNameType;
+import com.ruoyi.common.enums.SaleEnum;
 import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.EnumUtil;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -636,7 +638,7 @@
             // 4. 澶勭悊瀛愯〃鏁版嵁
             List<SalesLedgerProduct> productList = salesLedgerDto.getProductData();
             if (productList != null && !productList.isEmpty()) {
-                handleSalesLedgerProducts(salesLedger.getId(), productList, salesLedgerDto.getType());
+                handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class,salesLedgerDto.getType()));
                 updateMainContractAmount(
                         salesLedger.getId(),
                         productList,
@@ -734,7 +736,8 @@
     }
 
 
-    private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, Integer type) {
+    @Override
+    public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) {
         // 鎸塈D鍒嗙粍锛屽尯鍒嗘柊澧炲拰鏇存柊鐨勮褰�
         Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream()
                 .peek(p -> p.setSalesLedgerId(salesLedgerId))
@@ -746,14 +749,14 @@
         // 鎵ц鏇存柊鎿嶄綔
         if (!updateList.isEmpty()) {
             for (SalesLedgerProduct product : updateList) {
-                product.setType(type);
+                product.setType(type.getCode());
                 salesLedgerProductMapper.updateById(product);
             }
         }
         // 鎵ц鎻掑叆鎿嶄綔
         if (!insertList.isEmpty()) {
             for (SalesLedgerProduct salesLedgerProduct : insertList) {
-                salesLedgerProduct.setType(type);
+                salesLedgerProduct.setType(type.getCode());
                 salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
                 salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                 salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
diff --git a/src/main/resources/mapper/projectManagement/ContractInfoMapper.xml b/src/main/resources/mapper/projectManagement/ContractInfoMapper.xml
new file mode 100644
index 0000000..74033cb
--- /dev/null
+++ b/src/main/resources/mapper/projectManagement/ContractInfoMapper.xml
@@ -0,0 +1,38 @@
+<?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.ruoyi.projectManagement.mapper.ContractInfoMapper">
+
+    <resultMap id="BaseResultMap" type="com.ruoyi.projectManagement.pojo.ContractInfo">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="name" column="name" jdbcType="VARCHAR"/>
+            <result property="sex" column="sex" jdbcType="VARCHAR"/>
+            <result property="birthday" column="birthday" jdbcType="VARCHAR"/>
+            <result property="department" column="department" jdbcType="VARCHAR"/>
+            <result property="job" column="job" jdbcType="VARCHAR"/>
+            <result property="phoneNumber" column="phone_number" jdbcType="VARCHAR"/>
+            <result property="email" column="email" jdbcType="VARCHAR"/>
+            <result property="qq" column="qq" jdbcType="VARCHAR"/>
+            <result property="lineaFissa" column="linea_fissa" jdbcType="VARCHAR"/>
+            <result property="wx" column="wx" jdbcType="VARCHAR"/>
+            <result property="origineEtnica" column="origine_etnica" jdbcType="VARCHAR"/>
+            <result property="rappresentanteLegale" column="rappresentante_legale" jdbcType="VARCHAR"/>
+            <result property="projectManagementInfoId" column="project_management_info_id" jdbcType="BIGINT"/>
+            <result property="isDelete" column="is_delete" jdbcType="INTEGER"/>
+            <result property="createUser" column="create_user" jdbcType="BIGINT"/>
+            <result property="updateUser" column="update_user" jdbcType="BIGINT"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,name,sex,
+        birthday,department,job,
+        phone_number,email,qq,
+        linea_fissa,wx,origine_etnica,
+        rappresentante_legale,project_management_info_id,is_delete,
+        create_user,update_user,create_time,
+        update_time
+    </sql>
+</mapper>
diff --git a/src/main/resources/mapper/projectManagement/InfoMapper.xml b/src/main/resources/mapper/projectManagement/InfoMapper.xml
new file mode 100644
index 0000000..26449ef
--- /dev/null
+++ b/src/main/resources/mapper/projectManagement/InfoMapper.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.projectManagement.mapper.InfoMapper">
+
+    <resultMap id="BaseResultMap" type="com.ruoyi.projectManagement.pojo.Info">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="no" column="no" jdbcType="VARCHAR"/>
+            <result property="title" column="title" jdbcType="VARCHAR"/>
+            <result property="clientId" column="client_id" jdbcType="BIGINT"/>
+            <result property="clientName" column="client_name" jdbcType="VARCHAR"/>
+            <result property="projectManagementInfoParentId" column="project_management_info_parent_id" jdbcType="BIGINT"/>
+            <result property="establishTime" column="establish_time" jdbcType="TIMESTAMP"/>
+            <result property="projectManagementPlanId" column="project_management_plan_id" jdbcType="BIGINT"/>
+            <result property="source" column="source" jdbcType="VARCHAR"/>
+            <result property="managerId" column="manager_id" jdbcType="BIGINT"/>
+            <result property="managerName" column="manager_name" jdbcType="VARCHAR"/>
+            <result property="salesmanId" column="salesman_id" jdbcType="BIGINT"/>
+            <result property="salesmanName" column="salesman_name" jdbcType="VARCHAR"/>
+            <result property="isDelete" column="is_delete" jdbcType="INTEGER"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+            <result property="createUser" column="create_user" jdbcType="INTEGER"/>
+            <result property="updateUser" column="update_user" jdbcType="INTEGER"/>
+            <result property="planStartTime" column="plan_start_time" jdbcType="TIMESTAMP"/>
+            <result property="planEndTime" column="plan_end_time" jdbcType="TIMESTAMP"/>
+            <result property="actualStartTime" column="actual_start_time" jdbcType="TIMESTAMP"/>
+            <result property="actualEndTime" column="actual_end_time" jdbcType="TIMESTAMP"/>
+            <result property="status" column="status" jdbcType="INTEGER"/>
+            <result property="departmentId" column="department_id" jdbcType="BIGINT"/>
+            <result property="departmentName" column="department_name" jdbcType="VARCHAR"/>
+            <result property="orderDate" column="order_date" jdbcType="TIMESTAMP"/>
+            <result property="orderAmount" column="order_amount" jdbcType="VARCHAR"/>
+            <result property="remark" column="remark" jdbcType="VARCHAR"/>
+            <result property="attachment" column="attachment" jdbcType="VARCHAR"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,no,title,
+        client_id,client_name,project_management_info_parent_id,
+        establish_time,project_management_plan_id,source,
+        manager_id,manager_name,salesman_id,
+        salesman_name,is_delete,create_time,
+        update_time,create_user,update_user,
+        plan_start_time,plan_end_time,actual_start_time,
+        actual_end_time,status,department_id,
+        department_name,order_date,order_amount,
+        remark,attachment
+    </sql>
+</mapper>
diff --git a/src/main/resources/mapper/projectManagement/ShippingAddressMapper.xml b/src/main/resources/mapper/projectManagement/ShippingAddressMapper.xml
new file mode 100644
index 0000000..259d928
--- /dev/null
+++ b/src/main/resources/mapper/projectManagement/ShippingAddressMapper.xml
@@ -0,0 +1,24 @@
+<?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.ruoyi.projectManagement.mapper.ShippingAddressMapper">
+
+    <resultMap id="BaseResultMap" type="com.ruoyi.projectManagement.pojo.ShippingAddress">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="consignee" column="consignee" jdbcType="VARCHAR"/>
+            <result property="contract" column="contract" jdbcType="VARCHAR"/>
+            <result property="address" column="address" jdbcType="VARCHAR"/>
+            <result property="isDelete" column="is_delete" jdbcType="INTEGER"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+            <result property="createUser" column="create_user" jdbcType="BIGINT"/>
+            <result property="updateUser" column="update_user" jdbcType="BIGINT"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,consignee,contract,
+        address,is_delete,create_time,
+        update_time,create_user,update_user
+    </sql>
+</mapper>

--
Gitblit v1.9.3