diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/common/model/constant/ExistsSqlConst.java b/hz-pm-api/src/main/java/com/hz/pm/api/common/model/constant/ExistsSqlConst.java index a270002..a4d6257 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/common/model/constant/ExistsSqlConst.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/common/model/constant/ExistsSqlConst.java @@ -23,6 +23,6 @@ public class ExistsSqlConst { public static final String PROJECT_EXISTS_PURCHASE_STATUS_CHANGE = "select 1 from nd_purchase_status_change npsc where npsc.project_code = nd_project.project_code "; - public static final String PURCHASE_EXISTS_PURCHASE_STATUS_CHANGE = "select 1 from nd_purchase_status_change npsc where npsc.bid_id = nd_purchase.id "; + public static final String PURCHASE_EXISTS_STATUS_CHANGE = "select 1 from nd_purchase_status_change npsc where npsc.bid_id = nd_purchase.id "; } diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/controller/ConstructionController.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/controller/ConstructionController.java index 23baaf7..d836593 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/controller/ConstructionController.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/controller/ConstructionController.java @@ -6,6 +6,7 @@ import com.hz.pm.api.projectdeclared.model.dto.PaymentPlanSupplementDTO; import com.hz.pm.api.projectdeclared.model.dto.PreInsSaveDTO; import com.hz.pm.api.projectdeclared.model.req.XcfhxApplyReq; import com.hz.pm.api.projectdeclared.model.vo.ContractVO; +import com.hz.pm.api.projectdeclared.model.vo.FirstAcceptProgressStatisticsVO; import com.hz.pm.api.projectdeclared.model.vo.PreInsVO; import com.hz.pm.api.projectdeclared.model.vo.ProjectContractListVO; import com.hz.pm.api.projectlib.model.req.ProjectListReq; @@ -70,6 +71,12 @@ public class ConstructionController { return constructionManage.supplement(plans); } + @GetMapping("/pre-ins/progressStatistics") + @ApiOperation("项目初验进度统计") + public FirstAcceptProgressStatisticsVO firstAcceptProgressStatistics(@ModelAttribute ProjectListReq req) { + return constructionManage.firstAcceptProgressStatistics(req); + } + @ApiOperation(value = "待初验备案的项目列表") @GetMapping("/pre-ins/project-list") public PageVo preProjectList(@ModelAttribute ProjectListReq req) { diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/ConstructionManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/ConstructionManage.java index 1e080f4..2a497cd 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/ConstructionManage.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/ConstructionManage.java @@ -2,6 +2,7 @@ package com.hz.pm.api.projectdeclared.manage; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.NumberUtil; import com.alibaba.excel.EasyExcel; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.StringUtils; @@ -11,6 +12,8 @@ import com.google.common.collect.Lists; import com.hz.pm.api.common.enumeration.ProjectProcessType; import com.hz.pm.api.common.helper.UserInfoHelper; import com.hz.pm.api.common.model.constant.BizConst; +import com.hz.pm.api.common.model.constant.ExistsSqlConst; +import com.hz.pm.api.common.statemachine.event.TenderStateChangeEvent; import com.hz.pm.api.common.statemachine.util.ProjectStateMachineUtil; import com.hz.pm.api.common.statemachine.util.TenderStateMachineUtil; import com.hz.pm.api.common.statemachine.util.XcfhxStateMachineUtil; @@ -23,16 +26,14 @@ import com.hz.pm.api.projectdeclared.model.dto.PaymentPlanSupplementDTO; import com.hz.pm.api.projectdeclared.model.dto.PreInsSaveDTO; import com.hz.pm.api.projectdeclared.model.entity.*; import com.hz.pm.api.projectdeclared.model.req.XcfhxApplyReq; -import com.hz.pm.api.projectdeclared.model.vo.ContractVO; -import com.hz.pm.api.projectdeclared.model.vo.PreInsAcceptancePersonVO; -import com.hz.pm.api.projectdeclared.model.vo.PreInsVO; -import com.hz.pm.api.projectdeclared.model.vo.ProjectContractListVO; +import com.hz.pm.api.projectdeclared.model.vo.*; import com.hz.pm.api.projectdeclared.service.*; import com.hz.pm.api.projectlib.helper.ProjectManageUtil; import com.hz.pm.api.projectlib.model.entity.Project; import com.hz.pm.api.projectlib.model.entity.ProjectAnnualPaymentPlan; import com.hz.pm.api.projectlib.model.entity.ProjectInst; import com.hz.pm.api.projectlib.model.enumeration.ProjectTypeNewEnum; +import com.hz.pm.api.projectlib.model.enumeration.status.ITenderStatus; import com.hz.pm.api.projectlib.model.enumeration.status.ProjectStatus; import com.hz.pm.api.projectlib.model.enumeration.status.TenderMainStatus; import com.hz.pm.api.projectlib.model.enumeration.status.TenderXcfhxApplyStatus; @@ -43,6 +44,8 @@ import com.hz.pm.api.projectlib.service.IProjectAnnualPaymentPlanService; import com.hz.pm.api.projectlib.service.IProjectInstService; import com.hz.pm.api.projectlib.service.IProjectService; import com.hz.pm.api.sys.manage.ProcessModelManage; +import com.hz.pm.api.user.helper.MhUnitQueryHelper; +import com.hz.pm.api.user.helper.MhUnitQueryHelper.UnitQueryState; import com.hz.pm.api.user.security.model.UserFullInfoDTO; import com.hz.pm.api.user.security.model.UserInfoDetails; import com.hz.pm.api.user.util.LoginUserUtil; @@ -69,6 +72,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiFunction; import java.util.stream.Collectors; /** @@ -98,12 +102,12 @@ public class ConstructionManage { private final TenderStateMachineUtil tenderStateMachineUtil; private final XcfhxStateMachineUtil xcfhxStateMachineUtil; private final MhXchxFileHelper mhXchxFileHelper; - private final IXinchuangService xinchuangService; private final TaskService taskService; private final IXinchuangInstService xinchuangInstService; + private final MhUnitQueryHelper mhUnitQueryHelper; /** * 待采购的-项目列表 @@ -293,6 +297,57 @@ public class ConstructionManage { PRE_INSPECTED_PURCHASE_STATUS.add(TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO); } + public FirstAcceptProgressStatisticsVO firstAcceptProgressStatistics(ProjectListReq req) { + UserInfoDetails user = LoginUserUtil.loginUserDetail(); + String buildOrgCode = req.clearBuildOrgCode(); + Long buildOrgCodeNum = NumberUtil.parseLong(buildOrgCode, null); + UnitQueryState queryState = mhUnitQueryHelper.listCanViewUnitIds(buildOrgCodeNum, user); + if (!queryState.isState()) { + return null; + } + LambdaQueryWrapper query = ProjectManageUtil.projectQuery(req) + .select(Project::getId) + .eq(Project::getNewest, Boolean.TRUE) + .ne(Project::getStage, ProjectStatus.STOPPED.getCode()) + .and(q1 -> q1.exists(ExistsSqlConst.PROJECT_EXISTS_PURCHASE + + " and np.status = {0} ", TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO.getCode()) + .or(q2 -> q2.exists(ExistsSqlConst.PROJECT_EXISTS_PURCHASE_STATUS_CHANGE + + " and npsc.event = {0}", TenderStateChangeEvent.SUBMIT_FIRST_INSPECTED_FILES))); + if (CollUtil.isNotEmpty(queryState.getUnitIds())) { + query.in(Project::getBuildOrgCode, CollUtils.convert(queryState.getUnitIds(), String::valueOf)); + } + List projects = projectService.list(query); + if (projects.isEmpty()) { + return null; + } + List projectIds = CollUtils.fieldList(projects, Project::getId); + LambdaQueryWrapper purchaseQuery = Wrappers.lambdaQuery(Purchase.class) + .select(Purchase::getStatus, Purchase::getProjectId) + .in(Purchase::getProjectId, projectIds) + .and(q1 -> q1.eq(Purchase::getStatus, TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO.getCode()) + .or(q2 -> q2.exists(ExistsSqlConst.PURCHASE_EXISTS_STATUS_CHANGE + + " and npsc.event = {0}", TenderStateChangeEvent.SUBMIT_FIRST_INSPECTED_FILES))); + List purchases = purchaseService.list(purchaseQuery); + Map> purchaseMap = purchases.stream() + .collect(Collectors.groupingBy(Purchase::getProjectId, + Collectors.mapping(w -> { + if (TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO.eq(w.getStatus())) { + return TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO; + } else { + return TenderMainStatus.SUBMITTED_FIRST_INSPECTED_INFO; + } + }, Collectors.toList()))); + BiFunction>, ITenderStatus, Integer> counter = (p, s) -> { + Collection> values = purchaseMap.values(); + return CollUtil.count(values, x -> CollUtil.anyMatch(x, w -> w.eq(s))); + }; + FirstAcceptProgressStatisticsVO stat = new FirstAcceptProgressStatisticsVO(); + stat.setTotalCount(projectIds.size()); + stat.setPassedCount(counter.apply(purchaseMap, TenderMainStatus.SUBMITTED_FIRST_INSPECTED_INFO)); + stat.setTodoCount(counter.apply(purchaseMap, TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO)); + return stat; + } + /** * 待初验项目列表 * @@ -301,29 +356,54 @@ public class ConstructionManage { */ public PageVo preProjectList(ProjectListReq req) { UserInfoDetails user = LoginUserUtil.loginUserDetail(); - Set projectIds = purchaseService.listProjectIdByStatus(PRE_INSPECTED_PURCHASE_STATUS); - if (projectIds.isEmpty()) { + String buildOrgCode = req.clearBuildOrgCode(); + Long buildOrgCodeNum = NumberUtil.parseLong(buildOrgCode, null); + UnitQueryState queryState = mhUnitQueryHelper.listCanViewUnitIds(buildOrgCodeNum, user); + if (!queryState.isState()) { return PageVo.empty(); } - LambdaQueryWrapper query = ProjectManageUtil.projectQuery(req); - query.in(Project::getId, projectIds); - query.eq(Project::getStage, ProjectStatus.PROJECT_APPROVED.getCode()); - query.eq(Project::getNewest, Boolean.TRUE); - //只能看自己单位的 - if (!user.hasSuperAdmin()) { - query.eq(Project::getBuildOrgCode, user.getMhUnitIdStr()); + String existsSql = String.format(ExistsSqlConst.PROJECT_EXISTS_PURCHASE_STATUS_CHANGE + + " and npsc.event = '%s'", TenderStateChangeEvent.SUBMIT_FIRST_INSPECTED_FILES); + LambdaQueryWrapper query = ProjectManageUtil.projectQuery(req) + .ne(Project::getStage, ProjectStatus.STOPPED.getCode()) + .eq(Project::getNewest, Boolean.TRUE) + .orderByAsc(Project::getDeliveryTime); + if (req.getTabStatus() != null) { + if (TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO.eq(req.getTabStatus())) { + query.exists(ExistsSqlConst.PROJECT_EXISTS_PURCHASE + " and np.status = {0} ", req.getTabStatus()); + } else { + query.exists(existsSql); + } + } else { + query.and(q1 -> q1.exists(ExistsSqlConst.PROJECT_EXISTS_PURCHASE + + " and np.status = {0} ", TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO.getCode()) + .or(q2 -> q2.exists(existsSql))); + } + if (CollUtil.isNotEmpty(queryState.getUnitIds())) { + query.in(Project::getBuildOrgCode, CollUtils.convert(queryState.getUnitIds(), String::valueOf)); } - query.orderByAsc(Project::getDeliveryTime); Page page = projectService.page(req.page(), query); - long total; - if ((total = page.getTotal()) == 0) { + if (page.getTotal() == 0) { return PageVo.empty(); } - List currPageProjectIds = CollUtils.fieldList(page.getRecords(), Project::getId); - List purchases = purchaseService.listByProjectIds(currPageProjectIds); + List projectIds = CollUtils.fieldList(page.getRecords(), Project::getId); + LambdaQueryWrapper purchaseQuery = Wrappers.lambdaQuery(Purchase.class) + .in(Purchase::getProjectId, projectIds); + if (req.getTabStatus() != null) { + if (TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO.eq(req.getTabStatus())) { + purchaseQuery.eq(Purchase::getStatus, req.getTabStatus()); + } else { + purchaseQuery.exists(ExistsSqlConst.PURCHASE_EXISTS_STATUS_CHANGE + + " and npsc.event = {0}", TenderStateChangeEvent.SUBMIT_FIRST_INSPECTED_FILES); + } + } else { + purchaseQuery.and(q1 -> q1.eq(Purchase::getStatus, TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO.getCode()) + .or(q2 -> q2.exists(ExistsSqlConst.PURCHASE_EXISTS_STATUS_CHANGE + + " and npsc.event = {0}", TenderStateChangeEvent.SUBMIT_FIRST_INSPECTED_FILES))); + } + List purchases = purchaseService.list(purchaseQuery); Map> purchaseMap = CollUtils.group(purchases, Purchase::getProjectId); Map contractMap = contractService.listByProjectIds(projectIds); - Map> paymentPlansMap = projectPaymentPlanService.listByProjectIds(projectIds); List records = CollUtils.convert(page.getRecords(), w -> { ProjectLibListItemVO item = new ProjectLibListItemVO(); @@ -345,11 +425,6 @@ public class ConstructionManage { item.setApprovalDate(w.getApprovalDate()); item.setDeliveryTime(w.getDeliveryTime()); item.setContractAmount(w.getContractAmount()); - List paymentPlans = paymentPlansMap.getOrDefault(w.getId(), Collections.emptyList()); - BigDecimal totalAnnualAmount = paymentPlans.stream() - .map(ProjectAnnualPaymentPlan::getAnnualPlanAmount) - .reduce(BigDecimal::add).orElse(BigDecimal.ZERO); - item.setAnnualPlanAmount(totalAnnualAmount); item.setTransactionTime(w.getTransactionTime()); item.setTransactionAmount(w.getTransactionAmount()); List currPurchases = purchaseMap.get(w.getId()); @@ -358,19 +433,24 @@ public class ConstructionManage { TenderListInfoVO tender = new TenderListInfoVO(); tender.setBidName(x.getBidName()); tender.setBidId(x.getId()); - tender.setBidStatus(x.getStatus()); - tender.setBidStatusName(TenderMainStatus.getDesc(x.getStatus())); Contract contract = contractMap.get(x.getId()); if (contract != null) { tender.setConstructionAmount(contract.getTotalAmount()); } + if (!TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO.eq(x.getStatus())) { + tender.setBidStatus(TenderMainStatus.SUBMITTED_FIRST_INSPECTED_INFO.getCode()); + tender.setBidStatusName(TenderMainStatus.SUBMITTED_FIRST_INSPECTED_INFO.getDesc()); + } else { + tender.setBidStatus(x.getStatus()); + tender.setBidStatusName(TenderMainStatus.getDesc(x.getStatus())); + } return tender; }); item.setTenders(tmpPurchases); } return item; }); - return PageVo.of(records, total); + return PageVo.of(records, page.getTotal()); } public void exportPreList(HttpServletResponse response, ProjectListReq param) { diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/PurchaseManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/PurchaseManage.java index 16d7471..a88a2b7 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/PurchaseManage.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/PurchaseManage.java @@ -205,7 +205,7 @@ public class PurchaseManage { if (TenderMainStatus.TO_BE_SUBMIT_PURCHASE_CONSTRUCTION_INFO.eq(req.getTabStatus())) { purchaseQuery.eq(Purchase::getStatus, req.getTabStatus()); } else if (TenderMainStatus.PURCHASE_FINISHED.eq(req.getTabStatus())) { - purchaseQuery.exists(ExistsSqlConst.PURCHASE_EXISTS_PURCHASE_STATUS_CHANGE + + purchaseQuery.exists(ExistsSqlConst.PURCHASE_EXISTS_STATUS_CHANGE + " and npsc.event = {0} ", TenderStateChangeEvent.SUBMIT_PURCHASE_CONSTRUCTION_INFO); } } @@ -544,7 +544,7 @@ public class PurchaseManage { LambdaQueryWrapper query = Wrappers.lambdaQuery(Purchase.class) .select(Purchase::getStatus, Purchase::getId) .eq(Purchase::getBidType, BidTypeEnum.BUILD_APP.getCode()) - .exists(ExistsSqlConst.PURCHASE_EXISTS_PURCHASE_STATUS_CHANGE + .exists(ExistsSqlConst.PURCHASE_EXISTS_STATUS_CHANGE + " and npsc.event = {0}", TenderStateChangeEvent.SUBMIT_PURCHASE_CONSTRUCTION_INFO) .notExists(ExistsSqlConst.PURCHASE_EXISTS_PROJECT + "and np.stage in ({0}, {1})", ProjectStatus.STOPPED.getCode(), @@ -605,7 +605,7 @@ public class PurchaseManage { private PageVo queryData(PurchaseAdaptionListReq req) { LambdaQueryWrapper query = Wrappers.lambdaQuery(Purchase.class) .eq(Purchase::getBidType, BidTypeEnum.BUILD_APP.getCode()) - .exists(ExistsSqlConst.PURCHASE_EXISTS_PURCHASE_STATUS_CHANGE + .exists(ExistsSqlConst.PURCHASE_EXISTS_STATUS_CHANGE + " and npsc.event = {0}", TenderStateChangeEvent.SUBMIT_PURCHASE_CONSTRUCTION_INFO) .notExists(ExistsSqlConst.PURCHASE_EXISTS_PROJECT + "and np.stage in ({0}, {1})", ProjectStatus.STOPPED.getCode(), diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/vo/FirstAcceptProgressStatisticsVO.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/vo/FirstAcceptProgressStatisticsVO.java new file mode 100644 index 0000000..4a882e1 --- /dev/null +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/vo/FirstAcceptProgressStatisticsVO.java @@ -0,0 +1,26 @@ +package com.hz.pm.api.projectdeclared.model.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * FirstAcceptProgressStatisticsVO + *

+ * + * @author WendyYang + * @since 14:23 2024/9/4 + */ +@Data +public class FirstAcceptProgressStatisticsVO { + + @ApiModelProperty("总数量") + private Integer totalCount; + + @ApiModelProperty("待初验数量") + private Integer todoCount; + + @ApiModelProperty("已初验数量") + private Integer passedCount; + +} diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/TenderMainStatus.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/TenderMainStatus.java index 7140a1e..9ccd67e 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/TenderMainStatus.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/TenderMainStatus.java @@ -31,6 +31,7 @@ public enum TenderMainStatus implements ITenderStatus { WAIT_ORG_CONFIRM(ProjectStatus.ON_ADAPTING, 104, "待单位确认"), ORG_CONFIRM_PASSED(ProjectStatus.ON_ADAPTING, 105, "单位已确认"), TO_BE_SUBMIT_FIRST_INSPECTED_INFO(ProjectStatus.TO_BE_FIRST_INSPECTED, 201, "待上传初验材料"), + SUBMITTED_FIRST_INSPECTED_INFO(ProjectStatus.TO_BE_FIRST_INSPECTED, 202, "已上传初验材料"), TO_BE_SUBMIT_FINALLY_INSPECTED_APPLY(ProjectStatus.ON_PILOT_RUNNING, 401, "待终验申报"), ON_FINALLY_INSPECTED_APPLY(ProjectStatus.ON_FINALLY_INSPECTED, 501, "终验申报中"), FINALLY_INSPECTED_FAILED(ProjectStatus.ON_FINALLY_INSPECTED, 502, "终验申报不通过"), diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/service/IPurchaseStatusChangeService.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/service/IPurchaseStatusChangeService.java index 9b161c5..55766e8 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/service/IPurchaseStatusChangeService.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/service/IPurchaseStatusChangeService.java @@ -5,15 +5,19 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.hz.pm.api.common.model.constant.BizConst; import com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent; import com.hz.pm.api.common.statemachine.event.TenderStateChangeEvent; +import com.hz.pm.api.common.util.BizUtils; import com.hz.pm.api.projectlib.entity.PurchaseStatusChange; import com.baomidou.mybatisplus.extension.service.IService; import com.hz.pm.api.projectlib.model.entity.ProjectStatusChange; +import com.ningdatech.basic.util.CollUtils; import java.util.Collection; +import java.util.Comparator; +import java.util.Map; /** *

- * 服务类 + * 服务类 *

* * @author WendyYang @@ -28,4 +32,14 @@ public interface IPurchaseStatusChangeService extends IService listLastOne(Collection bidIds, TenderStateChangeEvent event) { + LambdaQueryWrapper pscQuery = Wrappers.lambdaQuery(PurchaseStatusChange.class) + .in(PurchaseStatusChange::getBidId, bidIds) + .eq(PurchaseStatusChange::getEvent, event) + .orderByDesc(PurchaseStatusChange::getCreateOn); + return BizUtils.groupFirstMap(list(pscQuery), PurchaseStatusChange::getBidId, + Comparator.comparing(PurchaseStatusChange::getCreateOn).reversed()); + } + }