From f9485760aac48e8a5f929d86accc862030dd04c3 Mon Sep 17 00:00:00 2001
From: Harry Yang <i.take.today@gmail.com>
Date: Fri, 30 Dec 2022 00:57:24 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=87=E8=B4=AD=E5=90=88=E5=90=8C=E6=B5=81?=
 =?UTF-8?q?=E7=A8=8B=20=E8=AF=A6=E6=83=85=E5=B1=95=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../controller/backend/ProcessController.java |  72 ++---
 .../model/process/ProjectProcessDetail.java   |  38 +++
 src/main/resources/sql/2.0.sql                |   3 +
 .../admin/business/process-detail.ftl         | 302 ++++++++++--------
 4 files changed, 234 insertions(+), 181 deletions(-)
 create mode 100644 src/main/java/cn/palmte/work/model/process/ProjectProcessDetail.java

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 72308e4..b107991 100644
--- a/src/main/java/cn/palmte/work/controller/backend/ProcessController.java
+++ b/src/main/java/cn/palmte/work/controller/backend/ProcessController.java
@@ -64,6 +64,7 @@ import cn.palmte.work.model.process.BudgetPurchaseDetail;
 import cn.palmte.work.model.process.ProcessAttachment;
 import cn.palmte.work.model.process.ProcurementContract;
 import cn.palmte.work.model.process.ProjectProcess;
+import cn.palmte.work.model.process.ProjectProcessDetail;
 import cn.palmte.work.model.process.ProjectProcessRepository;
 import cn.palmte.work.model.process.SaleContract;
 import cn.palmte.work.model.process.SealTypeArray;
@@ -170,6 +171,8 @@ public class ProcessController {
 
   @GetMapping("/detail/{id}")
   public String detail(@PathVariable int id, Model model) {
+    model.addAttribute("processId", id);
+
     ProjectProcess process = repository.findOne(id);
     model.addAttribute("process", process);
 
@@ -320,48 +323,41 @@ public class ProcessController {
    */
   @ResponseBody
   @GetMapping("/{id}")
-  public ProjectReturnValue get(@PathVariable int id) {
+  public ProjectProcessDetail get(@PathVariable int id) {
+    ProjectProcessDetail detail = new ProjectProcessDetail();
+    detail.setProcessId(id);
+
     ProjectProcess process = processService.getById(id);
+    detail.setProcess(process);
+
     Project project = projectRepository.findById(process.getProjectId());
+    detail.setProject(project);
     BigDecimal repaidAmount = getRepaidAmount(id);
-    Object contract;
+    detail.setRepaidAmount(repaidAmount);
+    Object contract = 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("还不支持");
+    if (process.getProcessType() == ProcessType.sale_contract) {
+      contract = processService.findSaleContract(id);
+      incomeDetails = projectBudgetService.getBudgetIncomeDetail(project);
+    }
+    else if (process.getProcessType() == ProcessType.procurement_contract) {
+      contract = processService.findProcurementContract(id);
+      supplierMaterials = processService.getSupplierMaterials(id);
+      procurementDetails = processService.getProcurementDetails(project.getId(), id);
     }
 
-    return ProjectReturnValue.builder()
-            .process(process)
-            .contract(contract)
-            .isPrepaid(isPrepaid(project))
-            .projectId(project.getId())
-            .incomeDetails(incomeDetails)
-            .projectName(project.getName())
-            .repaidAmount(repaidAmount + "元")
-            .budgetGrossMargin(project.getGrossProfitMargin())
-            .projectNo(project.getProjectNo())
-            .supplierMaterials(supplierMaterials)
-            .procurementDetails(procurementDetails)
-            .contractAmount(project.getContractAmount())
-            .applyPersonName(process.getApplyPersonName())
-            .terminalCustomer(project.getTerminalCustomer())
-            .projectType(Enumerable.of(ProjectType.class, project.getType()).getDescription())
-            .cooperationType(Enumerable.of(CooperationType.class, project.getCooperateType()).getDescription())
-            .build();
+    detail.setContract(contract);
+    detail.setIncomeDetails(incomeDetails);
+    detail.setSupplierMaterials(supplierMaterials);
+    detail.setProcurementDetails(procurementDetails);
+    detail.setProjectType(Enumerable.of(ProjectType.class, project.getType()));
+    detail.setCooperationType(Enumerable.of(CooperationType.class, project.getCooperateType()));
+    List<ProcessAttachment> attachments = JSONArray.parseArray(process.getAttachmentUri(), ProcessAttachment.class);
+    detail.setAttachments(attachments);
+    return detail;
   }
 
   // 合同流程
@@ -441,13 +437,7 @@ public class ProcessController {
             purchaseAmount.setAmountLeft(amountLeft);
           }
 
-          // 复制
-          if (purchaseAmount.getId() != null) {
-            entityManager.merge(purchaseAmount);
-          }
-          else {
-            entityManager.persist(purchaseAmount);
-          }
+          entityManager.persist(purchaseAmount);
 
           Integer amountId = purchaseAmount.getId(); // ID 自动生成或者使用之前已经有的
           // 保存成本对应的 明细
diff --git a/src/main/java/cn/palmte/work/model/process/ProjectProcessDetail.java b/src/main/java/cn/palmte/work/model/process/ProjectProcessDetail.java
new file mode 100644
index 0000000..f85c53e
--- /dev/null
+++ b/src/main/java/cn/palmte/work/model/process/ProjectProcessDetail.java
@@ -0,0 +1,38 @@
+package cn.palmte.work.model.process;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import cn.palmte.work.model.Project;
+import cn.palmte.work.model.ProjectBudgetIncomeDetail;
+import cn.palmte.work.model.enums.CooperationType;
+import cn.palmte.work.model.enums.ProjectType;
+import lombok.Data;
+
+/**
+ * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
+ * @since 2.0 2022/12/30 00:11
+ */
+@Data
+public class ProjectProcessDetail {
+
+  private Integer processId;
+
+  private Project project;
+  private ProjectProcess process;
+  private ProjectType projectType;
+  private CooperationType cooperationType;
+
+  private List<ProcessAttachment> attachments;
+
+  private String isPrepaid;
+  private BigDecimal repaidAmount;
+
+  private Object contract;
+
+  public List<ProjectBudgetIncomeDetail> incomeDetails;
+
+  public List<SupplierMaterial> supplierMaterials;
+  public List<ProcurementDetail> procurementDetails;
+
+}
diff --git a/src/main/resources/sql/2.0.sql b/src/main/resources/sql/2.0.sql
index df76b96..ca73503 100644
--- a/src/main/resources/sql/2.0.sql
+++ b/src/main/resources/sql/2.0.sql
@@ -83,6 +83,9 @@ create table procurement_contract_budget_purchase_amount
     UNIQUE key (process_id, budget_cost_id)
 ) comment '采购合同流程预算采购明细的数量记录';
 
+alter table procurement_contract_budget_purchase_amount
+    add amount decimal(11, 2) comment '总共要采购数量' after id;
+
 create table procurement_contract_budget_purchase_detail
 (
     id                 int auto_increment primary key comment 'ID',
diff --git a/src/main/resources/templates/admin/business/process-detail.ftl b/src/main/resources/templates/admin/business/process-detail.ftl
index 82d0359..bc6eb40 100644
--- a/src/main/resources/templates/admin/business/process-detail.ftl
+++ b/src/main/resources/templates/admin/business/process-detail.ftl
@@ -27,9 +27,14 @@
       .el-tag--small {
           margin-right: 5px;
       }
+
+      [v-cloak] {
+          display: none;
+      }
+
   </style>
 
-  <div class="admin-content" id="app">
+  <div class="admin-content" id="app" v-cloak>
     <div class="admin-content-body">
       <div class="am-cf am-padding">
         <div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">业务应用</strong> /
@@ -40,23 +45,23 @@
       <div class="am-u-sm-12 am-u-md-12">
 
         <el-descriptions title="${process.processType.description}详情">
-          <el-descriptions-item label="项目编号">${process.projectNo}</el-descriptions-item>
-          <el-descriptions-item label="项目标题">${process.projectTitle}</el-descriptions-item>
-          <el-descriptions-item label="申请时间">${process.applyDate}</el-descriptions-item>
+          <el-descriptions-item label="项目编号">{{process.projectNo}}</el-descriptions-item>
+          <el-descriptions-item label="项目标题">{{process.projectTitle}}</el-descriptions-item>
+          <el-descriptions-item label="申请时间">{{process.applyDate}}</el-descriptions-item>
           <el-descriptions-item label="项目类型">${projectType}</el-descriptions-item>
           <el-descriptions-item label="合作类型">${cooperationType}</el-descriptions-item>
 
-          <el-descriptions-item label="申请部门">${process.applyDept}</el-descriptions-item>
-          <el-descriptions-item label="申请人">${process.applyPersonName}</el-descriptions-item>
-          <el-descriptions-item label="申请部门领导">${process.applyDeptLeaderName}</el-descriptions-item>
-          <el-descriptions-item label="申请人电话">${contract.applyPersonPhone}</el-descriptions-item>
+          <el-descriptions-item label="申请部门">{{process.applyDept}}</el-descriptions-item>
+          <el-descriptions-item label="申请人">{{process.applyPersonName}}</el-descriptions-item>
+          <el-descriptions-item label="申请部门领导">{{process.applyDeptLeaderName}}</el-descriptions-item>
+          <el-descriptions-item label="申请人电话">{{contract?.applyPersonPhone}}</el-descriptions-item>
 
-          <el-descriptions-item label="合同编号">${process.contractNo}</el-descriptions-item>
-          <el-descriptions-item label="合同名称">${process.contractName}</el-descriptions-item>
-          <el-descriptions-item label="合同金额">${project.contractAmount}</el-descriptions-item>
+          <el-descriptions-item label="合同编号">{{process.contractNo}}</el-descriptions-item>
+          <el-descriptions-item label="合同名称">{{process.contractName}}</el-descriptions-item>
+          <el-descriptions-item label="合同金额">{{project.contractAmount}}</el-descriptions-item>
 
-          <el-descriptions-item label="客户名称">${contract.clientName}</el-descriptions-item>
-          <el-descriptions-item label="最终用户名称">${project.terminalCustomer}</el-descriptions-item>
+          <el-descriptions-item label="客户名称">{{contract.clientName}}</el-descriptions-item>
+          <el-descriptions-item label="最终用户名称">{{project.terminalCustomer}}</el-descriptions-item>
 
           <el-descriptions-item label="用印类型">
               <#list process.sealTypes.list as item>
@@ -64,155 +69,112 @@
               </#list>
           </el-descriptions-item>
 
-          <el-descriptions-item label="税率">${process.taxRate}%</el-descriptions-item>
-          <el-descriptions-item label="是否垫资">${isPrepaid}</el-descriptions-item>
+          <el-descriptions-item label="税率">{{process.taxRate}}%</el-descriptions-item>
+          <el-descriptions-item label="是否垫资">{{isPrepaid}}</el-descriptions-item>
           <el-descriptions-item label="垫资金额">${repaidAmount}元</el-descriptions-item>
-          <el-descriptions-item label="预算毛利率">${project.grossProfitMargin}</el-descriptions-item>
+          <el-descriptions-item label="预算毛利率">{{project.grossProfitMargin}}</el-descriptions-item>
 
-          <el-descriptions-item label="收款条件">${contract.paymentTerms}</el-descriptions-item>
-          <el-descriptions-item label="备注">${process.remark}</el-descriptions-item>
+          <el-descriptions-item label="收款条件">{{contract.paymentTerms}}</el-descriptions-item>
+          <el-descriptions-item label="备注">{{process.remark}}</el-descriptions-item>
           <el-descriptions-item label="附件">
-              <#list attachments as attachment>
-                <el-tag size="small">
-                  <a href="${attachment.uri}">
-                    <i class="el-icon-document"></i> ${attachment.name}
-                  </a>
-                </el-tag>
-              </#list>
+            <el-tag size="small" v-for="attachment in attachments">
+              <a :href="attachment.uri">
+                <i class="el-icon-document"></i> {{attachment.name}}
+              </a>
+            </el-tag>
           </el-descriptions-item>
 
         </el-descriptions>
 
-          <#--
-            <el-form :inline="true" ref="saleContractProcessForm" :model="processForm" label-position="right" label-width="100px">
+          <#-- 项目预算收入明细表 -->
+        <div>
+          <el-alert title="项目预算收入明细" type="success" center :closable="false"></el-alert>
 
-            <div class="am-form-inline">
+          <el-table border :data="incomeDetails" empty-text="暂无">
+            <el-table-column type="index" :index="1" label="序号" fixed></el-table-column>
+            <el-table-column prop="name" label="名称" fixed width="120"></el-table-column>
+            <el-table-column prop="type" label="类别"></el-table-column>
+            <el-table-column prop="spec" label="规格型号"></el-table-column>
+            <el-table-column prop="param" label="参数"></el-table-column>
+            <el-table-column prop="amount" label="数量"></el-table-column>
+            <el-table-column prop="unit" label="单位"></el-table-column>
+            <el-table-column prop="price" label="单价(元)" width="120"></el-table-column>
+            <el-table-column prop="taxRate" label="税率(%)"></el-table-column>
+            <el-table-column prop="totalTaxInclude" label="含税金额(元)" width="120"></el-table-column>
+            <el-table-column prop="totalTaxExclude" label="不含税金额(元)" width="120"></el-table-column>
+            <el-table-column prop="totalTax" label="税金(元)" width="120"></el-table-column>
+            <el-table-column prop="expirationDate" label="质保期" width="150"></el-table-column>
 
-              <el-form-item label="项目编号">
-                <span>${process.projectNo}</span>
-              </el-form-item>
+          </el-table>
 
-              <el-tooltip effect="light" :content="projectTitle" placement="top-start">
-                <el-form-item label="项目标题">
-                  <span>${process.projectTitle}</span>
-                </el-form-item>
-              </el-tooltip>
+        </div>
 
-              <el-form-item label="申请时间">
-                <span>${process.applyDate}</span>
-              </el-form-item>
+          <#-- 供应商比选材料 -->
 
-              <el-form-item label="项目类型">
-                <span>${projectType}</span>
-              </el-form-item>
+        <div>
+          <el-alert title="供应商比选材料" type="success" center :closable="false"></el-alert>
+          <el-table border :data="supplierMaterials" empty-text="暂无">
+            <el-table-column type="index" :index="1" label="序号" fixed></el-table-column>
 
-              <el-form-item label="合作类型">
-                <span>${cooperationType}</span>
-              </el-form-item>
+            <el-table-column prop="companyName" label="公司名称" width="180" align="center"></el-table-column>
+            <el-table-column prop="totalAmount" label="合计金额" width="160" align="center"></el-table-column>
+            <el-table-column prop="serviceTerms" label="服务条款" width="180" align="center"></el-table-column>
+            <el-table-column prop="paymentTerms" label="付款条件" align="center"></el-table-column>
+            <el-table-column prop="taxRate" label="税率(%)" width="160" align="center"></el-table-column>
+            <el-table-column prop="remark" label="备注" align="center"></el-table-column>
+            <el-table-column prop="attachment" label="附件" align="center" width="150">
+              <template slot-scope="scope">
+                <el-tag size="small" v-if="scope.row.attachment">
+                  <a :href="scope.row.attachment.uri">
+                    <i class="el-icon-document"></i> {{scope.row.attachment.name}}
+                  </a>
+                </el-tag>
+              </template>
+            </el-table-column>
 
-            </div>
+          </el-table>
 
-            <div>
+        </div>
 
-              <el-form-item label="申请部门">
-                <span>${process.applyDept}</span>
-              </el-form-item>
+          <#-- 采购详情 -->
+        <div>
+          <el-alert title="采购清单" type="success" center :closable="false"></el-alert>
 
-              <el-form-item label="申请人">
-                <span>${process.applyPersonName}</span>
-              </el-form-item>
+          <el-table border :data="procurementDetails" empty-text="暂无">
+            <el-table-column type="index" :index="1" label="序号" fixed></el-table-column>
+            <el-table-column prop="feeType" label="费用项目" fixed width="80"></el-table-column>
+            <el-table-column prop="name" label="产品名称" fixed></el-table-column>
+            <el-table-column prop="category" label="采购类别" fixed></el-table-column>
 
-              <el-form-item label="申请部门领导">
-                <span>${process.applyDeptLeaderName}</span>
-              </el-form-item>
+            <el-table-column prop="amount" label="数量"></el-table-column>
+            <el-table-column prop="unit" label="单位"></el-table-column>
+            <el-table-column prop="price" label="预算单价" width="100"></el-table-column>
+            <el-table-column prop="taxRate" label="税率(%)"></el-table-column>
+            <el-table-column prop="totalTaxInclude_" label="含税总金额(元)" width="120"></el-table-column>
+            <el-table-column prop="totalTaxExclude" label="不含税金额(元)" width="120"></el-table-column>
+            <el-table-column prop="totalTax" label="税金(元)" width="110"></el-table-column>
+            <el-table-column prop="isUnderwritten" label="是否垫资"></el-table-column>
+            <el-table-column prop="payTime" label="支出时间" width="160"></el-table-column>
+            <el-table-column prop="payAmount" label="支出金额(元)" width="120"></el-table-column>
+            <el-table-column prop="amountAlready" label="已采购数量" width="100"></el-table-column>
+            <el-table-column prop="amountCurrent" label="本次采购数量" width="180"></el-table-column>
+            <el-table-column prop="amountLeft" label="未采购数量" width="100"></el-table-column>
 
-              <el-form-item label="申请人电话" prop="applyPersonPhone">
-                <span>${contract.applyPersonPhone}</span>
-              </el-form-item>
+            <el-table-column prop="supplierName" label="供应商名称" width="200"></el-table-column>
+            <el-table-column prop="manufacturerName" label="设备厂商名称" width="200"></el-table-column>
+            <el-table-column prop="purchaseList" label="对应采购清单" width="200"></el-table-column>
+            <el-table-column prop="spec" label="规格型号" width="200"></el-table-column>
+            <el-table-column prop="procurementAmount" label="对应采购数目" width="200"></el-table-column>
+            <el-table-column prop="procurementPrice" label="采购单价" width="200"></el-table-column>
+            <el-table-column prop="totalTaxInclude" label="含税总金额(元)" width="200"></el-table-column>
 
-            </div>
+          </el-table>
 
-            <div>
+        </div>
 
-              <el-form-item label="合同编号">
-                <span>${process.contractNo}</span>
-              </el-form-item>
-
-              <el-form-item label="合同名称">
-                <span>${process.contractName}</span>
-              </el-form-item>
-
-              <el-form-item label="合同金额">
-                <span>${project.contractAmount}</span>
-              </el-form-item>
-
-            </div>
-
-            <div>
-              <el-form-item label="客户名称">
-                <span>${contract.clientName}</span>
-              </el-form-item>
-
-              <el-form-item label="最终用户名称">
-                <span>${project.terminalCustomer}</span>
-              </el-form-item>
-            </div>
-
-            <div>
-              <el-form-item label="用印类型">
-                  <#list process.sealTypes.sealTypes as item>
-                    <el-tag size="small">${item.description}</el-tag>
-                  </#list>
-              </el-form-item>
-            </div>
-
-            <div>
-
-              <el-form-item label="税率">
-                <span>${process.taxRate}%</span>
-              </el-form-item>
-
-              <el-form-item label="是否垫资">
-                <span>${isPrepaid}</span>
-              </el-form-item>
-
-              <el-form-item label="垫资金额">
-                <span>${repaidAmount}元</span>
-              </el-form-item>
-
-              <el-form-item label="预算毛利率">
-                <span>${project.grossProfitMargin}</span>
-              </el-form-item>
-
-            </div>
-
-            <div>
-              <el-form-item label="收款条件">
-                <div>${contract.paymentTerms}</div>
-              </el-form-item>
-            </div>
-
-            <div>
-              <el-form-item label="备注">
-                <div>${process.remark}</div>
-              </el-form-item>
-            </div>
-
-            <div>
-              <el-form-item label="附件">
-                  <#list attachments as attachment>
-                    <a href="${attachment.uri}">
-                      <i class="el-icon-document"></i> ${attachment.name}
-                    </a>
-                  </#list>
-              </el-form-item>
-            </div>
-
-          </el-form>
--->
 
         <el-row>
-          <el-button type="info" @click="backLastPage">返回上一级</el-button>
+          <el-button style="margin-top: 30px" type="info" @click="backLastPage">返回上一级</el-button>
         </el-row>
 
       </div>
@@ -245,19 +207,79 @@
     }
 
     const data = () => {
-      return {}
+      return {
+        process: {},
+        project: {},
+        supplierMaterials: []
+      }
     }
 
     const methods = {
       backLastPage() {
         window.history.back();
-      }
+      },
+      loadProject(id) {
+        const loading = this.$loading({
+          lock: true,
+          text: '正在加载项目',
+          spinner: 'el-icon-loading',
+          background: 'rgba(0, 0, 0, 0.7)'
+        })
+
+        fetch("${base}/process/" + id)
+            .then(res => res.json())
+            .then(data => {
+              const {
+                attachments, processId, isPrepaid, repaidAmount,
+                incomeDetails, process, projectType, cooperationType,
+                contract, supplierMaterials, procurementDetails, project
+              } = data
+              // 转换数据
+              // @formatter:off
+              const computeType = (type) => {
+                switch (type) {
+                  case 1: return '设备'
+                  case 2: return '工程'
+                  case 3: return '服务'
+                  default: return '未知'
+                }
+              }
+              // @formatter:on
+
+              this.incomeDetails = incomeDetails.map(detail => ({
+                ...detail, type: computeType(detail.type)
+              }))
+
+              this.process = process
+              this.project = project
+              this.isPrepaid = isPrepaid
+              this.repaidAmount = repaidAmount
+              this.contract = contract
+              this.processId = processId
+              this.projectType = projectType
+              this.cooperationType = cooperationType
+              this.supplierMaterials = supplierMaterials
+              this.procurementDetails = procurementDetails
+
+              this.attachments = attachments
+            })
+            .catch(err => {
+              this.$message.error("项目加载失败");
+            })
+            .finally(() => loading.close())
+      },
+
     }
 
     new Vue({
       el: '#app',
       data,
       methods,
+
+      mounted() {
+        const processId = ${processId}
+        this.loadProject(processId)
+      },
     })
 
   </script>