perf:节假日校验

This commit is contained in:
Zhujx
2025-10-04 10:45:44 +08:00
parent a1fe884386
commit 357f1e3a44
11 changed files with 366 additions and 8 deletions

View File

@@ -0,0 +1,109 @@
package com.xiang.xservice.common.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author: xiang
* @Date: 2025-10-04 10:23
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DayResult {
/**
* 阳历日期
*/
private String date;
/**
* 表示星期几
*/
private String week;
/**
* 状态描述,节假日/工作日/周末。1.当status为1时表示节假日2.当status为2时表示工作日3.当status为null时如果week为周六或者周日表示周末否则表示工作日
*/
private String statusDesc;
/**
* 当天状态标识1:节假日2:工作日null周末或工作日(可根据week进行判断也可以直接根据statusDesc进行判断)
*/
private String status;
/**
* 属相
*/
private String animal;
/**
* 忌
*/
private String avoid;
/**
* 星期几
*/
private String cnDay;
/**
* 阳历日
*/
private String day;
/**
* 节日描述,如:母亲节
*/
private String desc;
/**
* 干支纪日,如:丁巳
*/
private String gzDate;
/**
* 干支纪月,如:癸巳
*/
private String gzMonth;
/**
* 干支纪年,如:辛丑
*/
private String gzYear;
/**
* 是否大月
*/
private String isBigMonth;
/**
* 农历日,如:廿八
*/
private String lDate;
/**
* 农历月,如:三
*/
private String lMonth;
/**
* 农历日28
*/
private String lunarDate;
/**
* 农历月3
*/
private String lunarMonth;
/**
* 农历年2021
*/
private String lunarYear;
/**
* 阳历月
*/
private String month;
/**
* 宜
*/
private String suit;
/**
* 节气
*/
private String term;
/**
* 节日
*/
private String value;
/**
* 阳历年
*/
private String year;
}

View File

@@ -0,0 +1,18 @@
package com.xiang.xservice.common.enums;
import com.xiang.xservice.basic.utils.DateUtils;
import java.time.LocalDate;
/**
* @Author: xiang
* @Date: 2025-10-04 10:29
*/
public class RedisConstant {
public static final String DAY_INFO_PREFIX_KEY = "day:info:holiday";
public static String getDate4Key() {
return DateUtils.getDateFromDate(LocalDate.now(), "yyyyMM");
}
}

View File

@@ -0,0 +1,10 @@
package com.xiang.xservice.common.enums;
/**
* @Author: xiang
* @Date: 2025-10-04 10:15
*/
public class UrlConstant {
public static final String HOLIDAY_QUERY_URL = "http://apis.juhe.cn/fapig/calendar/day";
}

View File

@@ -0,0 +1,72 @@
package com.xiang.xservice.common.schedule;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.xiang.xservice.basic.utils.DateUtils;
import com.xiang.xservice.basic.utils.HttpUtils;
import com.xiang.xservice.cache.service.IRedisService;
import com.xiang.xservice.common.entity.DayResult;
import com.xiang.xservice.common.enums.RedisConstant;
import com.xiang.xservice.common.enums.UrlConstant;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.HashMap;
import java.util.Objects;
/**
* @Author: xiang
* @Date: 2025-10-04 10:09
*/
@Component
@RequiredArgsConstructor
@RestController
public class HolidayQueryJob {
private final IRedisService redisService;
private static final String API_KEY = "d20db0ca13e151ca7323d849d8efc6db";
@Scheduled(cron = "0 0 0 1 1/1 ?")
@PostMapping("/queryHolidayInfoJob")
public void queryHolidayInfoJob() {
YearMonth now = YearMonth.now(); // 当前年月
LocalDate start = now.atDay(1);
LocalDate end = now.atEndOfMonth();
for (LocalDate d = start; !d.isAfter(end); d = d.plusDays(1)) {
try {
String date = DateUtils.getDateFromDate(d);
HashMap<String, String> paramMap = Maps.newHashMap();
paramMap.put("key", API_KEY);
paramMap.put("date", date);
paramMap.put("detail", "");
HashMap<String, String> headers = Maps.newHashMap();
headers.put("Content-Type", "application/x-www-form-urlencoded");
String resp = HttpUtils.doGet(UrlConstant.HOLIDAY_QUERY_URL, headers, paramMap);
if (StringUtils.isNotBlank(resp)) {
JSONObject jsonObject = JSON.parseObject(resp);
String reason = (String) jsonObject.get("reason");
if (!StringUtils.equals(reason, "success")) {
continue;
}
JSONObject result = jsonObject.getJSONObject("result");
DayResult dayResult = JSON.toJavaObject(result, DayResult.class);
if (Objects.isNull(dayResult)) {
continue;
}
redisService.hSet(RedisConstant.DAY_INFO_PREFIX_KEY + RedisConstant.getDate4Key(), date, result);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,16 @@
package com.xiang.xservice.common.utils;
import com.xiang.xservice.common.entity.DayResult;
/**
* @Author: xiang
* @Date: 2025-10-04 10:34
*/
public class DateUtils {
public static Boolean validHoliday(DayResult result) {
return com.xiang.xservice.basic.utils.DateUtils.validHolidayTime(
result.getDate(), result.getStatusDesc(), result.getWeek(), result.getStatus());
}
}

View File

@@ -1,6 +1,7 @@
package com.xiang.xservice.fwd.entity.pojo;
import com.xiang.xservice.fwd.entity.resp.http.perform.SeatPlan;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -8,6 +9,7 @@ import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Data
@AllArgsConstructor
@@ -54,4 +56,9 @@ public class FPerformProjectInfo {
private String subClassifyName;
private LocalDateTime preSaleTime;
/**
* 座位id
*/
private List<SeatPlan> seatPlans;
}

View File

@@ -36,6 +36,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -135,6 +136,108 @@ public class PullDataFromFWDJob {
@PostMapping("/pullPerformDataJob")
@Scheduled(cron = "0 0 1 1/1 * ?")
public void pullPerformDataJobV2() {
int pageNum = 0;
while (true) {
pageNum++;
BaseRequest baseRequest = new BaseRequest();
baseRequest.setCurrent(pageNum);
baseRequest.setPageSize(50);
ProjectsResp projectsResp = httpRequestHelper.fetchWithRetry(() -> performServiceHttp.getShowProjectsFromHttp(baseRequest), "fetch-projects");
if (Objects.isNull(projectsResp) || CollectionUtils.isEmpty(projectsResp.getList())) {
break;
}
List<ProjectList> projects = projectsResp.getList();
List<CompletableFuture<FPerformProjectInfo>> futures = Lists.newArrayList();
for (ProjectList project : projects) {
CompletableFuture<FPerformProjectInfo> future = CompletableFuture.supplyAsync(() -> handleProjectData(project), es);
futures.add(future);
}
List<FPerformProjectInfo> results = futures.stream().map(CompletableFuture::join).toList();
// 查询演出座位档次信息
List<FPerformSeatInfo> insertList = Lists.newCopyOnWriteArrayList();
List<FPerformSeatInfo> updateList = Lists.newCopyOnWriteArrayList();
for (FPerformProjectInfo result : results) {
List<SeatPlan> seatPlans = result.getSeatPlans();
if (CollectionUtils.isEmpty(seatPlans)) {
continue;
}
List<Long> seatPlanIds = seatPlans.stream().map(SeatPlan::getSeatPlanId).toList();
List<SeatPlanStatus> seatPlanStatusList = httpRequestHelper.fetchWithRetry(() -> performServiceHttp.getSeatPlanStatusFromHttp(seatPlanIds), "fetch-seat-plan-status");
if (CollectionUtils.isEmpty(seatPlanStatusList)) {
continue;
}
Map<Long, SeatPlanStatus> map = seatPlanStatusList.stream().collect(Collectors.toMap(SeatPlanStatus::getSeatPlanId, Function.identity(), (a, b) -> a));
Map<Long, FPerformSeatInfo> existSeatMap = performSeatInfoMapper.getPerformSeatInfoBySeatIds(seatPlanIds)
.stream()
.collect(Collectors.toMap(FPerformSeatInfo::getSeatPlanId, Function.identity(), (a, b) -> a));
for (SeatPlan seatPlan : seatPlans) {
if (map.containsKey(seatPlan.getSeatPlanId())) {
SeatPlanStatus value = map.get(seatPlan.getSeatPlanId());
if (existSeatMap.containsKey(seatPlan.getSeatPlanId())) {
// 更新
FPerformSeatInfo performSeatInfo = existSeatMap.get(seatPlan.getSeatPlanId());
performSeatInfo.setSoldStock(value.getSoldOutFlag() ? 1 : 0);
updateList.add(performSeatInfo);
} else {
// 新增
saveSeatInfo(result.getProjectId(), seatPlan.getSeatPlanId(), value, seatPlan, insertList);
}
}
}
}
if (!CollectionUtils.isEmpty(insertList)) {
performSeatInfoMapper.batchSave(insertList);
}
if (!CollectionUtils.isEmpty(updateList)) {
for (FPerformSeatInfo seatInfo : updateList) {
performSeatInfoMapper.update(seatInfo);
}
}
}
}
private FPerformProjectInfo handleProjectData(ProjectList project) {
// 查询演出的详情
ProjectInfoResp projectInfoFromHttp = httpRequestHelper.fetchWithRetry(() -> performServiceHttp.getProjectInfoFromHttp(project.getProjectId()), "fetch-project-info");
if (Objects.isNull(projectInfoFromHttp)) {
return null;
}
// 查询演出信息
Perform performsByProjectIdFromHttp = httpRequestHelper.fetchWithRetry(() -> performServiceHttp.getPerformsByProjectIdFromHttp(project.getProjectId()), "fetch-perform-by-project-id");
if (Objects.isNull(performsByProjectIdFromHttp)) {
return null;
}
// 查询数据库
FPerformProjectInfo projectInfo = performProjectInfoMapper.getProjectByProjectId(performsByProjectIdFromHttp.getProjectId());
if (Objects.isNull(projectInfo)) {
// 不存在则新增
saveProjectInfo(project, projectInfoFromHttp);
} else {
// 存在则更新
buildUpdateProjectInfo(project, projectInfo, projectInfoFromHttp);
performProjectInfoMapper.update(projectInfo);
}
List<PerformInfo> performInfos = performsByProjectIdFromHttp.getPerformInfos();
List<SeatPlan> seats = Lists.newArrayList();
if (CollectionUtils.isEmpty(performInfos)) {
return projectInfo;
}
for (PerformInfo performInfo : performInfos) {
List<PerformDetail> info = performInfo.getPerformInfo();
if (CollectionUtils.isEmpty(info)) {
return projectInfo;
}
for (PerformDetail performDetail : info) {
seats.addAll(performDetail.getSeatPlans().stream().toList());
}
}
projectInfo.setSeatPlans(seats);
return projectInfo;
}
public void pullPerformDataJob() {
int pageNum = 0;
while (true) {
@@ -210,7 +313,7 @@ public class PullDataFromFWDJob {
updateList.add(performSeatInfo);
} else {
// 新增
saveSeatInfo(projectList, seatPlan.getSeatPlanId(), value, seatPlan, insertList);
saveSeatInfo(projectList.getProjectId(), seatPlan.getSeatPlanId(), value, seatPlan, insertList);
}
}
}
@@ -228,7 +331,7 @@ public class PullDataFromFWDJob {
}
}
private static void saveSeatInfo(ProjectList projectList, Long seatPlanId, SeatPlanStatus seatPlanStatus, SeatPlan seatPlan, List<FPerformSeatInfo> insertList) {
private static void saveSeatInfo(Long projectId, Long seatPlanId, SeatPlanStatus seatPlanStatus, SeatPlan seatPlan, List<FPerformSeatInfo> insertList) {
FPerformSeatInfo fPerformSeatInfo = new FPerformSeatInfo();
fPerformSeatInfo.setSeatPlanId(seatPlanId);
fPerformSeatInfo.setSeatPlanName(seatPlan.getSeatPlanName());
@@ -254,7 +357,7 @@ public class PullDataFromFWDJob {
if (StringUtils.isNotBlank(seatPlan.getSaleTime())) {
fPerformSeatInfo.setSaleTime(DateUtils.getDateTimeFromStr(seatPlan.getSaleTime()));
}
fPerformSeatInfo.setProjectId(projectList.getProjectId());
fPerformSeatInfo.setProjectId(projectId);
if (!seatPlanStatus.getSoldOutFlag() && seatPlanStatus.getStandbyStatus().equals(10)) {
fPerformSeatInfo.setSoldOut(0);
} else {

View File

@@ -23,6 +23,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -68,6 +69,7 @@ public class PerformServiceHttpServiceImpl implements IPerformServiceHttp {
public ProjectInfoResp getProjectInfoFromHttp(Long projectId) {
Map<String, String> params = Maps.newHashMap();
params.put("project_id", String.valueOf(projectId));
params.put("v", String.valueOf(Instant.now().getEpochSecond()));
String respStr = HttpUtils.doGet(UrlConstants.PROJECTS_INFO_URL, buildFWDHeaders(UrlConstants.token), params);
if (StringUtils.isBlank(respStr)) {
return null;
@@ -113,6 +115,7 @@ public class PerformServiceHttpServiceImpl implements IPerformServiceHttp {
public Perform getPerformsByProjectIdFromHttp(Long projectId) {
Map<String, String> params = Maps.newHashMap();
params.put("project_id", String.valueOf(projectId));
params.put("v", String.valueOf(Instant.now().getEpochSecond()));
String respStr = HttpUtils.doGet(UrlConstants.PERFORMS_URL, buildFWDHeaders(UrlConstants.token), params);
if (StringUtils.isBlank(respStr)) {
return null;
@@ -213,4 +216,9 @@ public class PerformServiceHttpServiceImpl implements IPerformServiceHttp {
headers.put("Accept-Language", "zh-CN,zh;q=0.9");
return headers;
}
private Map<String, String> buildFWDOrderHeaders(String token) {
Map<String, String> headers = Maps.newHashMap();
return headers;
}
}

View File

@@ -1,7 +1,11 @@
package com.xiang.xservice.stock.data.schedule;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.xiang.xservice.basic.utils.DateUtils;
import com.xiang.xservice.cache.service.IRedisService;
import com.xiang.xservice.common.entity.DayResult;
import com.xiang.xservice.common.enums.RedisConstant;
import com.xiang.xservice.stock.data.entity.StockSinaDataRecordDO;
import com.xiang.xservice.stock.data.service.IStockDataService;
import com.xiang.xservice.stock.gnshyx.entity.StockGnshyxRecordDataDO;
@@ -12,6 +16,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
@@ -22,11 +27,15 @@ public class StockDataPullJob {
private final ICloudRecordDataService cloudRecordDataService;
private final IStockDataService stockDataService;
private final IRedisService redisService;
private static final Integer BATCH_SIZE = 500;
@Scheduled(cron = "*/1 * * * * ?")
public void sinaDataPullJob() {
if (DateUtils.validWeekTime()) return;
LocalDate now = LocalDate.now();
String dayResult = (String) redisService.hGet(RedisConstant.DAY_INFO_PREFIX_KEY, DateUtils.getDateFromDate(now));
if (com.xiang.xservice.common.utils.DateUtils.validHoliday(JSON.parseObject(dayResult, DayResult.class))) return;
log.info(">>>>>>>>>>>>>>>>>新浪财经数据拉取开始>>>>>>>>>>>>>>>>>");
List<StockGnshyxRecordDataDO> dataList = cloudRecordDataService.getList();
List<StockSinaDataRecordDO> result = Lists.newArrayList();

View File

@@ -14,7 +14,6 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;

View File

@@ -1,9 +1,14 @@
package com.xiang.xservice.xb.schedule.xb;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Lists;
import com.xiang.xservice.basic.config.MyThreadFactory;
import com.xiang.xservice.basic.utils.DateUtils;
import com.xiang.xservice.basic.xservice.dingTalk.service.DingTalkService;
import com.xiang.xservice.cache.service.IRedisService;
import com.xiang.xservice.common.entity.DayResult;
import com.xiang.xservice.common.enums.RedisConstant;
import com.xiang.xservice.xb.entity.pojo.xb.FundMessage;
import com.xiang.xservice.xb.entity.pojo.xb.XbFundList;
import com.xiang.xservice.xb.entity.response.xbyj.fund.FundInfo;
@@ -47,6 +52,7 @@ public class FundInfoQueryJob {
private final FundService fundService;
private final DingTalkService dingTalkService;
private final XBFundMapper xbFundMapper;
private final IRedisService redisService;
private final ExecutorService es =
new ThreadPoolExecutor(
10,
@@ -67,10 +73,11 @@ public class FundInfoQueryJob {
@Scheduled(cron = "0 0/5 9,10,11,13,14,15 * * ? ")
public void queryFundEmergencyJob() throws Exception {
// 周六周日过滤
if (Objects.equals(LocalDateTime.now().getDayOfWeek(), DayOfWeek.SATURDAY) ||
Objects.equals(LocalDateTime.now().getDayOfWeek(), DayOfWeek.SUNDAY)) {
return;
}
if (DateUtils.validWeekTime()) return;
LocalDate now = LocalDate.now();
String dayResult = (String) redisService.hGet(RedisConstant.DAY_INFO_PREFIX_KEY, DateUtils.getDateFromDate(now));
if (com.xiang.xservice.common.utils.DateUtils.validHoliday(JSON.parseObject(dayResult, DayResult.class))) return;
List<com.xiang.xservice.xb.entity.pojo.xb.FundInfo> fundInfos = xbFundMapper.queryListIn2Min();
if (CollectionUtils.isEmpty(fundInfos)) {
return;