获取各预约时间段预约情况

This commit is contained in:
feng.li
2023-11-07 22:41:00 +08:00
parent d2c24e307a
commit 027e972482
12 changed files with 273 additions and 6 deletions

View File

@@ -1,10 +1,12 @@
package com.cool.store.mapper;
import com.cool.store.dto.calendar.UserFreeBusyInfoDTO;
import com.cool.store.dto.message.RemindInterviewMsgDTO;
import com.cool.store.dto.partner.AdvanceLineDTO;
import com.cool.store.dto.partner.PartnerInterviewInfoDTO;
import com.cool.store.dto.partner.SpecialDateRangeInterviewCountDTO;
import com.cool.store.entity.HyInterviewRemindDO;
import com.cool.store.entity.HyPartnerInterviewBookSituation;
import com.cool.store.entity.HyPartnerInterviewPlanDO;
import com.cool.store.request.GetInterviewListReq;
import com.cool.store.vo.EnterpriseUserBaseInfoVO;
@@ -185,4 +187,13 @@ public interface HyPartnerInterviewPlanMapper {
* @return
*/
List<HyInterviewRemindDO> remindInterviewStartMinutes();
/**
* 获取招商经理各时段预约情况
* @param interviewerId 招商经理 id
* @param startTimeStr 开始时间点
* @param endTimeStr 结束时间点
* @return
*/
List<HyPartnerInterviewBookSituation> getInterviewBookSituation(@Param("interviewerId") String interviewerId, @Param("startTime") String startTimeStr, @Param("endTime") String endTimeStr);
}

View File

@@ -569,4 +569,32 @@
AND t1.update_time &lt;= NOW()
</select>
<select id="getInterviewBookSituation" resultType="com.cool.store.entity.HyPartnerInterviewBookSituation">
SELECT t_booking_times.*, IFNULL(application_approved, 0) AS booked
FROM (
-- 查询已被预约成功的时间段
SELECT t1.start_time, t1.end_time, t1.application_approved, t1.deleted
FROM hy_partner_interview_plan t1
LEFT JOIN hy_partner_interview t2 ON t1.id = t2.interview_plan_id
WHERE t1.interviewer = #{interviewerId}
GROUP BY start_time
HAVING t1.deleted = 0
AND t1.application_approved = 1
AND t1.start_time &gt;= #{startTime}
AND t1.end_time &lt;= #{endTime}
)
AS t_booking_success
RIGHT JOIN (
-- 查询所有时间段预约人数
SELECT COUNT(*) AS booking_count, start_time, end_time, deleted
FROM hy_partner_interview_plan
WHERE interviewer = #{interviewerId}
GROUP BY start_time
HAVING deleted = 0
AND start_time &gt;= #{startTime}
AND end_time &lt;= #{endTime}
)
AS t_booking_times ON t_booking_times.start_time = t_booking_success.start_time
</select>
</mapper>

View File

@@ -0,0 +1,33 @@
package com.cool.store.entity;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author Fun Li 2023/11/7 17:06
* @version 1.0
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class HyPartnerInterviewBookSituation {
@ApiModelProperty("预约人数")
private Integer bookingCount;
@ApiModelProperty("预约的面试开始时间")
private String startTime;
@ApiModelProperty("预约的面试结束时间")
private String endTime;
@ApiModelProperty("是否已被预定")
private Boolean booked;
}

View File

@@ -22,4 +22,6 @@ public class GetFreeBusyListReq {
private String partnerId;
@ApiModelProperty("面试官ID(B端使用,如果该字段传了,就查询该面试官的日程忙闲信息,否则查询加盟商对应的面试官的信息)")
private String interviewerId;
@ApiModelProperty("是否是PC端请求")
private Boolean whetherPC;
}

View File

@@ -17,6 +17,12 @@ public class FreeBusyInfo {
@ApiModelProperty("是否空闲")
private boolean isFree;
@ApiModelProperty("预约人数")
private Integer appointmentCount;
@ApiModelProperty("是否被预约")
private Boolean booked;
public FreeBusyInfo(String startTime, String endTime, boolean isFree) {
this.startTime = startTime;
this.endTime = endTime;
@@ -29,6 +35,14 @@ public class FreeBusyInfo {
this.isFree = isFree;
}
public FreeBusyInfo(String startTime, String endTime, boolean isFree, Integer appointmentCount, Boolean booked) {
this.startTime = startTime;
this.endTime = endTime;
this.isFree = isFree;
this.appointmentCount = appointmentCount;
this.booked = booked;
}
public String getStartTime() {
return startTime;
}
@@ -52,4 +66,20 @@ public class FreeBusyInfo {
public void setFree(boolean free) {
isFree = free;
}
public Integer getAppointmentCount() {
return appointmentCount;
}
public void setAppointmentCount(Integer appointmentCount) {
this.appointmentCount = appointmentCount;
}
public Boolean getBooked() {
return booked;
}
public void setBooked(Boolean booked) {
this.booked = booked;
}
}

View File

@@ -14,6 +14,11 @@ import javax.annotation.Resource;
* @Description:
*/
public interface FeiShuService {
/**
* @deprecated {@link com.cool.store.service.InterviewService#getFreeBusyList}
*/
@Deprecated
GetFreeBusyListVO getFreeBusyList(GetFreeBusyListReq request) throws ApiException;
}

View File

@@ -5,6 +5,7 @@ import com.cool.store.exception.ApiException;
import com.cool.store.request.*;
import com.cool.store.vo.EnterInterviewVO;
import com.cool.store.vo.interview.CreateAppointmentVO;
import com.cool.store.vo.interview.GetFreeBusyListVO;
import com.cool.store.vo.interview.InterviewVO;
import java.util.List;
@@ -71,4 +72,10 @@ public interface InterviewService {
public String generateFeiShuInterviewMsg(String partnerName, String partnerMobile, String interviewTime);
/**
* 获取预约时间段的预约信息
* @param request {@link GetFreeBusyListReq}
* @return {@link GetFreeBusyListVO}
*/
GetFreeBusyListVO getFreeBusyList(GetFreeBusyListReq request);
}

View File

@@ -42,6 +42,14 @@ public class FeiShuServiceImpl implements FeiShuService {
@Autowired
private InterviewService interviewService;
/**
*
* @param request
* @return
* @throws ApiException
* @deprecated {@link com.cool.store.service.impl.InterviewServiceImpl#getFreeBusyList}
*/
@Deprecated
@Override
public GetFreeBusyListVO getFreeBusyList(GetFreeBusyListReq request) throws ApiException {
GetFreeBusyListVO freeBusyListVO = new GetFreeBusyListVO();

View File

@@ -5,8 +5,6 @@ import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.context.CurrentUserHolder;
import com.cool.store.context.LoginUserInfo;
import com.cool.store.context.PartnerUserHolder;
@@ -15,7 +13,6 @@ import com.cool.store.dao.HyIntendDevMappingDAO;
import com.cool.store.dao.HyInterviewDAO;
import com.cool.store.dto.calendar.*;
import com.cool.store.dto.log.*;
import com.cool.store.dto.message.SendCardMessageDTO;
import com.cool.store.dto.partner.EnterInterviewDto;
import com.cool.store.entity.*;
import com.cool.store.enums.*;
@@ -32,8 +29,7 @@ import com.cool.store.utils.TRTCUtils;
import com.cool.store.vo.EnterInterviewVO;
import com.cool.store.vo.EnterpriseUserBaseInfoVO;
import com.cool.store.vo.PartnerUserInfoVO;
import com.cool.store.vo.interview.CreateAppointmentVO;
import com.cool.store.vo.interview.InterviewVO;
import com.cool.store.vo.interview.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@@ -692,4 +688,86 @@ public class InterviewServiceImpl implements InterviewService {
hyPartnerInterviewPlanMapper.updateByPrimaryKeySelective(hyPartnerInterviewPlanDO);
}
@Override
public GetFreeBusyListVO getFreeBusyList(GetFreeBusyListReq request) {
//1. 处理数据
//1.1 传参整理
GetFreeBusyListVO freeBusyListVO = new GetFreeBusyListVO();
String startDate = request.getStartDate();//开始日期
String endDate = request.getEndDate();//结束日期
String partnerId = request.getPartnerId();//加盟商用户ID
String interviewerId = null;//面试官ID
String lineId = request.getLineId();//线索id
//如果加盟商用户ID为空且面试官ID为空返回错误信息
if (!(StringUtils.isNotEmpty(partnerId) && StringUtils.isNotEmpty(lineId)) && StringUtils.isEmpty(interviewerId)) {
throw new ServiceException(ErrorCodeEnum.INTERVIEW_AND_PARTNER_ID_IS_NULL);
}
//如果加盟商用户ID不为空且面试官ID为空
if (StringUtils.isNotEmpty(partnerId) && StringUtils.isNotEmpty(lineId)) {
interviewerId = getInterviewerByPartner(partnerId, lineId);
}
//1.2 时间转换
DateTime startDateTime = null;
DateTime endDateTime = null;
if (!StringUtils.isEmpty(startDate)&&!StringUtils.isEmpty(endDate)) {
startDateTime = DateUtil.beginOfDay(DateUtil.parse(startDate));
endDateTime = DateUtil.endOfDay(DateUtil.parse(endDate));
}
//1.3 校验时间
if (startDateTime.isAfter(endDateTime)) {
throw new ServiceException(ErrorCodeEnum.DATE_PARAMS_IS_ERROR);
}
//2. 查询招商经理各个已被预约时间段(成功或未成功)的预约情况
//2.1 PC 端和小程序查询的开始和结束时间不同
String startTimeSuffix = " 10:00:00";
String endTimeSuffix = " 17:00:00";
if (request.getWhetherPC()) {
startTimeSuffix = " 00:00:00";
endTimeSuffix = " 23:59:59";
}
String startTimeStr = DateUtil.format(startDateTime, "yyyy-MM-dd") + startTimeSuffix;
String endTimeStr = DateUtil.format(endDateTime, "yyyy-MM-dd") + endTimeSuffix;
List<HyPartnerInterviewBookSituation> bookSituations = hyPartnerInterviewPlanMapper.getInterviewBookSituation(interviewerId, startTimeStr, endTimeStr);
//3. 把数据装到各个时间槽里
//3.1 创建时间槽
// PC 端创建 8:00-24:00 的时间槽
// 小程序端创建 10:00-17:00 的时间槽并且不包含中午 12:00-13:00
List<CalendarInfo> daySlots;
if (request.getWhetherPC().equals(Boolean.TRUE)) {
daySlots = TimeSlotGenerator.generateDaySlotsForPc(startTimeStr, endTimeStr);
} else {
daySlots = TimeSlotGenerator.generateDaySlots(startTimeStr, endTimeStr);
}
freeBusyListVO.setCalendarList(daySlots);
//3.2 如果查询结果为空,则直接返回全部时间段都是空闲的
if (org.springframework.util.CollectionUtils.isEmpty(bookSituations)) {
return freeBusyListVO;
}
//3.3 装到槽里并返回
//3.3.1 外层循环每一天
for (CalendarInfo daySlot : daySlots) {
//3.3.2 内存循环每一天的每个时间段
List<FreeBusyInfo> freeBusyList = daySlot.getFreeBusyList();
for (FreeBusyInfo freeBusyInfo : freeBusyList) {
//把日期和时间拼接成yyyy-MM-dd HH:mm格式
String startStr = daySlot.getDateStr() + " " + freeBusyInfo.getStartTime();
String endStr = daySlot.getDateStr() + " " + freeBusyInfo.getEndTime();
for (HyPartnerInterviewBookSituation bookSituation : bookSituations) {
//比较两个时间段是否有重叠,重叠的就 set 数据进去
if (startStr.compareTo(bookSituation.getStartTime()) >= 0 && endStr.compareTo(bookSituation.getEndTime()) <= 0) {
freeBusyInfo.setFree(Boolean.FALSE);
freeBusyInfo.setBooked(Boolean.TRUE);
freeBusyInfo.setAppointmentCount(bookSituation.getBookingCount());
break;
}
}
}
}
return freeBusyListVO;
}
}

View File

@@ -52,6 +52,36 @@ public class TimeSlotGenerator {
return daySlots;
}
public static List<CalendarInfo> generateDaySlotsForPc(String startDate, String endDate) {
List<CalendarInfo> daySlots = new ArrayList<>();
Date start = DateUtil.parse(startDate);
Date end = DateUtil.parse(endDate);
Calendar startCal = DateUtil.calendar(start);
Calendar endCal = DateUtil.calendar(end);
while (!startCal.after(endCal)) {
int year = startCal.get(Calendar.YEAR);
int month = startCal.get(Calendar.MONTH) + 1;
int day = startCal.get(Calendar.DAY_OF_MONTH);
int dayOfWeek = startCal.get(Calendar.DAY_OF_WEEK);
List<FreeBusyInfo> hourSlots = generateHalfHourSlotsForPC();
CalendarInfo daySlot = new CalendarInfo(transDayOfWeek(dayOfWeek),
String.valueOf(year),
StringUtil.addZeroForNum(String.valueOf(month),2),
StringUtil.addZeroForNum(String.valueOf(day),2),
DateUtil.format(startCal.getTime(), "yyyy-MM-dd"),
hourSlots);
daySlots.add(daySlot);
startCal.add(Calendar.DATE, 1);
}
return daySlots;
}
private static List<FreeBusyInfo> generateHourSlots() {
List<FreeBusyInfo> hourSlots = new ArrayList<>();
@@ -83,7 +113,27 @@ public class TimeSlotGenerator {
String startTime2 = String.format("%02d:30", hour);
String endTime2 = String.format("%02d:00", hour + 1);
//默认空闲
FreeBusyInfo hourSlot2 = new FreeBusyInfo(startTime2, endTime2, true);
FreeBusyInfo hourSlot2 = new FreeBusyInfo(startTime2, endTime2, true, 0, false);
hourSlots.add(hourSlot2);
}
return hourSlots;
}
private static List<FreeBusyInfo> generateHalfHourSlotsForPC() {
List<FreeBusyInfo> hourSlots = new ArrayList<>();
//循环打印半小时的时间段
for (int hour = 8; hour < 24; hour++) {
String startTime = String.format("%02d:00", hour);
String endTime = String.format("%02d:30", hour);
//默认空闲
FreeBusyInfo hourSlot = new FreeBusyInfo(startTime, endTime, true);
hourSlots.add(hourSlot);
String startTime2 = String.format("%02d:30", hour);
String endTime2 = String.format("%02d:00", hour + 1);
//默认空闲,预约人数为 0
FreeBusyInfo hourSlot2 = new FreeBusyInfo(startTime2, endTime2, true, 0, false);
hourSlots.add(hourSlot2);
}
return hourSlots;

View File

@@ -17,16 +17,22 @@ import org.springframework.web.bind.annotation.RestController;
* @Author: young.yu
* @Date: 2023-06-16 13:06
* @Description:
* @deprecated {@link com.cool.store.controller.InterviewController}
*/
@Api(tags = "飞书相关接口")
@RestController
@RequestMapping({"/feishu"})
@Deprecated
public class FeiShuController {
/**
* @deprecated {@link com.cool.store.controller.InterviewController#getFreeBusyList(GetFreeBusyListReq)}
*/
@Autowired
private FeiShuService feiShuService;
@PostMapping("/interviewer/freebusy/list")
@ApiOperation("查询日程忙闲信息")
@Deprecated
public ResponseResult<GetFreeBusyListVO> getFreeBusyList(@RequestBody GetFreeBusyListReq request) throws ApiException {
GetFreeBusyListVO getFreeBusyListVO= feiShuService.getFreeBusyList(request);
return ResponseResult.success(getFreeBusyListVO);

View File

@@ -4,8 +4,10 @@ import com.cool.store.dto.partner.EnterInterviewDto;
import com.cool.store.exception.ApiException;
import com.cool.store.request.*;
import com.cool.store.response.ResponseResult;
import com.cool.store.service.FeiShuService;
import com.cool.store.service.InterviewService;
import com.cool.store.vo.EnterInterviewVO;
import com.cool.store.vo.interview.GetFreeBusyListVO;
import com.cool.store.vo.interview.InterviewVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
@@ -54,6 +56,13 @@ public class InterviewController {
return ResponseResult.success();
}
@PostMapping("/interviewer/freebusy/list")
@ApiOperation("查询各预约时间段情况")
public ResponseResult<GetFreeBusyListVO> getFreeBusyList(@RequestBody GetFreeBusyListReq request) throws ApiException {
GetFreeBusyListVO getFreeBusyListVO= interviewService.getFreeBusyList(request);
return ResponseResult.success(getFreeBusyListVO);
}
@PostMapping("/modifyInterviewTime")
@ApiOperation("修改面试时间")
public ResponseResult modifyInterviewTime(@RequestBody ModifyInterviewTimeReq request) throws ApiException {