refactor: 重构供应商文件类型枚举及相关服务

feat: 为多个服务添加缓存支持
fix: 修复WebSocket任务管理和远程调用异常处理
refactor: 重命名CompanyVendorFileType为VendorFileType
refactor: 优化项目成本导入任务实现
fix: 修复ContractTabSkinBase中的空指针问题
refactor: 统一WebSocket客户端任务调用接口
This commit is contained in:
2025-09-17 22:28:17 +08:00
parent 7560250036
commit c0e4916474
43 changed files with 624 additions and 260 deletions

View File

@@ -18,7 +18,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.util.StringUtils;
import com.ecep.contract.CompanyCustomerFileType;
import com.ecep.contract.CompanyVendorFileType;
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;
@@ -162,7 +162,7 @@ public abstract class CompanyBasicService {
* @param <F> 文件类
* @return 是否修改了
* @see CompanyVendorFile
* @see CompanyVendorFileType
* @see VendorFileType
* @see CompanyCustomerFile
* @see CompanyCustomerFileType
*/

View File

@@ -46,7 +46,7 @@ public class ContractFileTypeService
@Cacheable(key = "'all-'+#p0.getLanguage()")
public Map<ContractFileType, ContractFileTypeLocal> findAll(Locale locale) {
return repository.getCompleteMapByLocal(locale.getLanguage());
return repository.getCompleteMapByLocal(locale.toLanguageTag());
}
@Cacheable(key = "#p0")

View File

@@ -31,10 +31,8 @@ public class ContractRepairTask extends AbstContractRepairTasker implements WebS
}
public void init(JsonNode argsNode) {
int contractId = argsNode.get(1).asInt();
int contractId = argsNode.get(0).asInt();
contract = getCachedBean(ContractService.class).findById(contractId);
String lang = argsNode.get(2).asText();
setLocale(Locale.forLanguageTag(lang));
}
@Override

View File

@@ -16,7 +16,6 @@ import lombok.Getter;
import lombok.Setter;
public class ContractVerifyTasker extends Tasker<Object> implements WebSocketServerTasker {
@Getter
@Setter
private Contract contract;
@@ -64,7 +63,7 @@ public class ContractVerifyTasker extends Tasker<Object> implements WebSocketSer
@Override
public void init(JsonNode argsNode) {
int contractId = argsNode.get(1).asInt();
int contractId = argsNode.get(0).asInt();
contract = getCachedBean(ContractService.class).findById(contractId);
}

View File

@@ -8,9 +8,14 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.stream.Collectors;
import com.ecep.contract.service.WebSocketServerTasker;
import com.ecep.contract.ui.MessageHolderImpl;
import com.fasterxml.jackson.databind.JsonNode;
import org.hibernate.Hibernate;
import com.ecep.contract.MessageHolder;
@@ -32,22 +37,18 @@ import com.ecep.contract.util.TaxRateUtils;
import lombok.Setter;
public class ProjectCostImportItemsFromContractsTasker extends Tasker<Void> {
@Setter
private ProjectCostService costService;
@Setter
private ContractService contractService;
@Setter
private ProjectCostItemService itemService;
@Setter
private ContractItemService contractItemService;
public class ProjectCostImportItemsFromContractsTasker extends Tasker<Object> implements WebSocketServerTasker {
@Setter
private Supplier<Employee> currentUser;
@Setter
private InventoryService inventoryService;
@Setter
ProjectCost cost;
AtomicBoolean verified = new AtomicBoolean(true);
@Override
public void init(JsonNode argsNode) {
int contractId = argsNode.get(0).asInt();
cost = getCachedBean(ProjectCostService.class).findById(contractId);
}
@Override
protected Void execute(MessageHolder holder) throws Exception {
@@ -142,7 +143,7 @@ public class ProjectCostImportItemsFromContractsTasker extends Tasker<Void> {
}
private void compositeOut(Map<Inventory, List<ContractItem>> map, List<ProjectCostItem> results,
MessageHolder holder) {
MessageHolder holder) {
// 根据存货匹配,可对多个相同的存货进行合并
for (Map.Entry<Inventory, List<ContractItem>> entry : map.entrySet()) {
Inventory inventory = Hibernate.isInitialized(entry.getKey()) ? entry.getKey()
@@ -336,42 +337,28 @@ public class ProjectCostImportItemsFromContractsTasker extends Tasker<Void> {
}
ProjectCostService getCostService() {
if (costService == null) {
costService = getBean(ProjectCostService.class);
}
return costService;
return getCachedBean(ProjectCostService.class);
}
public ProjectCostItemService getItemService() {
if (itemService == null) {
itemService = getBean(ProjectCostItemService.class);
}
return itemService;
return getCachedBean(ProjectCostItemService.class);
}
ContractService getContractService() {
if (contractService == null) {
contractService = getBean(ContractService.class);
}
return contractService;
return getCachedBean(ContractService.class);
}
ContractItemService getContractItemService() {
if (contractItemService == null) {
contractItemService = getBean(ContractItemService.class);
}
return contractItemService;
return getCachedBean(ContractItemService.class);
}
InventoryService getInventoryService() {
if (inventoryService == null) {
inventoryService = getBean(InventoryService.class);
}
return inventoryService;
return getCachedBean(InventoryService.class);
}
public ProjectCostItem save(ProjectCostItem entity) {
return getItemService().save(entity);
}
}

View File

@@ -298,46 +298,6 @@ public class ProjectService implements IEntityService<Project>, QueryService<Pro
return project;
}
public String makeProjectCode(Project project) {
StringBuilder sb = new StringBuilder();
sb.append(project.getSaleType().getCode());
sb.append(project.getCodeYear());
if (project.getCodeSequenceNumber() < 10) {
sb.append("0");
}
if (project.getCodeSequenceNumber() < 100) {
sb.append("0");
}
sb.append(project.getCodeSequenceNumber());
return sb.toString();
}
public File searchPath(Project project) {
ProjectSaleType saleType = project.getSaleType();
if (saleType == null) {
return null;
}
if (!Hibernate.isInitialized(saleType)) {
saleType = projectSaleTypeService.findById(saleType.getId());
project.setSaleType(saleType);
}
if (!StringUtils.hasText(saleType.getPath())) {
return null;
}
File path = new File(saleType.getPath());
if (saleType.isStoreByYear()) {
path = new File(path, "20" + project.getCodeYear());
if (!path.exists()) {
path.mkdir();// 创建目录
}
}
String projectCode = makeProjectCode(project);
// 检索目录
File[] files = path.listFiles(f -> f.isDirectory() && f.getName().contains(projectCode));
if (files != null && files.length > 0) {
path = files[0];
}
return path;
}
}

View File

@@ -6,7 +6,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import com.ecep.contract.CompanyVendorFileType;
import com.ecep.contract.VendorFileType;
import com.ecep.contract.model.CompanyVendor;
import com.ecep.contract.model.CompanyVendorFile;
@@ -16,7 +16,7 @@ public interface CompanyVendorFileRepository
List<CompanyVendorFile> findAllByVendorId(int vendorId);
List<CompanyVendorFile> findAllByVendorAndType(CompanyVendor vendor, CompanyVendorFileType type);
List<CompanyVendorFile> findAllByVendorAndType(CompanyVendor vendor, VendorFileType type);
List<CompanyVendorFile> findByVendorId(int vendorId);
}

View File

@@ -2,21 +2,21 @@ package com.ecep.contract.ds.vendor.repository;
import org.springframework.stereotype.Repository;
import com.ecep.contract.CompanyVendorFileType;
import com.ecep.contract.VendorFileType;
import com.ecep.contract.ds.other.repository.BaseEnumEntityRepository;
import com.ecep.contract.model.CompanyVendorFileTypeLocal;
import com.ecep.contract.model.VendorFileTypeLocal;
@Repository
public interface CompanyVendorFileTypeLocalRepository
extends BaseEnumEntityRepository<CompanyVendorFileType, CompanyVendorFileTypeLocal, Integer> {
extends BaseEnumEntityRepository<VendorFileType, VendorFileTypeLocal, Integer> {
@Override
default CompanyVendorFileType[] getEnumConstants() {
return CompanyVendorFileType.values();
default VendorFileType[] getEnumConstants() {
return VendorFileType.values();
}
@Override
default CompanyVendorFileTypeLocal newEntity() {
return new CompanyVendorFileTypeLocal();
default VendorFileTypeLocal newEntity() {
return new VendorFileTypeLocal();
}
}

View File

@@ -7,7 +7,6 @@ import java.util.List;
import java.util.function.Consumer;
import com.ecep.contract.*;
import com.ecep.contract.model.CompanyVendorApprovedList;
import com.ecep.contract.util.SpecificationUtils;
import com.fasterxml.jackson.databind.JsonNode;
import org.slf4j.Logger;
@@ -65,7 +64,7 @@ public class CompanyVendorFileService implements IEntityService<CompanyVendorFil
}
// 添加额外的参数过滤
if (paramsNode.has("type")) {
CompanyVendorFileType type = CompanyVendorFileType.valueOf(paramsNode.get("type").asText());
VendorFileType type = VendorFileType.valueOf(paramsNode.get("type").asText());
spec = SpecificationUtils.and(spec, (root, query, builder) -> builder.equal(root.get("type"), type));
}
spec = SpecificationUtils.andFieldEqualParam(spec, paramsNode, "valid");
@@ -97,7 +96,7 @@ public class CompanyVendorFileService implements IEntityService<CompanyVendorFil
return repository.findAll(spec, sort);
}
public List<CompanyVendorFile> findAllByVendorAndType(CompanyVendor vendor, CompanyVendorFileType type) {
public List<CompanyVendorFile> findAllByVendorAndType(CompanyVendor vendor, VendorFileType type) {
return repository.findAllByVendorAndType(vendor, type);
}
@@ -116,7 +115,7 @@ public class CompanyVendorFileService implements IEntityService<CompanyVendorFil
}
// 查询所有评价表
List<CompanyVendorFile> files = findAllByVendorAndType(companyVendor, CompanyVendorFileType.EvaluationForm);
List<CompanyVendorFile> files = findAllByVendorAndType(companyVendor, VendorFileType.EvaluationForm);
if (files == null || files.isEmpty()) {
holder.error("未见供应商评价");
return;
@@ -161,7 +160,7 @@ public class CompanyVendorFileService implements IEntityService<CompanyVendorFil
return null;
}
// 检索评价表
List<CompanyVendorFile> files = findAllByVendorAndType(companyVendor, CompanyVendorFileType.EvaluationForm);
List<CompanyVendorFile> files = findAllByVendorAndType(companyVendor, VendorFileType.EvaluationForm);
CompanyVendorFile latestFile = files.stream()
.filter(v -> v.getSignDate() != null && v.isValid())
.max(Comparator.comparing(CompanyVendorFile::getSignDate))

View File

@@ -190,7 +190,7 @@ public class CompanyVendorService extends CompanyBasicService implements IEntity
@Override
protected <T, F extends CompanyBasicFile<T>> boolean fillFileAsDefaultType(F dbFile, File file, Consumer<String> status) {
dbFile.setType((T) CompanyVendorFileType.General);
dbFile.setType((T) VendorFileType.General);
fillFile(dbFile, file, null, status);
companyVendorFileService.save((CompanyVendorFile) dbFile);
return true;
@@ -199,7 +199,7 @@ public class CompanyVendorService extends CompanyBasicService implements IEntity
@Override
protected <T, F extends CompanyBasicFile<T>> F fillFileType(File file, List<File> fileList, Consumer<String> status) {
CompanyVendorFile vendorFile = new CompanyVendorFile();
vendorFile.setType(CompanyVendorFileType.General);
vendorFile.setType(VendorFileType.General);
vendorFile.setFilePath(file.getAbsolutePath());
fillFile(vendorFile, file, fileList, status);
return (F) vendorFile;
@@ -208,8 +208,8 @@ public class CompanyVendorService extends CompanyBasicService implements IEntity
@Override
protected <T, F extends CompanyBasicFile<T>> boolean setFileTypeAsEvaluationForm(F file) {
T type = file.getType();
if (type != CompanyVendorFileType.EvaluationForm) {
file.setType((T) CompanyVendorFileType.EvaluationForm);
if (type != VendorFileType.EvaluationForm) {
file.setType((T) VendorFileType.EvaluationForm);
return true;
}
return false;

View File

@@ -2,6 +2,7 @@ package com.ecep.contract.service;
import com.ecep.contract.Message;
import com.ecep.contract.constant.WebSocketConstant;
import com.ecep.contract.ui.Tasker;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
@@ -13,7 +14,11 @@ import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@Service
@@ -29,7 +34,9 @@ public class WebSocketServerTaskManager implements InitializingBean {
public void afterPropertiesSet() throws Exception {
taskClzMap = Map.of(
"ContractSyncTask", "com.ecep.contract.cloud.u8.ContractSyncTask",
"ContractRepairTask", "com.ecep.contract.ds.contract.tasker.ContractRepairTask"
"ContractRepairTask", "com.ecep.contract.ds.contract.tasker.ContractRepairTask",
"ContractVerifyTask", "com.ecep.contract.ds.contract.tasker.ContractVerifyTask",
"ProjectCostImportItemsFromContractsTasker", "com.ecep.contract.ds.project.ProjectCostImportItemsFromContractsTasker"
);
}
@@ -62,7 +69,6 @@ public class WebSocketServerTaskManager implements InitializingBean {
JsonNode argsNode = jsonNode.get(WebSocketConstant.ARGUMENTS_FIELD_NAME);
String taskName = argsNode.get(0).asText();
String clzName = taskClzMap.get(taskName);
if (clzName == null) {
throw new IllegalArgumentException("未知的任务类型: " + taskName);
@@ -77,15 +83,32 @@ public class WebSocketServerTaskManager implements InitializingBean {
throw new IllegalArgumentException("任务类型: " + taskName + ", class: " + clzName + " 实例化失败");
}
if (tasker instanceof Tasker<?> t) {
String locale = argsNode.get(1).asText();
t.setLocale(Locale.forLanguageTag(locale));
}
if (tasker instanceof WebSocketServerTasker t) {
t.setTitleHandler(title -> sendToSession(session, sessionId, "title", title));
t.setMessageHandler(msg -> sendMessageToSession(session, sessionId, msg));
t.setPropertyHandler((name, value) -> sendToSession(session, sessionId, "property", name, value));
t.setProgressHandler((current, total) -> sendToSession(session, sessionId, "progress", current, total));
t.init(argsNode);
scheduledExecutorService.submit(t);
t.init(argsNode.get(2));
}
if (tasker instanceof Callable<?> callable) {
Thread.ofVirtual().start(() -> {
try {
sendToSession(session, sessionId, "start");
callable.call();
sendToSession(session, sessionId, "done");
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}
private boolean sendMessageToSession(WebSocketSession session, String sessionId, Message msg) {