Commit 7a83ebbd595281c3662bd536d93a2e1f33f9391e

Authored by 房远帅
1 parent d3713aa2

采购合同:合同模块开发

Showing 25 changed files with 1899 additions and 6 deletions
@@ -2342,3 +2342,66 @@ CREATE TABLE `coordination_summary_approval_line` @@ -2342,3 +2342,66 @@ CREATE TABLE `coordination_summary_approval_line`
2342 KEY `idx_csal_approval_id` (`approval_id`), 2342 KEY `idx_csal_approval_id` (`approval_id`),
2343 KEY `idx_csal_plan_id` (`plan_id`) 2343 KEY `idx_csal_plan_id` (`plan_id`)
2344 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='采购吨超协汇总审批表明细'; 2344 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='采购吨超协汇总审批表明细';
  2345 +
  2346 +CREATE TABLE `procurement_contract`
  2347 +(
  2348 + `id` VARCHAR(32) NOT NULL COMMENT '主键ID',
  2349 + `procurement_plan_id` VARCHAR(32) NOT NULL COMMENT '关联采购计划ID',
  2350 + `procurement_plan_code` VARCHAR(32) NOT NULL COMMENT '投诉编码',
  2351 + `supplier_id` VARCHAR(32) NOT NULL COMMENT '供方ID',
  2352 + `company_short_id` VARCHAR(32) NOT NULL COMMENT '需方ID',
  2353 + `sign_place` VARCHAR(64) NOT NULL DEFAULT '芜湖市' COMMENT '签订地点(固定 芜湖市)',
  2354 + `sign_time` DATE NOT NULL COMMENT '签订时间',
  2355 + `delivery_time` DATE NOT NULL COMMENT '交货时间',
  2356 + `settlement_ratio` DECIMAL(10, 5) NOT NULL COMMENT '结算比例%',
  2357 + `total_quantity` DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '合计数量',
  2358 + `total_excluding_tax_amount` DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '合计不含税金额',
  2359 + `total_tax_amount` DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '合计税额',
  2360 + `total_amount` DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '合计金额',
  2361 + `special_agreement` TEXT DEFAULT NULL COMMENT '特殊约定(大文本)',
  2362 + `attachment_file_ids` TEXT DEFAULT NULL COMMENT '附件文件ID集合(多文件,逗号分隔)',
  2363 + `attachment_file_names` TEXT DEFAULT NULL COMMENT '附件文件名称集合(多文件,逗号分隔)',
  2364 + `approval_status` VARCHAR(32) DEFAULT NULL COMMENT '审核状态',
  2365 + `originator_id` VARCHAR(32) DEFAULT NULL COMMENT '发起人ID(计划的创建人)',
  2366 + `originator_name` VARCHAR(64) DEFAULT NULL COMMENT '发起人(显示)',
  2367 + `deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除 0否 1是',
  2368 + `create_by_id` VARCHAR(32) DEFAULT NULL COMMENT '创建人ID',
  2369 + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人',
  2370 + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  2371 + `update_by_id` VARCHAR(32) DEFAULT NULL COMMENT '更新人ID',
  2372 + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人',
  2373 + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  2374 + PRIMARY KEY (`id`),
  2375 + KEY `idx_pc_plan_id` (`procurement_plan_id`),
  2376 + KEY `idx_pc_supplier_id` (`supplier_id`),
  2377 + KEY `idx_pc_company_id` (`company_short_id`),
  2378 + KEY `idx_pc_sign_time` (`sign_time`),
  2379 + KEY `idx_pc_create_time` (`create_time`),
  2380 + KEY `idx_pc_approval_status` (`approval_status`)
  2381 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='采购合同主表';
  2382 +
  2383 +
  2384 +CREATE TABLE `procurement_contract_line`
  2385 +(
  2386 + `id` VARCHAR(32) NOT NULL COMMENT '主键ID',
  2387 + `contract_id` VARCHAR(32) NOT NULL COMMENT '采购合同主表ID',
  2388 + `plan_line_id` VARCHAR(32) DEFAULT NULL COMMENT '原采购计划明细行ID',
  2389 + `invoice_product_name` VARCHAR(200) NOT NULL COMMENT '名称',
  2390 + `product_id` VARCHAR(32) NOT NULL COMMENT '规格型号ID',
  2391 + `quantity` DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '数量',
  2392 + `unit_price` DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '单价',
  2393 + `excluding_tax_amount` DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '不含税金额 = 合计金额 / 1.13',
  2394 + `tax_amount` DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '税额 = 合计金额 - 不含税金额',
  2395 + `total_amount` DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '合计金额 = 数量 * 单价',
  2396 + `delivery_time` DATE NOT NULL COMMENT '交货时间',
  2397 + `item_id` VARCHAR(32) DEFAULT NULL COMMENT '前端行标识',
  2398 + `create_by_id` VARCHAR(32) DEFAULT NULL COMMENT '创建人ID',
  2399 + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人',
  2400 + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  2401 + `update_by_id` VARCHAR(32) DEFAULT NULL COMMENT '更新人ID',
  2402 + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人',
  2403 + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  2404 + PRIMARY KEY (`id`),
  2405 + KEY `idx_pcl_contract_id` (`contract_id`),
  2406 + KEY `idx_pcl_product_id` (`product_id`)
  2407 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='采购合同明细表';
  1 +package com.lframework.xingyun.sc.bo.procurement;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.lframework.starter.common.constants.StringPool;
  5 +import com.lframework.starter.web.core.bo.BaseBo;
  6 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContract;
  7 +import io.swagger.annotations.ApiModelProperty;
  8 +import java.math.BigDecimal;
  9 +import java.time.LocalDate;
  10 +import java.time.LocalDateTime;
  11 +import java.util.List;
  12 +import lombok.Data;
  13 +
  14 +@Data
  15 +public class GetProcurementContractBo extends BaseBo<ProcurementContract> {
  16 +
  17 + @ApiModelProperty("ID")
  18 + private String id;
  19 +
  20 + @ApiModelProperty("关联采购计划ID")
  21 + private String procurementPlanId;
  22 +
  23 + @ApiModelProperty("投诉编码(计划单编号)")
  24 + private String procurementPlanCode;
  25 +
  26 + @ApiModelProperty("供方ID(供应商ID)")
  27 + private String supplierId;
  28 +
  29 + @ApiModelProperty("供方名称")
  30 + private String supplierName;
  31 +
  32 + @ApiModelProperty("需方ID(公司简称ID)")
  33 + private String companyShortId;
  34 +
  35 + @ApiModelProperty("需方(公司全称)")
  36 + private String companyFullName;
  37 +
  38 + @ApiModelProperty("签订地点")
  39 + private String signPlace;
  40 +
  41 + @ApiModelProperty("签订时间")
  42 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  43 + private LocalDate signTime;
  44 +
  45 + @ApiModelProperty("交货时间")
  46 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  47 + private LocalDate deliveryTime;
  48 +
  49 + @ApiModelProperty("结算比例%")
  50 + private BigDecimal settlementRatio;
  51 +
  52 + @ApiModelProperty("合计数量")
  53 + private BigDecimal totalQuantity;
  54 +
  55 + @ApiModelProperty("合计不含税金额")
  56 + private BigDecimal totalExcludingTaxAmount;
  57 +
  58 + @ApiModelProperty("合计税额")
  59 + private BigDecimal totalTaxAmount;
  60 +
  61 + @ApiModelProperty("合计金额")
  62 + private BigDecimal totalAmount;
  63 +
  64 + @ApiModelProperty("特殊约定")
  65 + private String specialAgreement;
  66 +
  67 + @ApiModelProperty("附件文件ID集合")
  68 + private String attachmentFileIds;
  69 +
  70 + @ApiModelProperty("附件文件名称集合")
  71 + private String attachmentFileNames;
  72 +
  73 + @ApiModelProperty("审核状态 AUDIT/PASS/REFUSE/CANCEL")
  74 + private String approvalStatus;
  75 +
  76 + @ApiModelProperty("是否展示审核按钮 前端用")
  77 + private Boolean showExamine;
  78 +
  79 + @ApiModelProperty("是否展示审核详情按钮")
  80 + private Boolean showExamineDetail;
  81 +
  82 + @ApiModelProperty("发起人ID")
  83 + private String originatorId;
  84 +
  85 + @ApiModelProperty("发起人")
  86 + private String originatorName;
  87 +
  88 + @ApiModelProperty("创建人")
  89 + private String createBy;
  90 +
  91 + @ApiModelProperty("创建时间")
  92 + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN)
  93 + private LocalDateTime createTime;
  94 +
  95 + @ApiModelProperty("明细列表")
  96 + private List<GetProcurementContractLineBo> procurementContractLineList;
  97 +
  98 + public GetProcurementContractBo() {
  99 + super();
  100 + }
  101 +
  102 + public GetProcurementContractBo(ProcurementContract dto) {
  103 + super(dto);
  104 + }
  105 +}
  1 +package com.lframework.xingyun.sc.bo.procurement;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.lframework.starter.common.constants.StringPool;
  5 +import com.lframework.starter.web.core.bo.BaseBo;
  6 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContractLine;
  7 +import io.swagger.annotations.ApiModelProperty;
  8 +import java.math.BigDecimal;
  9 +import java.time.LocalDate;
  10 +import lombok.Data;
  11 +
  12 +@Data
  13 +public class GetProcurementContractLineBo extends BaseBo<ProcurementContractLine> {
  14 +
  15 + @ApiModelProperty("主键ID")
  16 + private String id;
  17 +
  18 + @ApiModelProperty("采购合同主表ID")
  19 + private String contractId;
  20 +
  21 + @ApiModelProperty("序号(从1开始 手动赋值) 非持久化")
  22 + private Integer seq;
  23 +
  24 + @ApiModelProperty("原采购计划明细行ID(追溯用)")
  25 + private String planLineId;
  26 +
  27 + @ApiModelProperty("名称(开票品名)")
  28 + private String invoiceProductName;
  29 +
  30 + @ApiModelProperty("规格型号ID(品种ID)")
  31 + private String productId;
  32 +
  33 + @ApiModelProperty("规格型号(品种名称)")
  34 + private String productName;
  35 +
  36 + @ApiModelProperty("数量")
  37 + private BigDecimal quantity;
  38 +
  39 + @ApiModelProperty("单价(实际采购价)")
  40 + private BigDecimal unitPrice;
  41 +
  42 + @ApiModelProperty("不含税金额 = 合计金额 / 1.13")
  43 + private BigDecimal excludingTaxAmount;
  44 +
  45 + @ApiModelProperty("税额 = 合计金额 - 不含税金额")
  46 + private BigDecimal taxAmount;
  47 +
  48 + @ApiModelProperty("合计金额 = 数量 * 单价")
  49 + private BigDecimal totalAmount;
  50 +
  51 + @ApiModelProperty("交货时间")
  52 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  53 + private LocalDate deliveryTime;
  54 +
  55 + @ApiModelProperty("前端行标识")
  56 + private String itemId;
  57 +
  58 + public GetProcurementContractLineBo() {
  59 + super();
  60 + }
  61 +
  62 + public GetProcurementContractLineBo(ProcurementContractLine dto) {
  63 + super(dto);
  64 + }
  65 +}
  1 +package com.lframework.xingyun.sc.bo.procurement;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.lframework.starter.common.constants.StringPool;
  5 +import com.lframework.starter.web.core.bo.BaseBo;
  6 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContract;
  7 +import io.swagger.annotations.ApiModelProperty;
  8 +import java.math.BigDecimal;
  9 +import java.time.LocalDate;
  10 +import java.time.LocalDateTime;
  11 +import lombok.Data;
  12 +
  13 +@Data
  14 +public class QueryProcurementContractBo extends BaseBo<ProcurementContract> {
  15 +
  16 + @ApiModelProperty("ID")
  17 + private String id;
  18 +
  19 + @ApiModelProperty("关联采购计划ID")
  20 + private String procurementPlanId;
  21 +
  22 + @ApiModelProperty("投诉编码(计划单编号)")
  23 + private String procurementPlanCode;
  24 +
  25 + @ApiModelProperty("供方ID(供应商ID)")
  26 + private String supplierId;
  27 +
  28 + @ApiModelProperty("供方名称")
  29 + private String supplierName;
  30 +
  31 + @ApiModelProperty("需方ID(公司简称ID)")
  32 + private String companyShortId;
  33 +
  34 + @ApiModelProperty("需方(公司全称)")
  35 + private String companyFullName;
  36 +
  37 + @ApiModelProperty("签订地点")
  38 + private String signPlace;
  39 +
  40 + @ApiModelProperty("签订时间")
  41 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  42 + private LocalDate signTime;
  43 +
  44 + @ApiModelProperty("交货时间")
  45 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  46 + private LocalDate deliveryTime;
  47 +
  48 + @ApiModelProperty("结算比例%")
  49 + private BigDecimal settlementRatio;
  50 +
  51 + @ApiModelProperty("合计数量")
  52 + private BigDecimal totalQuantity;
  53 +
  54 + @ApiModelProperty("合计不含税金额")
  55 + private BigDecimal totalExcludingTaxAmount;
  56 +
  57 + @ApiModelProperty("合计税额")
  58 + private BigDecimal totalTaxAmount;
  59 +
  60 + @ApiModelProperty("合计金额")
  61 + private BigDecimal totalAmount;
  62 +
  63 + @ApiModelProperty("审核状态 AUDIT/PASS/REFUSE/CANCEL")
  64 + private String approvalStatus;
  65 +
  66 + @ApiModelProperty("是否展示审核按钮 前端用")
  67 + private Boolean showExamine;
  68 +
  69 + @ApiModelProperty("是否展示审核详情按钮")
  70 + private Boolean showExamineDetail;
  71 +
  72 + @ApiModelProperty("发起人ID")
  73 + private String originatorId;
  74 +
  75 + @ApiModelProperty("发起人")
  76 + private String originatorName;
  77 +
  78 + @ApiModelProperty("创建人")
  79 + private String createBy;
  80 +
  81 + @ApiModelProperty("创建时间")
  82 + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN)
  83 + private LocalDateTime createTime;
  84 +
  85 + public QueryProcurementContractBo() {
  86 + super();
  87 + }
  88 +
  89 + public QueryProcurementContractBo(ProcurementContract dto) {
  90 + super(dto);
  91 + }
  92 +}
@@ -22,6 +22,7 @@ import com.lframework.xingyun.sc.procurement.entity.ProcurementDomesticCustomerC @@ -22,6 +22,7 @@ import com.lframework.xingyun.sc.procurement.entity.ProcurementDomesticCustomerC
22 import com.lframework.xingyun.sc.procurement.entity.ProcurementForeignTradeCredit; 22 import com.lframework.xingyun.sc.procurement.entity.ProcurementForeignTradeCredit;
23 import com.lframework.xingyun.sc.procurement.service.change.ProcurementPlanChangeService; 23 import com.lframework.xingyun.sc.procurement.service.change.ProcurementPlanChangeService;
24 import com.lframework.xingyun.sc.procurement.service.coordination.CoordinationSummaryApprovalService; 24 import com.lframework.xingyun.sc.procurement.service.coordination.CoordinationSummaryApprovalService;
  25 +import com.lframework.xingyun.sc.procurement.service.contract.ProcurementContractService;
25 import com.lframework.xingyun.sc.procurement.service.credit.ProcurementDomesticCustomerCreditService; 26 import com.lframework.xingyun.sc.procurement.service.credit.ProcurementDomesticCustomerCreditService;
26 import com.lframework.xingyun.sc.procurement.service.credit.ProcurementForeignTradeCreditService; 27 import com.lframework.xingyun.sc.procurement.service.credit.ProcurementForeignTradeCreditService;
27 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanService; 28 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanService;
@@ -168,6 +169,8 @@ public class BusinessDataHandlerServiceImpl implements BusinessDataHandlerServic @@ -168,6 +169,8 @@ public class BusinessDataHandlerServiceImpl implements BusinessDataHandlerServic
168 private ProcurementPlanReplenishService procurementPlanReplenishService; 169 private ProcurementPlanReplenishService procurementPlanReplenishService;
169 @Resource 170 @Resource
170 private CoordinationSummaryApprovalService coordinationSummaryApprovalService; 171 private CoordinationSummaryApprovalService coordinationSummaryApprovalService;
  172 + @Resource
  173 + private ProcurementContractService procurementContractService;
171 174
172 175
173 176
@@ -270,6 +273,9 @@ public class BusinessDataHandlerServiceImpl implements BusinessDataHandlerServic @@ -270,6 +273,9 @@ public class BusinessDataHandlerServiceImpl implements BusinessDataHandlerServic
270 case "XT_APPROVAL": 273 case "XT_APPROVAL":
271 handleCoordinationSummaryApprovalData(flowStatus, businessId); 274 handleCoordinationSummaryApprovalData(flowStatus, businessId);
272 break; 275 break;
  276 + case "PROCUREMENT_CONTRACT":
  277 + handleProcurementContractData(flowStatus, businessId);
  278 + break;
273 default: 279 default:
274 break; 280 break;
275 } 281 }
@@ -1208,4 +1214,15 @@ public class BusinessDataHandlerServiceImpl implements BusinessDataHandlerServic @@ -1208,4 +1214,15 @@ public class BusinessDataHandlerServiceImpl implements BusinessDataHandlerServic
1208 coordinationSummaryApprovalService.updateApprovalStatus(businessId, "REFUSE"); 1214 coordinationSummaryApprovalService.updateApprovalStatus(businessId, "REFUSE");
1209 } 1215 }
1210 } 1216 }
  1217 +
  1218 + private void handleProcurementContractData(String flowStatus, String businessId) {
  1219 + if (FlowInstanceStatus.APPROVE_PASS.getCode().equals(flowStatus)
  1220 + || FlowInstanceStatus.FINISH.getCode().equals(flowStatus)) {
  1221 + procurementContractService.updateApprovalStatus(businessId, "PASS");
  1222 + } else if (FlowInstanceStatus.REVOKE.getCode().equals(flowStatus)
  1223 + || FlowInstanceStatus.REFUSE.getCode().equals(flowStatus)
  1224 + || FlowInstanceStatus.TERMINATION.getCode().equals(flowStatus)) {
  1225 + procurementContractService.updateApprovalStatus(businessId, "REFUSE");
  1226 + }
  1227 + }
1211 } 1228 }
  1 +package com.lframework.xingyun.sc.procurement.controller.contract;
  2 +
  3 +import cn.hutool.core.io.resource.ClassPathResource;
  4 +import com.lframework.starter.common.exceptions.impl.DefaultClientException;
  5 +import com.lframework.starter.web.core.annotations.security.HasPermission;
  6 +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder;
  7 +import com.lframework.starter.web.core.controller.DefaultBaseController;
  8 +import com.lframework.starter.web.core.components.resp.InvokeResult;
  9 +import com.lframework.starter.web.core.components.resp.PageResult;
  10 +import com.lframework.xingyun.sc.bo.procurement.*;
  11 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContract;
  12 +import com.lframework.xingyun.sc.procurement.service.contract.ProcurementContractService;
  13 +import com.lframework.xingyun.sc.procurement.vo.contract.CreateProcurementContractVo;
  14 +import com.lframework.xingyun.sc.procurement.vo.contract.QueryProcurementContractVo;
  15 +import com.lframework.xingyun.sc.procurement.vo.contract.UpdateProcurementContractVo;
  16 +import com.lframework.xingyun.sc.utils.ExcelUtil;
  17 +import io.swagger.annotations.Api;
  18 +import io.swagger.annotations.ApiImplicitParam;
  19 +import io.swagger.annotations.ApiOperation;
  20 +import javax.annotation.Resource;
  21 +import javax.servlet.http.HttpServletResponse;
  22 +import javax.validation.Valid;
  23 +import javax.validation.constraints.NotBlank;
  24 +import lombok.extern.slf4j.Slf4j;
  25 +import org.apache.commons.collections4.CollectionUtils;
  26 +import org.apache.poi.ss.usermodel.Sheet;
  27 +import org.apache.poi.ss.usermodel.Workbook;
  28 +import org.apache.poi.util.IOUtils;
  29 +import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  30 +import org.springframework.validation.annotation.Validated;
  31 +import org.springframework.web.bind.annotation.*;
  32 +
  33 +import java.io.FileNotFoundException;
  34 +import java.io.IOException;
  35 +import java.io.InputStream;
  36 +import java.time.format.DateTimeFormatter;
  37 +import java.util.HashMap;
  38 +import java.util.List;
  39 +import java.util.Map;
  40 +
  41 +@Api(tags = "采购合同管理")
  42 +@Slf4j
  43 +@Validated
  44 +@RestController
  45 +@RequestMapping("/procurement/contract")
  46 +public class ProcurementContractController extends DefaultBaseController {
  47 +
  48 + @Resource
  49 + private ProcurementContractService procurementContractService;
  50 +
  51 + @ApiOperation("分页查询采购合同")
  52 + @HasPermission({"agreement-manage:domestic-agreement:query"})
  53 + @GetMapping("/query")
  54 + public InvokeResult<PageResult<ProcurementContract>> query(
  55 + @Valid QueryProcurementContractVo vo) {
  56 + return InvokeResultBuilder.success(procurementContractService.query(getPageIndex(vo), getPageSize(vo), vo));
  57 + }
  58 +
  59 + @ApiOperation("查询采购合同详情")
  60 + @ApiImplicitParam(value = "ID", name = "id", paramType = "path", required = true)
  61 + @HasPermission({"agreement-manage:domestic-agreement:query","agreement-manage:domestic-agreement:review"})
  62 + @GetMapping("")
  63 + public InvokeResult<GetProcurementContractBo> findById(@NotBlank(message = "ID不能为空!") String id) {
  64 + return InvokeResultBuilder.success(procurementContractService.findDetail(id));
  65 + }
  66 +
  67 + @ApiOperation("新增采购合同(草稿)")
  68 + @HasPermission({"agreement-manage:domestic-agreement:add"})
  69 + @PostMapping("/create")
  70 + public InvokeResult<String> create(@RequestBody @Valid CreateProcurementContractVo vo) {
  71 + return InvokeResultBuilder.success(procurementContractService.create(vo));
  72 + }
  73 +
  74 + @ApiOperation("修改采购合同")
  75 + @HasPermission({"agreement-manage:domestic-agreement:modify","agreement-manage:domestic-agreement:approve"})
  76 + @PutMapping("/update")
  77 + public InvokeResult<Void> update(@RequestBody @Valid UpdateProcurementContractVo vo) {
  78 + procurementContractService.update(vo);
  79 + return InvokeResultBuilder.success();
  80 + }
  81 +
  82 + @ApiOperation("取消采购合同")
  83 + @ApiImplicitParam(value = "ID", name = "id", paramType = "path", required = true)
  84 + @HasPermission({"agreement-manage:domestic-agreement:cancel"})
  85 + @PutMapping("/cancel")
  86 + public InvokeResult<Void> cancel(@NotBlank(message = "ID不能为空!") String id) {
  87 + procurementContractService.cancel(id);
  88 + return InvokeResultBuilder.success();
  89 + }
  90 +
  91 + @ApiOperation("提交审核采购合同")
  92 + @ApiImplicitParam(value = "ID", name = "id", paramType = "path", required = true)
  93 + @HasPermission({"agreement-manage:domestic-agreement:submit"})
  94 + @PutMapping("/submit")
  95 + public InvokeResult<Void> submit(@NotBlank(message = "ID不能为空!") String id) {
  96 + procurementContractService.submit(id);
  97 + return InvokeResultBuilder.success();
  98 + }
  99 +
  100 + @ApiOperation("根据计划ID废弃采购合同(逻辑删除 deleted=1)")
  101 + @ApiImplicitParam(value = "ID", name = "id", paramType = "path", required = true)
  102 + @HasPermission({"agreement-manage:domestic-agreement:delete"})
  103 + @DeleteMapping("/delete")
  104 + public InvokeResult<Void> delete(@NotBlank(message = "ID不能为空!") String id) {
  105 + procurementContractService.deleteById(id);
  106 + return InvokeResultBuilder.success();
  107 + }
  108 +
  109 + @ApiOperation("打印合同")
  110 + @GetMapping("/export")
  111 + public void export(@NotBlank(message = "ID不能为空!") String id,
  112 + HttpServletResponse response) throws IOException {
  113 +
  114 +// GetProcurementContractBo detail = procurementContractService.findDetail(id);
  115 +// if (detail == null) {
  116 +// throw new DefaultClientException("采购合同不存在!");
  117 +// }
  118 +// ExcelUtil.setupResponse(response, detail.getProcurementPlanCode() + "_" + detail.getCompanyFullName() + "-采购合同.xlsx");
  119 +//
  120 +// ClassPathResource templateResource = new ClassPathResource("templates/planTemplate.xlsx");
  121 +// try {
  122 +// try (InputStream inputStream = templateResource.getStream();
  123 +// Workbook workbook = new XSSFWorkbook(inputStream)) {
  124 +// try {
  125 +// DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  126 +// Sheet sheet = workbook.getSheetAt(0);
  127 +//
  128 +// List<GetProcurementContractLineBo> procurementContractLineList = detail.getProcurementContractLineList();
  129 +// int planStartRow = 4; // 合同计划子表开始行,可根据模板调整
  130 +// if (CollectionUtils.isNotEmpty(procurementContractLineList)) {
  131 +// for (int i = 0; i < procurementContractLineList.size(); i++) {
  132 +// GetProcurementContractLineBo line = procurementContractLineList.get(i);
  133 +// ExcelUtil.setCellValue(sheet, planStartRow, 0, line.getProductName());
  134 +// ExcelUtil.setCellValue(sheet, planStartRow, 1, line.getMaterialType());
  135 +// ExcelUtil.setCellValue(sheet, planStartRow, 2, line.getQuantity());
  136 +// ExcelUtil.setCellValue(sheet, planStartRow, 3, line.getActualPurchasePrice());
  137 +// ExcelUtil.setCellValue(sheet, planStartRow, 4, line.getIncludingShippingPrice());
  138 +// ExcelUtil.setCellValue(sheet, planStartRow, 5, line.getPriceListPrices());
  139 +// ExcelUtil.setCellValue(sheet, planStartRow, 6, line.getCoordinationRange());
  140 +// ExcelUtil.setCellValue(sheet, planStartRow, 7, line.getEstimatedLoss());
  141 +// ExcelUtil.setCellValue(sheet, planStartRow, 8, line.getWorkshopName());
  142 +// planStartRow++;
  143 +// }
  144 +// }
  145 +//
  146 +// Map<String, Object> planDataMap = new HashMap<>();
  147 +// planDataMap.put("code", nvl(plan.getCode()) + nvl(plan.getPlanType()));
  148 +// planDataMap.put("companyShortName", nvl(plan.getCompanyShortName()));
  149 +// planDataMap.put("workshopName", nvl(plan.getWorkshopName()));
  150 +// planDataMap.put("purchaseDepartmentName", nvl(plan.getPurchaseDepartmentName()));
  151 +// planDataMap.put("regionName", nvl(plan.getRegionName()));
  152 +// planDataMap.put("date", plan.getDate() == null ? "" : plan.getDate().format(dateFormatter));
  153 +// planDataMap.put("supplierName", nvl(plan.getSupplierName()));
  154 +// planDataMap.put("commodityBuyout", plan.getCommodityBuyout() == null ? "□" : (plan.getCommodityBuyout() ? "■" : "□"));
  155 +// planDataMap.put("qualityBuyout", plan.getQualityBuyout() == null ? "□" : (plan.getQualityBuyout() ? "■" : "□"));
  156 +// planDataMap.put("quantityBuyout", plan.getQuantityBuyout() == null ? "□" : (plan.getQuantityBuyout() ? "■" : "□"));
  157 +// planDataMap.put("doorDelivery", plan.getDoorDelivery() == null ? "□" : (plan.getDoorDelivery() ? "■" : "□"));
  158 +// planDataMap.put("longTermOperation", plan.getLongTermOperation() == null ? "□" : (plan.getLongTermOperation() ? "■" : "□"));
  159 +// planDataMap.put("terminalCustomer", plan.getTerminalCustomer() == null ? "□" : (plan.getTerminalCustomer() ? "■" : "□"));
  160 +// planDataMap.put("shippingCostB", plan.getShippingCost() == null ? "□" : "■");
  161 +// planDataMap.put("shippingCost", formatDecimal(plan.getShippingCost()));
  162 +// planDataMap.put("loadingFeeB", plan.getLoadingFee() == null ? "□" : "■");
  163 +// planDataMap.put("loadingFee", formatDecimal(plan.getLoadingFee()));
  164 +// planDataMap.put("otherExpenseSettlement", plan.getOtherExpenseSettlement() == null ? "□" : (plan.getOtherExpenseSettlement() ? "■" : "□"));
  165 +// planDataMap.put("remark", nvl(plan.getRemark()));
  166 +// planDataMap.put("totalQuantity", formatDecimal(plan.getTotalQuantity()));
  167 +// planDataMap.put("coordinationReason", nvl(plan.getCoordinationReason()));
  168 +// planDataMap.put("invoiceTypeStatus", nvl(plan.getInvoiceTypeStatus()));
  169 +// planDataMap.put("invoiceProductName", nvl(plan.getInvoiceProductName()));
  170 +// //制单人
  171 +// planDataMap.put("createBy", nvl(plan.getCreateBy()));
  172 +// //采购处主管
  173 +// planDataMap.put("purchaseDeptName", nvl(plan.getPurchaseDeptName()));
  174 +// //供应管理科主管
  175 +// planDataMap.put("managementDeptName", nvl(plan.getManagementDeptName()));
  176 +// //供应部主管
  177 +// planDataMap.put("supplyManagerName", nvl(plan.getSupplyManagerName()));
  178 +// //营销分管
  179 +// planDataMap.put("marketingManagerName", nvl(plan.getMarketingManagerName()));
  180 +// //总经理
  181 +// planDataMap.put("generalManagerName", nvl(plan.getGeneralManagerName()));
  182 +// ExcelUtil.processTemplateSheet(sheet, planDataMap);
  183 +//
  184 +// workbook.write(response.getOutputStream());
  185 +// response.getOutputStream().flush();
  186 +// } finally {
  187 +// IOUtils.closeQuietly(workbook);
  188 +// }
  189 +//
  190 +// } catch (FileNotFoundException e) {
  191 +// throw new RuntimeException("模板文件不存在: templates/planAndBuyoutTemplate.xlsx", e);
  192 +// } catch (IOException e) {
  193 +// throw new RuntimeException("无法读取模板文件: templates/planAndBuyoutTemplate.xlsx", e);
  194 +// }
  195 +// } catch (Exception e) {
  196 +// log.error("导出采购合同失败, id={}, {}", id, e.getMessage(), e);
  197 +// throw e;
  198 +// }
  199 + }
  200 +}
  1 +package com.lframework.xingyun.sc.procurement.entity.contract;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.FieldFill;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import com.lframework.starter.web.core.dto.BaseDto;
  7 +import com.lframework.starter.web.core.entity.BaseEntity;
  8 +import lombok.Data;
  9 +import lombok.NoArgsConstructor;
  10 +import java.math.BigDecimal;
  11 +import java.time.LocalDate;
  12 +import java.time.LocalDateTime;
  13 +
  14 +@Data
  15 +@TableName("procurement_contract")
  16 +@NoArgsConstructor
  17 +public class ProcurementContract extends BaseEntity implements BaseDto {
  18 +
  19 + private static final long serialVersionUID = 1L;
  20 +
  21 + private String id;
  22 +
  23 + private String procurementPlanId;
  24 +
  25 + private String procurementPlanCode;
  26 +
  27 + private String supplierId;
  28 +
  29 + @TableField(exist = false)
  30 + private String supplierName;
  31 +
  32 + private String companyShortId;
  33 +
  34 + @TableField(exist = false)
  35 + private String companyFullName;
  36 +
  37 + private String signPlace;
  38 +
  39 + private LocalDate signTime;
  40 +
  41 + private LocalDate deliveryTime;
  42 +
  43 + private BigDecimal settlementRatio;
  44 +
  45 + private BigDecimal totalQuantity;
  46 +
  47 + private BigDecimal totalExcludingTaxAmount;
  48 +
  49 + private BigDecimal totalTaxAmount;
  50 +
  51 + private BigDecimal totalAmount;
  52 +
  53 + private String specialAgreement;
  54 +
  55 + private String attachmentFileIds;
  56 +
  57 + private String attachmentFileNames;
  58 +
  59 + private String approvalStatus;
  60 +
  61 + @TableField(exist = false)
  62 + private Boolean showExamine;
  63 +
  64 + @TableField(exist = false)
  65 + private Boolean showExamineDetail;
  66 +
  67 + private String originatorId;
  68 +
  69 + private String originatorName;
  70 +
  71 + private Integer deleted;
  72 +
  73 + @TableField(fill = FieldFill.INSERT)
  74 + private String createById;
  75 +
  76 + @TableField(fill = FieldFill.INSERT)
  77 + private String createBy;
  78 +
  79 + @TableField(fill = FieldFill.INSERT_UPDATE)
  80 + private String updateById;
  81 +
  82 + @TableField(fill = FieldFill.INSERT_UPDATE)
  83 + private String updateBy;
  84 +
  85 + @TableField(fill = FieldFill.INSERT)
  86 + private LocalDateTime createTime;
  87 +
  88 + @TableField(fill = FieldFill.INSERT_UPDATE)
  89 + private LocalDateTime updateTime;
  90 +}
  1 +package com.lframework.xingyun.sc.procurement.entity.contract;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.FieldFill;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import com.lframework.starter.web.core.dto.BaseDto;
  7 +import com.lframework.starter.web.core.entity.BaseEntity;
  8 +import lombok.Data;
  9 +import java.math.BigDecimal;
  10 +import java.time.LocalDate;
  11 +import java.time.LocalDateTime;
  12 +
  13 +@Data
  14 +@TableName("procurement_contract_line")
  15 +public class ProcurementContractLine extends BaseEntity implements BaseDto {
  16 +
  17 + private static final long serialVersionUID = 1L;
  18 +
  19 + private String id;
  20 +
  21 + private String contractId;
  22 +
  23 + private String planLineId;
  24 +
  25 + private String invoiceProductName;
  26 +
  27 + private String productId;
  28 +
  29 + @TableField(exist = false)
  30 + private String productName;
  31 +
  32 + private BigDecimal quantity;
  33 +
  34 + private BigDecimal unitPrice;
  35 +
  36 + private BigDecimal excludingTaxAmount;
  37 +
  38 + private BigDecimal taxAmount;
  39 +
  40 + private BigDecimal totalAmount;
  41 +
  42 + private LocalDate deliveryTime;
  43 +
  44 + private String itemId;
  45 +
  46 + @TableField(fill = FieldFill.INSERT)
  47 + private String createById;
  48 +
  49 + @TableField(fill = FieldFill.INSERT)
  50 + private String createBy;
  51 +
  52 + @TableField(fill = FieldFill.INSERT_UPDATE)
  53 + private String updateById;
  54 +
  55 + @TableField(fill = FieldFill.INSERT_UPDATE)
  56 + private String updateBy;
  57 +
  58 + @TableField(fill = FieldFill.INSERT)
  59 + private LocalDateTime createTime;
  60 +
  61 + @TableField(fill = FieldFill.INSERT_UPDATE)
  62 + private LocalDateTime updateTime;
  63 +}
@@ -39,6 +39,7 @@ import com.lframework.xingyun.sc.procurement.mappers.change.ProcurementPlanChang @@ -39,6 +39,7 @@ import com.lframework.xingyun.sc.procurement.mappers.change.ProcurementPlanChang
39 import com.lframework.xingyun.sc.procurement.service.buyout.ProcurementBuyoutApplyService; 39 import com.lframework.xingyun.sc.procurement.service.buyout.ProcurementBuyoutApplyService;
40 import com.lframework.xingyun.sc.procurement.service.change.ProcurementPlanChangeLineService; 40 import com.lframework.xingyun.sc.procurement.service.change.ProcurementPlanChangeLineService;
41 import com.lframework.xingyun.sc.procurement.service.change.ProcurementPlanChangeService; 41 import com.lframework.xingyun.sc.procurement.service.change.ProcurementPlanChangeService;
  42 +import com.lframework.xingyun.sc.procurement.service.contract.ProcurementContractService;
42 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanLineService; 43 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanLineService;
43 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanService; 44 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanService;
44 import com.lframework.xingyun.sc.procurement.vo.buyout.CreateProcurementBuyoutApplyVo; 45 import com.lframework.xingyun.sc.procurement.vo.buyout.CreateProcurementBuyoutApplyVo;
@@ -47,6 +48,8 @@ import com.lframework.xingyun.sc.procurement.vo.change.CreateProcurementPlanChan @@ -47,6 +48,8 @@ import com.lframework.xingyun.sc.procurement.vo.change.CreateProcurementPlanChan
47 import com.lframework.xingyun.sc.procurement.vo.change.QueryProcurementPlanChangeVo; 48 import com.lframework.xingyun.sc.procurement.vo.change.QueryProcurementPlanChangeVo;
48 import com.lframework.xingyun.sc.procurement.vo.change.UpdateProcurementPlanChangeLineVo; 49 import com.lframework.xingyun.sc.procurement.vo.change.UpdateProcurementPlanChangeLineVo;
49 import com.lframework.xingyun.sc.procurement.vo.change.UpdateProcurementPlanChangeVo; 50 import com.lframework.xingyun.sc.procurement.vo.change.UpdateProcurementPlanChangeVo;
  51 +import com.lframework.xingyun.sc.procurement.vo.contract.CreateProcurementContractLineVo;
  52 +import com.lframework.xingyun.sc.procurement.vo.contract.CreateProcurementContractVo;
50 import com.lframework.xingyun.sc.procurement.vo.plan.CreateProcurementPlanVo; 53 import com.lframework.xingyun.sc.procurement.vo.plan.CreateProcurementPlanVo;
51 import com.lframework.xingyun.sc.procurement.vo.plan.ProcurementPlanLineVo; 54 import com.lframework.xingyun.sc.procurement.vo.plan.ProcurementPlanLineVo;
52 import java.math.BigDecimal; 55 import java.math.BigDecimal;
@@ -83,6 +86,8 @@ public class ProcurementPlanChangeServiceImpl extends @@ -83,6 +86,8 @@ public class ProcurementPlanChangeServiceImpl extends
83 private WorkshopService workshopService; 86 private WorkshopService workshopService;
84 @Resource 87 @Resource
85 private FlowTaskWrapperMapper flowTaskWrapperMapper; 88 private FlowTaskWrapperMapper flowTaskWrapperMapper;
  89 + @Resource
  90 + private ProcurementContractService procurementContractService;
86 91
87 92
88 private static final List<String> PROCESS_STATUSES = Arrays.asList( 93 private static final List<String> PROCESS_STATUSES = Arrays.asList(
@@ -200,7 +205,6 @@ public class ProcurementPlanChangeServiceImpl extends @@ -200,7 +205,6 @@ public class ProcurementPlanChangeServiceImpl extends
200 vo1.setProcurementPlanId(procurementPlan.getId()); 205 vo1.setProcurementPlanId(procurementPlan.getId());
201 procurementBuyoutApplyService.create(vo1); 206 procurementBuyoutApplyService.create(vo1);
202 } 207 }
203 - //todo 作废合同,生成新合同  
204 } else { 208 } else {
205 //没有子计划 209 //没有子计划
206 //修改 开票品名 公司名称 另付运费 210 //修改 开票品名 公司名称 另付运费
@@ -220,6 +224,39 @@ public class ProcurementPlanChangeServiceImpl extends @@ -220,6 +224,39 @@ public class ProcurementPlanChangeServiceImpl extends
220 vo1.setProcurementPlanId(vo.getProcurementPlanId()); 224 vo1.setProcurementPlanId(vo.getProcurementPlanId());
221 procurementBuyoutApplyService.create(vo1); 225 procurementBuyoutApplyService.create(vo1);
222 } 226 }
  227 + //作废合同
  228 + procurementContractService.deleteById(plan.getId());
  229 + //生成新合同
  230 + ProcurementPlan procurementPlan = procurementPlanService.getById(plan.getId());
  231 + CreateProcurementContractVo contractVo = new CreateProcurementContractVo();
  232 + contractVo.setProcurementPlanId(procurementPlan.getId());
  233 + contractVo.setProcurementPlanCode(procurementPlan.getCode());
  234 + contractVo.setSupplierId(procurementPlan.getSupplierId());
  235 + contractVo.setCompanyShortId(procurementPlan.getCompanyShortId());
  236 + contractVo.setSignTime(procurementPlan.getDate());
  237 + contractVo.setDeliveryTime(procurementPlan.getDeliveryDate());
  238 + contractVo.setSettlementRatio(procurementPlan.getSettlementRatio());
  239 + contractVo.setOriginatorId(procurementPlan.getCreateById());
  240 + contractVo.setOriginatorName(procurementPlan.getCreateBy());
  241 + List<CreateProcurementContractLineVo> contractLineVoList = new ArrayList<>();
  242 + List<ProcurementPlanLine> lineList = procurementPlanLineService.getByProcurementPlanId(plan.getId());
  243 + if (CollectionUtil.isEmpty(lineList)) {
  244 + throw new InputErrorException("采购计划明细没有数据!");
  245 + }
  246 + for (ProcurementPlanLine line : lineList) {
  247 + CreateProcurementContractLineVo lineVo = new CreateProcurementContractLineVo();
  248 + lineVo.setPlanLineId(line.getId());
  249 + lineVo.setItemId(IdUtil.getId());
  250 + //todo 开票品名逻辑需要修改
  251 + lineVo.setInvoiceProductName(procurementPlan.getInvoiceProductName());
  252 + lineVo.setProductId(line.getProductId());
  253 + lineVo.setQuantity(line.getQuantity());
  254 + lineVo.setUnitPrice(line.getActualPurchasePrice());
  255 + lineVo.setDeliveryTime(procurementPlan.getDeliveryDate());
  256 + contractLineVoList.add(lineVo);
  257 + }
  258 + contractVo.setProcurementContractLineList(contractLineVoList);
  259 + procurementContractService.create(contractVo);
223 } 260 }
224 return planChange.getId(); 261 return planChange.getId();
225 } else { 262 } else {
@@ -628,7 +665,39 @@ public class ProcurementPlanChangeServiceImpl extends @@ -628,7 +665,39 @@ public class ProcurementPlanChangeServiceImpl extends
628 .set(ProcurementPlan::getApprovalPassTime, LocalDateTime.now()) 665 .set(ProcurementPlan::getApprovalPassTime, LocalDateTime.now())
629 .eq(ProcurementPlan::getId, planId)); 666 .eq(ProcurementPlan::getId, planId));
630 667
631 - //todo 废弃原合同;生成新合同 668 + //作废合同
  669 + procurementContractService.deleteById(planId);
  670 + //生成新合同
  671 + ProcurementPlan procurementPlan = procurementPlanService.getById(planId);
  672 + CreateProcurementContractVo contractVo = new CreateProcurementContractVo();
  673 + contractVo.setProcurementPlanId(procurementPlan.getId());
  674 + contractVo.setProcurementPlanCode(procurementPlan.getCode());
  675 + contractVo.setSupplierId(procurementPlan.getSupplierId());
  676 + contractVo.setCompanyShortId(procurementPlan.getCompanyShortId());
  677 + contractVo.setSignTime(procurementPlan.getDate());
  678 + contractVo.setDeliveryTime(procurementPlan.getDeliveryDate());
  679 + contractVo.setSettlementRatio(procurementPlan.getSettlementRatio());
  680 + contractVo.setOriginatorId(procurementPlan.getCreateById());
  681 + contractVo.setOriginatorName(procurementPlan.getCreateBy());
  682 + List<CreateProcurementContractLineVo> contractLineVoList = new ArrayList<>();
  683 + List<ProcurementPlanLine> lineList = procurementPlanLineService.getByProcurementPlanId(planId);
  684 + if (CollectionUtil.isEmpty(lineList)) {
  685 + throw new InputErrorException("采购计划明细没有数据!");
  686 + }
  687 + for (ProcurementPlanLine line : lineList) {
  688 + CreateProcurementContractLineVo lineVo = new CreateProcurementContractLineVo();
  689 + lineVo.setPlanLineId(line.getId());
  690 + lineVo.setItemId(IdUtil.getId());
  691 + //todo 开票品名逻辑需要修改
  692 + lineVo.setInvoiceProductName(procurementPlan.getInvoiceProductName());
  693 + lineVo.setProductId(line.getProductId());
  694 + lineVo.setQuantity(line.getQuantity());
  695 + lineVo.setUnitPrice(line.getActualPurchasePrice());
  696 + lineVo.setDeliveryTime(procurementPlan.getDeliveryDate());
  697 + contractLineVoList.add(lineVo);
  698 + }
  699 + contractVo.setProcurementContractLineList(contractLineVoList);
  700 + procurementContractService.create(contractVo);
632 } else if ("REFUSE".equals(approvalStatus)) { 701 } else if ("REFUSE".equals(approvalStatus)) {
633 List<SysRole> roles = sysRoleService.getByUserId(entity.getCreateById()); 702 List<SysRole> roles = sysRoleService.getByUserId(entity.getCreateById());
634 List<String> roleCodes = CollectionUtil.isEmpty(roles) ? new java.util.ArrayList<>() 703 List<String> roleCodes = CollectionUtil.isEmpty(roles) ? new java.util.ArrayList<>()
  1 +package com.lframework.xingyun.sc.procurement.impl.contract;
  2 +
  3 +import com.lframework.starter.web.core.impl.BaseMpServiceImpl;
  4 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContractLine;
  5 +import com.lframework.xingyun.sc.procurement.mappers.contract.ProcurementContractLineMapper;
  6 +import com.lframework.xingyun.sc.procurement.service.contract.ProcurementContractLineService;
  7 +import java.util.List;
  8 +import org.springframework.stereotype.Service;
  9 +
  10 +@Service
  11 +public class ProcurementContractLineServiceImpl
  12 + extends BaseMpServiceImpl<ProcurementContractLineMapper, ProcurementContractLine>
  13 + implements ProcurementContractLineService {
  14 +
  15 + @Override
  16 + public List<ProcurementContractLine> getByContractId(String contractId) {
  17 + return getBaseMapper().getByContractId(contractId);
  18 + }
  19 +
  20 + @Override
  21 + public void deleteByContractId(String contractId) {
  22 + getBaseMapper().deleteByContractId(contractId);
  23 + }
  24 +}
  1 +package com.lframework.xingyun.sc.procurement.impl.contract;
  2 +
  3 +import cn.hutool.core.bean.BeanUtil;
  4 +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  5 +import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  6 +import com.github.pagehelper.PageInfo;
  7 +import com.lframework.starter.bpm.dto.FlowTaskDto;
  8 +import com.lframework.starter.bpm.entity.FlowInstanceWrapper;
  9 +import com.lframework.starter.bpm.service.FlowInstanceWrapperService;
  10 +import com.lframework.starter.bpm.vo.flow.task.QueryTodoTaskListVo;
  11 +import com.lframework.starter.common.exceptions.impl.DefaultClientException;
  12 +import com.lframework.starter.common.exceptions.impl.InputErrorException;
  13 +import com.lframework.starter.common.utils.Assert;
  14 +import com.lframework.starter.common.utils.CollectionUtil;
  15 +import com.lframework.starter.common.utils.StringUtil;
  16 +import com.lframework.starter.web.core.annotations.oplog.OpLog;
  17 +import com.lframework.starter.web.core.components.resp.PageResult;
  18 +import com.lframework.starter.web.core.components.security.SecurityUtil;
  19 +import com.lframework.starter.web.core.impl.BaseMpServiceImpl;
  20 +import com.lframework.starter.web.core.utils.*;
  21 +import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
  22 +import com.lframework.xingyun.sc.bo.procurement.GetProcurementContractBo;
  23 +import com.lframework.xingyun.sc.bo.procurement.GetProcurementContractLineBo;
  24 +import com.lframework.xingyun.sc.enums.CustomerDevelopStatus;
  25 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContract;
  26 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContractLine;
  27 +import com.lframework.xingyun.sc.procurement.mappers.contract.ProcurementContractMapper;
  28 +import com.lframework.xingyun.sc.procurement.service.contract.ProcurementContractLineService;
  29 +import com.lframework.xingyun.sc.procurement.service.contract.ProcurementContractService;
  30 +import com.lframework.xingyun.sc.procurement.vo.contract.CreateProcurementContractLineVo;
  31 +import com.lframework.xingyun.sc.procurement.vo.contract.CreateProcurementContractVo;
  32 +import com.lframework.xingyun.sc.procurement.vo.contract.QueryProcurementContractVo;
  33 +import com.lframework.xingyun.sc.procurement.vo.contract.UpdateProcurementContractLineVo;
  34 +import com.lframework.xingyun.sc.procurement.vo.contract.UpdateProcurementContractVo;
  35 +import java.math.BigDecimal;
  36 +import java.math.RoundingMode;
  37 +import java.util.*;
  38 +import java.util.stream.Collectors;
  39 +import javax.annotation.Resource;
  40 +import org.apache.commons.lang3.StringUtils;
  41 +import org.springframework.stereotype.Service;
  42 +import org.springframework.transaction.annotation.Transactional;
  43 +
  44 +@Service
  45 +public class ProcurementContractServiceImpl
  46 + extends BaseMpServiceImpl<ProcurementContractMapper, ProcurementContract>
  47 + implements ProcurementContractService {
  48 +
  49 + private static final String BPM_FLAG = "PROCUREMENT_CONTRACT";
  50 + private static final BigDecimal TAX_RATE_DIVISOR = new BigDecimal("1.13");
  51 +
  52 + @Resource
  53 + private ProcurementContractLineService lineService;
  54 + @Resource
  55 + private ProcurementContractMapper contractMapper;
  56 + @Resource
  57 + private FlowInstanceWrapperService flowInstanceWrapperService;
  58 + @Resource
  59 + private com.lframework.starter.bpm.mappers.FlowTaskWrapperMapper flowTaskWrapperMapper;
  60 +
  61 + @Override
  62 + public PageResult<ProcurementContract> query(Integer pageIndex, Integer pageSize,
  63 + QueryProcurementContractVo vo) {
  64 + Assert.greaterThanZero(pageIndex);
  65 + Assert.greaterThanZero(pageSize);
  66 +
  67 + PageHelperUtil.startPage(pageIndex, pageSize);
  68 + List<ProcurementContract> datas = this.query(vo);
  69 + if (CollectionUtil.isNotEmpty(datas)) {
  70 + fillShowExamineInfo(datas);
  71 + }
  72 + return PageResultUtil.convert(new PageInfo<>(datas));
  73 + }
  74 +
  75 + @Override
  76 + public List<ProcurementContract> query(QueryProcurementContractVo vo) {
  77 + return contractMapper.query(vo);
  78 + }
  79 +
  80 + @Override
  81 + public GetProcurementContractBo findDetail(String id) {
  82 + if (StringUtil.isBlank(id)) {
  83 + throw new InputErrorException("ID不能为空!");
  84 + }
  85 +
  86 + ProcurementContract entity = contractMapper.findById(id);
  87 + if (entity == null) {
  88 + throw new DefaultClientException("采购合同不存在!");
  89 + }
  90 + fillShowExamineInfo(Collections.singletonList(entity));
  91 +
  92 + GetProcurementContractBo bo = new GetProcurementContractBo(entity);
  93 + bo.convert(entity);
  94 +
  95 + List<ProcurementContractLine> lines = lineService.getByContractId(id);
  96 + List<GetProcurementContractLineBo> detailBoList = new ArrayList<>();
  97 + if (!CollectionUtil.isEmpty(lines)) {
  98 + for (int i = 0; i < lines.size(); i++) {
  99 + ProcurementContractLine line = lines.get(i);
  100 + GetProcurementContractLineBo lineBo = new GetProcurementContractLineBo(line);
  101 + lineBo.setSeq(i + 1);
  102 + detailBoList.add(lineBo);
  103 + }
  104 + }
  105 + bo.setProcurementContractLineList(detailBoList);
  106 +
  107 + return bo;
  108 + }
  109 +
  110 + @Override
  111 + @Transactional(rollbackFor = Exception.class)
  112 + @OpLog(type = OtherOpLogType.class, name = "创建采购合同,ID:{}", params = {"#result"})
  113 + public String create(CreateProcurementContractVo vo) {
  114 + Assert.notNull(vo.getSignTime(), "签订时间不能为空!");
  115 + Assert.notNull(vo.getSettlementRatio(), "结算比例不能为空!");
  116 + if (CollectionUtil.isEmpty(vo.getProcurementContractLineList())) {
  117 + throw new DefaultClientException("明细不能为空!");
  118 + }
  119 +
  120 + ProcurementContract main = new ProcurementContract();
  121 + BeanUtil.copyProperties(vo, main);
  122 + main.setId(IdUtil.getId());
  123 + main.setApprovalStatus(null);
  124 + if (StringUtil.isBlank(main.getSignPlace())) {
  125 + main.setSignPlace("芜湖市");
  126 + }
  127 + main.setDeleted(0);
  128 +
  129 + recalcMainAndLines(main, vo.getProcurementContractLineList());
  130 +
  131 + List<ProcurementContractLine> saveLines = buildSaveLines(main.getId(), vo.getProcurementContractLineList(), null);
  132 +
  133 + this.save(main);
  134 + if (!saveLines.isEmpty()) {
  135 + lineService.saveBatch(saveLines);
  136 + }
  137 +
  138 + OpLogUtil.setVariable("id", main.getId());
  139 + OpLogUtil.setExtra(main);
  140 +
  141 + return main.getId();
  142 + }
  143 +
  144 + @Override
  145 + @Transactional(rollbackFor = Exception.class)
  146 + @OpLog(type = OtherOpLogType.class, name = "修改采购合同,ID:{}", params = {"#vo.id"})
  147 + public void update(UpdateProcurementContractVo vo) {
  148 + Assert.notBlank(vo.getId(), "ID不能为空!");
  149 + ProcurementContract oldEntity = this.getById(vo.getId());
  150 + if (oldEntity == null || (oldEntity.getDeleted() != null && oldEntity.getDeleted() == 1)) {
  151 + throw new DefaultClientException("采购合同不存在或已废弃!");
  152 + }
  153 +
  154 + ProcurementContract update = new ProcurementContract();
  155 + BeanUtil.copyProperties(vo, update);
  156 + update.setId(vo.getId());
  157 + if (StringUtil.isBlank(update.getSignPlace())) {
  158 + update.setSignPlace("芜湖市");
  159 + }
  160 +
  161 + recalcMainAndLines(update, vo.getProcurementContractLineList());
  162 +
  163 + this.updateById(update);
  164 +
  165 + saveOrUpdateLines(vo.getId(), vo.getProcurementContractLineList());
  166 +
  167 + OpLogUtil.setVariable("id", vo.getId());
  168 + OpLogUtil.setExtra(oldEntity);
  169 + }
  170 +
  171 + @Override
  172 + @Transactional(rollbackFor = Exception.class)
  173 + @OpLog(type = OtherOpLogType.class, name = "取消采购合同,ID:{}", params = {"#id"})
  174 + public void cancel(String id) {
  175 + Assert.notBlank(id);
  176 + ProcurementContract entity = this.getById(id);
  177 + if (entity == null || (entity.getDeleted() != null && entity.getDeleted() == 1)) {
  178 + throw new DefaultClientException("采购合同不存在或已废弃!");
  179 + }
  180 +
  181 + this.update(Wrappers.lambdaUpdate(ProcurementContract.class)
  182 + .set(ProcurementContract::getApprovalStatus, "CANCEL")
  183 + .eq(ProcurementContract::getId, id));
  184 +
  185 + OpLogUtil.setVariable("id", id);
  186 + OpLogUtil.setExtra(entity);
  187 + }
  188 +
  189 + @Override
  190 + @Transactional(rollbackFor = Exception.class)
  191 + @OpLog(type = OtherOpLogType.class, name = "提交采购合同审核,ID:{}", params = {"#id"})
  192 + public void submit(String id) {
  193 + ProcurementContract entity = contractMapper.findById(id);
  194 + if (entity == null || (entity.getDeleted() != null && entity.getDeleted() == 1)) {
  195 + throw new DefaultClientException("采购合同不存在或已废弃!");
  196 + }
  197 +
  198 + flowInstanceWrapperService.startInstance(BPM_FLAG, id, BPM_FLAG, entity);
  199 +
  200 + OpLogUtil.setVariable("id", id);
  201 + OpLogUtil.setExtra(entity);
  202 + }
  203 +
  204 + @Override
  205 + @Transactional(rollbackFor = Exception.class)
  206 + @OpLog(type = OtherOpLogType.class, name = "根据计划ID废弃采购合同,ID:{}", params = {"#id"})
  207 + public void deleteById(String id) {
  208 + Assert.notBlank(id);
  209 + ProcurementContract entity = this.getById(id);
  210 + if (entity == null) {
  211 + return;
  212 + }
  213 +
  214 + this.update(Wrappers.lambdaUpdate(ProcurementContract.class)
  215 + .set(ProcurementContract::getDeleted, 1)
  216 + .eq(ProcurementContract::getProcurementPlanId, id));
  217 +
  218 + OpLogUtil.setVariable("id", id);
  219 + OpLogUtil.setExtra(entity);
  220 + }
  221 +
  222 + @Override
  223 + @Transactional(rollbackFor = Exception.class)
  224 + @OpLog(type = OtherOpLogType.class, name = "更新采购合同审核状态,ID:{}", params = {"#id"})
  225 + public void updateApprovalStatus(String id, String approvalStatus) {
  226 + if (StringUtil.isBlank(id) || StringUtil.isBlank(approvalStatus)) {
  227 + throw new InputErrorException("ID、审核状态不能为空!");
  228 + }
  229 +
  230 + ProcurementContract entity = this.getById(id);
  231 + if (entity == null) {
  232 + throw new DefaultClientException("采购合同不存在!");
  233 + }
  234 +
  235 + if ("PASS".equals(approvalStatus)) {
  236 + LambdaUpdateWrapper<ProcurementContract> updateWrapper =
  237 + Wrappers.lambdaUpdate(ProcurementContract.class)
  238 + .set(ProcurementContract::getApprovalStatus, "PASS")
  239 + .eq(ProcurementContract::getId, id);
  240 + this.update(updateWrapper);
  241 + } else if ("REFUSE".equals(approvalStatus)) {
  242 + LambdaUpdateWrapper<ProcurementContract> updateWrapper =
  243 + Wrappers.lambdaUpdate(ProcurementContract.class)
  244 + .set(ProcurementContract::getApprovalStatus, "REFUSE")
  245 + .eq(ProcurementContract::getId, id);
  246 + this.update(updateWrapper);
  247 + }
  248 +
  249 + OpLogUtil.setVariable("id", id);
  250 + OpLogUtil.setExtra(entity);
  251 + }
  252 +
  253 + private void recalcMainAndLines(ProcurementContract main,
  254 + List<? extends CreateProcurementContractLineVo> lineList) {
  255 + BigDecimal totalQty = BigDecimal.ZERO;
  256 + BigDecimal totalExcludingTax = BigDecimal.ZERO;
  257 + BigDecimal totalTax = BigDecimal.ZERO;
  258 + BigDecimal totalAmt = BigDecimal.ZERO;
  259 +
  260 + if (!CollectionUtil.isEmpty(lineList)) {
  261 + for (CreateProcurementContractLineVo lineVo : lineList) {
  262 + BigDecimal qty = lineVo.getQuantity() == null ? BigDecimal.ZERO : lineVo.getQuantity();
  263 + BigDecimal price = lineVo.getUnitPrice() == null ? BigDecimal.ZERO : lineVo.getUnitPrice();
  264 +
  265 + BigDecimal lineTotal = qty.multiply(price).setScale(4, RoundingMode.HALF_UP);
  266 + BigDecimal excludingTax = lineTotal.divide(TAX_RATE_DIVISOR, 4, RoundingMode.HALF_UP);
  267 + BigDecimal tax = lineTotal.subtract(excludingTax).setScale(4, RoundingMode.HALF_UP);
  268 +
  269 + lineVo.setTotalAmount(lineTotal);
  270 + lineVo.setExcludingTaxAmount(excludingTax);
  271 + lineVo.setTaxAmount(tax);
  272 +
  273 + totalQty = totalQty.add(qty);
  274 + totalExcludingTax = totalExcludingTax.add(excludingTax);
  275 + totalTax = totalTax.add(tax);
  276 + totalAmt = totalAmt.add(lineTotal);
  277 + }
  278 + }
  279 +
  280 + main.setTotalQuantity(totalQty);
  281 + main.setTotalExcludingTaxAmount(totalExcludingTax);
  282 + main.setTotalTaxAmount(totalTax);
  283 + main.setTotalAmount(totalAmt);
  284 + }
  285 +
  286 + private List<ProcurementContractLine> buildSaveLines(String contractId,
  287 + List<? extends CreateProcurementContractLineVo> lineList,
  288 + Map<String, ProcurementContractLine> oldLineMap) {
  289 + List<ProcurementContractLine> result = new ArrayList<>();
  290 + if (CollectionUtil.isEmpty(lineList)) {
  291 + return result;
  292 + }
  293 +
  294 + for (CreateProcurementContractLineVo lineVo : lineList) {
  295 + ProcurementContractLine saveLine;
  296 + if (StringUtil.isNotBlank(lineVo.getId()) && oldLineMap != null) {
  297 + ProcurementContractLine oldLine = oldLineMap.get(lineVo.getId());
  298 + saveLine = BeanUtil.copyProperties(lineVo, ProcurementContractLine.class);
  299 + if (oldLine != null) {
  300 + saveLine.setId(oldLine.getId());
  301 + } else {
  302 + saveLine.setId(IdUtil.getId());
  303 + }
  304 + } else {
  305 + saveLine = BeanUtil.copyProperties(lineVo, ProcurementContractLine.class);
  306 + saveLine.setId(IdUtil.getId());
  307 + }
  308 + saveLine.setContractId(contractId);
  309 +
  310 + BigDecimal qty = lineVo.getQuantity() == null ? BigDecimal.ZERO : lineVo.getQuantity();
  311 + BigDecimal price = lineVo.getUnitPrice() == null ? BigDecimal.ZERO : lineVo.getUnitPrice();
  312 + BigDecimal lineTotal = qty.multiply(price).setScale(4, RoundingMode.HALF_UP);
  313 + BigDecimal excludingTax = lineTotal.divide(TAX_RATE_DIVISOR, 4, RoundingMode.HALF_UP);
  314 + BigDecimal tax = lineTotal.subtract(excludingTax).setScale(4, RoundingMode.HALF_UP);
  315 + saveLine.setTotalAmount(lineTotal);
  316 + saveLine.setExcludingTaxAmount(excludingTax);
  317 + saveLine.setTaxAmount(tax);
  318 +
  319 + result.add(saveLine);
  320 + }
  321 + return result;
  322 + }
  323 +
  324 + private void saveOrUpdateLines(String contractId,
  325 + List<? extends CreateProcurementContractLineVo> lineList) {
  326 + String finalContractId = contractId;
  327 + if (StringUtil.isBlank(finalContractId) && !CollectionUtil.isEmpty(lineList)) {
  328 + finalContractId = lineList.stream()
  329 + .filter(l -> l != null && l instanceof UpdateProcurementContractLineVo
  330 + && StringUtil.isNotBlank(((UpdateProcurementContractLineVo) l).getContractId()))
  331 + .map(l -> ((UpdateProcurementContractLineVo) l).getContractId())
  332 + .findFirst().orElse(null);
  333 + }
  334 + if (StringUtil.isBlank(finalContractId)) {
  335 + throw new DefaultClientException("采购合同ID为空,无法保存明细!");
  336 + }
  337 + if (CollectionUtil.isEmpty(lineList)) {
  338 + List<ProcurementContractLine> old = lineService.getByContractId(finalContractId);
  339 + if (CollectionUtil.isNotEmpty(old)) {
  340 + lineService.removeByIds(old.stream().map(ProcurementContractLine::getId).collect(Collectors.toList()));
  341 + }
  342 + return;
  343 + }
  344 +
  345 + List<ProcurementContractLine> oldLineList = lineService.getByContractId(finalContractId);
  346 + Map<String, ProcurementContractLine> oldLineMap = CollectionUtil.isEmpty(oldLineList)
  347 + ? Collections.emptyMap()
  348 + : oldLineList.stream().collect(Collectors.toMap(ProcurementContractLine::getId, v -> v));
  349 +
  350 + List<String> existIdList = new ArrayList<>(lineList.size());
  351 + int orderNo = 0; // 每次保存全部重新分配排序号 从1开始连续
  352 + for (CreateProcurementContractLineVo lineVo : lineList) {
  353 + if (lineVo == null) continue;
  354 + ++orderNo;
  355 + BigDecimal qty = lineVo.getQuantity() == null ? BigDecimal.ZERO : lineVo.getQuantity();
  356 + BigDecimal price = lineVo.getUnitPrice() == null ? BigDecimal.ZERO : lineVo.getUnitPrice();
  357 + BigDecimal lineTotal = qty.multiply(price).setScale(4, RoundingMode.HALF_UP);
  358 + BigDecimal excludingTax = lineTotal.divide(TAX_RATE_DIVISOR, 4, RoundingMode.HALF_UP);
  359 + BigDecimal tax = lineTotal.subtract(excludingTax).setScale(4, RoundingMode.HALF_UP);
  360 +
  361 + if (lineVo instanceof UpdateProcurementContractLineVo
  362 + && StringUtil.isNotBlank(lineVo.getId())) {
  363 + UpdateProcurementContractLineVo updateLineVo = (UpdateProcurementContractLineVo) lineVo;
  364 + ProcurementContractLine oldLine = oldLineMap.get(updateLineVo.getId());
  365 + if (oldLine == null) {
  366 + throw new DefaultClientException("采购合同明细不存在或不属于当前采购合同!");
  367 + }
  368 + existIdList.add(updateLineVo.getId());
  369 + if (StringUtil.isBlank(updateLineVo.getPlanLineId())) {
  370 + updateLineVo.setPlanLineId(oldLine.getPlanLineId());
  371 + }
  372 + if (StringUtil.isBlank(updateLineVo.getItemId())) {
  373 + updateLineVo.setItemId(oldLine.getItemId());
  374 + }
  375 + LambdaUpdateWrapper<ProcurementContractLine> updateWrapper = new LambdaUpdateWrapper<>(ProcurementContractLine.class);
  376 + updateWrapper.eq(ProcurementContractLine::getId, updateLineVo.getId())
  377 + .set(ProcurementContractLine::getContractId, finalContractId)
  378 + .set(ProcurementContractLine::getPlanLineId, updateLineVo.getPlanLineId())
  379 + .set(ProcurementContractLine::getInvoiceProductName, updateLineVo.getInvoiceProductName())
  380 + .set(ProcurementContractLine::getProductId, updateLineVo.getProductId())
  381 + .set(ProcurementContractLine::getQuantity, qty)
  382 + .set(ProcurementContractLine::getUnitPrice, price)
  383 + .set(ProcurementContractLine::getExcludingTaxAmount, excludingTax)
  384 + .set(ProcurementContractLine::getTaxAmount, tax)
  385 + .set(ProcurementContractLine::getTotalAmount, lineTotal)
  386 + .set(ProcurementContractLine::getDeliveryTime, updateLineVo.getDeliveryTime())
  387 + .set(ProcurementContractLine::getItemId, updateLineVo.getItemId());
  388 + lineService.update(updateWrapper);
  389 + } else {
  390 + ProcurementContractLine createLine = BeanUtil.copyProperties(lineVo, ProcurementContractLine.class);
  391 + createLine.setId(IdUtil.getId());
  392 + createLine.setContractId(finalContractId);
  393 + createLine.setQuantity(qty);
  394 + createLine.setUnitPrice(price);
  395 + createLine.setTotalAmount(lineTotal);
  396 + createLine.setExcludingTaxAmount(excludingTax);
  397 + createLine.setTaxAmount(tax);
  398 + lineService.save(createLine);
  399 + existIdList.add(createLine.getId());
  400 + }
  401 + }
  402 +
  403 + List<ProcurementContractLine> safeOldLineList = oldLineList == null ? Collections.emptyList() : oldLineList;
  404 + List<String> needDeleteIdList = safeOldLineList.stream()
  405 + .map(ProcurementContractLine::getId)
  406 + .filter(oldLineId -> !existIdList.contains(oldLineId))
  407 + .collect(Collectors.toList());
  408 + if (CollectionUtil.isNotEmpty(needDeleteIdList)) {
  409 + lineService.removeByIds(needDeleteIdList);
  410 + }
  411 + }
  412 +
  413 + private void fillShowExamineInfo(List<ProcurementContract> datas) {
  414 + if (CollectionUtil.isEmpty(datas)) {
  415 + return;
  416 + }
  417 +
  418 + List<ProcurementContract> validDatas = datas.stream()
  419 + .filter(Objects::nonNull)
  420 + .collect(Collectors.toList());
  421 + if (CollectionUtil.isEmpty(validDatas)) {
  422 + return;
  423 + }
  424 +
  425 + List<String> businessIds = validDatas.stream()
  426 + .map(ProcurementContract::getId)
  427 + .collect(Collectors.toList());
  428 +
  429 + List<FlowInstanceWrapper> flowList = flowInstanceWrapperService.getFlowByBusinessIdList(businessIds);
  430 + Set<String> flowBusinessIdSet = CollectionUtil.isNotEmpty(flowList)
  431 + ? flowList.stream().map(FlowInstanceWrapper::getBusinessId).collect(Collectors.toSet())
  432 + : new HashSet<>();
  433 +
  434 + List<FlowTaskDto> todoFlowTaskList = flowTaskWrapperMapper.queryTodoList(
  435 + new QueryTodoTaskListVo(), SecurityUtil.getCurrentUser().getId());
  436 + Set<String> todoBusinessIdSet = CollectionUtil.isNotEmpty(todoFlowTaskList)
  437 + ? todoFlowTaskList.stream().map(FlowTaskDto::getBusinessId).collect(Collectors.toSet())
  438 + : new HashSet<>();
  439 +
  440 + for (ProcurementContract contract : validDatas) {
  441 + boolean hasFlow = flowBusinessIdSet.contains(contract.getId());
  442 + boolean hasTodo = todoBusinessIdSet.contains(contract.getId());
  443 + contract.setShowExamineDetail(hasFlow && StringUtils.isNotBlank(contract.getApprovalStatus()));
  444 + contract.setShowExamine(hasTodo && CustomerDevelopStatus.AUDIT.name().equals(contract.getApprovalStatus()));
  445 + }
  446 + }
  447 +}
@@ -37,10 +37,13 @@ import com.lframework.xingyun.sc.procurement.entity.ProcurementPlan; @@ -37,10 +37,13 @@ import com.lframework.xingyun.sc.procurement.entity.ProcurementPlan;
37 import com.lframework.xingyun.sc.procurement.entity.ProcurementPlanLine; 37 import com.lframework.xingyun.sc.procurement.entity.ProcurementPlanLine;
38 import com.lframework.xingyun.sc.procurement.mappers.plan.ProcurementPlanMapper; 38 import com.lframework.xingyun.sc.procurement.mappers.plan.ProcurementPlanMapper;
39 import com.lframework.xingyun.sc.procurement.service.buyout.ProcurementBuyoutApplyService; 39 import com.lframework.xingyun.sc.procurement.service.buyout.ProcurementBuyoutApplyService;
  40 +import com.lframework.xingyun.sc.procurement.service.contract.ProcurementContractService;
40 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanLineService; 41 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanLineService;
41 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanService; 42 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanService;
42 import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationService; 43 import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationService;
43 import com.lframework.xingyun.sc.procurement.vo.buyout.CreateProcurementBuyoutApplyVo; 44 import com.lframework.xingyun.sc.procurement.vo.buyout.CreateProcurementBuyoutApplyVo;
  45 +import com.lframework.xingyun.sc.procurement.vo.contract.CreateProcurementContractLineVo;
  46 +import com.lframework.xingyun.sc.procurement.vo.contract.CreateProcurementContractVo;
44 import com.lframework.xingyun.sc.procurement.vo.plan.CreateProcurementPlanVo; 47 import com.lframework.xingyun.sc.procurement.vo.plan.CreateProcurementPlanVo;
45 import com.lframework.xingyun.sc.procurement.vo.plan.ProcurementPlanLineVo; 48 import com.lframework.xingyun.sc.procurement.vo.plan.ProcurementPlanLineVo;
46 import com.lframework.xingyun.sc.procurement.vo.plan.ProcurementPlanUpdateLineVo; 49 import com.lframework.xingyun.sc.procurement.vo.plan.ProcurementPlanUpdateLineVo;
@@ -81,6 +84,8 @@ public class ProcurementPlanServiceImpl extends BaseMpServiceImpl<ProcurementPla @@ -81,6 +84,8 @@ public class ProcurementPlanServiceImpl extends BaseMpServiceImpl<ProcurementPla
81 private SysRoleService sysRoleService; 84 private SysRoleService sysRoleService;
82 @Resource 85 @Resource
83 private SalesmanQuotationService salesmanQuotationService; 86 private SalesmanQuotationService salesmanQuotationService;
  87 + @Resource
  88 + private ProcurementContractService procurementContractService;
84 89
85 @Override 90 @Override
86 public PageResult<ProcurementPlan> query(Integer pageIndex, Integer pageSize, 91 public PageResult<ProcurementPlan> query(Integer pageIndex, Integer pageSize,
@@ -334,7 +339,37 @@ public class ProcurementPlanServiceImpl extends BaseMpServiceImpl<ProcurementPla @@ -334,7 +339,37 @@ public class ProcurementPlanServiceImpl extends BaseMpServiceImpl<ProcurementPla
334 if (procurementPlan == null || procurementPlan.getCompanyShortId() == null) { 339 if (procurementPlan == null || procurementPlan.getCompanyShortId() == null) {
335 throw new InputErrorException("请先补充公司名称!"); 340 throw new InputErrorException("请先补充公司名称!");
336 } 341 }
337 - //todo 后面合同模块需要补充生成合同的逻辑 342 + //生成合同
  343 + CreateProcurementContractVo vo = new CreateProcurementContractVo();
  344 + vo.setProcurementPlanId(procurementPlan.getId());
  345 + vo.setProcurementPlanCode(procurementPlan.getCode());
  346 + vo.setSupplierId(procurementPlan.getSupplierId());
  347 + vo.setCompanyShortId(procurementPlan.getCompanyShortId());
  348 + vo.setSignTime(procurementPlan.getDate());
  349 + vo.setDeliveryTime(procurementPlan.getDeliveryDate());
  350 + vo.setSettlementRatio(procurementPlan.getSettlementRatio());
  351 + vo.setOriginatorId(procurementPlan.getCreateById());
  352 + vo.setOriginatorName(procurementPlan.getCreateBy());
  353 + List<CreateProcurementContractLineVo> list = new ArrayList<>();
  354 + List<ProcurementPlanLine> lines = procurementPlanLineService.getByProcurementPlanId(id);
  355 + if (CollectionUtil.isEmpty(lines)) {
  356 + throw new InputErrorException("采购计划明细没有数据!");
  357 + }
  358 + for (ProcurementPlanLine line : lines) {
  359 + CreateProcurementContractLineVo lineVo = new CreateProcurementContractLineVo();
  360 + lineVo.setPlanLineId(line.getId());
  361 + lineVo.setItemId(IdUtil.getId());
  362 + //todo 开票品名逻辑需要修改
  363 + lineVo.setInvoiceProductName(procurementPlan.getInvoiceProductName());
  364 + lineVo.setProductId(line.getProductId());
  365 + lineVo.setQuantity(line.getQuantity());
  366 + lineVo.setUnitPrice(line.getActualPurchasePrice());
  367 + lineVo.setDeliveryTime(procurementPlan.getDeliveryDate());
  368 + list.add(lineVo);
  369 + }
  370 + vo.setProcurementContractLineList(list);
  371 + procurementContractService.create(vo);
  372 +
338 LambdaUpdateWrapper<ProcurementPlan> updateWrapper = Wrappers.lambdaUpdate(ProcurementPlan.class) 373 LambdaUpdateWrapper<ProcurementPlan> updateWrapper = Wrappers.lambdaUpdate(ProcurementPlan.class)
339 .set(ProcurementPlan::getProcessNode, "GYGLKZLGLG") 374 .set(ProcurementPlan::getProcessNode, "GYGLKZLGLG")
340 .set(ProcurementPlan::getProcessStatus, "TO_SPLIT") 375 .set(ProcurementPlan::getProcessStatus, "TO_SPLIT")
@@ -31,18 +31,19 @@ import com.lframework.xingyun.sc.bo.procurement.GetProcurementPlanReplenishBo; @@ -31,18 +31,19 @@ import com.lframework.xingyun.sc.bo.procurement.GetProcurementPlanReplenishBo;
31 import com.lframework.xingyun.sc.bo.procurement.GetProcurementPlanReplenishLineBo; 31 import com.lframework.xingyun.sc.bo.procurement.GetProcurementPlanReplenishLineBo;
32 import com.lframework.xingyun.sc.enums.CustomerDevelopStatus; 32 import com.lframework.xingyun.sc.enums.CustomerDevelopStatus;
33 import com.lframework.xingyun.sc.procurement.entity.ProcurementPlan; 33 import com.lframework.xingyun.sc.procurement.entity.ProcurementPlan;
34 -import com.lframework.xingyun.sc.procurement.entity.ProcurementPlanChange;  
35 -import com.lframework.xingyun.sc.procurement.entity.ProcurementPlanChangeLine;  
36 import com.lframework.xingyun.sc.procurement.entity.ProcurementPlanLine; 34 import com.lframework.xingyun.sc.procurement.entity.ProcurementPlanLine;
37 import com.lframework.xingyun.sc.procurement.entity.replenish.ProcurementPlanReplenish; 35 import com.lframework.xingyun.sc.procurement.entity.replenish.ProcurementPlanReplenish;
38 import com.lframework.xingyun.sc.procurement.entity.replenish.ProcurementPlanReplenishLine; 36 import com.lframework.xingyun.sc.procurement.entity.replenish.ProcurementPlanReplenishLine;
39 import com.lframework.xingyun.sc.procurement.mappers.replenish.ProcurementPlanReplenishMapper; 37 import com.lframework.xingyun.sc.procurement.mappers.replenish.ProcurementPlanReplenishMapper;
40 import com.lframework.xingyun.sc.procurement.service.buyout.ProcurementBuyoutApplyService; 38 import com.lframework.xingyun.sc.procurement.service.buyout.ProcurementBuyoutApplyService;
  39 +import com.lframework.xingyun.sc.procurement.service.contract.ProcurementContractService;
41 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanLineService; 40 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanLineService;
42 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanService; 41 import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanService;
43 import com.lframework.xingyun.sc.procurement.service.replenish.ProcurementPlanReplenishLineService; 42 import com.lframework.xingyun.sc.procurement.service.replenish.ProcurementPlanReplenishLineService;
44 import com.lframework.xingyun.sc.procurement.service.replenish.ProcurementPlanReplenishService; 43 import com.lframework.xingyun.sc.procurement.service.replenish.ProcurementPlanReplenishService;
45 import com.lframework.xingyun.sc.procurement.vo.buyout.CreateProcurementBuyoutApplyVo; 44 import com.lframework.xingyun.sc.procurement.vo.buyout.CreateProcurementBuyoutApplyVo;
  45 +import com.lframework.xingyun.sc.procurement.vo.contract.CreateProcurementContractLineVo;
  46 +import com.lframework.xingyun.sc.procurement.vo.contract.CreateProcurementContractVo;
46 import com.lframework.xingyun.sc.procurement.vo.plan.CreateProcurementPlanVo; 47 import com.lframework.xingyun.sc.procurement.vo.plan.CreateProcurementPlanVo;
47 import com.lframework.xingyun.sc.procurement.vo.plan.ProcurementPlanLineVo; 48 import com.lframework.xingyun.sc.procurement.vo.plan.ProcurementPlanLineVo;
48 import com.lframework.xingyun.sc.procurement.vo.replenish.CreateProcurementPlanReplenishLineVo; 49 import com.lframework.xingyun.sc.procurement.vo.replenish.CreateProcurementPlanReplenishLineVo;
@@ -89,6 +90,8 @@ public class ProcurementPlanReplenishServiceImpl @@ -89,6 +90,8 @@ public class ProcurementPlanReplenishServiceImpl
89 private ProcurementBuyoutApplyService procurementBuyoutApplyService; 90 private ProcurementBuyoutApplyService procurementBuyoutApplyService;
90 @Resource 91 @Resource
91 private FlowTaskWrapperMapper flowTaskWrapperMapper; 92 private FlowTaskWrapperMapper flowTaskWrapperMapper;
  93 + @Resource
  94 + private ProcurementContractService procurementContractService;
92 95
93 96
94 @Override 97 @Override
@@ -396,7 +399,6 @@ public class ProcurementPlanReplenishServiceImpl @@ -396,7 +399,6 @@ public class ProcurementPlanReplenishServiceImpl
396 procurementPlanService.update(planWrapper); 399 procurementPlanService.update(planWrapper);
397 400
398 ProcurementPlanReplenish procurementPlanReplenish = this.getById(id); 401 ProcurementPlanReplenish procurementPlanReplenish = this.getById(id);
399 - //todo 生成新的合同  
400 //生成一个补的主计划 402 //生成一个补的主计划
401 // 归档主计划(ID新生成,保持原code以区分,添加补单标识) 403 // 归档主计划(ID新生成,保持原code以区分,添加补单标识)
402 List<ProcurementPlanReplenishLine> mainLines = 404 List<ProcurementPlanReplenishLine> mainLines =
@@ -444,6 +446,37 @@ public class ProcurementPlanReplenishServiceImpl @@ -444,6 +446,37 @@ public class ProcurementPlanReplenishServiceImpl
444 procurementPlanLineService.saveBatch(archivedMainLines); 446 procurementPlanLineService.saveBatch(archivedMainLines);
445 } 447 }
446 448
  449 + //生成合同
  450 + ProcurementPlan procurementPlan = procurementPlanService.getById(archivedMain.getId());
  451 + CreateProcurementContractVo contractVo = new CreateProcurementContractVo();
  452 + contractVo.setProcurementPlanId(procurementPlan.getId());
  453 + contractVo.setProcurementPlanCode(procurementPlan.getCode());
  454 + contractVo.setSupplierId(procurementPlan.getSupplierId());
  455 + contractVo.setCompanyShortId(procurementPlan.getCompanyShortId());
  456 + contractVo.setSignTime(procurementPlan.getDate());
  457 + contractVo.setDeliveryTime(procurementPlan.getDeliveryDate());
  458 + contractVo.setSettlementRatio(procurementPlan.getSettlementRatio());
  459 + contractVo.setOriginatorId(procurementPlan.getCreateById());
  460 + contractVo.setOriginatorName(procurementPlan.getCreateBy());
  461 + List<CreateProcurementContractLineVo> contractLineVoList = new ArrayList<>();
  462 + List<ProcurementPlanLine> lineList = procurementPlanLineService.getByProcurementPlanId(archivedMain.getId());
  463 + if (CollectionUtil.isEmpty(lineList)) {
  464 + throw new InputErrorException("采购计划明细没有数据!");
  465 + }
  466 + for (ProcurementPlanLine line : lineList) {
  467 + CreateProcurementContractLineVo lineVo = new CreateProcurementContractLineVo();
  468 + lineVo.setPlanLineId(line.getId());
  469 + lineVo.setItemId(IdUtil.getId());
  470 + //todo 开票品名逻辑需要修改
  471 + lineVo.setInvoiceProductName(procurementPlan.getInvoiceProductName());
  472 + lineVo.setProductId(line.getProductId());
  473 + lineVo.setQuantity(line.getQuantity());
  474 + lineVo.setUnitPrice(line.getActualPurchasePrice());
  475 + lineVo.setDeliveryTime(procurementPlan.getDeliveryDate());
  476 + contractLineVoList.add(lineVo);
  477 + }
  478 + contractVo.setProcurementContractLineList(contractLineVoList);
  479 + procurementContractService.create(contractVo);
447 //生成买断操作申请单 480 //生成买断操作申请单
448 if (CollectionUtil.isNotEmpty(allWorkshopIds) && allWorkshopIds.size() == 1) { 481 if (CollectionUtil.isNotEmpty(allWorkshopIds) && allWorkshopIds.size() == 1) {
449 CreateProcurementBuyoutApplyVo vo = new CreateProcurementBuyoutApplyVo(); 482 CreateProcurementBuyoutApplyVo vo = new CreateProcurementBuyoutApplyVo();
  1 +package com.lframework.xingyun.sc.procurement.mappers.contract;
  2 +
  3 +import com.lframework.starter.web.core.mapper.BaseMapper;
  4 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContractLine;
  5 +import java.util.List;
  6 +import org.apache.ibatis.annotations.Param;
  7 +
  8 +public interface ProcurementContractLineMapper extends BaseMapper<ProcurementContractLine> {
  9 +
  10 + List<ProcurementContractLine> getByContractId(@Param("contractId") String contractId);
  11 +
  12 + void deleteByContractId(@Param("contractId") String contractId);
  13 +}
  1 +package com.lframework.xingyun.sc.procurement.mappers.contract;
  2 +
  3 +import com.lframework.starter.web.core.mapper.BaseMapper;
  4 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContract;
  5 +import com.lframework.xingyun.sc.procurement.vo.contract.QueryProcurementContractVo;
  6 +import java.util.List;
  7 +import org.apache.ibatis.annotations.Param;
  8 +
  9 +public interface ProcurementContractMapper extends BaseMapper<ProcurementContract> {
  10 +
  11 + List<ProcurementContract> query(@Param("vo") QueryProcurementContractVo vo);
  12 +
  13 + ProcurementContract findById(@Param("id") String id);
  14 +}
  1 +package com.lframework.xingyun.sc.procurement.service.contract;
  2 +
  3 +import com.baomidou.mybatisplus.extension.service.IService;
  4 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContractLine;
  5 +import java.util.List;
  6 +
  7 +public interface ProcurementContractLineService extends IService<ProcurementContractLine> {
  8 +
  9 + List<ProcurementContractLine> getByContractId(String contractId);
  10 +
  11 + void deleteByContractId(String contractId);
  12 +}
  1 +package com.lframework.xingyun.sc.procurement.service.contract;
  2 +
  3 +import com.baomidou.mybatisplus.extension.service.IService;
  4 +import com.lframework.starter.web.core.components.resp.PageResult;
  5 +import com.lframework.xingyun.sc.bo.procurement.GetProcurementContractBo;
  6 +import com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContract;
  7 +import com.lframework.xingyun.sc.procurement.vo.contract.CreateProcurementContractVo;
  8 +import com.lframework.xingyun.sc.procurement.vo.contract.QueryProcurementContractVo;
  9 +import com.lframework.xingyun.sc.procurement.vo.contract.UpdateProcurementContractVo;
  10 +import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +public interface ProcurementContractService extends IService<ProcurementContract> {
  14 +
  15 + PageResult<ProcurementContract> query(Integer pageIndex, Integer pageSize,
  16 + QueryProcurementContractVo vo);
  17 +
  18 + List<ProcurementContract> query(QueryProcurementContractVo vo);
  19 +
  20 + GetProcurementContractBo findDetail(String id);
  21 +
  22 + String create(CreateProcurementContractVo vo);
  23 +
  24 + void update(UpdateProcurementContractVo vo);
  25 +
  26 + /**
  27 + * 取消
  28 + */
  29 + void cancel(String id);
  30 +
  31 + /**
  32 + * 提交审核
  33 + */
  34 + void submit(String id);
  35 +
  36 + /**
  37 + * 根据计划ID废弃采购合同
  38 + */
  39 + void deleteById(String id);
  40 +
  41 + /**
  42 + * 更新审核状态
  43 + */
  44 + void updateApprovalStatus(String id, String approvalStatus);
  45 +
  46 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.contract;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.lframework.starter.common.constants.StringPool;
  5 +import com.lframework.starter.web.core.vo.BaseVo;
  6 +import io.swagger.annotations.ApiModel;
  7 +import io.swagger.annotations.ApiModelProperty;
  8 +import java.io.Serializable;
  9 +import java.math.BigDecimal;
  10 +import java.time.LocalDate;
  11 +import javax.validation.constraints.Digits;
  12 +import javax.validation.constraints.NotBlank;
  13 +import javax.validation.constraints.NotNull;
  14 +import lombok.Data;
  15 +
  16 +@Data
  17 +@ApiModel("新增采购合同明细行Vo")
  18 +public class CreateProcurementContractLineVo implements BaseVo, Serializable {
  19 +
  20 + private static final long serialVersionUID = 1L;
  21 +
  22 + @ApiModelProperty("ID")
  23 + private String id;
  24 +
  25 + @ApiModelProperty("前端行标识")
  26 + private String itemId;
  27 +
  28 + @ApiModelProperty("原采购计划明细行ID(追溯用)")
  29 + private String planLineId;
  30 +
  31 + @ApiModelProperty(value = "名称(开票品名) 必填", required = true)
  32 + @NotBlank(message = "开票品名不能为空!")
  33 + private String invoiceProductName;
  34 +
  35 + @ApiModelProperty(value = "规格型号ID(品种ID) 必填", required = true)
  36 + @NotBlank(message = "规格型号ID不能为空!")
  37 + private String productId;
  38 +
  39 + @ApiModelProperty(value = "数量 必填", required = true)
  40 + @NotNull(message = "数量不能为空!")
  41 + @Digits(integer = 14, fraction = 4, message = "数量最多支持14位整数和4位小数!")
  42 + private BigDecimal quantity;
  43 +
  44 + @ApiModelProperty(value = "单价(实际采购价) 必填", required = true)
  45 + @NotNull(message = "单价不能为空!")
  46 + @Digits(integer = 14, fraction = 4, message = "单价最多支持14位整数和4位小数!")
  47 + private BigDecimal unitPrice;
  48 +
  49 + @ApiModelProperty("不含税金额 后端重算 可不传")
  50 + private BigDecimal excludingTaxAmount;
  51 +
  52 + @ApiModelProperty("税额 后端重算 可不传")
  53 + private BigDecimal taxAmount;
  54 +
  55 + @ApiModelProperty("合计金额 = 数量 * 单价 后端重算 可不传")
  56 + private BigDecimal totalAmount;
  57 +
  58 + @ApiModelProperty(value = "交货时间 必填", required = true)
  59 + @NotNull(message = "交货时间不能为空!")
  60 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  61 + private LocalDate deliveryTime;
  62 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.contract;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.lframework.starter.common.constants.StringPool;
  5 +import com.lframework.starter.web.core.vo.BaseVo;
  6 +import io.swagger.annotations.ApiModel;
  7 +import io.swagger.annotations.ApiModelProperty;
  8 +import java.io.Serializable;
  9 +import java.math.BigDecimal;
  10 +import java.time.LocalDate;
  11 +import java.util.List;
  12 +import javax.validation.Valid;
  13 +import javax.validation.constraints.NotBlank;
  14 +import javax.validation.constraints.NotNull;
  15 +import lombok.Data;
  16 +import org.hibernate.validator.constraints.Length;
  17 +
  18 +@Data
  19 +@ApiModel("新增采购合同Vo")
  20 +public class CreateProcurementContractVo implements BaseVo, Serializable {
  21 +
  22 + private static final long serialVersionUID = 1L;
  23 +
  24 + @ApiModelProperty(value = "关联采购计划ID 必填", required = true)
  25 + @NotBlank(message = "关联采购计划ID不能为空!")
  26 + private String procurementPlanId;
  27 +
  28 + @ApiModelProperty(value = "投诉编码(计划单编号) 必填", required = true)
  29 + @NotBlank(message = "计划单编号不能为空!")
  30 + private String procurementPlanCode;
  31 +
  32 + @ApiModelProperty(value = "供方ID(供应商ID) 必填", required = true)
  33 + @NotBlank(message = "供方ID不能为空!")
  34 + private String supplierId;
  35 +
  36 + @ApiModelProperty(value = "需方ID(公司简称ID) 必填", required = true)
  37 + @NotBlank(message = "需方ID不能为空!")
  38 + private String companyShortId;
  39 +
  40 + @ApiModelProperty("签订地点(固定 芜湖市)")
  41 + @Length(max = 64, message = "签订地点最多允许64个字符!")
  42 + private String signPlace;
  43 +
  44 + @ApiModelProperty(value = "签订时间 必填", required = true)
  45 + @NotNull(message = "签订时间不能为空!")
  46 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  47 + private LocalDate signTime;
  48 +
  49 + @ApiModelProperty(value = "交货时间 必填", required = true)
  50 + @NotNull(message = "交货时间不能为空!")
  51 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  52 + private LocalDate deliveryTime;
  53 +
  54 + @ApiModelProperty(value = "结算比例% 必填", required = true)
  55 + @NotNull(message = "结算比例不能为空!")
  56 + private BigDecimal settlementRatio;
  57 +
  58 + @ApiModelProperty("合计数量 后端根据明细重算 可不传")
  59 + private BigDecimal totalQuantity;
  60 +
  61 + @ApiModelProperty("合计不含税金额 后端重算 可不传")
  62 + private BigDecimal totalExcludingTaxAmount;
  63 +
  64 + @ApiModelProperty("合计税额 后端重算 可不传")
  65 + private BigDecimal totalTaxAmount;
  66 +
  67 + @ApiModelProperty("合计金额 后端重算 可不传")
  68 + private BigDecimal totalAmount;
  69 +
  70 + @ApiModelProperty("特殊约定(大文本)")
  71 + private String specialAgreement;
  72 +
  73 + @ApiModelProperty("附件文件ID集合(多文件,逗号分隔)")
  74 + private String attachmentFileIds;
  75 +
  76 + @ApiModelProperty("附件文件名称集合(多文件,逗号分隔)")
  77 + private String attachmentFileNames;
  78 +
  79 + @ApiModelProperty("发起人ID(计划的创建人)")
  80 + private String originatorId;
  81 +
  82 + @ApiModelProperty("发起人(显示)")
  83 + private String originatorName;
  84 +
  85 + @ApiModelProperty(value = "明细列表 必填", required = true)
  86 + @Valid
  87 + private List<CreateProcurementContractLineVo> procurementContractLineList;
  88 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.contract;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.lframework.starter.common.constants.StringPool;
  5 +import com.lframework.starter.web.core.vo.SortPageVo;
  6 +import io.swagger.annotations.ApiModel;
  7 +import io.swagger.annotations.ApiModelProperty;
  8 +import java.io.Serializable;
  9 +import java.time.LocalDate;
  10 +import lombok.Data;
  11 +
  12 +@Data
  13 +@ApiModel("查询采购合同")
  14 +public class QueryProcurementContractVo extends SortPageVo implements Serializable {
  15 +
  16 + private static final long serialVersionUID = 1L;
  17 +
  18 + @ApiModelProperty("计划单编号(精确或模糊匹配)")
  19 + private String procurementPlanCode;
  20 +
  21 + @ApiModelProperty("供方名称")
  22 + private String supplierName;
  23 +
  24 + @ApiModelProperty("需方名称")
  25 + private String companyFullName;
  26 +
  27 + @ApiModelProperty("合同状态 1代表删除,0代表正常")
  28 + private Integer deleted;
  29 +
  30 + @ApiModelProperty("审核状态 AUDIT/PASS/REFUSE/CANCEL")
  31 + private String approvalStatus;
  32 +
  33 + @ApiModelProperty("签订时间开始")
  34 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  35 + private LocalDate startSignTime;
  36 +
  37 + @ApiModelProperty("签订时间结束")
  38 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  39 + private LocalDate endSignTime;
  40 +
  41 + @ApiModelProperty("交货时间开始")
  42 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  43 + private LocalDate startDeliveryTime;
  44 +
  45 + @ApiModelProperty("交货时间结束")
  46 + @JsonFormat(pattern = StringPool.DATE_PATTERN)
  47 + private LocalDate endDeliveryTime;
  48 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.contract;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import java.io.Serializable;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ApiModel("修改采购合同明细行Vo")
  12 +public class UpdateProcurementContractLineVo extends CreateProcurementContractLineVo implements Serializable {
  13 +
  14 + private static final long serialVersionUID = 1L;
  15 +
  16 + @ApiModelProperty("明细行主键ID")
  17 + private String id;
  18 +
  19 + @ApiModelProperty("主表ID")
  20 + private String contractId;
  21 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.contract;
  2 +
  3 +import com.lframework.starter.web.core.vo.BaseVo;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import java.io.Serializable;
  7 +import java.math.BigDecimal;
  8 +import java.time.LocalDate;
  9 +import java.util.List;
  10 +import javax.validation.Valid;
  11 +import javax.validation.constraints.NotBlank;
  12 +import javax.validation.constraints.NotNull;
  13 +import lombok.Data;
  14 +import org.hibernate.validator.constraints.Length;
  15 +
  16 +@Data
  17 +@ApiModel("修改采购合同Vo")
  18 +public class UpdateProcurementContractVo implements BaseVo, Serializable {
  19 +
  20 + private static final long serialVersionUID = 1L;
  21 +
  22 + @ApiModelProperty(value = "ID 必填", required = true)
  23 + @NotBlank(message = "ID不能为空!")
  24 + private String id;
  25 +
  26 + @ApiModelProperty(value = "关联采购计划ID 必填", required = true)
  27 + @NotBlank(message = "关联采购计划ID不能为空!")
  28 + private String procurementPlanId;
  29 +
  30 + @ApiModelProperty(value = "投诉编码(计划单编号) 必填", required = true)
  31 + @NotBlank(message = "计划单编号不能为空!")
  32 + private String procurementPlanCode;
  33 +
  34 + @ApiModelProperty(value = "供方ID(供应商ID) 必填", required = true)
  35 + @NotBlank(message = "供方ID不能为空!")
  36 + private String supplierId;
  37 +
  38 + @ApiModelProperty(value = "需方ID(公司简称ID) 必填", required = true)
  39 + @NotBlank(message = "需方ID不能为空!")
  40 + private String companyShortId;
  41 +
  42 + @ApiModelProperty("签订地点")
  43 + @Length(max = 64, message = "签订地点最多允许64个字符!")
  44 + private String signPlace;
  45 +
  46 + @ApiModelProperty(value = "签订时间 必填", required = true)
  47 + @NotNull(message = "签订时间不能为空!")
  48 + private LocalDate signTime;
  49 +
  50 + @ApiModelProperty(value = "交货时间 必填", required = true)
  51 + @NotNull(message = "交货时间不能为空!")
  52 + private LocalDate deliveryTime;
  53 +
  54 + @ApiModelProperty(value = "结算比例% 必填", required = true)
  55 + @NotNull(message = "结算比例不能为空!")
  56 + private BigDecimal settlementRatio;
  57 +
  58 + @ApiModelProperty("合计数量 后端重算")
  59 + private BigDecimal totalQuantity;
  60 +
  61 + @ApiModelProperty("合计不含税金额 后端重算")
  62 + private BigDecimal totalExcludingTaxAmount;
  63 +
  64 + @ApiModelProperty("合计税额 后端重算")
  65 + private BigDecimal totalTaxAmount;
  66 +
  67 + @ApiModelProperty("合计金额 后端重算")
  68 + private BigDecimal totalAmount;
  69 +
  70 + @ApiModelProperty("特殊约定(大文本)")
  71 + private String specialAgreement;
  72 +
  73 + @ApiModelProperty("附件文件ID集合")
  74 + private String attachmentFileIds;
  75 +
  76 + @ApiModelProperty("附件文件名称集合")
  77 + private String attachmentFileNames;
  78 +
  79 + @ApiModelProperty("发起人ID")
  80 + private String originatorId;
  81 +
  82 + @ApiModelProperty("发起人")
  83 + private String originatorName;
  84 +
  85 + @ApiModelProperty("明细列表")
  86 + @Valid
  87 + private List<UpdateProcurementContractLineVo> procurementContractLineList;
  88 +}
@@ -8,11 +8,13 @@ import org.apache.commons.lang3.StringUtils; @@ -8,11 +8,13 @@ import org.apache.commons.lang3.StringUtils;
8 import org.apache.poi.ss.usermodel.*; 8 import org.apache.poi.ss.usermodel.*;
9 import org.apache.poi.ss.util.CellRangeAddress; 9 import org.apache.poi.ss.util.CellRangeAddress;
10 10
  11 +import javax.servlet.http.HttpServletResponse;
11 import javax.swing.*; 12 import javax.swing.*;
12 import java.awt.*; 13 import java.awt.*;
13 import java.io.File; 14 import java.io.File;
14 import java.io.IOException; 15 import java.io.IOException;
15 import java.math.BigDecimal; 16 import java.math.BigDecimal;
  17 +import java.net.URLEncoder;
16 import java.time.LocalDate; 18 import java.time.LocalDate;
17 import java.time.format.DateTimeFormatter; 19 import java.time.format.DateTimeFormatter;
18 import java.util.ArrayList; 20 import java.util.ArrayList;
@@ -445,4 +447,33 @@ public class ExcelUtil { @@ -445,4 +447,33 @@ public class ExcelUtil {
445 } 447 }
446 return null; 448 return null;
447 } 449 }
  450 +
  451 + /**
  452 + * 设置HTTP响应头
  453 + */
  454 + public static void setupResponse(HttpServletResponse response, String fileName) throws IOException {
  455 + String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
  456 +
  457 + response.setContentType("application/vnd.ms-excel");
  458 + response.setCharacterEncoding("UTF-8");
  459 + response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName);
  460 + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
  461 + }
  462 +
  463 + /**
  464 + * 按单 Sheet 替换模板占位符(${...} / #{...})
  465 + */
  466 + public static void processTemplateSheet(Sheet sheet, Map<String, Object> dataMap) {
  467 + for (Row row : sheet) {
  468 + for (Cell cell : row) {
  469 + if (cell.getCellTypeEnum() == CellType.STRING) {
  470 + String cellValue = cell.getStringCellValue();
  471 + String newValue = replacePlaceholders(cellValue, dataMap);
  472 + if (!cellValue.equals(newValue)) {
  473 + cell.setCellValue(newValue);
  474 + }
  475 + }
  476 + }
  477 + }
  478 + }
448 } 479 }
  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.lframework.xingyun.sc.procurement.mappers.contract.ProcurementContractLineMapper">
  4 +
  5 + <resultMap id="ProcurementContractLineResult" type="com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContractLine">
  6 + <id column="id" property="id"/>
  7 + <result column="contract_id" property="contractId"/>
  8 + <result column="plan_line_id" property="planLineId"/>
  9 + <result column="invoice_product_name" property="invoiceProductName"/>
  10 + <result column="product_id" property="productId"/>
  11 + <result column="product_name" property="productName"/>
  12 + <result column="quantity" property="quantity"/>
  13 + <result column="unit_price" property="unitPrice"/>
  14 + <result column="excluding_tax_amount" property="excludingTaxAmount"/>
  15 + <result column="tax_amount" property="taxAmount"/>
  16 + <result column="total_amount" property="totalAmount"/>
  17 + <result column="delivery_time" property="deliveryTime"/>
  18 + <result column="item_id" property="itemId"/>
  19 + <result column="create_by_id" property="createById"/>
  20 + <result column="create_by" property="createBy"/>
  21 + <result column="update_by_id" property="updateById"/>
  22 + <result column="update_by" property="updateBy"/>
  23 + <result column="create_time" property="createTime"/>
  24 + <result column="update_time" property="updateTime"/>
  25 + </resultMap>
  26 +
  27 + <sql id="PCL_sql">
  28 + SELECT
  29 + pcl.id,
  30 + pcl.contract_id,
  31 + pcl.plan_line_id,
  32 + pcl.invoice_product_name,
  33 + pcl.product_id,
  34 + bbr.product_name,
  35 + pcl.quantity,
  36 + pcl.unit_price,
  37 + pcl.excluding_tax_amount,
  38 + pcl.tax_amount,
  39 + pcl.total_amount,
  40 + pcl.delivery_time,
  41 + pcl.item_id,
  42 + pcl.create_by_id,
  43 + pcl.create_by,
  44 + pcl.update_by_id,
  45 + pcl.update_by,
  46 + pcl.create_time,
  47 + pcl.update_time
  48 + FROM procurement_contract_line AS pcl
  49 + LEFT JOIN base_data_breed_relationship bbr ON bbr.id = pcl.product_id
  50 + </sql>
  51 +
  52 + <select id="getByContractId" resultMap="ProcurementContractLineResult">
  53 + <include refid="PCL_sql"/>
  54 + WHERE pcl.contract_id = #{contractId}
  55 + </select>
  56 +
  57 + <delete id="deleteByContractId">
  58 + DELETE FROM procurement_contract_line WHERE contract_id = #{contractId}
  59 + </delete>
  60 +</mapper>
  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.lframework.xingyun.sc.procurement.mappers.contract.ProcurementContractMapper">
  4 +
  5 + <resultMap id="ProcurementContractResult" type="com.lframework.xingyun.sc.procurement.entity.contract.ProcurementContract">
  6 + <id column="id" property="id"/>
  7 + <result column="procurement_plan_id" property="procurementPlanId"/>
  8 + <result column="procurement_plan_code" property="procurementPlanCode"/>
  9 + <result column="supplier_id" property="supplierId"/>
  10 + <result column="supplier_name" property="supplierName"/>
  11 + <result column="company_short_id" property="companyShortId"/>
  12 + <result column="company_full_name" property="companyFullName"/>
  13 + <result column="sign_place" property="signPlace"/>
  14 + <result column="sign_time" property="signTime"/>
  15 + <result column="delivery_time" property="deliveryTime"/>
  16 + <result column="settlement_ratio" property="settlementRatio"/>
  17 + <result column="total_quantity" property="totalQuantity"/>
  18 + <result column="total_excluding_tax_amount" property="totalExcludingTaxAmount"/>
  19 + <result column="total_tax_amount" property="totalTaxAmount"/>
  20 + <result column="total_amount" property="totalAmount"/>
  21 + <result column="special_agreement" property="specialAgreement"/>
  22 + <result column="attachment_file_ids" property="attachmentFileIds"/>
  23 + <result column="attachment_file_names" property="attachmentFileNames"/>
  24 + <result column="approval_status" property="approvalStatus"/>
  25 + <result column="originator_id" property="originatorId"/>
  26 + <result column="originator_name" property="originatorName"/>
  27 + <result column="deleted" property="deleted"/>
  28 + <result column="create_by_id" property="createById"/>
  29 + <result column="create_by" property="createBy"/>
  30 + <result column="update_by_id" property="updateById"/>
  31 + <result column="update_by" property="updateBy"/>
  32 + <result column="create_time" property="createTime"/>
  33 + <result column="update_time" property="updateTime"/>
  34 + </resultMap>
  35 +
  36 + <sql id="PC_sql">
  37 + SELECT
  38 + pc.id,
  39 + pc.procurement_plan_id,
  40 + pc.procurement_plan_code,
  41 + pc.supplier_id,
  42 + pdcc.unit_name AS supplier_name,
  43 + pc.company_short_id,
  44 + bdcs.company_name AS company_full_name,
  45 + pc.sign_place,
  46 + pc.sign_time,
  47 + pc.delivery_time,
  48 + pc.settlement_ratio,
  49 + pc.total_quantity,
  50 + pc.total_excluding_tax_amount,
  51 + pc.total_tax_amount,
  52 + pc.total_amount,
  53 + pc.special_agreement,
  54 + pc.attachment_file_ids,
  55 + pc.attachment_file_names,
  56 + pc.approval_status,
  57 + pc.originator_id,
  58 + pc.originator_name,
  59 + pc.deleted,
  60 + pc.create_by_id,
  61 + pc.create_by,
  62 + pc.update_by_id,
  63 + pc.update_by,
  64 + pc.create_time,
  65 + pc.update_time
  66 + FROM procurement_contract AS pc
  67 + LEFT JOIN procurement_domestic_customer_credit pdcc ON pdcc.id = pc.supplier_id
  68 + LEFT JOIN base_data_company_short bdcs ON bdcs.id = pc.company_short_id
  69 + </sql>
  70 +
  71 + <select id="query" resultMap="ProcurementContractResult">
  72 + <include refid="PC_sql"/>
  73 + <where>
  74 + pc.deleted = 0
  75 + <if test="vo.procurementPlanCode != null and vo.procurementPlanCode != ''">
  76 + AND pc.procurement_plan_code LIKE CONCAT('%', #{vo.procurementPlanCode}, '%')
  77 + </if>
  78 + <if test="vo.supplierName != null and vo.supplierName != ''">
  79 + AND pdcc.unit_name LIKE CONCAT('%', #{vo.supplierName}, '%')
  80 + </if>
  81 + <if test="vo.companyFullName != null and vo.companyFullName != ''">
  82 + AND bdcs.company_name LIKE CONCAT('%', #{vo.companyFullName}, '%')
  83 + </if>
  84 + <if test="vo.approvalStatus != null and vo.approvalStatus != ''">
  85 + AND pc.approval_status = #{vo.approvalStatus}
  86 + </if>
  87 + <if test="vo.startSignTime != null">
  88 + AND pc.sign_time <![CDATA[ >= ]]> #{vo.startSignTime}
  89 + </if>
  90 + <if test="vo.endSignTime != null">
  91 + AND pc.sign_time <![CDATA[ <= ]]> #{vo.endSignTime}
  92 + </if>
  93 + <if test="vo.startDeliveryTime != null">
  94 + AND pc.delivery_time <![CDATA[ >= ]]> #{vo.startDeliveryTime}
  95 + </if>
  96 + <if test="vo.endDeliveryTime != null">
  97 + AND pc.delivery_time <![CDATA[ <= ]]> #{vo.endDeliveryTime}
  98 + </if>
  99 + </where>
  100 + ORDER BY pc.create_time DESC
  101 + </select>
  102 +
  103 + <select id="findById" resultMap="ProcurementContractResult">
  104 + <include refid="PC_sql"/>
  105 + WHERE pc.id = #{id} AND pc.deleted = 0
  106 + </select>
  107 +</mapper>