diff --git a/src/main/java/cn/palmte/work/controller/backend/ProcessController.java b/src/main/java/cn/palmte/work/controller/backend/ProcessController.java index 0d765b1..72308e4 100644 --- a/src/main/java/cn/palmte/work/controller/backend/ProcessController.java +++ b/src/main/java/cn/palmte/work/controller/backend/ProcessController.java @@ -31,6 +31,7 @@ import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -278,16 +279,21 @@ public class ProcessController { */ @ResponseBody @GetMapping("/projects/{id}") - public ProjectReturnValue getProject(@PathVariable int id) { + public ProjectReturnValue getProject(@PathVariable int id, @RequestParam ProcessType processType) { Project project = projectRepository.findById(id); Admin admin = InterfaceUtil.getAdmin(); // project_budget_plan_detail 垫资金额计算 - BigDecimal repaidAmount = getRepaidAmount(id); - // 可以在对应表数据查询 是否存在再启用 - List procurementDetails = processService.getProcurementDetails(id); - List incomeDetails = projectBudgetService.getBudgetIncomeDetail(project); + + List procurementDetails = Collections.emptyList(); + List incomeDetails = Collections.emptyList(); + if (processType == ProcessType.sale_contract) { + incomeDetails = projectBudgetService.getBudgetIncomeDetail(project); + } + else if (processType == ProcessType.procurement_contract) { + procurementDetails = processService.getProcurementDetails(id, null); + } return ProjectReturnValue.builder() .isPrepaid(isPrepaid(project)) .projectId(project.getId()) @@ -319,23 +325,25 @@ public class ProcessController { Project project = projectRepository.findById(process.getProjectId()); BigDecimal repaidAmount = getRepaidAmount(id); Object contract; - List supplierMaterials = null; + List supplierMaterials = Collections.emptyList(); + List procurementDetails = Collections.emptyList(); + List incomeDetails = Collections.emptyList(); switch (process.getProcessType()) { case sale_contract: { contract = processService.findSaleContract(id); + incomeDetails = projectBudgetService.getBudgetIncomeDetail(project); break; } case procurement_contract: { contract = processService.findProcurementContract(id); supplierMaterials = processService.getSupplierMaterials(id); + procurementDetails = processService.getProcurementDetails(project.getId(), id); break; } default: throw new UnsupportedOperationException("还不支持"); } - // 可以在对应表数据查询 是否存在再启用 - List incomeDetails = projectBudgetService.getBudgetIncomeDetail(project); return ProjectReturnValue.builder() .process(process) .contract(contract) @@ -347,6 +355,7 @@ public class ProcessController { .budgetGrossMargin(project.getGrossProfitMargin()) .projectNo(project.getProjectNo()) .supplierMaterials(supplierMaterials) + .procurementDetails(procurementDetails) .contractAmount(project.getContractAmount()) .applyPersonName(process.getApplyPersonName()) .terminalCustomer(project.getTerminalCustomer()) @@ -386,6 +395,7 @@ public class ProcessController { processService.updateIncomeDetails(form.getIncomeDetails()); } else if (processType == ProcessType.procurement_contract) { + // 采购合同 ProcurementContract contract = ProcurementContract.from(form); contract.setProcessId(processId); entityManager.persist(contract); @@ -403,26 +413,54 @@ public class ProcessController { if (!CollectionUtils.isEmpty(form.getPurchaseAmount())) { for (BudgetPurchaseAmountModel amountForm : form.getPurchaseAmount()) { - // 保存 成本明细数量 - BudgetPurchaseAmount amountEntity = new BudgetPurchaseAmount(); - BeanUtils.copyProperties(amountForm, amountEntity, "details"); - amountEntity.setProcessId(processId); - amountEntity.setContractId(contractId); + // 草稿模式也不允许为空 (基础数据) + Assert.notNull(amountForm.amount, "合同明细填写不完整"); + Assert.notNull(amountForm.budgetCostId, "合同明细填写不完整"); - entityManager.persist(amountEntity); + // 已经采购的数量 要么是数据库存在的值要么是0 ,数据库获取已经采购数目 + BigDecimal amountAlready = processService.getAmountAlready(amountForm.budgetCostId); - Integer amountId = amountEntity.getId(); + // 新建 + BudgetPurchaseAmount purchaseAmount = new BudgetPurchaseAmount(); + purchaseAmount.setProcessId(processId); + purchaseAmount.setContractId(contractId); + purchaseAmount.setAmount(amountForm.amount); + purchaseAmount.setBudgetCostId(amountForm.budgetCostId); + purchaseAmount.setAmountCurrent(amountForm.amountCurrent); + + // TODO 提交模式才计算 剩余 + if (form.getStatus() == ProcessStatus.to_be_audit) { + // 当前的必须填写 + Assert.notNull(amountForm.amountCurrent, "合同明细填写不完整"); + + // 提交的时候 更新(计算)已经采购的数量 = 已经采购的数量 + 本次采购数量 + amountAlready = amountAlready.add(amountForm.amountCurrent); + purchaseAmount.setAmountAlready(amountAlready); // 更新数据库 + // amountForm.amount 和数据库的一致 剩余的未采购数量 = 总数 - 已经采购数量 + BigDecimal amountLeft = amountForm.amount.subtract(amountAlready); + purchaseAmount.setAmountLeft(amountLeft); + } + + // 复制 + if (purchaseAmount.getId() != null) { + entityManager.merge(purchaseAmount); + } + else { + entityManager.persist(purchaseAmount); + } + + Integer amountId = purchaseAmount.getId(); // ID 自动生成或者使用之前已经有的 // 保存成本对应的 明细 - - if (!CollectionUtils.isEmpty(amountForm.getDetails())) { - for (BudgetPurchaseDetailModel detail : amountForm.getDetails()) { + if (!CollectionUtils.isEmpty(amountForm.details)) { + for (BudgetPurchaseDetailModel detail : amountForm.details) { BudgetPurchaseDetail purchaseDetail = new BudgetPurchaseDetail(); - BeanUtils.copyProperties(detail, purchaseDetail, "details"); - // 关联主键 purchaseDetail.setAmountId(amountId); purchaseDetail.setProcessId(processId); purchaseDetail.setContractId(contractId); + purchaseDetail.setBudgetCostId(amountForm.budgetCostId); + + BeanUtils.copyProperties(detail, purchaseDetail, "details"); entityManager.persist(purchaseDetail); } } @@ -468,6 +506,10 @@ public class ProcessController { contract.setPaymentTerms(form.getPaymentTerms()); contract.setSupplierName(form.getSupplierName()); entityManager.merge(contract); + + // 保存BudgetPurchaseAmount的时候要检测 budgetCostId 该条记录不能重复 +// BudgetPurchaseAmount purchaseAmount = processService.getPurchaseAmount(amountForm.budgetCostId, processId); + break; } default: diff --git a/src/main/java/cn/palmte/work/model/process/BudgetPurchaseAmount.java b/src/main/java/cn/palmte/work/model/process/BudgetPurchaseAmount.java index 1bc0734..3b55d35 100644 --- a/src/main/java/cn/palmte/work/model/process/BudgetPurchaseAmount.java +++ b/src/main/java/cn/palmte/work/model/process/BudgetPurchaseAmount.java @@ -33,6 +33,9 @@ public class BudgetPurchaseAmount implements Serializable { // TODO 撤回的时候 amountAlready 数据一致问题 + // 所有的 + private BigDecimal amount; + // 已采购数量 private BigDecimal amountAlready; diff --git a/src/main/java/cn/palmte/work/model/process/BudgetPurchaseAmountModel.java b/src/main/java/cn/palmte/work/model/process/BudgetPurchaseAmountModel.java index 3a80b31..08c4e32 100644 --- a/src/main/java/cn/palmte/work/model/process/BudgetPurchaseAmountModel.java +++ b/src/main/java/cn/palmte/work/model/process/BudgetPurchaseAmountModel.java @@ -1,8 +1,11 @@ package cn.palmte.work.model.process; +import java.math.BigDecimal; import java.util.List; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Setter; +import lombok.ToString; /** * 采购合同流程预算采购明细的数量记录 @@ -10,20 +13,19 @@ import lombok.Data; * @author Harry Yang * @since 2.0 2022/12/28 15:00 */ -@Data +@Setter +@ToString +@EqualsAndHashCode public class BudgetPurchaseAmountModel { - // 已采购数量 - private Integer amountAlready; + // 所有的 + public BigDecimal amount; // 本次采购数量 - private Integer amountCurrent; - - // 未采购数量 - private Integer amountLeft; + public BigDecimal amountCurrent; // 项目的成本明细ID - private Integer budgetCostId; + public Integer budgetCostId; - private List details; + public List details; } diff --git a/src/main/java/cn/palmte/work/model/process/BudgetPurchaseDetail.java b/src/main/java/cn/palmte/work/model/process/BudgetPurchaseDetail.java index 4d1cdb5..7859635 100644 --- a/src/main/java/cn/palmte/work/model/process/BudgetPurchaseDetail.java +++ b/src/main/java/cn/palmte/work/model/process/BudgetPurchaseDetail.java @@ -59,4 +59,7 @@ public class BudgetPurchaseDetail implements Serializable { private Integer amountId; + // 项目的成本明细ID + private Integer budgetCostId; + } diff --git a/src/main/java/cn/palmte/work/model/process/ProcurementDetail.java b/src/main/java/cn/palmte/work/model/process/ProcurementDetail.java index e03c4a7..0e1b8b0 100644 --- a/src/main/java/cn/palmte/work/model/process/ProcurementDetail.java +++ b/src/main/java/cn/palmte/work/model/process/ProcurementDetail.java @@ -42,6 +42,9 @@ public class ProcurementDetail { private String payWay; private String remark; + // 项目的成本明细ID + private Integer budgetCostId; + // 要采购的总量 private BigDecimal amount; diff --git a/src/main/java/cn/palmte/work/service/ProjectProcessService.java b/src/main/java/cn/palmte/work/service/ProjectProcessService.java index 7f159c5..1a0c201 100644 --- a/src/main/java/cn/palmte/work/service/ProjectProcessService.java +++ b/src/main/java/cn/palmte/work/service/ProjectProcessService.java @@ -1,7 +1,5 @@ package cn.palmte.work.service; -import cn.palmte.work.config.activiti.ActConstant; - import org.springframework.beans.BeanUtils; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; @@ -22,6 +20,7 @@ import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.TypedQuery; +import cn.palmte.work.config.activiti.ActConstant; import cn.palmte.work.config.activiti.ActProjectTypeEnum; import cn.palmte.work.model.Admin; import cn.palmte.work.model.AdminRepository; @@ -35,7 +34,6 @@ import cn.palmte.work.model.ProjectRepository; import cn.palmte.work.model.enums.ProcessStatus; import cn.palmte.work.model.process.BudgetPurchaseAmount; import cn.palmte.work.model.process.BudgetPurchaseDetail; -import cn.palmte.work.model.process.BudgetPurchaseDetailModel; import cn.palmte.work.model.process.ProcurementContract; import cn.palmte.work.model.process.ProcurementDetail; import cn.palmte.work.model.process.ProjectProcess; @@ -204,24 +202,32 @@ public class ProjectProcessService { * 获取 采购清单 * * @param projectId 项目ID + * @param processId 流程ID 一般用于获取详情 */ - public List getProcurementDetails(int projectId) { + public List getProcurementDetails(int projectId, Integer processId) { List ret = new ArrayList<>(); List costDetails = getCostDetails(projectId); for (ProjectBudgetCostDetail costDetail : costDetails) { ProcurementDetail detail = new ProcurementDetail(); BeanUtils.copyProperties(costDetail, detail); - BudgetPurchaseAmount purchaseAmount = getPurchaseAmount(costDetail); - if (purchaseAmount != null) { - detail.setAmountAlready(purchaseAmount.getAmountAlready()); - Integer amountId = purchaseAmount.getId(); - List purchaseDetails = getBudgetPurchaseDetails(amountId); - detail.setPurchaseDetails(purchaseDetails); + // 可能为 0 + BigDecimal amountAlready = getAmountAlready(costDetail.getId()); + detail.setAmountAlready(amountAlready); + + if (processId != null) { + // 根据 processId 确定唯一的 BudgetPurchaseAmount 用作获取详情 , 可能还未创建 + BudgetPurchaseAmount purchaseAmount = getPurchaseAmount(projectId, processId); + if (purchaseAmount != null) { + Integer amountId = purchaseAmount.getId(); + List purchaseDetails = getBudgetPurchaseDetails(amountId); + detail.setPurchaseDetails(purchaseDetails); + } } // TODO 查询太频繁 detail.setCategory(getCategory(costDetail)); + detail.setBudgetCostId(costDetail.getId()); ret.add(detail); } @@ -256,10 +262,11 @@ public class ProjectProcessService { return query.getResultList(); } - private BudgetPurchaseAmount getPurchaseAmount(ProjectBudgetCostDetail costDetail) { + public BudgetPurchaseAmount getPurchaseAmount(int budgetCostId, Integer processId) { TypedQuery amountQuery = entityManager.createQuery( - "from BudgetPurchaseAmount where budgetCostId=:budgetCostId", BudgetPurchaseAmount.class); - amountQuery.setParameter("budgetCostId", costDetail.getId()); + "from BudgetPurchaseAmount where budgetCostId=:budgetCostId and processId=:processId", BudgetPurchaseAmount.class); + amountQuery.setParameter("budgetCostId", budgetCostId); + amountQuery.setParameter("processId", processId); try { return amountQuery.getSingleResult(); } @@ -268,6 +275,19 @@ public class ProjectProcessService { } } + public List getPurchaseAmountList(int budgetCostId) { + TypedQuery amountQuery = entityManager.createQuery( + "from BudgetPurchaseAmount where budgetCostId=:budgetCostId", BudgetPurchaseAmount.class); + amountQuery.setParameter("budgetCostId", budgetCostId); + return amountQuery.getResultList(); + } + + public BigDecimal getAmountAlready(int budgetCostId) { + return getPurchaseAmountList(budgetCostId).stream() + .map(BudgetPurchaseAmount::getAmountAlready) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } + public ProjectProcess getById(int id) { return entityManager.find(ProjectProcess.class, id); } diff --git a/src/main/resources/sql/2.0.sql b/src/main/resources/sql/2.0.sql index d1eebf7..df76b96 100644 --- a/src/main/resources/sql/2.0.sql +++ b/src/main/resources/sql/2.0.sql @@ -72,13 +72,15 @@ create table procurement_contract_supplier_material create table procurement_contract_budget_purchase_amount ( id int auto_increment primary key comment 'ID', + amount decimal(11, 2) comment '总共要采购数量', amount_current decimal(11, 2) comment '本次采购数量', amount_already decimal(11, 2) comment '已采购数量', amount_left decimal(11, 2) comment '未采购数量', - process_id int comment '流程ID', - contract_id int comment '采购合同ID', - budget_cost_id int comment '成本ID' + process_id int not null comment '流程ID', + contract_id int not null comment '采购合同ID', + budget_cost_id int not null comment '成本ID', + UNIQUE key (process_id, budget_cost_id) ) comment '采购合同流程预算采购明细的数量记录'; create table procurement_contract_budget_purchase_detail @@ -92,8 +94,9 @@ create table procurement_contract_budget_purchase_detail procurement_price decimal(19, 5) null comment '采购单价', total_tax_include decimal(19, 5) null comment '含税总金额(元)', - process_id int comment '流程ID', - contract_id int comment '采购合同ID', - amount_id int comment '成本ID' + process_id int not null comment '流程ID', + contract_id int not null comment '采购合同ID', + amount_id int not null comment '记录数量表的ID', + budget_cost_id int not null comment '成本ID' ) comment '采购合同流程预算采购明细的详情'; \ No newline at end of file