Commit 13193246659513aa96b13a2e69873cb83bb0f6fe

Authored by chenhang4442024
2 parents 9d5da66f 9d4411aa

Merge remote-tracking branch 'origin/profit-analysis' into fix-main-ch

Showing 55 changed files with 3280 additions and 51 deletions
src/main/java/com/order/erp/common/constant/Constant.java
... ... @@ -161,7 +161,7 @@ public class Constant {
161 161  
162 162 public static final int SEVEN = 7;
163 163 public static final int FOURTEEN= 14;
164   - public static final int THIRTY = 30;
  164 + public static final Integer THIRTY = 30;
165 165  
166 166 public static final int TWENTY_FIRST = 21;
167 167  
... ...
src/main/java/com/order/erp/controller/OrderCostController.java 0 → 100644
  1 +package com.order.erp.controller;
  2 +
  3 +import com.order.erp.common.constant.ServerResult;
  4 +import com.order.erp.domain.vo.OrderProfitAnalysisVo;
  5 +import com.order.erp.domain.vo.order.*;
  6 +import com.order.erp.service.order.IOrderCostInfoService;
  7 +import com.order.erp.service.order.OrderProfitAnalysisService;
  8 +import io.swagger.annotations.Api;
  9 +import io.swagger.annotations.ApiOperation;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.validation.annotation.Validated;
  12 +import org.springframework.web.bind.annotation.*;
  13 +
  14 +import javax.annotation.Resource;
  15 +import javax.servlet.http.HttpServletResponse;
  16 +import java.util.Collections;
  17 +
  18 +/**
  19 + * @author zhongnanhuang
  20 + * @version 1.0
  21 + * @project order-erp
  22 + * @description 订单利润表控制层
  23 + * @date 2023/10/23 11:48:36
  24 + */
  25 +@RestController
  26 +@RequestMapping("/order/cost")
  27 +@Api(tags = "订单费用表")
  28 +public class OrderCostController {
  29 +
  30 + @Resource
  31 + OrderProfitAnalysisService orderProfitAnalysisService;
  32 + @Autowired
  33 + IOrderCostInfoService orderCostInfoService;
  34 +
  35 +
  36 + @PostMapping("/InnerProfitDetail/listByPage")
  37 + @ApiOperation("内部生产费用明细表")
  38 + public ServerResult listInnerProfitDetailByPage(@RequestBody @Validated OrderBaseInfoQueryVO queryVO) {
  39 + queryVO.setProductionDepartment(Collections.singletonList("内部"));
  40 + return orderCostInfoService.listInnerProfitDetailByPage(queryVO);
  41 + }
  42 + @PostMapping("/BusinessProfitDetail/listByPage")
  43 + @ApiOperation("包装费用明细表")
  44 + public ServerResult listBusinessProfitDetailsByPage(@RequestBody @Validated OrderBaseInfoQueryVO queryVO) {
  45 + return orderCostInfoService.listBusinessProfitDetailByPage(queryVO);
  46 + }
  47 + @PostMapping("/edit")
  48 + @ApiOperation("编辑")
  49 + public ServerResult edit(@RequestBody OrderCostInfoVO vo) throws Exception {
  50 + return orderCostInfoService.edit(vo);
  51 + }
  52 +
  53 + @PostMapping("/applyEditFileds")
  54 + @ApiOperation("申请编辑字段")
  55 + public ServerResult applyEditFileds(OrderCostInfolockFieldVO vo) throws Exception {
  56 + return orderCostInfoService.applyEditFileds(vo);
  57 + }
  58 +
  59 +}
... ...
src/main/java/com/order/erp/controller/OrderProfitController.java
... ... @@ -2,16 +2,20 @@ package com.order.erp.controller;
2 2  
3 3 import com.order.erp.common.constant.ServerResult;
4 4 import com.order.erp.domain.vo.OrderProfitAnalysisVo;
5   -import com.order.erp.domain.vo.order.OrderProfitAnalysisVO;
6   -import com.order.erp.domain.vo.order.ProfitCalculateVO;
  5 +import com.order.erp.domain.vo.order.*;
  6 +import com.order.erp.service.order.IOrderCostInfoService;
7 7 import com.order.erp.service.order.OrderProfitAnalysisService;
  8 +import io.swagger.annotations.Api;
  9 +import io.swagger.annotations.ApiOperation;
  10 +import org.springframework.beans.factory.annotation.Autowired;
8 11 import org.springframework.validation.annotation.Validated;
9   -import org.springframework.web.bind.annotation.PostMapping;
10   -import org.springframework.web.bind.annotation.RequestBody;
11   -import org.springframework.web.bind.annotation.RequestMapping;
12   -import org.springframework.web.bind.annotation.RestController;
  12 +import org.springframework.web.bind.annotation.*;
13 13  
14 14 import javax.annotation.Resource;
  15 +import javax.servlet.http.HttpServletResponse;
  16 +import java.io.IOException;
  17 +import java.util.Arrays;
  18 +import java.util.Collections;
15 19  
16 20 /**
17 21 * @author zhongnanhuang
... ... @@ -36,4 +40,5 @@ public class OrderProfitController {
36 40 public ServerResult calculate(@RequestBody @Validated ProfitCalculateVO calculateVO) {
37 41 return orderProfitAnalysisService.calculate(calculateVO);
38 42 }
  43 +
39 44 }
... ...
src/main/java/com/order/erp/controller/ProjectController.java 0 → 100644
  1 +package com.order.erp.controller;
  2 +
  3 +import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  4 +import com.order.erp.common.constant.ServerResult;
  5 +import com.order.erp.domain.vo.OrderProfitAnalysisVo;
  6 +import com.order.erp.domain.vo.order.*;
  7 +import com.order.erp.service.order.IOrderCostInfoService;
  8 +import com.order.erp.service.order.IProjectBaseInfoService;
  9 +import com.order.erp.service.order.OrderProfitAnalysisService;
  10 +import io.swagger.annotations.Api;
  11 +import io.swagger.annotations.ApiOperation;
  12 +import org.springframework.beans.factory.annotation.Autowired;
  13 +import org.springframework.validation.annotation.Validated;
  14 +import org.springframework.web.bind.annotation.*;
  15 +
  16 +import javax.annotation.Resource;
  17 +import javax.servlet.http.HttpServletResponse;
  18 +import java.util.Collections;
  19 +
  20 +/**
  21 + * @author zhongnanhuang
  22 + * @version 1.0
  23 + * @project order-erp
  24 + * @description 订单利润表控制层
  25 + * @date 2023/10/23 11:48:36
  26 + */
  27 +@RestController
  28 +@RequestMapping("/project")
  29 +@Api(tags = "项目信息")
  30 +public class ProjectController {
  31 + @Autowired
  32 + IOrderCostInfoService orderCostInfoService;
  33 + @Autowired
  34 + IProjectBaseInfoService projectBaseInfoService;
  35 +
  36 + @PostMapping("/edit")
  37 + @ApiOperation("编辑")
  38 + public ServerResult<OrderProfitAnalysisVO> edit(@RequestBody @Validated ProjectBaseInfoVO vo) {
  39 + return projectBaseInfoService.edit(vo);
  40 + }
  41 +
  42 + @PostMapping("/applyEditFileds")
  43 + @ApiOperation("申请修改")
  44 + public ServerResult<OrderProfitAnalysisVO> applyEditFileds(@RequestBody @Validated ProjectBaseInfoLockFieldVO vo) {
  45 + return projectBaseInfoService.applyEditFileds(vo);
  46 + }
  47 +
  48 + @PostMapping("/pageProjectLockFieldApply")
  49 + @ApiOperation("分页查询项目字段申请记录")
  50 + public ServerResult<OrderProfitAnalysisVO> pageProjectLockFieldApply(@RequestBody @Validated QueryProjectLockFieldVO vo) {
  51 + return projectBaseInfoService.pageProjectLockFieldApply(vo);
  52 + }
  53 +
  54 + @PostMapping("/audit")
  55 + @ApiOperation("审核")
  56 + public ServerResult<OrderProfitAnalysisVO> audit(@RequestBody @Validated AuditVO vo) {
  57 + return projectBaseInfoService.audit(vo);
  58 + }
  59 + @PostMapping("/InnerProfitInfo/listByPage")
  60 + @ApiOperation("内部生产利润分析表")
  61 + public ServerResult<Page<InnerProfitInfoVO>> listInnerProfitInfoByPage(@RequestBody @Validated OrderBaseInfoQueryVO queryVO) {
  62 + queryVO.setProductionDepartment(Collections.singletonList("内部"));
  63 + return projectBaseInfoService.listInnerProfitInfoByPage(queryVO);
  64 + }
  65 +
  66 + @PostMapping("/BusinessProfitInfo/listByPage")
  67 + @ApiOperation("业务研发净利润分析表")
  68 + public ServerResult<Page<BusinessProfitInfoVO>> listBusinessProfitInfosByPage(@RequestBody @Validated OrderBaseInfoQueryVO queryVO) {
  69 + queryVO.setProductionDepartment(Collections.singletonList("内部"));
  70 + return projectBaseInfoService.listBusinessProfitInfoByPage(queryVO);
  71 + }
  72 +
  73 + @PostMapping("/businessProfit/export")
  74 + @ApiOperation("业务研发净利润分析表导出")
  75 + public void exportBusinessProfitInfo(HttpServletResponse response, @RequestParam("projectNoPrefix") String projectNoPrefix) throws Exception {
  76 + projectBaseInfoService.exportBusinessProfitInfo(response, projectNoPrefix);
  77 + }
  78 +
  79 + @PostMapping("/innerProfit/export")
  80 + @ApiOperation("内部研发净利润分析表导出")
  81 + public void exportInnerProfitInfo(HttpServletResponse response, @RequestParam("projectNoPrefix") String projectNoPrefix) throws Exception {
  82 + projectBaseInfoService.exportInnerProfitInfo(response, projectNoPrefix);
  83 + }
  84 +
  85 +}
... ...
src/main/java/com/order/erp/domain/ApplyTypeEnum.java
... ... @@ -24,6 +24,8 @@ public enum ApplyTypeEnum {
24 24 CHECK_BILL_APPLY(40, "应付账单申请"),
25 25  
26 26 DEPARTMENT_INVOICE_APPLY(50,"生产科发票申请"),
  27 +
  28 + ORDER_COST_FIELD_EDIT_APPLY(60,"订单费用字段申请"),
27 29 ;
28 30 private Integer type;
29 31  
... ...
src/main/java/com/order/erp/domain/ProjectApplyTypeEnum.java 0 → 100644
  1 +package com.order.erp.domain;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.EnumValue;
  4 +import com.fasterxml.jackson.annotation.JsonValue;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Getter;
  7 +
  8 +/**
  9 + * @author: xms
  10 + * @description: TODO
  11 + * @date: 2023/9/13 18:05
  12 + * @version: 1.0
  13 + */
  14 +@Getter
  15 +@AllArgsConstructor
  16 +public enum ProjectApplyTypeEnum {
  17 +
  18 + FIELD_EDIT_APPLY(0, "字段编辑申请"),
  19 + ;
  20 + @EnumValue
  21 + @JsonValue
  22 + private Integer type;
  23 +
  24 + private String desc;
  25 +}
... ...
src/main/java/com/order/erp/domain/dto/order/OrderCostInfoDO.java 0 → 100644
  1 +package com.order.erp.domain.dto.order;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import com.baomidou.mybatisplus.annotation.IdType;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import java.io.Serializable;
  7 +import java.math.BigDecimal;
  8 +
  9 +import com.order.erp.domain.dto.BaseDO;
  10 +import io.swagger.annotations.ApiModel;
  11 +import lombok.AllArgsConstructor;
  12 +import lombok.Data;
  13 +import lombok.EqualsAndHashCode;
  14 +import lombok.NoArgsConstructor;
  15 +import lombok.experimental.SuperBuilder;
  16 +
  17 +/**
  18 + * <p>
  19 + *
  20 + * </p>
  21 + *
  22 + * @author author
  23 + * @since 2024-12-22
  24 + */
  25 +@Data
  26 +@EqualsAndHashCode(callSuper = false)
  27 +@SuperBuilder
  28 +@AllArgsConstructor
  29 +@NoArgsConstructor
  30 +@TableName("order_cost_info")
  31 +@ApiModel(value="OrderCostinfo对象", description="")
  32 +public class OrderCostInfoDO extends BaseDO implements Serializable {
  33 +
  34 + private static final long serialVersionUID = 1L;
  35 +
  36 + @TableId(value = "id", type = IdType.AUTO)
  37 + private Long id;
  38 +
  39 + private Long orderId;
  40 +
  41 + private BigDecimal productionDepartmentPredictPrice;
  42 +
  43 + private BigDecimal productionActualPrice;
  44 +
  45 + private BigDecimal packetActualRmbTotalPrice;
  46 +
  47 +
  48 +}
... ...
src/main/java/com/order/erp/domain/dto/order/OrderProfitAnalysisDO.java
... ... @@ -6,6 +6,7 @@ import lombok.*;
6 6 import lombok.experimental.SuperBuilder;
7 7  
8 8 import java.io.Serializable;
  9 +import java.math.BigDecimal;
9 10  
10 11 /**
11 12 * 订单利润分析表(OrderProfitAnalysis)实体类
... ...
src/main/java/com/order/erp/domain/dto/order/ProjectBaseInfoDO.java 0 → 100644
  1 +package com.order.erp.domain.dto.order;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import com.baomidou.mybatisplus.annotation.IdType;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +
  7 +import java.math.BigDecimal;
  8 +import java.time.LocalDateTime;
  9 +import java.io.Serializable;
  10 +
  11 +import com.order.erp.domain.dto.BaseDO;
  12 +import io.swagger.annotations.ApiModel;
  13 +import lombok.Data;
  14 +import lombok.EqualsAndHashCode;
  15 +import lombok.experimental.Accessors;
  16 +
  17 +/**
  18 + * <p>
  19 + *
  20 + * </p>
  21 + *
  22 + * @author author
  23 + * @since 2024-12-18
  24 + */
  25 +@Data
  26 +@EqualsAndHashCode(callSuper = false)
  27 +@Accessors(chain = true)
  28 +@TableName("project_base_info")
  29 +@ApiModel(value="ProjectBaseInfoDO", description="")
  30 +public class ProjectBaseInfoDO extends BaseDO implements Serializable {
  31 +
  32 + private static final long serialVersionUID = 1L;
  33 +
  34 + @TableId(value = "id", type = IdType.AUTO)
  35 + private Long id;
  36 +
  37 + private String projectNoPrefix;
  38 +
  39 + private BigDecimal developmentCopyRmbTotalPrice;
  40 +
  41 + private LocalDateTime projectStartTime;
  42 +
  43 + private LocalDateTime projectEndTime;
  44 +
  45 +
  46 + private BigDecimal spainPaidRmbCommission;
  47 +
  48 + private BigDecimal paidRmbCommission;
  49 +
  50 + private BigDecimal actualExchangeRate;
  51 +
  52 +
  53 +}
... ...
src/main/java/com/order/erp/domain/model/OrderCostFieldLockRecord.java 0 → 100644
  1 +package com.order.erp.domain.model;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import com.baomidou.mybatisplus.annotation.IdType;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.FieldFill;
  8 +import com.baomidou.mybatisplus.annotation.TableField;
  9 +import java.io.Serializable;
  10 +
  11 +import com.order.erp.domain.dto.BaseDO;
  12 +import io.swagger.annotations.ApiModel;
  13 +import io.swagger.annotations.ApiModelProperty;
  14 +import lombok.AllArgsConstructor;
  15 +import lombok.Data;
  16 +import lombok.EqualsAndHashCode;
  17 +import lombok.NoArgsConstructor;
  18 +import lombok.experimental.Accessors;
  19 +import lombok.experimental.SuperBuilder;
  20 +
  21 +/**
  22 + * <p>
  23 + *
  24 + * </p>
  25 + *
  26 + * @author author
  27 + * @since 2024-12-22
  28 + */
  29 +@Data
  30 +@EqualsAndHashCode(callSuper = false)
  31 +@SuperBuilder
  32 +@NoArgsConstructor
  33 +@AllArgsConstructor
  34 +@TableName("order_cost_field_lock_record")
  35 +@ApiModel(value="OrderCostFieldLockRecord对象", description="")
  36 +public class OrderCostFieldLockRecord extends BaseDO implements Serializable {
  37 +
  38 + private static final long serialVersionUID = 1L;
  39 +
  40 + @TableId(value = "id", type = IdType.AUTO)
  41 + private Long id;
  42 +
  43 + private String fields;
  44 +
  45 + private Long userId;
  46 +
  47 + private Long orderId;
  48 +
  49 +
  50 +
  51 +}
... ...
src/main/java/com/order/erp/domain/model/ProjectApplyDO.java 0 → 100644
  1 +package com.order.erp.domain.model;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import com.baomidou.mybatisplus.annotation.IdType;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +
  7 +import java.io.Serializable;
  8 +
  9 +import com.order.erp.domain.ProjectApplyTypeEnum;
  10 +import com.order.erp.domain.dto.BaseDO;
  11 +import io.swagger.annotations.ApiModel;
  12 +import io.swagger.annotations.ApiModelProperty;
  13 +import lombok.AllArgsConstructor;
  14 +import lombok.Data;
  15 +import lombok.EqualsAndHashCode;
  16 +import lombok.NoArgsConstructor;
  17 +import lombok.experimental.SuperBuilder;
  18 +
  19 +/**
  20 + * <p>
  21 + * 项目-字段锁定申请表
  22 + * </p>
  23 + *
  24 + * @author author
  25 + * @since 2024-12-22
  26 + */
  27 +@Data
  28 +@EqualsAndHashCode(callSuper = false)
  29 +@SuperBuilder
  30 +@AllArgsConstructor
  31 +@NoArgsConstructor
  32 +@TableName("project_apply")
  33 +@ApiModel(value="ProjectFieldLockApply对象", description="项目-字段锁定申请表")
  34 +public class ProjectApplyDO extends BaseDO implements Serializable {
  35 +
  36 + private static final long serialVersionUID = 1L;
  37 +
  38 + @TableId(value = "id", type = IdType.AUTO)
  39 + private Long id;
  40 +
  41 + @ApiModelProperty(value = "项目号")
  42 + private String projectNoPrefix;
  43 +
  44 +
  45 + @ApiModelProperty(value = "申请用户id")
  46 + private Long applyUserId;
  47 +
  48 + @ApiModelProperty(value = "审批用户id")
  49 + private Long auditUserId;
  50 +
  51 + @ApiModelProperty(value = "锁定字段 json字符串")
  52 + private String fields;
  53 +
  54 + @ApiModelProperty(value = "锁定字段 json字符串")
  55 + private ProjectApplyTypeEnum type;
  56 +
  57 + @ApiModelProperty(value = "状态:0 待审批,1 通过,2 拒绝")
  58 + private Integer status;
  59 +
  60 + @ApiModelProperty(value = "审核备注")
  61 + private String auditRemark;
  62 +
  63 + @ApiModelProperty(value = "审批角色code集合,分割")
  64 + private String auditRoleCodes;
  65 +
  66 + @ApiModelProperty(value = "申请原因")
  67 + private String applyRemark;
  68 +
  69 +
  70 +}
... ...
src/main/java/com/order/erp/domain/model/ProjectFieldLockRecord.java 0 → 100644
  1 +package com.order.erp.domain.model;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import com.baomidou.mybatisplus.annotation.IdType;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.FieldFill;
  8 +import com.baomidou.mybatisplus.annotation.TableField;
  9 +import java.io.Serializable;
  10 +
  11 +import com.order.erp.domain.dto.BaseDO;
  12 +import io.swagger.annotations.ApiModel;
  13 +import io.swagger.annotations.ApiModelProperty;
  14 +import lombok.AllArgsConstructor;
  15 +import lombok.Data;
  16 +import lombok.EqualsAndHashCode;
  17 +import lombok.NoArgsConstructor;
  18 +import lombok.experimental.Accessors;
  19 +import lombok.experimental.SuperBuilder;
  20 +
  21 +/**
  22 + * <p>
  23 + * 项目-字段锁定记录表
  24 + * </p>
  25 + *
  26 + * @author author
  27 + * @since 2024-12-22
  28 + */
  29 +@Data
  30 +@EqualsAndHashCode(callSuper = false)
  31 +@AllArgsConstructor
  32 +@NoArgsConstructor
  33 +@SuperBuilder
  34 +@TableName("project_field_lock_record")
  35 +@ApiModel(value="ProjectFieldLockRecord对象", description="项目-字段锁定记录表")
  36 +public class ProjectFieldLockRecord extends BaseDO implements Serializable {
  37 +
  38 + private static final long serialVersionUID = 1L;
  39 +
  40 + @TableId(value = "id", type = IdType.AUTO)
  41 + private Long id;
  42 +
  43 +
  44 + @ApiModelProperty(value = "项目号")
  45 + private String projectNoPrefix;
  46 +
  47 + @ApiModelProperty(value = "用户id")
  48 + private Long userId;
  49 +
  50 + @ApiModelProperty(value = "锁定字段 json字符串")
  51 + private String fields;
  52 +
  53 +
  54 +
  55 +}
... ...
src/main/java/com/order/erp/domain/vo/order/AuditVO.java
1 1 package com.order.erp.domain.vo.order;
2 2  
3 3 import com.order.erp.domain.vo.BasePageVO;
  4 +import io.swagger.annotations.ApiModelProperty;
4 5 import lombok.*;
5 6 import lombok.experimental.SuperBuilder;
6 7  
... ... @@ -23,17 +24,20 @@ public class AuditVO extends BasePageVO implements Serializable {
23 24 * 申请id
24 25 */
25 26 @NotNull(message = "申请id不能为空")
  27 + @ApiModelProperty(value = "申请id", required = true)
26 28 private Long id;
27 29  
28 30 /**
29 31 * 状态:1 通过,2 拒绝
30 32 */
31 33 @NotNull(message = "状态不能为空")
  34 + @ApiModelProperty(value = "状态:1 通过,2 拒绝", required = true)
32 35 private Integer status;
33 36  
34 37 /**
35 38 * 拒绝原因备注
36 39 */
  40 + @ApiModelProperty(value = "拒绝原因备注")
37 41 private String refuseRemark;
38 42 }
39 43  
... ...
src/main/java/com/order/erp/domain/vo/order/BusinessProfitDetailVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import io.swagger.annotations.ApiModelProperty;
  4 +import lombok.*;
  5 +import lombok.experimental.SuperBuilder;
  6 +
  7 +import java.io.Serializable;
  8 +import java.math.BigDecimal;
  9 +
  10 +/**
  11 + * 业务/研发净利润分析
  12 + *
  13 + * @author makejava
  14 + * @since 2024-08-05 16:26:34
  15 + */
  16 +@Data
  17 +@AllArgsConstructor
  18 +@ToString
  19 +@NoArgsConstructor
  20 +@EqualsAndHashCode(callSuper = false)
  21 +@SuperBuilder
  22 +public class BusinessProfitDetailVO implements Serializable {
  23 +
  24 +
  25 + /**
  26 + * 客户编码
  27 + */
  28 + @ApiModelProperty(value = "客户编码")
  29 + private String customerCode;
  30 +
  31 + /**
  32 + * 项目号
  33 + */
  34 + @ApiModelProperty(value = "项目号")
  35 + private String projectNo;
  36 +
  37 + /**
  38 + * 生产科
  39 + */
  40 + @ApiModelProperty(value = "生产部门")
  41 + private String productionDepartment;
  42 +
  43 + /**
  44 + * 内部编号
  45 + */
  46 + @ApiModelProperty(value = "内部编号")
  47 + private String innerNo;
  48 +
  49 + /**
  50 + * pic图片地址
  51 + */
  52 + @ApiModelProperty(value = "图片地址")
  53 + private String picUrl;
  54 +
  55 + /**
  56 + * 订单数量
  57 + */
  58 + @ApiModelProperty(value = "订单数量")
  59 + private Integer orderCount;
  60 +
  61 + /**
  62 + * 包装费用$
  63 + */
  64 + @ApiModelProperty(value = "包装费用(美元)")
  65 + private Double packetPrice;
  66 +
  67 + /**
  68 + * 包装费用合计$
  69 + */
  70 + @ApiModelProperty(value = "包装费用合计(美元)")
  71 + private Double packetTotalPrice;
  72 +
  73 + /**
  74 + * 包装费用合计¥
  75 + */
  76 + @ApiModelProperty(value = "包装费用合计(人民币)")
  77 + private Double packetRmbTotalPrice;
  78 +
  79 + /**
  80 + * 包装费用实际金额
  81 + */
  82 + @ApiModelProperty(value = "包装费用实际金额(人民币)")
  83 + private BigDecimal packetActualRmbTotalPrice;
  84 +
  85 + /**
  86 + * 包装费用实际金额¥
  87 + */
  88 + @ApiModelProperty(value = "包装费用实际金额(人民币)")
  89 + private BigDecimal packetActualRmbPrice;
  90 +
  91 + /**
  92 + * 包装费用实际金额$
  93 + */
  94 + @ApiModelProperty(value = "包装费用实际金额(美元)")
  95 + private BigDecimal packetActualPrice;
  96 +
  97 + /**
  98 + * 包装费用收益
  99 + */
  100 + @ApiModelProperty(value = "包装费用收益(人民币)")
  101 + private BigDecimal packetProfitRmbPrice;
  102 +
  103 + /**
  104 + * 包装费用利润率
  105 + */
  106 + @ApiModelProperty(value = "包装费用利润率")
  107 + private BigDecimal packetProfitRate;
  108 +
  109 + /**
  110 + * 锁定字段信息
  111 + */
  112 + @ApiModelProperty(value = "锁定字段信息")
  113 + private OrderCostInfolockFieldVO lockFields;
  114 +
  115 +
  116 +}
  117 +
... ...
src/main/java/com/order/erp/domain/vo/order/BusinessProfitInfoVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import io.swagger.annotations.ApiModelProperty;
  4 +import lombok.*;
  5 +import lombok.experimental.SuperBuilder;
  6 +
  7 +import java.io.Serializable;
  8 +import java.math.BigDecimal;
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * 业务/研发净利润分析
  13 + *
  14 + * @author makejava
  15 + * @since 2024-08-05 16:26:34
  16 + */
  17 +@Data
  18 +@AllArgsConstructor
  19 +@ToString
  20 +@NoArgsConstructor
  21 +@EqualsAndHashCode(callSuper = false)
  22 +@SuperBuilder
  23 +public class BusinessProfitInfoVO implements Serializable {
  24 +
  25 +
  26 + /**
  27 + * 客户编码
  28 + */
  29 + @ApiModelProperty(value = "客户编码")
  30 + private String customerCode;
  31 +
  32 + /**
  33 + * 项目号
  34 + */
  35 + @ApiModelProperty(value = "项目号")
  36 + private String projectNoPrefix;
  37 +
  38 + /**
  39 + * 客户总价¥
  40 + */
  41 + @ApiModelProperty(value = "客户总价(人民币)")
  42 + private Double customerRmbTotalPrice;
  43 +
  44 + /**
  45 + * 客户总价¥
  46 + */
  47 + @ApiModelProperty(value = "客户总价")
  48 + private Double customerTotalPrice;
  49 +
  50 + /**
  51 + * 生成科总价¥
  52 + */
  53 + @ApiModelProperty(value = "生产部门总价")
  54 + private Double productionDepartmentTotalPrice;
  55 +
  56 + /**
  57 + * 生产科
  58 + */
  59 + @ApiModelProperty(value = "生产部门")
  60 + private String productionDepartment;
  61 +
  62 + /**
  63 + * 内部编号
  64 + */
  65 + @ApiModelProperty(value = "内部编号")
  66 + private String innerNo;
  67 +
  68 + /**
  69 + * pic图片地址
  70 + */
  71 + @ApiModelProperty(value = "图片地址")
  72 + private String picUrl;
  73 +
  74 + /**
  75 + * 订单数量
  76 + */
  77 + @ApiModelProperty(value = "订单数量")
  78 + private Integer orderCount;
  79 +
  80 + /**
  81 + * 包装费用$
  82 + */
  83 + @ApiModelProperty(value = "包装费用(美元)")
  84 + private Double packetPrice;
  85 +
  86 + /**
  87 + * 包装费用合计$
  88 + */
  89 + @ApiModelProperty(value = "包装费用合计(美元)")
  90 + private Double packetTotalPrice;
  91 +
  92 + /**
  93 + * 包装费用合计¥
  94 + */
  95 + @ApiModelProperty(value = "包装费用合计(人民币)")
  96 + private Double packetRmbTotalPrice;
  97 +
  98 + /**
  99 + * 包装费用实际金额
  100 + */
  101 + @ApiModelProperty(value = "包装费用实际金额(人民币)")
  102 + private BigDecimal packetActualRmbTotalPrice;
  103 +
  104 + /**
  105 + * 包装费用实际金额¥
  106 + */
  107 + @ApiModelProperty(value = "包装费用实际金额(人民币)")
  108 + private BigDecimal packetActualRmbPrice;
  109 +
  110 + /**
  111 + * 包装费用实际金额$
  112 + */
  113 + @ApiModelProperty(value = "包装费用实际金额(美元)")
  114 + private BigDecimal packetActualPrice;
  115 +
  116 + /**
  117 + * 包装费用收益
  118 + */
  119 + @ApiModelProperty(value = "包装费用收益(人民币)")
  120 + private BigDecimal packetProfitRmbPrice;
  121 +
  122 + /**
  123 + * 包装费用利润率
  124 + */
  125 + @ApiModelProperty(value = "包装费用利润率")
  126 + private BigDecimal packetProfitRate;
  127 +
  128 + /**
  129 + * 研发复制费合计¥
  130 + */
  131 + @ApiModelProperty(value = "研发复制费合计(人民币)")
  132 + private BigDecimal developmentCopyRmbTotalPrice;
  133 +
  134 + /**
  135 + * 固定成本
  136 + */
  137 + @ApiModelProperty(value = "固定成本")
  138 + private BigDecimal fixedCost;
  139 +
  140 + /**
  141 + * 西班牙已发提成¥
  142 + */
  143 + @ApiModelProperty(value = "西班牙已发提成(人民币)")
  144 + private BigDecimal spainPaidRmbCommission;
  145 +
  146 + /**
  147 + * 西班牙提成¥
  148 + */
  149 + @ApiModelProperty(value = "西班牙提成(人民币)")
  150 + private BigDecimal spainRmbCommission;
  151 +
  152 + /**
  153 + * 西班牙未发提成¥
  154 + */
  155 + @ApiModelProperty(value = "西班牙未发提成(人民币)")
  156 + private BigDecimal spainUnpaidRmbCommission;
  157 +
  158 + /**
  159 + * 已发提成¥
  160 + */
  161 + @ApiModelProperty(value = "已发提成(人民币)")
  162 + private BigDecimal paidRmbCommission;
  163 +
  164 + /**
  165 + * 提成¥
  166 + */
  167 + @ApiModelProperty(value = "提成(人民币)")
  168 + private BigDecimal rmbCommission;
  169 +
  170 + /**
  171 + * 未发提成¥
  172 + */
  173 + @ApiModelProperty(value = "未发提成(人民币)")
  174 + private BigDecimal unpaidRmbCommission;
  175 +
  176 + /**
  177 + * 实际汇率
  178 + */
  179 + @ApiModelProperty(value = "实际汇率")
  180 + private BigDecimal actualExchangeRate;
  181 +
  182 + /**
  183 + * 支出合计
  184 + */
  185 + @ApiModelProperty(value = "支出合计(人民币)")
  186 + private BigDecimal rmbTotalExpense;
  187 +
  188 + /**
  189 + * 毛利润
  190 + */
  191 + @ApiModelProperty(value = "毛利润")
  192 + private BigDecimal profit;
  193 +
  194 + /**
  195 + * 毛利率
  196 + */
  197 + @ApiModelProperty(value = "毛利率")
  198 + private BigDecimal profitRate;
  199 +
  200 + /**
  201 + * 研发净利润
  202 + */
  203 + @ApiModelProperty(value = "研发净利润")
  204 + private BigDecimal developmentProfit;
  205 +
  206 + /**
  207 + * 研发净利率
  208 + */
  209 + @ApiModelProperty(value = "研发净利率")
  210 + private BigDecimal developmentProfitRate;
  211 +
  212 + /**
  213 + * 实际跟单单价
  214 + */
  215 + @ApiModelProperty(value = "实际跟单单价(人民币)")
  216 + private BigDecimal actualOrderRmbPrice;
  217 +
  218 + /**
  219 + * 实际跟单单价$
  220 + */
  221 + @ApiModelProperty(value = "实际跟单单价(美元)")
  222 + private BigDecimal actualOrderPrice;
  223 +
  224 + /**
  225 + * 汇率收益
  226 + */
  227 + @ApiModelProperty(value = "汇率收益")
  228 + private BigDecimal exchangeRateProfit;
  229 +
  230 + /**
  231 + * 综合收益
  232 + */
  233 + @ApiModelProperty(value = "综合收益")
  234 + private BigDecimal comprehensiveProfit;
  235 +
  236 + /**
  237 + * 项目开始时间
  238 + */
  239 + @ApiModelProperty(value = "项目开始时间")
  240 + private LocalDateTime projectStartTime;
  241 +
  242 + /**
  243 + * 项目结束时间
  244 + */
  245 + @ApiModelProperty(value = "项目结束时间")
  246 + private LocalDateTime projectEndTime;
  247 +
  248 + @ApiModelProperty(value = "生产开始时间")
  249 + private LocalDateTime produceStartTime;
  250 +
  251 + @ApiModelProperty(value = "生产结束时间")
  252 + private LocalDateTime produceEndTime;
  253 +
  254 + @ApiModelProperty(value = "锁定字段信息")
  255 + private ProjectBaseInfoLockFieldVO lockFields;
  256 +
  257 +
  258 +}
  259 +
... ...
src/main/java/com/order/erp/domain/vo/order/InnerProfitDetailVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import io.swagger.annotations.ApiModelProperty;
  4 +import lombok.*;
  5 +import lombok.experimental.SuperBuilder;
  6 +
  7 +import java.io.Serializable;
  8 +import java.math.BigDecimal;
  9 +import java.util.Map;
  10 +
  11 +/**
  12 + * 业务/研发净利润分析
  13 + *
  14 + * @author makejava
  15 + * @since 2024-08-05 16:26:34
  16 + */
  17 +@Data
  18 +@AllArgsConstructor
  19 +@ToString
  20 +@NoArgsConstructor
  21 +@EqualsAndHashCode(callSuper = false)
  22 +@SuperBuilder
  23 +public class InnerProfitDetailVO implements Serializable {
  24 +
  25 +
  26 + /**
  27 + * 客户编码
  28 + */
  29 + @ApiModelProperty(value = "客户编码")
  30 + private String customerCode;
  31 +
  32 + /**
  33 + * 项目号
  34 + */
  35 + @ApiModelProperty(value = "项目号")
  36 + private String projectNo;
  37 + @ApiModelProperty(value = "生产科")
  38 + private String productionDepartment;
  39 +
  40 + /**
  41 + * 内部编号
  42 + */
  43 + @ApiModelProperty(value = "内部编码")
  44 + private String innerNo;
  45 + /**
  46 + * pic图片地址
  47 + */
  48 + @ApiModelProperty(value = "图片")
  49 + private String picUrl;
  50 +
  51 + /**
  52 + * 订单数量
  53 + */
  54 + @ApiModelProperty(value = "数量")
  55 + private Integer orderCount;
  56 +
  57 + /**
  58 + * 生产科预算金额由财务手动输入
  59 + */
  60 + @ApiModelProperty(value = "生产科预算金额")
  61 + private BigDecimal productionDepartmentPredictPrice;
  62 +
  63 +
  64 + /**
  65 + * 实际发生费用 手动输入
  66 + */
  67 + @ApiModelProperty(value = "实际发生费用")
  68 + private BigDecimal productionActualPrice;
  69 +
  70 + /**
  71 + * 生产科总价合计
  72 + */
  73 + @ApiModelProperty(value = "生产科总价")
  74 + private Double productionDepartmentTotalPrice;
  75 + /**
  76 + * 生产科总价合计
  77 + */
  78 + @ApiModelProperty(value = "生产科单价")
  79 + private Double productionDepartmentPrice;
  80 +
  81 +
  82 + /**
  83 + * 预算占比
  84 + * 预算占比计算(实际发生费用/预算金额
  85 + */
  86 + @ApiModelProperty(value = "预算占比")
  87 + private BigDecimal predictRatio;
  88 +
  89 + /**
  90 + * 预算占比与实际占比差
  91 + * 预算占比与实际占比差计算(1-预算占比)
  92 + */
  93 + @ApiModelProperty(value = "预算占比与实际占比差")
  94 + private BigDecimal predictAndActualRatio;
  95 +
  96 + /**
  97 + * 内部生产毛利润计算:生产科总价-预算金额
  98 + */
  99 + @ApiModelProperty(value = "事前毛利润")
  100 + private BigDecimal beforeGrossProfit;
  101 +
  102 + /**
  103 + * 内部生产毛利润率计算:事前毛利润/生产科总价
  104 + */
  105 + @ApiModelProperty(value = "事前毛利润")
  106 + private BigDecimal beforeGrossProfitRate;
  107 +
  108 + /**
  109 + * 内部生产毛利润计算:生产科总价-实际发生费用就是得出
  110 + */
  111 + @ApiModelProperty(value = "事后毛利润")
  112 + private BigDecimal grossProfit;
  113 +
  114 + /**
  115 + * 内部生产毛利润率计算:事后毛利润/生产科总价
  116 + */
  117 + @ApiModelProperty(value = "事后毛利润")
  118 + private BigDecimal grossProfitRate;
  119 +
  120 + private OrderCostInfolockFieldVO lockFields;
  121 +
  122 +}
  123 +
... ...
src/main/java/com/order/erp/domain/vo/order/InnerProfitInfoVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import io.swagger.annotations.ApiModelProperty;
  4 +import lombok.*;
  5 +import lombok.experimental.SuperBuilder;
  6 +
  7 +import java.io.Serializable;
  8 +import java.math.BigDecimal;
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * 业务/研发净利润分析
  13 + *
  14 + * @author makejava
  15 + * @since 2024-08-05 16:26:34
  16 + */
  17 +@Data
  18 +@AllArgsConstructor
  19 +@ToString
  20 +@NoArgsConstructor
  21 +@EqualsAndHashCode(callSuper = false)
  22 +@SuperBuilder
  23 +public class InnerProfitInfoVO implements Serializable {
  24 +
  25 +
  26 + /**
  27 + * 客户编码
  28 + */
  29 + @ApiModelProperty(value = "客户编码")
  30 + private String customerCode;
  31 +
  32 + /**
  33 + * 项目号
  34 + */
  35 + @ApiModelProperty(value = "项目号")
  36 + private String projectNoPrefix;
  37 + @ApiModelProperty(value = "生产科")
  38 + private String productionDepartment;
  39 +
  40 + /**
  41 + * 订单数量
  42 + */
  43 + @ApiModelProperty(value = "数量")
  44 + private Integer orderCount;
  45 +
  46 + /**
  47 + * 生产科预算金额由财务手动输入
  48 + */
  49 + @ApiModelProperty(value = "生产科预算金额")
  50 + private BigDecimal productionDepartmentPredictPrice;
  51 +
  52 +
  53 + /**
  54 + * 实际发生费用 手动输入
  55 + */
  56 + @ApiModelProperty(value = "实际发生费用")
  57 + private BigDecimal productionActualPrice;
  58 +
  59 + /**
  60 + * 生产科总价合计
  61 + */
  62 + @ApiModelProperty(value = "生产科总价")
  63 + private Double productionDepartmentTotalPrice;
  64 +
  65 +
  66 + /**
  67 + * 预算占比
  68 + * 预算占比计算(实际发生费用/预算金额
  69 + */
  70 + @ApiModelProperty(value = "预算占比")
  71 + private BigDecimal predictRatio;
  72 +
  73 + /**
  74 + * 预算占比与实际占比差
  75 + * 预算占比与实际占比差计算(1-预算占比)
  76 + */
  77 + @ApiModelProperty(value = "预算占比与实际占比差")
  78 + private BigDecimal predictAndActualRatio;
  79 +
  80 + /**
  81 + * 内部生产毛利润计算:生产科总价-预算金额
  82 + */
  83 + @ApiModelProperty(value = "事前毛利润")
  84 + private BigDecimal beforeGrossProfit;
  85 +
  86 + /**
  87 + * 内部生产毛利润率计算:事前毛利润/生产科总价
  88 + */
  89 + @ApiModelProperty(value = "事前毛利润")
  90 + private BigDecimal beforeGrossProfitRate;
  91 +
  92 + /**
  93 + * 内部生产毛利润计算:生产科总价-实际发生费用就是得出
  94 + */
  95 + @ApiModelProperty(value = "事后毛利润")
  96 + private BigDecimal grossProfit;
  97 +
  98 + /**
  99 + * 内部生产毛利润率计算:事后毛利润/生产科总价
  100 + */
  101 + @ApiModelProperty(value = "事后毛利润")
  102 + private BigDecimal grossProfitRate;
  103 +
  104 + /**
  105 + * 内部生产固定成本
  106 + */
  107 + @ApiModelProperty(value = "内部生产固定成本")
  108 + private BigDecimal innerProductionFixedCost;
  109 +
  110 + /**
  111 + * 内部生产提成
  112 + */
  113 + @ApiModelProperty(value = "内部生产提成")
  114 + private BigDecimal innerProductionCommission;
  115 + /**
  116 + * 内部生产净利润
  117 + */
  118 + @ApiModelProperty(value = "内部生产净利润")
  119 + private BigDecimal innerProductionProfit;
  120 + /**
  121 + * 内部生产净利润率
  122 + */
  123 + @ApiModelProperty(value = "内部生产净利润率")
  124 + private BigDecimal innerProductionProfitRate;
  125 +
  126 + /**
  127 + * 项目开始时间
  128 + */
  129 + @ApiModelProperty(value = "项目开始时间")
  130 + private LocalDateTime produceStartTime;
  131 + /**
  132 + * 项目结束时间
  133 + */
  134 + @ApiModelProperty(value = "项目结束时间")
  135 + private LocalDateTime produceEndTime;
  136 +
  137 +}
  138 +
... ...
src/main/java/com/order/erp/domain/vo/order/OrderBaseInfoQueryVO.java
... ... @@ -61,6 +61,12 @@ public class OrderBaseInfoQueryVO extends BasePageVO implements Serializable {
61 61 private List<String> projectNo;
62 62  
63 63 /**
  64 + * 项目号右模糊
  65 + */
  66 + private String projectNoLikeRight;
  67 +
  68 +
  69 + /**
64 70 * 客户编码集合
65 71 */
66 72 private List<String> customerCode;
... ...
src/main/java/com/order/erp/domain/vo/order/OrderCostInfoVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.IdType;
  4 +import com.baomidou.mybatisplus.annotation.TableId;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import io.swagger.annotations.ApiModel;
  7 +import lombok.AllArgsConstructor;
  8 +import lombok.Data;
  9 +import lombok.EqualsAndHashCode;
  10 +import lombok.NoArgsConstructor;
  11 +import lombok.experimental.SuperBuilder;
  12 +
  13 +import java.io.Serializable;
  14 +import java.math.BigDecimal;
  15 +
  16 +/**
  17 + * <p>
  18 + *
  19 + * </p>
  20 + *
  21 + * @author author
  22 + * @since 2024-12-22
  23 + */
  24 +@Data
  25 +@EqualsAndHashCode(callSuper = false)
  26 +@SuperBuilder
  27 +@AllArgsConstructor
  28 +@NoArgsConstructor
  29 +@TableName("order_cost_info")
  30 +@ApiModel(value="OrderCostDetail对象", description="")
  31 +public class OrderCostInfoVO implements Serializable {
  32 +
  33 + private static final long serialVersionUID = 1L;
  34 +
  35 + @TableId(value = "id", type = IdType.AUTO)
  36 + private Long id;
  37 +
  38 + private Long orderId;
  39 +
  40 + private BigDecimal productionDepartmentPredictPrice;
  41 +
  42 + private BigDecimal productionActualPrice;
  43 +
  44 + private BigDecimal packetActualRmbTotalPrice;
  45 +
  46 +
  47 +}
... ...
src/main/java/com/order/erp/domain/vo/order/OrderCostInfolockFieldVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import io.swagger.annotations.ApiModel;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.NoArgsConstructor;
  9 +import lombok.experimental.SuperBuilder;
  10 +
  11 +import java.io.Serializable;
  12 +
  13 +/**
  14 + * <p>
  15 + *
  16 + * </p>
  17 + *
  18 + * @author author
  19 + * @since 2024-12-22
  20 + */
  21 +@Data
  22 +@EqualsAndHashCode(callSuper = false)
  23 +@SuperBuilder
  24 +@AllArgsConstructor
  25 +@NoArgsConstructor
  26 +@TableName("order_cost_info")
  27 +@ApiModel(value="OrderCostDetail对象", description="")
  28 +public class OrderCostInfolockFieldVO implements Serializable {
  29 +
  30 + private static final long serialVersionUID = 1L;
  31 +
  32 + private Long orderId;
  33 +
  34 + private String productionDepartmentPredictPrice;
  35 +
  36 + private String productionActualPrice;
  37 +
  38 + private String packetActualRmbTotalPrice;
  39 +
  40 +
  41 +}
... ...
src/main/java/com/order/erp/domain/vo/order/OrderFieldLockApplyQueryVO.java
... ... @@ -59,6 +59,11 @@ public class OrderFieldLockApplyQueryVO extends BasePageVO implements Serializab
59 59 private Integer type;
60 60  
61 61 /**
  62 + * 申请类型:枚举类ApplyTypeEnum
  63 + */
  64 + private List<Integer> typeIn;
  65 +
  66 + /**
62 67 * 项目号
63 68 */
64 69 private List<String> projectNo;
... ...
src/main/java/com/order/erp/domain/vo/order/OrderInfoResultVO.java
... ... @@ -38,6 +38,10 @@ public class OrderInfoResultVO extends OrderBaseInfoVO implements Serializable {
38 38 * 质检信息
39 39 */
40 40 private OrderInspectionStageVO inspectionStageInfo;
  41 + /**
  42 + * 费用明细
  43 + */
  44 + private OrderCostInfoVO orderCostInfo;
41 45  
42 46 /**
43 47 * 字段锁定集合
... ...
src/main/java/com/order/erp/domain/vo/order/OrderLockFieldVO.java
... ... @@ -46,6 +46,11 @@ public class OrderLockFieldVO implements Serializable {
46 46 private OrderInspectionStageFieldVO inspectionStageFields;
47 47  
48 48 /**
  49 + * 费用字段
  50 + */
  51 + private OrderCostInfolockFieldVO costInfolockFieldVO;
  52 +
  53 + /**
49 54 * 应收款账单字段
50 55 */
51 56 // private List<InvoiceBillOrderDO> invoiceBillOrderDOList;
... ...
src/main/java/com/order/erp/domain/vo/order/OrderProfitAnalysisVO.java
... ... @@ -4,6 +4,7 @@ import lombok.*;
4 4 import lombok.experimental.SuperBuilder;
5 5  
6 6 import java.io.Serializable;
  7 +import java.math.BigDecimal;
7 8  
8 9 /**
9 10 * 订单利润分析表(OrderProfitAnalysis)实体类
... ... @@ -34,7 +35,6 @@ public class OrderProfitAnalysisVO implements Serializable {
34 35 */
35 36 private Double customerTotalPrice;
36 37  
37   -
38 38 /**
39 39 * 客户单价¥
40 40 */
... ... @@ -111,4 +111,6 @@ public class OrderProfitAnalysisVO implements Serializable {
111 111 */
112 112 private Integer recordNum;
113 113  
  114 +
  115 +
114 116 }
... ...
src/main/java/com/order/erp/domain/vo/order/OrderProfitQueryVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import com.order.erp.domain.vo.BasePageVO;
  4 +import lombok.*;
  5 +import lombok.experimental.SuperBuilder;
  6 +
  7 +import java.io.Serializable;
  8 +import java.util.List;
  9 +import java.util.Set;
  10 +
  11 +/**
  12 + * 订单基础信息表(OrderBaseInfo)实体类
  13 + *
  14 + * @author makejava
  15 + * @since 2023-09-08 15:26:43
  16 + */
  17 +@Data
  18 +@AllArgsConstructor
  19 +@ToString
  20 +@NoArgsConstructor
  21 +@EqualsAndHashCode(callSuper = false)
  22 +@SuperBuilder
  23 +public class OrderProfitQueryVO extends BasePageVO implements Serializable {
  24 + private static final long serialVersionUID = -84816007994858993L;
  25 +
  26 + private List<Long> ids;
  27 +
  28 + private Set<Long> orderIds;
  29 +
  30 +
  31 + private Long id;
  32 +
  33 + /**
  34 + * 生成开始时间
  35 + */
  36 + private String createStartTime;
  37 +
  38 + /**
  39 + * 生成结束时间
  40 + */
  41 + private String createEndTime;
  42 +
  43 + /**
  44 + * 单据状态
  45 + */
  46 + private List<String> orderStatus;
  47 +
  48 + /**
  49 + * 提交人名称
  50 + */
  51 + private String commitUserName;
  52 +
  53 + /**
  54 + * 提交人手机号码
  55 + */
  56 + private String commitUserPhone;
  57 +
  58 + /**
  59 + * 项目号
  60 + */
  61 + private List<String> projectNo;
  62 +
  63 + /**
  64 + * 客户编码集合
  65 + */
  66 + private List<String> customerCode;
  67 +
  68 + /**
  69 + * 客户STYLE#
  70 + */
  71 + private List<String> customerStyle;
  72 +
  73 + /**
  74 + * 内部编号
  75 + */
  76 + private List<String> innerNo;
  77 +
  78 + /**
  79 + * 生产科
  80 + */
  81 + private List<String> productionDepartment;
  82 +
  83 + /**
  84 + * 生成科拖货开始时间
  85 + */
  86 + private String productionDepartmentConsignStartTime;
  87 +
  88 + /**
  89 + * 生成科拖货结束时间
  90 + */
  91 + private String productionDepartmentConsignEndTime;
  92 +
  93 + /**
  94 + * 订单上HOD开始时间
  95 + */
  96 + private String orderHodStartTime;
  97 +
  98 + /**
  99 + * 订单上HOD结束时间
  100 + */
  101 + private String orderHodEndTime;
  102 +
  103 + /**
  104 + * 最小利润率
  105 + */
  106 + private Double profitRateLqt;
  107 +
  108 + /**
  109 + * 最大利润率
  110 + */
  111 + private Double profitRateGqt;
  112 +
  113 + /**
  114 + * 想法来源
  115 + */
  116 + private List<String> ideaSource;
  117 +
  118 + /**
  119 + * 想法来源占比
  120 + */
  121 + private Double ideaSourceRate;
  122 +
  123 + /**
  124 + * 设计师
  125 + */
  126 + private String designer;
  127 +
  128 + /**
  129 + * 手工初型1
  130 + */
  131 + private List<String> manualPreform1;
  132 +
  133 + /**
  134 + * 手工初型1占比
  135 + */
  136 + private Double manualPreform1Rate;
  137 +
  138 + /**
  139 + * 手工初型2
  140 + */
  141 + private List<String> manualPreform2;
  142 +
  143 + /**
  144 + * 手工初型2占比
  145 + */
  146 + private Double manualPreform2Rate;
  147 +
  148 + /**
  149 + * pp样品确认意见
  150 + */
  151 + private List<String> ppConfirmResult;
  152 +
  153 + /**
  154 + * 自测通过开始时间
  155 + */
  156 + private String selfTestPassStartTime;
  157 +
  158 + /**
  159 + * 自测通过结束时间
  160 + */
  161 + private String selfTestPassEndTime;
  162 +
  163 + /**
  164 + * 中期验货结果PASS / FAIL
  165 + */
  166 + private List<String> midCheckResult;
  167 +
  168 + /**
  169 + * 尾期验货结果PASS / FAIL
  170 + */
  171 + private List<String> endCheckResult;
  172 +
  173 + /**
  174 + * 选择的字段
  175 + */
  176 + private OrderLockFieldVO fieldVO;
  177 +
  178 + /**
  179 + * 创建人
  180 + */
  181 + private String createBy;
  182 +
  183 + /**
  184 + * 业务员
  185 + */
  186 + private List<String> businessPerson;
  187 +
  188 +
  189 + private List<Long> exportOrderIds;
  190 +
  191 + /**
  192 + * invoice 首页筛选invoice。
  193 + */
  194 + private List<String> invoiceNo;
  195 +
  196 + /**
  197 + * checkNo 首页筛选Check。
  198 + */
  199 + private List<String> CheckNo;
  200 + /**
  201 + * invoice invoice状态。
  202 + */
  203 + private Long invoiceStatus;
  204 + /**
  205 + * checkNo checkNo状态。
  206 + */
  207 + private Long checkNoStatus;
  208 +}
  209 +
... ...
src/main/java/com/order/erp/domain/vo/order/ProjectApplyVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.IdType;
  4 +import com.baomidou.mybatisplus.annotation.TableId;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import com.order.erp.domain.dto.BaseDO;
  7 +import io.swagger.annotations.ApiModel;
  8 +import io.swagger.annotations.ApiModelProperty;
  9 +import lombok.AllArgsConstructor;
  10 +import lombok.Data;
  11 +import lombok.EqualsAndHashCode;
  12 +import lombok.NoArgsConstructor;
  13 +import lombok.experimental.SuperBuilder;
  14 +
  15 +import java.io.Serializable;
  16 +
  17 +/**
  18 + * <p>
  19 + * 项目-字段锁定申请表
  20 + * </p>
  21 + *
  22 + * @author author
  23 + * @since 2024-12-22
  24 + */
  25 +@Data
  26 +@EqualsAndHashCode(callSuper = false)
  27 +@SuperBuilder
  28 +@AllArgsConstructor
  29 +@NoArgsConstructor
  30 +@TableName("project_apply")
  31 +@ApiModel(value="ProjectApply对象", description="项目-字段锁定申请表")
  32 +public class ProjectApplyVO extends BaseDO implements Serializable {
  33 +
  34 + private static final long serialVersionUID = 1L;
  35 +
  36 + @TableId(value = "id", type = IdType.AUTO)
  37 + private Long id;
  38 +
  39 + @ApiModelProperty(value = "项目id")
  40 + private Long projectId;
  41 +
  42 + @ApiModelProperty(value = "项目号")
  43 + private String projectNoPrefix;
  44 +
  45 + @ApiModelProperty(value = "申请用户id")
  46 + private Long applyUserId;
  47 +
  48 + @ApiModelProperty(value = "审批用户id")
  49 + private Long auditUserId;
  50 +
  51 + @ApiModelProperty(value = "锁定字段 json字符串")
  52 + private String fields;
  53 +
  54 + @ApiModelProperty(value = "状态:0 待审批,1 通过,2 拒绝")
  55 + private Integer status;
  56 +
  57 + @ApiModelProperty(value = "审核备注")
  58 + private String auditRemark;
  59 +
  60 + @ApiModelProperty(value = "审批角色code集合,分割")
  61 + private String auditRoleCodes;
  62 +
  63 + @ApiModelProperty(value = "申请原因")
  64 + private String applyRemark;
  65 +
  66 +
  67 +}
... ...
src/main/java/com/order/erp/domain/vo/order/ProjectBaseInfoLockFieldVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.IdType;
  4 +import com.baomidou.mybatisplus.annotation.TableId;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import com.order.erp.domain.dto.BaseDO;
  7 +import io.swagger.annotations.ApiModel;
  8 +import io.swagger.annotations.ApiModelProperty;
  9 +import lombok.Data;
  10 +import lombok.EqualsAndHashCode;
  11 +import lombok.experimental.Accessors;
  12 +
  13 +import java.io.Serializable;
  14 +import java.math.BigDecimal;
  15 +import java.time.LocalDateTime;
  16 +
  17 +/**
  18 + * <p>
  19 + * 项目-字段锁定申请表
  20 + * </p>
  21 + *
  22 + * @author author
  23 + * @since 2024-12-22
  24 + */
  25 +@Data
  26 +@EqualsAndHashCode(callSuper = false)
  27 +@Accessors(chain = true)
  28 +@ApiModel(value="ProjectFieldLockApply对象", description="项目-字段锁定申请表")
  29 +public class ProjectBaseInfoLockFieldVO implements Serializable {
  30 +
  31 +
  32 + private Long projectId;
  33 +
  34 + private String projectNoPrefix;
  35 +
  36 + private String developmentCopyRmbTotalPrice;
  37 +
  38 + private String projectStartTime;
  39 +
  40 + private String projectEndTime;
  41 +
  42 +
  43 + private String spainPaidRmbCommission;
  44 +
  45 + private String paidRmbCommission;
  46 +
  47 + private String actualExchangeRate;
  48 +
  49 +
  50 +}
... ...
src/main/java/com/order/erp/domain/vo/order/ProjectBaseInfoVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.IdType;
  4 +import com.baomidou.mybatisplus.annotation.TableId;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import io.swagger.annotations.ApiModel;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import lombok.experimental.Accessors;
  10 +
  11 +import java.io.Serializable;
  12 +import java.math.BigDecimal;
  13 +import java.time.LocalDateTime;
  14 +
  15 +/**
  16 + * <p>
  17 + *
  18 + * </p>
  19 + *
  20 + * @author author
  21 + * @since 2024-12-18
  22 + */
  23 +@Data
  24 +@EqualsAndHashCode(callSuper = false)
  25 +@Accessors(chain = true)
  26 +@TableName("project_base_info")
  27 +@ApiModel(value="ProjectBaseInfoDO", description="")
  28 +public class ProjectBaseInfoVO implements Serializable {
  29 +
  30 + private static final long serialVersionUID = 1L;
  31 +
  32 + @TableId(value = "id", type = IdType.AUTO)
  33 + private Long id;
  34 +
  35 + private String projectNoPrefix;
  36 +
  37 + private BigDecimal developmentCopyRmbTotalPrice;
  38 +
  39 + private LocalDateTime projectStartTime;
  40 +
  41 + private LocalDateTime projectEndTime;
  42 +
  43 +
  44 + private BigDecimal spainPaidRmbCommission;
  45 +
  46 + private BigDecimal paidRmbCommission;
  47 +
  48 + private BigDecimal actualExchangeRate;
  49 +
  50 +
  51 +}
... ...
src/main/java/com/order/erp/domain/vo/order/QueryProjectLockFieldVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import com.order.erp.domain.vo.BasePageVO;
  5 +import io.swagger.annotations.ApiModel;
  6 +import lombok.AllArgsConstructor;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import lombok.NoArgsConstructor;
  10 +import lombok.experimental.SuperBuilder;
  11 +
  12 +import java.io.Serializable;
  13 +
  14 +/**
  15 + * <p>
  16 + *
  17 + * </p>
  18 + *
  19 + * @author author
  20 + * @since 2024-12-22
  21 + */
  22 +@Data
  23 +@EqualsAndHashCode(callSuper = false)
  24 +@SuperBuilder
  25 +@AllArgsConstructor
  26 +@NoArgsConstructor
  27 +@TableName("order_cost_info")
  28 +@ApiModel(value="OrderCostDetail对象", description="")
  29 +public class QueryProjectLockFieldVO extends BasePageVO implements Serializable {
  30 +
  31 + private static final long serialVersionUID = 1L;
  32 +
  33 + private Long orderId;
  34 +
  35 + private String productionDepartmentPredictPrice;
  36 +
  37 + private String productionActualPrice;
  38 +
  39 + private String packetActualRmbTotalPrice;
  40 +
  41 +
  42 +}
... ...
src/main/java/com/order/erp/mapper/OrderCostFieldLockRecordMapper.java 0 → 100644
  1 +package com.order.erp.mapper;
  2 +
  3 +import com.order.erp.domain.model.OrderCostFieldLockRecord;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +
  6 +/**
  7 + * <p>
  8 + * Mapper 接口
  9 + * </p>
  10 + *
  11 + * @author author
  12 + * @since 2024-12-22
  13 + */
  14 +public interface OrderCostFieldLockRecordMapper extends BaseMapper<OrderCostFieldLockRecord> {
  15 +
  16 +}
... ...
src/main/java/com/order/erp/mapper/ProjectApplyMapper.java 0 → 100644
  1 +package com.order.erp.mapper;
  2 +
  3 +import com.order.erp.domain.model.ProjectApplyDO;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +
  6 +/**
  7 + * <p>
  8 + * 项目-字段锁定申请表 Mapper 接口
  9 + * </p>
  10 + *
  11 + * @author author
  12 + * @since 2024-12-22
  13 + */
  14 +public interface ProjectApplyMapper extends BaseMapper<ProjectApplyDO> {
  15 +
  16 +}
... ...
src/main/java/com/order/erp/mapper/ProjectFieldLockRecordMapper.java 0 → 100644
  1 +package com.order.erp.mapper;
  2 +
  3 +import com.order.erp.domain.model.ProjectFieldLockRecord;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +
  6 +/**
  7 + * <p>
  8 + * 项目-字段锁定记录表 Mapper 接口
  9 + * </p>
  10 + *
  11 + * @author author
  12 + * @since 2024-12-22
  13 + */
  14 +public interface ProjectFieldLockRecordMapper extends BaseMapper<ProjectFieldLockRecord> {
  15 +
  16 +}
... ...
src/main/java/com/order/erp/mapper/order/OrderCostInfoMapper.java 0 → 100644
  1 +package com.order.erp.mapper.order;
  2 +
  3 +import com.order.erp.domain.dto.order.OrderCostInfoDO;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +
  6 +/**
  7 + * <p>
  8 + * Mapper 接口
  9 + * </p>
  10 + *
  11 + * @author author
  12 + * @since 2024-12-22
  13 + */
  14 +public interface OrderCostInfoMapper extends BaseMapper<OrderCostInfoDO> {
  15 +
  16 +}
... ...
src/main/java/com/order/erp/mapper/order/ProjectBaseInfoMapper.java 0 → 100644
  1 +package com.order.erp.mapper.order;
  2 +
  3 +import com.order.erp.domain.dto.order.ProjectBaseInfoDO;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +
  6 +/**
  7 + * <p>
  8 + * Mapper 接口
  9 + * </p>
  10 + *
  11 + * @author author
  12 + * @since 2024-12-18
  13 + */
  14 +public interface ProjectBaseInfoMapper extends BaseMapper<ProjectBaseInfoDO> {
  15 +
  16 +}
... ...
src/main/java/com/order/erp/service/IOrderCostFieldLockRecordService.java 0 → 100644
  1 +package com.order.erp.service;
  2 +
  3 +import com.order.erp.domain.model.OrderCostFieldLockRecord;
  4 +import com.baomidou.mybatisplus.extension.service.IService;
  5 +
  6 +/**
  7 + * <p>
  8 + * 服务类
  9 + * </p>
  10 + *
  11 + * @author author
  12 + * @since 2024-12-22
  13 + */
  14 +public interface IOrderCostFieldLockRecordService extends IService<OrderCostFieldLockRecord> {
  15 +
  16 +}
... ...
src/main/java/com/order/erp/service/IProjectApplyService.java 0 → 100644
  1 +package com.order.erp.service;
  2 +
  3 +import com.order.erp.domain.model.ProjectApplyDO;
  4 +import com.baomidou.mybatisplus.extension.service.IService;
  5 +
  6 +/**
  7 + * <p>
  8 + * 项目-字段锁定申请表 服务类
  9 + * </p>
  10 + *
  11 + * @author author
  12 + * @since 2024-12-22
  13 + */
  14 +public interface IProjectApplyService extends IService<ProjectApplyDO> {
  15 +
  16 +}
... ...
src/main/java/com/order/erp/service/IProjectFieldLockRecordService.java 0 → 100644
  1 +package com.order.erp.service;
  2 +
  3 +import com.order.erp.domain.model.ProjectFieldLockRecord;
  4 +import com.baomidou.mybatisplus.extension.service.IService;
  5 +
  6 +/**
  7 + * <p>
  8 + * 项目-字段锁定记录表 服务类
  9 + * </p>
  10 + *
  11 + * @author author
  12 + * @since 2024-12-22
  13 + */
  14 +public interface IProjectFieldLockRecordService extends IService<ProjectFieldLockRecord> {
  15 +
  16 +}
... ...
src/main/java/com/order/erp/service/SystemSettingService.java
... ... @@ -6,6 +6,8 @@ import com.order.erp.domain.dto.SystemSettingDO;
6 6 import com.order.erp.domain.vo.SystemSettingQueryVO;
7 7 import com.order.erp.domain.vo.SystemSettingVO;
8 8  
  9 +import java.math.BigDecimal;
  10 +
9 11 /**
10 12 * 系统配置(SystemSetting)表服务接口
11 13 *
... ... @@ -37,6 +39,8 @@ public interface SystemSettingService extends IService&lt;SystemSettingDO&gt; {
37 39 */
38 40 ServerResult listByPage(SystemSettingQueryVO systemSettingQueryVO);
39 41  
  42 + BigDecimal getExchangeRate();
  43 +
40 44 /**
41 45 * 新增数据
42 46 *
... ...
src/main/java/com/order/erp/service/impl/OrderCostFieldLockRecordServiceImpl.java 0 → 100644
  1 +package com.order.erp.service.impl;
  2 +
  3 +import com.order.erp.domain.model.OrderCostFieldLockRecord;
  4 +import com.order.erp.mapper.OrderCostFieldLockRecordMapper;
  5 +import com.order.erp.service.IOrderCostFieldLockRecordService;
  6 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  7 +import org.springframework.stereotype.Service;
  8 +
  9 +/**
  10 + * <p>
  11 + * 服务实现类
  12 + * </p>
  13 + *
  14 + * @author author
  15 + * @since 2024-12-22
  16 + */
  17 +@Service
  18 +public class OrderCostFieldLockRecordServiceImpl extends ServiceImpl<OrderCostFieldLockRecordMapper, OrderCostFieldLockRecord> implements IOrderCostFieldLockRecordService {
  19 +
  20 +}
... ...
src/main/java/com/order/erp/service/impl/ProjectApplyServiceImpl.java 0 → 100644
  1 +package com.order.erp.service.impl;
  2 +
  3 +import com.order.erp.domain.model.ProjectApplyDO;
  4 +import com.order.erp.mapper.ProjectApplyMapper;
  5 +import com.order.erp.service.IProjectApplyService;
  6 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  7 +import org.springframework.stereotype.Service;
  8 +
  9 +/**
  10 + * <p>
  11 + * 项目-字段锁定申请表 服务实现类
  12 + * </p>
  13 + *
  14 + * @author author
  15 + * @since 2024-12-22
  16 + */
  17 +@Service
  18 +public class ProjectApplyServiceImpl extends ServiceImpl<ProjectApplyMapper, ProjectApplyDO> implements IProjectApplyService {
  19 +
  20 +}
... ...
src/main/java/com/order/erp/service/impl/ProjectFieldLockRecordServiceImpl.java 0 → 100644
  1 +package com.order.erp.service.impl;
  2 +
  3 +import com.order.erp.domain.model.ProjectFieldLockRecord;
  4 +import com.order.erp.mapper.ProjectFieldLockRecordMapper;
  5 +import com.order.erp.service.IProjectFieldLockRecordService;
  6 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  7 +import org.springframework.stereotype.Service;
  8 +
  9 +/**
  10 + * <p>
  11 + * 项目-字段锁定记录表 服务实现类
  12 + * </p>
  13 + *
  14 + * @author author
  15 + * @since 2024-12-22
  16 + */
  17 +@Service
  18 +public class ProjectFieldLockRecordServiceImpl extends ServiceImpl<ProjectFieldLockRecordMapper, ProjectFieldLockRecord> implements IProjectFieldLockRecordService {
  19 +
  20 +}
... ...
src/main/java/com/order/erp/service/impl/SystemSettingServiceImpl.java
... ... @@ -24,7 +24,9 @@ import com.order.erp.service.SystemSettingService;
24 24 import lombok.extern.slf4j.Slf4j;
25 25 import org.springframework.beans.BeanUtils;
26 26 import org.springframework.stereotype.Service;
  27 +import springfox.documentation.annotations.Cacheable;
27 28  
  29 +import java.math.BigDecimal;
28 30 import java.util.List;
29 31 import java.util.Objects;
30 32 import java.util.stream.Collectors;
... ... @@ -110,6 +112,15 @@ public class SystemSettingServiceImpl extends ServiceImpl&lt;SystemSettingMapper, S
110 112 .eq(StringUtils.isNotBlank(queryVO.getRelationCode()), SystemSettingDO::getRelationCode, queryVO.getRelationCode());
111 113 }
112 114  
  115 + @Override
  116 + public BigDecimal getExchangeRate(){
  117 + SystemSettingDO exchangeRate = this.lambdaQuery()
  118 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  119 + .eq(SystemSettingDO::getSettingCode, "exchangeRate")
  120 + .one();
  121 + return BigDecimal.valueOf(Double.parseDouble(exchangeRate.getSettingValue()));
  122 + }
  123 +
113 124  
114 125 /**
115 126 * 新增数据
... ...
src/main/java/com/order/erp/service/order/IOrderCostInfoService.java 0 → 100644
  1 +package com.order.erp.service.order;
  2 +
  3 +import com.order.erp.common.constant.ServerResult;
  4 +import com.order.erp.domain.dto.order.OrderCostInfoDO;
  5 +import com.baomidou.mybatisplus.extension.service.IService;
  6 +import com.order.erp.domain.vo.order.OrderBaseInfoQueryVO;
  7 +import com.order.erp.domain.vo.order.OrderCostInfoVO;
  8 +import com.order.erp.domain.vo.order.OrderCostInfolockFieldVO;
  9 +
  10 +/**
  11 + * <p>
  12 + * 服务类
  13 + * </p>
  14 + *
  15 + * @author author
  16 + * @since 2024-12-22
  17 + */
  18 +public interface IOrderCostInfoService extends IService<OrderCostInfoDO> {
  19 +
  20 + ServerResult edit(OrderCostInfoVO vo);
  21 +
  22 + ServerResult applyEditFileds(OrderCostInfolockFieldVO vo);
  23 +
  24 + ServerResult listInnerProfitDetailByPage(OrderBaseInfoQueryVO queryVO);
  25 +
  26 + ServerResult listBusinessProfitDetailByPage(OrderBaseInfoQueryVO queryVO);
  27 +}
... ...
src/main/java/com/order/erp/service/order/IProjectBaseInfoService.java 0 → 100644
  1 +package com.order.erp.service.order;
  2 +
  3 +import com.order.erp.common.constant.ServerResult;
  4 +import com.order.erp.domain.dto.order.ProjectBaseInfoDO;
  5 +import com.baomidou.mybatisplus.extension.service.IService;
  6 +import com.order.erp.domain.vo.order.*;
  7 +
  8 +import javax.servlet.http.HttpServletResponse;
  9 +
  10 +/**
  11 + * <p>
  12 + * 服务类
  13 + * </p>
  14 + *
  15 + * @author author
  16 + * @since 2024-12-18
  17 + */
  18 +public interface IProjectBaseInfoService extends IService<ProjectBaseInfoDO> {
  19 +
  20 + ServerResult edit(ProjectBaseInfoVO vo);
  21 +
  22 + ServerResult applyEditFileds(ProjectBaseInfoLockFieldVO vo);
  23 +
  24 + ServerResult pageProjectLockFieldApply(QueryProjectLockFieldVO vo);
  25 +
  26 + ServerResult audit(AuditVO vo);
  27 +
  28 + ServerResult listInnerProfitInfoByPage(OrderBaseInfoQueryVO queryVO);
  29 +
  30 + ServerResult listBusinessProfitInfoByPage(OrderBaseInfoQueryVO queryVO);
  31 +
  32 + void exportBusinessProfitInfo(HttpServletResponse response, String projectNoPrefix) throws Exception;
  33 +
  34 + void exportInnerProfitInfo(HttpServletResponse response, String projectNoPrefix) throws Exception;
  35 +}
... ...
src/main/java/com/order/erp/service/order/OrderProfitAnalysisService.java
... ... @@ -4,10 +4,9 @@ import com.baomidou.mybatisplus.extension.service.IService;
4 4 import com.order.erp.common.constant.ServerResult;
5 5 import com.order.erp.domain.dto.order.OrderProfitAnalysisDO;
6 6 import com.order.erp.domain.vo.OrderProfitAnalysisVo;
7   -import com.order.erp.domain.vo.order.OrderProfitAnalysisQueryVO;
8   -import com.order.erp.domain.vo.order.OrderProfitAnalysisVO;
9   -import com.order.erp.domain.vo.order.ProfitCalculateVO;
  7 +import com.order.erp.domain.vo.order.*;
10 8  
  9 +import javax.servlet.http.HttpServletResponse;
11 10 import java.util.List;
12 11  
13 12 /**
... ...
src/main/java/com/order/erp/service/order/impl/CalculateProfitServiceImpl.java
... ... @@ -67,6 +67,10 @@ public class CalculateProfitServiceImpl {
67 67 */
68 68 public ServerResult businessProfitRatioExport(HttpServletResponse response, BusinessProfitRatioQueryVO queryVO) throws IOException {
69 69 BusinessProfitRatioResultVO resultVO = buildBusinessProfitRatioResultVO(queryVO);
  70 + return writeBusinessProfitRatioResult(response, resultVO);
  71 + }
  72 +
  73 + private ServerResult<Object> writeBusinessProfitRatioResult(HttpServletResponse response, BusinessProfitRatioResultVO resultVO) throws IOException {
70 74 //开始
71 75 Workbook workbook = new XSSFWorkbook();
72 76 Sheet sheet = workbook.createSheet("业务净利润分析表");
... ... @@ -90,7 +94,7 @@ public class CalculateProfitServiceImpl {
90 94  
91 95 // 第二行
92 96 createMergedCell(sheet, workbook, 4, 0, 4, 5, 0, 1, "项目号");
93   - createMergedCell(sheet, workbook, 4, 2, 4, 5, 2, 4, String.join(",",resultVO.getProjectNo()));
  97 + createMergedCell(sheet, workbook, 4, 2, 4, 5, 2, 4, String.join(",", resultVO.getProjectNo()));
94 98 createMergedCell(sheet, workbook, 4, 5, 4, 5, 5, 6, "开始时间");
95 99 createMergedCell(sheet, workbook, 4, 7, 4, 5, 7, 9, "结束时间");
96 100 // 第三行
... ... @@ -111,55 +115,55 @@ public class CalculateProfitServiceImpl {
111 115 createMergedCell(sheet, workbook, 10, 7, 10, 11, 7, 9, "备注");
112 116 //第六行
113 117 createMergedCell(sheet, workbook, 12, 0, 12, 13, 0, 4, "客户总金额计算");
114   - createMergedCell(sheet, workbook, 12, 5, 12, 13, 5, 6, "¥"+resultVO.getCustomerTotalPrice());
115   - createMergedCell(sheet, workbook, 12, 7, 12, 13, 7, 9, "$"+resultVO.getCustomerTotalPriceUsd());
  118 + createMergedCell(sheet, workbook, 12, 5, 12, 13, 5, 6, "¥"+ resultVO.getCustomerTotalPrice());
  119 + createMergedCell(sheet, workbook, 12, 7, 12, 13, 7, 9, "$"+ resultVO.getCustomerTotalPriceUsd());
116 120 ////第七行
117 121 createMergedCell(sheet, workbook, 14, 0, 14, 15, 0, 4, "生产科总价合计");
118   - createMergedCell(sheet, workbook, 14, 5, 14, 15, 5, 6, "¥"+resultVO.getProductionDepartmentTotalPrice());
119   - createMergedCell(sheet, workbook, 14, 7, 14, 15, 7, 9, "$"+resultVO.getProductionDepartmentTotalPriceUsd());
  122 + createMergedCell(sheet, workbook, 14, 5, 14, 15, 5, 6, "¥"+ resultVO.getProductionDepartmentTotalPrice());
  123 + createMergedCell(sheet, workbook, 14, 7, 14, 15, 7, 9, "$"+ resultVO.getProductionDepartmentTotalPriceUsd());
120 124 ////第八行
121 125 createMergedCell(sheet, workbook, 16, 0, 16, 17, 0, 4, "包装费用合计");
122   - createMergedCell(sheet, workbook, 16, 5, 16, 17, 5, 6, "¥"+resultVO.getPacketTotalPrice());
123   - createMergedCell(sheet, workbook, 16, 7, 16, 17, 7, 9, "$"+resultVO.getPacketTotalPriceUsd());
  126 + createMergedCell(sheet, workbook, 16, 5, 16, 17, 5, 6, "¥"+ resultVO.getPacketTotalPrice());
  127 + createMergedCell(sheet, workbook, 16, 7, 16, 17, 7, 9, "$"+ resultVO.getPacketTotalPriceUsd());
124 128 ////第九行
125 129 createMergedCell(sheet, workbook, 18, 0, 18, 19, 0, 4, "研发开发费合计");
126   - createMergedCell(sheet, workbook, 18, 5, 18, 19, 5, 6, "¥"+resultVO.getDevelopTotalPrice().setScale(2, RoundingMode.HALF_UP));
  130 + createMergedCell(sheet, workbook, 18, 5, 18, 19, 5, 6, "¥"+ resultVO.getDevelopTotalPrice().setScale(2, RoundingMode.HALF_UP));
127 131 createMergedCell(sheet, workbook, 18, 7, 18, 19, 7, 9, "");
128 132 ////第十行
129 133 createMergedCell(sheet, workbook, 20, 0, 20, 21, 0, 4, "复制费用合计");
130   - createMergedCell(sheet, workbook, 20, 5, 20, 21, 5, 6, "¥"+resultVO.getCopyTotalPrice().setScale(2, RoundingMode.HALF_UP));
  134 + createMergedCell(sheet, workbook, 20, 5, 20, 21, 5, 6, "¥"+ resultVO.getCopyTotalPrice().setScale(2, RoundingMode.HALF_UP));
131 135 createMergedCell(sheet, workbook, 20, 7, 20, 21, 7, 9, "");
132 136 //第十一行
133 137 createMergedCell(sheet, workbook, 22, 0, 22, 23, 0, 4, "固定成本");
134   - createMergedCell(sheet, workbook, 22, 5, 22, 23, 5, 6, "¥"+resultVO.getFixCost());
  138 + createMergedCell(sheet, workbook, 22, 5, 22, 23, 5, 6, "¥"+ resultVO.getFixCost());
135 139 createMergedCell(sheet, workbook, 22, 7, 22, 23, 7, 9, "");
136 140 //第十二行
137 141 createMergedCell(sheet, workbook, 24, 0, 24, 25, 0, 4, "西班牙提成");
138   - createMergedCell(sheet, workbook, 24, 5, 24, 25, 5, 6, "¥"+resultVO.getSpainRatioProfitPrice());
  142 + createMergedCell(sheet, workbook, 24, 5, 24, 25, 5, 6, "¥"+ resultVO.getSpainRatioProfitPrice());
139 143 createMergedCell(sheet, workbook, 24, 7, 24, 25, 7, 9, "");
140 144 //第十三行
141 145 createMergedCell(sheet, workbook, 26, 0, 26, 27, 0, 4, "中国团队提成");
142   - createMergedCell(sheet, workbook, 26, 5, 26, 27, 5, 6, "¥"+resultVO.getChinaRatioProfitPrice());
  146 + createMergedCell(sheet, workbook, 26, 5, 26, 27, 5, 6, "¥"+ resultVO.getChinaRatioProfitPrice());
143 147 createMergedCell(sheet, workbook, 26, 7, 26, 27, 7, 9, "");
144   - //第十四行
  148 + //第十四行
145 149 createMergedCell(sheet, workbook, 28, 0, 28, 29, 0, 4, "支出合计");
146   - createMergedCell(sheet, workbook, 28, 5, 28, 29, 5, 6, "¥"+resultVO.getOutTotalPrice());
  150 + createMergedCell(sheet, workbook, 28, 5, 28, 29, 5, 6, "¥"+ resultVO.getOutTotalPrice());
147 151 createMergedCell(sheet, workbook, 28, 7, 28, 29, 7, 9, "");
148 152 //第十五行
149 153 createMergedCell(sheet, workbook, 30, 0, 30, 31, 0, 4, "毛利润");
150   - createMergedCell(sheet, workbook, 30, 5, 30, 31, 5, 6, "¥"+resultVO.getGrossProfit());
  154 + createMergedCell(sheet, workbook, 30, 5, 30, 31, 5, 6, "¥"+ resultVO.getGrossProfit());
151 155 createMergedCell(sheet, workbook, 30, 7, 30, 31, 7, 9, "");
152 156 ////第十六行
153 157 createMergedCell(sheet, workbook, 32, 0, 32, 33, 0, 4, "研发贸易净利润");
154   - createMergedCell(sheet, workbook, 32, 5, 32, 33, 5, 6, "¥"+resultVO.getDevelopProfit());
  158 + createMergedCell(sheet, workbook, 32, 5, 32, 33, 5, 6, "¥"+ resultVO.getDevelopProfit());
155 159 createMergedCell(sheet, workbook, 32, 7, 32, 33, 7, 9, "");
156 160 ////第十七行
157 161 createMergedCell(sheet, workbook, 34, 0, 34, 35, 0, 4, "包装费用合计金额");
158   - createMergedCell(sheet, workbook, 34, 5, 34, 35, 5, 6, "¥"+resultVO.getPacketTotalPrice());
  162 + createMergedCell(sheet, workbook, 34, 5, 34, 35, 5, 6, "¥"+ resultVO.getPacketTotalPrice());
159 163 createMergedCell(sheet, workbook, 34, 7, 34, 35, 7, 9, "");
160 164 ////第十八行
161 165 createMergedCell(sheet, workbook, 36, 0, 36, 37, 0, 4, "包装费用实际金额");
162   - createMergedCell(sheet, workbook, 36, 5, 36, 37, 5, 6, "¥"+resultVO.getPacketActualTotalPrice().setScale(2, RoundingMode.HALF_UP));
  166 + createMergedCell(sheet, workbook, 36, 5, 36, 37, 5, 6, "¥"+ resultVO.getPacketActualTotalPrice().setScale(2, RoundingMode.HALF_UP));
163 167 createMergedCell(sheet, workbook, 36, 7, 36, 37, 7, 9, "");
164 168 ////第十九行
165 169 createMergedCell(sheet, workbook, 38, 0, 38, 39, 0, 4, "订单总数量");
... ... @@ -167,27 +171,27 @@ public class CalculateProfitServiceImpl {
167 171 createMergedCell(sheet, workbook, 38, 7, 38, 39, 7, 9, "");
168 172 ////第二十行
169 173 createMergedCell(sheet, workbook, 40, 0, 40, 41, 0, 4, "实际跟单单价=实际跟单费用/件数");
170   - createMergedCell(sheet, workbook, 40, 5, 40, 41, 5, 6, "¥"+resultVO.getActualRmbPrice());
  174 + createMergedCell(sheet, workbook, 40, 5, 40, 41, 5, 6, "¥"+ resultVO.getActualRmbPrice());
171 175 createMergedCell(sheet, workbook, 40, 7, 40, 41, 7, 9, "");
172 176 //第二十一行
173 177 createMergedCell(sheet, workbook, 42, 0, 42, 43, 0, 4, "实际跟单单价折算美金");
174   - createMergedCell(sheet, workbook, 42, 5, 42, 43, 5, 6, "$"+resultVO.getActualPrice());
  178 + createMergedCell(sheet, workbook, 42, 5, 42, 43, 5, 6, "$"+ resultVO.getActualPrice());
175 179 createMergedCell(sheet, workbook, 42, 7, 42, 43, 7, 9, "");
176 180 //第二十二行
177 181 createMergedCell(sheet, workbook, 44, 0, 44, 45, 0, 4, "包装费用收益");
178   - createMergedCell(sheet, workbook, 44, 5, 44, 45, 5, 6, "¥"+resultVO.getPacketProfitPrice());
  182 + createMergedCell(sheet, workbook, 44, 5, 44, 45, 5, 6, "¥"+ resultVO.getPacketProfitPrice());
179 183 createMergedCell(sheet, workbook, 44, 7, 44, 45, 7, 9, "");
180 184 //第二十三行
181 185 createMergedCell(sheet, workbook, 46, 0, 46, 47, 0, 4, "实际汇率");
182   - createMergedCell(sheet, workbook, 46, 5, 46, 47, 5, 6, "¥"+resultVO.getActualRatio().setScale(2, RoundingMode.HALF_UP));
  186 + createMergedCell(sheet, workbook, 46, 5, 46, 47, 5, 6, "¥"+ resultVO.getActualRatio().setScale(2, RoundingMode.HALF_UP));
183 187 createMergedCell(sheet, workbook, 46, 7, 46, 47, 7, 9, "");
184 188 //第二十四行
185 189 createMergedCell(sheet, workbook, 48, 0, 48, 49, 0, 4, "汇率收益");
186   - createMergedCell(sheet, workbook, 48, 5, 48, 49, 5, 6, "¥"+resultVO.getActualRatioProfitPrice());
  190 + createMergedCell(sheet, workbook, 48, 5, 48, 49, 5, 6, "¥"+ resultVO.getActualRatioProfitPrice());
187 191 createMergedCell(sheet, workbook, 48, 7, 48, 49, 7, 9, "");
188 192 //第二十五行
189 193 createMergedCell(sheet, workbook, 50, 0, 50, 51, 0, 4, "综合收益");
190   - createMergedCell(sheet, workbook, 50, 5, 50, 51, 5, 6, "¥"+resultVO.getTotalProfitPrice());
  194 + createMergedCell(sheet, workbook, 50, 5, 50, 51, 5, 6, "¥"+ resultVO.getTotalProfitPrice());
191 195 createMergedCell(sheet, workbook, 50, 7, 50, 51, 7, 9, "");
192 196 response.setHeader("Content-Disposition", "attachment; filename=\"-.xlsx\"");
193 197 workbook.write(response.getOutputStream());
... ... @@ -203,6 +207,10 @@ public class CalculateProfitServiceImpl {
203 207 */
204 208 public ServerResult innerProfitRatioExport(HttpServletResponse response,InnerProfitRatioQueryVO queryVO) throws IOException {
205 209 InnerProfitRatioResultVO resultVO = buildInnerProfitRatioResultVO(queryVO);
  210 + return writeInnerProfitRatioData(response, resultVO);
  211 + }
  212 +
  213 + private ServerResult<Object> writeInnerProfitRatioData(HttpServletResponse response, InnerProfitRatioResultVO resultVO) throws IOException {
206 214 Workbook workbook = new XSSFWorkbook();
207 215 Sheet sheet = workbook.createSheet("内部生产净利润分析表");
208 216 Row row = sheet.createRow(0);
... ... @@ -270,7 +278,7 @@ public class CalculateProfitServiceImpl {
270 278 createMergedCell(sheet, workbook, 20, 4, 20, 21, 4, 5, "¥"+ resultVO.getInnerProduceTotalPrice());
271 279 createMergedCell(sheet, workbook, 20, 6, 20, 21, 6, 7, "");
272 280 createMergedCell(sheet, workbook, 20, 8, 20, 21, 8, 10, "");
273   - //第十一行
  281 + //第十一行
274 282 createMergedCell(sheet, workbook, 22, 0, 22, 23, 0, 3, "内部生产净利润");
275 283 createMergedCell(sheet, workbook, 22, 4, 22, 23, 4, 5, "¥"+ resultVO.getInnerProduceTotalProfit());
276 284 createMergedCell(sheet, workbook, 22, 6, 22, 23, 6, 7, "");
... ... @@ -281,6 +289,7 @@ public class CalculateProfitServiceImpl {
281 289 workbook.close();
282 290 return ServerResult.success();
283 291 }
  292 +
284 293 public void createMergedCell(Sheet sheet, Workbook workbook, int rowIndex, int colIndex, int startRow, int endRow, int startCol, int endCol, String value) {
285 294 // 创建或获取当前行
286 295 Row row = sheet.getRow(rowIndex);
... ...
src/main/java/com/order/erp/service/order/impl/OrderBaseInfoServiceImpl.java
... ... @@ -31,22 +31,19 @@ import com.order.erp.domain.dto.admin.AdminUserRoleDO;
31 31 import com.order.erp.domain.dto.order.*;
32 32 import com.order.erp.domain.vo.ProducePdfVO;
33 33 import com.order.erp.domain.vo.order.*;
34   -import com.order.erp.job.OrderOverTimeEventJob;
35 34 import com.order.erp.mapper.order.OrderBaseInfoMapper;
36 35 import com.order.erp.service.SystemSettingService;
37 36 import com.order.erp.service.admin.AdminUserRoleService;
38 37 import com.order.erp.service.admin.AdminUserService;
39 38 import com.order.erp.service.order.*;
40   -import freemarker.template.TemplateException;
41 39 import lombok.extern.slf4j.Slf4j;
42   -import org.joda.time.DateTime;
43 40 import org.springframework.beans.BeanUtils;
  41 +import org.springframework.beans.factory.annotation.Autowired;
44 42 import org.springframework.beans.factory.annotation.Value;
45 43 import org.springframework.stereotype.Service;
46 44 import org.springframework.transaction.annotation.Transactional;
47 45  
48 46 import javax.annotation.Resource;
49   -import javax.mail.MessagingException;
50 47 import javax.servlet.http.HttpServletResponse;
51 48 import java.io.File;
52 49 import java.io.IOException;
... ... @@ -56,7 +53,6 @@ import java.math.RoundingMode;
56 53 import java.net.URL;
57 54 import java.text.DecimalFormat;
58 55 import java.time.LocalDate;
59   -import java.time.LocalDateTime;
60 56 import java.time.Month;
61 57 import java.util.*;
62 58 import java.util.concurrent.TimeUnit;
... ... @@ -146,6 +142,8 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
146 142  
147 143 @Resource
148 144 private ProducePaymentCheckBillOrderService producePaymentCheckBillOrderService;
  145 + @Autowired
  146 + private IOrderCostInfoService orderCostInfoService;
149 147  
150 148  
151 149  
... ... @@ -232,6 +230,8 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
232 230  
233 231 // 填充发票信息
234 232 fillInvoiceNo(resultVOList);
  233 +
  234 + fillOrderCostDetils(resultVOList);
235 235 //第四版 start
236 236 /* //需要填充生产科对账单号信息
237 237 fillCheckNo(resultVOList);
... ... @@ -252,6 +252,29 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
252 252 return resultVOList;
253 253 }
254 254  
  255 + private void fillOrderCostDetils(List<OrderInfoResultVO> resultVOList) {
  256 + if (CollectionUtils.isEmpty(resultVOList)) {
  257 + return;
  258 + }
  259 +
  260 + Set<Long> orderIds = resultVOList.stream().map(OrderInfoResultVO::getId).collect(Collectors.toSet());
  261 + List<OrderCostInfoDO> orderCostInfoDOS = orderCostInfoService.lambdaQuery()
  262 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  263 + .in(OrderCostInfoDO::getOrderId, orderIds)
  264 + .list();
  265 +
  266 + if (CollectionUtils.isNotEmpty(orderCostInfoDOS)) {
  267 + Map<Long, OrderCostInfoDO> orderCostDetailDOMap = orderCostInfoDOS.stream().collect(Collectors.toMap(OrderCostInfoDO::getOrderId, Function.identity(), (v1, v2) -> v1));
  268 + resultVOList.forEach(result -> {
  269 + if (orderCostDetailDOMap.containsKey(result.getId())) {
  270 + OrderCostInfoDO orderCostInfoDO = orderCostDetailDOMap.get(result.getId());
  271 + OrderCostInfoVO orderCostInfoVO = BeanUtil.copyProperties(orderCostInfoDO, OrderCostInfoVO.class);
  272 + result.setOrderCostInfo(orderCostInfoVO);
  273 + }
  274 + });
  275 + }
  276 + }
  277 +
255 278 @Override
256 279 public void export(HttpServletResponse response, OrderBaseInfoQueryVO queryVO) throws IOException, Excel4JException {
257 280 OrderLockFieldVO lockFieldVO = queryVO.getFieldVO();
... ... @@ -1511,6 +1534,8 @@ end
1511 1534 .in(CollectionUtils.isNotEmpty(queryVO.getCheckNo()),OrderBaseInfoDO::getCheckNo,queryVO.getCheckNo())
1512 1535 .eq(Objects.nonNull(queryVO.getInvoiceStatus()), OrderBaseInfoDO::getInvoiceStatus, queryVO.getInvoiceStatus())
1513 1536 .eq(Objects.nonNull(queryVO.getCheckNoStatus()), OrderBaseInfoDO::getCheckStatus, queryVO.getCheckNoStatus())
  1537 + .in(CollUtil.isNotEmpty(queryVO.getIds()), OrderBaseInfoDO::getId, queryVO.getIds())
  1538 + .likeRight(StringUtils.isNotBlank(queryVO.getProjectNoLikeRight()), OrderBaseInfoDO::getProjectNo, queryVO.getProjectNoLikeRight())
1514 1539 .orderByDesc(OrderBaseInfoDO::getId)
1515 1540 ;
1516 1541 }
... ...
src/main/java/com/order/erp/service/order/impl/OrderCostInfoServiceImpl.java 0 → 100644
  1 +package com.order.erp.service.order.impl;
  2 +
  3 +import cn.hutool.core.bean.BeanUtil;
  4 +import cn.hutool.core.collection.CollUtil;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  7 +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
  8 +import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  9 +import com.fasterxml.jackson.core.JsonProcessingException;
  10 +import com.fasterxml.jackson.databind.ObjectMapper;
  11 +import com.order.erp.common.constant.Constant;
  12 +import com.order.erp.common.constant.ServerResult;
  13 +import com.order.erp.common.constant.ServerResultCode;
  14 +import com.order.erp.common.exception.BusinessException;
  15 +import com.order.erp.config.DataScope;
  16 +import com.order.erp.domain.ApplyStatusEnum;
  17 +import com.order.erp.domain.ApplyTypeEnum;
  18 +import com.order.erp.domain.ProjectApplyTypeEnum;
  19 +import com.order.erp.domain.dto.BaseDO;
  20 +import com.order.erp.domain.dto.order.OrderCostInfoDO;
  21 +import com.order.erp.domain.dto.order.OrderFieldLockApplyDO;
  22 +import com.order.erp.domain.model.OrderCostFieldLockRecord;
  23 +import com.order.erp.domain.vo.order.*;
  24 +import com.order.erp.mapper.order.OrderCostInfoMapper;
  25 +import com.order.erp.service.IOrderCostFieldLockRecordService;
  26 +import com.order.erp.service.order.IOrderCostInfoService;
  27 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  28 +import com.order.erp.service.order.OrderBaseInfoService;
  29 +import com.order.erp.service.order.OrderFieldLockApplyService;
  30 +import com.order.erp.service.order.OrderFieldLockRecordService;
  31 +import org.springframework.beans.BeanUtils;
  32 +import org.springframework.beans.factory.annotation.Autowired;
  33 +import org.springframework.stereotype.Service;
  34 +
  35 +import javax.annotation.Resource;
  36 +import java.math.BigDecimal;
  37 +import java.math.RoundingMode;
  38 +import java.util.List;
  39 +import java.util.Map;
  40 +import java.util.Objects;
  41 +import java.util.Set;
  42 +import java.util.stream.Collectors;
  43 +
  44 +/**
  45 + * <p>
  46 + * 服务实现类
  47 + * </p>
  48 + *
  49 + * @author author
  50 + * @since 2024-12-22
  51 + */
  52 +@Service
  53 +public class OrderCostInfoServiceImpl extends ServiceImpl<OrderCostInfoMapper, OrderCostInfoDO> implements IOrderCostInfoService {
  54 + @Autowired
  55 + private DataScope dataScope;
  56 + @Resource
  57 + private OrderFieldLockRecordService orderFieldLockRecordService;
  58 + @Resource
  59 + private OrderFieldLockApplyService orderFieldLockApplyService;
  60 + @Autowired
  61 + private OrderBaseInfoService orderBaseInfoService;
  62 + @Autowired
  63 + private IOrderCostFieldLockRecordService orderCostFieldLockRecordService;
  64 +
  65 + @Override
  66 + public ServerResult edit(OrderCostInfoVO vo) {
  67 + Long id = vo.getId();
  68 + OrderCostInfoDO byId = this.getById(id);
  69 + if (Objects.isNull(byId)) {
  70 + byId = BeanUtil.copyProperties(vo, OrderCostInfoDO.class);
  71 + }else {
  72 + BeanUtil.copyProperties(vo, byId);
  73 + }
  74 + return ServerResult.success(this.saveOrUpdate(byId));
  75 + }
  76 + @Override
  77 + public ServerResult applyEditFileds(OrderCostInfolockFieldVO vo) {
  78 + List<OrderFieldLockApplyDO> applyDOS = orderFieldLockApplyService.list(new LambdaQueryWrapper<OrderFieldLockApplyDO>()
  79 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  80 + .eq(OrderFieldLockApplyDO::getOrderId, vo.getOrderId())
  81 + .eq(OrderFieldLockApplyDO::getApplyUserId, dataScope.getLoginUserId())
  82 + .eq(OrderFieldLockApplyDO::getType, ProjectApplyTypeEnum.FIELD_EDIT_APPLY.getType())
  83 + .eq(OrderFieldLockApplyDO::getStatus, ApplyStatusEnum.WAIT_AUDIT.getStatus()));
  84 + if (CollectionUtils.isNotEmpty(applyDOS)) {
  85 + throw new BusinessException(ServerResultCode.APPLY_UNLOCK_FIELD_EXIST);
  86 + }
  87 + Long orderId = vo.getOrderId();
  88 + vo.setOrderId(null);
  89 + OrderFieldLockApplyDO build = OrderFieldLockApplyDO.builder()
  90 + .orderId(orderId)
  91 + .applyUserId(dataScope.getLoginUserId())
  92 + .fields(JSONObject.toJSONString(vo))
  93 + .status(ApplyStatusEnum.WAIT_AUDIT.getStatus())
  94 + .type(ApplyTypeEnum.ORDER_COST_FIELD_EDIT_APPLY.getType())
  95 + .remark(ApplyTypeEnum.ORDER_COST_FIELD_EDIT_APPLY.getDesc())
  96 + .build();
  97 + orderFieldLockApplyService.save(build);
  98 + return ServerResult.success();
  99 + }
  100 +
  101 + @Override
  102 + public ServerResult<Page<InnerProfitDetailVO>> listInnerProfitDetailByPage(OrderBaseInfoQueryVO queryVO) {
  103 + ServerResult serverResult = orderBaseInfoService.listByPage(queryVO);
  104 + Page<OrderInfoResultVO> page = (Page<OrderInfoResultVO>) serverResult.getData();
  105 + List<OrderInfoResultVO> records = page.getRecords();
  106 + List<OrderCostFieldLockRecord> lockRecords = orderCostFieldLockRecordService
  107 + .lambdaQuery()
  108 + .func(query -> {
  109 + Set<Long> collect = records.stream().map(OrderInfoResultVO::getId).collect(Collectors.toSet());
  110 + if(CollUtil.isNotEmpty(collect)){
  111 + query.in(OrderCostFieldLockRecord::getOrderId,collect);
  112 +
  113 + }else {
  114 + query.apply("1!=1");
  115 + }
  116 + })
  117 + .list();
  118 + ObjectMapper objectMapper = new ObjectMapper();
  119 + Map<Long,OrderCostInfolockFieldVO> orderId2fieldMapMap = lockRecords.stream().collect(Collectors.toMap(OrderCostFieldLockRecord::getOrderId, record -> {
  120 + try {
  121 + return objectMapper.readValue(record.getFields(), OrderCostInfolockFieldVO.class);
  122 + } catch (JsonProcessingException e) {
  123 + throw new RuntimeException(e);
  124 + }
  125 + }));
  126 + List<InnerProfitDetailVO> innerProfitRatioResultVOs = records.stream().map(record -> {
  127 + InnerProfitDetailVO vo = InnerProfitDetailVO.builder()
  128 + .customerCode(record.getCustomerCode())
  129 + .projectNo(record.getProjectNo())
  130 + .productionDepartment(record.getProductionDepartment())
  131 + .innerNo(record.getInnerNo())
  132 + .picUrl(record.getPicUrl())
  133 + .orderCount(record.getOrderCount())
  134 + .productionDepartmentPrice(Objects.isNull(record.getProfitAnalysisInfo()) ? null : record.getProfitAnalysisInfo().getProductionDepartmentPrice())
  135 + .productionDepartmentTotalPrice(Objects.isNull(record.getProfitAnalysisInfo()) ? null : record.getProfitAnalysisInfo().getProductionDepartmentTotalPrice())
  136 + .productionDepartmentPredictPrice(Objects.isNull(record.getOrderCostInfo()) ? null : record.getOrderCostInfo().getProductionDepartmentPredictPrice())
  137 + .productionActualPrice(Objects.isNull(record.getOrderCostInfo()) ? null : record.getOrderCostInfo().getProductionActualPrice())
  138 + .build();
  139 +
  140 + if (Objects.nonNull(vo.getProductionDepartmentPredictPrice())
  141 + && Objects.nonNull(vo.getProductionActualPrice())
  142 + && vo.getProductionDepartmentPredictPrice().compareTo(BigDecimal.ZERO) != 0) {
  143 + //预算占比=实际发生费用/预算金额
  144 + vo.setPredictRatio(vo.getProductionActualPrice().divide(vo.getProductionDepartmentPredictPrice(), 4, RoundingMode.HALF_UP));
  145 + //预算占比与实际比占比差:1-预算占比
  146 + vo.setPredictAndActualRatio(new BigDecimal(1).subtract(vo.getPredictRatio()));
  147 + }
  148 + if (Objects.nonNull(vo.getProductionDepartmentTotalPrice())
  149 + && Objects.nonNull(vo.getProductionDepartmentPredictPrice())) {
  150 + //事前毛利润=生产总额-预算金额
  151 + vo.setBeforeGrossProfit(BigDecimal.valueOf(vo.getProductionDepartmentTotalPrice()).subtract(vo.getProductionDepartmentPredictPrice()));
  152 + if (Objects.nonNull(vo.getProductionDepartmentTotalPrice())
  153 + && vo.getProductionDepartmentTotalPrice().compareTo(0.0) != 0) {
  154 + //事前毛利润率=事前毛利润/生产总额
  155 + vo.setBeforeGrossProfitRate(vo.getBeforeGrossProfit().divide(BigDecimal.valueOf(vo.getProductionDepartmentTotalPrice()), 4, RoundingMode.HALF_UP));
  156 + }
  157 + }
  158 + if (Objects.nonNull(vo.getProductionDepartmentTotalPrice())
  159 + && Objects.nonNull(vo.getProductionActualPrice())) {
  160 + //事后毛利润=实际发生费用-生产总额
  161 + vo.setGrossProfit(BigDecimal.valueOf(vo.getProductionDepartmentTotalPrice()).subtract(vo.getProductionActualPrice()));
  162 + if (Objects.nonNull(vo.getProductionDepartmentTotalPrice())
  163 + && vo.getProductionDepartmentTotalPrice().compareTo(0.0) != 0) {
  164 + //事后毛利润率=事后毛利润/生产总额
  165 + vo.setGrossProfitRate(vo.getGrossProfit().divide(BigDecimal.valueOf(vo.getProductionDepartmentTotalPrice()), 4, RoundingMode.HALF_UP));
  166 + }
  167 + }
  168 + return vo;
  169 + }).collect(Collectors.toList());
  170 + Page<InnerProfitDetailVO> webVOPage = new Page<>();
  171 + webVOPage.setRecords(innerProfitRatioResultVOs);
  172 + BeanUtils.copyProperties(page, webVOPage, "records");
  173 + return ServerResult.success(webVOPage);
  174 + }
  175 +
  176 +
  177 + @Override
  178 + public ServerResult<Page<BusinessProfitDetailVO>> listBusinessProfitDetailByPage(OrderBaseInfoQueryVO queryVO) {
  179 + ServerResult serverResult = orderBaseInfoService.listByPage(queryVO);
  180 + Page<OrderInfoResultVO> page = (Page<OrderInfoResultVO>) serverResult.getData();
  181 + List<OrderInfoResultVO> records = page.getRecords();
  182 + List<OrderCostFieldLockRecord> lockRecords = orderCostFieldLockRecordService
  183 + .lambdaQuery()
  184 + .func(query -> {
  185 + Set<Long> collect = records.stream().map(OrderInfoResultVO::getId).collect(Collectors.toSet());
  186 + if(CollUtil.isNotEmpty(collect)){
  187 + query.in(OrderCostFieldLockRecord::getOrderId,collect);
  188 +
  189 + }else {
  190 + query.apply("1!=1");
  191 + }
  192 + })
  193 + .list();
  194 + ObjectMapper objectMapper = new ObjectMapper();
  195 + Map<Long,OrderCostInfolockFieldVO> orderId2fieldMapMap = lockRecords.stream().collect(Collectors.toMap(OrderCostFieldLockRecord::getOrderId,record -> {
  196 + try {
  197 + return objectMapper.readValue(record.getFields(), OrderCostInfolockFieldVO.class);
  198 + } catch (JsonProcessingException e) {
  199 + throw new RuntimeException(e);
  200 + }
  201 + }));
  202 + List<BusinessProfitDetailVO> innerProfitRatioResultVOs = records.stream().map(record -> {
  203 + BusinessProfitDetailVO vo = BusinessProfitDetailVO.builder()
  204 + .customerCode(record.getCustomerCode())
  205 + .projectNo(record.getProjectNo())
  206 + .productionDepartment(record.getProductionDepartment())
  207 + .innerNo(record.getInnerNo())
  208 + .picUrl(record.getPicUrl())
  209 + .orderCount(record.getOrderCount())
  210 + .packetPrice(Objects.isNull(record.getProfitAnalysisInfo()) ? null : record.getProfitAnalysisInfo().getPacketPrice())
  211 + .packetTotalPrice(Objects.isNull(record.getProfitAnalysisInfo()) ? null : record.getProfitAnalysisInfo().getPacketTotalPrice())
  212 + .packetActualRmbTotalPrice(Objects.isNull(record.getOrderCostInfo()) ? null : record.getOrderCostInfo().getPacketActualRmbTotalPrice())
  213 + .lockFields(orderId2fieldMapMap.get(record.getId()))
  214 + .build();
  215 + if (Objects.nonNull(vo.getPacketTotalPrice())) {
  216 + //包装费用合计 = 包装费合计*汇率
  217 + vo.setPacketRmbTotalPrice(BigDecimal.valueOf(vo.getPacketTotalPrice()).multiply((new BigDecimal("6.2")).setScale(4, RoundingMode.HALF_UP)).doubleValue());
  218 + }
  219 + if (Objects.nonNull(vo.getPacketActualRmbTotalPrice()) && Objects.nonNull(vo.getOrderCount())) {
  220 + //实际跟单单价 = 包装费用实际金额/数量
  221 + vo.setPacketActualRmbPrice(vo.getPacketActualRmbTotalPrice().divide(BigDecimal.valueOf(vo.getOrderCount()), 4, RoundingMode.HALF_UP));
  222 + //实际跟单单价折算美金$ = 人民币单价/汇率
  223 + vo.setPacketActualPrice(vo.getPacketActualRmbPrice().divide(new BigDecimal("6.2"), 4, RoundingMode.HALF_UP));
  224 + }
  225 + if (Objects.nonNull(vo.getPacketRmbTotalPrice()) && Objects.nonNull(vo.getPacketActualRmbPrice())) {
  226 + //包装费用收益¥ = 包装费用合计-包装费用实际金额
  227 + vo.setPacketProfitRmbPrice(BigDecimal.valueOf(vo.getPacketRmbTotalPrice()).subtract(vo.getPacketActualRmbTotalPrice()));
  228 + }
  229 + if (Objects.nonNull(vo.getPacketProfitRmbPrice()) && Objects.nonNull(vo.getPacketRmbTotalPrice())) {
  230 + //包装费用净利润率 = 包装费用收益/包装费用合计
  231 + vo.setPacketProfitRate(vo.getPacketProfitRmbPrice().divide(BigDecimal.valueOf(vo.getPacketRmbTotalPrice()), 4, RoundingMode.HALF_UP));
  232 + }
  233 + return vo;
  234 + }).collect(Collectors.toList());
  235 + Page<BusinessProfitDetailVO> webVOPage = new Page<>();
  236 + webVOPage.setRecords(innerProfitRatioResultVOs);
  237 + BeanUtils.copyProperties(page, webVOPage, "records");
  238 + return ServerResult.success(webVOPage);
  239 + }
  240 +
  241 +}
... ...
src/main/java/com/order/erp/service/order/impl/OrderFieldLockApplyServiceImpl.java
... ... @@ -20,11 +20,14 @@ import com.order.erp.config.DataScope;
20 20 import com.order.erp.domain.*;
21 21 import com.order.erp.domain.dto.BaseDO;
22 22 import com.order.erp.domain.dto.order.*;
  23 +import com.order.erp.domain.model.OrderCostFieldLockRecord;
23 24 import com.order.erp.domain.vo.order.*;
24 25 import com.order.erp.mapper.order.OrderFieldLockApplyMapper;
  26 +import com.order.erp.service.IOrderCostFieldLockRecordService;
25 27 import com.order.erp.service.order.*;
26 28 import lombok.extern.slf4j.Slf4j;
27 29 import org.springframework.beans.BeanUtils;
  30 +import org.springframework.beans.factory.annotation.Autowired;
28 31 import org.springframework.stereotype.Service;
29 32 import org.springframework.transaction.annotation.Transactional;
30 33  
... ... @@ -49,6 +52,9 @@ public class OrderFieldLockApplyServiceImpl extends ServiceImpl&lt;OrderFieldLockAp
49 52 @Resource
50 53 private OrderFieldLockRecordService fieldLockRecordService;
51 54  
  55 + @Autowired
  56 + private IOrderCostFieldLockRecordService orderCostFieldLockRecordService;
  57 +
52 58 @Resource
53 59 private OrderFieldLockApplyService applyService;
54 60  
... ... @@ -126,6 +132,10 @@ public class OrderFieldLockApplyServiceImpl extends ServiceImpl&lt;OrderFieldLockAp
126 132 if (ApplyTypeEnum.FIELD_EDIT_APPLY.getType() .equals(x.getType())) {
127 133 resultVO.setFieldInfos(JSONObject.parseObject(fields, OrderLockFieldVO.class));
128 134 }
  135 + if(ApplyTypeEnum.ORDER_COST_FIELD_EDIT_APPLY.getType().equals(x.getType())){
  136 + OrderCostInfolockFieldVO orderCostInfolockFieldVO = JSONObject.parseObject(fields, OrderCostInfolockFieldVO.class);
  137 + resultVO.setFieldInfos(OrderLockFieldVO.builder().costInfolockFieldVO(orderCostInfolockFieldVO).build());
  138 + }
129 139 if (ApplyTypeEnum.ORDER_REPORT_APPLY.getType().equals(x.getType())) {
130 140 OrderLockFieldVO fieldVO = new OrderLockFieldVO();
131 141 fieldVO.setReportFields(JSONObject.parseObject(fields, OrderCompletionReportFieldVO.class));
... ... @@ -174,7 +184,7 @@ public class OrderFieldLockApplyServiceImpl extends ServiceImpl&lt;OrderFieldLockAp
174 184 }
175 185 }
176 186 return resultVO;
177   - }).filter(result->result!=null).collect(Collectors.toList());
  187 + }).filter(Objects::nonNull).collect(Collectors.toList());
178 188 if (resultVOList != null && resultVOList.stream().noneMatch(x -> ApplyTypeEnum.INVOICE_BILL_APPLY.getType().equals(x.getType())
179 189 || ApplyTypeEnum.DEPARTMENT_INVOICE_APPLY.getType().equals(x.getType())
180 190 || ApplyTypeEnum.CHECK_BILL_APPLY.getType().equals(x.getType()))) {
... ... @@ -358,7 +368,7 @@ public class OrderFieldLockApplyServiceImpl extends ServiceImpl&lt;OrderFieldLockAp
358 368 }
359 369 Set<Long> orderIds = new HashSet<>();
360 370 //由于下面是原始的代码,怕改出错了,所以我只对我需要的需求进行判断,我只针对我需要的这种情况,其他情况下就不走这种情况。 限制情况为跟单业务,对应收款,应付款,发票审核请求时。
361   - if(queryVO.getType()==Constant.THIRTY || queryVO.getType()==4050){
  371 + if(Constant.THIRTY.equals(queryVO.getType()) ||Integer.valueOf(4050).equals(queryVO.getType())){
362 372  
363 373 }else{
364 374 /** 这部分代码是之前的,每台看懂,就先不修改了,保留*/
... ... @@ -461,7 +471,14 @@ public class OrderFieldLockApplyServiceImpl extends ServiceImpl&lt;OrderFieldLockAp
461 471  
462 472 }
463 473 }
464   - return queryWrapper;
  474 + return queryWrapper
  475 + .func(Objects.nonNull(queryVO.getTypeIn()),query-> {
  476 + if(CollUtil.isNotEmpty(queryVO.getTypeIn())){
  477 + query.in(OrderFieldLockApplyDO::getType, queryVO.getTypeIn());
  478 + }else {
  479 + query.apply("1!=1");
  480 + }
  481 + });
465 482 }
466 483  
467 484 /**
... ... @@ -802,6 +819,28 @@ public class OrderFieldLockApplyServiceImpl extends ServiceImpl&lt;OrderFieldLockAp
802 819 }
803 820 }
804 821 checkBillOrderService.updateById(invoiceInfoDO);
  822 + } else if (ApplyTypeEnum.ORDER_COST_FIELD_EDIT_APPLY.getType().equals(applyDO.getType())){
  823 + applyDO.setAuditUserId(auditUserId);
  824 + applyDO.setStatus(ApplyStatusEnum.AUDIT_PASS.getStatus());
  825 +
  826 + OrderCostFieldLockRecord recordDO = orderCostFieldLockRecordService.getOne(new LambdaQueryWrapper<OrderCostFieldLockRecord>()
  827 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  828 + .eq(OrderCostFieldLockRecord::getOrderId, applyDO.getOrderId())
  829 + .eq(OrderCostFieldLockRecord::getUserId, applyDO.getApplyUserId())
  830 + .orderByDesc(OrderCostFieldLockRecord::getId)
  831 + .last("limit 1"));
  832 + if (Objects.isNull(recordDO)) {
  833 + recordDO = OrderCostFieldLockRecord.builder()
  834 + .orderId(applyDO.getOrderId())
  835 + .userId(applyDO.getApplyUserId())
  836 + .build();
  837 + }
  838 + recordDO.setFields(applyDO.getFields());
  839 + if (Objects.isNull(recordDO.getId())) {
  840 + orderCostFieldLockRecordService.save(recordDO);
  841 + } else {
  842 + orderCostFieldLockRecordService.updateById(recordDO);
  843 + }
805 844 }
806 845  
807 846 OrderAuditLogDO auditLogDO = OrderAuditLogDO.builder().applyId(applyDO.getId()).orderId(applyDO.getOrderId()).optType(ApplyStatusEnum.AUDIT_PASS.getDesc()).build();
... ...
src/main/java/com/order/erp/service/order/impl/OrderProfitAnalysisServiceImpl.java
... ... @@ -3,34 +3,55 @@ package com.order.erp.service.order.impl;
3 3 import cn.hutool.core.bean.BeanUtil;
4 4 import cn.hutool.core.collection.CollUtil;
5 5 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  6 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
6 7 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
7 8 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
  9 +import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
8 10 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  11 +import com.fasterxml.jackson.core.JsonProcessingException;
  12 +import com.fasterxml.jackson.databind.ObjectMapper;
9 13 import com.order.erp.common.constant.Constant;
10 14 import com.order.erp.common.constant.ServerResult;
11 15 import com.order.erp.common.exception.BusinessException;
12 16 import com.order.erp.common.utils.ProfitUtils;
13 17 import com.order.erp.common.utils.StringUtils;
14 18 import com.order.erp.domain.dto.BaseDO;
  19 +import com.order.erp.domain.dto.SystemSettingDO;
15 20 import com.order.erp.domain.dto.order.OrderBaseInfoDO;
16 21 import com.order.erp.domain.dto.order.OrderProfitAnalysisDO;
  22 +import com.order.erp.domain.dto.order.ProjectBaseInfoDO;
  23 +import com.order.erp.domain.model.OrderCostFieldLockRecord;
  24 +import com.order.erp.domain.model.ProjectFieldLockRecord;
17 25 import com.order.erp.domain.vo.OrderProfitAnalysisVo;
18   -import com.order.erp.domain.vo.order.OrderProfitAnalysisQueryVO;
19   -import com.order.erp.domain.vo.order.OrderProfitAnalysisVO;
20   -import com.order.erp.domain.vo.order.ProfitCalculateVO;
  26 +import com.order.erp.domain.vo.order.*;
21 27 import com.order.erp.mapper.order.OrderProfitAnalysisMapper;
  28 +import com.order.erp.service.IProjectFieldLockRecordService;
  29 +import com.order.erp.service.SystemSettingService;
  30 +import com.order.erp.service.impl.OrderCostFieldLockRecordServiceImpl;
  31 +import com.order.erp.service.order.IProjectBaseInfoService;
22 32 import com.order.erp.service.order.OrderBaseInfoService;
  33 +import com.order.erp.service.order.OrderFieldLockRecordService;
23 34 import com.order.erp.service.order.OrderProfitAnalysisService;
24 35 import lombok.extern.slf4j.Slf4j;
  36 +import org.apache.poi.ss.usermodel.*;
  37 +import org.apache.poi.ss.util.CellRangeAddress;
  38 +import org.apache.poi.xssf.usermodel.XSSFFont;
  39 +import org.apache.poi.xssf.usermodel.XSSFWorkbook;
25 40 import org.springframework.beans.BeanUtils;
  41 +import org.springframework.beans.factory.annotation.Autowired;
26 42 import org.springframework.stereotype.Service;
27 43  
28 44 import javax.annotation.Resource;
  45 +import javax.servlet.http.HttpServletResponse;
  46 +import java.io.OutputStream;
29 47 import java.math.BigDecimal;
30   -import java.util.HashSet;
31   -import java.util.List;
32   -import java.util.Objects;
33   -import java.util.Set;
  48 +import java.math.RoundingMode;
  49 +import java.time.Duration;
  50 +import java.time.LocalDateTime;
  51 +import java.time.format.DateTimeFormatter;
  52 +import java.time.temporal.ChronoUnit;
  53 +import java.util.*;
  54 +import java.util.function.Function;
34 55 import java.util.stream.Collectors;
35 56  
36 57 /**
... ... @@ -45,6 +66,16 @@ public class OrderProfitAnalysisServiceImpl extends ServiceImpl&lt;OrderProfitAnaly
45 66  
46 67 @Resource
47 68 private OrderBaseInfoService orderBaseInfoService;
  69 + @Autowired
  70 + private SystemSettingService systemSettingService;
  71 + @Autowired
  72 + private IProjectBaseInfoService projectProfitAnalysisService;
  73 + @Autowired
  74 + private IProjectFieldLockRecordService projectionFieldLockRecordService;
  75 + @Resource
  76 + private OrderFieldLockRecordService orderFieldLockRecordService;
  77 + @Autowired
  78 + OrderCostFieldLockRecordServiceImpl orderCostFieldLockRecordService;
48 79  
49 80 /**
50 81 * 通过ID查询单条数据
... ... @@ -108,6 +139,7 @@ public class OrderProfitAnalysisServiceImpl extends ServiceImpl&lt;OrderProfitAnaly
108 139 if (Objects.isNull(orderProfitAnalysisVO.getId())) {
109 140 return ServerResult.fail("id 不能为空");
110 141 }
  142 + orderProfitAnalysisVO.getId();
111 143 OrderProfitAnalysisDO orderProfitAnalysisDo = BeanUtil.copyProperties(orderProfitAnalysisVO, OrderProfitAnalysisDO.class);
112 144  
113 145 updateById(orderProfitAnalysisDo);
... ...
src/main/java/com/order/erp/service/order/impl/ProjectBaseInfoServiceImpl.java 0 → 100644
  1 +package com.order.erp.service.order.impl;
  2 +
  3 +import cn.hutool.core.bean.BeanUtil;
  4 +import cn.hutool.core.collection.CollUtil;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  7 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  8 +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
  9 +import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  10 +import com.fasterxml.jackson.core.JsonProcessingException;
  11 +import com.fasterxml.jackson.databind.ObjectMapper;
  12 +import com.order.erp.common.constant.Constant;
  13 +import com.order.erp.common.constant.ServerResult;
  14 +import com.order.erp.common.constant.ServerResultCode;
  15 +import com.order.erp.common.exception.BusinessException;
  16 +import com.order.erp.config.DataScope;
  17 +import com.order.erp.domain.ApplyStatusEnum;
  18 +import com.order.erp.domain.ProjectApplyTypeEnum;
  19 +import com.order.erp.domain.dto.BaseDO;
  20 +import com.order.erp.domain.dto.SystemSettingDO;
  21 +import com.order.erp.domain.dto.order.OrderBaseInfoDO;
  22 +import com.order.erp.domain.dto.order.OrderCostInfoDO;
  23 +import com.order.erp.domain.dto.order.ProjectBaseInfoDO;
  24 +import com.order.erp.domain.model.ProjectApplyDO;
  25 +import com.order.erp.domain.model.ProjectFieldLockRecord;
  26 +import com.order.erp.domain.vo.order.*;
  27 +import com.order.erp.mapper.order.ProjectBaseInfoMapper;
  28 +import com.order.erp.service.IProjectFieldLockRecordService;
  29 +import com.order.erp.service.SystemSettingService;
  30 +import com.order.erp.service.impl.ProjectApplyServiceImpl;
  31 +import com.order.erp.service.order.IProjectBaseInfoService;
  32 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  33 +import com.order.erp.service.order.OrderBaseInfoService;
  34 +import com.order.erp.service.order.OrderProfitAnalysisService;
  35 +import org.apache.poi.ss.usermodel.*;
  36 +import org.apache.poi.ss.util.CellRangeAddress;
  37 +import org.apache.poi.xssf.usermodel.XSSFFont;
  38 +import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  39 +import org.springframework.beans.BeanUtils;
  40 +import org.springframework.beans.factory.annotation.Autowired;
  41 +import org.springframework.stereotype.Service;
  42 +
  43 +import javax.servlet.http.HttpServletResponse;
  44 +import java.io.OutputStream;
  45 +import java.math.BigDecimal;
  46 +import java.math.RoundingMode;
  47 +import java.time.Duration;
  48 +import java.time.LocalDateTime;
  49 +import java.time.format.DateTimeFormatter;
  50 +import java.time.temporal.ChronoUnit;
  51 +import java.util.*;
  52 +import java.util.function.Function;
  53 +import java.util.stream.Collectors;
  54 +
  55 +/**
  56 + * <p>
  57 + * 服务实现类
  58 + * </p>
  59 + *
  60 + * @author author
  61 + * @since 2024-12-18
  62 + */
  63 +@Service
  64 +public class ProjectBaseInfoServiceImpl extends ServiceImpl<ProjectBaseInfoMapper, ProjectBaseInfoDO> implements IProjectBaseInfoService {
  65 + @Autowired
  66 + private ProjectApplyServiceImpl projectFieldLockApplyService;
  67 + @Autowired
  68 + private DataScope dataScope;
  69 + @Autowired
  70 + private IProjectFieldLockRecordService projectionFieldLockRecordService;
  71 + @Autowired
  72 + private OrderBaseInfoService orderBaseInfoService;
  73 + @Autowired
  74 + private OrderProfitAnalysisService projectProfitAnalysisService;
  75 + @Autowired
  76 + private SystemSettingService systemSettingService;
  77 +
  78 + @Override
  79 + public ServerResult edit(ProjectBaseInfoVO vo) {
  80 + String projectNoPrefix = vo.getProjectNoPrefix();
  81 + Optional<ProjectBaseInfoDO> projectBaseInfoDOOpt = this.lambdaQuery()
  82 + .eq(ProjectBaseInfoDO::getProjectNoPrefix, projectNoPrefix)
  83 + .last(" limit 1 ")
  84 + .oneOpt();
  85 + ProjectBaseInfoDO projectBaseInfoDO = null;
  86 + if (projectBaseInfoDOOpt.isPresent()) {
  87 + projectBaseInfoDO = projectBaseInfoDOOpt.get();
  88 + BeanUtil.copyProperties(vo, projectBaseInfoDO,"id");
  89 + }else {
  90 + projectBaseInfoDO = BeanUtil.copyProperties(vo, ProjectBaseInfoDO.class);
  91 + }
  92 + return ServerResult.success(this.saveOrUpdate(projectBaseInfoDO));
  93 + }
  94 + @Override
  95 + public ServerResult applyEditFileds(ProjectBaseInfoLockFieldVO vo) {
  96 + List<ProjectApplyDO> applyDOS = projectFieldLockApplyService.list(new LambdaQueryWrapper<ProjectApplyDO>()
  97 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  98 + .eq(ProjectApplyDO::getProjectNoPrefix, vo.getProjectNoPrefix())
  99 + .eq(ProjectApplyDO::getApplyUserId, dataScope.getLoginUserId())
  100 + .eq(ProjectApplyDO::getStatus, ApplyStatusEnum.WAIT_AUDIT.getStatus()));
  101 + if (CollectionUtils.isNotEmpty(applyDOS)) {
  102 + throw new BusinessException(ServerResultCode.APPLY_UNLOCK_FIELD_EXIST);
  103 + }
  104 + String projectNoPrefix = vo.getProjectNoPrefix();
  105 + vo.setProjectNoPrefix(null);
  106 + ProjectApplyDO build = ProjectApplyDO.builder()
  107 + .projectNoPrefix(projectNoPrefix)
  108 + .applyUserId(dataScope.getLoginUserId())
  109 + .fields(JSONObject.toJSONString(vo))
  110 + .type(ProjectApplyTypeEnum.FIELD_EDIT_APPLY)
  111 + .status(ApplyStatusEnum.WAIT_AUDIT.getStatus())
  112 + .build();
  113 + projectFieldLockApplyService.save(build);
  114 + return ServerResult.success();
  115 + }
  116 +
  117 +
  118 +
  119 +
  120 + @Override
  121 + public ServerResult pageProjectLockFieldApply(QueryProjectLockFieldVO vo) {
  122 + Page<ProjectApplyDO> page = projectFieldLockApplyService.lambdaQuery()
  123 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  124 + .eq(ProjectApplyDO::getType, ProjectApplyTypeEnum.FIELD_EDIT_APPLY.getType())
  125 + .eq(ProjectApplyDO::getStatus, ApplyStatusEnum.WAIT_AUDIT.getStatus())
  126 + .orderByDesc(ProjectApplyDO::getCreateTime)
  127 + .page(new Page<>(vo.getPage(), vo.getPageSize()));
  128 + List<ProjectApplyDO> records = page.getRecords();
  129 + if(CollectionUtils.isEmpty(records)){
  130 + return buildPageResult(page, Collections.emptyList());
  131 + }
  132 + List<ProjectApplyVO> collect = records.stream().map(e -> {
  133 + ProjectApplyVO projectApplyVO = BeanUtil.copyProperties(e, ProjectApplyVO.class);
  134 + return projectApplyVO;
  135 + }).collect(Collectors.toList());
  136 + return ServerResult.success(buildPageResult(page, collect));
  137 + }
  138 +
  139 + @Override
  140 + public ServerResult audit(AuditVO vo) {
  141 + ProjectApplyDO applyDO = projectFieldLockApplyService.getById(vo.getId());
  142 + applyDO.setAuditUserId(dataScope.getLoginUserId());
  143 +
  144 + if(ApplyStatusEnum.AUDIT_PASS.getStatus().equals(vo.getStatus())){
  145 + applyDO.setStatus(ApplyStatusEnum.AUDIT_PASS.getStatus());
  146 + ProjectFieldLockRecord recordDO = projectionFieldLockRecordService.getOne(new LambdaQueryWrapper<ProjectFieldLockRecord>()
  147 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  148 + .eq(ProjectFieldLockRecord::getProjectNoPrefix, applyDO.getProjectNoPrefix())
  149 + .eq(ProjectFieldLockRecord::getUserId, applyDO.getApplyUserId())
  150 + .orderByDesc(ProjectFieldLockRecord::getId)
  151 + .last("limit 1"));
  152 + if (Objects.isNull(recordDO)) {
  153 + recordDO = ProjectFieldLockRecord.builder()
  154 + .projectNoPrefix(applyDO.getProjectNoPrefix())
  155 + .userId(applyDO.getApplyUserId())
  156 + .build();
  157 + }
  158 + recordDO.setFields(applyDO.getFields());
  159 + if (Objects.isNull(recordDO.getId())) {
  160 + projectionFieldLockRecordService.save(recordDO);
  161 + } else {
  162 + projectionFieldLockRecordService.updateById(recordDO);
  163 + }
  164 + }
  165 + projectFieldLockApplyService.updateById(applyDO);
  166 + return ServerResult.success();
  167 + }
  168 +
  169 +
  170 + @Override
  171 + public ServerResult<Page<InnerProfitInfoVO>> listInnerProfitInfoByPage(OrderBaseInfoQueryVO queryVO) {
  172 + Page<OrderBaseInfoDO> page = pageProjectNoPrefix(queryVO);
  173 + List<OrderInfoResultVO> orderInfoResultVOS = getOrderInfoResultVOS(page, queryVO);
  174 + List<InnerProfitInfoVO> innerProfitInfoVOs = buildInnerProfitInfos(orderInfoResultVOS);
  175 + return buildPageResult(page, innerProfitInfoVOs);
  176 + }
  177 +
  178 + @Override
  179 + public ServerResult<Page<BusinessProfitInfoVO>> listBusinessProfitInfoByPage(OrderBaseInfoQueryVO queryVO) {
  180 + Page<OrderBaseInfoDO> page = pageProjectNoPrefix(queryVO);
  181 + List<OrderInfoResultVO> orderInfoResultVOS = getOrderInfoResultVOS(page, queryVO);
  182 + List<BusinessProfitInfoVO> businessProfitInfoVOs = buildBusinessProfitInfos(orderInfoResultVOS);
  183 + return buildPageResult(page, businessProfitInfoVOs);
  184 + }
  185 +
  186 + /**
  187 + * 分页查询项目号前8位
  188 + */
  189 + private Page<OrderBaseInfoDO> pageProjectNoPrefix(OrderBaseInfoQueryVO queryVO) {
  190 + LambdaQueryWrapper<OrderBaseInfoDO> orderBaseInfoDOLambdaQueryWrapper = orderBaseInfoService.buildQueryByParam(queryVO).select(OrderBaseInfoDO::getId);
  191 + return orderBaseInfoService.page(new Page<>(queryVO.getPage(), queryVO.getPageSize()),
  192 + new QueryWrapper<OrderBaseInfoDO>()
  193 + .select("LEFT(project_no, 8) as project_no")
  194 + .func(!orderBaseInfoDOLambdaQueryWrapper.isEmptyOfWhere(), queryWrapper -> {
  195 + List<OrderBaseInfoDO> list = orderBaseInfoService.list(orderBaseInfoDOLambdaQueryWrapper);
  196 + List<Long> ids = list.stream().map(OrderBaseInfoDO::getId).collect(Collectors.toList());
  197 + if (CollUtil.isNotEmpty(ids)) {
  198 + queryWrapper.in("id", ids);
  199 + } else {
  200 + queryWrapper.ne("1", 1);
  201 + }
  202 + })
  203 + .groupBy("LEFT(project_no, 8)"));
  204 + }
  205 +
  206 + /**
  207 + * 查询订单列表
  208 + */
  209 + private List<OrderInfoResultVO> getOrderInfoResultVOS(Page<OrderBaseInfoDO> page, OrderBaseInfoQueryVO queryVO) {
  210 + List<String> projectNoPrefix = page.getRecords().stream()
  211 + .map(OrderBaseInfoDO::getProjectNo)
  212 + .map(x -> x.substring(0, 8))
  213 + .collect(Collectors.toList());
  214 +
  215 + List<OrderBaseInfoDO> orderBaseInfoDOS = orderBaseInfoService.list(orderBaseInfoService.buildQueryByParam(queryVO)
  216 + .and(CollUtil.isNotEmpty(projectNoPrefix),query -> {
  217 + for (int i = 0; i < projectNoPrefix.size(); i++) {
  218 + query.likeRight(OrderBaseInfoDO::getProjectNo, projectNoPrefix.get(i));
  219 + if (i != projectNoPrefix.size() - 1) {
  220 + query.or();
  221 + }
  222 + }
  223 + }))
  224 + ;
  225 +
  226 + return orderBaseInfoService.wrapperOrderResultList(true, orderBaseInfoDOS);
  227 + }
  228 +
  229 + /**
  230 + * 构建分页
  231 + */
  232 + private <T> ServerResult buildPageResult(Page<?> page, List<T> records) {
  233 + Page<T> webVOPage = new Page<>();
  234 + webVOPage.setRecords(records);
  235 + BeanUtils.copyProperties(page, webVOPage, "records");
  236 + return ServerResult.success(webVOPage);
  237 + }
  238 +
  239 + private List<InnerProfitInfoVO> buildInnerProfitInfos(List<OrderInfoResultVO> orderInfoResultVOS) {
  240 + Map<String, List<OrderInfoResultVO>> orderBaseInfoDOSGroupByProjectNoPre = orderInfoResultVOS.stream()
  241 + .collect(Collectors.groupingBy(
  242 + order -> order.getProjectNo().substring(0, 8)
  243 + ));
  244 + Set<String> collect = orderInfoResultVOS.stream()
  245 + .map(OrderBaseInfoVO::getCustomerCode)
  246 + .collect(Collectors.toSet());
  247 + List<SystemSettingDO> systemSettingDOS = systemSettingService.lambdaQuery()
  248 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  249 + .eq(SystemSettingDO::getRelationCode, "ProduceSettingItem")
  250 + .in(SystemSettingDO::getSettingValue, collect)
  251 + .list();
  252 + Map<String, SystemSettingDO> systemSettingDOSMap = systemSettingDOS.stream()
  253 + .collect(Collectors.toMap(SystemSettingDO::getSettingValue, Function.identity(), (x, y) -> x));
  254 + List<InnerProfitInfoVO> innerProfitInfoVOs = orderBaseInfoDOSGroupByProjectNoPre.entrySet().stream().map(entry -> {
  255 + List<OrderInfoResultVO> details = entry.getValue();
  256 + InnerProfitInfoVO innerProfitInfoVO = InnerProfitInfoVO.builder()
  257 + .customerCode(details.get(0).getCustomerCode())
  258 + .projectNoPrefix(entry.getKey())
  259 + .productionDepartment(details.get(0).getProductionDepartment())
  260 + .build();
  261 +
  262 + //数量
  263 + details.stream()
  264 + .filter(vo -> Objects.nonNull(vo.getOrderCount()))
  265 + .mapToInt(OrderInfoResultVO::getOrderCount)
  266 + .reduce(Integer::sum)
  267 + .ifPresent(innerProfitInfoVO::setOrderCount);
  268 +
  269 + //生产科总价
  270 + details.stream()
  271 + .map(OrderInfoResultVO::getProfitAnalysisInfo)
  272 + .filter(Objects::nonNull)
  273 + .map(OrderProfitAnalysisVO::getProductionDepartmentTotalPrice)
  274 + .filter(Objects::nonNull)
  275 + .map(BigDecimal::valueOf)
  276 + .reduce(BigDecimal::add)
  277 + .ifPresent(price -> {
  278 + innerProfitInfoVO.setProductionDepartmentTotalPrice(price.doubleValue());
  279 + });
  280 +
  281 + //生产科预算金额
  282 + details.stream()
  283 + .map(OrderInfoResultVO::getOrderCostInfo)
  284 + .filter(Objects::nonNull)
  285 + .map(OrderCostInfoVO::getProductionDepartmentPredictPrice)
  286 + .filter(Objects::nonNull)
  287 + .reduce(BigDecimal::add)
  288 + .ifPresent(innerProfitInfoVO::setProductionDepartmentPredictPrice);
  289 + //实际发生费用
  290 + details.stream()
  291 + .map(OrderInfoResultVO::getOrderCostInfo)
  292 + .filter(Objects::nonNull)
  293 + .map(OrderCostInfoVO::getProductionActualPrice)
  294 + .filter(Objects::nonNull)
  295 + .reduce(BigDecimal::add)
  296 + .ifPresent(innerProfitInfoVO::setProductionActualPrice);
  297 +
  298 + if (Objects.nonNull(innerProfitInfoVO.getProductionDepartmentPredictPrice())
  299 + && Objects.nonNull(innerProfitInfoVO.getProductionActualPrice())) {
  300 + //预算占比=实际发生费用/预算金额
  301 + innerProfitInfoVO.setPredictRatio(innerProfitInfoVO.getProductionActualPrice().divide(innerProfitInfoVO.getProductionDepartmentPredictPrice(), 4, RoundingMode.HALF_UP));
  302 + if (innerProfitInfoVO.getProductionDepartmentPredictPrice().compareTo(BigDecimal.ZERO) != 0) {
  303 + //预算占比与实际比占比差:1-预算占比
  304 + innerProfitInfoVO.setPredictAndActualRatio(new BigDecimal(1).subtract(innerProfitInfoVO.getPredictRatio()));
  305 + }
  306 + }
  307 +
  308 + //事前毛利润 = 生产总额-预算金额
  309 + if (Objects.nonNull(innerProfitInfoVO.getProductionDepartmentTotalPrice())
  310 + && Objects.nonNull(innerProfitInfoVO.getProductionDepartmentPredictPrice())) {
  311 + innerProfitInfoVO.setBeforeGrossProfit(BigDecimal.valueOf(innerProfitInfoVO.getProductionDepartmentTotalPrice()).subtract(innerProfitInfoVO.getProductionDepartmentPredictPrice()));
  312 + //事前毛利润率 = 事前毛利/生产科总价
  313 + if (innerProfitInfoVO.getProductionDepartmentTotalPrice().compareTo(0.0) != 0) {
  314 + innerProfitInfoVO.setBeforeGrossProfitRate(innerProfitInfoVO.getBeforeGrossProfit().divide(BigDecimal.valueOf(innerProfitInfoVO.getProductionDepartmentTotalPrice()), 4, RoundingMode.HALF_UP));
  315 + }
  316 + }
  317 + //事后毛利率 = 总价-实际发生费用
  318 + if (Objects.nonNull(innerProfitInfoVO.getProductionDepartmentTotalPrice())
  319 + && Objects.nonNull(innerProfitInfoVO.getProductionActualPrice())) {
  320 + innerProfitInfoVO.setGrossProfit(BigDecimal.valueOf(innerProfitInfoVO.getProductionDepartmentTotalPrice()).subtract(innerProfitInfoVO.getProductionActualPrice()));
  321 + if (innerProfitInfoVO.getProductionDepartmentTotalPrice().compareTo(0.0) != 0) {
  322 + innerProfitInfoVO.setGrossProfitRate(innerProfitInfoVO.getGrossProfit().divide(BigDecimal.valueOf(innerProfitInfoVO.getProductionDepartmentTotalPrice()), 4, RoundingMode.HALF_UP));
  323 + }
  324 + }
  325 +
  326 + //hod时间差
  327 + LocalDateTime earliest = details.stream()
  328 + .map(OrderInfoResultVO::getOrderHodTime)
  329 + .map(hodTime -> LocalDateTime.parse(hodTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
  330 + .min(Comparator.naturalOrder())
  331 + .orElse(null);
  332 + LocalDateTime latest = details.stream()
  333 + .map(OrderInfoResultVO::getOrderHodTime)
  334 + .map(hodTime -> LocalDateTime.parse(hodTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
  335 + .max(Comparator.naturalOrder())
  336 + .orElse(null);
  337 + innerProfitInfoVO.setProduceStartTime(earliest);
  338 + innerProfitInfoVO.setProduceEndTime(latest);
  339 + SystemSettingDO systemSettingDO = systemSettingDOSMap.get(innerProfitInfoVO.getCustomerCode());
  340 + if (Objects.nonNull(systemSettingDO)) {
  341 + String relationValue = systemSettingDO.getRelationValue();
  342 + ObjectMapper objectMapper = new ObjectMapper();
  343 + try {
  344 + // 将 JSON 字符串解析为 List<Map<String, String>>
  345 + List<Map<String, String>> relations = objectMapper.readValue(relationValue, objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class));
  346 + // 提取 fixCost 和 ratio 的 relationValue
  347 + String fixCostValue = null;
  348 + String ratioValue = null;
  349 +
  350 + for (Map<String, String> relation : relations) {
  351 + if ("fixCost".equals(relation.get("relationCode"))) {
  352 + fixCostValue = relation.get("relationValue");
  353 + } else if ("ratio".equals(relation.get("relationCode"))) {
  354 + ratioValue = relation.get("relationValue");
  355 + }
  356 + }
  357 + if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(fixCostValue)
  358 + && Objects.nonNull(earliest)
  359 + && Objects.nonNull(latest)) {
  360 + Duration duration = Duration.between(earliest, latest);
  361 + //内部生产固定成本¥
  362 + innerProfitInfoVO.setInnerProductionFixedCost(BigDecimal.valueOf(duration.toDays() * Double.parseDouble(fixCostValue)));
  363 + }
  364 + if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(ratioValue)
  365 + && Objects.nonNull(innerProfitInfoVO.getPredictRatio())
  366 + && innerProfitInfoVO.getPredictRatio().compareTo(BigDecimal.valueOf(1.05)) < 0) {
  367 + //内部生产提成¥
  368 + innerProfitInfoVO.setInnerProductionCommission(BigDecimal.valueOf(details.size()).multiply(BigDecimal.valueOf(Double.parseDouble(ratioValue))));
  369 + }
  370 + //内部生产净利润 = 总价-实际费用-固定成本-提成
  371 + if (Objects.nonNull(innerProfitInfoVO.getProductionDepartmentTotalPrice())
  372 + && Objects.nonNull(innerProfitInfoVO.getProductionActualPrice())
  373 + && Objects.nonNull(innerProfitInfoVO.getInnerProductionFixedCost())
  374 + && Objects.nonNull(innerProfitInfoVO.getInnerProductionCommission())) {
  375 + innerProfitInfoVO.setInnerProductionProfit(BigDecimal.valueOf(innerProfitInfoVO.getProductionDepartmentTotalPrice())
  376 + .subtract(innerProfitInfoVO.getProductionActualPrice())
  377 + .subtract(innerProfitInfoVO.getInnerProductionFixedCost())
  378 + .subtract(innerProfitInfoVO.getInnerProductionCommission()));
  379 + }
  380 + //内部生产净利润率 = 净利润/总价
  381 + if (Objects.nonNull(innerProfitInfoVO.getProductionDepartmentTotalPrice())
  382 + && Objects.nonNull(innerProfitInfoVO.getInnerProductionProfit())) {
  383 + innerProfitInfoVO.setInnerProductionProfitRate(innerProfitInfoVO.getInnerProductionProfit().divide(BigDecimal.valueOf(innerProfitInfoVO.getProductionDepartmentTotalPrice()), 4, RoundingMode.HALF_UP));
  384 + }
  385 + } catch (JsonProcessingException e) {
  386 + throw new RuntimeException(e);
  387 + }
  388 + }
  389 + return innerProfitInfoVO;
  390 + }).collect(Collectors.toList());
  391 + return innerProfitInfoVOs;
  392 + }
  393 +
  394 + private List<BusinessProfitInfoVO> buildBusinessProfitInfos(List<OrderInfoResultVO> orderInfoResultVOS) {
  395 + List<String> projectNoPrefix = orderInfoResultVOS.stream()
  396 + .map(OrderInfoResultVO::getProjectNo)
  397 + .map(projectNo -> projectNo.substring(0, 8))
  398 + .distinct()
  399 + .collect(Collectors.toList());
  400 + Map<String, List<OrderInfoResultVO>> orderBaseInfoDOSGroupByProjectNoPre = orderInfoResultVOS.stream()
  401 + .collect(Collectors.groupingBy(
  402 + order -> order.getProjectNo().substring(0, 8)
  403 + ));
  404 + List<ProjectBaseInfoDO> list = this.lambdaQuery()
  405 + .func(query -> {
  406 + if (CollUtil.isNotEmpty(projectNoPrefix)) {
  407 + query.in(ProjectBaseInfoDO::getProjectNoPrefix, projectNoPrefix);
  408 + } else {
  409 + query.apply("1!=1");
  410 + }
  411 + })
  412 + .list();
  413 + Map<String, ProjectBaseInfoDO> noPrefix2ProjectProfitAnalysisDOMap = list.stream().collect(Collectors.toMap(ProjectBaseInfoDO::getProjectNoPrefix, Function.identity()));
  414 + Set<String> collect = orderInfoResultVOS.stream()
  415 + .map(OrderBaseInfoVO::getCustomerCode)
  416 + .collect(Collectors.toSet());
  417 + List<SystemSettingDO> systemSettingDOS = systemSettingService.lambdaQuery()
  418 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  419 + .eq(SystemSettingDO::getRelationCode, "costSettingItem")
  420 + .in(SystemSettingDO::getSettingValue, collect)
  421 + .list();
  422 + Map<String, SystemSettingDO> systemSettingDOSMap = systemSettingDOS.stream()
  423 + .collect(Collectors.toMap(SystemSettingDO::getSettingValue, Function.identity(), (x, y) -> x));
  424 + ObjectMapper objectMapper = new ObjectMapper();
  425 + BigDecimal systemExchangeRate = systemSettingService.getExchangeRate();
  426 + List<ProjectFieldLockRecord> lockRecords = projectionFieldLockRecordService
  427 + .lambdaQuery()
  428 + .func(query -> {
  429 + Set<String> projectNoPrefixs = list.stream().map(ProjectBaseInfoDO::getProjectNoPrefix).collect(Collectors.toSet());
  430 + if(CollUtil.isNotEmpty(projectNoPrefixs)){
  431 + query.in(ProjectFieldLockRecord::getProjectNoPrefix,projectNoPrefixs);
  432 +
  433 + }else {
  434 + query.apply("1!=1");
  435 + }
  436 + })
  437 + .list();
  438 + Map<String,ProjectBaseInfoLockFieldVO> prjectNo2LockRecordMap = lockRecords.stream()
  439 + .collect(Collectors.toMap(ProjectFieldLockRecord::getProjectNoPrefix, record -> {
  440 + try {
  441 + return objectMapper.readValue(record.getFields(), ProjectBaseInfoLockFieldVO.class);
  442 + } catch (JsonProcessingException e) {
  443 + throw new RuntimeException(e);
  444 + }
  445 + }));
  446 +
  447 + List<BusinessProfitInfoVO> businessProfitInfoVOs = orderBaseInfoDOSGroupByProjectNoPre.entrySet().stream().map(entry -> {
  448 + List<OrderInfoResultVO> details = entry.getValue();
  449 + BusinessProfitInfoVO businessProfitInfoVO = BusinessProfitInfoVO.builder()
  450 + .customerCode(details.get(0).getCustomerCode())
  451 + .projectNoPrefix(entry.getKey())
  452 + .lockFields(prjectNo2LockRecordMap.get(entry.getKey()))
  453 + .build();
  454 +
  455 + //客户总金额¥
  456 + details.stream()
  457 + .map(OrderInfoResultVO::getProfitAnalysisInfo)
  458 + .filter(Objects::nonNull)
  459 + .map(OrderProfitAnalysisVO::getCustomerRmbTotalPrice)
  460 + .filter(Objects::nonNull)
  461 + .map(BigDecimal::valueOf)
  462 + .reduce(BigDecimal::add)
  463 + .ifPresent(price -> businessProfitInfoVO.setCustomerRmbTotalPrice(price.doubleValue()));
  464 +
  465 + //客户总金额$
  466 + details.stream()
  467 + .map(OrderInfoResultVO::getProfitAnalysisInfo)
  468 + .filter(Objects::nonNull)
  469 + .map(OrderProfitAnalysisVO::getCustomerTotalPrice)
  470 + .filter(Objects::nonNull)
  471 + .map(BigDecimal::valueOf)
  472 + .reduce(BigDecimal::add)
  473 + .ifPresent(price -> businessProfitInfoVO.setCustomerTotalPrice(price.doubleValue()));
  474 +
  475 + //生产科总价¥
  476 + details.stream()
  477 + .map(OrderInfoResultVO::getProfitAnalysisInfo)
  478 + .filter(Objects::nonNull)
  479 + .map(OrderProfitAnalysisVO::getProductionDepartmentTotalPrice)
  480 + .filter(Objects::nonNull)
  481 + .map(BigDecimal::valueOf)
  482 + .reduce(BigDecimal::add)
  483 + .ifPresent(price -> businessProfitInfoVO.setProductionDepartmentTotalPrice(price.doubleValue()));
  484 +
  485 + //包装费用合计$
  486 + details.stream()
  487 + .map(OrderInfoResultVO::getProfitAnalysisInfo)
  488 + .filter(Objects::nonNull)
  489 + .map(OrderProfitAnalysisVO::getPacketTotalPrice)
  490 + .filter(Objects::nonNull)
  491 + .map(BigDecimal::valueOf)
  492 + .reduce(BigDecimal::add)
  493 + .ifPresent(price -> businessProfitInfoVO.setPacketTotalPrice(price.doubleValue()));
  494 +
  495 + //包装费用合计¥
  496 + businessProfitInfoVO.setPacketRmbTotalPrice(Optional.ofNullable(businessProfitInfoVO.getPacketTotalPrice())
  497 + .orElse(0.0) * 6.2);
  498 + //包装费用实际金额
  499 + details.stream()
  500 + .map(OrderInfoResultVO::getOrderCostInfo)
  501 + .filter(Objects::nonNull)
  502 + .map(OrderCostInfoVO::getPacketActualRmbTotalPrice)
  503 + .filter(Objects::nonNull)
  504 + .reduce(BigDecimal::add)
  505 + .ifPresent(packetActualRmbTotalPrice -> {
  506 + businessProfitInfoVO.setPacketActualRmbTotalPrice(packetActualRmbTotalPrice.setScale(4, RoundingMode.HALF_UP));
  507 + });
  508 + //订单数
  509 + details.stream()
  510 + .mapToInt(OrderInfoResultVO::getOrderCount)
  511 + .filter(Objects::nonNull)
  512 + .reduce(Integer::sum)
  513 + .ifPresent(businessProfitInfoVO::setOrderCount);
  514 + if (Objects.nonNull(businessProfitInfoVO.getOrderCount())
  515 + && Objects.nonNull(businessProfitInfoVO.getPacketActualRmbTotalPrice())
  516 + ) {
  517 + //实际跟单单价
  518 + businessProfitInfoVO.setActualOrderRmbPrice(businessProfitInfoVO.getPacketActualRmbTotalPrice().divide(new BigDecimal(businessProfitInfoVO.getOrderCount()), 4, RoundingMode.HALF_UP));
  519 + //折换成美金
  520 + businessProfitInfoVO.setActualOrderPrice(businessProfitInfoVO.getActualOrderRmbPrice().divide(BigDecimal.valueOf(6.2), 4, RoundingMode.HALF_UP));
  521 + }
  522 + if (Objects.nonNull(businessProfitInfoVO.getPacketActualRmbTotalPrice())
  523 + && Objects.nonNull(businessProfitInfoVO.getPacketRmbTotalPrice())) {
  524 + //包装费用收益¥
  525 + businessProfitInfoVO.setPacketProfitRmbPrice(BigDecimal.valueOf(businessProfitInfoVO.getPacketRmbTotalPrice()).subtract(businessProfitInfoVO.getPacketActualRmbTotalPrice()));
  526 + }
  527 +
  528 + //hod时间差
  529 + LocalDateTime earliest = details.stream()
  530 + .map(OrderInfoResultVO::getOrderHodTime)
  531 + .map(hodTime -> LocalDateTime.parse(hodTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
  532 + .min(Comparator.naturalOrder())
  533 + .orElse(null);
  534 + LocalDateTime latest = details.stream()
  535 + .map(OrderInfoResultVO::getOrderHodTime)
  536 + .map(hodTime -> LocalDateTime.parse(hodTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
  537 + .max(Comparator.naturalOrder())
  538 + .orElse(null);
  539 + businessProfitInfoVO.setProduceStartTime(earliest);
  540 + businessProfitInfoVO.setProduceEndTime(latest);
  541 + //研发复制费合计¥ 固定成本¥ 西班牙已发提成¥ 已发提成¥ 实际汇率¥
  542 + if (Objects.nonNull(noPrefix2ProjectProfitAnalysisDOMap.get(entry.getKey()))) {
  543 + ProjectBaseInfoDO projectBaseInfoDO = noPrefix2ProjectProfitAnalysisDOMap.get(entry.getKey());
  544 + //研发复制费用
  545 + businessProfitInfoVO.setDevelopmentCopyRmbTotalPrice(projectBaseInfoDO.getDevelopmentCopyRmbTotalPrice());
  546 + //西班牙已付提成
  547 + businessProfitInfoVO.setSpainPaidRmbCommission(projectBaseInfoDO.getSpainPaidRmbCommission());
  548 + //已付提成
  549 + businessProfitInfoVO.setPaidRmbCommission(projectBaseInfoDO.getPaidRmbCommission());
  550 + //实际汇率
  551 + businessProfitInfoVO.setActualExchangeRate(projectBaseInfoDO.getActualExchangeRate());
  552 + //项目开始时间
  553 + businessProfitInfoVO.setProjectStartTime(projectBaseInfoDO.getProjectStartTime());
  554 + //项目结束时间
  555 + businessProfitInfoVO.setProjectEndTime(projectBaseInfoDO.getProjectEndTime());
  556 + //生产开始时间
  557 + if (Objects.nonNull(projectBaseInfoDO.getProjectStartTime())
  558 + && Objects.nonNull(projectBaseInfoDO.getProjectEndTime())
  559 + && Objects.nonNull(systemSettingDOSMap.get(details.get(0).getCustomerCode()))) {
  560 +
  561 + //获取固定成本、提成比率、西班牙提成比例
  562 + long between = ChronoUnit.DAYS.between(projectBaseInfoDO.getProjectStartTime(), projectBaseInfoDO.getProjectEndTime());
  563 + SystemSettingDO systemSettingDO = systemSettingDOSMap.get(details.get(0).getCustomerCode());
  564 + String relationValue = systemSettingDO.getRelationValue();
  565 + List<Map<String, String>> relations = null;
  566 + try {
  567 + relations = objectMapper.readValue(relationValue, objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class));
  568 + } catch (JsonProcessingException e) {
  569 + throw new RuntimeException(e);
  570 + }
  571 + String fixCostValue = null;
  572 + String ratio = null;
  573 + String spainRatio = null;
  574 + for (Map<String, String> relation : relations) {
  575 + if ("fixCost".equals(relation.get("relationCode"))) {
  576 + fixCostValue = relation.get("relationValue");
  577 + } else if ("ratio".equals(relation.get("relationCode"))) {
  578 + ratio = relation.get("relationValue");
  579 + } else if ("spainRatio".equals(relation.get("relationCode"))) {
  580 + spainRatio = relation.get("relationValue");
  581 + }
  582 + }
  583 + //固定成本
  584 + businessProfitInfoVO.setFixedCost(BigDecimal.valueOf(between * Double.parseDouble(fixCostValue)));
  585 + if (Objects.nonNull(spainRatio)
  586 + && Objects.nonNull(businessProfitInfoVO.getCustomerRmbTotalPrice())) {
  587 + //西班牙提成
  588 + businessProfitInfoVO.setSpainRmbCommission(BigDecimal.valueOf(businessProfitInfoVO.getCustomerRmbTotalPrice()).multiply(BigDecimal.valueOf(Double.parseDouble(spainRatio))));
  589 + }
  590 + if (Objects.nonNull(businessProfitInfoVO.getSpainRmbCommission())
  591 + && Objects.nonNull(projectBaseInfoDO.getSpainPaidRmbCommission())) {
  592 + //西班牙未发提成
  593 + businessProfitInfoVO.setSpainUnpaidRmbCommission(businessProfitInfoVO.getSpainRmbCommission().subtract(projectBaseInfoDO.getSpainPaidRmbCommission()));
  594 + }
  595 +
  596 + if (Objects.nonNull(ratio)
  597 + && Objects.nonNull(businessProfitInfoVO.getCustomerRmbTotalPrice())) {
  598 + //中国团队提成
  599 + businessProfitInfoVO.setRmbCommission(BigDecimal.valueOf(businessProfitInfoVO.getCustomerRmbTotalPrice()).multiply(BigDecimal.valueOf(Double.parseDouble(ratio))));
  600 + }
  601 + if (Objects.nonNull(businessProfitInfoVO.getRmbCommission())
  602 + && Objects.nonNull(projectBaseInfoDO.getPaidRmbCommission())) {
  603 + //未发提成
  604 + businessProfitInfoVO.setUnpaidRmbCommission(businessProfitInfoVO.getRmbCommission().subtract(projectBaseInfoDO.getPaidRmbCommission()));
  605 + }
  606 + }
  607 + if (Objects.nonNull(businessProfitInfoVO.getActualExchangeRate())
  608 + && Objects.nonNull(businessProfitInfoVO.getCustomerTotalPrice())) {
  609 + businessProfitInfoVO.setExchangeRateProfit(BigDecimal.valueOf(businessProfitInfoVO.getCustomerTotalPrice())
  610 + .multiply(businessProfitInfoVO.getActualExchangeRate().subtract(systemExchangeRate)));
  611 + }
  612 + }
  613 + //支出合计
  614 + businessProfitInfoVO.setRmbTotalExpense(Optional.ofNullable(businessProfitInfoVO.getSpainPaidRmbCommission()).orElse(BigDecimal.ZERO)
  615 + .add(Optional.ofNullable(businessProfitInfoVO.getPaidRmbCommission()).orElse(BigDecimal.ZERO))
  616 + .add(Optional.ofNullable(businessProfitInfoVO.getFixedCost()).orElse(BigDecimal.ZERO))
  617 + .add(Optional.ofNullable(businessProfitInfoVO.getDevelopmentCopyRmbTotalPrice()).orElse(BigDecimal.ZERO))
  618 + .add(BigDecimal.valueOf(Optional.ofNullable(businessProfitInfoVO.getPacketRmbTotalPrice()).orElse(0.0)))
  619 + .add(BigDecimal.valueOf(Optional.ofNullable(businessProfitInfoVO.getProductionDepartmentTotalPrice()).orElse(0.0))));
  620 + if (Objects.nonNull(businessProfitInfoVO.getCustomerRmbTotalPrice())
  621 + && Objects.nonNull(businessProfitInfoVO.getProductionDepartmentTotalPrice())
  622 + && Objects.nonNull(businessProfitInfoVO.getPacketRmbTotalPrice())) {
  623 + //毛利润
  624 + businessProfitInfoVO.setProfit(BigDecimal.valueOf(businessProfitInfoVO.getCustomerRmbTotalPrice())
  625 + .subtract(BigDecimal.valueOf(businessProfitInfoVO.getProductionDepartmentTotalPrice()))
  626 + .subtract(BigDecimal.valueOf(businessProfitInfoVO.getPacketRmbTotalPrice())));
  627 + }
  628 + if (Objects.nonNull(businessProfitInfoVO.getProfit())
  629 + && Objects.nonNull(businessProfitInfoVO.getCustomerRmbTotalPrice())) {
  630 + //毛利润率
  631 + businessProfitInfoVO.setProfitRate(businessProfitInfoVO.getProfit()
  632 + .divide(BigDecimal.valueOf(businessProfitInfoVO.getCustomerRmbTotalPrice()), 4, RoundingMode.HALF_UP));
  633 + }
  634 + if (Objects.nonNull(businessProfitInfoVO.getCustomerRmbTotalPrice())
  635 + && Objects.nonNull(businessProfitInfoVO.getRmbTotalExpense())) {
  636 + //研发贸易净利润
  637 + businessProfitInfoVO.setDevelopmentProfit(BigDecimal.valueOf(businessProfitInfoVO.getCustomerRmbTotalPrice())
  638 + .subtract(businessProfitInfoVO.getRmbTotalExpense())
  639 + );
  640 + //研发贸易净利润率
  641 + businessProfitInfoVO.setDevelopmentProfitRate(businessProfitInfoVO.getDevelopmentProfit()
  642 + .divide(BigDecimal.valueOf(businessProfitInfoVO.getCustomerRmbTotalPrice()), 4, RoundingMode.HALF_UP));
  643 + }
  644 + //综合收益
  645 + businessProfitInfoVO.setComprehensiveProfit(Optional.ofNullable(businessProfitInfoVO.getDevelopmentProfit()).orElse(BigDecimal.ZERO)
  646 + .add(Optional.ofNullable(businessProfitInfoVO.getExchangeRateProfit()).orElse(BigDecimal.ZERO))
  647 + .add(Optional.ofNullable(businessProfitInfoVO.getActualOrderRmbPrice()).orElse(BigDecimal.ZERO)));
  648 + return businessProfitInfoVO;
  649 + }).collect(Collectors.toList());
  650 + return businessProfitInfoVOs;
  651 + }
  652 +
  653 + @Override
  654 + public void exportBusinessProfitInfo(HttpServletResponse response, String projectNoPrefix) throws Exception {
  655 + ServerResult serverResult = listBusinessProfitInfoByPage(OrderBaseInfoQueryVO.builder().page(1).pageSize(1).projectNoLikeRight(projectNoPrefix).build());
  656 + Page<BusinessProfitInfoVO> page = (Page<BusinessProfitInfoVO>) serverResult.getData();
  657 + List<BusinessProfitInfoVO> orderInfoResultVOS = page.getRecords();
  658 + BusinessProfitInfoVO businessProfitInfoVO = orderInfoResultVOS.get(0);
  659 + exportBusinessProfitExcel(response, businessProfitInfoVO);
  660 + }
  661 + public void exportBusinessProfitExcel(HttpServletResponse response, BusinessProfitInfoVO businessProfitInfoVO) throws Exception {
  662 + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  663 + XSSFWorkbook workbook = new XSSFWorkbook();
  664 + Sheet sheet = workbook.createSheet("业务净利润分析");
  665 +
  666 + // 设置默认列宽
  667 + sheet.setDefaultColumnWidth(10);
  668 +
  669 + // 创建字体和样式
  670 + XSSFFont font = workbook.createFont();
  671 + font.setFontName("Arial");
  672 + font.setFontHeightInPoints((short) 10);
  673 +
  674 + CellStyle cellStyle = workbook.createCellStyle();
  675 + cellStyle.setAlignment(HorizontalAlignment.CENTER);
  676 + cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
  677 + cellStyle.setFont(font);
  678 + cellStyle.setWrapText(true);
  679 +
  680 +
  681 + createMergedRow(sheet, cellStyle, 0, 3, 0, 9, "业务净利润分析表");
  682 + createMergedRow(sheet, cellStyle, 4, 5, 0, 1, "项目号");
  683 + createMergedRow(sheet, cellStyle, 4, 5, 2, 4, Optional.ofNullable(businessProfitInfoVO.getProjectNoPrefix()).orElse("-"));
  684 + createMergedRow(sheet, cellStyle, 4, 5, 5, 6, "开始时间");
  685 + createMergedRow(sheet, cellStyle, 4, 5, 7, 9, "结束时间");
  686 + createMergedRow(sheet, cellStyle, 6, 7, 0, 1, "");
  687 + createMergedRow(sheet, cellStyle, 6, 7, 2, 4, "项目开始时间");
  688 + createMergedRow(sheet, cellStyle, 6, 7, 5, 6, Optional.ofNullable(dateTimeFormatter.format(businessProfitInfoVO.getProjectStartTime())).orElse("-"));
  689 + createMergedRow(sheet, cellStyle, 6, 7, 7, 9, Optional.ofNullable(dateTimeFormatter.format(businessProfitInfoVO.getProjectEndTime())).orElse("-"));
  690 + createMergedRow(sheet, cellStyle, 8, 9, 0, 1, "");
  691 + createMergedRow(sheet, cellStyle, 8, 9, 2, 4, "生产进行时间");
  692 + createMergedRow(sheet, cellStyle, 8, 9, 5, 6, Optional.ofNullable(dateTimeFormatter.format(businessProfitInfoVO.getProduceStartTime())).orElse("-"));
  693 + createMergedRow(sheet, cellStyle, 8, 9, 7, 9, Optional.ofNullable(dateTimeFormatter.format(businessProfitInfoVO.getProduceEndTime())).orElse("-"));
  694 + createMergedRow(sheet, cellStyle, 10, 11, 0, 1, "客户编码");
  695 + createMergedRow(sheet, cellStyle, 10, 11, 2, 4, Optional.ofNullable(businessProfitInfoVO.getCustomerCode()).orElse("-"));
  696 + createMergedRow(sheet, cellStyle, 10, 11, 5, 6, "");
  697 + createMergedRow(sheet, cellStyle, 10, 11, 7, 9, "备注");
  698 + createMergedRow(sheet, cellStyle, 12, 13, 0, 4, "客户总金额计算");
  699 + createMergedRow(sheet, cellStyle, 12, 13, 5, 6, Optional.ofNullable(businessProfitInfoVO.getCustomerRmbTotalPrice()).map(price -> "¥" + price).orElse("-"));
  700 + createMergedRow(sheet, cellStyle, 12, 13, 7, 9, Optional.ofNullable(businessProfitInfoVO.getCustomerTotalPrice()).map(price -> "$" + price).orElse("-"));
  701 + createMergedRow(sheet, cellStyle, 14, 15, 0, 4, "生产科总价合计");
  702 + createMergedRow(sheet, cellStyle, 14, 15, 5, 6, Optional.ofNullable(businessProfitInfoVO.getProductionDepartmentTotalPrice()).map(price -> "¥" + price).orElse("-"));
  703 + createMergedRow(sheet, cellStyle, 14, 15, 7, 9,"");
  704 + createMergedRow(sheet, cellStyle, 16, 17, 0, 4, "包装费用合计");
  705 + createMergedRow(sheet, cellStyle, 16, 17, 5, 6, Optional.ofNullable(businessProfitInfoVO.getPacketRmbTotalPrice()).map(price -> "¥" + price).orElse("-"));
  706 + createMergedRow(sheet, cellStyle, 16, 17, 7, 9, Optional.ofNullable(businessProfitInfoVO.getPacketTotalPrice()).map(price -> "$" + price).orElse("-"));
  707 + createMergedRow(sheet, cellStyle, 18, 19, 0, 4, "研发复制费合计");
  708 + createMergedRow(sheet, cellStyle, 18, 19, 5, 6, Optional.ofNullable(businessProfitInfoVO.getDevelopmentCopyRmbTotalPrice()).map(price -> "¥" + price).orElse("-"));
  709 + createMergedRow(sheet, cellStyle, 18, 19, 7, 9,"");
  710 + createMergedRow(sheet, cellStyle, 20, 21, 0, 4, "固定成本");
  711 + createMergedRow(sheet, cellStyle, 20, 21, 5, 6, Optional.ofNullable(businessProfitInfoVO.getFixedCost()).map(price -> "¥" + price).orElse("-"));
  712 + createMergedRow(sheet, cellStyle, 20, 21, 7, 9,"");
  713 + createMergedRow(sheet, cellStyle, 22, 23, 0, 4, "西班牙提成");
  714 + createMergedRow(sheet, cellStyle, 22, 23, 5, 6, Optional.ofNullable(businessProfitInfoVO.getSpainRmbCommission()).map(price -> "¥" + price).orElse("-"));
  715 + createMergedRow(sheet, cellStyle, 22, 23, 7, 9,"");
  716 + createMergedRow(sheet, cellStyle, 24, 25, 0, 4, "中国团队提成");
  717 + createMergedRow(sheet, cellStyle, 24, 25, 5, 6, Optional.ofNullable(businessProfitInfoVO.getRmbCommission()).map(price -> "¥" + price).orElse("-"));
  718 + createMergedRow(sheet, cellStyle, 24, 25, 7, 9,"");
  719 + createMergedRow(sheet, cellStyle, 26, 27, 0, 4, "支出合计");
  720 + createMergedRow(sheet, cellStyle, 26, 27, 5, 6, Optional.ofNullable(businessProfitInfoVO.getRmbTotalExpense()).map(price -> "¥" + price).orElse("-"));
  721 + createMergedRow(sheet, cellStyle, 26, 27, 7, 9,"");
  722 + createMergedRow(sheet, cellStyle, 28, 29, 0, 4, "毛利润");
  723 + createMergedRow(sheet, cellStyle, 28, 29, 5, 6, Optional.ofNullable(businessProfitInfoVO.getProfit()).map(price -> "¥" + price).orElse("-"));
  724 + createMergedRow(sheet, cellStyle, 28, 29, 7, 9,"");
  725 + createMergedRow(sheet, cellStyle, 30, 31, 0, 4, "毛利率");
  726 + createMergedRow(sheet, cellStyle, 30, 31, 5, 6, Optional.ofNullable(businessProfitInfoVO.getProfitRate()).map(rate -> rate.multiply(new BigDecimal(100)) + "%").orElse("-"));
  727 + createMergedRow(sheet, cellStyle, 30, 31, 7, 9,"");
  728 + createMergedRow(sheet, cellStyle, 32, 33, 0, 4, "研发贸易净利润");
  729 + createMergedRow(sheet, cellStyle, 32, 33, 5, 6, Optional.ofNullable(businessProfitInfoVO.getDevelopmentProfit()).map(price -> "¥" + price).orElse("-"));
  730 + createMergedRow(sheet, cellStyle, 32, 33, 7, 9,"");
  731 + createMergedRow(sheet, cellStyle, 34, 35, 0, 4, "研发贸易净利润率");
  732 + createMergedRow(sheet, cellStyle, 34, 35, 5, 6, Optional.ofNullable(businessProfitInfoVO.getDevelopmentProfitRate()).map(rate -> rate.multiply(new BigDecimal(100)) + "%").orElse("-"));
  733 + createMergedRow(sheet, cellStyle, 34, 35, 7, 9,"");
  734 + createMergedRow(sheet, cellStyle, 36, 37, 0, 4, "包装费用合计金额");
  735 + createMergedRow(sheet, cellStyle, 36, 37, 5, 6, Optional.ofNullable(businessProfitInfoVO.getPacketRmbTotalPrice()).map(price -> "¥" + price).orElse("-"));
  736 + createMergedRow(sheet, cellStyle, 36, 37, 7, 9,"");
  737 + createMergedRow(sheet, cellStyle, 38, 39, 0, 4, "包装费用实际金额");
  738 + createMergedRow(sheet, cellStyle, 38, 39, 5, 6, Optional.ofNullable(businessProfitInfoVO.getPacketActualRmbTotalPrice()).map(price -> "¥" + price).orElse("-"));
  739 + createMergedRow(sheet, cellStyle, 38, 39, 7, 9,"");
  740 + createMergedRow(sheet, cellStyle, 40, 41, 0, 4, "订单总数量");
  741 + createMergedRow(sheet, cellStyle, 40, 41, 5, 6, Optional.ofNullable(businessProfitInfoVO.getOrderCount()).map(String::valueOf).orElse("-"));
  742 + createMergedRow(sheet, cellStyle, 40, 41, 7, 9,"");
  743 + createMergedRow(sheet, cellStyle, 42, 43, 0, 4, "实际跟单单价=实际跟单费用/件数");
  744 + createMergedRow(sheet, cellStyle, 42, 43, 5, 6, Optional.ofNullable(businessProfitInfoVO.getActualOrderRmbPrice()).map(price -> "¥" + price).orElse("-"));
  745 + createMergedRow(sheet, cellStyle, 42, 43, 7, 9,"");
  746 + createMergedRow(sheet, cellStyle, 44, 45, 0, 4, "实际跟单单价折算美金");
  747 + createMergedRow(sheet, cellStyle, 44, 45, 5, 6, Optional.ofNullable(businessProfitInfoVO.getActualOrderPrice()).map(price -> "$" + price).orElse("-"));
  748 + createMergedRow(sheet, cellStyle, 44, 45, 7, 9,"");
  749 + createMergedRow(sheet, cellStyle, 46, 47, 0, 4, "包装费用收益");
  750 + createMergedRow(sheet, cellStyle, 46, 47, 5, 6, Optional.ofNullable(businessProfitInfoVO.getPacketProfitRmbPrice()).map(price -> "¥" + price).orElse("-"));
  751 + createMergedRow(sheet, cellStyle, 46, 47, 7, 9,"");
  752 + createMergedRow(sheet, cellStyle, 48, 49, 0, 4, "包装费用净利润率");
  753 + createMergedRow(sheet, cellStyle, 48, 49, 5, 6, Optional.ofNullable(businessProfitInfoVO.getPacketProfitRate()).map(rate -> rate.multiply(new BigDecimal(100)) + "%").orElse("-"));
  754 + createMergedRow(sheet, cellStyle, 48, 49, 7, 9,"");
  755 + createMergedRow(sheet, cellStyle, 50, 51, 0, 4, "实际汇率");
  756 + createMergedRow(sheet, cellStyle, 50, 51, 5, 6, Optional.ofNullable(businessProfitInfoVO.getActualExchangeRate()).map(String::valueOf).orElse("-"));
  757 + createMergedRow(sheet, cellStyle, 50, 51, 7, 9,"");
  758 + createMergedRow(sheet, cellStyle, 52, 53, 0, 4, "汇率收益");
  759 + createMergedRow(sheet, cellStyle, 52, 53, 5, 6, Optional.ofNullable(businessProfitInfoVO.getExchangeRateProfit()).map(price -> "¥" + price).orElse("-"));
  760 + createMergedRow(sheet, cellStyle, 52, 53, 7, 9,"");
  761 + createMergedRow(sheet, cellStyle, 54, 55, 0, 4, "综合收益");
  762 + createMergedRow(sheet, cellStyle, 54, 55, 5, 6, Optional.ofNullable(businessProfitInfoVO.getComprehensiveProfit()).map(price -> "¥" + price).orElse("-"));
  763 + createMergedRow(sheet, cellStyle, 54, 55, 7, 9,"");
  764 +
  765 + // 设置响应头
  766 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  767 + response.setHeader("Content-Disposition", "attachment;filename=BusinessProfitAnalysis.xlsx");
  768 + try (OutputStream out = response.getOutputStream()) {
  769 + workbook.write(out);
  770 + } finally {
  771 + workbook.close();
  772 + }
  773 + }
  774 +
  775 + @Override
  776 + public void exportInnerProfitInfo(HttpServletResponse response, String projectNoPrefix) throws Exception {
  777 + ServerResult serverResult = listInnerProfitInfoByPage(OrderBaseInfoQueryVO.builder().page(1).pageSize(1).projectNoLikeRight(projectNoPrefix).build());
  778 + Page<InnerProfitInfoVO> page = (Page<InnerProfitInfoVO>) serverResult.getData();
  779 + List<InnerProfitInfoVO> profitInfoVOS = page.getRecords();
  780 + InnerProfitInfoVO ProfitInfoVO = profitInfoVOS.get(0);
  781 + exportInnerProfitExcel(response, ProfitInfoVO);
  782 + }
  783 +
  784 + public void exportInnerProfitExcel(HttpServletResponse response, InnerProfitInfoVO vo) throws Exception {
  785 + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  786 + XSSFWorkbook workbook = new XSSFWorkbook();
  787 + Sheet sheet = workbook.createSheet("内部生产净利润分析");
  788 + sheet.setDefaultColumnWidth(10);
  789 +
  790 + // 设置字体和样式
  791 + XSSFFont font = workbook.createFont();
  792 + font.setFontName("Arial");
  793 + font.setFontHeightInPoints((short) 10);
  794 +
  795 + CellStyle cellStyle = workbook.createCellStyle();
  796 + cellStyle.setAlignment(HorizontalAlignment.CENTER);
  797 + cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
  798 + cellStyle.setFont(font);
  799 + cellStyle.setWrapText(true);
  800 +
  801 + // 第一部分:表头
  802 + createMergedRow(sheet, cellStyle, 0, 3, 0, 9, "内部生产净利润分析表");
  803 +
  804 + // 第二部分:项目信息
  805 + createMergedRow(sheet, cellStyle, 4, 5, 0, 1, "项目号");
  806 + createMergedRow(sheet, cellStyle, 4, 5, 2, 3, Optional.ofNullable(vo.getProjectNoPrefix()).orElse("-"));
  807 + createMergedRow(sheet, cellStyle, 4, 5, 4, 5, "开始时间");
  808 + createMergedRow(sheet, cellStyle, 4, 5, 6, 7, "结束时间");
  809 + createMergedRow(sheet, cellStyle, 4, 5, 8, 9, "生产持续时间");
  810 +
  811 + String projectStartTime = Optional.ofNullable(vo.getProduceStartTime()).map(dateTimeFormatter::format).orElse("-");
  812 + String projectEndTime = Optional.ofNullable(vo.getProduceEndTime()).map(dateTimeFormatter::format).orElse("-");
  813 + String duration = (vo.getProduceStartTime() != null && vo.getProduceEndTime() != null)
  814 + ? String.valueOf(Duration.between(vo.getProduceStartTime(), vo.getProduceEndTime()).toDays())
  815 + : "-";
  816 + createMergedRow(sheet, cellStyle, 6, 7, 0, 1, "");
  817 + createMergedRow(sheet, cellStyle, 6, 7, 2, 3, "生产起止时间");
  818 + createMergedRow(sheet, cellStyle, 6, 7, 4, 5, projectStartTime);
  819 + createMergedRow(sheet, cellStyle, 6, 7, 6, 7, projectEndTime);
  820 + createMergedRow(sheet, cellStyle, 6, 7, 8, 9, duration);
  821 +
  822 + // 第三部分:客户和订单信息
  823 + createMergedRow(sheet, cellStyle, 8, 9, 0, 1, "客户编码");
  824 + createMergedRow(sheet, cellStyle, 8, 9, 2, 3, Optional.ofNullable(vo.getCustomerCode()).orElse("-"));
  825 + createMergedRow(sheet, cellStyle, 8, 9, 4, 5, "明细");
  826 + createMergedRow(sheet, cellStyle, 8, 9, 6, 7, "金额");
  827 + createMergedRow(sheet, cellStyle, 8, 9, 8, 9, "订单数量");
  828 +
  829 + // 第四部分:生产科总价合计
  830 + createMergedRow(sheet, cellStyle, 10, 11, 0, 3, "生产科总价合计");
  831 + createMergedRow(sheet, cellStyle, 10, 11, 4, 5, "¥" + Optional.ofNullable(vo.getProductionDepartmentTotalPrice()).orElse(0.0));
  832 + createMergedRow(sheet, cellStyle, 10, 11, 6, 7, "¥" + Optional.ofNullable(vo.getProductionDepartmentTotalPrice()).orElse(0.0));
  833 + createMergedRow(sheet, cellStyle, 10, 11, 8, 9, Optional.ofNullable(vo.getOrderCount()).map(String::valueOf).orElse("-"));
  834 +
  835 + // 第五部分:预算与实际
  836 + createMergedRow(sheet, cellStyle, 12, 13, 0, 3, "生产科预算金额");
  837 + createMergedRow(sheet, cellStyle, 12, 13, 4, 5, "¥" + Optional.ofNullable(vo.getProductionDepartmentPredictPrice()).map(String::valueOf).orElse("-"));
  838 + createMergedRow(sheet, cellStyle, 12, 13, 6, 7, "预算占比");
  839 + createMergedRow(sheet, cellStyle, 12, 13, 8, 9, "预算占比与实际占比差");
  840 +
  841 + createMergedRow(sheet, cellStyle, 14, 15, 0, 3, "实际发生费用");
  842 + createMergedRow(sheet, cellStyle, 14, 15, 4, 5, "¥" + Optional.ofNullable(vo.getProductionActualPrice()).orElse(BigDecimal.ZERO));
  843 + createMergedRow(sheet, cellStyle, 14, 15, 6, 7, Optional.ofNullable(vo.getPredictRatio()).map(r -> r.multiply(BigDecimal.valueOf(100)) + "%").orElse("-"));
  844 + createMergedRow(sheet, cellStyle, 14, 15, 8, 9, Optional.ofNullable(vo.getPredictAndActualRatio()).map(r -> r.multiply(BigDecimal.valueOf(100)) + "%").orElse("-"));
  845 +
  846 + // 第六部分:毛利润
  847 + createMergedRow(sheet, cellStyle, 16, 17, 0, 3, "内部生产毛利润");
  848 + createMergedRow(sheet, cellStyle, 16, 17, 4, 5, "¥" + Optional.ofNullable(vo.getBeforeGrossProfit()).orElse(BigDecimal.ZERO));
  849 + createMergedRow(sheet, cellStyle, 16, 16, 6, 7, "事前毛利润");
  850 + createMergedRow(sheet, cellStyle, 16, 16, 8, 9, "事前毛利率");
  851 + createMergedRow(sheet, cellStyle, 17, 17, 6, 7, Optional.ofNullable(vo.getBeforeGrossProfit()).orElse(BigDecimal.ZERO).toString());
  852 + createMergedRow(sheet, cellStyle, 17, 17, 8, 9, Optional.ofNullable(vo.getBeforeGrossProfitRate()).map(r -> r.multiply(BigDecimal.valueOf(100)) + "%").orElse("-"));
  853 +
  854 + // 第七部分:固定成本与净利润
  855 + createMergedRow(sheet, cellStyle, 18, 19, 0, 3, "内部生产固定成本");
  856 + createMergedRow(sheet, cellStyle, 18, 19, 4, 5, "¥" + Optional.ofNullable(vo.getInnerProductionFixedCost()).orElse(BigDecimal.ZERO));
  857 + createMergedRow(sheet, cellStyle, 18, 18, 6, 7, "事后毛利润");
  858 + createMergedRow(sheet, cellStyle, 18, 18, 8, 9, "事后毛利率");
  859 + createMergedRow(sheet, cellStyle, 19, 19, 6, 7, Optional.ofNullable(vo.getGrossProfit()).orElse(BigDecimal.ZERO).toString());
  860 + createMergedRow(sheet, cellStyle, 19, 19, 8, 9, Optional.ofNullable(vo.getGrossProfitRate()).map(r -> r.multiply(BigDecimal.valueOf(100)) + "%").orElse("-"));
  861 +
  862 + // 第八部分:提成与净利润
  863 + createMergedRow(sheet, cellStyle, 20, 21, 0, 3, "内部生产提成");
  864 + createMergedRow(sheet, cellStyle, 20, 21, 4, 5, "¥" + Optional.ofNullable(vo.getInnerProductionCommission()).orElse(BigDecimal.ZERO));
  865 + createMergedRow(sheet, cellStyle, 20, 21, 6, 7, "净利润");
  866 + createMergedRow(sheet, cellStyle, 20, 21, 8, 9, "");
  867 +
  868 + createMergedRow(sheet, cellStyle, 22, 23, 0, 3, "内部生产净利润");
  869 + createMergedRow(sheet, cellStyle, 22, 23, 4, 5, "¥" + Optional.ofNullable(vo.getInnerProductionProfit()).orElse(BigDecimal.ZERO));
  870 + createMergedRow(sheet, cellStyle, 22, 23, 6, 7, Optional.ofNullable(vo.getInnerProductionProfitRate()).map(r -> r.multiply(BigDecimal.valueOf(100)) + "%").orElse("-"));
  871 + createMergedRow(sheet, cellStyle, 22, 23, 8, 9, "");
  872 +
  873 + // 设置响应头
  874 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  875 + response.setHeader("Content-Disposition", "attachment;filename=BusinessProfitAnalysis.xlsx");
  876 + try (OutputStream out = response.getOutputStream()) {
  877 + workbook.write(out);
  878 + } finally {
  879 + workbook.close();
  880 + }
  881 + }
  882 +
  883 + private void createMergedRow(Sheet sheet, CellStyle cellStyle, int startRow, int endRow, int startCol, int endCol, String value) {
  884 + for (int i = startRow; i <= endRow; i++) {
  885 + Row row = sheet.getRow(i);
  886 + if (row == null) {
  887 + row = sheet.createRow(i);
  888 + }
  889 + for (int j = startCol; j <= endCol; j++) {
  890 + Cell cell = row.createCell(j);
  891 + cell.setCellStyle(cellStyle);
  892 + if (i == startRow && j == startCol) {
  893 + cell.setCellValue(value);
  894 + }
  895 + }
  896 + }
  897 + sheet.addMergedRegion(new CellRangeAddress(startRow, endRow, startCol, endCol));
  898 + }
  899 +
  900 +}
... ...
src/main/resources/mapper/OrderCostFieldLockRecordMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="com.order.erp.mapper.OrderCostFieldLockRecordMapper">
  4 +
  5 + <!-- 通用查询映射结果 -->
  6 + <resultMap id="BaseResultMap" type="com.order.erp.domain.model.OrderCostFieldLockRecord">
  7 + <id column="id" property="id" />
  8 + <result column="fields" property="fields" />
  9 + <result column="user_id" property="userId" />
  10 + <result column="order_id" property="orderId" />
  11 + <result column="enable_flag" property="enableFlag" />
  12 + <result column="create_time" property="createTime" />
  13 + <result column="create_by" property="createBy" />
  14 + <result column="modify_time" property="modifyTime" />
  15 + <result column="modify_by" property="modifyBy" />
  16 + <result column="version" property="version" />
  17 + </resultMap>
  18 +
  19 + <!-- 通用查询结果列 -->
  20 + <sql id="Base_Column_List">
  21 + id, fields, user_id, order_id, enable_flag, create_time, create_by, modify_time, modify_by, version
  22 + </sql>
  23 +
  24 +</mapper>
... ...
src/main/resources/mapper/OrderCostInfoMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="com.order.erp.mapper.order.OrderCostInfoMapper">
  4 +
  5 + <!-- 通用查询映射结果 -->
  6 + <resultMap id="BaseResultMap" type="com.order.erp.domain.dto.order.OrderCostInfoDO">
  7 + <id column="id" property="id" />
  8 + <result column="production_department_predict_price" property="productionDepartmentPredictPrice" />
  9 + <result column="production_actual_price" property="productionActualPrice" />
  10 + <result column="packet_actual_rmb_total_price" property="packetActualRmbTotalPrice" />
  11 + </resultMap>
  12 +
  13 + <!-- 通用查询结果列 -->
  14 + <sql id="Base_Column_List">
  15 + id, production_department_predict_price, production_actual_price, packet_actual_rmb_total_price
  16 + </sql>
  17 +
  18 +</mapper>
... ...
src/main/resources/mapper/ProjectApplyMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="com.order.erp.mapper.ProjectApplyMapper">
  4 +
  5 + <!-- 通用查询映射结果 -->
  6 + <resultMap id="BaseResultMap" type="com.order.erp.domain.model.ProjectApplyDO">
  7 + <id column="id" property="id" />
  8 + <result column="project_id" property="projectId" />
  9 + <result column="apply_user_id" property="applyUserId" />
  10 + <result column="audit_user_id" property="auditUserId" />
  11 + <result column="fields" property="fields" />
  12 + <result column="status" property="status" />
  13 + <result column="audit_remark" property="auditRemark" />
  14 + <result column="audit_role_codes" property="auditRoleCodes" />
  15 + <result column="apply_remark" property="applyRemark" />
  16 + <result column="enable_flag" property="enableFlag" />
  17 + <result column="create_time" property="createTime" />
  18 + <result column="create_by" property="createBy" />
  19 + <result column="modify_time" property="modifyTime" />
  20 + <result column="modify_by" property="modifyBy" />
  21 + <result column="version" property="version" />
  22 + </resultMap>
  23 +
  24 + <!-- 通用查询结果列 -->
  25 + <sql id="Base_Column_List">
  26 + id, project_id, apply_user_id, audit_user_id, fields, status, audit_remark, audit_role_codes, apply_remark, enable_flag, create_time, create_by, modify_time, modify_by, version
  27 + </sql>
  28 +
  29 +</mapper>
... ...
src/main/resources/mapper/ProjectFieldLockRecordMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="com.order.erp.mapper.ProjectFieldLockRecordMapper">
  4 +
  5 + <!-- 通用查询映射结果 -->
  6 + <resultMap id="BaseResultMap" type="com.order.erp.domain.model.ProjectFieldLockRecord">
  7 + <id column="id" property="id" />
  8 + <result column="project_id" property="projectId" />
  9 + <result column="user_id" property="userId" />
  10 + <result column="fields" property="fields" />
  11 + <result column="enable_flag" property="enableFlag" />
  12 + <result column="create_time" property="createTime" />
  13 + <result column="create_by" property="createBy" />
  14 + <result column="modify_time" property="modifyTime" />
  15 + <result column="modify_by" property="modifyBy" />
  16 + <result column="version" property="version" />
  17 + </resultMap>
  18 +
  19 + <!-- 通用查询结果列 -->
  20 + <sql id="Base_Column_List">
  21 + id, project_id, user_id, fields, enable_flag, create_time, create_by, modify_time, modify_by, version
  22 + </sql>
  23 +
  24 +</mapper>
... ...