重构所有VO对象,统一字段命名规范,移除冗余字段,优化接口实现 新增Voable接口用于VO对象转换 调整BaseViewModel和ProjectBasedViewModel接口定义 更新相关服务和控制器以适应VO对象变更
492 lines
19 KiB
Java
492 lines
19 KiB
Java
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);
|
||
}
|
||
}
|
||
}
|