diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/controller/PurchaseController.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/controller/PurchaseController.java index 3d0a7fd..ac52265 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/controller/PurchaseController.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/controller/PurchaseController.java @@ -6,7 +6,6 @@ import com.ningdatech.pmapi.common.util.ExcelDownUtil; import com.ningdatech.pmapi.projectdeclared.manage.ProjectAdjustmentManage; import com.ningdatech.pmapi.projectdeclared.manage.PurchaseManage; import com.ningdatech.pmapi.projectdeclared.model.dto.PurchaseSaveDTO; -import com.ningdatech.pmapi.projectdeclared.model.dto.PurchaseSaveDTOV1; import com.ningdatech.pmapi.projectdeclared.model.vo.PurchaseVO; import com.ningdatech.pmapi.projectlib.model.req.ProjectListReq; import com.ningdatech.pmapi.projectlib.model.vo.ProjectLibListItemVO; @@ -56,19 +55,11 @@ public class PurchaseController { ExcelDownUtil.downXls(response, req, purchaseManage::exportList); } - /*@ApiOperation(value = "填写采购结果", notes = "填写采购结果") + @ApiOperation(value = "填写采购结果", notes = "填写采购结果") @WebLog("填写采购结果") @PostMapping("/submit-result") public String submitResult(@Validated @RequestBody PurchaseSaveDTO dto) { return purchaseManage.submitResult(dto); - }*/ - - @ApiOperation(value = "填写采购结果", notes = "填写采购结果") - @WebLog("填写采购结果") - @PostMapping("/submit-result") - public String submitResult(@Validated @RequestBody PurchaseSaveDTOV1 dto) { - return purchaseManage.submitResultV1(dto); } - } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/PurchaseManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/PurchaseManage.java index 55b7afb..98c7f11 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/PurchaseManage.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/PurchaseManage.java @@ -4,7 +4,6 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.lang.Assert; import com.alibaba.excel.EasyExcel; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.google.common.collect.Lists; import com.ningdatech.basic.exception.BizException; @@ -12,14 +11,12 @@ import com.ningdatech.basic.function.VUtils; import com.ningdatech.basic.model.PageVo; import com.ningdatech.basic.util.CollUtils; import com.ningdatech.basic.util.NdDateUtils; -import com.ningdatech.pmapi.common.constant.BizConst; import com.ningdatech.pmapi.common.helper.UserInfoHelper; import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils; import com.ningdatech.pmapi.common.util.ExcelDownUtil; import com.ningdatech.pmapi.common.util.ExcelExportStyle; import com.ningdatech.pmapi.projectdeclared.model.dto.DeclaredProjectExportDTO; import com.ningdatech.pmapi.projectdeclared.model.dto.PurchaseSaveDTO; -import com.ningdatech.pmapi.projectdeclared.model.dto.PurchaseSaveDTOV1; import com.ningdatech.pmapi.projectdeclared.model.entity.Purchase; import com.ningdatech.pmapi.projectdeclared.model.vo.PurchaseVO; import com.ningdatech.pmapi.projectdeclared.service.IPurchaseService; @@ -230,60 +227,4 @@ public class PurchaseManage { return "保存失败"; } - /** - * 填写采购结果 - * - * @param dto - * @return - */ - public String submitResultV1(PurchaseSaveDTOV1 dto) { - UserFullInfoDTO user = userInfoHelper.getUserFullInfo(LoginUserUtil.getUserId()); - String employeeCode = user.getEmployeeCode(); - VUtils.isTrue(StringUtils.isBlank(employeeCode)).throwMessage("获取登录用户 员工号 失败!"); - - Long projectId = dto.getProjectId(); - VUtils.isTrue(Objects.isNull(projectId)).throwMessage("提交失败 缺少项目ID!"); - Project project = projectService.getNewProject(dto.getProjectId()); - VUtils.isTrue(Objects.isNull(project)).throwMessage("提交失败 此项目不存在!"); - - //首先要判断 项目当前状态 是不是 采购结果备案 - VUtils.isTrue(!ProjectStatusEnum.TO_BE_PURCHASED.eq(project.getStatus()) - || !ProjectStatusEnum.PROJECT_APPROVED.eq(project.getStage())) - .throwMessage("提交失败 该项目不是 待采购备案状态或者已立项阶段"); - - Purchase purchase1 = purchaseService.getOne(Wrappers.lambdaQuery(Purchase.class) - .eq(Purchase::getProjectId, projectId) - .last(BizConst.LIMIT_1)); - Purchase purchase = BeanUtil.copyProperties(dto, Purchase.class); - if (purchase1 == null) { - purchase.setCreateBy(employeeCode); - purchase.setCreateOn(LocalDateTime.now()); - } - purchase.setProjectId(projectId); - - if (purchaseService.saveOrUpdate(purchase)) { - // 如果 需要推送项目和应用管理的话 只有遂昌县才有 - // String areaCode = project.getAreaCode(); - // String appCode = dto.getAppCode(); - // if(RegionConst.RC_SC.equals(areaCode) && StringUtils.isNotBlank(appCode)){ - // try{ - // - // }catch (Exception e){ - // log.info("绑定以及推送项目和应用关系 失败! {}" + e.getMessage()); - // } - // } - //进入到下一状态 - stateMachineUtils.pass(project); - project.setUpdateOn(LocalDateTime.now()); - - // 获取总的成交时间及金额 - project.setTransactionAmount(purchase.getTransactionAmount()); - project.setTransactionTime(purchase.getTransactionTime()); - projectService.updateById(project); - - return "填写成功"; - } - - return "保存失败"; - } } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/model/dto/PurchaseSaveDTOV1.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/model/dto/PurchaseSaveDTOV1.java deleted file mode 100644 index 7a5ee25..0000000 --- a/pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/model/dto/PurchaseSaveDTOV1.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.ningdatech.pmapi.projectdeclared.model.dto; - -import com.fasterxml.jackson.annotation.JsonFormat; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; - -import javax.validation.constraints.NotNull; -import java.math.BigDecimal; -import java.time.LocalDateTime; - -/** - * @Classname Purchase - * @Description - * @Date 2023/5/29 10:00 - * @Author PoffyZhang - */ -@Data -@ApiModel(value = "采购对象", description = "采购对象") -@AllArgsConstructor -public class PurchaseSaveDTOV1 { - - @ApiModelProperty("项目ID") - @NotNull(message = "请传项目ID") - private Long projectId; - - @ApiModelProperty("供应商") - private String supplier; - - @ApiModelProperty("供应商联系人") - private String supplierContact; - - @ApiModelProperty("供应商联系方式") - private String supplierContactInfo; - - @ApiModelProperty("采购方式 1公开招标 2自行采购") - private Integer purchaseMethod; - - @ApiModelProperty("成交金额") - private BigDecimal transactionAmount; - - @ApiModelProperty("成交时间") - @JsonFormat(pattern = "yyyy-MM-dd") - private LocalDateTime transactionTime; - - @ApiModelProperty("代理机构") - private String agency; - - @ApiModelProperty("投标文件") - private String biddingDoc; - - @ApiModelProperty("招标文件") - private String bidDoc; - - @ApiModelProperty("中标通知书") - private String acceptanceLetter; - - @ApiModelProperty("应用编码") - private String appCode; - -} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/controller/ProcessStatisticsController.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/controller/ProcessStatisticsController.java new file mode 100644 index 0000000..7ebf22f --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/controller/ProcessStatisticsController.java @@ -0,0 +1,39 @@ +package com.ningdatech.pmapi.sys.controller; + +import com.ningdatech.pmapi.projectlib.enumeration.InstTypeEnum; +import com.ningdatech.pmapi.sys.manage.ProcessStatisticsManage; +import com.ningdatech.pmapi.sys.model.vo.ProcessDetailStatVO; +import lombok.AllArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import java.util.concurrent.TimeUnit; + +/** + *

+ * ProcessStatisticsController + *

+ * + * @author WendyYang + * @since 2023/7/31 + **/ +@Validated +@RestController +@RequestMapping("/api/v1/process/statistics") +@AllArgsConstructor +public class ProcessStatisticsController { + + private final ProcessStatisticsManage processStatisticsManage; + + @GetMapping("detailByInstType") + public ProcessDetailStatVO processDetailStat(@RequestParam(required = false, defaultValue = "DAYS") TimeUnit unit, + @Valid @NotNull(message = "流程类型不能为空") InstTypeEnum instType) { + return processStatisticsManage.processDetailStat(unit, instType); + } + +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/manage/ProcessStatisticsManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/manage/ProcessStatisticsManage.java new file mode 100644 index 0000000..7ad08f6 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/manage/ProcessStatisticsManage.java @@ -0,0 +1,74 @@ +package com.ningdatech.pmapi.sys.manage; + +import cn.hutool.core.util.NumberUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.pmapi.projectlib.enumeration.InstTypeEnum; +import com.ningdatech.pmapi.projectlib.model.entity.ProjectInst; +import com.ningdatech.pmapi.projectlib.service.IProjectInstService; +import com.ningdatech.pmapi.sys.model.vo.ProcessDetailStatVO; +import lombok.AllArgsConstructor; +import org.flowable.engine.HistoryService; +import org.flowable.engine.history.HistoricProcessInstance; +import org.springframework.stereotype.Component; + +import java.util.HashSet; +import java.util.List; +import java.util.LongSummaryStatistics; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + *

+ * ProcessStatisticsManage + *

+ * + * @author WendyYang + * @since 2023/7/31 + **/ +@Component +@AllArgsConstructor +public class ProcessStatisticsManage { + + private final HistoryService historyService; + private final IProjectInstService projectInstService; + + public ProcessDetailStatVO processDetailStat(TimeUnit unit, InstTypeEnum instType) { + if (!TimeUnit.DAYS.equals(unit) && !TimeUnit.HOURS.equals(unit)) { + throw BizException.wrap("仅支持以天和小时为单位的统计"); + } + ProcessDetailStatVO detailStat = ProcessDetailStatVO.init(); + LambdaQueryWrapper modelQuery = Wrappers.lambdaQuery(ProjectInst.class) + .select(ProjectInst::getInstCode) + .eq(ProjectInst::getInstType, instType.getCode()); + List projectInsts = projectInstService.list(modelQuery); + if (projectInsts.isEmpty()) { + return detailStat; + } + List instCodeList = CollUtils.fieldList(projectInsts, ProjectInst::getInstCode); + List instances = historyService.createHistoricProcessInstanceQuery() + .processInstanceIds(new HashSet<>(instCodeList)) + .list(); + detailStat.setTotalInst(instances.size()); + LongSummaryStatistics statistics = instances.stream().filter(w -> { + boolean finished = w.getEndTime() != null; + if (finished) { + detailStat.incrFinished(); + } else { + detailStat.incrPending(); + } + return finished; + }).map(HistoricProcessInstance::getDurationInMillis) + .collect(Collectors.summarizingLong(Long::longValue)); + if (detailStat.getFinishedInst() != 0) { + long unitMillis = unit.toMillis(1); + detailStat.setAvgTime(NumberUtil.div(statistics.getAverage(), unitMillis, 1)); + detailStat.setMaxTime(NumberUtil.div(statistics.getMax(), unitMillis, 1)); + detailStat.setMinTime(NumberUtil.div(statistics.getMin(), unitMillis, 1)); + } + return detailStat; + } + +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/model/vo/ProcessDetailStatVO.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/model/vo/ProcessDetailStatVO.java new file mode 100644 index 0000000..6e92b4a --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/model/vo/ProcessDetailStatVO.java @@ -0,0 +1,56 @@ +package com.ningdatech.pmapi.sys.model.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.concurrent.TimeUnit; + +/** + *

+ * ProcessDetailStatVO + *

+ * + * @author WendyYang + * @since 2023/7/31 + **/ +@Data +public class ProcessDetailStatVO { + + @ApiModelProperty("流程实例总数") + private Integer totalInst; + + @ApiModelProperty("已完成流程实例数") + private Integer finishedInst; + + @ApiModelProperty("已完成流程实例数") + private Integer pendingInst; + + @ApiModelProperty("平均耗时") + private double avgTime; + + @ApiModelProperty("最长耗时") + private double maxTime; + + @ApiModelProperty("最短耗时") + private double minTime; + + @ApiModelProperty("时间单位") + private TimeUnit timeUnit; + + public static ProcessDetailStatVO init() { + ProcessDetailStatVO stat = new ProcessDetailStatVO(); + stat.setFinishedInst(0); + stat.setTotalInst(0); + stat.setPendingInst(0); + return stat; + } + + public void incrPending() { + this.pendingInst += 1; + } + + public void incrFinished() { + this.finishedInst += 1; + } + +} diff --git a/pmapi/src/test/java/com/ningdatech/pmapi/instance/InstanceTest.java b/pmapi/src/test/java/com/ningdatech/pmapi/instance/InstanceTest.java index c7620b1..1b64794 100644 --- a/pmapi/src/test/java/com/ningdatech/pmapi/instance/InstanceTest.java +++ b/pmapi/src/test/java/com/ningdatech/pmapi/instance/InstanceTest.java @@ -3,26 +3,21 @@ package com.ningdatech.pmapi.instance; import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.ningdatech.basic.model.PageVo; import com.ningdatech.pmapi.AppTests; import com.ningdatech.pmapi.projectlib.manage.ProjectLibManage; import com.ningdatech.pmapi.projectlib.model.entity.Project; import com.ningdatech.pmapi.projectlib.model.entity.ProjectInst; import com.ningdatech.pmapi.projectlib.model.req.ProjectListReq; import com.ningdatech.pmapi.projectlib.service.IProjectInstService; -import com.wflow.contants.ProcessConstant; -import com.wflow.workflow.bean.dto.ProcessInstanceUserDto; import com.wflow.workflow.bean.dto.TodoCenterListReqDTO; -import com.wflow.workflow.enums.ProcessHandlerEnum; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.history.HistoricActivityInstance; +import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.runtime.ActivityInstance; import org.flowable.task.api.history.HistoricTaskInstance; import org.flowable.task.service.history.NativeHistoricTaskInstanceQuery; -import org.flowable.variable.api.history.HistoricVariableInstance; import org.junit.Test; -import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import java.util.*; @@ -49,7 +44,7 @@ public class InstanceTest extends AppTests { private IProjectInstService projectInstService; @Test - public void test(){ + public void test() { String instanceId = "896fa188-96d8-11ed-9539-e2d4e8f16b2f"; Object user = runtimeService.getVariable(instanceId, "owner"); @@ -57,7 +52,7 @@ public class InstanceTest extends AppTests { } @Test - public void testHistory(){ + public void testHistory() { //如果有已经被审核过的 节点 List finished = historyService.createHistoricActivityInstanceQuery() .processInstanceId("085af7ef-d133-11ed-a3f6-02426daa406d").finished() @@ -68,7 +63,7 @@ public class InstanceTest extends AppTests { } @Test - public void testRuntime(){ + public void testRuntime() { //如果有已经被审核过的 节点 List userTask = runtimeService.createActivityInstanceQuery() .processInstanceId("1709ebe3-d148-11ed-9351-02426daa406d") @@ -78,7 +73,7 @@ public class InstanceTest extends AppTests { } @Test - public void testTodo(){ + public void testTodo() { String employeeCode = "GE_e9d5c7917acd4eeea04ff2a9454af62e"; // 查出项目库项目 ProjectListReq projectListReq = new ProjectListReq(); @@ -93,7 +88,7 @@ public class InstanceTest extends AppTests { List projectInstList = projectInstService.list(Wrappers.lambdaQuery(ProjectInst.class) .in(ProjectInst::getProjectId, projectIdList) .orderByDesc(ProjectInst::getProjectId)); - Map projectInfoMap = projectInstList.stream().collect(Collectors.toMap(ProjectInst::getInstCode, p-> projectsMap.get(p.getProjectId()))); + Map projectInfoMap = projectInstList.stream().collect(Collectors.toMap(ProjectInst::getInstCode, p -> projectsMap.get(p.getProjectId()))); List instCodes = projectInstList.stream().map(ProjectInst::getInstCode).collect(Collectors.toList()); // 查出用户工作流 @@ -108,7 +103,7 @@ public class InstanceTest extends AppTests { historyService.createNativeHistoricTaskInstanceQuery().sql(nativeSql); List taskInstances = taskInstanceQuery.list(); - Set set = new HashSet(); + Set set = new HashSet<>(); List taskInstanceList = taskInstances.stream() .filter(t -> instCodes.contains(t.getProcessInstanceId())) .sorted(Comparator.comparing(HistoricTaskInstance::getEndTime)).collect(Collectors.toList()) @@ -120,14 +115,34 @@ public class InstanceTest extends AppTests { } @Test - public void test2(){ + public void test2() { // 获取节点处理结果 // Map varMap = historyService.createHistoricVariableInstanceQuery() // .processInstanceId("e99fe24c-d21c-11ed-af5d-02426daa406d") // .variableNameLike("approve_%") // .list().stream() // .collect(Collectors.toMap(HistoricVariableInstance::getVariableName, v -> (ProcessHandlerEnum) v.getValue())); - runtimeService.removeVariable("564102ce-d1ff-11ed-b694-02424b2b849f","approve_7d2a191a-d1ff-11ed-b694-02424b2b849f"); + runtimeService.removeVariable("564102ce-d1ff-11ed-b694-02424b2b849f", "approve_7d2a191a-d1ff-11ed-b694-02424b2b849f"); System.out.println(1); } + + @Test + public void usageTimeStat() { + // 查询所有已完成的流程实例 + List processInstanceList = historyService.createHistoricProcessInstanceQuery() + .orderByProcessInstanceStartTime() + .desc() + .finished() + .list(); + + // 统计每个流程实例的审批耗时 + for (HistoricProcessInstance processInstance : processInstanceList) { + System.out.println("流程实例ID:" + processInstance.getId()); + System.out.println("流程开始时间:" + processInstance.getStartTime()); + System.out.println("流程结束时间:" + processInstance.getEndTime()); + System.out.println("流程耗时(ms):" + processInstance.getDurationInMillis() / 1000); + System.out.println("================================================================"); + } + } + } diff --git a/pmapi/src/test/resources/application.yml b/pmapi/src/test/resources/application.yml index 9f96606..3d7808a 100644 --- a/pmapi/src/test/resources/application.yml +++ b/pmapi/src/test/resources/application.yml @@ -1,3 +1,3 @@ spring: profiles: - active: prod + active: dev