فهرست منبع

物资-食材采购统计模块

huangguoce 14 ساعت پیش
والد
کامیت
3c795e06db
16فایلهای تغییر یافته به همراه727 افزوده شده و 41 حذف شده
  1. 79 1
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/controller/PsiFoodPurchaseController.java
  2. 1 1
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/domain/PsiFoodPurchaseBasic.java
  3. 35 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/domain/PsiFoodPurchaseChange.java
  4. 41 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/domain/PsiFoodPurchaseChangeDetail.java
  5. 2 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/domain/PsiFoodPurchaseDetail.java
  6. 3 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/PsiFoodPurchaseBasicMapper.java
  7. 16 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/PsiFoodPurchaseChangeDetailMapper.java
  8. 16 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/PsiFoodPurchaseChangeMapper.java
  9. 3 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/PsiFoodPurchaseDetailMapper.java
  10. 22 5
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/xml/PsiFoodPurchaseBasicMapper.xml
  11. 46 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/xml/PsiFoodPurchaseChangeDetailMapper.xml
  12. 44 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/xml/PsiFoodPurchaseChangeMapper.xml
  13. 13 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/xml/PsiFoodPurchaseDetailMapper.xml
  14. 347 33
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/service/PsiFoodPurchaseService.java
  15. 17 1
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/service/dto/PsiFoodPurchaseDto.java
  16. 42 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/service/dto/PsiFoodPurchaseExportDto.java

+ 79 - 1
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/controller/PsiFoodPurchaseController.java

@@ -2,9 +2,15 @@ package com.jeeplus.psimanage.foodPurchase.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jeeplus.common.excel.EasyExcelUtils;
+import com.jeeplus.common.excel.ExcelOptions;
+import com.jeeplus.common.excel.annotation.ExportMode;
 import com.jeeplus.common.utils.ResponseUtil;
+import com.jeeplus.logging.annotation.ApiLog;
+import com.jeeplus.logging.constant.enums.LogTypeEnum;
 import com.jeeplus.psimanage.foodPurchase.service.PsiFoodPurchaseService;
 import com.jeeplus.psimanage.foodPurchase.service.dto.PsiFoodPurchaseDto;
+import com.jeeplus.psimanage.foodPurchase.service.dto.PsiFoodPurchaseExportDto;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.http.ResponseEntity;
@@ -16,9 +22,12 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @RestController
 @Api(tags = "进销存-食材采购")
@@ -34,6 +43,28 @@ public class PsiFoodPurchaseController {
         psiFoodPurchaseService.updateStatusById(dto);
     }
 
+    @ApiOperation(value = "根据修改单id修改状态")
+    @PostMapping("/updateChangeStatusById")
+    public void updateChangeStatusById(@RequestBody PsiFoodPurchaseDto dto) {
+        psiFoodPurchaseService.updateChangeStatusById(dto);
+    }
+
+    @ApiOperation(value = "准备修改单")
+    @GetMapping("/prepareChange")
+    public ResponseEntity<String> prepareChange(@RequestParam String sourceBasicId) throws Exception {
+        String changeId = psiFoodPurchaseService.prepareChange(sourceBasicId);
+        return ResponseUtil.newInstance()
+                .add("businessTable", "psi_management_food_purchase_change")
+                .add("businessId", changeId)
+                .ok("操作成功");
+    }
+
+    @ApiOperation(value = "删除修改单")
+    @GetMapping("/removeChange")
+    public ResponseEntity<String> removeChange(@RequestParam String id) {
+        return ResponseEntity.ok(psiFoodPurchaseService.removeChange(id));
+    }
+
     @ApiOperation(value = "删除")
     @GetMapping("/remove")
     public ResponseEntity<String> remove(@RequestParam String id) {
@@ -50,18 +81,65 @@ public class PsiFoodPurchaseController {
                 .ok("操作成功");
     }
 
+    @ApiOperation(value = "保存修改单")
+    @PostMapping("/saveChange")
+    public ResponseEntity<String> saveChange(@RequestBody PsiFoodPurchaseDto dto) throws Exception {
+        String id = psiFoodPurchaseService.saveChange(dto);
+        return ResponseUtil.newInstance()
+                .add("businessTable", "psi_management_food_purchase_change")
+                .add("businessId", id)
+                .ok("操作成功");
+    }
+
+    @ApiOperation(value = "审批通过后应用修改")
+    @PostMapping("/approveChange")
+    public ResponseEntity<String> approveChange(@RequestBody PsiFoodPurchaseDto dto) throws Exception {
+        String id = psiFoodPurchaseService.approveChange(dto);
+        return ResponseUtil.newInstance()
+                .add("businessTable", "psi_management_food_purchase_change")
+                .add("businessId", id)
+                .ok("操作成功");
+    }
+
     @ApiOperation(value = "查询")
     @GetMapping("/findById")
-    public ResponseEntity<PsiFoodPurchaseDto> findById(@RequestParam String id) throws Exception {
+    public ResponseEntity<PsiFoodPurchaseDto> findById(@RequestParam String id) {
         return ResponseEntity.ok(psiFoodPurchaseService.findById(id));
     }
 
+    @ApiOperation(value = "根据修改单id查询")
+    @GetMapping("/findChangeById")
+    public ResponseEntity<PsiFoodPurchaseDto> findChangeById(@RequestParam String id) {
+        return ResponseEntity.ok(psiFoodPurchaseService.findChangeById(id));
+    }
+
     @ApiOperation(value = "列表查询")
     @GetMapping("/list")
     public ResponseEntity<IPage<PsiFoodPurchaseDto>> list(Page<PsiFoodPurchaseDto> page, PsiFoodPurchaseDto dto) throws Exception {
         return ResponseEntity.ok(psiFoodPurchaseService.list(page, dto));
     }
 
+    @ApiLog(value = "导出食材采购数据", type = LogTypeEnum.EXPORT)
+    @ApiOperation(value = "导出食材采购数据")
+    @GetMapping("/exportFile")
+    public void exportFile(Page<PsiFoodPurchaseDto> page, PsiFoodPurchaseDto dto, ExcelOptions options, HttpServletResponse response) throws Exception {
+        String fileName = options.getFilename();
+        String sheetName = options.getSheetName();
+        List<PsiFoodPurchaseExportDto> result;
+        if (ExportMode.current.equals(options.getMode())) {
+            result = psiFoodPurchaseService.exportList(page, dto);
+        } else if (ExportMode.selected.equals(options.getMode())) {
+            result = psiFoodPurchaseService.exportList(page, dto).stream().filter(item ->
+                    options.getSelectIds().contains(item.getId())
+            ).collect(Collectors.toList());
+        } else {
+            page.setSize(-1);
+            page.setCurrent(0);
+            result = psiFoodPurchaseService.exportList(page, dto);
+        }
+        EasyExcelUtils.newInstance().exportExcel(result, sheetName, PsiFoodPurchaseExportDto.class, fileName, null, response);
+    }
+
     @ApiOperation(value = "采购金额统计")
     @GetMapping("/statistics")
     public ResponseEntity<Map<String, BigDecimal>> statistics(PsiFoodPurchaseDto dto) {

+ 1 - 1
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/domain/PsiFoodPurchaseBasic.java

@@ -14,7 +14,7 @@ import java.util.List;
 @TableName("psi_management_food_purchase_basic")
 public class PsiFoodPurchaseBasic extends BaseEntity {
 
-    public static final String BIZ_CODE = "153";
+    public static final String BIZ_CODE = "154";
 
     private String remarks;
 

+ 35 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/domain/PsiFoodPurchaseChange.java

@@ -0,0 +1,35 @@
+package com.jeeplus.psimanage.foodPurchase.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jeeplus.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@TableName("psi_management_food_purchase_change")
+public class PsiFoodPurchaseChange extends BaseEntity {
+
+    private String sourceBasicId;
+
+    private String remarks;
+
+    private String purchaseNo;
+
+    private String handledBy;
+
+    private String handledByOffice;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date purchaseTime;
+
+    private BigDecimal totalPrice;
+
+    private String procInsId;
+
+    private String status;
+
+    private String processDefinitionId;
+}

+ 41 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/domain/PsiFoodPurchaseChangeDetail.java

@@ -0,0 +1,41 @@
+package com.jeeplus.psimanage.foodPurchase.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jeeplus.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@TableName("psi_management_food_purchase_change_detail")
+public class PsiFoodPurchaseChangeDetail extends BaseEntity {
+
+    private String changeId;
+
+    private String goodsName;
+
+    private String foodType;
+
+    private BigDecimal purchaseNumber;
+
+    private String unit;
+
+    private BigDecimal unitPrice;
+
+    private BigDecimal totalPrice;
+
+    private String storageArea;
+
+    private String shelfLife;
+
+    private String shelfLifeUnit;
+
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date expiryDate;
+
+    private Integer sort;
+
+    private String remarks;
+}

+ 2 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/domain/PsiFoodPurchaseDetail.java

@@ -30,6 +30,8 @@ public class PsiFoodPurchaseDetail extends BaseEntity {
 
     private String shelfLife;
 
+    private String shelfLifeUnit;
+
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private Date expiryDate;
 

+ 3 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/PsiFoodPurchaseBasicMapper.java

@@ -25,4 +25,7 @@ public interface PsiFoodPurchaseBasicMapper extends BaseMapper<PsiFoodPurchaseBa
     String getOfficeNameByOfficeId(String handledByOffice);
 
     BigDecimal statistics(@Param(Constants.WRAPPER) QueryWrapper<PsiFoodPurchaseDto> queryWrapper);
+
+    void updateFlowInfoById(@Param("id") String id, @Param("status") String status,
+                            @Param("procInsId") String procInsId, @Param("processDefinitionId") String processDefinitionId);
 }

+ 16 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/PsiFoodPurchaseChangeDetailMapper.java

@@ -0,0 +1,16 @@
+package com.jeeplus.psimanage.foodPurchase.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jeeplus.psimanage.foodPurchase.domain.PsiFoodPurchaseChangeDetail;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface PsiFoodPurchaseChangeDetailMapper extends BaseMapper<PsiFoodPurchaseChangeDetail> {
+
+    List<PsiFoodPurchaseChangeDetail> getByChangeId(String changeId);
+
+    List<String> getIdByChangeId(String changeId);
+
+    void deleteByChangeId(@Param("changeId") String changeId);
+}

+ 16 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/PsiFoodPurchaseChangeMapper.java

@@ -0,0 +1,16 @@
+package com.jeeplus.psimanage.foodPurchase.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jeeplus.psimanage.foodPurchase.domain.PsiFoodPurchaseChange;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface PsiFoodPurchaseChangeMapper extends BaseMapper<PsiFoodPurchaseChange> {
+
+    void updateStatusById(@Param("id") String id, @Param("status") String status);
+
+    PsiFoodPurchaseChange findActiveBySourceBasicId(@Param("sourceBasicId") String sourceBasicId);
+
+    List<String> getIdsBySourceBasicId(@Param("sourceBasicId") String sourceBasicId);
+}

+ 3 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/PsiFoodPurchaseDetailMapper.java

@@ -2,6 +2,7 @@ package com.jeeplus.psimanage.foodPurchase.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.jeeplus.psimanage.foodPurchase.domain.PsiFoodPurchaseDetail;
+import com.jeeplus.psimanage.oss.service.dto.WorkAttachmentDto;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -12,5 +13,7 @@ public interface PsiFoodPurchaseDetailMapper extends BaseMapper<PsiFoodPurchaseD
 
     List<String> getIdByBasicId(String basicId);
 
+    List<WorkAttachmentDto> getByAttachmentId(String id);
+
     void deleteByBasicId(@Param("basicId") String basicId);
 }

+ 22 - 5
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/xml/PsiFoodPurchaseBasicMapper.xml

@@ -8,6 +8,14 @@
         WHERE id = #{id}
     </update>
 
+    <update id="updateFlowInfoById">
+        UPDATE psi_management_food_purchase_basic
+        SET status = #{status},
+            proc_ins_id = #{procInsId},
+            process_definition_id = #{processDefinitionId}
+        WHERE id = #{id}
+    </update>
+
     <select id="findChildIds" resultType="java.lang.String">
         SELECT id
         FROM sys_office
@@ -24,16 +32,25 @@
             a.handled_by_office,
             a.purchase_time,
             a.total_price,
-            a.status,
-            a.proc_ins_id,
-            a.process_definition_id,
+            a.status AS formalStatus,
+            IFNULL(c.status, a.status) AS status,
+            c.id AS changeId,
+            c.status AS changeStatus,
+            c.purchase_time AS changePurchaseTime,
+            c.total_price AS changeTotalPrice,
+            IFNULL(c.proc_ins_id, a.proc_ins_id) AS procInsId,
+            IFNULL(c.process_definition_id, a.process_definition_id) AS processDefinitionId,
             su.name AS handledByName,
             so.name AS handledByOfficeName,
-            art.ID_ AS task_id
+            art.ID_ AS taskId
         FROM psi_management_food_purchase_basic a
+        LEFT JOIN psi_management_food_purchase_change c
+            ON c.source_basic_id = a.id
+            AND c.del_flag = 0
+            AND c.status IN ('1', '2', '3', '4')
         LEFT JOIN sys_user su ON a.handled_by = su.id
         LEFT JOIN sys_office so ON a.handled_by_office = so.id
-        LEFT JOIN act_ru_task art ON a.proc_ins_id = art.PROC_INST_ID_
+        LEFT JOIN act_ru_task art ON IFNULL(c.proc_ins_id, a.proc_ins_id) = art.PROC_INST_ID_
         ${ew.customSqlSegment}
         ORDER BY a.update_time DESC
     </select>

+ 46 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/xml/PsiFoodPurchaseChangeDetailMapper.xml

@@ -0,0 +1,46 @@
+<?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.jeeplus.psimanage.foodPurchase.mapper.PsiFoodPurchaseChangeDetailMapper">
+
+    <select id="getByChangeId" resultType="com.jeeplus.psimanage.foodPurchase.domain.PsiFoodPurchaseChangeDetail">
+        SELECT
+            id,
+            create_by_id,
+            create_time,
+            update_by_id,
+            update_time,
+            del_flag,
+            tenant_id,
+            remarks,
+            change_id,
+            goods_name,
+            food_type,
+            purchase_number,
+            unit,
+            unit_price,
+            total_price,
+            storage_area,
+            shelf_life,
+            shelf_life_unit,
+            expiry_date,
+            sort
+        FROM psi_management_food_purchase_change_detail
+        WHERE change_id = #{changeId}
+          AND del_flag = 0
+        ORDER BY sort ASC, create_time ASC
+    </select>
+
+    <select id="getIdByChangeId" resultType="java.lang.String">
+        SELECT id
+        FROM psi_management_food_purchase_change_detail
+        WHERE change_id = #{changeId}
+          AND del_flag = 0
+    </select>
+
+    <update id="deleteByChangeId">
+        UPDATE psi_management_food_purchase_change_detail
+        SET del_flag = 1
+        WHERE change_id = #{changeId}
+          AND del_flag = 0
+    </update>
+</mapper>

+ 44 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/xml/PsiFoodPurchaseChangeMapper.xml

@@ -0,0 +1,44 @@
+<?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.jeeplus.psimanage.foodPurchase.mapper.PsiFoodPurchaseChangeMapper">
+
+    <update id="updateStatusById">
+        UPDATE psi_management_food_purchase_change
+        SET status = #{status}
+        WHERE id = #{id}
+    </update>
+
+    <select id="findActiveBySourceBasicId" resultType="com.jeeplus.psimanage.foodPurchase.domain.PsiFoodPurchaseChange">
+        SELECT
+            id,
+            source_basic_id,
+            remarks,
+            purchase_no,
+            handled_by,
+            handled_by_office,
+            purchase_time,
+            total_price,
+            proc_ins_id,
+            status,
+            process_definition_id,
+            create_time,
+            create_by_id,
+            update_time,
+            update_by_id,
+            del_flag,
+            tenant_id
+        FROM psi_management_food_purchase_change
+        WHERE source_basic_id = #{sourceBasicId}
+          AND del_flag = 0
+          AND status IN ('1', '2', '3', '4')
+        ORDER BY update_time DESC, create_time DESC
+        LIMIT 1
+    </select>
+
+    <select id="getIdsBySourceBasicId" resultType="java.lang.String">
+        SELECT id
+        FROM psi_management_food_purchase_change
+        WHERE source_basic_id = #{sourceBasicId}
+          AND del_flag = 0
+    </select>
+</mapper>

+ 13 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/mapper/xml/PsiFoodPurchaseDetailMapper.xml

@@ -21,6 +21,7 @@
             total_price,
             storage_area,
             shelf_life,
+            shelf_life_unit,
             expiry_date,
             sort
         FROM psi_management_food_purchase_detail
@@ -36,6 +37,18 @@
           AND del_flag = 0
     </select>
 
+    <select id="getByAttachmentId" resultType="com.jeeplus.psimanage.oss.service.dto.WorkAttachmentDto">
+        SELECT
+            id,
+            url,
+            attachment_name AS `name`,
+            create_by_id AS `by`,
+            create_time
+        FROM work_attachment
+        WHERE del_flag = 0
+          AND attachment_id = #{id}
+    </select>
+
     <update id="deleteByBasicId">
         UPDATE psi_management_food_purchase_detail
         SET del_flag = 1

+ 347 - 33
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/service/PsiFoodPurchaseService.java

@@ -8,12 +8,20 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jeeplus.common.TokenProvider;
 import com.jeeplus.flowable.feign.IFlowableApi;
 import com.jeeplus.psimanage.foodPurchase.domain.PsiFoodPurchaseBasic;
+import com.jeeplus.psimanage.foodPurchase.domain.PsiFoodPurchaseChange;
+import com.jeeplus.psimanage.foodPurchase.domain.PsiFoodPurchaseChangeDetail;
 import com.jeeplus.psimanage.foodPurchase.domain.PsiFoodPurchaseDetail;
 import com.jeeplus.psimanage.foodPurchase.mapper.PsiFoodPurchaseBasicMapper;
+import com.jeeplus.psimanage.foodPurchase.mapper.PsiFoodPurchaseChangeDetailMapper;
+import com.jeeplus.psimanage.foodPurchase.mapper.PsiFoodPurchaseChangeMapper;
 import com.jeeplus.psimanage.foodPurchase.mapper.PsiFoodPurchaseDetailMapper;
+import com.jeeplus.psimanage.oss.service.dto.WorkAttachmentDto;
+import com.jeeplus.psimanage.purchase.service.PsiMaterialService;
 import com.jeeplus.psimanage.foodPurchase.service.dto.PsiFoodPurchaseDto;
+import com.jeeplus.psimanage.foodPurchase.service.dto.PsiFoodPurchaseExportDto;
 import com.jeeplus.psimanage.serialNumTpl.service.PsiSerialnumTplService;
 import com.jeeplus.sys.feign.IUserApi;
+import com.jeeplus.sys.feign.IWorkAttachmentApi;
 import com.jeeplus.sys.service.dto.UserDTO;
 import com.jeeplus.utils.StringUtils;
 import org.springframework.beans.BeanUtils;
@@ -34,6 +42,12 @@ import java.util.UUID;
 @Transactional
 public class PsiFoodPurchaseService {
 
+    private static final String CHANGE_STATUS_DRAFT = "1";
+    private static final String CHANGE_STATUS_IN_APPROVAL = "2";
+    private static final String CHANGE_STATUS_REVOKED = "3";
+    private static final String CHANGE_STATUS_REJECTED = "4";
+    private static final String CHANGE_STATUS_APPROVED = "5";
+
     @Resource
     private PsiFoodPurchaseBasicMapper basicMapper;
 
@@ -41,18 +55,54 @@ public class PsiFoodPurchaseService {
     private PsiFoodPurchaseDetailMapper detailMapper;
 
     @Resource
+    private PsiFoodPurchaseChangeMapper changeMapper;
+
+    @Resource
+    private PsiFoodPurchaseChangeDetailMapper changeDetailMapper;
+
+    @Resource
     private PsiSerialnumTplService psiSerialnumTplService;
 
     @Resource
+    private PsiMaterialService psiMaterialService;
+
+    @Resource
     private IFlowableApi flowTaskService;
 
+    @Resource
+    private IWorkAttachmentApi workAttachmentApi;
+
     public void updateStatusById(PsiFoodPurchaseDto dto) {
         basicMapper.updateStatusById(dto.getId(), dto.getStatus());
     }
 
+    public void updateChangeStatusById(PsiFoodPurchaseDto dto) {
+        changeMapper.updateStatusById(dto.getId(), dto.getStatus());
+    }
+
+    public String removeChange(String changeId) {
+        PsiFoodPurchaseChange change = changeMapper.selectById(changeId);
+        if (change == null) {
+            throw new RuntimeException("修改单不存在");
+        }
+        workAttachmentApi.deleteByAttachmentId(changeId);
+        changeDetailMapper.deleteByChangeId(changeId);
+        changeMapper.deleteById(changeId);
+        return "操作成功";
+    }
+
     public String remove(String id) {
+        workAttachmentApi.deleteByAttachmentId(id);
         basicMapper.deleteById(id);
         detailMapper.deleteByBasicId(id);
+        List<String> changeIds = changeMapper.getIdsBySourceBasicId(id);
+        if (CollectionUtils.isNotEmpty(changeIds)) {
+            changeIds.forEach(changeId -> {
+                workAttachmentApi.deleteByAttachmentId(changeId);
+                changeMapper.deleteById(changeId);
+                changeDetailMapper.deleteByChangeId(changeId);
+            });
+        }
         return "操作成功";
     }
 
@@ -64,6 +114,48 @@ public class PsiFoodPurchaseService {
         return add(dto, userDTO);
     }
 
+    public String saveChange(PsiFoodPurchaseDto dto) throws Exception {
+        UserDTO userDTO = SpringUtil.getBean(IUserApi.class).getByToken(TokenProvider.getCurrentToken());
+        if (StringUtils.isBlank(dto.getId()) || "false".equals(dto.getId())) {
+            throw new RuntimeException("修改单不存在");
+        }
+        return updateChange(dto, userDTO);
+    }
+
+    public String approveChange(PsiFoodPurchaseDto dto) throws Exception {
+        UserDTO userDTO = SpringUtil.getBean(IUserApi.class).getByToken(TokenProvider.getCurrentToken());
+        String changeId = updateChange(dto, userDTO);
+        PsiFoodPurchaseChange change = changeMapper.selectById(changeId);
+        if (change == null) {
+            throw new RuntimeException("修改单不存在");
+        }
+        PsiFoodPurchaseBasic oldBasic = basicMapper.selectById(change.getSourceBasicId());
+        if (oldBasic == null) {
+            throw new RuntimeException("食材采购单不存在");
+        }
+
+        PsiFoodPurchaseBasic basic = new PsiFoodPurchaseBasic();
+        basic.setId(oldBasic.getId());
+        basic.setPurchaseNo(oldBasic.getPurchaseNo());
+        basic.setHandledBy(change.getHandledBy());
+        basic.setHandledByOffice(change.getHandledByOffice());
+        basic.setPurchaseTime(change.getPurchaseTime());
+        basic.setTotalPrice(change.getTotalPrice());
+        basic.setRemarks(change.getRemarks());
+        basic.setStatus(CHANGE_STATUS_APPROVED);
+        basic.setProcInsId(change.getProcInsId());
+        basic.setProcessDefinitionId(change.getProcessDefinitionId());
+        basic.setUpdateById(userDTO.getId());
+        basic.setUpdateTime(new Date());
+        basicMapper.updateById(basic);
+
+        syncFormalDetails(convertChangeDetails(changeDetailMapper.getByChangeId(changeId)), oldBasic.getId(), userDTO);
+        updateAttachmentFiles(resolveAttachmentFiles(dto.getFiles(), changeId), userDTO, oldBasic.getId());
+        changeMapper.updateStatusById(changeId, CHANGE_STATUS_APPROVED);
+        basicMapper.updateFlowInfoById(oldBasic.getId(), CHANGE_STATUS_APPROVED, change.getProcInsId(), change.getProcessDefinitionId());
+        return changeId;
+    }
+
     public String add(PsiFoodPurchaseDto dto, UserDTO userDTO) throws Exception {
         validateDetailInfos(dto.getDetailInfos());
         String id = UUID.randomUUID().toString().replace("-", "");
@@ -85,6 +177,7 @@ public class PsiFoodPurchaseService {
         basicMapper.insert(basic);
 
         saveDetails(dto.getDetailInfos(), id, userDTO);
+        saveAttachmentFiles(dto.getFiles(), userDTO, id);
         return id;
     }
 
@@ -110,38 +203,59 @@ public class PsiFoodPurchaseService {
         basic.setUpdateTime(new Date());
         basicMapper.updateById(basic);
 
-        List<String> dbIds = detailMapper.getIdByBasicId(dto.getId());
-        List<String> liveIds = new ArrayList<>();
-        if (CollectionUtils.isNotEmpty(dto.getDetailInfos())) {
-            int sort = 1;
-            for (PsiFoodPurchaseDetail detail : dto.getDetailInfos()) {
-                normalizeDetail(detail, sort++);
-                detail.setBasicId(dto.getId());
-                if (StringUtils.isNotBlank(detail.getId())) {
-                    liveIds.add(detail.getId());
-                }
-                if (StringUtils.isBlank(detail.getId()) || detailMapper.selectById(detail.getId()) == null) {
-                    detail.setId(UUID.randomUUID().toString().replace("-", ""));
-                    detail.setCreateById(userDTO.getId());
-                    detail.setCreateTime(new Date());
-                    detail.setUpdateById(userDTO.getId());
-                    detail.setUpdateTime(new Date());
-                    detail.setDelFlag(0);
-                    detailMapper.insert(detail);
-                    liveIds.add(detail.getId());
-                } else {
-                    detail.setUpdateById(userDTO.getId());
-                    detail.setUpdateTime(new Date());
-                    detailMapper.updateById(detail);
-                }
-            }
+        syncFormalDetails(dto.getDetailInfos(), dto.getId(), userDTO);
+        updateAttachmentFiles(dto.getFiles(), userDTO, dto.getId());
+        return dto.getId();
+    }
+
+    public String prepareChange(String sourceBasicId) throws Exception {
+        UserDTO userDTO = SpringUtil.getBean(IUserApi.class).getByToken(TokenProvider.getCurrentToken());
+        PsiFoodPurchaseBasic basic = basicMapper.selectById(sourceBasicId);
+        if (basic == null) {
+            throw new RuntimeException("食材采购单不存在");
         }
-        if (CollectionUtils.isNotEmpty(dbIds)) {
-            dbIds.stream()
-                    .filter(dbId -> !liveIds.contains(dbId))
-                    .forEach(detailMapper::deleteById);
+        PsiFoodPurchaseChange activeChange = changeMapper.findActiveBySourceBasicId(sourceBasicId);
+        if (activeChange != null) {
+            return activeChange.getId();
         }
-        return dto.getId();
+
+        String changeId = UUID.randomUUID().toString().replace("-", "");
+        PsiFoodPurchaseChange change = new PsiFoodPurchaseChange();
+        change.setId(changeId);
+        change.setSourceBasicId(sourceBasicId);
+        change.setPurchaseNo(basic.getPurchaseNo());
+        change.setHandledBy(basic.getHandledBy());
+        change.setHandledByOffice(basic.getHandledByOffice());
+        change.setPurchaseTime(basic.getPurchaseTime());
+        change.setTotalPrice(basic.getTotalPrice());
+        change.setRemarks(basic.getRemarks());
+        change.setStatus(CHANGE_STATUS_DRAFT);
+        change.setCreateById(userDTO.getId());
+        change.setCreateTime(new Date());
+        change.setUpdateById(userDTO.getId());
+        change.setUpdateTime(new Date());
+        change.setDelFlag(0);
+        change.setTenantId(basic.getTenantId());
+        changeMapper.insert(change);
+
+        List<PsiFoodPurchaseDetail> details = detailMapper.getByBasicId(sourceBasicId);
+        int sort = 1;
+        for (PsiFoodPurchaseDetail detail : details) {
+            PsiFoodPurchaseChangeDetail changeDetail = new PsiFoodPurchaseChangeDetail();
+            BeanUtils.copyProperties(detail, changeDetail);
+            changeDetail.setId(UUID.randomUUID().toString().replace("-", ""));
+            changeDetail.setChangeId(changeId);
+            changeDetail.setSort(sort++);
+            changeDetail.setCreateById(userDTO.getId());
+            changeDetail.setCreateTime(new Date());
+            changeDetail.setUpdateById(userDTO.getId());
+            changeDetail.setUpdateTime(new Date());
+            changeDetail.setDelFlag(0);
+            changeDetail.setTenantId(detail.getTenantId());
+            changeDetailMapper.insert(changeDetail);
+        }
+        saveAttachmentFiles(loadAttachmentFiles(sourceBasicId), userDTO, changeId);
+        return changeId;
     }
 
     public PsiFoodPurchaseDto findById(String id) {
@@ -155,6 +269,26 @@ public class PsiFoodPurchaseService {
         dto.setHandledBy(basicMapper.getUserNameByUserId(basic.getHandledBy()));
         dto.setHandledByOfficeName(basicMapper.getOfficeNameByOfficeId(basic.getHandledByOffice()));
         dto.setDetailInfos(detailMapper.getByBasicId(id));
+        dto.setFiles(loadAttachmentFiles(id));
+        return dto;
+    }
+
+    public PsiFoodPurchaseDto findChangeById(String id) {
+        PsiFoodPurchaseDto dto = new PsiFoodPurchaseDto();
+        PsiFoodPurchaseChange change = changeMapper.selectById(id);
+        if (change == null) {
+            return dto;
+        }
+        BeanUtils.copyProperties(change, dto);
+        dto.setHandledById(change.getHandledBy());
+        dto.setHandledBy(basicMapper.getUserNameByUserId(change.getHandledBy()));
+        dto.setHandledByOfficeName(basicMapper.getOfficeNameByOfficeId(change.getHandledByOffice()));
+        dto.setDetailInfos(convertChangeDetails(changeDetailMapper.getByChangeId(id)));
+        List<WorkAttachmentDto> files = loadAttachmentFiles(id);
+        if (CollectionUtils.isEmpty(files) && StringUtils.isNotBlank(change.getSourceBasicId())) {
+            files = loadAttachmentFiles(change.getSourceBasicId());
+        }
+        dto.setFiles(files);
         return dto;
     }
 
@@ -162,7 +296,7 @@ public class PsiFoodPurchaseService {
         QueryWrapper<PsiFoodPurchaseDto> queryWrapper = buildListWrapper(dto);
         IPage<PsiFoodPurchaseDto> pageData = basicMapper.findList(page, queryWrapper);
         pageData.getRecords().forEach(item -> {
-            if ("2".equals(item.getStatus()) && StringUtils.isNotBlank(item.getTaskId())) {
+            if (CHANGE_STATUS_IN_APPROVAL.equals(item.getStatus()) && StringUtils.isNotBlank(item.getTaskId())) {
                 item.setAuditUserIds(flowTaskService.getTaskAuditUsers(item.getTaskId()));
             }
         });
@@ -175,11 +309,67 @@ public class PsiFoodPurchaseService {
         return total == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : total.setScale(2, RoundingMode.HALF_UP);
     }
 
+    public List<PsiFoodPurchaseExportDto> exportList(Page<PsiFoodPurchaseDto> page, PsiFoodPurchaseDto dto) {
+        IPage<PsiFoodPurchaseDto> pageData = basicMapper.findList(page, buildListWrapper(dto));
+        List<PsiFoodPurchaseExportDto> result = new ArrayList<>();
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        pageData.getRecords().forEach(item -> {
+            List<PsiFoodPurchaseDetail> details = detailMapper.getByBasicId(item.getId());
+            if (CollectionUtils.isEmpty(details)) {
+                return;
+            }
+            details.forEach(detail -> {
+                PsiFoodPurchaseExportDto exportDto = new PsiFoodPurchaseExportDto();
+                exportDto.setId(detail.getId());
+                exportDto.setPurchaseNo(item.getPurchaseNo());
+                exportDto.setGoodsName(detail.getGoodsName());
+                exportDto.setFoodType(detail.getFoodType());
+                exportDto.setPurchaseNumber(formatNumber(detail.getPurchaseNumber()));
+                exportDto.setUnit(detail.getUnit());
+                exportDto.setUnitPrice(formatNumber(detail.getUnitPrice()));
+                exportDto.setTotalPrice(formatNumber(detail.getTotalPrice()));
+                exportDto.setStorageArea(detail.getStorageArea());
+                exportDto.setShelfLife(formatShelfLife(detail.getShelfLife(), detail.getShelfLifeUnit()));
+                exportDto.setExpiryDate(detail.getExpiryDate() == null ? "" : dateFormat.format(detail.getExpiryDate()));
+                result.add(exportDto);
+            });
+        });
+        return result;
+    }
+
+    private String updateChange(PsiFoodPurchaseDto dto, UserDTO userDTO) throws Exception {
+        validateDetailInfos(dto.getDetailInfos());
+        PsiFoodPurchaseChange oldInfo = changeMapper.selectById(dto.getId());
+        if (oldInfo == null) {
+            throw new RuntimeException("修改单不存在");
+        }
+
+        PsiFoodPurchaseChange change = new PsiFoodPurchaseChange();
+        BeanUtils.copyProperties(dto, change);
+        change.setId(dto.getId());
+        change.setSourceBasicId(StringUtils.isNotBlank(dto.getSourceBasicId()) ? dto.getSourceBasicId() : oldInfo.getSourceBasicId());
+        change.setPurchaseNo(StringUtils.isNotBlank(dto.getPurchaseNo()) ? dto.getPurchaseNo() : oldInfo.getPurchaseNo());
+        change.setHandledBy(StringUtils.isNotBlank(dto.getHandledById()) ? dto.getHandledById() : oldInfo.getHandledBy());
+        change.setHandledByOffice(resolveOfficeId(dto.getHandledByOffice(), userDTO, oldInfo.getHandledByOffice()));
+        change.setPurchaseTime(Objects.nonNull(dto.getPurchaseTime()) ? dto.getPurchaseTime() : oldInfo.getPurchaseTime());
+        change.setTotalPrice(calculateBasicTotal(dto.getDetailInfos()));
+        change.setStatus(StringUtils.isNotBlank(dto.getStatus()) ? dto.getStatus() : oldInfo.getStatus());
+        change.setProcInsId(StringUtils.isNotBlank(dto.getProcInsId()) ? dto.getProcInsId() : oldInfo.getProcInsId());
+        change.setProcessDefinitionId(StringUtils.isNotBlank(dto.getProcessDefinitionId()) ? dto.getProcessDefinitionId() : oldInfo.getProcessDefinitionId());
+        change.setUpdateById(userDTO.getId());
+        change.setUpdateTime(new Date());
+        changeMapper.updateById(change);
+
+        syncChangeDetails(dto.getDetailInfos(), dto.getId(), userDTO);
+        updateAttachmentFiles(dto.getFiles(), userDTO, dto.getId());
+        return dto.getId();
+    }
+
     private QueryWrapper<PsiFoodPurchaseDto> buildListWrapper(PsiFoodPurchaseDto dto) {
         QueryWrapper<PsiFoodPurchaseDto> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq("a.del_flag", 0);
         if (StringUtils.isNotBlank(dto.getPurchaseNo())) {
-            queryWrapper.like("a.purchase_no", dto.getPurchaseNo());
+            queryWrapper.eq("a.purchase_no", dto.getPurchaseNo());
         }
         if (StringUtils.isNotBlank(dto.getHandledBy())) {
             queryWrapper.eq("a.handled_by", dto.getHandledBy());
@@ -194,7 +384,7 @@ public class PsiFoodPurchaseService {
             }
         }
         if (StringUtils.isNotBlank(dto.getStatus())) {
-            queryWrapper.eq("a.status", dto.getStatus());
+            queryWrapper.apply("IFNULL(c.status, a.status) = {0}", dto.getStatus());
         }
         if (dto.getPurchaseTimes() != null && dto.getPurchaseTimes().length == 2
                 && StringUtils.isNotBlank(dto.getPurchaseTimes()[0]) && StringUtils.isNotBlank(dto.getPurchaseTimes()[1])) {
@@ -206,6 +396,9 @@ public class PsiFoodPurchaseService {
     private QueryWrapper<PsiFoodPurchaseDto> buildStatisticsWrapper(PsiFoodPurchaseDto dto) {
         QueryWrapper<PsiFoodPurchaseDto> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq("a.del_flag", 0);
+        if (StringUtils.isNotBlank(dto.getPurchaseNo())) {
+            queryWrapper.eq("a.purchase_no", dto.getPurchaseNo());
+        }
         if (StringUtils.isNotBlank(dto.getHandledBy())) {
             queryWrapper.eq("a.handled_by", dto.getHandledBy());
         }
@@ -251,6 +444,85 @@ public class PsiFoodPurchaseService {
         }
     }
 
+    private void syncFormalDetails(List<PsiFoodPurchaseDetail> detailInfos, String basicId, UserDTO userDTO) {
+        List<String> dbIds = detailMapper.getIdByBasicId(basicId);
+        List<String> liveIds = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(detailInfos)) {
+            int sort = 1;
+            for (PsiFoodPurchaseDetail detail : detailInfos) {
+                normalizeDetail(detail, sort++);
+                detail.setBasicId(basicId);
+                if (StringUtils.isNotBlank(detail.getId())) {
+                    liveIds.add(detail.getId());
+                }
+                if (StringUtils.isBlank(detail.getId()) || detailMapper.selectById(detail.getId()) == null) {
+                    detail.setId(UUID.randomUUID().toString().replace("-", ""));
+                    detail.setCreateById(userDTO.getId());
+                    detail.setCreateTime(new Date());
+                    detail.setUpdateById(userDTO.getId());
+                    detail.setUpdateTime(new Date());
+                    detail.setDelFlag(0);
+                    detailMapper.insert(detail);
+                    liveIds.add(detail.getId());
+                } else {
+                    detail.setUpdateById(userDTO.getId());
+                    detail.setUpdateTime(new Date());
+                    detailMapper.updateById(detail);
+                }
+            }
+        }
+        if (CollectionUtils.isNotEmpty(dbIds)) {
+            dbIds.stream().filter(dbId -> !liveIds.contains(dbId)).forEach(detailMapper::deleteById);
+        }
+    }
+
+    private void syncChangeDetails(List<PsiFoodPurchaseDetail> detailInfos, String changeId, UserDTO userDTO) {
+        List<String> dbIds = changeDetailMapper.getIdByChangeId(changeId);
+        List<String> liveIds = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(detailInfos)) {
+            int sort = 1;
+            for (PsiFoodPurchaseDetail detail : detailInfos) {
+                normalizeDetail(detail, sort++);
+                PsiFoodPurchaseChangeDetail changeDetail = new PsiFoodPurchaseChangeDetail();
+                BeanUtils.copyProperties(detail, changeDetail);
+                changeDetail.setChangeId(changeId);
+                if (StringUtils.isNotBlank(changeDetail.getId())) {
+                    liveIds.add(changeDetail.getId());
+                }
+                if (StringUtils.isBlank(changeDetail.getId()) || changeDetailMapper.selectById(changeDetail.getId()) == null) {
+                    changeDetail.setId(UUID.randomUUID().toString().replace("-", ""));
+                    changeDetail.setCreateById(userDTO.getId());
+                    changeDetail.setCreateTime(new Date());
+                    changeDetail.setUpdateById(userDTO.getId());
+                    changeDetail.setUpdateTime(new Date());
+                    changeDetail.setDelFlag(0);
+                    changeDetailMapper.insert(changeDetail);
+                    liveIds.add(changeDetail.getId());
+                } else {
+                    changeDetail.setUpdateById(userDTO.getId());
+                    changeDetail.setUpdateTime(new Date());
+                    changeDetailMapper.updateById(changeDetail);
+                }
+            }
+        }
+        if (CollectionUtils.isNotEmpty(dbIds)) {
+            dbIds.stream().filter(dbId -> !liveIds.contains(dbId)).forEach(changeDetailMapper::deleteById);
+        }
+    }
+
+    private List<PsiFoodPurchaseDetail> convertChangeDetails(List<PsiFoodPurchaseChangeDetail> changeDetails) {
+        List<PsiFoodPurchaseDetail> details = new ArrayList<>();
+        if (CollectionUtils.isEmpty(changeDetails)) {
+            return details;
+        }
+        for (PsiFoodPurchaseChangeDetail changeDetail : changeDetails) {
+            PsiFoodPurchaseDetail detail = new PsiFoodPurchaseDetail();
+            BeanUtils.copyProperties(changeDetail, detail);
+            details.add(detail);
+        }
+        return details;
+    }
+
     private void normalizeDetail(PsiFoodPurchaseDetail detail, int sort) {
         detail.setSort(sort);
         if (detail.getTotalPrice() == null && detail.getPurchaseNumber() != null && detail.getUnitPrice() != null) {
@@ -300,4 +572,46 @@ public class PsiFoodPurchaseService {
         }
         return fallback;
     }
+
+    private String formatNumber(BigDecimal value) {
+        if (value == null) {
+            return "";
+        }
+        return value.stripTrailingZeros().toPlainString();
+    }
+
+    private String formatShelfLife(String shelfLife, String shelfLifeUnit) {
+        if (StringUtils.isBlank(shelfLife)) {
+            return "";
+        }
+        if (StringUtils.isBlank(shelfLifeUnit)) {
+            return shelfLife;
+        }
+        return shelfLife + " " + shelfLifeUnit;
+    }
+
+    private List<WorkAttachmentDto> loadAttachmentFiles(String attachmentId) {
+        List<WorkAttachmentDto> files = detailMapper.getByAttachmentId(attachmentId);
+        if (CollectionUtils.isNotEmpty(files)) {
+            files.forEach(file -> file.setCreateBy(SpringUtil.getBean(IUserApi.class).getById(file.getBy())));
+        }
+        return files;
+    }
+
+    private List<WorkAttachmentDto> resolveAttachmentFiles(List<WorkAttachmentDto> files, String fallbackAttachmentId) {
+        if (CollectionUtils.isNotEmpty(files)) {
+            return files;
+        }
+        return loadAttachmentFiles(fallbackAttachmentId);
+    }
+
+    private void saveAttachmentFiles(List<WorkAttachmentDto> files, UserDTO userDTO, String attachmentId) {
+        if (CollectionUtils.isNotEmpty(files)) {
+            psiMaterialService.saveFiles(files, userDTO, attachmentId);
+        }
+    }
+
+    private void updateAttachmentFiles(List<WorkAttachmentDto> files, UserDTO userDTO, String attachmentId) {
+        psiMaterialService.updateFiles(files == null ? new ArrayList<>() : files, userDTO, attachmentId);
+    }
 }

+ 17 - 1
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/service/dto/PsiFoodPurchaseDto.java

@@ -2,6 +2,7 @@ package com.jeeplus.psimanage.foodPurchase.service.dto;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.jeeplus.psimanage.foodPurchase.domain.PsiFoodPurchaseDetail;
+import com.jeeplus.psimanage.oss.service.dto.WorkAttachmentDto;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -11,7 +12,7 @@ import java.util.List;
 @Data
 public class PsiFoodPurchaseDto {
 
-    public static final String BIZ_CODE = "153";
+    public static final String BIZ_CODE = "154";
 
     private String id;
 
@@ -45,8 +46,23 @@ public class PsiFoodPurchaseDto {
 
     private String processDefinitionId;
 
+    private String sourceBasicId;
+
+    private String changeId;
+
+    private String formalStatus;
+
+    private String changeStatus;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date changePurchaseTime;
+
+    private BigDecimal changeTotalPrice;
+
     private List<PsiFoodPurchaseDetail> detailInfos;
 
+    private List<WorkAttachmentDto> files;
+
     private String taskId;
 
     private List<String> auditUserIds;

+ 42 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/foodPurchase/service/dto/PsiFoodPurchaseExportDto.java

@@ -0,0 +1,42 @@
+package com.jeeplus.psimanage.foodPurchase.service.dto;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+@Data
+public class PsiFoodPurchaseExportDto {
+
+    @ExcelIgnore
+    private String id;
+
+    @ExcelProperty("采购编号")
+    private String purchaseNo;
+
+    @ExcelProperty("采购食材名称")
+    private String goodsName;
+
+    @ExcelProperty("食材分类")
+    private String foodType;
+
+    @ExcelProperty("采购数量")
+    private String purchaseNumber;
+
+    @ExcelProperty("单位")
+    private String unit;
+
+    @ExcelProperty("单价")
+    private String unitPrice;
+
+    @ExcelProperty("总价")
+    private String totalPrice;
+
+    @ExcelProperty("存储区域")
+    private String storageArea;
+
+    @ExcelProperty("保质期")
+    private String shelfLife;
+
+    @ExcelProperty("到期日期")
+    private String expiryDate;
+}