feat: 实现节假日服务功能并更新项目版本

refactor(CloudRkManagerWindowController): 简化任务初始化逻辑
feat(HolidayService): 添加节假日调整和检查功能
feat(HolidayTable): 实现Voable接口并添加toVo方法
feat(HolidayTableRepository): 添加节假日查询方法
docs: 添加服务器端Service类规则文档
build: 更新项目版本至0.0.101-SNAPSHOT
This commit is contained in:
2025-10-10 10:21:51 +08:00
parent e49952a63c
commit 0dcc9236a8
14 changed files with 744 additions and 62 deletions

View File

@@ -6,12 +6,12 @@
<parent>
<groupId>com.ecep.contract</groupId>
<artifactId>Contract-Manager</artifactId>
<version>0.0.100-SNAPSHOT</version>
<version>0.0.101-SNAPSHOT</version>
</parent>
<groupId>com.ecep.contract</groupId>
<artifactId>server</artifactId>
<version>0.0.100-SNAPSHOT</version>
<version>0.0.101-SNAPSHOT</version>
<properties>
<maven.compiler.source>${java.version}</maven.compiler.source>
@@ -22,7 +22,7 @@
<dependency>
<groupId>com.ecep.contract</groupId>
<artifactId>common</artifactId>
<version>0.0.100-SNAPSHOT</version>
<version>0.0.101-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -21,7 +21,6 @@ import com.ecep.contract.CustomerFileType;
import com.ecep.contract.VendorFileType;
import com.ecep.contract.SpringApp;
import com.ecep.contract.ds.company.CompanyFileUtils;
import com.ecep.contract.ds.other.repository.HolidayTableRepository;
import com.ecep.contract.ds.company.model.Company;
import com.ecep.contract.model.CompanyBasicFile;
import com.ecep.contract.ds.customer.model.CompanyCustomerFile;
@@ -46,11 +45,11 @@ public abstract class CompanyBasicService {
date = date.plusDays(-2);
}
HolidayTableRepository holidayTableRepository = SpringApp.getBean(HolidayTableRepository.class);
//TODO 跳过节假日
HolidayService holidayTableRepository = SpringApp.getBean(HolidayService.class);
// TODO 跳过节假日
int tryDays = 15;
while (tryDays-- > 0) {
HolidayTable holidayTable = holidayTableRepository.findById(date).orElse(null);
HolidayTable holidayTable = holidayTableRepository.getById(date);
if (holidayTable == null) {
// 没有节假日定义,检查是否是工作日
DayOfWeek dayOfWeek = date.getDayOfWeek();
@@ -78,7 +77,6 @@ public abstract class CompanyBasicService {
@Autowired
protected CompanyService companyService;
protected boolean isEditableFile(String fileName) {
return FileUtils.withExtensions(fileName,
FileUtils.XLS, FileUtils.XLSX,
@@ -93,7 +91,8 @@ public abstract class CompanyBasicService {
public abstract <T, F extends CompanyBasicFile<T>, ID> void deleteFile(F file);
protected <T, F extends CompanyBasicFile<T>, ID> boolean fetchDbFiles(List<F> dbFiles, Map<String, F> map, Consumer<String> status) {
protected <T, F extends CompanyBasicFile<T>, ID> boolean fetchDbFiles(List<F> dbFiles, Map<String, F> map,
Consumer<String> status) {
boolean modified = false;
List<File> editFiles = new ArrayList<>();
// 排除掉数据库中重复的
@@ -166,8 +165,8 @@ public abstract class CompanyBasicService {
* @see CompanyCustomerFile
* @see CustomerFileType
*/
protected abstract <T, F extends CompanyBasicFile<T>> boolean fillFileAsDefaultType(F dbFile, File file, Consumer<String> status);
protected abstract <T, F extends CompanyBasicFile<T>> boolean fillFileAsDefaultType(F dbFile, File file,
Consumer<String> status);
protected void moveFileToCompany(Company company, List<File> needMoveToCompanyPath) {
if (needMoveToCompanyPath.isEmpty()) {
@@ -219,8 +218,7 @@ public abstract class CompanyBasicService {
List<File> needMoveToCompanyPath,
List<F> retrieveFiles,
Map<String, F> map,
Consumer<String> status
) {
Consumer<String> status) {
if (!StringUtils.hasText(path)) {
return;
}
@@ -281,7 +279,8 @@ public abstract class CompanyBasicService {
* @param <T> 类型类
* @param <F> 文件类
*/
protected abstract <T, F extends CompanyBasicFile<T>> F fillFileType(File file, List<File> fileList, Consumer<String> status);
protected abstract <T, F extends CompanyBasicFile<T>> F fillFileType(File file, List<File> fileList,
Consumer<String> status);
/**
* @param customerFile 文件对象
@@ -292,7 +291,8 @@ public abstract class CompanyBasicService {
* @param <F> 文件类
* @return true 有修改
*/
protected <T, F extends CompanyBasicFile<T>> boolean fillFile(F customerFile, File file, List<File> fileList, Consumer<String> status) {
protected <T, F extends CompanyBasicFile<T>> boolean fillFile(F customerFile, File file, List<File> fileList,
Consumer<String> status) {
String fileName = file.getName();
boolean modified = CompanyFileUtils.fillApplyDateAbsent(file, customerFile, F::getSignDate, F::setSignDate);
// 评估表
@@ -320,7 +320,8 @@ public abstract class CompanyBasicService {
* @param <F> 文件类
* @return true文件对象有修改否则返回false
*/
protected <T, F extends CompanyBasicFile<T>> boolean fillFileAsEvaluationFile(F customerFile, File file, List<File> fileList, Consumer<String> status) {
protected <T, F extends CompanyBasicFile<T>> boolean fillFileAsEvaluationFile(F customerFile, File file,
List<File> fileList, Consumer<String> status) {
boolean modified = setFileTypeAsEvaluationForm(customerFile);
String fileName = file.getName();
@@ -353,7 +354,8 @@ public abstract class CompanyBasicService {
return modified;
}
private <T, F extends CompanyBasicFile<T>> boolean useAsEditableFile(F customerFile, File file, List<File> fileList, Consumer<String> status) {
private <T, F extends CompanyBasicFile<T>> boolean useAsEditableFile(F customerFile, File file, List<File> fileList,
Consumer<String> status) {
if (fileList == null) {
return false;
}
@@ -403,7 +405,8 @@ public abstract class CompanyBasicService {
return false;
}
private <T, F extends CompanyBasicFile<T>> boolean useAsArchiveFile(F customerFile, File file, List<File> fileList, Consumer<String> status) {
private <T, F extends CompanyBasicFile<T>> boolean useAsArchiveFile(F customerFile, File file, List<File> fileList,
Consumer<String> status) {
if (fileList == null) {
return false;
}
@@ -449,7 +452,6 @@ public abstract class CompanyBasicService {
return false;
}
/**
* 设置文件类型为表单文件
*
@@ -468,5 +470,4 @@ public abstract class CompanyBasicService {
*/
protected abstract boolean isEvaluationFile(String fileName);
}

View File

@@ -0,0 +1,254 @@
package com.ecep.contract.ds.company.service;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import com.ecep.contract.IEntityService;
import com.ecep.contract.QueryService;
import com.ecep.contract.ds.other.repository.HolidayTableRepository;
import com.ecep.contract.model.HolidayTable;
import com.ecep.contract.service.VoableService;
import com.ecep.contract.vo.HolidayTableVo;
import com.fasterxml.jackson.databind.JsonNode;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import lombok.extern.slf4j.Slf4j;
/**
* 节假日表服务类
*
* @author System
*/
@Service
@CacheConfig(cacheNames = "HolidayTable")
@Slf4j
public class HolidayService implements IEntityService<HolidayTable>, QueryService<HolidayTableVo>, VoableService<HolidayTable, HolidayTableVo> {
@Autowired
private HolidayTableRepository holidayTableRepository;
/**
* 调整日期到工作日
*
* @param date 要调整的日期
* @return 调整的日期
*/
public LocalDate adjustToWorkDay(LocalDate date) {
if (date == null) {
return null;
}
while (date.getDayOfWeek() == DayOfWeek.SATURDAY || date.getDayOfWeek() == DayOfWeek.SUNDAY || isHoliday(date)) {
date = date.plusDays(1);
}
return date;
}
/**
* 检查日期是否为节假日
*
* @param date 日期
* @return 是否为节假日
*/
public boolean isHoliday(LocalDate date) {
if (date == null) {
return false;
}
HolidayTable holidayTable = holidayTableRepository.findById(date).orElse(null);
return holidayTable != null && holidayTable.isHoliday();
}
@Override
public HolidayTable getById(Integer id) {
throw new UnsupportedOperationException("HolidayTable uses LocalDate as ID, please use getById(LocalDate id) method instead");
}
/**
* 根据LocalDate类型的ID查询实体
* @param id 实体ID
* @return 实体对象
*/
public HolidayTable getById(LocalDate id) {
if (id == null) {
return null;
}
return holidayTableRepository.findById(id).orElse(null);
}
@Override
public HolidayTable save(HolidayTable entity) {
if (entity == null) {
return null;
}
return holidayTableRepository.save(entity);
}
@Override
public void delete(HolidayTable entity) {
if (entity != null && entity.getId() != null) {
holidayTableRepository.deleteById(entity.getId());
}
}
/**
* 根据LocalDate类型的ID删除实体
* @param id 实体ID
*/
public void deleteById(LocalDate id) {
if (id != null) {
holidayTableRepository.deleteById(id);
}
}
/**
* 获取所有节假日
* @param pageable 分页参数
* @return 分页结果
*/
public Page<HolidayTable> findAll(Pageable pageable) {
return holidayTableRepository.findAll(pageable);
}
@Override
public Page<HolidayTable> findAll(Specification<HolidayTable> spec, Pageable pageable) {
// 由于HolidayTableRepository不支持Specification查询返回所有节假日
return findAll(pageable);
}
@Override
public Specification<HolidayTable> getSpecification(String searchText) {
// 实现根据搜索文本构建规格化查询
return (Root<HolidayTable> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
if (searchText != null && !searchText.trim().isEmpty()) {
try {
// 尝试将搜索文本解析为日期
LocalDate date = LocalDate.parse(searchText.trim());
predicates.add(criteriaBuilder.equal(root.get("id"), date));
} catch (DateTimeParseException e) {
// 如果不是日期格式,尝试其他搜索方式
// 由于HolidayTable只有id和holiday字段这里无法进行其他字段的模糊搜索
log.warn("Search text '{}' is not a valid date format", searchText);
}
}
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
}
@Override
public HolidayTableVo findById(Integer id) {
throw new UnsupportedOperationException("HolidayTable uses LocalDate as ID, please use findById(Object id) instead");
}
@Cacheable(key = "#id", unless = "#result == null")
public HolidayTableVo findById(LocalDate id) {
HolidayTable entity = getById(id);
return entity != null ? entity.toVo() : null;
}
@Override
public Page<HolidayTableVo> findAll(JsonNode paramsNode, Pageable pageable) {
// 实现根据JSON参数过滤节假日
Page<HolidayTable> entityPage;
if (paramsNode == null || paramsNode.isEmpty()) {
// 如果没有参数,返回所有节假日
entityPage = findAll(pageable);
} else {
// 处理参数过滤
Boolean isHoliday = null;
LocalDate startDate = null;
LocalDate endDate = null;
if (paramsNode.has("isHoliday")) {
isHoliday = paramsNode.get("isHoliday").asBoolean();
}
if (paramsNode.has("startDate")) {
try {
startDate = LocalDate.parse(paramsNode.get("startDate").asText());
} catch (Exception e) {
log.warn("Failed to parse startDate: {}", e.getMessage());
}
}
if (paramsNode.has("endDate")) {
try {
endDate = LocalDate.parse(paramsNode.get("endDate").asText());
} catch (Exception e) {
log.warn("Failed to parse endDate: {}", e.getMessage());
}
}
// 根据参数组合选择合适的查询方法
if (isHoliday != null && startDate != null && endDate != null) {
// 组合条件:是否为节假日 + 日期范围
entityPage = holidayTableRepository.findByHolidayAndIdBetween(isHoliday, startDate, endDate, pageable);
} else if (isHoliday != null) {
// 单个条件:是否为节假日
entityPage = holidayTableRepository.findByHoliday(isHoliday, pageable);
} else if (startDate != null && endDate != null) {
// 单个条件:日期范围
entityPage = holidayTableRepository.findByIdBetween(startDate, endDate, pageable);
} else {
// 不满足上述条件,返回所有节假日
entityPage = findAll(pageable);
}
}
return entityPage.map(HolidayTable::toVo);
}
@Override
public long count(JsonNode paramsNode) {
// 简单实现,返回所有节假日数量
return holidayTableRepository.count();
}
@Override
public void updateByVo(HolidayTable model, HolidayTableVo vo) {
if (model == null || vo == null) {
return;
}
// 更新实体属性
model.setHoliday(vo.isHoliday());
save(model);
}
/**
* 创建节假日
*
* @param vo 节假日VO对象
* @return 创建后的节假日VO对象
*/
public HolidayTableVo createByVo(HolidayTableVo vo) {
if (vo == null || vo.getId() == null) {
throw new IllegalArgumentException("HolidayTableVo or ID cannot be null");
}
HolidayTable entity = new HolidayTable();
entity.setId(vo.getId());
entity.setHoliday(vo.isHoliday());
HolidayTable savedEntity = save(entity);
return savedEntity.toVo();
}
}

View File

@@ -1,14 +1,47 @@
package com.ecep.contract.ds.other.repository;
import java.time.LocalDate;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import com.ecep.contract.model.HolidayTable;
import java.time.LocalDate;
@Repository
public interface HolidayTableRepository // curd
extends CrudRepository<HolidayTable, LocalDate>, PagingAndSortingRepository<HolidayTable, LocalDate> {
public interface HolidayTableRepository // curd
extends CrudRepository<HolidayTable, LocalDate>, PagingAndSortingRepository<HolidayTable, LocalDate> {
/**
* 根据是否为节假日过滤
*
* @param isHoliday 是否为节假日
* @param pageable 分页参数
* @return 分页结果
*/
Page<HolidayTable> findByHoliday(boolean isHoliday, Pageable pageable);
/**
* 根据日期范围过滤
*
* @param startDate 开始日期
* @param endDate 结束日期
* @param pageable 分页参数
* @return 分页结果
*/
Page<HolidayTable> findByIdBetween(LocalDate startDate, LocalDate endDate, Pageable pageable);
/**
* 根据是否为节假日和日期范围组合过滤
*
* @param isHoliday 是否为节假日
* @param startDate 开始日期
* @param endDate 结束日期
* @param pageable 分页参数
* @return 分页结果
*/
Page<HolidayTable> findByHolidayAndIdBetween(boolean isHoliday, LocalDate startDate, LocalDate endDate,
Pageable pageable);
}