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

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.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<ProcurementDetail> procurementDetails = processService.getProcurementDetails(id);
List<ProjectBudgetIncomeDetail> incomeDetails = projectBudgetService.getBudgetIncomeDetail(project);
List<ProcurementDetail> procurementDetails = Collections.emptyList();
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()
.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<SupplierMaterial> supplierMaterials = null;
List<SupplierMaterial> supplierMaterials = Collections.emptyList();
List<ProcurementDetail> procurementDetails = Collections.emptyList();
List<ProjectBudgetIncomeDetail> 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<ProjectBudgetIncomeDetail> 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:

View File

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

View File

@ -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 <a href="https://github.com/TAKETODAY">Harry Yang</a>
* @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<BudgetPurchaseDetailModel> details;
public List<BudgetPurchaseDetailModel> details;
}

View File

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

View File

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

View File

@ -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<ProcurementDetail> getProcurementDetails(int projectId) {
public List<ProcurementDetail> getProcurementDetails(int projectId, Integer processId) {
List<ProcurementDetail> ret = new ArrayList<>();
List<ProjectBudgetCostDetail> 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<BudgetPurchaseDetail> 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<BudgetPurchaseDetail> 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<BudgetPurchaseAmount> 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<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) {
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
(
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 '采购合同流程预算采购明细的详情';