Browse Source

项目超期滞留提醒

dev_shibei_match
zhaoqifeng 5 years ago
parent
commit
5a8237f007
  1. 7
      epmet-gateway/pom.xml
  2. 5
      epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/dto/form/CostDayFormDTO.java
  3. 6
      epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/dto/result/CostDayResultDTO.java
  4. 4
      epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/feign/EpmetCommonServiceOpenFeignClient.java
  5. 11
      epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/service/impl/WorkDayServiceImpl.java
  6. 28
      epmet-module/gov-project/gov-project-client/src/main/java/com/epmet/dto/result/OverdueAndDelayDTO.java
  7. 6
      epmet-module/gov-project/gov-project-client/src/main/java/com/epmet/dto/result/StaffUnHandledDTO.java
  8. 6
      epmet-module/gov-project/gov-project-server/pom.xml
  9. 31
      epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/constant/UserMessageConstant.java
  10. 5
      epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/controller/ProjectController.java
  11. 120
      epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/service/impl/ProjectServiceImpl.java
  12. 2
      epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/service/impl/ProjectStaffServiceImpl.java
  13. 3
      epmet-module/gov-project/gov-project-server/src/main/resources/mapper/ProjectStaffDao.xml

7
epmet-gateway/pom.xml

@ -288,10 +288,11 @@
<!-- <gateway.routes.gov-issue-server.uri>http://localhost:8101</gateway.routes.gov-issue-server.uri>--> <!-- <gateway.routes.gov-issue-server.uri>http://localhost:8101</gateway.routes.gov-issue-server.uri>-->
<gateway.routes.gov-issue-server.uri>lb://gov-issue-server</gateway.routes.gov-issue-server.uri> <gateway.routes.gov-issue-server.uri>lb://gov-issue-server</gateway.routes.gov-issue-server.uri>
<!-- 23、政府工作端项目管理 --> <!-- 23、政府工作端项目管理 -->
<!-- <gateway.routes.gov-project-server.uri>http://localhost:8102</gateway.routes.gov-project-server.uri>--> <gateway.routes.gov-project-server.uri>http://localhost:8102</gateway.routes.gov-project-server.uri>
<gateway.routes.gov-project-server.uri>lb://gov-project-server</gateway.routes.gov-project-server.uri> <!-- <gateway.routes.gov-project-server.uri>lb://gov-project-server</gateway.routes.gov-project-server.uri>-->
<!-- 24、公共服务 --> <!-- 24、公共服务 -->
<gateway.routes.common-service-server.uri>lb://common-service-server</gateway.routes.common-service-server.uri> <!-- <gateway.routes.common-service-server.uri>lb://common-service-server</gateway.routes.common-service-server.uri>-->
<gateway.routes.common-service-server.uri>http://localhost:8103</gateway.routes.common-service-server.uri>
<!-- 25、党建园地 --> <!-- 25、党建园地 -->
<gateway.routes.resi-home-server.uri>lb://resi-home-server</gateway.routes.resi-home-server.uri> <gateway.routes.resi-home-server.uri>lb://resi-home-server</gateway.routes.resi-home-server.uri>
<!-- <gateway.routes.resi-home-server.uri>http://localhost:8104</gateway.routes.resi-home-server.uri>--> <!-- <gateway.routes.resi-home-server.uri>http://localhost:8104</gateway.routes.resi-home-server.uri>-->

5
epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/dto/form/CostDayFormDTO.java

@ -3,6 +3,7 @@ package com.epmet.dto.form;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
/** /**
* @author zhaoqifeng * @author zhaoqifeng
@ -25,10 +26,10 @@ public class CostDayFormDTO implements Serializable {
/** /**
* 起始日期 * 起始日期
*/ */
private String startDate; private Date startDate;
/** /**
* 终止日期 * 终止日期
*/ */
private String endDate; private Date endDate;
} }

6
epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/dto/result/CostDayResultDTO.java

@ -3,6 +3,7 @@ package com.epmet.dto.result;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
/** /**
* @author zhaoqifeng * @author zhaoqifeng
@ -27,5 +28,10 @@ public class CostDayResultDTO implements Serializable {
*/ */
private Integer detentionDays; private Integer detentionDays;
/**
* 起始日期
*/
private Date startDate;
} }

4
epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/feign/EpmetCommonServiceOpenFeignClient.java

@ -21,8 +21,8 @@ import java.util.List;
* @author yinzuomei@elink-cn.com * @author yinzuomei@elink-cn.com
* @date 2020/6/4 10:28 * @date 2020/6/4 10:28
*/ */
@FeignClient(name = ServiceConstant.EPMET_COMMON_SERVICE, fallback = EpmetCommonServiceOpenFeignClientFallback.class) //@FeignClient(name = ServiceConstant.EPMET_COMMON_SERVICE, fallback = EpmetCommonServiceOpenFeignClientFallback.class)
//@FeignClient(name = ServiceConstant.EPMET_COMMON_SERVICE, fallback = EpmetCommonServiceOpenFeignClientFallback.class, url = "http://localhost:8103") @FeignClient(name = ServiceConstant.EPMET_COMMON_SERVICE, fallback = EpmetCommonServiceOpenFeignClientFallback.class, url = "http://localhost:8103")
public interface EpmetCommonServiceOpenFeignClient { public interface EpmetCommonServiceOpenFeignClient {
/** /**
* @param formDTO * @param formDTO

11
epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/service/impl/WorkDayServiceImpl.java

@ -1,6 +1,7 @@
package com.epmet.service.impl; package com.epmet.service.impl;
import com.epmet.commons.tools.exception.RenException; import com.epmet.commons.tools.exception.RenException;
import com.epmet.commons.tools.utils.DateUtils;
import com.epmet.dao.CalenderDao; import com.epmet.dao.CalenderDao;
import com.epmet.dto.form.CostDayFormDTO; import com.epmet.dto.form.CostDayFormDTO;
import com.epmet.dto.form.WorkDayFormDTO; import com.epmet.dto.form.WorkDayFormDTO;
@ -65,6 +66,7 @@ public class WorkDayServiceImpl implements WorkDayService {
result.setId(form.getId()); result.setId(form.getId());
result.setStaffId(form.getStaffId()); result.setStaffId(form.getStaffId());
result.setDetentionDays(this.getWorkDays(form.getStartDate(), form.getEndDate())); result.setDetentionDays(this.getWorkDays(form.getStartDate(), form.getEndDate()));
result.setStartDate(form.getStartDate());
list.add(result); list.add(result);
} }
return list; return list;
@ -89,6 +91,7 @@ public class WorkDayServiceImpl implements WorkDayService {
result.setId(form.getId()); result.setId(form.getId());
result.setStaffId(form.getStaffId()); result.setStaffId(form.getStaffId());
result.setDetentionDays(this.getCalendarDays(form.getStartDate(), form.getEndDate())); result.setDetentionDays(this.getCalendarDays(form.getStartDate(), form.getEndDate()));
result.setStartDate(form.getStartDate());
list.add(result); list.add(result);
} }
return list; return list;
@ -128,7 +131,9 @@ public class WorkDayServiceImpl implements WorkDayService {
} }
private Integer getWorkDays(String startDateStr, String endDateStr) { private Integer getWorkDays(Date start, Date end) {
String startDateStr = DateUtils.format(start, DateUtils.DATE_PATTERN_YYYYMMDD);
String endDateStr = DateUtils.format(end, DateUtils.DATE_PATTERN_YYYYMMDD);
if (startDateStr.equals(endDateStr)) { if (startDateStr.equals(endDateStr)) {
logger.info(String.format("%s-%s起止时间一致,返回<1,",startDateStr,endDateStr)); logger.info(String.format("%s-%s起止时间一致,返回<1,",startDateStr,endDateStr));
return 0; return 0;
@ -158,7 +163,9 @@ public class WorkDayServiceImpl implements WorkDayService {
} }
private Integer getCalendarDays(String startDateStr, String endDateStr) { private Integer getCalendarDays(Date start, Date end) {
String startDateStr = DateUtils.format(start, DateUtils.DATE_PATTERN_YYYYMMDD);
String endDateStr = DateUtils.format(end, DateUtils.DATE_PATTERN_YYYYMMDD);
if (startDateStr.equals(endDateStr)) { if (startDateStr.equals(endDateStr)) {
logger.info(String.format("%s-%s起止时间一致,返回<1,",startDateStr,endDateStr)); logger.info(String.format("%s-%s起止时间一致,返回<1,",startDateStr,endDateStr));
return 0; return 0;

28
epmet-module/gov-project/gov-project-client/src/main/java/com/epmet/dto/result/OverdueAndDelayDTO.java

@ -0,0 +1,28 @@
package com.epmet.dto.result;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author zhaoqifeng
* @dscription
* @date 2020/10/22 15:45
*/
@Data
public class OverdueAndDelayDTO implements Serializable {
private static final long serialVersionUID = -3632539647818460833L;
/**
* 工作人员ID
*/
private String staffId;
/**
* 即将超期
*/
private List<StaffUnHandledDTO> overdueList;
/**
* 滞留
*/
private List<StaffUnHandledDTO> delayList;
}

6
epmet-module/gov-project/gov-project-client/src/main/java/com/epmet/dto/result/StaffUnHandledDTO.java

@ -14,9 +14,13 @@ import java.util.Date;
public class StaffUnHandledDTO implements Serializable { public class StaffUnHandledDTO implements Serializable {
private static final long serialVersionUID = 5257146338113364709L; private static final long serialVersionUID = 5257146338113364709L;
/** /**
* 项目ID * project_staff ID
*/ */
private String id; private String id;
/**
* 项目ID
*/
private String projectId;
/** /**
* 项目标题 * 项目标题
*/ */

6
epmet-module/gov-project/gov-project-server/pom.xml

@ -54,6 +54,12 @@
<groupId>com.alibaba.cloud</groupId> <groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.3</version>
<scope>compile</scope>
</dependency>
<!-- 替换Feign原生httpclient --> <!-- 替换Feign原生httpclient -->
<dependency> <dependency>
<groupId>io.github.openfeign</groupId> <groupId>io.github.openfeign</groupId>

31
epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/constant/UserMessageConstant.java

@ -21,4 +21,35 @@ public interface UserMessageConstant {
*/ */
String PROJECT_CLOSED_MSG = "您好,您参与的【%s】项目已结案,原因:%s"; String PROJECT_CLOSED_MSG = "您好,您参与的【%s】项目已结案,原因:%s";
/**
* 滞留超期消息标题
*/
String STAY_REMINDER_TITLE_1 = "您有%d个项目即将超期,%d个项目已经滞留";
/**
* 滞留超期消息模板
*/
String STAY_REMINDER_MSG_1 = "即将超期项目:%n%s 滞留项目:%n%s";
/**
* 滞留超期消息标题
*/
String STAY_REMINDER_TITLE_2 = "您有%d个项目即将超期";
/**
* 滞留超期消息模板
*/
String STAY_REMINDER_MSG_2 = "即将超期项目:%n%s";
/**
* 滞留超期消息标题
*/
String STAY_REMINDER_TITLE_3 = "您有%d个项目已经滞留";
/**
* 滞留超期消息模板
*/
String STAY_REMINDER_MSG_3 = "滞留项目:%n%s";
} }

5
epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/controller/ProjectController.java

@ -151,5 +151,10 @@ public class ProjectController {
List<PendProjectListResultDTO> result = projectService.getPendProjectList(fromDTO); List<PendProjectListResultDTO> result = projectService.getPendProjectList(fromDTO);
return new Result<List<PendProjectListResultDTO>>().ok(result); return new Result<List<PendProjectListResultDTO>>().ok(result);
} }
@PostMapping("message")
public Result sendMessage(@RequestBody ProjectDTO formDTO) {
projectService.sendMessage(formDTO.getCustomerId());
return new Result();
}
} }

120
epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/service/impl/ProjectServiceImpl.java

@ -20,10 +20,7 @@ package com.epmet.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.epmet.commons.mybatis.service.impl.BaseServiceImpl; import com.epmet.commons.mybatis.service.impl.BaseServiceImpl;
import com.epmet.commons.tools.constant.AppClientConstant; import com.epmet.commons.tools.constant.*;
import com.epmet.commons.tools.constant.Constant;
import com.epmet.commons.tools.constant.FieldConstant;
import com.epmet.commons.tools.constant.NumConstant;
import com.epmet.commons.tools.exception.EpmetErrorCode; import com.epmet.commons.tools.exception.EpmetErrorCode;
import com.epmet.commons.tools.exception.RenException; import com.epmet.commons.tools.exception.RenException;
import com.epmet.commons.tools.page.PageData; import com.epmet.commons.tools.page.PageData;
@ -48,6 +45,7 @@ import com.epmet.entity.ProjectStaffEntity;
import com.epmet.feign.*; import com.epmet.feign.*;
import com.epmet.redis.ProjectRedis; import com.epmet.redis.ProjectRedis;
import com.epmet.service.*; import com.epmet.service.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -732,7 +730,7 @@ public class ProjectServiceImpl extends BaseServiceImpl<ProjectDao, ProjectEntit
int remindTime = 0; int remindTime = 0;
//推送时间 //推送时间
String pushTime = "08:00"; String pushTime = "08:00";
if (null != paramList && paramList.size() > NumConstant.ZERO) { if (CollectionUtils.isNotEmpty(paramList)) {
for (CustomerProjectParameterDTO dto : paramList) { for (CustomerProjectParameterDTO dto : paramList) {
if (ParameterKeyConstant.DETENTION_DAYS.equals(dto.getParameterKey())) { if (ParameterKeyConstant.DETENTION_DAYS.equals(dto.getParameterKey())) {
detentionDays = Integer.parseInt(dto.getParameterValue()); detentionDays = Integer.parseInt(dto.getParameterValue());
@ -748,35 +746,133 @@ public class ProjectServiceImpl extends BaseServiceImpl<ProjectDao, ProjectEntit
} }
//获取工作人员未处理的节点 //获取工作人员未处理的节点
List<StaffUnHandledDTO> unHandledList = projectStaffService.getStaffUnHandledList(customerId); List<StaffUnHandledDTO> unHandledList = projectStaffService.getStaffUnHandledList(customerId);
List<CostDayFormDTO> formDTOS = unHandledList.stream().map(item -> { List<CostDayFormDTO> form = unHandledList.stream().map(item -> {
CostDayFormDTO dto = new CostDayFormDTO(); CostDayFormDTO dto = new CostDayFormDTO();
dto.setId(item.getId()); dto.setId(item.getId());
dto.setStaffId(item.getStaffId()); dto.setStaffId(item.getStaffId());
if (null != item.getUpdatedTime()) { if (null != item.getUpdatedTime()) {
dto.setStartDate(DateUtils.format(item.getUpdatedTime(), DateUtils.DATE_PATTERN_YYYYMMDD)); dto.setStartDate(item.getUpdatedTime());
} else { } else {
dto.setStartDate(DateUtils.format(item.getCreatedTime(), DateUtils.DATE_PATTERN_YYYYMMDD)); dto.setStartDate(item.getCreatedTime());
} }
dto.setEndDate(DateUtils.format(new Date(), DateUtils.DATE_PATTERN_YYYYMMDD)); dto.setEndDate(new Date());
return dto; return dto;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
List<CostDayResultDTO> costDayList = new ArrayList<>(); List<CostDayResultDTO> costDayList;
if (ParameterKeyConstant.WORK.equals(calculation)) { if (ParameterKeyConstant.WORK.equals(calculation)) {
//工作日计算 //工作日计算
Result<List<CostDayResultDTO>> result = epmetCommonServiceOpenFeignClient.costWorkDays(formDTOS); Result<List<CostDayResultDTO>> result = epmetCommonServiceOpenFeignClient.costWorkDays(form);
if (!result.success()) { if (!result.success()) {
throw new RenException(result.getCode(), result.getMsg()); throw new RenException(result.getCode(), result.getMsg());
} }
costDayList = result.getData(); costDayList = result.getData();
} else { } else {
//日历日计算 //日历日计算
Result<List<CostDayResultDTO>> result = epmetCommonServiceOpenFeignClient.costCalendarDays(formDTOS); Result<List<CostDayResultDTO>> result = epmetCommonServiceOpenFeignClient.costCalendarDays(form);
if (!result.success()) { if (!result.success()) {
throw new RenException(result.getCode(), result.getMsg()); throw new RenException(result.getCode(), result.getMsg());
} }
costDayList = result.getData(); costDayList = result.getData();
} }
//即将超期项目
List<StaffUnHandledDTO> overdueList = new ArrayList<>();
//滞留项目
List<StaffUnHandledDTO> delayList = new ArrayList<>();
List<CostDayResultDTO> finalCostDayList = costDayList;
List<OverdueAndDelayDTO> list = new ArrayList<>();
int finalDetentionDays = detentionDays;
int finalRemindTime = remindTime;
unHandledList.forEach(unHandle -> finalCostDayList.stream().filter(cost ->
unHandle.getId().equals(cost.getId())).forEach(item -> {
int diff = finalDetentionDays - item.getDetentionDays();
OverdueAndDelayDTO dto = new OverdueAndDelayDTO();
if (diff < 0) {
dto.setStaffId(unHandle.getStaffId());
list.add(dto);
delayList.add(unHandle);
} else if (diff <= finalRemindTime) {
dto.setStaffId(unHandle.getStaffId());
overdueList.add(unHandle);
list.add(dto);
}
}));
if (CollectionUtils.isNotEmpty(list)) {
setMessage(customerId, overdueList, delayList, list);
}
}
private void setMessage(String customerId, List<StaffUnHandledDTO> overdueList, List<StaffUnHandledDTO> delayList, List<OverdueAndDelayDTO> list) {
list = list.stream().distinct().collect(Collectors.toList());
Map<String, List<StaffUnHandledDTO>> overdueMap = overdueList.stream().collect(Collectors.groupingBy(StaffUnHandledDTO::getStaffId));
Map<String, List<StaffUnHandledDTO>> delayMap = delayList.stream().collect(Collectors.groupingBy(StaffUnHandledDTO::getStaffId));
List<OverdueAndDelayDTO> overdue = overdueMap.entrySet().stream().map(item -> {
OverdueAndDelayDTO dto = new OverdueAndDelayDTO();
dto.setStaffId(item.getKey());
dto.setOverdueList(item.getValue());
return dto;
}).collect(Collectors.toList());
List<OverdueAndDelayDTO> delay = delayMap.entrySet().stream().map(item -> {
OverdueAndDelayDTO dto = new OverdueAndDelayDTO();
dto.setStaffId(item.getKey());
dto.setDelayList(item.getValue());
return dto;
}).collect(Collectors.toList());
list.forEach(dto -> overdue.forEach(item -> {
if (dto.getStaffId().equals(item.getStaffId())) {
dto.setOverdueList(item.getOverdueList());
}
}));
list.forEach(dto -> delay.forEach(item -> {
if (dto.getStaffId().equals(item.getStaffId())) {
dto.setDelayList(item.getDelayList());
}
}));
//通知
List<UserMessageFormDTO> msgList = new ArrayList<>();
list.forEach(dto -> {
String title;
String msg;
if (CollectionUtils.isNotEmpty(dto.getOverdueList()) && CollectionUtils.isNotEmpty(dto.getDelayList())) {
title = String.format(UserMessageConstant.STAY_REMINDER_TITLE_1, dto.getOverdueList().size(), dto.getDelayList().size());
StringBuilder overdueMsg = new StringBuilder();
StringBuilder delayMsg = new StringBuilder();
for (int i = 0; i < dto.getOverdueList().size(); i++) {
overdueMsg.append(i + 1).append(StrConstant.COMMA_ZH).append(dto.getOverdueList().get(i).getTitle()).append("\n");
}
for (int i = 0; i < dto.getDelayList().size(); i++) {
delayMsg.append(i + 1).append(StrConstant.COMMA_ZH).append(dto.getDelayList().get(i).getTitle()).append("\n");
}
msg = String.format(UserMessageConstant.STAY_REMINDER_MSG_1, overdueMsg.toString(), delayMsg.toString());
} else if (CollectionUtils.isNotEmpty(dto.getOverdueList()) && CollectionUtils.isEmpty(dto.getDelayList())) {
title = String.format(UserMessageConstant.STAY_REMINDER_TITLE_2, dto.getOverdueList().size());
StringBuilder overdueMsg = new StringBuilder();
for (int i = 0; i < dto.getOverdueList().size(); i++) {
overdueMsg.append(i + 1).append(StrConstant.COMMA_ZH).append(dto.getOverdueList().get(i).getTitle()).append("\n");
}
msg = String.format(UserMessageConstant.STAY_REMINDER_MSG_2, overdueMsg.toString());
} else {
title = String.format(UserMessageConstant.STAY_REMINDER_TITLE_3, dto.getDelayList().size());
StringBuilder delayMsg = new StringBuilder();
for (int i = 0; i < dto.getDelayList().size(); i++) {
delayMsg.append(i + 1).append(StrConstant.COMMA_ZH).append(dto.getDelayList().get(i).getTitle()).append("\n");
}
msg = String.format(UserMessageConstant.STAY_REMINDER_MSG_3, delayMsg.toString());
}
UserMessageFormDTO messageFormDTO = new UserMessageFormDTO();
messageFormDTO.setCustomerId(customerId);
messageFormDTO.setApp(ProjectConstant.GOV);
messageFormDTO.setGridId(StrConstant.STAR);
messageFormDTO.setUserId(dto.getStaffId());
messageFormDTO.setTitle(title);
messageFormDTO.setMessageContent(msg);
messageFormDTO.setReadFlag(Constant.UNREAD);
msgList.add(messageFormDTO);
});
System.out.println(msgList);
messageFeignClient.saveUserMessageList(msgList);
} }
} }

2
epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/service/impl/ProjectStaffServiceImpl.java

@ -166,7 +166,7 @@ public class ProjectStaffServiceImpl extends BaseServiceImpl<ProjectStaffDao, Pr
*/ */
@Override @Override
public List<StaffUnHandledDTO> getStaffUnHandledList(String customerId) { public List<StaffUnHandledDTO> getStaffUnHandledList(String customerId) {
return null; return baseDao.getStaffUnHandledList(customerId);
} }
} }

3
epmet-module/gov-project/gov-project-server/src/main/resources/mapper/ProjectStaffDao.xml

@ -67,7 +67,8 @@
</select> </select>
<select id="getStaffUnHandledList" resultType="com.epmet.dto.result.StaffUnHandledDTO"> <select id="getStaffUnHandledList" resultType="com.epmet.dto.result.StaffUnHandledDTO">
SELECT DISTINCT SELECT DISTINCT
p.ID, ps.ID,
ps.PROJECT_ID,
p.TITLE, p.TITLE,
ps.STAFF_ID, ps.STAFF_ID,
ps.CREATED_TIME, ps.CREATED_TIME,

Loading…
Cancel
Save