This commit is contained in:
2025-10-11 09:21:14 +08:00
parent bda92193d4
commit 553feac0a4
93 changed files with 1736 additions and 676 deletions

View File

@@ -2,7 +2,7 @@ package com.ecep.contract.cloud.old;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.ds.company.model.Company;
import com.ecep.contract.ds.contract.model.Contract;
import com.ecep.contract.ui.Tasker;
@@ -37,7 +37,7 @@ public class OldVersionSyncCustomerTask extends Tasker<Object> {
@Override
protected Object execute(MessageHolder holder) throws Exception {
updateTitle("老版本-同步客户数据");
basePath = getCachedBean(CompanyCustomerService.class).getBasePath();
basePath = getCachedBean(CustomerService.class).getBasePath();
List<Runnable> runnable = Arrays.asList(this::loadOldNames, this::loadContacts, this::syncCustomers,
this::syncContracts);

View File

@@ -1,6 +1,7 @@
package com.ecep.contract.cloud.rk;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
@@ -38,13 +39,13 @@ public interface CloudRkRepository extends MyRepository<CloudRk, Integer> {
List<CloudRk> findAllByCompanyId(int companyId);
long countByLatestUpdateBefore(Instant instant);
long countByLatestUpdateBefore(LocalDateTime instant);
long countByAutoUpdateIsTrueAndLatestUpdateBefore(Instant instant);
long countByAutoUpdateIsTrueAndLatestUpdateBefore(LocalDateTime instant);
List<CloudRk> findTop100ByLatestUpdateBeforeOrderByLatestUpdateDesc(Instant instant);
List<CloudRk> findTop100ByLatestUpdateBeforeOrderByLatestUpdateDesc(LocalDateTime instant);
List<CloudRk> findTop100ByAutoUpdateIsTrueAndLatestUpdateBeforeOrderByLatestUpdateDesc(Instant instant);
List<CloudRk> findTop100ByAutoUpdateIsTrueAndLatestUpdateBeforeOrderByLatestUpdateDesc(LocalDateTime instant);
@Modifying
@Transactional

View File

@@ -354,9 +354,9 @@ public class CloudRkService implements IEntityService<CloudRk>, QueryService<Clo
* @return 记录条数
*/
public long countNeedUpdate() {
Instant now = Instant.now();
LocalDateTime now = LocalDateTime.now();
long elapse = getSyncElapse();
Instant instant = now.minusSeconds(elapse);
LocalDateTime instant = now.minusSeconds(elapse);
return cloudRKRepository.countByAutoUpdateIsTrueAndLatestUpdateBefore(instant);
}
@@ -365,9 +365,9 @@ public class CloudRkService implements IEntityService<CloudRk>, QueryService<Clo
*/
// @Transactional
public List<CloudRk> findNeedUpdate() {
Instant now = Instant.now();
LocalDateTime now = LocalDateTime.now();
long elapse = getSyncElapse();
Instant instant = now.minusSeconds(elapse);
LocalDateTime instant = now.minusSeconds(elapse);
return cloudRKRepository.findTop100ByAutoUpdateIsTrueAndLatestUpdateBeforeOrderByLatestUpdateDesc(instant);
}

View File

@@ -86,7 +86,7 @@ public class CloudRkCtx extends AbstractCtx implements CloudRkContext {
*/
public boolean syncCompany(Company company, CloudRk cloudRk, MessageHolder holder) {
if (!StringUtils.hasText(cloudRk.getCloudId())) {
holder.warn("未定义平台编号, 尝试从平台上自动获取");
holder.warn("未定义平台编号, 尝试获取平台编号");
// 当未定义平台编号时,尝试自动获取
if (!queryCloudIdAndSelectOne(company, cloudRk, holder)) {
// 自动获取到平台编号失败,立即返回
@@ -468,6 +468,7 @@ public class CloudRkCtx extends AbstractCtx implements CloudRkContext {
List<CloudRkService.EntInfo> results = new ArrayList<>();
ObjectMapper objectMapper = getObjectMapper();
try {
holder.debug("POST " + url);
HttpJsonUtils.post(url, data -> {
data.put("theKey", company.getName());
data.put("get", true);
@@ -819,13 +820,13 @@ public class CloudRkCtx extends AbstractCtx implements CloudRkContext {
private void saveJsonToFile(Company company, JsonNode json, String fileName, MessageHolder holder) {
String companyPath = company.getPath();
if (!StringUtils.hasText(companyPath)) {
holder.warn("公司路径为空");
holder.warn("公司路径为空, 无法保存 " + fileName);
return;
}
File dir = new File(companyPath);
if (!dir.exists()) {
holder.warn("公司路径不存在");
holder.warn("公司路径" + dir.getName() + "不存在, 无法保存 " + fileName);
return;
}

View File

@@ -12,7 +12,7 @@ import org.springframework.beans.BeansException;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.model.CustomerCatalog;
import com.ecep.contract.ui.Tasker;
import com.ecep.contract.vo.CustomerCatalogVo;
@@ -25,15 +25,15 @@ import lombok.Setter;
public class CustomerClassSyncTask extends Tasker<Object> {
private static final Logger logger = LoggerFactory.getLogger(CustomerClassSyncTask.class);
@Setter
private CompanyCustomerService companyCustomerService;
private CustomerService companyCustomerService;
public CustomerClassSyncTask() {
updateTitle("用友U8系统-同步客户分类信息");
}
CompanyCustomerService getCompanyCustomerService() {
CustomerService getCompanyCustomerService() {
if (companyCustomerService == null) {
companyCustomerService = SpringApp.getBean(CompanyCustomerService.class);
companyCustomerService = SpringApp.getBean(CustomerService.class);
}
return companyCustomerService;
}

View File

@@ -20,7 +20,7 @@ import com.ecep.contract.cloud.u8.ctx.CustomerCtx;
import com.ecep.contract.constant.CloudServiceConstant;
import com.ecep.contract.ds.company.service.CompanyService;
import com.ecep.contract.ds.contract.tasker.AbstContractRepairTasker;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.ds.other.model.CloudYu;
import com.ecep.contract.ds.company.model.Company;
import com.ecep.contract.ds.customer.model.CompanyCustomer;
@@ -42,7 +42,7 @@ public class CustomerSyncTask extends AbstContractRepairTasker {
updateTitle("用友U8系统-同步客户");
}
private CompanyCustomerService getCompanyCustomerService() {
private CustomerService getCompanyCustomerService() {
return customerCtx.getCompanyCustomerService();
}

View File

@@ -14,7 +14,7 @@ import com.ecep.contract.cloud.AbstractCtx;
import com.ecep.contract.cloud.u8.YongYouU8Repository;
import com.ecep.contract.constant.CloudServiceConstant;
import com.ecep.contract.ds.customer.service.CompanyCustomerEntityService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.ds.vendor.service.VendorEntityService;
import com.ecep.contract.ds.vendor.service.VendorService;
import com.ecep.contract.ds.company.model.Company;
@@ -45,8 +45,8 @@ public class AbstractYongYouU8Ctx extends AbstractCtx {
}
}
public CompanyCustomerService getCompanyCustomerService() {
return getCachedBean(CompanyCustomerService.class);
public CustomerService getCompanyCustomerService() {
return getCachedBean(CustomerService.class);
}
public CompanyCustomerEntityService getCompanyCustomerEntityService() {
@@ -111,12 +111,12 @@ public class AbstractYongYouU8Ctx extends AbstractCtx {
Company company = null;
if (StringUtils.hasText(customerCode)) {
CompanyCustomerEntityService customerEntityService = getCompanyCustomerEntityService();
CompanyCustomerService customerService = getCompanyCustomerService();
CustomerService customerService = getCompanyCustomerService();
CompanyCustomerEntityVo entity = customerEntityService.findByCustomerCode(customerCode);
if (entity == null) {
holder.warn("无效" + topic + "" + customerCode);
} else {
CompanyCustomerVo customer = customerService.findById(entity.getCustomerId());
CustomerVo customer = customerService.findById(entity.getCustomerId());
if (customer == null) {
holder.warn("无效" + topic + "" + customerCode);
} else {

View File

@@ -37,7 +37,7 @@ import com.ecep.contract.ds.contract.service.ContractPayPlanService;
import com.ecep.contract.ds.contract.service.ContractService;
import com.ecep.contract.ds.contract.service.ContractTypeService;
import com.ecep.contract.ds.customer.service.CompanyCustomerEntityService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.ds.project.ProjectCtx;
import com.ecep.contract.ds.project.service.ProjectSaleTypeService;
import com.ecep.contract.ds.vendor.service.VendorEntityService;
@@ -463,7 +463,7 @@ public class ContractCtx extends AbstractYongYouU8Ctx {
boolean modified = false;
boolean customerModified = false;
CompanyCustomerEntityService customerEntityService = getCompanyCustomerEntityService();
CompanyCustomerService customerService = getCompanyCustomerService();
CustomerService customerService = getCompanyCustomerService();
CompanyCustomerEntityVo entity = customerEntityService.findByCustomerCode(unit);
if (entity == null) {
CompanyCustomerEntity v1 = new CompanyCustomerEntity();
@@ -472,7 +472,7 @@ public class ContractCtx extends AbstractYongYouU8Ctx {
}
entity = updateCustomerEntityDetailByCode(entity, unit, holder);
CompanyCustomerVo customer = customerService.findById(entity.getCustomerId());
CustomerVo customer = customerService.findById(entity.getCustomerId());
if (customer == null) {
if (company != null) {
customer = customerService.findByCompany(company).toVo();

View File

@@ -14,6 +14,8 @@ public interface CompanyContactRepository extends MyRepository<CompanyContact, I
Optional<CompanyContact> findFirstByCompany(Company company);
Optional<CompanyContact> findFirstByCompanyId(Integer companyId);
List<CompanyContact> findAllByCompany(Company company);
List<CompanyContact> findAllByCompanyAndName(Company company, String name);

View File

@@ -77,18 +77,6 @@ public abstract class CompanyBasicService {
@Autowired
protected CompanyService companyService;
protected boolean isEditableFile(String fileName) {
return FileUtils.withExtensions(fileName,
FileUtils.XLS, FileUtils.XLSX,
FileUtils.DOC, FileUtils.DOCX);
}
protected boolean isArchiveFile(String fileName) {
return FileUtils.withExtensions(fileName,
FileUtils.PNG, FileUtils.PDF,
FileUtils.JPG, FileUtils.JPEG);
}
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,
@@ -328,7 +316,7 @@ public abstract class CompanyBasicService {
// 文件全路径
String fileAbsolutePath = file.getAbsolutePath();
if (isEditableFile(fileName)) {
if (FileUtils.isEditableFile(fileName)) {
// 是可编辑文件时
if (!Objects.equals(fileAbsolutePath, customerFile.getEditFilePath())) {
customerFile.setEditFilePath(fileAbsolutePath);
@@ -338,7 +326,7 @@ public abstract class CompanyBasicService {
if (useAsEditableFile(customerFile, file, fileList, status)) {
modified = true;
}
} else if (isArchiveFile(fileName)) {
} else if (FileUtils.isArchiveFile(fileName)) {
// 存档文件时
if (!Objects.equals(fileAbsolutePath, customerFile.getFilePath())) {
customerFile.setFilePath(fileAbsolutePath);
@@ -387,7 +375,7 @@ public abstract class CompanyBasicService {
String name = StringUtils.stripFilenameExtension(fileName);
for (File f : fileList) {
// 查找存档文件
if (f.getName().startsWith(name) && isArchiveFile(f.getName())) {
if (f.getName().startsWith(name) && FileUtils.isArchiveFile(f.getName())) {
archiveFile = f;
break;
}
@@ -431,7 +419,7 @@ public abstract class CompanyBasicService {
String name = StringUtils.stripFilenameExtension(fileName);
for (File f : fileList) {
// 查找存档文件
if (f.getName().startsWith(name) && isEditableFile(f.getName())) {
if (f.getName().startsWith(name) && FileUtils.isEditableFile(f.getName())) {
editFile = f;
break;
}

View File

@@ -25,6 +25,7 @@ import com.ecep.contract.service.VoableService;
import com.ecep.contract.util.MyStringUtils;
import com.ecep.contract.util.SpecificationUtils;
import com.ecep.contract.vo.CompanyContactVo;
import com.ecep.contract.vo.CompanyVo;
import com.fasterxml.jackson.databind.JsonNode;
/**
@@ -81,6 +82,10 @@ public class CompanyContactService implements IEntityService<CompanyContact>, Qu
return repository.findFirstByCompany(company).orElse(null);
}
public CompanyContactVo findFirstByCompany(CompanyVo company) {
return repository.findFirstByCompanyId(company.getId()).map(CompanyContact::toVo).orElse(null);
}
@Override
public CompanyContactVo findById(Integer id) {
return repository.findById(id).map(CompanyContact::toVo).orElse(null);

View File

@@ -33,7 +33,7 @@ import com.ecep.contract.cloud.u8.YongYouU8Service;
import com.ecep.contract.constant.CompanyConstant;
import com.ecep.contract.ds.company.repository.CompanyRepository;
import com.ecep.contract.ds.contract.service.ContractService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.ds.other.service.SysConfService;
import com.ecep.contract.ds.vendor.service.VendorService;
import com.ecep.contract.ds.company.model.Company;
@@ -76,7 +76,7 @@ public class CompanyService extends EntityService<Company, CompanyVo, Integer>
private VendorService vendorService;
@Lazy
@Autowired
private CompanyCustomerService companyCustomerService;
private CustomerService companyCustomerService;
@Lazy
@Autowired
private CompanyOldNameService companyOldNameService;
@@ -267,7 +267,7 @@ public class CompanyService extends EntityService<Company, CompanyVo, Integer>
* 删除前需要把关联数据解除
* <ul>
* <li>{@link VendorService#deleteByCompany(Company)}</li>
* <li>{@link CompanyCustomerService#deleteByCompany(Company)}</li>
* <li>{@link CustomerService#deleteByCompany(Company)}</li>
* <li>{@link CompanyOldNameService#deleteByCompany(Company)}</li>
* <li>{@link CompanyContactService#deleteByCompany(Company)}</li>
* <li>{@link ContractService#deleteByCompany(Company)}</li>
@@ -276,7 +276,7 @@ public class CompanyService extends EntityService<Company, CompanyVo, Integer>
* 或者 把关联数据转移到其他公司
* <ul>
* <li>{@link VendorService#resetTo(Company, Company)}</li>
* <li>{@link CompanyCustomerService#resetTo(Company, Company)}</li>
* <li>{@link CustomerService#resetTo(Company, Company)}</li>
* <li>{@link CompanyOldNameService#resetTo(Company, Company)}</li>
* <li>{@link CompanyContactService#resetTo(Company, Company)}</li>
* <li>{@link ContractService#resetTo(Company, Company)}</li>

View File

@@ -42,6 +42,7 @@ import com.ecep.contract.ds.vendor.model.Vendor;
import com.ecep.contract.service.VoableService;
import com.ecep.contract.util.MyStringUtils;
import com.ecep.contract.util.SpecificationUtils;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.ContractVo;
import com.fasterxml.jackson.databind.JsonNode;
@@ -119,6 +120,16 @@ public class ContractService extends EntityService<Contract, ContractVo, Integer
return contractRepository.findAllByCompanyId(company.getId());
}
public List<Contract> findAllByCompany(CompanyVo company, ContractPayWay payWay, LocalDate beginDate,
LocalDate endDate) {
return contractRepository.findAll((root, query, cb) -> {
Predicate p = cb.and(
cb.equal(root.get("company").get("id"), company.getId()),
cb.equal(root.get("payWay"), payWay));
return applyPredicate(root, cb, p, beginDate, endDate);
}, Sort.unsorted());
}
public List<Contract> findAllByProject(Project project) {
return contractRepository.findAllByProjectId(project.getId());
}

View File

@@ -13,7 +13,7 @@ import com.ecep.contract.model.Voable;
import org.hibernate.annotations.ColumnDefault;
import com.ecep.contract.util.HibernateProxyUtils;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CustomerVo;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -34,7 +34,7 @@ import lombok.ToString;
})
@ToString
public class CompanyCustomer implements IdentityEntity, CompanyBasedEntity, Voable<CompanyCustomerVo> {
public class CompanyCustomer implements IdentityEntity, CompanyBasedEntity, Voable<CustomerVo> {
@Id
@Column(name = "ID", nullable = false)
private Integer id;
@@ -105,8 +105,8 @@ public class CompanyCustomer implements IdentityEntity, CompanyBasedEntity, Voab
}
@Override
public CompanyCustomerVo toVo() {
CompanyCustomerVo vo = new CompanyCustomerVo();
public CustomerVo toVo() {
CustomerVo vo = new CustomerVo();
vo.setId(id);
vo.setCompanyId(company != null ? company.getId() : null);
vo.setCatalogId(catalog != null ? catalog.getId() : null);

View File

@@ -7,7 +7,7 @@ import com.ecep.contract.CustomerFileType;
import com.ecep.contract.model.CompanyBasicFile;
import com.ecep.contract.model.Voable;
import com.ecep.contract.util.HibernateProxyUtils;
import com.ecep.contract.vo.CompanyCustomerFileVo;
import com.ecep.contract.vo.CustomerFileVo;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -29,7 +29,7 @@ import lombok.ToString;
@Entity
@Table(name = "COMPANY_CUSTOMER_FILE")
@ToString
public class CompanyCustomerFile implements CompanyBasicFile<CustomerFileType>, Voable<CompanyCustomerFileVo> {
public class CompanyCustomerFile implements CompanyBasicFile<CustomerFileType>, Voable<CustomerFileVo> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", nullable = false)
@@ -81,8 +81,8 @@ public class CompanyCustomerFile implements CompanyBasicFile<CustomerFileType>,
}
@Override
public CompanyCustomerFileVo toVo() {
CompanyCustomerFileVo vo = new CompanyCustomerFileVo();
public CustomerFileVo toVo() {
CustomerFileVo vo = new CustomerFileVo();
vo.setId(getId());
vo.setCustomer(getCustomer() != null ? getCustomer().getId() : null);
vo.setType(getType());

View File

@@ -143,7 +143,6 @@ public class SalesBillVoucher implements IdentityEntity, BasedEntity, Voable<Sal
}
if (order != null) {
vo.setOrderId(order.getId());
vo.setOrderCode(order.getCode());
}
if (employee != null) {
vo.setEmployeeId(employee.getId());

View File

@@ -34,7 +34,7 @@ public class CompanyCustomerEntityService implements IEntityService<CompanyCusto
private CompanyCustomerEntityRepository repository;
@Autowired
private CompanyCustomerService companyCustomerService;
private CustomerService companyCustomerService;
@Autowired
private CustomerCatalogService customerCatalogService;

View File

@@ -6,6 +6,7 @@ import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import com.ecep.contract.ds.company.service.HolidayService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -39,7 +40,7 @@ import com.ecep.contract.ds.contract.model.Contract;
import com.ecep.contract.service.ServiceException;
import com.ecep.contract.service.VoableService;
import com.ecep.contract.util.SpecificationUtils;
import com.ecep.contract.vo.CompanyCustomerFileVo;
import com.ecep.contract.vo.CustomerFileVo;
import com.fasterxml.jackson.databind.JsonNode;
import jakarta.persistence.criteria.Path;
@@ -49,7 +50,7 @@ import jakarta.persistence.criteria.Path;
@CacheConfig(cacheNames = "company-customer-file")
public class CompanyCustomerFileService
implements IEntityService<CompanyCustomerFile>, QueryService<CompanyCustomerFile>,
VoableService<CompanyCustomerFile, CompanyCustomerFileVo> {
VoableService<CompanyCustomerFile, CustomerFileVo> {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerFileService.class);
@Lazy
@Autowired
@@ -183,7 +184,7 @@ public class CompanyCustomerFileService
LocalDate miniContractDate = LocalDate.of(2022, 1, 1);
// 检索全部合同
ContractService contractService = SpringApp.getBean(ContractService.class);
List<Contract> contractList = contractService.findAllByCompanyCustomer(companyCustomer, null, null);
List<Contract> contractList = contractService.findAllByCompanyCustomer(companyCustomer, miniContractDate, LocalDate.now());
if (contractList.isEmpty()) {
holder.error("未发现已登记的合同");
return null;
@@ -210,7 +211,7 @@ public class CompanyCustomerFileService
LocalDate setupDate = firstContract.getSetupDate();
holder.info("依据合同 " + firstContract.getCode() + " 的日期 " + setupDate + " 推算");
return CompanyBasicService.adjustToWorkDay(setupDate.plusDays(-7));
return SpringApp.getBean(HolidayService.class).adjustToWorkDay(setupDate.plusDays(-7));
}
// 检查失效日期起的第一个合同
@@ -233,7 +234,7 @@ public class CompanyCustomerFileService
LocalDate setupDate = firstContract.getSetupDate();
holder.info("匹配失效期 " + nextInValidDate + " 后的第一个合同 " + firstContract.getCode());
holder.info("依据合同 " + firstContract.getCode() + " 的日期 " + setupDate + " 推算");
return CompanyBasicService.adjustToWorkDay(setupDate.plusDays(-7));
return SpringApp.getBean(HolidayService.class).adjustToWorkDay(setupDate.plusDays(-7));
}
public File getEvaluationFormTemplate() {
@@ -271,7 +272,7 @@ public class CompanyCustomerFileService
}
@Override
public void updateByVo(CompanyCustomerFile model, CompanyCustomerFileVo vo) {
public void updateByVo(CompanyCustomerFile model, CustomerFileVo vo) {
if (model == null) {
throw new ServiceException("companyCustomerFile is null");
}
@@ -290,7 +291,7 @@ public class CompanyCustomerFileService
if (vo.getCustomer() == null) {
model.setCustomer(null);
} else {
CompanyCustomerService service = SpringApp.getBean(CompanyCustomerService.class);
CustomerService service = SpringApp.getBean(CustomerService.class);
// 添加实体匹配检查
if (model.getCustomer() == null || !model.getCustomer().getId().equals(vo.getCustomer())) {
// 使用getById方法替代findById

View File

@@ -48,7 +48,7 @@ import com.ecep.contract.util.CompanyUtils;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.util.MyStringUtils;
import com.ecep.contract.util.SpecificationUtils;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CustomerVo;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -58,10 +58,10 @@ import jakarta.persistence.criteria.Path;
@Lazy
@Service
@CacheConfig(cacheNames = "company-customer")
public class CompanyCustomerService extends CompanyBasicService
implements IEntityService<CompanyCustomer>, QueryService<CompanyCustomerVo>,
VoableService<CompanyCustomer, CompanyCustomerVo> {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerService.class);
public class CustomerService extends CompanyBasicService
implements IEntityService<CompanyCustomer>, QueryService<CustomerVo>,
VoableService<CompanyCustomer, CustomerVo> {
private static final Logger logger = LoggerFactory.getLogger(CustomerService.class);
@Lazy
@Autowired
@@ -86,7 +86,7 @@ public class CompanyCustomerService extends CompanyBasicService
}
@Cacheable(key = "#p0")
public CompanyCustomerVo findById(Integer id) {
public CustomerVo findById(Integer id) {
return repository.findById(id).map(CompanyCustomer::toVo).orElse(null);
}
@@ -334,7 +334,7 @@ public class CompanyCustomerService extends CompanyBasicService
}
@Override
public Page<CompanyCustomerVo> findAll(JsonNode paramsNode, Pageable pageable) {
public Page<CustomerVo> findAll(JsonNode paramsNode, Pageable pageable) {
Specification<CompanyCustomer> spec = null;
if (paramsNode.has("searchText")) {
spec = getSpecification(paramsNode.get("searchText").asText());
@@ -399,7 +399,7 @@ public class CompanyCustomerService extends CompanyBasicService
}
@Override
public void updateByVo(CompanyCustomer customer, CompanyCustomerVo vo) {
public void updateByVo(CompanyCustomer customer, CustomerVo vo) {
// 优化关联实体处理逻辑 - 公司关联
if (vo.getCompanyId() == null) {
customer.setCompany(null);

View File

@@ -18,5 +18,7 @@ public interface VendorFileRepository
List<VendorFile> findAllByVendorAndType(Vendor vendor, VendorFileType type);
List<VendorFile> findAllByVendorIdAndType(Integer vendorId, VendorFileType type);
List<VendorFile> findByVendorId(int vendorId);
}

View File

@@ -4,7 +4,6 @@ import java.io.File;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -16,22 +15,28 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import com.ecep.contract.ContractPayWay;
import com.ecep.contract.IEntityService;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.QueryService;
import com.ecep.contract.SpringApp;
import com.ecep.contract.VendorFileType;
import com.ecep.contract.ds.company.service.CompanyBasicService;
import com.ecep.contract.ds.contract.service.ContractService;
import com.ecep.contract.ds.vendor.repository.VendorFileRepository;
import com.ecep.contract.constant.CompanyVendorConstant;
import com.ecep.contract.ds.company.service.CompanyService;
import com.ecep.contract.ds.company.service.HolidayService;
import com.ecep.contract.ds.contract.model.Contract;
import com.ecep.contract.ds.contract.service.ContractService;
import com.ecep.contract.ds.other.service.SysConfService;
import com.ecep.contract.ds.vendor.model.Vendor;
import com.ecep.contract.ds.vendor.model.VendorFile;
import com.ecep.contract.ds.vendor.repository.VendorFileRepository;
import com.ecep.contract.service.ServiceException;
import com.ecep.contract.service.VoableService;
import com.ecep.contract.util.SpecificationUtils;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.VendorFileVo;
import com.ecep.contract.vo.VendorVo;
import com.fasterxml.jackson.databind.JsonNode;
@Lazy
@@ -41,6 +46,15 @@ public class VendorFileService
private static final Logger logger = LoggerFactory.getLogger(VendorFileService.class);
public File getEvaluationFormTemplate() {
SysConfService confService = SpringApp.getBean(SysConfService.class);
String path = confService.getString(CompanyVendorConstant.KEY_EVALUATION_FORM_TEMPLATE);
if (path == null) {
return null;
}
return new File(path);
}
@Autowired
private VendorFileRepository repository;
@@ -85,6 +99,10 @@ public class VendorFileService
return repository.findAllByVendorId(vendor.getId());
}
public List<VendorFileVo> findAllByVendor(VendorVo vendor) {
return repository.findAllByVendorId(vendor.getId()).stream().map(VendorFile::toVo).toList();
}
public void delete(VendorFile file) {
repository.delete(file);
}
@@ -109,6 +127,10 @@ public class VendorFileService
return repository.findAllByVendorAndType(vendor, type);
}
public List<VendorFile> findAllByVendorAndType(VendorVo vendor, VendorFileType type) {
return repository.findAllByVendorIdAndType(vendor.getId(), type);
}
/**
* 验证供应商文件
*
@@ -158,14 +180,17 @@ public class VendorFileService
* @param vendor 供应商
* @return 下一个评价日期
*/
public LocalDate getNextSignDate(Vendor vendor, Consumer<String> state) {
public LocalDate getNextSignDate(VendorVo vendor, MessageHolder holder) {
LocalDate miniContractDate = LocalDate.of(2022, 1, 1);
// 检索全部合同
ContractService contractService = SpringApp.getBean(ContractService.class);
List<Contract> contractList = contractService.findAllByCompanyVendor(vendor, null, null);
CompanyService companyService = SpringApp.getBean(CompanyService.class);
CompanyVo company = companyService.findById(vendor.getCompanyId());
List<Contract> contractList = contractService.findAllByCompany(company, ContractPayWay.PAY, miniContractDate,
LocalDate.now());
if (contractList.isEmpty()) {
state.accept("未发现已登记的合同");
holder.error("未发现已登记的合同");
return null;
}
// 检索评价表
@@ -177,43 +202,43 @@ public class VendorFileService
// 没有有效的评价表的评价日期
if (latestFile == null) {
state.accept("未发现有效的评价表");
holder.warn("未发现有效的评价表");
// 返回最早的合同日期
Contract firstContract = contractList.stream()
.filter(v -> v.getSetupDate() != null && !v.getSetupDate().isBefore(miniContractDate))
.min(Comparator.comparing(Contract::getSetupDate))
.orElse(null);
if (firstContract == null) {
state.accept("最早的合同不存在?");
holder.error("最早的合同不存在?");
return null;
}
LocalDate setupDate = firstContract.getSetupDate();
state.accept("依据合同 " + firstContract.getCode() + " 的日期 " + setupDate + " 推算");
return CompanyBasicService.adjustToWorkDay(setupDate.plusDays(-7));
holder.info("依据合同 " + firstContract.getCode() + " 的日期 " + setupDate + " 推算");
return SpringApp.getBean(HolidayService.class).adjustToWorkDay(setupDate.plusDays(-7));
}
// 检查失效日期起的第一个合同
LocalDate nextInValidDate = latestFile.getSignDate().plusYears(1);
File file = new File(latestFile.getFilePath());
state.accept("依据 " + file.getName() + " 的失效期 " + nextInValidDate + " 检索合同");
holder.info("依据 " + file.getName() + " 的失效期 " + nextInValidDate + " 检索合同");
List<Contract> matchedContracts = contractList.stream()
.filter(v -> v.getSetupDate().isAfter(nextInValidDate)).toList();
// 没有在失效日期后的合同时,使用失效日期
if (matchedContracts.isEmpty()) {
state.accept("未发现失效期 " + nextInValidDate + " 后的合同");
holder.warn("未发现失效期 " + nextInValidDate + " 后的合同");
return null;
}
state.accept("发现匹配合同 " + matchedContracts.size() + "");
holder.info("发现匹配合同 " + matchedContracts.size() + "");
// 按时间取最早一个
Contract firstContract = matchedContracts.stream()
.min(Comparator.comparing(Contract::getSetupDate))
.orElse(null);
LocalDate setupDate = firstContract.getSetupDate();
state.accept("匹配失效期 " + nextInValidDate + " 后的第一个合同 " + firstContract.getCode());
state.accept("依据合同 " + firstContract.getCode() + " 的日期 " + setupDate + " 推算");
return CompanyBasicService.adjustToWorkDay(setupDate.plusDays(-7));
holder.info("匹配失效期 " + nextInValidDate + " 后的第一个合同 " + firstContract.getCode());
holder.info("依据合同 " + firstContract.getCode() + " 的日期 " + setupDate + " 推算");
return SpringApp.getBean(HolidayService.class).adjustToWorkDay(setupDate.plusDays(-7));
}
@Override

View File

@@ -255,7 +255,7 @@ public class VendorService extends CompanyBasicService
List<File> fileList, Consumer<String> status) {
boolean modified = super.fillFileAsEvaluationFile(customerFile, file, fileList, status);
// 当评价表有日期,并且未设审核时
boolean valid = isArchiveFile(customerFile.getFilePath()) && customerFile.getSignDate() != null;
boolean valid = FileUtils.isArchiveFile(customerFile.getFilePath()) && customerFile.getSignDate() != null;
if (valid != customerFile.isValid()) {
customerFile.setValid(valid);
modified = true;
@@ -263,7 +263,7 @@ public class VendorService extends CompanyBasicService
return modified;
}
protected boolean isEvaluationFile(String fileName) {
public boolean isEvaluationFile(String fileName) {
return fileName.contains(CompanyVendorConstant.EVALUATION_FORM_NAME1)
|| fileName.contains(CompanyVendorConstant.EVALUATION_FORM_NAME2)
|| fileName.contains(CompanyVendorConstant.EVALUATION_FORM_NAME3);
@@ -375,14 +375,6 @@ public class VendorService extends CompanyBasicService
return modified;
}
public File getEvaluationFormTemplate() {
String path = confService.getString(CompanyVendorConstant.KEY_EVALUATION_FORM_TEMPLATE);
if (path == null) {
return null;
}
return new File(path);
}
public File getVendorApprovedListTemplate() {
String path = confService.getString(CompanyVendorConstant.KEY_APPROVED_LIST_TEMPLATE);
if (path == null) {

View File

@@ -0,0 +1,489 @@
package com.ecep.contract.ds.vendor.task;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.VendorFileType;
import com.ecep.contract.ds.company.CompanyFileUtils;
import com.ecep.contract.ds.company.service.CompanyService;
import com.ecep.contract.ds.vendor.model.VendorFile;
import com.ecep.contract.ds.vendor.service.VendorFileService;
import com.ecep.contract.ds.vendor.service.VendorService;
import com.ecep.contract.service.tasker.WebSocketServerTasker;
import com.ecep.contract.ui.Tasker;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.VendorFileVo;
import com.ecep.contract.vo.VendorVo;
import com.fasterxml.jackson.databind.JsonNode;
/**
* 供应商文件重建任务
* 1. 从供应商目录下递归遍历所有文件
* 2. 检查数据库中是否存在该文件
* 3. 如果不存在,则添加到数据库中
* 4. 如果存在,则检查文件是否被修改
* 5. 如果被修改,则更新数据库中的文件信息
* 6. 如果文件不存在于供应商目录下,则从数据库中删除该文件
*/
public class VendorReBuildFilesTasker extends Tasker<Object> implements WebSocketServerTasker {
private final Logger logger = LoggerFactory.getLogger(VendorReBuildFilesTasker.class);
private VendorService vendorService;
private VendorFileService vendorFileService;
private VendorVo vendor;
@Override
public void init(JsonNode argsNode) {
int vendorId = argsNode.get(0).asInt();
vendorService = getCachedBean(VendorService.class);
vendorFileService = getCachedBean(VendorFileService.class);
vendor = vendorService.findById(vendorId);
}
@Override
protected Object execute(MessageHolder holder) throws Exception {
CompanyVo company = getCachedBean(CompanyService.class).findById(vendor.getCompanyId());
holder.info("开始重建供应商[" + company.getName() + "]的文件信息...");
updateProgress(0, 100);
holder.info("正在读取数据库中的文件记录...");
List<VendorFileVo> dbFiles = vendorFileService.findAllByVendor(vendor);
holder.info("共找到 " + dbFiles.size() + " 条数据库记录,正在进行数据清理...");
Map<String, VendorFileVo> map = new HashMap<>();
boolean modified = fetchDbFiles(dbFiles, map, holder);
updateProgress(30, 100);
// 供应商目录下,准备用于移动到公司目录
List<File> needMoveToCompanyPath = new ArrayList<>();
// 有修改和新导入的文件
List<VendorFileVo> retrieveFiles = new ArrayList<>();
holder.info("正在扫描供应商目录[" + vendor.getPath() + "]中的文件...");
fetchFiles(vendor.getPath(), needMoveToCompanyPath, retrieveFiles, map, holder);
updateProgress(60, 100);
// 移动文件到公司目录下 to company path
if (!needMoveToCompanyPath.isEmpty()) {
holder.info("发现 " + needMoveToCompanyPath.size() + " 个文件需要移动到公司目录,正在处理...");
moveFileToCompany(needMoveToCompanyPath, holder);
holder.info("文件移动完成");
}
holder.info("导入 " + retrieveFiles.size() + " 个文件");
if (!retrieveFiles.isEmpty()) {
holder.info("正在更新数据库记录...");
int totalFiles = retrieveFiles.size();
int processed = 0;
// update db
for (VendorFileVo v0 : retrieveFiles) {
v0.setVendorId(vendor.getId());
save(v0);
processed++;
updateProgress(60 + (processed * 40) / totalFiles, 100);
}
modified = true;
holder.info("数据库更新完成");
}
updateProperty("modified", modified);
updateProgress(100, 100);
holder.info("文件重建任务完成");
return null;
}
protected void moveFileToCompany(List<File> needMoveToCompanyPath, MessageHolder holder) {
CompanyService companyService = getCachedBean(CompanyService.class);
CompanyVo company = companyService.findById(vendor.getCompanyId());
String companyPath = company.getPath();
if (!StringUtils.hasText(companyPath)) {
holder.warn("公司路径未设置,无法移动文件");
return;
}
int movedCount = 0;
int totalCount = needMoveToCompanyPath.size();
for (File file : needMoveToCompanyPath) {
File dest = new File(companyPath, file.getName());
if (file.renameTo(dest)) {
holder.info("移动文件: " + file.getAbsolutePath() + " -> " + dest.getAbsolutePath());
movedCount++;
} else {
if (dest.exists()) {
if (file.delete()) {
holder.info("删除重复文件: " + file.getAbsolutePath());
} else {
holder.warn("无法删除重复文件: " + file.getAbsolutePath());
}
} else {
holder.warn("无法移动文件: " + file.getAbsolutePath());
}
}
}
holder.info("文件移动完成: 共 " + totalCount + " 个文件,成功移动 " + movedCount + "");
}
/**
* 从数据库中获取所有文件信息
*
* @param dbFiles
* @param map
* @param holder
* @return
*/
protected boolean fetchDbFiles(List<VendorFileVo> dbFiles, Map<String, VendorFileVo> map, MessageHolder holder) {
boolean modified = false;
List<File> editFiles = new ArrayList<>();
int deletedCount = 0;
int updatedCount = 0;
int totalCount = dbFiles.size();
// 排除掉数据库中重复的
for (int i = 0; i < dbFiles.size(); i++) {
VendorFileVo dbFile = dbFiles.get(i);
String filePath = dbFile.getFilePath();
// 更新进度
if (i % 10 == 0 || i == totalCount - 1) {
updateProgress(10 + (i * 20) / totalCount, 100);
}
// 没有文件信息,无效记录,删除
if (!StringUtils.hasText(filePath)) {
deleteFile(dbFile);
deletedCount++;
continue;
}
// 文件不存在或者隐藏文件,删除记录
File file = new File(filePath);
if (!file.exists() || FileUtils.isHiddenFile(file)) {
deleteFile(dbFile);
deletedCount++;
continue;
}
// old 是冲突的按dbFiles顺序旧的list前面的
VendorFileVo old = map.put(filePath, dbFile);
// 目录有重复删除
if (old != null) {
deleteFile(old);
deletedCount++;
}
String editFilePath = dbFile.getEditFilePath();
if (!Objects.equals(filePath, editFilePath)) {
// 没有文件信息,无效记录,删除
if (StringUtils.hasText(editFilePath)) {
File editFile = new File(editFilePath);
if (editFile.exists()) {
editFiles.add(editFile);
} else {
dbFile.setEditFilePath("");
updatedCount++;
}
}
}
// 类型未设置,补充类型
if (dbFile.getType() == null) {
if (fillFileAsDefaultType(dbFile, file, holder)) {
modified = true;
updatedCount++;
}
}
}
// 处理编辑文件
int editDeletedCount = 0;
for (File editFile : editFiles) {
String editFilePath = editFile.getAbsolutePath();
VendorFileVo dup = map.remove(editFilePath);
// 目录有重复删除
if (dup != null) {
deleteFile(dup);
editDeletedCount++;
}
}
holder.info("数据库清理完成: 删除 " + (deletedCount + editDeletedCount) + " 条无效记录,更新 " + updatedCount + " 条记录");
return modified;
}
/**
* 遍历扫描 path 目录下的文件, 并根据文件类型,填充到 retrieveFiles 中
*
* @param path
* @param needMoveToCompanyPath 符合 CompanyFileUtils.isCompanyFile(file)
* 规则的文件,会加到此集合中
* @param retrieveFiles
* @param map
* @param status
* @param <T>
* @param <F>
*/
protected void fetchFiles(
String path,
List<File> needMoveToCompanyPath,
List<VendorFileVo> retrieveFiles,
Map<String, VendorFileVo> map,
MessageHolder holder) {
if (!StringUtils.hasText(path)) {
return;
}
File dir = new File(path);
if (!dir.exists()) {
return;
}
File[] files = dir.listFiles();
if (files == null) {
return;
}
List<File> step1 = new ArrayList<>();
for (File file : files) {
// 只处理文件
if (!file.isFile() || FileUtils.isHiddenFile(file)) {
continue;
}
if (CompanyFileUtils.isCompanyFile(file)) {
needMoveToCompanyPath.add(file);
continue;
}
// 先把所有文件加到列表中
step1.add(file);
}
if (!step1.isEmpty()) {
// 第一步,处理已经存在的
for (File file : new ArrayList<>(step1)) {
String filePath = file.getAbsolutePath();
if (map.containsKey(filePath)) {
// 已记录
VendorFileVo customerFile = map.get(filePath);
if (fillFile(customerFile, file, step1, holder)) {
retrieveFiles.add(customerFile);
}
step1.remove(file);
}
}
// 第二步骤,再处理
while (!step1.isEmpty()) {
File file = step1.removeLast();
VendorFileVo vendorFile = new VendorFileVo();
vendorFile.setType(VendorFileType.General);
vendorFile.setFilePath(file.getAbsolutePath());
fillFile(vendorFile, file, step1, holder);
if (vendorFile != null) {
retrieveFiles.add(vendorFile);
}
}
}
}
protected boolean fillFile(VendorFileVo customerFile, File file, List<File> fileList,
MessageHolder holder) {
String fileName = file.getName();
boolean modified = CompanyFileUtils.fillApplyDateAbsent(file, customerFile, VendorFileVo::getSignDate,
VendorFileVo::setSignDate);
// 评估表
if (getCachedBean(VendorService.class).isEvaluationFile(fileName)) {
if (fillFileAsEvaluationFile(customerFile, file, fileList, holder)) {
modified = true;
}
} else {
if (!Objects.equals(file.getAbsolutePath(), customerFile.getFilePath())) {
customerFile.setFilePath(file.getAbsolutePath());
modified = true;
}
}
return modified;
}
/**
* 以评价表单模板。填充文件信息
*
* @param customerFile 文件对象
* @param file 相关文件
* @param fileList 待处理文件列表
* @param status 状态输出
* @param <T> 类型类
* @param <F> 文件类
* @return true文件对象有修改否则返回false
*/
protected boolean fillFileAsEvaluationFile(VendorFileVo customerFile, File file,
List<File> fileList, MessageHolder holder) {
boolean modified = setFileTypeAsEvaluationForm(customerFile);
String fileName = file.getName();
// 文件全路径
String fileAbsolutePath = file.getAbsolutePath();
if (FileUtils.isEditableFile(fileName)) {
// 是可编辑文件时
if (!Objects.equals(fileAbsolutePath, customerFile.getEditFilePath())) {
customerFile.setEditFilePath(fileAbsolutePath);
modified = true;
}
if (useAsEditableFile(customerFile, file, fileList, holder)) {
modified = true;
}
} else if (FileUtils.isArchiveFile(fileName)) {
// 存档文件时
if (!Objects.equals(fileAbsolutePath, customerFile.getFilePath())) {
customerFile.setFilePath(fileAbsolutePath);
modified = true;
}
if (useAsArchiveFile(customerFile, file, fileList, holder)) {
modified = true;
}
} else {
customerFile.setFilePath(file.getAbsolutePath());
}
return modified;
}
protected boolean setFileTypeAsEvaluationForm(VendorFileVo file) {
VendorFileType type = file.getType();
if (type != VendorFileType.EvaluationForm) {
file.setType(VendorFileType.EvaluationForm);
return true;
}
return false;
}
private boolean useAsEditableFile(VendorFileVo customerFile, File file, List<File> fileList,
MessageHolder holder) {
if (fileList == null) {
return false;
}
// 检查存档文件
if (StringUtils.hasText(customerFile.getFilePath())) {
// 移除 存档文件
File archiveFile = new File(customerFile.getFilePath());
fileList.remove(archiveFile);
return false;
}
// 未关联存档文件,去找 fileList 查
if (fileList.isEmpty()) {
// 文件全路径
String fileAbsolutePath = file.getAbsolutePath();
// 当没有其他文件时,与 EditFile 相同
if (!Objects.equals(fileAbsolutePath, customerFile.getFilePath())) {
customerFile.setFilePath(fileAbsolutePath);
return true;
}
return false;
}
File archiveFile = null;
// 文件名
String fileName = file.getName();
// 文件名,不含后缀
String name = StringUtils.stripFilenameExtension(fileName);
for (File f : fileList) {
// 查找存档文件
if (f.getName().startsWith(name) && FileUtils.isArchiveFile(f.getName())) {
archiveFile = f;
break;
}
}
// 没有匹配到文件
if (archiveFile == null) {
return false;
}
if (fileList.remove(archiveFile)) {
customerFile.setFilePath(archiveFile.getAbsolutePath());
return true;
}
return false;
}
private boolean useAsArchiveFile(VendorFileVo customerFile, File file, List<File> fileList,
MessageHolder holder) {
if (fileList == null) {
return false;
}
// 未关联存档文件,去找 fileList 查
if (fileList.isEmpty()) {
return false;
}
// 检查可编辑文件
if (StringUtils.hasText(customerFile.getEditFilePath())) {
// 移除 可编辑文件
File editFile = new File(customerFile.getEditFilePath());
fileList.remove(editFile);
return false;
}
File editFile = null;
// 文件名
String fileName = file.getName();
// 文件名,不含后缀
String name = StringUtils.stripFilenameExtension(fileName);
for (File f : fileList) {
// 查找存档文件
if (f.getName().startsWith(name) && FileUtils.isEditableFile(f.getName())) {
editFile = f;
break;
}
}
// 没有匹配到文件
if (editFile == null) {
return false;
}
if (fileList.remove(editFile)) {
String editFilePath = editFile.getAbsolutePath();
if (!Objects.equals(editFilePath, customerFile.getEditFilePath())) {
customerFile.setEditFilePath(editFilePath);
return true;
}
}
return false;
}
protected boolean fillFileAsDefaultType(VendorFileVo dbFile, File file,
MessageHolder holder) {
dbFile.setType(VendorFileType.General);
fillFile(dbFile, file, null, holder);
save(dbFile);
return true;
}
private void save(VendorFileVo dbFile) {
VendorFile v1 = vendorFileService.getById(dbFile.getId());
vendorFileService.updateByVo(v1, dbFile);
vendorFileService.save(v1);
}
private void deleteFile(VendorFileVo dbFile) {
VendorFile v1 = vendorFileService.getById(dbFile.getId());
vendorFileService.delete(v1);
}
}

View File

@@ -1,6 +1,7 @@
package com.ecep.contract.service.tasker;
import static com.ecep.contract.util.ExcelUtils.setCellValue;
import static com.ecep.contract.util.ExcelUtils.getCellValue;
import java.io.File;
import java.io.FileInputStream;
@@ -12,6 +13,7 @@ import java.io.OutputStream;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
@@ -26,7 +28,7 @@ import com.ecep.contract.SpringApp;
import com.ecep.contract.cloud.tyc.CloudTycService;
import com.ecep.contract.ds.customer.service.CompanyCustomerEvaluationFormFileService;
import com.ecep.contract.ds.customer.service.CompanyCustomerFileService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.ds.other.model.CloudTyc;
import com.ecep.contract.ds.company.model.Company;
import com.ecep.contract.ds.customer.model.CompanyCustomer;
@@ -34,6 +36,7 @@ import com.ecep.contract.ds.customer.model.CompanyCustomerEvaluationFormFile;
import com.ecep.contract.ds.customer.model.CompanyCustomerFile;
import com.ecep.contract.ui.Tasker;
import com.ecep.contract.util.CompanyUtils;
import com.ecep.contract.util.ExcelUtils;
import com.fasterxml.jackson.databind.JsonNode;
public class CompanyCustomerEvaluationFormUpdateTask extends Tasker<Object> implements WebSocketServerTasker {
@@ -42,7 +45,7 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Tasker<Object> impl
@Override
public void init(JsonNode argsNode) {
int customerId = argsNode.get(0).asInt();
customer = getCachedBean(CompanyCustomerService.class).getById(customerId);
customer = getCachedBean(CustomerService.class).getById(customerId);
}
CompanyCustomerFileService getCompanyCustomerFileService() {
@@ -131,36 +134,100 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Tasker<Object> impl
}
private void updateSheet(Company company, Sheet sheet, MessageHolder holder) {
setCellValue(sheet, "B3", "客户编号:" + CompanyUtils.formatCompanyVendorId(customer.getId()));
setCellValue(sheet, "B4", "客户名称:" + company.getName());
String customerId = "客户编号:" + CompanyUtils.formatCompanyVendorId(customer.getId());
String currentCustomerId = ExcelUtils.getCellValue(sheet, "B3");
if (!Objects.equals(customerId, currentCustomerId)) {
setCellValue(sheet, "B3", customerId);
holder.info("更新客户编号为:" + CompanyUtils.formatCompanyVendorId(customer.getId()));
}
String customerName = "客户名称:" + company.getName();
String currentCustomerName = ExcelUtils.getCellValue(sheet, "B4");
if (!Objects.equals(customerName, currentCustomerName)) {
setCellValue(sheet, "B4", customerName);
holder.info("更新客户名称为:" + company.getName());
}
LocalDate suggestDate = getCompanyCustomerFileService().getNextSignDate(customer, holder);
if (suggestDate == null) {
suggestDate = LocalDate.now();
holder.debug("未获取到推荐评定日期,使用当前日期:" + suggestDate);
} else {
holder.debug("获取到推荐评定日期:" + suggestDate);
}
setCellValue(sheet, "H3", "评定时间:" + suggestDate);
String evalDate = "评定时间:" + suggestDate;
String currentEvalDate = ExcelUtils.getCellValue(sheet, "H3");
if (!Objects.equals(evalDate, currentEvalDate)) {
setCellValue(sheet, "H3", evalDate);
holder.info("更新评定时间为:" + suggestDate);
}
setCellValue(sheet, "H4", "统一社会信用代码:");
setCellValue(sheet, "H5", company.getUniscid());
if (!Objects.equals(company.getUniscid(), ExcelUtils.getCellValue(sheet, "H5"))) {
setCellValue(sheet, "H5", company.getUniscid());
holder.info("更新统一社会信用代码为:" + company.getUniscid());
}
// 注册所属地
setCellValue(sheet, "B5", "注册所属地:" + company.getDistrict());
String district = "注册所属地:" + company.getDistrict();
if (!Objects.equals(district, ExcelUtils.getCellValue(sheet, "B5"))) {
setCellValue(sheet, "B5", district);
holder.info("更新注册所属地为:" + company.getDistrict());
}
// 经营状态
setCellValue(sheet, "D6", "经营状态:" + company.getEntStatus());
String entStatus = "经营状态:" + company.getEntStatus();
if (!Objects.equals(entStatus, ExcelUtils.getCellValue(sheet, "D6"))) {
setCellValue(sheet, "D6", entStatus);
holder.info("更新经营状态为:" + company.getEntStatus());
}
// 成立日期
setCellValue(sheet, "H6", "成立日期:" + company.getSetupDate());
String setupDate = "成立日期:" + company.getSetupDate();
if (!Objects.equals(setupDate, ExcelUtils.getCellValue(sheet, "H6"))) {
setCellValue(sheet, "H6", setupDate);
holder.info("更新成立日期为:" + company.getSetupDate());
}
// 所属行业
setCellValue(sheet, "D7", "所属行业:" + company.getIndustry());
setCellValue(sheet, "D8",
"注册资金:" + company.getRegisteredCapital() + " " + company.getRegisteredCapitalCurrency());
String industry = "所属行业:" + company.getIndustry();
if (!Objects.equals(industry, ExcelUtils.getCellValue(sheet, "D7"))) {
setCellValue(sheet, "D7", industry);
holder.info("更新所属行业为:" + company.getIndustry());
}
String registeredCapital = "注册资金:" + company.getRegisteredCapital() + " " + company.getRegisteredCapitalCurrency();
if (!Objects.equals(registeredCapital, ExcelUtils.getCellValue(sheet, "D8"))) {
setCellValue(sheet, "D8", registeredCapital);
holder.info("更新注册资金为:" + registeredCapital);
}
// 企业类型
setCellValue(sheet, "H10", "企业类型:" + company.getEntType());
String entType = "企业类型:" + company.getEntType();
if (!Objects.equals(entType, ExcelUtils.getCellValue(sheet, "H10"))) {
setCellValue(sheet, "H10", entType);
holder.info("更新企业类型为:" + company.getEntType());
}
// 天眼评分
CloudTycService cloudTycService = SpringApp.getBean(CloudTycService.class);
CloudTyc cloudTyc = cloudTycService.getOrCreateCloudTyc(company);
setCellValue(sheet, "D10", "天眼评分:" + (cloudTyc.getScore() > 0 ? cloudTyc.getScore() : ""));
String tycScore = "天眼评分:" + (cloudTyc.getScore() > 0 ? cloudTyc.getScore() : "");
if (!Objects.equals(tycScore, ExcelUtils.getCellValue(sheet, "D10"))) {
setCellValue(sheet, "D10", tycScore);
if (cloudTyc.getScore() > 0) {
holder.info("更新天眼评分为:" + cloudTyc.getScore());
} else {
holder.debug("天眼评分未设置或为0");
}
}
// 检索评估表
holder.debug("开始检索客户评价表文件");
List<CompanyCustomerFile> customerFiles = getCompanyCustomerFileService().findAllByCustomerAndType(customer,
CustomerFileType.EvaluationForm);
holder.debug("共检索到 " + customerFiles.size() + " 个客户评价表文件");
List<CompanyCustomerEvaluationFormFile> filteredList = customerFiles.stream().filter(file -> {
return file.getSignDate() != null && file.isValid();
@@ -168,29 +235,45 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Tasker<Object> impl
.sorted(Comparator.comparing(CompanyCustomerFile::getSignDate))
.map(getCompanyCustomerEvaluationFormFileService()::findByCustomerFile)
.toList();
holder.debug("有效评价表数量:" + filteredList.size());
if (filteredList.isEmpty()) {
setCellValue(sheet, "C40", "首次评价");
if (!Objects.equals("首次评价", ExcelUtils.getCellValue(sheet, "C40"))) {
setCellValue(sheet, "C40", "首次评价");
holder.info("设置客户为首次评价状态");
}
try {
sheet.addMergedRegion(CellRangeAddress.valueOf("C40:K40"));
} catch (Exception ignored) {
holder.debug("合并单元格C40:K40失败可能已合并");
}
} else {
holder.info("客户有 " + filteredList.size() + " 条评价表");
setCellValue(sheet, "C40", "评价日期");
try {
sheet.addMergedRegion(CellRangeAddress.valueOf("C40:D40"));
} catch (Exception ignored) {
holder.info("客户有 " + filteredList.size() + "有效评价表记录");
if (!Objects.equals("评价日期", ExcelUtils.getCellValue(sheet, "C40"))) {
setCellValue(sheet, "C40", "评价日期");
try {
sheet.addMergedRegion(CellRangeAddress.valueOf("C40:D40"));
} catch (Exception ignored) {
holder.debug("合并单元格C40:D40失败可能已合并");
}
}
if (!Objects.equals("经济指标", ExcelUtils.getCellValue(sheet, "E40"))) {
setCellValue(sheet, "E40", "经济指标");
}
if (!Objects.equals("综合指标", ExcelUtils.getCellValue(sheet, "F40"))) {
setCellValue(sheet, "F40", "综合指标");
}
if (!Objects.equals("资信等级", ExcelUtils.getCellValue(sheet, "G40"))) {
setCellValue(sheet, "G40", "资信等级");
}
setCellValue(sheet, "E40", "经济指标");
setCellValue(sheet, "F40", "综合指标");
setCellValue(sheet, "G40", "资信等级");
String[] CreditLevelTitles = new String[] { "-", "差★", " 一般★★", " 较好★★★", " 好★★★★", " " };
int baseRow = 40;
for (CompanyCustomerEvaluationFormFile form : filteredList) {
baseRow++;
CompanyCustomerFile customerFile = form.getCustomerFile();
if (!Hibernate.isInitialized(customerFile)) {
customerFile = getCompanyCustomerFileService().findById(customerFile.getId());
holder.debug("延迟加载评价表文件信息文件ID" + customerFile.getId());
}
setCellValue(sheet, baseRow, 2, String.valueOf(customerFile.getSignDate()));
setCellValue(sheet, baseRow, 4, form.getCatalog());
@@ -203,9 +286,10 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Tasker<Object> impl
try {
sheet.addMergedRegion(new CellRangeAddress(baseRow, baseRow, 2, 3));
} catch (Exception ignored) {
holder.debug("合并单元格第" + baseRow + "行的2-3列失败可能已合并");
}
baseRow++;
}
holder.info("已成功更新所有评价表记录到Excel中");
}
}
}

View File

@@ -8,7 +8,7 @@ import com.ecep.contract.CustomerFileType;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.ds.contract.service.ContractService;
import com.ecep.contract.ds.customer.service.CompanyCustomerFileService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.ds.customer.model.CompanyCustomer;
import com.ecep.contract.ds.customer.model.CompanyCustomerFile;
import com.ecep.contract.ds.contract.model.Contract;
@@ -22,15 +22,15 @@ public class CompanyCustomerNextSignDateTask extends Tasker<Object> implements W
@Override
public void init(JsonNode argsNode) {
int customerId = argsNode.get(0).asInt();
customer = getCachedBean(CompanyCustomerService.class).getById(customerId);
customer = getCachedBean(CustomerService.class).getById(customerId);
}
CompanyCustomerFileService getCompanyCustomerFileService() {
return getCachedBean(CompanyCustomerFileService.class);
}
CompanyCustomerService getCompanyCustomerService() {
return getCachedBean(CompanyCustomerService.class);
CustomerService getCompanyCustomerService() {
return getCachedBean(CustomerService.class);
}
ContractService getContractService() {

View File

@@ -5,7 +5,7 @@ import org.springframework.util.StringUtils;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.ds.company.service.CompanyService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.ds.company.model.Company;
import com.ecep.contract.ds.customer.model.CompanyCustomer;
import com.ecep.contract.ui.Tasker;
@@ -19,8 +19,8 @@ public class CompanyCustomerRebuildFilesTasker extends Tasker<Object> implements
private CompanyCustomer customer;
CompanyCustomerService getCompanyCustomerService() {
return getCachedBean(CompanyCustomerService.class);
CustomerService getCompanyCustomerService() {
return getCachedBean(CustomerService.class);
}
@Override

View File

@@ -1,6 +1,7 @@
package com.ecep.contract.service.tasker;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.cloud.rk.CloudRkService;
import com.ecep.contract.cloud.rk.ctx.CloudRkCtx;
import com.ecep.contract.constant.CloudServiceConstant;
@@ -34,16 +35,18 @@ public class CompanyRkUpdateTasker extends Tasker<Object> implements WebSocketSe
@Override
protected Object execute(MessageHolder holder) throws Exception {
holder.debug("1. 从 " + CloudServiceConstant.RK_NAME + " 更新...");
try {
cloudRkService = getCachedBean(CloudRkService.class);
} catch (BeansException e) {
throw new RuntimeException("服务未启用");
throw new RuntimeException("服务未启用,请联系管理员");
}
CloudRk cloudRk = cloudRkService.getOrCreateCloudRk(company);
if (cloudRk == null) {
throw new RuntimeException("无法创建或获取 CloudRk 对象");
}
if (cloudRk.getLatestUpdate() != null) {
holder.info("上次更新:" + MyDateTimeUtils.format(cloudRk.getLatestUpdate()));
}
try {
CloudRkCtx cloudRkCtx = new CloudRkCtx();

View File

@@ -0,0 +1,282 @@
package com.ecep.contract.service.tasker;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.VendorFileType;
import com.ecep.contract.ds.company.service.CompanyContactService;
import com.ecep.contract.ds.company.service.CompanyService;
import com.ecep.contract.ds.vendor.model.Vendor;
import com.ecep.contract.ds.vendor.model.VendorFile;
import com.ecep.contract.ds.vendor.service.VendorFileService;
import com.ecep.contract.ds.vendor.service.VendorService;
import com.ecep.contract.ui.Tasker;
import com.ecep.contract.util.ExcelUtils;
import com.ecep.contract.vo.CompanyContactVo;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.VendorVo;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Objects;
import static com.ecep.contract.util.ExcelUtils.getCellValue;
import static com.ecep.contract.util.ExcelUtils.setCellValue;
/**
* 更新供应商评价表
*/
@Component
public class CompanyVendorEvaluationFormUpdateTask extends Tasker<Object> implements WebSocketServerTasker {
private VendorVo vendor;
private CompanyVo company;
private File template;
@Override
public void init(JsonNode argsNode) {
int vendorId = argsNode.get(0).asInt();
vendor = getVendorService().findById(vendorId);
}
private VendorService getVendorService() {
return getCachedBean(VendorService.class);
}
VendorFileService getVendorFileService() {
return getCachedBean(VendorFileService.class);
}
@Override
protected Object execute(MessageHolder holder) throws Exception {
if (vendor == null) {
holder.error("未找到供应商信息");
return null;
}
if (!StringUtils.hasText(vendor.getPath())) {
holder.error("供应商目录未设置,请先设置供应商目录");
return null;
}
updateEvaluationForm(holder);
return null;
}
public void updateEvaluationForm(MessageHolder holder) {
company = getCachedBean(CompanyService.class).findById(vendor.getCompanyId());
template = getVendorFileService().getEvaluationFormTemplate();
if (template == null) {
holder.error("评价表模板文件未设置,请先设置评价表模板文件");
return;
}
if (!template.exists()) {
holder.error("评价表模板文件 " + template.getAbsolutePath() + " 不存在,请检查");
return;
}
updateProgress(1, 10);
File dir = new File(vendor.getPath());
String template_file_name = template.getName();
File destFile = new File(dir, template_file_name);
if (destFile.exists()) {
holder.info("表单文件已经存在," + destFile.getName());
try (
InputStream inp = new FileInputStream(destFile);
Workbook wb = WorkbookFactory.create(inp)) {
updateEvaluationForm(wb, destFile, holder);
holder.info("评价表已更新");
} catch (Exception e) {
holder.error(e.getMessage());
}
} else {
holder.info("根据模板 " + template_file_name + " 创建表单 " + destFile.getName());
try (
InputStream inp = new FileInputStream(template);
Workbook wb = WorkbookFactory.create(inp)) {
updateEvaluationForm(wb, destFile, holder);
holder.info("评价表已创建");
// 创建 VendorFile 对象
VendorFile vendorFile = new VendorFile();
Vendor vendorEntity = getCachedBean(VendorService.class).getById(vendor.getId());
vendorFile.setVendor(vendorEntity);
vendorFile.setFilePath(destFile.getAbsolutePath());
vendorFile.setType(VendorFileType.EvaluationForm);
vendorFile.setSignDate(LocalDate.now());
vendorFile.setValid(false);
getVendorFileService().save(vendorFile);
} catch (Exception e) {
holder.error(e.getMessage());
}
}
updateProgress(10, 10);
}
/**
* 更新供应商评估表,依据模板创建,如果已经存在生成的文件,则更新评估表
*
* @param wb work book
* @param destFile 目标文件
*/
public void updateEvaluationForm(Workbook wb, File destFile, MessageHolder holder) throws IOException {
updateProgress(2, 10);
Sheet sheet = wb.getSheetAt(0);
holder.info("更新 " + sheet.getSheetName() + " Sheet");
updateSheet(sheet, holder.sub(" - "));
updateProgress(8, 10);
// 输出到文件
try (OutputStream fileOut = new FileOutputStream(destFile)) {
wb.write(fileOut);
} catch (FileNotFoundException e) {
holder.error("写评估表时发生文件错误,请检查评估表是否被打开中:" + e.getMessage());
}
}
private void updateSheet(Sheet sheet, MessageHolder holder) {
String vendor_id = "" + vendor.getId();
if (!Objects.equals(vendor_id, getCellValue(sheet, "G1"))) {
setCellValue(sheet, "G1", vendor_id);
holder.info("供应商编号更新为:" + vendor_id);
}
String companyName = company.getName();
if (!Objects.equals(companyName, getCellValue(sheet, "B2"))) {
setCellValue(sheet, "B2", companyName);
holder.info("供应商名称更新为:" + companyName);
}
String address = null;
// 联系人
CompanyContactVo contact = null;
if (vendor.getContactId() != null) {
contact = getCompanyContactService().findById(vendor.getContactId());
if (contact != null) {
holder.debug("供应商指定联系人:" + contact.getName());
}
}
if (contact == null) {
contact = getCompanyContactService().findFirstByCompany(company);
if (contact != null) {
holder.debug("从公司联系人列表中获取联系人:" + contact.getName());
}
}
if (contact != null) {
String contactName = contact.getName();
if (!Objects.equals(contactName, getCellValue(sheet, "F2"))) {
setCellValue(sheet, "F2", contactName);
holder.info("联系人姓名更新为:" + contactName);
}
String contactPhone = contact.getPhone();
if (StringUtils.hasText(contactPhone)) {
if (!Objects.equals(contactPhone, getCellValue(sheet, "F3"))) {
setCellValue(sheet, "F3", contactPhone);
holder.info("联系人电话更新为:" + contactPhone);
}
}
if (StringUtils.hasText(contact.getAddress())) {
address = contact.getAddress();
}
}
if (!StringUtils.hasText(address)) {
address = company.getAddress();
if (StringUtils.hasText(address)) {
holder.debug("使用公司地址:" + address);
}
}
if (!StringUtils.hasText(address)) {
address = company.getRegAddr();
if (StringUtils.hasText(address)) {
holder.debug("使用公司注册地址:" + address);
}
}
if (StringUtils.hasText(address)) {
if (!Objects.equals(address, getCellValue(sheet, "B3"))) {
setCellValue(sheet, "B3", address);
holder.info("更新供应商地址为:" + address);
}
} else {
holder.warn("没有获取到供应商地址,请检查供应商信息");
}
String companyUniscid = company.getUniscid();
if (!Objects.equals(companyUniscid, getCellValue(sheet, "B8"))) {
setCellValue(sheet, "B8", companyUniscid);
holder.info("更新供应商统一社会信用代码为:" + companyUniscid);
}
String regCap = company.getRegisteredCapital() + " " + company.getRegisteredCapitalCurrency();
if (!Objects.equals(regCap, getCellValue(sheet, "E8"))) {
setCellValue(sheet, "E8", regCap);
holder.info("更新供应商注册资金为:" + regCap);
}
setCellValue(sheet, "H8", company.getOperationPeriodBegin());
if (company.getOperationPeriodEnd() == null) {
if (company.getOperationPeriodBegin() != null) {
setCellValue(sheet, "H9", "无固定期限");
}
} else {
setCellValue(sheet, "H9", company.getOperationPeriodEnd());
}
String vendorPurchase = vendor.getPurchase();
if (!Objects.equals(vendorPurchase, getCellValue(sheet, "C4"))) {
setCellValue(sheet, "C4", vendorPurchase);
holder.info("更新供应商采购内容为:" + vendorPurchase);
}
Cell a6 = ExcelUtils.getCell(sheet, "A6");
if (a6 != null) {
if (!Objects.equals(a6.getStringCellValue(), vendor.getDescription())) {
a6.setCellValue(vendor.getDescription());
holder.info("更新供应商描述为:" + StringUtils.truncate(a6.getStringCellValue(), 30));
}
if (a6.getCellStyle().getAlignment() != HorizontalAlignment.LEFT) {
a6.getCellStyle().setAlignment(HorizontalAlignment.LEFT);
holder.info("更新供应商描述对齐方式为左对齐");
}
}
// 第一个评价日期
Cell g16 = ExcelUtils.getCell(sheet, "G16");
if (g16 == null) {
holder.error("模板异常, 第一个评价日期单元格(G16)未找到!");
} else {
CellType cellType = g16.getCellType();
// 未设置, 尝试更新
if (cellType == CellType.BLANK || cellType == CellType.NUMERIC) {
holder.debug("推算下一个评价日期...");
LocalDate nextSignDate = getVendorFileService().getNextSignDate(vendor, holder.sub(" -| "));
// 当没有推荐日期时,说明不需要评价,更新为空
if (nextSignDate == null) {
g16.setBlank();
holder.info("!未推算出下一个评价日期,单元格设空!");
} else {
holder.debug("推算出下一个评价日期:" + nextSignDate);
LocalDateTime value = g16.getLocalDateTimeCellValue();
if (value == null) {
g16.setCellValue(nextSignDate);
holder.info("评价日期更新为:" + nextSignDate);
} else {
if (!Objects.equals(value.toLocalDate(), nextSignDate)) {
g16.setCellValue(nextSignDate);
holder.info("评价日期更新为:" + nextSignDate);
}
}
}
} else {
holder.warn("第一个评价日期所在单元格 " + g16.getAddress().formatAsR1C1String() + " 的单元格类型未知:" + cellType);
}
}
}
private CompanyContactService getCompanyContactService() {
return getCachedBean(CompanyContactService.class);
}
}

View File

@@ -2,7 +2,7 @@ package com.ecep.contract.service.tasker;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.ds.customer.service.CompanyCustomerFileService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.ds.company.model.Company;
import com.ecep.contract.ds.customer.model.CompanyCustomer;
import com.ecep.contract.ds.customer.model.CompanyCustomerFile;
@@ -104,7 +104,7 @@ public class CustomerFileMoveTasker extends Tasker<Object> implements WebSocketS
return getCachedBean(CompanyCustomerFileService.class);
}
private CompanyCustomerService getCompanyCustomerService() {
return getCachedBean(CompanyCustomerService.class);
private CustomerService getCompanyCustomerService() {
return getCachedBean(CustomerService.class);
}
}

View File

@@ -0,0 +1,121 @@
package com.ecep.contract.service.tasker;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.VendorFileType;
import com.ecep.contract.ds.contract.model.Contract;
import com.ecep.contract.ds.contract.service.ContractService;
import com.ecep.contract.ds.vendor.model.Vendor;
import com.ecep.contract.ds.vendor.model.VendorFile;
import com.ecep.contract.ds.vendor.service.VendorFileService;
import com.ecep.contract.ds.vendor.service.VendorService;
import com.ecep.contract.ui.Tasker;
import com.fasterxml.jackson.databind.JsonNode;
public class VendorNextSignDateTask extends Tasker<Object> implements WebSocketServerTasker {
private Vendor vendor;
@Override
public void init(JsonNode argsNode) {
int vendorId = argsNode.get(0).asInt();
vendor = getCachedBean(VendorService.class).getById(vendorId);
}
VendorFileService getVendorFileService() {
return getCachedBean(VendorFileService.class);
}
VendorService getVendorService() {
return getCachedBean(VendorService.class);
}
ContractService getContractService() {
return getCachedBean(ContractService.class);
}
@Override
protected Object execute(MessageHolder holder) throws Exception {
if (vendor == null) {
holder.error("未找到供应商信息");
return null;
}
holder.info("开始计算供应商下一个评价日期");
LocalDate nextSignDate = calculateNextSignDate(holder);
if (nextSignDate != null) {
holder.info("下一个评价日期:" + nextSignDate);
} else {
holder.warn("无法计算下一个评价日期");
}
return nextSignDate;
}
private LocalDate calculateNextSignDate(MessageHolder holder) {
LocalDate miniContractDate = LocalDate.of(2022, 1, 1);
// 检索全部合同
ContractService contractService = getContractService();
List<Contract> contractList = contractService.findAllByCompanyVendor(vendor, null, null);
if (contractList.isEmpty()) {
holder.error("未发现已登记的合同");
return null;
}
holder.info("发现" + contractList.size() + "份合同");
// 检索评价表
List<VendorFile> files = getVendorFileService().findAllByVendorAndType(vendor,
VendorFileType.EvaluationForm);
VendorFile latestFile = files.stream()
.filter(v -> v.getSignDate() != null && v.isValid())
.max(Comparator.comparing(VendorFile::getSignDate))
.orElse(null);
// 没有有效的评价表的评价日期
if (latestFile == null) {
holder.warn("未发现有效的评价表");
// 返回最早的合同日期
Contract firstContract = contractList.stream()
.filter(v -> v.getSetupDate() != null && !v.getSetupDate().isBefore(miniContractDate))
.min(Comparator.comparing(Contract::getSetupDate))
.orElse(null);
if (firstContract == null) {
holder.error("最早的合同不存在");
return null;
}
LocalDate setupDate = firstContract.getSetupDate();
holder.info("选择最早的合同:" + firstContract.getCode() + ",日期:" + setupDate);
return setupDate.plusDays(-7);
}
// 有有效的评价表,计算下一个日期
LocalDate lastSignDate = latestFile.getSignDate();
holder.info("最近一次有效的评价表日期:" + lastSignDate);
// 查找最近一次评价日期之后的合同
Contract firstContractAfter = contractList.stream()
.filter(v -> v.getSetupDate() != null && v.getSetupDate().isAfter(lastSignDate))
.min(Comparator.comparing(Contract::getSetupDate))
.orElse(null);
if (firstContractAfter == null) {
holder.warn("没有找到在" + lastSignDate + "之后的合同");
// 返回当前日期作为建议
return LocalDate.now();
}
LocalDate setupDate = firstContractAfter.getSetupDate();
holder.info("找到最近一次评价日期后的第一个合同:" + firstContractAfter.getCode() + ",日期:" + setupDate);
return setupDate.plusDays(-7);
}
}

View File

@@ -13,7 +13,7 @@ import com.ecep.contract.ds.contract.service.ContractFileTypeService;
import com.ecep.contract.ds.contract.service.ContractService;
import com.ecep.contract.ds.customer.service.CompanyCustomerFileService;
import com.ecep.contract.ds.customer.service.CompanyCustomerFileTypeService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.service.CustomerService;
import com.ecep.contract.ds.other.service.EmployeeService;
import com.ecep.contract.ds.project.service.ProjectFileService;
import com.ecep.contract.ds.project.service.ProjectFileTypeService;
@@ -109,8 +109,8 @@ public class VerifyContext {
// Customer
protected CompanyCustomerService getCompanyCustomerService() {
return getBean(CompanyCustomerService.class);
protected CustomerService getCompanyCustomerService() {
return getBean(CustomerService.class);
}
protected CompanyCustomerFileTypeService getCompanyCustomerFileTypeService() {