采购合同流程 数据结构 保存表单

master
Harry Yang 2022-12-29 22:35:46 +08:00
parent e03cf2f57e
commit 2871a53d95
7 changed files with 125 additions and 49 deletions

View File

@ -31,6 +31,7 @@ import java.text.SimpleDateFormat;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -278,16 +279,21 @@ public class ProcessController {
*/ */
@ResponseBody @ResponseBody
@GetMapping("/projects/{id}") @GetMapping("/projects/{id}")
public ProjectReturnValue getProject(@PathVariable int id) { public ProjectReturnValue getProject(@PathVariable int id, @RequestParam ProcessType processType) {
Project project = projectRepository.findById(id); Project project = projectRepository.findById(id);
Admin admin = InterfaceUtil.getAdmin(); Admin admin = InterfaceUtil.getAdmin();
// project_budget_plan_detail 垫资金额计算 // project_budget_plan_detail 垫资金额计算
BigDecimal repaidAmount = getRepaidAmount(id); BigDecimal repaidAmount = getRepaidAmount(id);
// 可以在对应表数据查询 是否存在再启用
List<ProcurementDetail> procurementDetails = processService.getProcurementDetails(id); List<ProcurementDetail> procurementDetails = Collections.emptyList();
List<ProjectBudgetIncomeDetail> incomeDetails = projectBudgetService.getBudgetIncomeDetail(project); List<ProjectBudgetIncomeDetail> 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() return ProjectReturnValue.builder()
.isPrepaid(isPrepaid(project)) .isPrepaid(isPrepaid(project))
.projectId(project.getId()) .projectId(project.getId())
@ -319,23 +325,25 @@ public class ProcessController {
Project project = projectRepository.findById(process.getProjectId()); Project project = projectRepository.findById(process.getProjectId());
BigDecimal repaidAmount = getRepaidAmount(id); BigDecimal repaidAmount = getRepaidAmount(id);
Object contract; Object contract;
List<SupplierMaterial> supplierMaterials = null; List<SupplierMaterial> supplierMaterials = Collections.emptyList();
List<ProcurementDetail> procurementDetails = Collections.emptyList();
List<ProjectBudgetIncomeDetail> incomeDetails = Collections.emptyList();
switch (process.getProcessType()) { switch (process.getProcessType()) {
case sale_contract: { case sale_contract: {
contract = processService.findSaleContract(id); contract = processService.findSaleContract(id);
incomeDetails = projectBudgetService.getBudgetIncomeDetail(project);
break; break;
} }
case procurement_contract: { case procurement_contract: {
contract = processService.findProcurementContract(id); contract = processService.findProcurementContract(id);
supplierMaterials = processService.getSupplierMaterials(id); supplierMaterials = processService.getSupplierMaterials(id);
procurementDetails = processService.getProcurementDetails(project.getId(), id);
break; break;
} }
default: default:
throw new UnsupportedOperationException("还不支持"); throw new UnsupportedOperationException("还不支持");
} }
// 可以在对应表数据查询 是否存在再启用
List<ProjectBudgetIncomeDetail> incomeDetails = projectBudgetService.getBudgetIncomeDetail(project);
return ProjectReturnValue.builder() return ProjectReturnValue.builder()
.process(process) .process(process)
.contract(contract) .contract(contract)
@ -347,6 +355,7 @@ public class ProcessController {
.budgetGrossMargin(project.getGrossProfitMargin()) .budgetGrossMargin(project.getGrossProfitMargin())
.projectNo(project.getProjectNo()) .projectNo(project.getProjectNo())
.supplierMaterials(supplierMaterials) .supplierMaterials(supplierMaterials)
.procurementDetails(procurementDetails)
.contractAmount(project.getContractAmount()) .contractAmount(project.getContractAmount())
.applyPersonName(process.getApplyPersonName()) .applyPersonName(process.getApplyPersonName())
.terminalCustomer(project.getTerminalCustomer()) .terminalCustomer(project.getTerminalCustomer())
@ -386,6 +395,7 @@ public class ProcessController {
processService.updateIncomeDetails(form.getIncomeDetails()); processService.updateIncomeDetails(form.getIncomeDetails());
} }
else if (processType == ProcessType.procurement_contract) { else if (processType == ProcessType.procurement_contract) {
// 采购合同
ProcurementContract contract = ProcurementContract.from(form); ProcurementContract contract = ProcurementContract.from(form);
contract.setProcessId(processId); contract.setProcessId(processId);
entityManager.persist(contract); entityManager.persist(contract);
@ -403,26 +413,54 @@ public class ProcessController {
if (!CollectionUtils.isEmpty(form.getPurchaseAmount())) { if (!CollectionUtils.isEmpty(form.getPurchaseAmount())) {
for (BudgetPurchaseAmountModel amountForm : form.getPurchaseAmount()) { for (BudgetPurchaseAmountModel amountForm : form.getPurchaseAmount()) {
// 保存 成本明细数量 // 草稿模式也不允许为空 (基础数据)
BudgetPurchaseAmount amountEntity = new BudgetPurchaseAmount(); Assert.notNull(amountForm.amount, "合同明细填写不完整");
BeanUtils.copyProperties(amountForm, amountEntity, "details"); Assert.notNull(amountForm.budgetCostId, "合同明细填写不完整");
amountEntity.setProcessId(processId);
amountEntity.setContractId(contractId);
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.details)) {
if (!CollectionUtils.isEmpty(amountForm.getDetails())) { for (BudgetPurchaseDetailModel detail : amountForm.details) {
for (BudgetPurchaseDetailModel detail : amountForm.getDetails()) {
BudgetPurchaseDetail purchaseDetail = new BudgetPurchaseDetail(); BudgetPurchaseDetail purchaseDetail = new BudgetPurchaseDetail();
BeanUtils.copyProperties(detail, purchaseDetail, "details");
// 关联主键 // 关联主键
purchaseDetail.setAmountId(amountId); purchaseDetail.setAmountId(amountId);
purchaseDetail.setProcessId(processId); purchaseDetail.setProcessId(processId);
purchaseDetail.setContractId(contractId); purchaseDetail.setContractId(contractId);
purchaseDetail.setBudgetCostId(amountForm.budgetCostId);
BeanUtils.copyProperties(detail, purchaseDetail, "details");
entityManager.persist(purchaseDetail); entityManager.persist(purchaseDetail);
} }
} }
@ -468,6 +506,10 @@ public class ProcessController {
contract.setPaymentTerms(form.getPaymentTerms()); contract.setPaymentTerms(form.getPaymentTerms());
contract.setSupplierName(form.getSupplierName()); contract.setSupplierName(form.getSupplierName());
entityManager.merge(contract); entityManager.merge(contract);
// 保存BudgetPurchaseAmount的时候要检测 budgetCostId 该条记录不能重复
// BudgetPurchaseAmount purchaseAmount = processService.getPurchaseAmount(amountForm.budgetCostId, processId);
break; break;
} }
default: default:

View File

@ -33,6 +33,9 @@ public class BudgetPurchaseAmount implements Serializable {
// TODO 撤回的时候 amountAlready 数据一致问题 // TODO 撤回的时候 amountAlready 数据一致问题
// 所有的
private BigDecimal amount;
// 已采购数量 // 已采购数量
private BigDecimal amountAlready; private BigDecimal amountAlready;

View File

@ -1,8 +1,11 @@
package cn.palmte.work.model.process; package cn.palmte.work.model.process;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
import lombok.Data; import lombok.EqualsAndHashCode;
import lombok.Setter;
import lombok.ToString;
/** /**
* *
@ -10,20 +13,19 @@ import lombok.Data;
* @author <a href="https://github.com/TAKETODAY">Harry Yang</a> * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
* @since 2.0 2022/12/28 15:00 * @since 2.0 2022/12/28 15:00
*/ */
@Data @Setter
@ToString
@EqualsAndHashCode
public class BudgetPurchaseAmountModel { public class BudgetPurchaseAmountModel {
// 已采购数量 // 所有的
private Integer amountAlready; public BigDecimal amount;
// 本次采购数量 // 本次采购数量
private Integer amountCurrent; public BigDecimal amountCurrent;
// 未采购数量
private Integer amountLeft;
// 项目的成本明细ID // 项目的成本明细ID
private Integer budgetCostId; public Integer budgetCostId;
private List<BudgetPurchaseDetailModel> details; public List<BudgetPurchaseDetailModel> details;
} }

View File

@ -59,4 +59,7 @@ public class BudgetPurchaseDetail implements Serializable {
private Integer amountId; private Integer amountId;
// 项目的成本明细ID
private Integer budgetCostId;
} }

View File

@ -42,6 +42,9 @@ public class ProcurementDetail {
private String payWay; private String payWay;
private String remark; private String remark;
// 项目的成本明细ID
private Integer budgetCostId;
// 要采购的总量 // 要采购的总量
private BigDecimal amount; private BigDecimal amount;

View File

@ -1,7 +1,5 @@
package cn.palmte.work.service; package cn.palmte.work.service;
import cn.palmte.work.config.activiti.ActConstant;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
@ -22,6 +20,7 @@ import javax.persistence.EntityManager;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import cn.palmte.work.config.activiti.ActConstant;
import cn.palmte.work.config.activiti.ActProjectTypeEnum; import cn.palmte.work.config.activiti.ActProjectTypeEnum;
import cn.palmte.work.model.Admin; import cn.palmte.work.model.Admin;
import cn.palmte.work.model.AdminRepository; 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.enums.ProcessStatus;
import cn.palmte.work.model.process.BudgetPurchaseAmount; import cn.palmte.work.model.process.BudgetPurchaseAmount;
import cn.palmte.work.model.process.BudgetPurchaseDetail; 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.ProcurementContract;
import cn.palmte.work.model.process.ProcurementDetail; import cn.palmte.work.model.process.ProcurementDetail;
import cn.palmte.work.model.process.ProjectProcess; import cn.palmte.work.model.process.ProjectProcess;
@ -204,24 +202,32 @@ public class ProjectProcessService {
* *
* *
* @param projectId ID * @param projectId ID
* @param processId ID
*/ */
public List<ProcurementDetail> getProcurementDetails(int projectId) { public List<ProcurementDetail> getProcurementDetails(int projectId, Integer processId) {
List<ProcurementDetail> ret = new ArrayList<>(); List<ProcurementDetail> ret = new ArrayList<>();
List<ProjectBudgetCostDetail> costDetails = getCostDetails(projectId); List<ProjectBudgetCostDetail> costDetails = getCostDetails(projectId);
for (ProjectBudgetCostDetail costDetail : costDetails) { for (ProjectBudgetCostDetail costDetail : costDetails) {
ProcurementDetail detail = new ProcurementDetail(); ProcurementDetail detail = new ProcurementDetail();
BeanUtils.copyProperties(costDetail, detail); BeanUtils.copyProperties(costDetail, detail);
BudgetPurchaseAmount purchaseAmount = getPurchaseAmount(costDetail); // 可能为 0
if (purchaseAmount != null) { BigDecimal amountAlready = getAmountAlready(costDetail.getId());
detail.setAmountAlready(purchaseAmount.getAmountAlready()); detail.setAmountAlready(amountAlready);
Integer amountId = purchaseAmount.getId();
List<BudgetPurchaseDetail> purchaseDetails = getBudgetPurchaseDetails(amountId); if (processId != null) {
detail.setPurchaseDetails(purchaseDetails); // 根据 processId 确定唯一的 BudgetPurchaseAmount 用作获取详情 , 可能还未创建
BudgetPurchaseAmount purchaseAmount = getPurchaseAmount(projectId, processId);
if (purchaseAmount != null) {
Integer amountId = purchaseAmount.getId();
List<BudgetPurchaseDetail> purchaseDetails = getBudgetPurchaseDetails(amountId);
detail.setPurchaseDetails(purchaseDetails);
}
} }
// TODO 查询太频繁 // TODO 查询太频繁
detail.setCategory(getCategory(costDetail)); detail.setCategory(getCategory(costDetail));
detail.setBudgetCostId(costDetail.getId());
ret.add(detail); ret.add(detail);
} }
@ -256,10 +262,11 @@ public class ProjectProcessService {
return query.getResultList(); return query.getResultList();
} }
private BudgetPurchaseAmount getPurchaseAmount(ProjectBudgetCostDetail costDetail) { public BudgetPurchaseAmount getPurchaseAmount(int budgetCostId, Integer processId) {
TypedQuery<BudgetPurchaseAmount> amountQuery = entityManager.createQuery( TypedQuery<BudgetPurchaseAmount> amountQuery = entityManager.createQuery(
"from BudgetPurchaseAmount where budgetCostId=:budgetCostId", BudgetPurchaseAmount.class); "from BudgetPurchaseAmount where budgetCostId=:budgetCostId and processId=:processId", BudgetPurchaseAmount.class);
amountQuery.setParameter("budgetCostId", costDetail.getId()); amountQuery.setParameter("budgetCostId", budgetCostId);
amountQuery.setParameter("processId", processId);
try { try {
return amountQuery.getSingleResult(); return amountQuery.getSingleResult();
} }
@ -268,6 +275,19 @@ public class ProjectProcessService {
} }
} }
public List<BudgetPurchaseAmount> getPurchaseAmountList(int budgetCostId) {
TypedQuery<BudgetPurchaseAmount> 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) { public ProjectProcess getById(int id) {
return entityManager.find(ProjectProcess.class, id); return entityManager.find(ProjectProcess.class, id);
} }

View File

@ -72,13 +72,15 @@ create table procurement_contract_supplier_material
create table procurement_contract_budget_purchase_amount create table procurement_contract_budget_purchase_amount
( (
id int auto_increment primary key comment 'ID', id int auto_increment primary key comment 'ID',
amount decimal(11, 2) comment '总共要采购数量',
amount_current decimal(11, 2) comment '本次采购数量', amount_current decimal(11, 2) comment '本次采购数量',
amount_already decimal(11, 2) comment '已采购数量', amount_already decimal(11, 2) comment '已采购数量',
amount_left decimal(11, 2) comment '未采购数量', amount_left decimal(11, 2) comment '未采购数量',
process_id int comment '流程ID', process_id int not null comment '流程ID',
contract_id int comment '采购合同ID', contract_id int not null comment '采购合同ID',
budget_cost_id int comment '成本ID' budget_cost_id int not null comment '成本ID',
UNIQUE key (process_id, budget_cost_id)
) comment '采购合同流程预算采购明细的数量记录'; ) comment '采购合同流程预算采购明细的数量记录';
create table procurement_contract_budget_purchase_detail 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 '采购单价', procurement_price decimal(19, 5) null comment '采购单价',
total_tax_include decimal(19, 5) null comment '含税总金额(元)', total_tax_include decimal(19, 5) null comment '含税总金额(元)',
process_id int comment '流程ID', process_id int not null comment '流程ID',
contract_id int comment '采购合同ID', contract_id int not null comment '采购合同ID',
amount_id int comment '成本ID' amount_id int not null comment '记录数量表的ID',
budget_cost_id int not null comment '成本ID'
) comment '采购合同流程预算采购明细的详情'; ) comment '采购合同流程预算采购明细的详情';