Commit 38454d25 by 丁伟峰

工作队、分部、分站等,容量的定时计算,改用了java/schedule模式

1 parent 4db2bba4
...@@ -17,4 +17,6 @@ public interface CapacityOrgStatDao extends JpaRepository<CapacityOrgStatEntity, ...@@ -17,4 +17,6 @@ public interface CapacityOrgStatDao extends JpaRepository<CapacityOrgStatEntity,
@Query("select c from CapacityOrgStatEntity c where c.type = 'branch' and c.orgId in :branchIds and c.workday between :beginDate and :endDate") @Query("select c from CapacityOrgStatEntity c where c.type = 'branch' and c.orgId in :branchIds and c.workday between :beginDate and :endDate")
Page<?> findByBranchIdsAndWorkdayBetween(List<String> branchIds, String beginDate, String endDate, Pageable page); Page<?> findByBranchIdsAndWorkdayBetween(List<String> branchIds, String beginDate, String endDate, Pageable page);
CapacityOrgStatEntity getByTypeAndWorkdayAndOrgIdAndLayer(String group, String date, String groupId, String layer);
} }
package com.dituhui.pea.order.dao;
import com.dituhui.pea.order.entity.CapacityTeamStatEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface CapacityStatisticDao extends JpaRepository<CapacityTeamStatEntity, Long> {
@Query(value = "SELECT a.workday, " +
" v.layer_id, " +
" v.layer, " +
" count(distinct a.engineer_code) engineer_count, " +
" ifnull(sum(a.cap_total),0) cap_total, " +
" ifnull(sum(cap_used),0)+ifnull(sum(cap_used_travel),0) as cap_used, " +
" ifnull(sum(a.cap_left),0) cap_left" +
" FROM capacity_engineer_stat a\n" +
" INNER JOIN org_team_engineer b ON a.engineer_code=b.engineer_code AND b.status=1" +
" INNER JOIN v_engineer_skill v ON a.engineer_code = v.engineer_code" +
" WHERE b.team_id= :teamId " +
" AND a.workday= :date" +
" GROUP BY a.workday, v.layer_id, v.layer", nativeQuery = true)
List<Object[]> sumTeamCapacity(String date, String teamId);
@Query(value = "SELECT a.workday, " +
" v.layer_id, " +
" v.layer, " +
" count(distinct a.engineer_code) engineer_count, " +
" sum(a.cap_total) cap_total, " +
" ifnull(sum(cap_used),0)+ifnull(sum(cap_used_travel),0) as cap_used, " +
" sum(a.cap_left) cap_left\n" +
" FROM capacity_engineer_stat a\n" +
" JOIN v_engineer_skill v ON a.engineer_code = v.engineer_code\n" +
" JOIN engineer_info z ON a.engineer_code = z.engineer_code\n" +
" WHERE z.group_id= :groupId AND a.workday= :date \n" +
" GROUP BY a.workday, v.layer_id, v.layer;", nativeQuery = true)
List<Object[]> sumGroupCapacity(String date, String groupId);
@Query(value = "SELECT a.workday, " +
" v.layer_id, " +
" v.layer, " +
" count(distinct a.engineer_code) engineer_count, " +
" sum(a.cap_total) cap_total, " +
" ifnull(sum(cap_used),0)+ifnull(sum(cap_used_travel),0) as cap_used, " +
" sum(a.cap_left) cap_left\n" +
" FROM capacity_engineer_stat a\n" +
" JOIN v_engineer_skill v ON a.engineer_code = v.engineer_code\n" +
" JOIN engineer_info z ON a.engineer_code = z.engineer_code\n" +
" JOIN org_group g ON z.group_id = g.group_id\n" +
" WHERE g.branch_id= :branchId AND a.workday= :date \n" +
" GROUP BY a.workday, v.layer_id, v.layer;", nativeQuery = true)
List<Object[]> sumBranchCapacity(String date, String branchId);
}
...@@ -12,7 +12,7 @@ import java.util.List; ...@@ -12,7 +12,7 @@ import java.util.List;
@Repository @Repository
public interface CapacityTeamStatDao extends JpaRepository<CapacityTeamStatEntity, Long> { public interface CapacityTeamStatDao extends JpaRepository<CapacityTeamStatEntity, Long> {
List<CapacityTeamStatEntity> findAllByTeamIdAndLayerAndWorkdayBetween(String teamId, String layer, String beginDate, String endDate); CapacityTeamStatEntity getByWorkdayAndTeamIdAndLayer(String date, String teamId, String layer);
@Query("select c from CapacityTeamStatEntity c where c.teamId IN :teamIds and c.workday between :beginDate and :endDate") @Query("select c from CapacityTeamStatEntity c where c.teamId IN :teamIds and c.workday between :beginDate and :endDate")
Page<?> findByTeamIdsAndWorkdayBetween(List<String> teamIds, String beginDate, String endDate, Pageable pageable); Page<?> findByTeamIdsAndWorkdayBetween(List<String> teamIds, String beginDate, String endDate, Pageable pageable);
...@@ -24,6 +24,4 @@ public interface CapacityTeamStatDao extends JpaRepository<CapacityTeamStatEntit ...@@ -24,6 +24,4 @@ public interface CapacityTeamStatDao extends JpaRepository<CapacityTeamStatEntit
@Query(value = "SELECT team_id FROM capacity_team_stat ORDER BY RAND() LIMIT 1", nativeQuery = true) @Query(value = "SELECT team_id FROM capacity_team_stat ORDER BY RAND() LIMIT 1", nativeQuery = true)
String getRandomTeamId(); String getRandomTeamId();
// @Query("select TeamCapacityStageDTO(sum(a.capTotal), sum(a.capUsed), sum(a.capLeft), count(1)) from CapacityEngineerStatEntity a join OrgTeamEngineerEntity t on a.engineerCode = t.engineerCode where t.teamId = :teamId")
// TeamCapacityStageDTO getTeamCapacityStage(String teamId);
} }
package com.dituhui.pea.order.dto;
import lombok.Data;
@Data
public class CapacityOrgStatDTO {
private String date;
private String orgId;
private String layerId;
private String layer;
private Integer engineerCount;
private Integer capTotal;
private Integer capUsed;
private Integer capLeft;
}
...@@ -22,15 +22,13 @@ public class CapacityTeamStatEntity implements Serializable { ...@@ -22,15 +22,13 @@ public class CapacityTeamStatEntity implements Serializable {
private String workday; private String workday;
private String timeSpan; // private String timeSpan;
//
// private String timeSpanDetail;
private String timeSpanDetail;
private String teamId; private String teamId;
private String layer; private String layer;
......
...@@ -74,10 +74,8 @@ public class CalcEngineerCapacityScheduler { ...@@ -74,10 +74,8 @@ public class CalcEngineerCapacityScheduler {
log.info("正在处理: 日期[{}]技术员[{}]容量相关信息 ==> used:{}, orderCnt:{}, maxDuration:{}", date, engineerCode, used, cnt, max); log.info("正在处理: 日期[{}]技术员[{}]容量相关信息 ==> used:{}, orderCnt:{}, maxDuration:{}", date, engineerCode, used, cnt, max);
CapacityEngineerStatEntity statEntity = capacityEngineerStatDao.getByWorkdayAndEngineerCode(date, engineerCode); CapacityEngineerStatEntity statEntity = capacityEngineerStatDao.getByWorkdayAndEngineerCode(date, engineerCode);
if (statEntity == null) { if (statEntity == null) {
statEntity = new CapacityEngineerStatEntity(); log.error("错误:日期[{}]技术员[{}]容量尚未初始化,忽略退出!", date, engineerCode);
statEntity.setWorkday(date); return;
statEntity.setEngineerCode(engineerCode);
statEntity.setCreateTime(LocalDateTime.now());
} }
statEntity.setOrderCount((int) cnt); statEntity.setOrderCount((int) cnt);
statEntity.setCapUsed(used); statEntity.setCapUsed(used);
......
package com.dituhui.pea.order.scheduler;
import com.dituhui.pea.order.common.DateUtils;
import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.dto.CapacityOrgStatDTO;
import com.dituhui.pea.order.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
@Slf4j
@Component
public class CalcOrgCapacityScheduler {
@Autowired
private CapacityStatisticDao capacityStatisticDao;
@Autowired
private OrgBranchDao orgBranchDao;
@Autowired
private OrgGroupDao orgGroupDao;
@Autowired
private OrgTeamDao orgTeamDao;
@Autowired
private CapacityOrgStatDao capacityOrgStatDao;
@Autowired
private CapacityTeamStatDao capacityTeamStatDao;
@Value("${scheduler.calc-org-capacity.day-offset-begin}")
private int dayOffsetBegin;
@Value("${scheduler.calc-org-capacity.day-offset-end}")
private int dayOffsetEnd;
private final ExecutorService executorService = Executors.newFixedThreadPool(3);
@Scheduled(cron = "${scheduler.calc-org-capacity.cron-expr}")
public void run() {
log.info("工作队/各级机构容量定时计算,根据相关的工程师的容量进行汇总");
String bdate = DateUtils.formatDate(LocalDate.now().plusDays(dayOffsetBegin));
String edate = DateUtils.formatDate(LocalDate.now().plusDays(dayOffsetEnd));
executorService.submit(() -> calcAllTeamByDays(bdate, edate));
executorService.submit(() -> calcAllGroupByDays(bdate, edate));
executorService.submit(() -> calcAllBranchByDays(bdate, edate));
}
private void calcOneTeam(String date, String teamId) {
// 重新计算保存1个工作队1天的容量
List<Object[]> nativeQueryResult = capacityStatisticDao.sumTeamCapacity(date, teamId);
List<CapacityOrgStatDTO> teamStats = new ArrayList<>();
for (Object[] result : nativeQueryResult) {
CapacityOrgStatDTO dto = new CapacityOrgStatDTO();
dto.setDate(date);
dto.setOrgId(teamId);
dto.setLayerId((String) result[1]);
dto.setLayer((String) result[2]);
dto.setEngineerCount((Integer) result[3]);
dto.setCapTotal((Integer) result[4]);
dto.setCapUsed((Integer) result[5]);
dto.setCapLeft((Integer) result[6]);
teamStats.add(dto);
}
// 逐条保存
for (CapacityOrgStatDTO dto : teamStats) {
CapacityTeamStatEntity entity = capacityTeamStatDao.getByWorkdayAndTeamIdAndLayer(date, teamId, dto.getLayer());
if (entity == null) {
entity = new CapacityTeamStatEntity();
entity.setWorkday(date);
entity.setTeamId(teamId);
entity.setLayer(dto.getLayer());
entity.setCapUsedTravel(0);
entity.setOrderCount(0);
entity.setCreateTime(LocalDateTime.now());
}
entity.setEngineerCount(dto.getEngineerCount());
entity.setCapTotal(dto.getCapTotal());
entity.setCapUsed(dto.getCapUsed());
entity.setCapLeft(dto.getCapLeft());
entity.setUpdateTime(LocalDateTime.now());
// todo entity.setOrderCount();
capacityTeamStatDao.save(entity);
}
}
private void calcOneGroup(String date, String groupId) {
// 重新计算1个分组/分站 1天的容量
List<Object[]> nativeQueryResult = capacityStatisticDao.sumGroupCapacity(date, groupId);
List<CapacityOrgStatDTO> stats = new ArrayList<>();
for (Object[] result : nativeQueryResult) {
CapacityOrgStatDTO dto = new CapacityOrgStatDTO();
dto.setDate(date);
dto.setOrgId(groupId);
dto.setLayerId((String) result[1]);
dto.setLayer((String) result[2]);
dto.setEngineerCount((Integer) result[3]);
dto.setCapTotal((Integer) result[4]);
dto.setCapUsed((Integer) result[5]);
dto.setCapLeft((Integer) result[6]);
stats.add(dto);
}
// 逐条保存
for (CapacityOrgStatDTO dto : stats) {
CapacityOrgStatEntity entity = capacityOrgStatDao.getByTypeAndWorkdayAndOrgIdAndLayer("group", date, groupId, dto.getLayer());
if (entity == null) {
entity = new CapacityOrgStatEntity();
entity.setType("group");
entity.setWorkday(date);
entity.setOrgId(groupId);
entity.setLayer(dto.getLayer());
entity.setOrderCount(0);
entity.setCreateTime(LocalDateTime.now());
}
entity.setEngineerCount(dto.getEngineerCount());
entity.setCapTotal(dto.getCapTotal());
entity.setCapUsedTotal(dto.getCapUsed());
entity.setCapLeft(dto.getCapLeft());
entity.setUpdateTime(LocalDateTime.now());
// todo entity.setOrderCount();
capacityOrgStatDao.save(entity);
}
}
private void calcOneBranch(String date, String branchId) {
//
List<Object[]> nativeQueryResult = capacityStatisticDao.sumBranchCapacity(date, branchId);
List<CapacityOrgStatDTO> stats = new ArrayList<>();
for (Object[] result : nativeQueryResult) {
CapacityOrgStatDTO dto = new CapacityOrgStatDTO();
dto.setDate(date);
dto.setOrgId(branchId);
dto.setLayerId((String) result[1]);
dto.setLayer((String) result[2]);
dto.setEngineerCount((Integer) result[3]);
dto.setCapTotal((Integer) result[4]);
dto.setCapUsed((Integer) result[5]);
dto.setCapLeft((Integer) result[6]);
stats.add(dto);
}
// 逐条保存
for (CapacityOrgStatDTO dto : stats) {
CapacityOrgStatEntity entity = capacityOrgStatDao.getByTypeAndWorkdayAndOrgIdAndLayer("branch", date, branchId, dto.getLayer());
if (entity == null) {
entity = new CapacityOrgStatEntity();
entity.setType("branch");
entity.setWorkday(date);
entity.setOrgId(branchId);
entity.setLayer(dto.getLayer());
entity.setOrderCount(0);
entity.setCreateTime(LocalDateTime.now());
}
entity.setEngineerCount(dto.getEngineerCount());
entity.setCapTotal(dto.getCapTotal());
entity.setCapUsedTotal(dto.getCapUsed());
entity.setCapLeft(dto.getCapLeft());
entity.setUpdateTime(LocalDateTime.now());
// todo entity.setOrderCount();
capacityOrgStatDao.save(entity);
}
}
private void calcAllTeamByDays(String bdate, String edate) {
LocalDate currentDate = DateUtils.localDateFromStr(bdate);
LocalDate endDate = DateUtils.localDateFromStr(edate);
List<String> allTeamIds = orgTeamDao.findAll().stream().map(OrgTeamEntity::getTeamId).collect(Collectors.toList());
while (!currentDate.isAfter(endDate)) {
for (String teamId : allTeamIds) {
calcOneTeam(DateUtils.formatDate(currentDate), teamId);
}
currentDate = currentDate.plusDays(1);
}
}
private void calcAllGroupByDays(String bdate, String edate) {
LocalDate currentDate = DateUtils.localDateFromStr(bdate);
LocalDate endDate = DateUtils.localDateFromStr(edate);
List<String> allGroupIds = orgGroupDao.findAll().stream().map(OrgGroupEntity::getGroupId).collect(Collectors.toList());
while (!currentDate.isAfter(endDate)) {
for (String groupId : allGroupIds) {
calcOneGroup(DateUtils.formatDate(currentDate), groupId);
}
currentDate = currentDate.plusDays(1);
}
}
private void calcAllBranchByDays(String bdate, String edate) {
LocalDate currentDate = DateUtils.localDateFromStr(bdate);
LocalDate endDate = DateUtils.localDateFromStr(edate);
List<String> allBranchIds = orgBranchDao.findAll().stream().map(OrgBranchEntity::getBranchId).collect(Collectors.toList());
while (!currentDate.isAfter(endDate)) {
for (String branchId : allBranchIds) {
calcOneBranch(DateUtils.formatDate(currentDate), branchId);
}
currentDate = currentDate.plusDays(1);
}
}
}
...@@ -62,12 +62,20 @@ SaaS: ...@@ -62,12 +62,20 @@ SaaS:
scheduler: scheduler:
init-engineer-capacity: init-engineer-capacity:
cron-expr: 0 */10 8-18 * * ? # 每天22点1次
cron-expr: 0 0 22 * * ?
day-offset-begin: 0 day-offset-begin: 0
day-offset-end: 14 day-offset-end: 14
rewrite-force: true rewrite-force: true
calc-engineer-capacity: calc-engineer-capacity:
cron-expr: 0 */5 8-23 * * ? # 8-20点,每30分钟1次
cron-expr: 0 */30 1-23 * * ?
day-offset-begin: 0
day-offset-end: 14
calc-org-capacity:
# 8-20点,每小时1次
cron-expr: 0 0 1-23 * * ?
day-offset-begin: 0 day-offset-begin: 0
day-offset-end: 14 day-offset-end: 14
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!