diff --git a/docs/project_fund_plan_table.sql b/docs/project_fund_plan_table.sql new file mode 100644 index 0000000..9a9ecde --- /dev/null +++ b/docs/project_fund_plan_table.sql @@ -0,0 +1,53 @@ +-- 项目资金计划表结构 +CREATE TABLE `PROJECT_FUND_PLAN` ( + `ID` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `PROJECT_ID` int DEFAULT NULL COMMENT '项目ID', + `PAY_DATE` date DEFAULT NULL COMMENT '付款日期', + `PAY_WAY` int DEFAULT NULL COMMENT '付款方式', + `PAY_RATIO` float DEFAULT NULL COMMENT '付款比例', + `PAY_CURRENCY` double DEFAULT NULL COMMENT '付款金额', + `PAY_TERM` varchar(255) DEFAULT NULL COMMENT '付款条件', + `CONTRACT_PAY_PLAN_ID` int DEFAULT NULL COMMENT '合同付款计划ID', + `UPDATE_TIME` datetime DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`ID`), + KEY `FK_PROJECT_FUND_PLAN_PROJECT` (`PROJECT_ID`), + KEY `FK_PROJECT_FUND_PLAN_CONTRACT_PAY_PLAN` (`CONTRACT_PAY_PLAN_ID`), + CONSTRAINT `FK_PROJECT_FUND_PLAN_PROJECT` FOREIGN KEY (`PROJECT_ID`) REFERENCES `PROJECT` (`ID`), + CONSTRAINT `FK_PROJECT_FUND_PLAN_CONTRACT_PAY_PLAN` FOREIGN KEY (`CONTRACT_PAY_PLAN_ID`) REFERENCES `CONTRACT_PAY_PLAN` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='项目资金计划'; + +/** Alert 增加 PAY_WAY **/ +ALTER TABLE `PROJECT_FUND_PLAN` +ADD COLUMN `PAY_WAY` int DEFAULT NULL COMMENT '付款方式'; + +-- 项目投标表结构 (参考) +CREATE TABLE `PROJECT_BID` ( + `ID` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `PROJECT_ID` int DEFAULT NULL COMMENT '项目ID', + `LEVEL` int NOT NULL COMMENT '客户资信等级', + `AMOUNT` double DEFAULT NULL COMMENT '报价金额', + `CUS_EVAL_FILE_ID` int DEFAULT NULL COMMENT '评价表单文件ID', + `COST_ID` int DEFAULT NULL COMMENT '成本ID', + `STANDARD_PAY_WAY` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否标准付款方式', + `NO_STANDARD_PAY_WAY_TEXT` varchar(255) DEFAULT NULL COMMENT '非标准付款方式文本', + `STANDARD_CONTRACT_TEXT` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否标准合同文本', + `NO_STANDARD_CONTRACT_TEXT` varchar(255) DEFAULT NULL COMMENT '非标准合同文本', + `AUTHORIZER_FILE` varchar(255) DEFAULT NULL COMMENT '审核文件', + `BID_ACCEPTANCE_LETTER_FILE` varchar(255) DEFAULT NULL COMMENT '中标通知书文件', + `APPLICANT_ID` int DEFAULT NULL COMMENT '申请人ID', + `APPLY_DATE` datetime DEFAULT NULL COMMENT '申请日期', + `AUTHORIZER_ID` int DEFAULT NULL COMMENT '审核人ID', + `AUTHORIZER_DATE` datetime DEFAULT NULL COMMENT '审核时间', + `DESCRIPTION` text COMMENT '说明', + PRIMARY KEY (`ID`), + KEY `FK_PROJECT_BID_PROJECT` (`PROJECT_ID`), + KEY `FK_PROJECT_BID_CUS_EVAL_FILE` (`CUS_EVAL_FILE_ID`), + KEY `FK_PROJECT_BID_COST` (`COST_ID`), + KEY `FK_PROJECT_BID_APPLICANT` (`APPLICANT_ID`), + KEY `FK_PROJECT_BID_AUTHORIZER` (`AUTHORIZER_ID`), + CONSTRAINT `FK_PROJECT_BID_PROJECT` FOREIGN KEY (`PROJECT_ID`) REFERENCES `PROJECT` (`ID`), + CONSTRAINT `FK_PROJECT_BID_CUS_EVAL_FILE` FOREIGN KEY (`CUS_EVAL_FILE_ID`) REFERENCES `COMPANY_CUSTOMER_EVALUATION_FORM_FILE` (`ID`), + CONSTRAINT `FK_PROJECT_BID_COST` FOREIGN KEY (`COST_ID`) REFERENCES `PROJECT_COST` (`ID`), + CONSTRAINT `FK_PROJECT_BID_APPLICANT` FOREIGN KEY (`APPLICANT_ID`) REFERENCES `EMPLOYEE` (`ID`), + CONSTRAINT `FK_PROJECT_BID_AUTHORIZER` FOREIGN KEY (`AUTHORIZER_ID`) REFERENCES `EMPLOYEE` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='项目投标'; \ No newline at end of file diff --git a/src/main/java/com/ecep/contract/manager/cloud/tyc/CloudTycService.java b/src/main/java/com/ecep/contract/manager/cloud/tyc/CloudTycService.java index d77c8de..b781202 100644 --- a/src/main/java/com/ecep/contract/manager/cloud/tyc/CloudTycService.java +++ b/src/main/java/com/ecep/contract/manager/cloud/tyc/CloudTycService.java @@ -1,15 +1,10 @@ package com.ecep.contract.manager.cloud.tyc; -import com.ecep.contract.manager.SpringApp; -import com.ecep.contract.manager.cloud.CloudInfo; -import com.ecep.contract.manager.ds.company.model.Company; -import com.ecep.contract.manager.ds.other.repository.SysConfRepository; -import com.ecep.contract.manager.ds.other.service.SysConfService; -import com.ecep.contract.manager.ui.MessageHolder; -import com.ecep.contract.manager.ui.ViewModelService; -import com.ecep.contract.manager.util.MyStringUtils; -import com.ecep.contract.manager.util.UITools; -import javafx.application.Platform; +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -21,10 +16,16 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; -import java.time.Instant; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; +import com.ecep.contract.manager.SpringApp; +import com.ecep.contract.manager.cloud.CloudInfo; +import com.ecep.contract.manager.ds.company.model.Company; +import com.ecep.contract.manager.ds.other.service.SysConfService; +import com.ecep.contract.manager.ui.MessageHolder; +import com.ecep.contract.manager.ui.ViewModelService; +import com.ecep.contract.manager.util.MyStringUtils; +import com.ecep.contract.manager.util.UITools; + +import javafx.application.Platform; @Lazy @Service diff --git a/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectTabSkinBid.java b/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectTabSkinBid.java index 95d0db9..00d84be 100644 --- a/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectTabSkinBid.java +++ b/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectTabSkinBid.java @@ -1,35 +1,33 @@ package com.ecep.contract.manager.ds.project.controller; -import com.ecep.contract.manager.SpringApp; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + import com.ecep.contract.manager.ds.company.CompanyStringConverter; import com.ecep.contract.manager.ds.company.service.CompanyService; import com.ecep.contract.manager.ds.customer.model.CompanyCustomerEvaluationFormFile; -import com.ecep.contract.manager.ds.customer.model.CompanyCustomerFile; import com.ecep.contract.manager.ds.customer.service.CompanyCustomerFileService; import com.ecep.contract.manager.ds.customer.service.CompanyCustomerService; import com.ecep.contract.manager.ds.other.EmployeeStringConverter; -import com.ecep.contract.manager.ui.table.cell.EmployeeTableCell; import com.ecep.contract.manager.ds.other.model.Employee; import com.ecep.contract.manager.ds.project.controller.bid.ProjectBidWindowController; import com.ecep.contract.manager.ds.project.model.Project; import com.ecep.contract.manager.ds.project.model.ProjectBid; import com.ecep.contract.manager.ds.project.service.ProjectBidService; import com.ecep.contract.manager.ds.project.vo.ProjectBidViewModel; -import com.ecep.contract.manager.ui.*; +import com.ecep.contract.manager.ui.FxmlPath; +import com.ecep.contract.manager.ui.RefreshableSkin; import com.ecep.contract.manager.ui.tab.TabSkin; import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin; -import javafx.scene.control.*; +import com.ecep.contract.manager.ui.table.cell.EmployeeTableCell; + +import javafx.scene.control.Tab; +import javafx.scene.control.TableCell; +import javafx.scene.control.TableColumn; import javafx.util.converter.LocalDateStringConverter; import lombok.Setter; -import org.hibernate.Hibernate; -import org.springframework.util.StringUtils; - -import java.io.File; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; -import java.util.concurrent.CompletableFuture; @FxmlPath("/ui/project/project-tab-bid.fxml") public class ProjectTabSkinBid diff --git a/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectTabSkinFundPlan.java b/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectTabSkinFundPlan.java new file mode 100644 index 0000000..2da6c2d --- /dev/null +++ b/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectTabSkinFundPlan.java @@ -0,0 +1,255 @@ +package com.ecep.contract.manager.ds.project.controller; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ecep.contract.manager.ds.contract.model.Contract; +import com.ecep.contract.manager.ds.contract.model.ContractPayPlan; +import com.ecep.contract.manager.ds.contract.service.ContractPayPlanService; +import com.ecep.contract.manager.ds.contract.service.ContractService; +import com.ecep.contract.manager.ds.project.model.Project; +import com.ecep.contract.manager.ds.project.model.ProjectFundPlan; +import com.ecep.contract.manager.ds.project.service.ProjectFundPlanService; +import com.ecep.contract.manager.ds.project.vo.ProjectFundPlanViewModel; +import com.ecep.contract.manager.ui.FxmlPath; +import com.ecep.contract.manager.ui.RefreshableSkin; +import com.ecep.contract.manager.ui.tab.TabSkin; +import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin; +import com.ecep.contract.manager.util.NumberUtils; + +import javafx.event.ActionEvent; +import javafx.scene.control.Button; +import javafx.scene.control.Tab; +import javafx.scene.control.TableColumn; +import lombok.Setter; + +/** + * 项目资金计划 + * 工单 #2 + * fxml 文件在 /src/main/resources/ui/ 目录 + */ +@FxmlPath("/ui/project/project-tab-fund-plan.fxml") +public class ProjectTabSkinFundPlan + extends AbstProjectTableTabSkin + implements TabSkin, EditableEntityTableTabSkin, RefreshableSkin { + private static final Logger logger = LoggerFactory.getLogger(ProjectTabSkinFundPlan.class); + + public TableColumn idColumn; + public TableColumn versionColumn; + public TableColumn payDateColumn; + public TableColumn payRatioColumn; + public TableColumn payCurrencyColumn; + public TableColumn payTermColumn; + public TableColumn updateDateColumn; + public TableColumn payWayColumn; + public Button updatePlanBtn; + + @Setter + private ProjectFundPlanService projectFundPlanService; + + public ProjectTabSkinFundPlan(ProjectWindowController controller) { + super(controller); + } + + @Override + protected ProjectFundPlanService getViewModelService() { + if (projectFundPlanService == null) { + projectFundPlanService = getBean(ProjectFundPlanService.class); + } + return projectFundPlanService; + } + + public ContractPayPlanService getContractPayPlanService() { + return controller.getCachedBean(ContractPayPlanService.class); + } + + private ContractService getContractService() { + return controller.getCachedBean(ContractService.class); + } + + @Override + public Tab getTab() { + return controller.fundPlanTab; + } + + @Override + public void initializeTable() { + super.initializeTable(); + // 关闭所有的排序功能 + idColumn.setSortable(false); + versionColumn.setSortable(false); + payDateColumn.setSortable(false); + payRatioColumn.setSortable(false); + payCurrencyColumn.setSortable(false); + payTermColumn.setSortable(false); + updateDateColumn.setSortable(false); + payWayColumn.setSortable(false); + + bindNumberColumn(idColumn, ProjectFundPlanViewModel::getId); + bindLocalDateColumn(payDateColumn, ProjectFundPlanViewModel::getPayDate); + bindColumn(payWayColumn, model -> { + javafx.beans.property.SimpleStringProperty property = new javafx.beans.property.SimpleStringProperty(); + property.set(model.getPayWay().get() != null ? model.getPayWay().get().getText() : ""); + return property; + }); + bindNumberColumn(payRatioColumn, ProjectFundPlanViewModel::getPayRatio); + bindNumberColumn(payCurrencyColumn, ProjectFundPlanViewModel::getPayCurrency); + bindColumn(payTermColumn, ProjectFundPlanViewModel::getPayTerm); + bindLocalDateTimeColumn(updateDateColumn, ProjectFundPlanViewModel::getUpdateDate); + updatePlanBtn.setOnAction(this::onUpdatePlanAction); + } + + @Override + public List loadTableData(Project parent) { + List rows = super.loadTableData(parent); + if (rows == null) { + return null; + } + // TODO 按付款日期排序 + // rows.stream().sorted(Comparator.comparing(ProjectFundPlanViewModel::getPayDate)).collect(Collectors.toList()); + + return rows; + + } + + /** + * 从合同的付款计划中更新项目的资金计划 + * 1. 从项目相关的合同中获取付款计划 + * 2. 更新项目的资金计划 + */ + private void onUpdatePlanAction(ActionEvent event) { + try { + // 获取当前项目 + Project project = getParent(); + if (project == null || project.getId() == null) { + setStatus("提示, 无法获取项目信息"); + return; + } + + List fundPlans = getViewModelService().findAllByProject(project); + // 将现有的项目资金计划转为以 ContractPayPlan 的id为key的map + java.util.Map fundPlansMap = fundPlans.stream() + .filter(plan -> plan.getContractPayPlan() != null && plan.getContractPayPlan().getId() != null) + .collect(Collectors.toMap( + plan -> plan.getContractPayPlan().getId(), + plan -> plan)); + + // 获取项目关联的所有合同 + List contracts = getContractService().findAllByProject(project); + if (contracts == null || contracts.isEmpty()) { + setStatus("提示, 未找到与项目关联的合同"); + return; + } + + // 遍历所有合同 + for (Contract contract : contracts) { + // 获取合同的付款计划 + List payPlans = getContractPayPlanService().findAllByContract(contract); + + // 遍历每个付款计划 + for (ContractPayPlan payPlan : payPlans) { + // 检查是否已存在相同的合同付款计划 + if (fundPlansMap.containsKey(payPlan.getId())) { + // 更新 + ProjectFundPlan fundPlan = fundPlansMap.remove(payPlan.getId()); + // 检查是否需要更新 + boolean needsUpdate = false; + if (!Objects.equals(fundPlan.getPayWay(), contract.getPayWay())) { + fundPlan.setPayWay(contract.getPayWay()); + needsUpdate = true; + } + if (!Objects.equals(fundPlan.getPayDate(), payPlan.getPayDate())) { + fundPlan.setPayDate(payPlan.getPayDate()); + needsUpdate = true; + } + if (!NumberUtils.equals(fundPlan.getPayRatio(), payPlan.getPayRatio())) { + fundPlan.setPayRatio(payPlan.getPayRatio()); + needsUpdate = true; + } + if (!Objects.equals(fundPlan.getPayTerm(), payPlan.getPayTerm())) { + fundPlan.setPayTerm(payPlan.getPayTerm()); + needsUpdate = true; + } + if (!NumberUtils.equals(fundPlan.getPayCurrency(), payPlan.getPayCurrency())) { + fundPlan.setPayCurrency(payPlan.getPayCurrency()); + needsUpdate = true; + } + if (needsUpdate) { + fundPlan.setContractPayPlan(payPlan); + fundPlan.setUpdateDate(LocalDateTime.now()); + saveRowData(fundPlan); + } + continue; + } + + // 创建新的项目资金计划 + ProjectFundPlan fundPlan = getViewModelService().newInstanceByProject(project); + // 设置资金计划的属性 + fundPlan.setPayDate(payPlan.getPayDate()); + fundPlan.setPayWay(contract.getPayWay()); + fundPlan.setPayRatio(payPlan.getPayRatio()); + fundPlan.setPayTerm(payPlan.getPayTerm()); + fundPlan.setPayCurrency(payPlan.getPayCurrency()); + fundPlan.setContractPayPlan(payPlan); + fundPlan.setUpdateDate(LocalDateTime.now()); + saveRowData(fundPlan); + } + } + + // 删除 + if (!fundPlansMap.isEmpty()) { + for (ProjectFundPlan fundPlan : fundPlansMap.values()) { + getViewModelService().delete(fundPlan); + } + } + // 刷新表格数据 + refresh(); + } catch (Exception e) { + logger.error("更新项目资金计划失败", e); + } + } + + @Override + protected ProjectFundPlanViewModel createNewViewModel() { + ProjectFundPlanViewModel model = new ProjectFundPlanViewModel(); + Project project = getParent(); + model.getProject().set(project); + model.getUpdateDate().set(LocalDateTime.now()); + saveRow(model); + return model; + } + + @Override + protected void onTableRowDoubleClickedAction(ProjectFundPlanViewModel item) { + // 可以在这里实现双击打开详情窗口的逻辑 + // 目前暂不实现具体的窗口 + } + + private ProjectFundPlanService getProjectFundPlanService() { + if (projectFundPlanService == null) { + projectFundPlanService = getBean(ProjectFundPlanService.class); + } + return projectFundPlanService; + } + + @Override + public void deleteRowData(ProjectFundPlan entity) { + getProjectFundPlanService().delete(entity); + } + + @Override + public ProjectFundPlan loadRowData(ProjectFundPlanViewModel row) { + return getProjectFundPlanService().findById(row.getId().get()); + } + + @Override + public ProjectFundPlan saveRowData(ProjectFundPlan entity) { + return getProjectFundPlanService().save(entity); + } +} diff --git a/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectWindowController.java b/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectWindowController.java index 76814ef..054c66f 100644 --- a/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectWindowController.java +++ b/src/main/java/com/ecep/contract/manager/ds/project/controller/ProjectWindowController.java @@ -108,6 +108,13 @@ public class ProjectWindowController extends AbstEntityController new ProjectTabSkinCost(this)); registerTabSkin(quotationApprovalTab, tab -> new ProjectTabSkinQuotation(this)); registerTabSkin(bidTab, tab -> new ProjectTabSkinBid(this)); + registerTabSkin(fundPlanTab, tab -> new ProjectTabSkinFundPlan(this)); // registerTabSkin(costItemTab, this::createCostItemTabSkin); registerTabSkin(satisfactionTab, tab -> new ProjectTabSkinCustomerSatisfactionSurvey(this)); } diff --git a/src/main/java/com/ecep/contract/manager/ds/project/model/ProjectFundPlan.java b/src/main/java/com/ecep/contract/manager/ds/project/model/ProjectFundPlan.java new file mode 100644 index 0000000..f8e3868 --- /dev/null +++ b/src/main/java/com/ecep/contract/manager/ds/project/model/ProjectFundPlan.java @@ -0,0 +1,81 @@ +package com.ecep.contract.manager.ds.project.model; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import com.ecep.contract.manager.ds.contract.ContractPayWay; +import com.ecep.contract.manager.ds.contract.model.ContractPayPlan; +import com.ecep.contract.manager.ds.other.model.IdentityEntity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + * 项目投标 + *

+ * Approval 审批 + */ +@Getter +@Setter +@Entity +@Table(name = "PROJECT_FUND_PLAN") +@ToString +public class ProjectFundPlan implements IdentityEntity, ProjectBasedEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ID", nullable = false) + private Integer id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "PROJECT_ID") + private Project project; + /** + * 付款日期 + */ + @Column(name = "PAY_DATE") + private LocalDate payDate; + /** + * 付款方式 + */ + @Column(name = "PAY_WAY") + @Enumerated(EnumType.ORDINAL) + private ContractPayWay payWay; + /** + * 付款比例 + */ + @Column(name = "PAY_RATIO") + private float payRatio; + /** + * 付款金额 + */ + @Column(name = "PAY_CURRENCY") + private double payCurrency; + /** + * 付款条件 + */ + @Column(name = "PAY_TERM") + private String payTerm; + + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "CONTRACT_PAY_PLAN_ID") + private ContractPayPlan contractPayPlan; + + /** + * 更新日期,从销售合同和采购合同中更新 + */ + @Column(name = "UPDATE_TIME") + private LocalDateTime updateDate; +} diff --git a/src/main/java/com/ecep/contract/manager/ds/project/repository/ProjectBidRepository.java b/src/main/java/com/ecep/contract/manager/ds/project/repository/ProjectBidRepository.java index 053b877..6f92566 100644 --- a/src/main/java/com/ecep/contract/manager/ds/project/repository/ProjectBidRepository.java +++ b/src/main/java/com/ecep/contract/manager/ds/project/repository/ProjectBidRepository.java @@ -1,16 +1,15 @@ package com.ecep.contract.manager.ds.project.repository; -import com.ecep.contract.manager.ds.project.model.Project; -import com.ecep.contract.manager.ds.project.model.ProjectBid; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.stereotype.Repository; - import java.util.List; +import org.springframework.stereotype.Repository; + +import com.ecep.contract.manager.ds.MyRepository; +import com.ecep.contract.manager.ds.project.model.Project; +import com.ecep.contract.manager.ds.project.model.ProjectBid; + @Repository -public interface ProjectBidRepository - extends JpaRepository, JpaSpecificationExecutor { +public interface ProjectBidRepository extends MyRepository { /** * 根据项目查询 diff --git a/src/main/java/com/ecep/contract/manager/ds/project/repository/ProjectFundPlanRepository.java b/src/main/java/com/ecep/contract/manager/ds/project/repository/ProjectFundPlanRepository.java new file mode 100644 index 0000000..f55ead4 --- /dev/null +++ b/src/main/java/com/ecep/contract/manager/ds/project/repository/ProjectFundPlanRepository.java @@ -0,0 +1,20 @@ +package com.ecep.contract.manager.ds.project.repository; + +import java.util.List; + +import org.springframework.stereotype.Repository; + +import com.ecep.contract.manager.ds.MyRepository; +import com.ecep.contract.manager.ds.project.model.Project; +import com.ecep.contract.manager.ds.project.model.ProjectFundPlan; + +@Repository +public interface ProjectFundPlanRepository extends MyRepository { + /** + * 根据项目查询 + * + * @param project 项目 + * @return ProjectFundPlan list + */ + List findAllByProject(Project project); +} diff --git a/src/main/java/com/ecep/contract/manager/ds/project/service/ProjectFundPlanService.java b/src/main/java/com/ecep/contract/manager/ds/project/service/ProjectFundPlanService.java new file mode 100644 index 0000000..34d3414 --- /dev/null +++ b/src/main/java/com/ecep/contract/manager/ds/project/service/ProjectFundPlanService.java @@ -0,0 +1,72 @@ +package com.ecep.contract.manager.ds.project.service; + +import com.ecep.contract.manager.ds.project.model.Project; +import com.ecep.contract.manager.ds.project.model.ProjectFundPlan; +import com.ecep.contract.manager.ds.project.repository.ProjectFundPlanRepository; +import com.ecep.contract.manager.ds.project.vo.ProjectFundPlanViewModel; +import com.ecep.contract.manager.ui.ViewModelService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +@Lazy +@Service +public class ProjectFundPlanService implements ViewModelService { + private static final Logger logger = LoggerFactory.getLogger(ProjectFundPlanService.class); + + @Lazy + @Autowired + private ProjectFundPlanRepository repository; + + public ProjectFundPlan findById(Integer id) { + return repository.findById(id).orElse(null); + } + + @Override + public Page findAll(Specification spec, Pageable pageable) { + return repository.findAll(spec, pageable); + } + + public List findAllByProject(Project project) { + return repository.findAllByProject(project); + } + + public ProjectFundPlan save(ProjectFundPlan fundPlan) { + return repository.save(fundPlan); + } + + @Override + public Specification getSpecification(String searchText) { + return (root, query, builder) -> { + return builder.or( + builder.like(root.get("payTerm"), "%" + searchText + "%"), + builder.like(builder.toString(root.get("payRatio")), "%" + searchText + "%"), + builder.like(builder.toString(root.get("payCurrency")), "%" + searchText + "%") + ); + }; + } + + public void delete(ProjectFundPlan fundPlan) { + repository.delete(fundPlan); + } + + public ProjectFundPlan newInstanceByProject(Project project) { + ProjectFundPlan fundPlan = new ProjectFundPlan(); + fundPlan.setProject(project); + fundPlan.setUpdateDate(LocalDateTime.now()); + return fundPlan; + } + + public List findAll(Specification spec, Sort sort) { + return repository.findAll(spec, sort); + } +} diff --git a/src/main/java/com/ecep/contract/manager/ds/project/vo/ProjectFundPlanViewModel.java b/src/main/java/com/ecep/contract/manager/ds/project/vo/ProjectFundPlanViewModel.java new file mode 100644 index 0000000..d9b12fa --- /dev/null +++ b/src/main/java/com/ecep/contract/manager/ds/project/vo/ProjectFundPlanViewModel.java @@ -0,0 +1,154 @@ +package com.ecep.contract.manager.ds.project.vo; + +import com.ecep.contract.manager.ds.contract.ContractPayWay; +import com.ecep.contract.manager.ds.contract.model.ContractPayPlan; +import com.ecep.contract.manager.ds.other.vo.IdentityViewModel; +import com.ecep.contract.manager.ds.project.model.Project; +import com.ecep.contract.manager.ds.project.model.ProjectFundPlan; +import com.ecep.contract.manager.util.NumberUtils; + +import javafx.beans.property.SimpleDoubleProperty; +import javafx.beans.property.SimpleFloatProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Objects; + +/** + * 项目资金计划视图模型 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class ProjectFundPlanViewModel extends IdentityViewModel implements ProjectBasedViewModel { + /** + * 关联的项目 + */ + private SimpleObjectProperty project = new SimpleObjectProperty<>(); + + /** + * 付款日期 + */ + private SimpleObjectProperty payDate = new SimpleObjectProperty<>(); + + /** + * 付款比例 + */ + private SimpleFloatProperty payRatio = new SimpleFloatProperty(); + + /** + * 付款金额 + */ + private SimpleDoubleProperty payCurrency = new SimpleDoubleProperty(); + /** + * 余额 + */ + private SimpleDoubleProperty balance = new SimpleDoubleProperty(); + /** + * 付款条件 + */ + private SimpleStringProperty payTerm = new SimpleStringProperty(); + + /** + * 合同付款计划 + */ + private SimpleObjectProperty contractPayPlan = new SimpleObjectProperty<>(); + + /** + * 更新日期 + */ + private SimpleObjectProperty updateDate = new SimpleObjectProperty<>(); + + /** + * 付款方式 + */ + private SimpleObjectProperty payWay = new SimpleObjectProperty<>(); + + /** + * 从实体对象创建视图模型 + */ + public static ProjectFundPlanViewModel from(ProjectFundPlan entity) { + ProjectFundPlanViewModel model = new ProjectFundPlanViewModel(); + model.update(entity); + return model; + } + + @Override + protected void updateFrom(ProjectFundPlan entity) { + super.updateFrom(entity); + + // 设置项目关联 + getProject().set(entity.getProject()); + + // 设置付款相关信息 + getPayDate().set(entity.getPayDate()); + getPayRatio().set(entity.getPayRatio()); + getPayCurrency().set(entity.getPayCurrency()); + getPayTerm().set(entity.getPayTerm()); + + // 设置合同付款计划关联 + getContractPayPlan().set(entity.getContractPayPlan()); + + // 设置更新日期 + getUpdateDate().set(entity.getUpdateDate()); + + // 设置付款方式 + getPayWay().set(entity.getPayWay()); + } + + @Override + public boolean copyTo(ProjectFundPlan entity) { + boolean modified = super.copyTo(entity); + + // 复制项目关联 + if (!Objects.equals(getProject().get(), entity.getProject())) { + entity.setProject(getProject().get()); + modified = true; + } + + // 复制付款相关信息 + if (!Objects.equals(getPayDate().get(), entity.getPayDate())) { + entity.setPayDate(getPayDate().get()); + modified = true; + } + + if (!NumberUtils.equals(getPayRatio().get(), entity.getPayRatio())) { + entity.setPayRatio(getPayRatio().get()); + modified = true; + } + + if (!NumberUtils.equals(getPayCurrency().get(), entity.getPayCurrency())) { + entity.setPayCurrency(getPayCurrency().get()); + modified = true; + } + + if (!Objects.equals(getPayTerm().get(), entity.getPayTerm())) { + entity.setPayTerm(getPayTerm().get()); + modified = true; + } + + // 复制合同付款计划关联 + if (!Objects.equals(getContractPayPlan().get(), entity.getContractPayPlan())) { + entity.setContractPayPlan(getContractPayPlan().get()); + modified = true; + } + + // 复制更新日期 + if (!Objects.equals(getUpdateDate().get(), entity.getUpdateDate())) { + entity.setUpdateDate(getUpdateDate().get()); + modified = true; + } + + // 复制付款方式 + if (!Objects.equals(getPayWay().get(), entity.getPayWay())) { + entity.setPayWay(getPayWay().get()); + modified = true; + } + + return modified; + } + +} diff --git a/src/main/resources/ui/project/project-tab-fund-plan.fxml b/src/main/resources/ui/project/project-tab-fund-plan.fxml new file mode 100644 index 0000000..a17d633 --- /dev/null +++ b/src/main/resources/ui/project/project-tab-fund-plan.fxml @@ -0,0 +1,37 @@ + + + + + + + + + + + +