Files
contract-manager/client/src/main/java/com/ecep/contract/service/CompanyFileService.java
songqq 039d753bab refactor(vo): 重构VO对象结构,统一字段命名和接口实现
重构所有VO对象,统一字段命名规范,移除冗余字段,优化接口实现
新增Voable接口用于VO对象转换
调整BaseViewModel和ProjectBasedViewModel接口定义
更新相关服务和控制器以适应VO对象变更
2025-09-21 17:47:52 +08:00

492 lines
19 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.ecep.contract.service;
import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.ecep.contract.vo.CompanyOldNameVo;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.ecep.contract.CompanyFileType;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.SpringApp;
import com.ecep.contract.constant.CloudServiceConstant;
import com.ecep.contract.constant.CompanyConstant;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.CompanyFile;
import com.ecep.contract.model.CompanyOldName;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.CompanyFileViewModel;
import com.ecep.contract.vo.CompanyFileVo;
import com.ecep.contract.vo.CompanyVo;
import javafx.collections.ObservableList;
@Service
public class CompanyFileService extends QueryService<CompanyFileVo, CompanyFileViewModel> {
public List<CompanyFileVo> findByCompany(CompanyVo company) {
if (company == null) {
return List.of();
}
return findAll(ParamUtils.equal("company", company.getId()), Pageable.unpaged()).getContent();
}
public List<CompanyFileVo> findByCompanyAndPath(CompanyVo company, String absolutePath) {
return findAll(ParamUtils.builder().equals("company", company.getId()).equals("filePath", absolutePath).build(),
Pageable.unpaged()).getContent();
}
public boolean reBuildingFiles(CompanyVo company, MessageHolder holder) {
List<CompanyFileVo> dbFiles = findByCompany(company);
List<CompanyFileVo> retrieveFiles = new ArrayList<>();
boolean modfied = false;
Map<String, CompanyFileVo> map = new HashMap<>();
// 排除掉数据库中重复的
for (CompanyFileVo dbFile : dbFiles) {
String filePath = dbFile.getFilePath();
// 没有文件信息,无效记录,删除
if (!StringUtils.hasText(filePath)) {
delete(dbFile);
modfied = true;
continue;
}
// 目录不存在,删除
File dir = new File(filePath);
if (!dir.exists()) {
delete(dbFile);
modfied = true;
continue;
}
CompanyFileVo old = map.put(filePath, dbFile);
// 目录有重复删除
if (old != null) {
delete(old);
modfied = true;
}
}
Map<String, File> directoryMap = new HashMap<>();
// 公司目录
if (StringUtils.hasText(company.getPath())) {
File dir = new File(company.getPath());
directoryMap.put(company.getName(), dir);
}
// 获取所有曾用名
List<CompanyOldNameVo> oldNames = SpringApp.getBean(CompanyOldNameService.class).findAllByCompany(company);
for (CompanyOldNameVo companyOldName : oldNames) {
String path = companyOldName.getPath();
if (StringUtils.hasText(path)) {
File dir = new File(path);
directoryMap.put(companyOldName.getName(), dir);
}
}
for (Map.Entry<String, File> entry : directoryMap.entrySet()) {
String companyName = entry.getKey();
File dir = entry.getValue();
if (!StringUtils.hasText(companyName)) {
continue;
}
if (dir == null || !dir.exists()) {
continue;
}
File[] files = dir.listFiles();
if (files == null) {
// 文件系统出错或者没有相关文件
continue;
}
for (File file : files) {
// 只处理文件
if (!file.isFile() || FileUtils.isHiddenFile(file)) {
continue;
}
String filePath = file.getAbsolutePath();
if (!map.containsKey(filePath)) {
// 未记录
CompanyFileVo filled = fillFileType(file, holder);
retrieveFiles.add(filled);
}
}
}
holder.info("导入 " + retrieveFiles.size() + " 个文件");
if (retrieveFiles.isEmpty()) {
return modfied;
}
// update db
retrieveFiles.forEach(v -> {
v.setCompanyId(company.getId());
save(v);
});
return true;
}
/**
* 从文件名生成公司文件对象,文件已经存在公司对应的存储目录下
*
* @param file 文件
* @param holder 状态输出
* @return 公司文件对象
*/
private CompanyFileVo fillFileType(File file, MessageHolder holder) {
String fileName = file.getName();
CompanyFileVo companyFile = new CompanyFileVo();
companyFile.setType(CompanyFileType.General);
companyFile.setFilePath(file.getAbsolutePath());
fillApplyDateAndExpiringDateAbsent(file, companyFile);
// 天眼查 基础版企业信用报告
if (fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_BASIC_REPORT)
|| fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_MAJOR_REPORT)
|| fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_ANALYSIS_REPORT)) {
companyFile.setType(CompanyFileType.CreditReport);
fillExpiringDateAbsent(companyFile);
return companyFile;
}
// 天眼查 企业信用信息公示报告
if (fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_CREDIT_REPORT)) {
companyFile.setType(CompanyFileType.CreditInfoPublicityReport);
return companyFile;
}
// 集团相关方平台 元素征信 企业征信报告
if (fileName.contains(CloudServiceConstant.RK_VENDOR_NAME)
&& fileName.contains(CloudServiceConstant.RK_ENTERPRISE_CREDIT_REPORT)) {
companyFile.setType(CompanyFileType.CreditReport);
fillExpiringDateAbsent(companyFile);
return companyFile;
}
// 营业执照
if (fileName.contains(CompanyConstant.BUSINESS_LICENSE)) {
companyFile.setType(CompanyFileType.BusinessLicense);
return companyFile;
}
// 其他企业信用报告
if (fileName.contains(CompanyConstant.ENTERPRISE_REPORT)) {
companyFile.setType(CompanyFileType.CreditReport);
fillExpiringDateAbsent(companyFile);
return companyFile;
}
return companyFile;
}
/**
* 补齐有效期
*/
private void fillExpiringDateAbsent(CompanyFileVo file) {
LocalDate expiringDate = file.getExpiringDate();
if (expiringDate == null) {
LocalDate applyDate = file.getApplyDate();
if (applyDate != null) {
expiringDate = applyDate.plusYears(1);
file.setExpiringDate(expiringDate);
}
}
}
private static void fillApplyDateAndExpiringDateAbsent(File file, CompanyFileVo companyFile) {
LocalDate applyDate = companyFile.getApplyDate();
if (applyDate != null) {
return;
}
String fileName = file.getName();
Pattern pattern = Pattern.compile(MyDateTimeUtils.REGEX_DATE);
Matcher matcher = pattern.matcher(fileName);
while (matcher.find()) {
// 找到第一个日期,记作起始日期
String date = matcher.group();
try {
LocalDate n = LocalDate.parse(date);
companyFile.setApplyDate(n);
// 如果 截至日期未设置,则第二个日期记作截至日期(如有)
LocalDate expiringDate = companyFile.getExpiringDate();
if (expiringDate == null) {
while (matcher.find()) {
date = matcher.group();
try {
n = LocalDate.parse(date);
companyFile.setExpiringDate(n);
break;
} catch (Exception ignored) {
}
}
}
break;
} catch (Exception ignored) {
}
}
}
public void verify(CompanyVo company, LocalDate verifyDate, MessageHolder holder) {
// 查询公司的资信评估报告
List<CompanyFileVo> files = findFileByCompanyAndType(company, CompanyFileType.CreditReport);
CompanyFileVo companyFile = files.stream()
.filter(v -> v.getApplyDate() != null && v.getExpiringDate() != null)
.filter(v -> MyDateTimeUtils.dateValidFilter(verifyDate, v.getApplyDate(), v.getExpiringDate(), 30))
.findFirst().orElse(null);
if (companyFile == null) {
List<LocalDate> dates = new ArrayList<>();
files.stream()
.filter(v -> v.getApplyDate() != null && !verifyDate.isBefore(v.getApplyDate()))
.max(Comparator.comparing(CompanyFileVo::getApplyDate))
.map(CompanyFileVo::getApplyDate)
.ifPresent(dates::add);
files.stream()
.filter(v -> v.getExpiringDate() != null && !verifyDate.isAfter(v.getExpiringDate()))
.min(Comparator.comparing(CompanyFileVo::getApplyDate))
.map(CompanyFileVo::getApplyDate)
.ifPresent(dates::add);
if (dates.isEmpty()) {
holder.error("未匹配到资信评估报告");
} else if (dates.size() == 1) {
holder.error("未匹配到资信评估报告, 最接近日期:" + dates.getFirst());
} else {
LocalDate localDate = dates.stream().max(LocalDate::compareTo).orElse(null);
holder.error("未匹配到资信评估报告, 最接近日期:" + localDate);
}
}
}
private List<CompanyFileVo> findFileByCompanyAndType(CompanyVo company, CompanyFileType companyFileType) {
return findAll(ParamUtils.builder().equals("company", company.getId()).equals("type", companyFileType).build(),
Pageable.unpaged()).getContent();
}
public LocalDate getNextCreditReportDate(CompanyVo company, Consumer<String> state) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getNextCreditReportDate'");
}
public void copyAsMatched(CompanyVo company, LocalDate applyDate, Consumer<String> state) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'copyAsMatched'");
}
public void copyAsMatchedByContract(CompanyVo company, ObservableList<String> list) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'copyAsMatchedByContract'");
}
/**
* 移动文件到企业目录下
*
* @param company 企业对象
* @param files 要被移动的文件集合,需要从中选择需要的
* @param holder 状态输出
*/
public boolean retrieveFromDownloadFiles(CompanyVo company, File[] files, MessageHolder holder) {
Map<String, File> map = new HashMap<>();
File home = new File(company.getPath());
map.put(company.getName(), home);
List<CompanyFileVo> retrieveFiles = new ArrayList<>();
List<CompanyOldNameVo> oldNames = SpringApp.getBean(CompanyOldNameService.class).findAllByCompany(company);
// 获取所有曾用名
for (CompanyOldNameVo companyOldName : oldNames) {
String name = companyOldName.getName();
if (!StringUtils.hasText(name)) {
continue;
}
File dir = null;
String path = companyOldName.getPath();
if (StringUtils.hasText(path)) {
dir = new File(path);
}
map.put(name, dir);
}
// 对所有文件进行遍历
for (int i = 0; i < files.length; i++) {
File file = files[i];
// 只处理文件
if (!file.isFile()) {
continue;
}
MessageHolder sub = holder.sub("[" + (i + 1) + "/" + files.length + "]");
String fileName = file.getName();
sub.info(fileName);
for (Map.Entry<String, File> entry : map.entrySet()) {
String companyName = entry.getKey();
// 必须要包含公司名称否则无法区分
if (!fileName.contains(companyName)) {
continue;
}
// 文件存储的目的地目录
File dir = entry.getValue();
if (dir == null) {
dir = home;
}
CompanyFileVo filled = fillDownloadFileType(company, file, companyName, dir, sub);
if (filled != null) {
retrieveFiles.add(filled);
}
}
}
holder.info("导入 " + retrieveFiles.size() + " 个文件");
if (retrieveFiles.isEmpty()) {
return false;
}
// update db
retrieveFiles.forEach(v -> {
v.setCompanyId(company.getId());
save(v);
});
return true;
}
/**
* 从文件名生成公司文件对象
* 文件从下载目录中导入
*
* @param company 公司对象
* @param file 导入的文件对象
* @param companyName 公司名称
* @param destDir 目标目录
* @param holder 状态输出
* @return 生成的公司文件对象如果无法转换则返回null
*/
private CompanyFileVo fillDownloadFileType(CompanyVo company, File file, String companyName, File destDir,
MessageHolder holder) {
String fileName = file.getName();
// 天眼查的报告
// 目前只有 基础版企业信用报告, 企业信用信息公示报告下载保存时的文件名中没有天眼查
if (CloudTycService.isTycReport(fileName)) {
CompanyFileVo companyFile = new CompanyFileVo();
companyFile.setType(CompanyFileType.CreditReport);
fillApplyDateAbsent(file, companyFile);
String destFileName = fileName;
// 重命名 基础版企业信用报告
for (String report : Arrays.asList(
CloudServiceConstant.TYC_ENTERPRISE_ANALYSIS_REPORT,
CloudServiceConstant.TYC_ENTERPRISE_BASIC_REPORT,
CloudServiceConstant.TYC_ENTERPRISE_MAJOR_REPORT)) {
if (fileName.contains(report)) {
LocalDate applyDate = companyFile.getApplyDate();
if (applyDate == null) {
applyDate = LocalDate.now();
companyFile.setApplyDate(applyDate);
}
String formatted = MyDateTimeUtils.format(applyDate);
String extension = StringUtils.getFilenameExtension(fileName);
destFileName = String.format("%s_%s_%s_%s.%s",
companyName, CloudServiceConstant.TYC_NAME, report, formatted, extension);
}
}
// 重新设置 企业分析报告 未普通文件
// if (fileName.contains(CloudTycService.TYC_ENTERPRISE_ANALYSIS_REPORT)) {
// companyFile.setType(General);
// }
File dest = new File(destDir, destFileName);
// 移动文件
if (!file.renameTo(dest)) {
// 移动失败时
holder.warn(fileName + " 无法移动到 " + dest.getAbsolutePath());
return null;
}
holder.info(fileName + " 移动到 " + dest.getAbsolutePath());
companyFile.setFilePath(dest.getAbsolutePath());
//
if (companyFile.getExpiringDate() == null) {
if (companyFile.getApplyDate() != null) {
companyFile.setExpiringDate(companyFile.getApplyDate().plusYears(1));
}
}
return companyFile;
}
// 企业信用信息公示报告
if (fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_CREDIT_REPORT)) {
CompanyFileVo companyFile = new CompanyFileVo();
companyFile.setType(CompanyFileType.CreditInfoPublicityReport);
fillApplyDateAbsent(file, companyFile);
File dest = new File(destDir, fileName);
// 移动文件
if (!file.renameTo(dest)) {
if (dest.exists()) {
// 尝试删除已经存在的文件
if (!dest.delete()) {
holder.warn("覆盖时,无法删除已存在的文件 " + dest.getAbsolutePath());
return null;
}
if (file.renameTo(dest)) {
List<CompanyFileVo> files = findByCompanyAndPath(company, dest.getAbsolutePath());
if (!files.isEmpty()) {
companyFile = files.getFirst();
}
} else {
holder.error(fileName + " 无法覆盖到 " + dest.getAbsolutePath());
return null;
}
} else {
holder.error(fileName + " 无法移动到 " + dest.getAbsolutePath());
return null;
}
}
holder.info(fileName + " 移动到 " + dest.getAbsolutePath());
companyFile.setFilePath(dest.getAbsolutePath());
return companyFile;
}
return null;
}
/**
* 当 ApplyDate 未设置时,尝试使用文件名中包含的日期
*/
private static void fillApplyDateAbsent(File file, CompanyFileVo companyFile) {
LocalDate applyDate = companyFile.getApplyDate();
if (applyDate != null) {
return;
}
String fileName = file.getName();
// 从文件名中提取日期
LocalDate picked = MyDateTimeUtils.pickLocalDate(fileName);
if (picked != null) {
companyFile.setApplyDate(picked);
}
}
}