拆分模块
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package com.ecep.contract.ds;
|
||||
|
||||
import static com.ecep.contract.AppV2.DEFAULT_DB_DATABASE;
|
||||
import static com.ecep.contract.AppV2.DEFAULT_DB_HOST;
|
||||
import static com.ecep.contract.AppV2.DEFAULT_DB_PASSWORD;
|
||||
import static com.ecep.contract.AppV2.DEFAULT_DB_PORT;
|
||||
import static com.ecep.contract.AppV2.DEFAULT_DB_USERNAME;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.config.BootstrapMode;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
@Configuration
|
||||
@EnableJpaRepositories(
|
||||
basePackages = {"com.ecep.contract.ds"},
|
||||
bootstrapMode = BootstrapMode.LAZY,
|
||||
repositoryFactoryBeanClass = JpaRepositoryFactoryBean.class
|
||||
)
|
||||
public class DsRepositoriesConfig {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DsRepositoriesConfig.class);
|
||||
|
||||
@Bean
|
||||
// @ConfigurationProperties(prefix = "spring.datasource")
|
||||
@Primary
|
||||
public DataSource dataSource(Environment env) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("SpringApp.dataSource, env:{}", env);
|
||||
}
|
||||
|
||||
String host = env.getProperty("db.server.host", DEFAULT_DB_HOST);
|
||||
String port = env.getProperty("db.server.port", DEFAULT_DB_PORT);
|
||||
String database = env.getProperty("db.server.database", DEFAULT_DB_DATABASE);
|
||||
String username = env.getProperty("db.server.username", DEFAULT_DB_USERNAME);
|
||||
String password = env.getProperty("db.server.password", DEFAULT_DB_PASSWORD);
|
||||
|
||||
String url = "jdbc:mysql://" + host + ":" + port + "/" + database;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("db server url:{},user:{}", url, username);
|
||||
}
|
||||
|
||||
return DataSourceBuilder.create()
|
||||
.type(HikariDataSource.class)
|
||||
.url(url)
|
||||
.username(username)
|
||||
.password(password)
|
||||
.driverClassName("com.mysql.cj.jdbc.Driver")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public JdbcTemplate jdbcTemplate(@Qualifier("dataSource") DataSource dataSource) {
|
||||
return new JdbcTemplate(dataSource);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ecep.contract.ds;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
import java.time.MonthDay;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
@Converter(autoApply = true)
|
||||
public class MonthDayConverter implements AttributeConverter<MonthDay, String> {
|
||||
|
||||
// 定义日期格式(月-日,两位数)
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("MM-dd");
|
||||
|
||||
@Override
|
||||
public String convertToDatabaseColumn(MonthDay attribute) {
|
||||
// 将 MonthDay 转换为数据库存储的字符串(MM-dd)
|
||||
return attribute != null ? attribute.format(FORMATTER) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonthDay convertToEntityAttribute(String dbData) {
|
||||
// 将数据库字符串(MM-dd)转换为 MonthDay
|
||||
return dbData != null ? MonthDay.parse(dbData, FORMATTER) : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.ecep.contract.ds;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface MyRepository<T, ID> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ecep.contract.ds.company;
|
||||
|
||||
import com.ecep.contract.ds.company.service.CompanyContactService;
|
||||
import com.ecep.contract.model.CompanyContact;
|
||||
import com.ecep.contract.util.EntityStringConverter;
|
||||
|
||||
public class CompanyContactStringConverter extends EntityStringConverter<CompanyContact> {
|
||||
|
||||
public CompanyContactStringConverter() {
|
||||
|
||||
}
|
||||
|
||||
public CompanyContactStringConverter(CompanyContactService service) {
|
||||
setInitialized(employee -> service.findById(employee.getId()));
|
||||
// setFromString(service::findByName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package com.ecep.contract.ds.company;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.ecep.contract.util.FileUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.CompanyFileType;
|
||||
import com.ecep.contract.MyDateTimeUtils;
|
||||
import com.ecep.contract.constant.CloudServiceConstant;
|
||||
import com.ecep.contract.ds.company.service.CompanyFileService;
|
||||
import com.ecep.contract.model.CompanyFile;
|
||||
|
||||
public class CompanyFileUtils {
|
||||
|
||||
public static CompanyFile fillType(String fileName, String companyName, File destDir) {
|
||||
CompanyFile companyFile = new CompanyFile();
|
||||
if (isTycReport(fileName, companyName)) {
|
||||
File dest = new File(destDir, fileName);
|
||||
companyFile.setType(CompanyFileType.CreditReport);
|
||||
companyFile.setFilePath(dest.getAbsolutePath());
|
||||
return companyFile;
|
||||
}
|
||||
|
||||
// 包含公司名称 和 天眼查 的文件
|
||||
if (fileName.contains(companyName) && fileName.contains(CloudServiceConstant.TYC_NAME)) {
|
||||
LocalDateTime dateTime = LocalDateTime.now();
|
||||
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm");
|
||||
int idx = fileName.indexOf("报告");
|
||||
String destName = (idx > 0 ? fileName.substring(0, fileName.indexOf("报告") + 2) + "_" : "") +
|
||||
companyName + "_天眼查_" + dateTime.format(fmt) + "." + StringUtils.getFilenameExtension(fileName);
|
||||
}
|
||||
|
||||
for (CompanyFileType value : CompanyFileType.values()) {
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从文件名判断是否是天眼查的报告文件
|
||||
*/
|
||||
public static boolean isTycReport(String fileName, String companyName) {
|
||||
// 文件名中必须包含 天眼查 字样
|
||||
if (!fileName.contains(CloudServiceConstant.TYC_NAME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 文件名中必须包含 公司名称
|
||||
if (!fileName.contains(companyName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 文件名后缀需符合要求
|
||||
return FileUtils.withExtensions(fileName, FileUtils.PDF, FileUtils.DOC, FileUtils.DOCX);
|
||||
}
|
||||
|
||||
public static boolean isCompanyFile(File file) {
|
||||
String fileName = file.getName();
|
||||
if (fileName.equals(FileUtils.FILE_DB_JSON)) {
|
||||
return true;
|
||||
}
|
||||
if (fileName.equals(FileUtils.FILE_B1001_JSON)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fileName.equals(FileUtils.FILE_BLACK_LIST_JSON)) {
|
||||
return true;
|
||||
}
|
||||
if (fileName.equals("合同列表.json")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 营业执照
|
||||
if (fileName.contains(CompanyFileService.BUSINESS_LICENSE)) {
|
||||
return true;
|
||||
}
|
||||
// 操作证
|
||||
if (fileName.contains(CompanyFileService.OPERATION_CERTIFICATE)) {
|
||||
return true;
|
||||
}
|
||||
// 许可证
|
||||
if (fileName.contains(CompanyFileService.PERMIT_CERTIFICATE)) {
|
||||
return true;
|
||||
}
|
||||
// 登记证
|
||||
if (fileName.contains(CompanyFileService.REGISTRATION_CERTIFICATE)) {
|
||||
return true;
|
||||
}
|
||||
// 组织机构代码证
|
||||
if (fileName.contains(CompanyFileService.ORGANIZATION_CODE_CERTIFICATE)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件名中提取的日期信息更新对象的日期,如果文件名称中没有可识别的日期,则不进行任何更新
|
||||
* 日期提取方法参考 {@link MyDateTimeUtils#pickLocalDate(String)}
|
||||
*
|
||||
* @param file 日期来源文件对象
|
||||
* @param vendorFile 要更新的对象
|
||||
* @param getter 对象的日期获取方法
|
||||
* @param setter 对象的日期设置方法
|
||||
* @param <T> 对象泛型
|
||||
* @return 是否更新了日期
|
||||
*/
|
||||
public static <T> boolean fillApplyDateAbsent(File file, T vendorFile, Function<T, LocalDate> getter,
|
||||
BiConsumer<T, LocalDate> setter) {
|
||||
LocalDate applyDate = getter.apply(vendorFile);
|
||||
if (applyDate != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean modified = false;
|
||||
String fileName = file.getName();
|
||||
// 从文件的名称中提取日期
|
||||
LocalDate picked = MyDateTimeUtils.pickLocalDate(fileName);
|
||||
if (picked != null) {
|
||||
// 如果提取出的日期不为空,则通过setter函数将这个日期设置到vendorFile中,并将modified标志设置为true。
|
||||
setter.accept(vendorFile, picked);
|
||||
modified = true;
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
public static boolean isHiddenFile(File file) {
|
||||
String fileName = file.getName();
|
||||
if (fileName.equals(FileUtils.FILE_DB_THUMBS)) {
|
||||
return true;
|
||||
}
|
||||
return fileName.startsWith("~$");
|
||||
}
|
||||
|
||||
public static String escapeFileName(String fileName) {
|
||||
String patternStr = "[\\\\/:*?\"<>|]";
|
||||
Pattern pattern = Pattern.compile(patternStr);
|
||||
Matcher matcher = pattern.matcher(fileName);
|
||||
return matcher.replaceAll("_");
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回 district 中关于省份的部门zi
|
||||
*
|
||||
* @param district 地区
|
||||
* @return 省份名称
|
||||
*/
|
||||
public static String getParentPrefixByDistrict(String district) {
|
||||
int indexOf = district.indexOf("省");
|
||||
if (indexOf != -1) {
|
||||
return district.substring(0, indexOf);
|
||||
}
|
||||
|
||||
indexOf = district.indexOf("自治区");
|
||||
if (indexOf != -1) {
|
||||
return district.substring(0, 2);
|
||||
}
|
||||
|
||||
indexOf = district.indexOf("市");
|
||||
if (indexOf != -1) {
|
||||
return district.substring(0, indexOf);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean exists(String path) {
|
||||
if (!StringUtils.hasText(path)) {
|
||||
return false;
|
||||
}
|
||||
File file = new File(path);
|
||||
return file.exists();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
CREATE TABLE supplier_ms.COMPANY_BANK_ACCOUNT
|
||||
(
|
||||
ID INT AUTO_INCREMENT NOT NULL,
|
||||
BANK_ID INT NULL,
|
||||
OPENING_BANK VARCHAR(255) NULL,
|
||||
ACCOUNT VARCHAR(255) NULL,
|
||||
CONSTRAINT pk_company_bank_account PRIMARY KEY (ID)
|
||||
);
|
||||
|
||||
ALTER TABLE supplier_ms.COMPANY_BANK_ACCOUNT
|
||||
ADD CONSTRAINT FK_COMPANY_BANK_ACCOUNT_ON_BANK FOREIGN KEY (BANK_ID) REFERENCES supplier_ms.BANK (ID);
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyBankAccount;
|
||||
|
||||
public interface CompanyBankAccountRepository extends MyRepository<CompanyBankAccount, Integer> {
|
||||
|
||||
Optional<CompanyBankAccount> findByCompanyAndAccount(Company company, String account);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyBlackReason;
|
||||
|
||||
@Repository
|
||||
public interface CompanyBlackReasonRepository extends MyRepository<CompanyBlackReason, Integer> {
|
||||
|
||||
List<CompanyBlackReason> findAllByCompany(Company company);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyContact;
|
||||
|
||||
@Repository
|
||||
public interface CompanyContactRepository extends MyRepository<CompanyContact, Integer> {
|
||||
|
||||
Optional<CompanyContact> findFirstByCompany(Company company);
|
||||
|
||||
List<CompanyContact> findAllByCompany(Company company);
|
||||
|
||||
List<CompanyContact> findAllByCompanyAndName(Company company, String name);
|
||||
|
||||
int deleteAllByCompany(Company company);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyContract;
|
||||
import com.ecep.contract.model.Contract;
|
||||
|
||||
@Repository
|
||||
public interface CompanyContractRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<CompanyContract, Integer>, PagingAndSortingRepository<CompanyContract, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<CompanyContract, Integer>, JpaSpecificationExecutor<CompanyContract> {
|
||||
|
||||
List<CompanyContract> findByCompanyId(int companyId);
|
||||
|
||||
List<CompanyContract> findByCompany(Company company);
|
||||
|
||||
Stream<CompanyContract> findStreamByCompany(Company company);
|
||||
|
||||
Optional<CompanyContract> findByContractId(int contractId);
|
||||
|
||||
Optional<CompanyContract> findByContract(Contract contract);
|
||||
|
||||
Optional<CompanyContract> findByCompanyAndContract(Company company, Contract contract);
|
||||
|
||||
List<CompanyContract> findAllByCompany(Company company);
|
||||
|
||||
/**
|
||||
* Delete all company contracts by company
|
||||
*
|
||||
* @param company Company
|
||||
* @return 删除的记录行数
|
||||
*/
|
||||
int deleteAllByCompany(Company company);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyExtendInfo;
|
||||
|
||||
public interface CompanyExtendInfoRepository extends MyRepository<CompanyExtendInfo, Integer> {
|
||||
|
||||
List<CompanyExtendInfo> findByCompany(Company company);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.ecep.contract.CompanyFileType;
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyFile;
|
||||
|
||||
public interface CompanyFileRepository extends MyRepository<CompanyFile, Integer> {
|
||||
|
||||
List<CompanyFile> findByCompany(Company company);
|
||||
|
||||
List<CompanyFile> findByCompanyAndType(Company company, CompanyFileType type);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.CompanyFileType;
|
||||
import com.ecep.contract.ds.other.repository.BaseEnumEntityRepository;
|
||||
import com.ecep.contract.model.CompanyFileTypeLocal;
|
||||
|
||||
@Repository
|
||||
public interface CompanyFileTypeLocalRepository extends BaseEnumEntityRepository<CompanyFileType, CompanyFileTypeLocal, Integer> {
|
||||
|
||||
@Override
|
||||
default CompanyFileType[] getEnumConstants() {
|
||||
return CompanyFileType.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
default CompanyFileTypeLocal newEntity() {
|
||||
return new CompanyFileTypeLocal();
|
||||
}
|
||||
|
||||
CompanyFileTypeLocal findByTypeAndLang(CompanyFileType type, String lang);
|
||||
|
||||
default CompanyFileTypeLocal getCompleteByTypeAndLang(CompanyFileType type, String lang) {
|
||||
CompanyFileTypeLocal v = findByTypeAndLang(type, lang);
|
||||
if (v == null) {
|
||||
v = newEntity();
|
||||
v.setType(type);
|
||||
v.setLang(lang);
|
||||
v.setValue(type.name());
|
||||
v = save(v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.CompanyInvoiceInfo;
|
||||
|
||||
/**
|
||||
* 公司发票信息 Repository
|
||||
*/
|
||||
@Repository
|
||||
public interface CompanyInvoiceInfoRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<CompanyInvoiceInfo, Integer>, PagingAndSortingRepository<CompanyInvoiceInfo, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<CompanyInvoiceInfo, Integer>, JpaSpecificationExecutor<CompanyInvoiceInfo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.ecep.contract.model.CompanyOldName;
|
||||
|
||||
@Repository
|
||||
public interface CompanyOldNameRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<CompanyOldName, Integer>, PagingAndSortingRepository<CompanyOldName, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<CompanyOldName, Integer>, JpaSpecificationExecutor<CompanyOldName> {
|
||||
|
||||
List<CompanyOldName> findAllByCompanyId(Integer companyId);
|
||||
|
||||
List<CompanyOldName> findAllByCompanyIdAndName(Integer companyId, String name);
|
||||
|
||||
List<CompanyOldName> findAllByName(String name);
|
||||
|
||||
List<CompanyOldName> findByNameLike(String searchText);
|
||||
|
||||
List<CompanyOldName> findByMemoLike(String searchText);
|
||||
|
||||
@Modifying
|
||||
@Transactional
|
||||
int deleteAllByCompanyId(Integer companyId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.Company;
|
||||
|
||||
@Repository
|
||||
public interface CompanyRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<Company, Integer>, PagingAndSortingRepository<Company, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<Company, Integer>, JpaSpecificationExecutor<Company> {
|
||||
|
||||
List<Company> findAllByName(String name);
|
||||
|
||||
Optional<Company> findFirstByName(String name);
|
||||
|
||||
List<Company> findAllByShortName(String shortName);
|
||||
|
||||
/**
|
||||
* @param uniscid 统一社会信用代码
|
||||
*/
|
||||
List<Company> findAllByUniscid(String uniscid);
|
||||
|
||||
@Query("select u from Company u")
|
||||
Stream<Company> findAllAsStream();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.ecep.contract.ds.company.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.Invoice;
|
||||
|
||||
public interface InvoiceRepository extends MyRepository<Invoice, Integer> {
|
||||
|
||||
List<Invoice> findByCompany(Company company);
|
||||
|
||||
Invoice findByCode(String invoiceNumber);
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.ecep.contract.ds.company.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.ds.company.repository.CompanyBankAccountRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyBankAccount;
|
||||
import com.ecep.contract.util.SpecificationUtils;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "company-bank-account")
|
||||
public class CompanyBankAccountService implements IEntityService<CompanyBankAccount> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyBankAccountService.class);
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyBankAccountRepository repository;
|
||||
|
||||
|
||||
public CompanyBankAccount findByAccount(Company company, String account) {
|
||||
return repository.findByCompanyAndAccount(company, account).orElse(null);
|
||||
}
|
||||
|
||||
public void updateBankAccount(Company company, String bank, String bankAccount, MessageHolder holder) {
|
||||
boolean modified = false;
|
||||
if (!StringUtils.hasText(bankAccount)) {
|
||||
// 空账户不用存储
|
||||
return;
|
||||
}
|
||||
|
||||
CompanyBankAccount account = findByAccount(company, bankAccount);
|
||||
if (account == null) {
|
||||
account = new CompanyBankAccount();
|
||||
account.setCompany(company);
|
||||
account.setAccount(bankAccount);
|
||||
holder.info("新增银行账户" + bankAccount);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(bank)) {
|
||||
// 更新开户行
|
||||
if (!Objects.equals(account.getOpeningBank(), bank)) {
|
||||
account.setOpeningBank(bank);
|
||||
holder.info("更新开户行" + bank);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
save(account);
|
||||
}
|
||||
}
|
||||
|
||||
public CompanyBankAccount save(CompanyBankAccount account) {
|
||||
return repository.save(account);
|
||||
}
|
||||
|
||||
public List<CompanyBankAccount> findAll(Specification<CompanyBankAccount> spec, Sort sort) {
|
||||
return repository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompanyBankAccount findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Specification<CompanyBankAccount> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.and(
|
||||
builder.isNotNull(root.get("bank")),
|
||||
builder.or(
|
||||
builder.like(root.get("bank").get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("bank").get("code"), "%" + searchText + "%")
|
||||
)
|
||||
),
|
||||
builder.like(root.get("openingBank"), "%" + searchText + "%"),
|
||||
builder.like(root.get("account"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CompanyBankAccount> findAll(Specification<CompanyBankAccount> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public void delete(CompanyBankAccount entity) {
|
||||
repository.delete(entity);
|
||||
}
|
||||
|
||||
public List<CompanyBankAccount> searchByCompany(Company company, String searchText) {
|
||||
Specification<CompanyBankAccount> spec = getSpecification(searchText);
|
||||
if (company != null) {
|
||||
spec = SpecificationUtils.and(spec, (root, query, builder) -> {
|
||||
return builder.equal(root.get("company"), company);
|
||||
});
|
||||
}
|
||||
return repository.findAll(spec, Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,472 @@
|
||||
package com.ecep.contract.ds.company.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.ecep.contract.util.FileUtils;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.SpringApp;
|
||||
import com.ecep.contract.ds.company.CompanyFileUtils;
|
||||
import com.ecep.contract.ds.other.repository.HolidayTableRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyBasicFile;
|
||||
import com.ecep.contract.model.CompanyCustomerFile;
|
||||
import com.ecep.contract.model.CompanyVendorFile;
|
||||
import com.ecep.contract.model.HolidayTable;
|
||||
|
||||
public abstract class CompanyBasicService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyBasicService.class);
|
||||
|
||||
/**
|
||||
* 调整日期到工作日
|
||||
*
|
||||
* @param date 要调整的日期
|
||||
* @return 调整的日期
|
||||
*/
|
||||
public static LocalDate adjustToWorkDay(LocalDate date) {
|
||||
if (date.getDayOfWeek() == DayOfWeek.SATURDAY) {
|
||||
// 再减去1天,到周五
|
||||
date = date.plusDays(-1);
|
||||
} else if (date.getDayOfWeek() == DayOfWeek.SUNDAY) {
|
||||
// 再减去2天,到周五
|
||||
date = date.plusDays(-2);
|
||||
}
|
||||
|
||||
HolidayTableRepository holidayTableRepository = SpringApp.getBean(HolidayTableRepository.class);
|
||||
//TODO 跳过节假日
|
||||
int tryDays = 15;
|
||||
while (tryDays-- > 0) {
|
||||
HolidayTable holidayTable = holidayTableRepository.findById(date).orElse(null);
|
||||
if (holidayTable == null) {
|
||||
// 没有节假日定义,检查是否是工作日
|
||||
DayOfWeek dayOfWeek = date.getDayOfWeek();
|
||||
if (dayOfWeek == DayOfWeek.SATURDAY) {
|
||||
date = date.plusDays(-1);
|
||||
continue;
|
||||
}
|
||||
if (dayOfWeek == DayOfWeek.SUNDAY) {
|
||||
date = date.plusDays(-2);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!holidayTable.isHoliday()) {
|
||||
// 不是节假日
|
||||
break;
|
||||
}
|
||||
date = date.plusDays(-1);
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
@Lazy
|
||||
@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, Consumer<String> status) {
|
||||
boolean modified = false;
|
||||
List<File> editFiles = new ArrayList<>();
|
||||
// 排除掉数据库中重复的
|
||||
for (F dbFile : dbFiles) {
|
||||
String filePath = dbFile.getFilePath();
|
||||
// 没有文件信息,无效记录,删除
|
||||
if (!StringUtils.hasText(filePath)) {
|
||||
deleteFile(dbFile);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 文件不存在或者隐藏文件,删除记录
|
||||
File file = new File(filePath);
|
||||
if (!file.exists() || CompanyFileUtils.isHiddenFile(file)) {
|
||||
deleteFile(dbFile);
|
||||
continue;
|
||||
}
|
||||
|
||||
// old 是冲突的,按dbFiles顺序,旧的(list前面的)
|
||||
F old = map.put(filePath, dbFile);
|
||||
// 目录有重复删除
|
||||
if (old != null) {
|
||||
deleteFile(old);
|
||||
}
|
||||
|
||||
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("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 类型未设置,补充类型
|
||||
if (dbFile.getType() == null) {
|
||||
if (fillFileAsDefaultType(dbFile, file, status)) {
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (File editFile : editFiles) {
|
||||
String editFilePath = editFile.getAbsolutePath();
|
||||
F dup = map.remove(editFilePath);
|
||||
// 目录有重复删除
|
||||
if (dup != null) {
|
||||
deleteFile(dup);
|
||||
}
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* dbFile 的 Type 未设置时,设置为默认类型
|
||||
*
|
||||
* @param dbFile 要设置的 对象
|
||||
* @param file 相关文件对象
|
||||
* @param status 状态输出
|
||||
* @param <T> 类型类
|
||||
* @param <F> 文件类
|
||||
* @return 是否修改了
|
||||
* @see CompanyVendorFile
|
||||
* @see CompanyVendorFileType
|
||||
* @see CompanyCustomerFile
|
||||
* @see CompanyCustomerFileType
|
||||
*/
|
||||
protected abstract <T, F extends CompanyBasicFile<T>> boolean fillFileAsDefaultType(F dbFile, File file, Consumer<String> status);
|
||||
|
||||
|
||||
protected void moveFileToCompany(Company company, List<File> needMoveToCompanyPath) {
|
||||
if (needMoveToCompanyPath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!Hibernate.isInitialized(company)) {
|
||||
company = companyService.findById(company.getId());
|
||||
}
|
||||
String companyPath = company.getPath();
|
||||
if (!StringUtils.hasText(companyPath)) {
|
||||
return;
|
||||
}
|
||||
for (File file : needMoveToCompanyPath) {
|
||||
File dest = new File(companyPath, file.getName());
|
||||
if (file.renameTo(dest)) {
|
||||
//
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("{} -> {}", file.getAbsolutePath(), dest.getAbsolutePath());
|
||||
}
|
||||
} else {
|
||||
//
|
||||
if (dest.exists()) {
|
||||
if (file.delete()) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Delete File {}", file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 公司目录下文件更新后,待公司文件自行处理
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历扫描 path 目录下的文件,
|
||||
*
|
||||
* @param path
|
||||
* @param needMoveToCompanyPath
|
||||
* @param retrieveFiles
|
||||
* @param map
|
||||
* @param status
|
||||
* @param <T>
|
||||
* @param <F>
|
||||
*/
|
||||
protected <T, F extends CompanyBasicFile<T>> void fetchFiles(
|
||||
String path,
|
||||
List<File> needMoveToCompanyPath,
|
||||
List<F> retrieveFiles,
|
||||
Map<String, F> map,
|
||||
Consumer<String> status
|
||||
) {
|
||||
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() || CompanyFileUtils.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)) {
|
||||
// 已记录
|
||||
F customerFile = map.get(filePath);
|
||||
if (fillFile(customerFile, file, step1, status)) {
|
||||
retrieveFiles.add(customerFile);
|
||||
}
|
||||
step1.remove(file);
|
||||
}
|
||||
}
|
||||
|
||||
// 第二步骤,再处理
|
||||
while (!step1.isEmpty()) {
|
||||
File file = step1.removeLast();
|
||||
F filled = fillFileType(file, step1, status);
|
||||
if (filled != null) {
|
||||
retrieveFiles.add(filled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充文件类型
|
||||
*
|
||||
* @param file
|
||||
* @param fileList
|
||||
* @param status 状态输出
|
||||
* @param <T> 类型类
|
||||
* @param <F> 文件类
|
||||
*/
|
||||
protected abstract <T, F extends CompanyBasicFile<T>> F fillFileType(File file, List<File> fileList, Consumer<String> status);
|
||||
|
||||
/**
|
||||
* @param customerFile 文件对象
|
||||
* @param file 相关文件
|
||||
* @param fileList 待处理文件列表
|
||||
* @param status 状态输出
|
||||
* @param <T> 类型类
|
||||
* @param <F> 文件类
|
||||
* @return true 有修改
|
||||
*/
|
||||
protected <T, F extends CompanyBasicFile<T>> boolean fillFile(F customerFile, File file, List<File> fileList, Consumer<String> status) {
|
||||
String fileName = file.getName();
|
||||
boolean modified = CompanyFileUtils.fillApplyDateAbsent(file, customerFile, F::getSignDate, F::setSignDate);
|
||||
// 评估表
|
||||
if (isEvaluationFile(fileName)) {
|
||||
if (fillFileAsEvaluationFile(customerFile, file, fileList, status)) {
|
||||
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 <T, F extends CompanyBasicFile<T>> boolean fillFileAsEvaluationFile(F customerFile, File file, List<File> fileList, Consumer<String> status) {
|
||||
boolean modified = setFileTypeAsEvaluationForm(customerFile);
|
||||
String fileName = file.getName();
|
||||
|
||||
// 文件全路径
|
||||
String fileAbsolutePath = file.getAbsolutePath();
|
||||
|
||||
if (isEditableFile(fileName)) {
|
||||
// 是可编辑文件时
|
||||
if (!Objects.equals(fileAbsolutePath, customerFile.getEditFilePath())) {
|
||||
customerFile.setEditFilePath(fileAbsolutePath);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (useAsEditableFile(customerFile, file, fileList, status)) {
|
||||
modified = true;
|
||||
}
|
||||
} else if (isArchiveFile(fileName)) {
|
||||
// 存档文件时
|
||||
if (!Objects.equals(fileAbsolutePath, customerFile.getFilePath())) {
|
||||
customerFile.setFilePath(fileAbsolutePath);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (useAsArchiveFile(customerFile, file, fileList, status)) {
|
||||
modified = true;
|
||||
}
|
||||
} else {
|
||||
customerFile.setFilePath(file.getAbsolutePath());
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
private <T, F extends CompanyBasicFile<T>> boolean useAsEditableFile(F customerFile, File file, List<File> fileList, Consumer<String> status) {
|
||||
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) && isArchiveFile(f.getName())) {
|
||||
archiveFile = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 没有匹配到文件
|
||||
if (archiveFile == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileList.remove(archiveFile)) {
|
||||
customerFile.setFilePath(archiveFile.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private <T, F extends CompanyBasicFile<T>> boolean useAsArchiveFile(F customerFile, File file, List<File> fileList, Consumer<String> status) {
|
||||
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) && 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置文件类型为表单文件
|
||||
*
|
||||
* @param file 文件对象
|
||||
* @param <T> 类型类
|
||||
* @param <F> 文件类
|
||||
* @return true 文件对象有修改,否则false
|
||||
*/
|
||||
protected abstract <T, F extends CompanyBasicFile<T>> boolean setFileTypeAsEvaluationForm(F file);
|
||||
|
||||
/**
|
||||
* 判定 参数 fileName 是否是一个评价表文件
|
||||
*
|
||||
* @param fileName 文件名称
|
||||
* @return true 是评价表,否则false
|
||||
*/
|
||||
protected abstract boolean isEvaluationFile(String fileName);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.ecep.contract.ds.company.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.company.repository.CompanyBlackReasonRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyBlackReason;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
public class CompanyBlackReasonService implements IEntityService<CompanyBlackReason> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyContactService.class);
|
||||
|
||||
@Autowired
|
||||
private CompanyBlackReasonRepository repository;
|
||||
|
||||
|
||||
public CompanyBlackReason findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<CompanyBlackReason> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("applyName"), "%" + searchText + "%"),
|
||||
builder.like(root.get("blackReason"), "%" + searchText + "%"),
|
||||
builder.like(root.get("description"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CompanyBlackReason> findAll(Specification<CompanyBlackReason> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public void delete(CompanyBlackReason entity) {
|
||||
repository.delete(entity);
|
||||
}
|
||||
|
||||
public List<CompanyBlackReason> findAll(Specification<CompanyBlackReason> spec, Sort by) {
|
||||
return repository.findAll(spec, by);
|
||||
}
|
||||
|
||||
public List<CompanyBlackReason> findAllByCompany(Company company) {
|
||||
return repository.findAllByCompany(company);
|
||||
}
|
||||
|
||||
public CompanyBlackReason save(CompanyBlackReason companyBlackReason) {
|
||||
return repository.save(companyBlackReason);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.ecep.contract.ds.company.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.company.repository.CompanyContactRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyContact;
|
||||
import com.ecep.contract.util.MyStringUtils;
|
||||
import com.ecep.contract.util.SpecificationUtils;
|
||||
|
||||
/**
|
||||
* 公司联系人服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "company-contact")
|
||||
public class CompanyContactService implements IEntityService<CompanyContact> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyContactService.class);
|
||||
|
||||
@Autowired
|
||||
private CompanyContactRepository companyContactRepository;
|
||||
|
||||
public CompanyContact save(CompanyContact contact) {
|
||||
return companyContactRepository.save(contact);
|
||||
}
|
||||
|
||||
public void resetTo(Company from, Company to) {
|
||||
// 曾用名 关联到 updater
|
||||
List<CompanyContact> list = companyContactRepository.findAllByCompany(from);
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (CompanyContact oldName : list) {
|
||||
oldName.setMemo(MyStringUtils.appendIfAbsent(oldName.getMemo(), "转自 " + from.getId()));
|
||||
oldName.setCompany(to);
|
||||
}
|
||||
companyContactRepository.saveAll(list);
|
||||
}
|
||||
|
||||
public void deleteByCompany(Company company) {
|
||||
int deleted = companyContactRepository.deleteAllByCompany(company);
|
||||
if (deleted > 0) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Delete {} records by company:#{}", deleted, company.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(CompanyContact entity) {
|
||||
companyContactRepository.delete(entity);
|
||||
}
|
||||
|
||||
public CompanyContact findFirstByCompany(Company company) {
|
||||
return companyContactRepository.findFirstByCompany(company).orElse(null);
|
||||
}
|
||||
|
||||
public CompanyContact findById(Integer id) {
|
||||
return companyContactRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<CompanyContact> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("phone"), "%" + searchText + "%"),
|
||||
builder.like(root.get("email"), "%" + searchText + "%"),
|
||||
builder.like(root.get("position"), "%" + searchText + "%"),
|
||||
builder.like(root.get("memo"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CompanyContact> findAll(Specification<CompanyContact> spec, Pageable pageable) {
|
||||
return companyContactRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<CompanyContact> searchByCompany(Company company, String userText) {
|
||||
Specification<CompanyContact> spec = SpecificationUtils.and((root, query, builder) -> {
|
||||
return builder.equal(root.get("company"), company);
|
||||
}, getSpecification(userText));
|
||||
return companyContactRepository.findAll(spec);
|
||||
}
|
||||
|
||||
public List<CompanyContact> findAll(Specification<CompanyContact> spec, Sort sort) {
|
||||
return companyContactRepository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
public List<CompanyContact> findAllByCompanyAndName(Company company, String contactName) {
|
||||
return companyContactRepository.findAllByCompanyAndName(company, contactName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.ecep.contract.ds.company.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.ds.company.repository.CompanyExtendInfoRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyExtendInfo;
|
||||
|
||||
/**
|
||||
* 公司文件服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "company-extend-info")
|
||||
public class CompanyExtendInfoService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyExtendInfoService.class);
|
||||
@Autowired
|
||||
private CompanyExtendInfoRepository repository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public CompanyExtendInfo findById(int id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
|
||||
public List<CompanyExtendInfo> findAll(Specification<CompanyExtendInfo> spec, Sort sort) {
|
||||
return repository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'byCompany-'+#p0.company.id")
|
||||
}
|
||||
)
|
||||
public void delete(CompanyExtendInfo extendInfo) {
|
||||
repository.delete(extendInfo);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'byCompany-'+#p0.company.id")
|
||||
}
|
||||
)
|
||||
public CompanyExtendInfo save(CompanyExtendInfo extendInfo) {
|
||||
return repository.save(extendInfo);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'byCompany-'+#p0")
|
||||
public CompanyExtendInfo findByCompany(Company company) {
|
||||
List<CompanyExtendInfo> list = repository.findByCompany(company);
|
||||
if (list.isEmpty()) {
|
||||
CompanyExtendInfo extendInfo = new CompanyExtendInfo();
|
||||
extendInfo.setCompany(company);
|
||||
extendInfo.setDisableVerify(false);
|
||||
return repository.save(extendInfo);
|
||||
}
|
||||
return list.getFirst();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,635 @@
|
||||
package com.ecep.contract.ds.company.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.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.CompanyFileType;
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.MyDateTimeUtils;
|
||||
import com.ecep.contract.SpringApp;
|
||||
import com.ecep.contract.cloud.rk.CloudRkService;
|
||||
import com.ecep.contract.cloud.tyc.CloudTycService;
|
||||
import com.ecep.contract.constant.CloudServiceConstant;
|
||||
import com.ecep.contract.ds.company.CompanyFileUtils;
|
||||
import com.ecep.contract.ds.company.repository.CompanyFileRepository;
|
||||
import com.ecep.contract.ds.company.repository.CompanyFileTypeLocalRepository;
|
||||
import com.ecep.contract.ds.company.repository.CompanyOldNameRepository;
|
||||
import com.ecep.contract.ds.contract.service.ContractService;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyFile;
|
||||
import com.ecep.contract.model.CompanyFileTypeLocal;
|
||||
import com.ecep.contract.model.CompanyOldName;
|
||||
import com.ecep.contract.model.Contract;
|
||||
|
||||
/**
|
||||
* 公司文件服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "company-file")
|
||||
public class CompanyFileService implements IEntityService<CompanyFile> {
|
||||
public final static String ENTERPRISE_REPORT = "企业信用报告";
|
||||
public final static String BUSINESS_LICENSE = "营业执照";
|
||||
public final static String ORGANIZATION_CODE_CERTIFICATE = "组织机构代码证";
|
||||
public final static String OPERATION_CERTIFICATE = "操作证";
|
||||
public final static String PERMIT_CERTIFICATE = "许可证";
|
||||
public final static String REGISTRATION_CERTIFICATE = "登记证";
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyFileService.class);
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyFileRepository companyFileRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyOldNameRepository companyOldNameRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyFileTypeLocalRepository fileTypeLocalRepository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public CompanyFile findById(Integer id) {
|
||||
return companyFileRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CompanyFile> findAll(Specification<CompanyFile> spec, Pageable pageable) {
|
||||
return companyFileRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<CompanyFile> findFileByCompanyAndType(Company company, CompanyFileType type) {
|
||||
return companyFileRepository.findByCompanyAndType(company, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<CompanyFile> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(builder.like(root.get("filePath"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
|
||||
@Cacheable(key = "'type-locals-'+#p0")
|
||||
public Map<CompanyFileType, CompanyFileTypeLocal> findAllFileTypes(String lang) {
|
||||
return fileTypeLocalRepository.getCompleteMapByLocal(lang);
|
||||
}
|
||||
// public List<CompanyFileTypeLocal> findAllFileTypes(String lang) {
|
||||
// Map<CompanyFileType, CompanyFileTypeLocal> map =
|
||||
// fileTypeLocalRepository.getCompleteMapByLocal(lang);
|
||||
// List<CompanyFileTypeLocal> list = new ArrayList<>(map.values());
|
||||
// list.sort((o1, o2) -> Objects.compare(o1.getValue(), o2.getValue(),
|
||||
// String::compareTo));
|
||||
// return list;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 根据公司的合同的资信报告文件,推算下一个咨询报告日期
|
||||
*
|
||||
* @param company 公司
|
||||
* @param state 状态输出
|
||||
* @return 下一个咨询报告日期
|
||||
*/
|
||||
public LocalDate getNextCreditReportDate(Company company, Consumer<String> state) {
|
||||
// 检索全部合同
|
||||
ContractService contractService = SpringApp.getBean(ContractService.class);
|
||||
List<Contract> contractList = contractService.findAllByCompany(company);
|
||||
if (contractList.isEmpty()) {
|
||||
state.accept("未发现已登记的合同");
|
||||
return null;
|
||||
}
|
||||
|
||||
LocalDate minDate = LocalDate.of(2023, 1, 1);
|
||||
List<Contract> contracts = contractList.stream()
|
||||
.filter(v -> !v.getSetupDate().isBefore(minDate))
|
||||
.sorted(Comparator.comparing(Contract::getSetupDate))
|
||||
.toList();
|
||||
if (contracts.isEmpty()) {
|
||||
state.accept("没有发现待处理的合同");
|
||||
return null;
|
||||
}
|
||||
// 检索资信报告
|
||||
List<CompanyFile> files = findFileByCompanyAndType(company, CompanyFileType.CreditReport);
|
||||
if (files.isEmpty()) {
|
||||
Contract first = contracts.getFirst();
|
||||
// 没有资信报告,返回第一个合同的提交日期
|
||||
state.accept("没有资信报告,推荐使用第一个合同 " + first.getCode() + " 的日期 " + first.getSetupDate());
|
||||
return first.getSetupDate();
|
||||
}
|
||||
|
||||
for (Contract contract : contracts) {
|
||||
if (files.stream().noneMatch(v -> MyDateTimeUtils.dateValidFilter(contract.getSetupDate(), v.getApplyDate(),
|
||||
v.getExpiringDate(), 1))) {
|
||||
state.accept("发现未匹配的合同 " + contract.getCode() + " " + contract.getSetupDate());
|
||||
return contract.getSetupDate();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证企业文件
|
||||
* <p>
|
||||
* 检查是否有类型为{@link CompanyFileType#CreditReport
|
||||
* 资讯评估}的文件,且参数verifyDate在文件的{@link CompanyFile#getApplyDate()}和{@link CompanyFile#getExpiringDate()}
|
||||
* ()}指定验证日期内有
|
||||
* <p>
|
||||
* 2023-01-01后要求有资信评估报告
|
||||
*
|
||||
* @param company 检查的公司对象
|
||||
* @param verifyDate 检查日期
|
||||
* @param status 状态输出
|
||||
* @see CompanyFile
|
||||
* @see CompanyFileType
|
||||
*/
|
||||
public void verify(Company company, LocalDate verifyDate, Consumer<String> status) {
|
||||
if (verifyDate.isBefore(LocalDate.of(2023, 1, 1))) {
|
||||
// 不检查2023-01-01之前的资信评估报告
|
||||
return;
|
||||
}
|
||||
|
||||
// 查询公司的资信评估报告
|
||||
List<CompanyFile> files = findFileByCompanyAndType(company, CompanyFileType.CreditReport);
|
||||
CompanyFile 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(CompanyFile::getApplyDate))
|
||||
.map(CompanyFile::getApplyDate)
|
||||
.ifPresent(dates::add);
|
||||
|
||||
files.stream()
|
||||
.filter(v -> v.getExpiringDate() != null && !verifyDate.isAfter(v.getExpiringDate()))
|
||||
.min(Comparator.comparing(CompanyFile::getApplyDate))
|
||||
.map(CompanyFile::getApplyDate)
|
||||
.ifPresent(dates::add);
|
||||
|
||||
if (dates.isEmpty()) {
|
||||
status.accept("未匹配到资信评估报告");
|
||||
} else if (dates.size() == 1) {
|
||||
status.accept("未匹配到资信评估报告, 最接近日期:" + dates.getFirst());
|
||||
} else {
|
||||
LocalDate localDate = dates.stream().max(LocalDate::compareTo).orElse(null);
|
||||
status.accept("未匹配到资信评估报告, 最接近日期:" + localDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存企业文件
|
||||
*
|
||||
* @param companyFile 企业文件
|
||||
* @return 保存后的企业文件
|
||||
*/
|
||||
public CompanyFile save(CompanyFile companyFile) {
|
||||
return companyFileRepository.save(companyFile);
|
||||
}
|
||||
|
||||
public List<CompanyFile> findAll(Specification<CompanyFile> spec, Sort sort) {
|
||||
return companyFileRepository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
public void deleteById(int id) {
|
||||
companyFileRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public void delete(CompanyFile file) {
|
||||
companyFileRepository.delete(file);
|
||||
}
|
||||
|
||||
public List<CompanyFile> findByCompany(Company company) {
|
||||
return companyFileRepository.findByCompany(company);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置 公司文件
|
||||
*
|
||||
* @param company 要重置的公司对象
|
||||
* @param status 输出
|
||||
*/
|
||||
public boolean reBuildingFiles(Company company, Consumer<String> status) {
|
||||
List<CompanyFile> dbFiles = companyFileRepository.findByCompany(company);
|
||||
List<CompanyFile> retrieveFiles = new ArrayList<>();
|
||||
boolean modfied = false;
|
||||
|
||||
Map<String, CompanyFile> map = new HashMap<>();
|
||||
// 排除掉数据库中重复的
|
||||
for (CompanyFile dbFile : dbFiles) {
|
||||
String filePath = dbFile.getFilePath();
|
||||
// 没有文件信息,无效记录,删除
|
||||
if (!StringUtils.hasText(filePath)) {
|
||||
companyFileRepository.delete(dbFile);
|
||||
modfied = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 目录不存在,删除
|
||||
File dir = new File(filePath);
|
||||
if (!dir.exists()) {
|
||||
companyFileRepository.delete(dbFile);
|
||||
modfied = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
CompanyFile old = map.put(filePath, dbFile);
|
||||
// 目录有重复删除
|
||||
if (old != null) {
|
||||
companyFileRepository.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);
|
||||
}
|
||||
|
||||
// 获取所有曾用名
|
||||
for (CompanyOldName companyOldName : companyOldNameRepository.findAllByCompanyId(company.getId())) {
|
||||
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() || CompanyFileUtils.isHiddenFile(file)) {
|
||||
continue;
|
||||
}
|
||||
String filePath = file.getAbsolutePath();
|
||||
if (!map.containsKey(filePath)) {
|
||||
// 未记录
|
||||
CompanyFile filled = fillFileType(file, status);
|
||||
retrieveFiles.add(filled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status.accept("导入 " + retrieveFiles.size() + " 个文件");
|
||||
if (retrieveFiles.isEmpty()) {
|
||||
return modfied;
|
||||
}
|
||||
|
||||
// update db
|
||||
retrieveFiles.forEach(v -> v.setCompany(company));
|
||||
companyFileRepository.saveAll(retrieveFiles);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从文件名生成公司文件对象,文件已经存在公司对应的存储目录下
|
||||
*
|
||||
* @param file 文件
|
||||
* @param status 状态输出
|
||||
* @return 公司文件对象
|
||||
*/
|
||||
private CompanyFile fillFileType(File file, Consumer<String> status) {
|
||||
String fileName = file.getName();
|
||||
CompanyFile companyFile = new CompanyFile();
|
||||
companyFile.setType(CompanyFileType.General);
|
||||
companyFile.setFilePath(file.getAbsolutePath());
|
||||
fillApplyDateAndExpiringDateAbsent(file, companyFile);
|
||||
|
||||
// 天眼查 基础版企业信用报告
|
||||
if (fileName.contains(CloudTycService.TYC_ENTERPRISE_BASIC_REPORT)
|
||||
|| fileName.contains(CloudTycService.TYC_ENTERPRISE_MAJOR_REPORT)
|
||||
|| fileName.contains(CloudTycService.TYC_ENTERPRISE_ANALYSIS_REPORT)) {
|
||||
companyFile.setType(CompanyFileType.CreditReport);
|
||||
fillExpiringDateAbsent(companyFile);
|
||||
return companyFile;
|
||||
}
|
||||
|
||||
// 天眼查 企业信用信息公示报告
|
||||
if (fileName.contains(CloudTycService.TYC_ENTERPRISE_CREDIT_REPORT)) {
|
||||
companyFile.setType(CompanyFileType.CreditInfoPublicityReport);
|
||||
return companyFile;
|
||||
}
|
||||
|
||||
// 集团相关方平台 元素征信 企业征信报告
|
||||
if (fileName.contains(CloudServiceConstant.RK_VENDOR_NAME)
|
||||
&& fileName.contains(CloudRkService.ENTERPRISE_CREDIT_REPORT)) {
|
||||
companyFile.setType(CompanyFileType.CreditReport);
|
||||
fillExpiringDateAbsent(companyFile);
|
||||
return companyFile;
|
||||
}
|
||||
|
||||
// 营业执照
|
||||
if (fileName.contains(BUSINESS_LICENSE)) {
|
||||
companyFile.setType(CompanyFileType.BusinessLicense);
|
||||
return companyFile;
|
||||
}
|
||||
|
||||
// 其他企业信用报告
|
||||
if (fileName.contains(ENTERPRISE_REPORT)) {
|
||||
companyFile.setType(CompanyFileType.CreditReport);
|
||||
fillExpiringDateAbsent(companyFile);
|
||||
return companyFile;
|
||||
}
|
||||
return companyFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 补齐有效期
|
||||
*/
|
||||
private void fillExpiringDateAbsent(CompanyFile 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, CompanyFile 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 e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"parse date failure, it used to set ExpiringDate, {} from {} by Regex:{}, @{}",
|
||||
date, fileName, MyDateTimeUtils.REGEX_DATE, companyFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("parse date failure, it used to set ApplyDate, {} from {} by Regex:{}, @{}",
|
||||
date, fileName, MyDateTimeUtils.REGEX_DATE, companyFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动文件到企业目录下
|
||||
*
|
||||
* @param company 企业对象
|
||||
* @param files 要被移动的文件集合,需要从中选择需要的
|
||||
* @param status 状态输出
|
||||
*/
|
||||
public boolean retrieveFromDownloadFiles(Company company, File[] files, Consumer<String> status) {
|
||||
Map<String, File> map = new HashMap<>();
|
||||
File home = new File(company.getPath());
|
||||
map.put(company.getName(), home);
|
||||
List<CompanyFile> retrieveFiles = new ArrayList<>();
|
||||
|
||||
// 获取所有曾用名
|
||||
for (CompanyOldName companyOldName : companyOldNameRepository.findAllByCompanyId(company.getId())) {
|
||||
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;
|
||||
}
|
||||
String prefix = (i + 1) + "/" + files.length + ":";
|
||||
Consumer<String> inner = (str) -> {
|
||||
status.accept(prefix + str);
|
||||
};
|
||||
|
||||
String fileName = file.getName();
|
||||
inner.accept(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;
|
||||
}
|
||||
|
||||
CompanyFile filled = fillDownloadFileType(company, file, companyName, dir, inner);
|
||||
if (filled != null) {
|
||||
retrieveFiles.add(filled);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
status.accept("导入 " + retrieveFiles.size() + " 个文件");
|
||||
if (retrieveFiles.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// update db
|
||||
retrieveFiles.forEach(v -> v.setCompany(company));
|
||||
companyFileRepository.saveAll(retrieveFiles);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从文件名生成公司文件对象
|
||||
* 文件从下载目录中导入
|
||||
*
|
||||
* @param company 公司对象
|
||||
* @param file 导入的文件对象
|
||||
* @param companyName 公司名称
|
||||
* @param destDir 目标目录
|
||||
* @param status 状态输出
|
||||
* @return 生成的公司文件对象,如果无法转换则返回null
|
||||
*/
|
||||
private CompanyFile fillDownloadFileType(Company company, File file, String companyName, File destDir,
|
||||
Consumer<String> status) {
|
||||
String fileName = file.getName();
|
||||
// 天眼查的报告
|
||||
// 目前只有 基础版企业信用报告, 企业信用信息公示报告下载保存时的文件名中没有天眼查
|
||||
if (CloudTycService.isTycReport(fileName)) {
|
||||
CompanyFile companyFile = new CompanyFile();
|
||||
companyFile.setType(CompanyFileType.CreditReport);
|
||||
fillApplyDateAbsent(file, companyFile);
|
||||
|
||||
String destFileName = fileName;
|
||||
// 重命名 基础版企业信用报告
|
||||
for (String report : Arrays.asList(
|
||||
CloudTycService.TYC_ENTERPRISE_ANALYSIS_REPORT,
|
||||
CloudTycService.TYC_ENTERPRISE_BASIC_REPORT,
|
||||
CloudTycService.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)) {
|
||||
// 移动失败时
|
||||
status.accept(fileName + " 无法移动到 " + dest.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
|
||||
status.accept(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(CloudTycService.TYC_ENTERPRISE_CREDIT_REPORT)) {
|
||||
CompanyFile companyFile = new CompanyFile();
|
||||
companyFile.setType(CompanyFileType.CreditInfoPublicityReport);
|
||||
fillApplyDateAbsent(file, companyFile);
|
||||
File dest = new File(destDir, fileName);
|
||||
|
||||
// 移动文件
|
||||
if (!file.renameTo(dest)) {
|
||||
if (dest.exists()) {
|
||||
// 尝试删除已经存在的文件
|
||||
if (!dest.delete()) {
|
||||
status.accept("覆盖时,无法删除已存在的文件 " + dest.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
if (file.renameTo(dest)) {
|
||||
Optional<CompanyFile> one = companyFileRepository.findOne(((root, query, builder) -> {
|
||||
return builder.and(
|
||||
builder.equal(root.get("filePath"), dest.getAbsolutePath()),
|
||||
builder.equal(root.get("company"), company));
|
||||
}));
|
||||
if (one.isPresent()) {
|
||||
companyFile = one.get();
|
||||
}
|
||||
} else {
|
||||
status.accept(fileName + " 无法覆盖到 " + dest.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
status.accept(fileName + " 无法移动到 " + dest.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
status.accept(fileName + " 移动到 " + dest.getAbsolutePath());
|
||||
companyFile.setFilePath(dest.getAbsolutePath());
|
||||
|
||||
return companyFile;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当 ApplyDate 未设置时,尝试使用文件名中包含的日期
|
||||
*/
|
||||
private static void fillApplyDateAbsent(File file, CompanyFile companyFile) {
|
||||
LocalDate applyDate = companyFile.getApplyDate();
|
||||
if (applyDate != null) {
|
||||
return;
|
||||
}
|
||||
String fileName = file.getName();
|
||||
// 从文件名中提取日期
|
||||
LocalDate picked = MyDateTimeUtils.pickLocalDate(fileName);
|
||||
if (picked != null) {
|
||||
companyFile.setApplyDate(picked);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ecep.contract.ds.company.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.ds.company.repository.CompanyInvoiceInfoRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyInvoiceInfo;
|
||||
|
||||
/**
|
||||
* 公司发票信息服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "company-invoice-info")
|
||||
public class CompanyInvoiceInfoService {
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyInvoiceInfoRepository repository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public CompanyInvoiceInfo findById(int id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
|
||||
public List<CompanyInvoiceInfo> searchByCompany(Company company, String searchText) {
|
||||
Specification<CompanyInvoiceInfo> spec = (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("taxId"), "%" + searchText + "%"),
|
||||
builder.like(root.get("address"), "%" + searchText + "%"),
|
||||
builder.like(root.get("phone"), "%" + searchText + "%"),
|
||||
builder.like(root.get("bankName"), "%" + searchText + "%"),
|
||||
builder.like(root.get("bankAccount"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
|
||||
if (company != null) {
|
||||
spec = spec.and((root, query, builder) -> {
|
||||
return builder.equal(root.get("company"), company);
|
||||
});
|
||||
}
|
||||
return repository.findAll(spec, Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package com.ecep.contract.ds.company.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.company.CompanyFileUtils;
|
||||
import com.ecep.contract.ds.company.repository.CompanyOldNameRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyOldName;
|
||||
import com.ecep.contract.util.MyStringUtils;
|
||||
import com.ecep.contract.util.SpecificationUtils;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
public class CompanyOldNameService implements IEntityService<CompanyOldName> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyOldNameService.class);
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyOldNameRepository companyOldNameRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyService companyService;
|
||||
|
||||
|
||||
public CompanyOldName findById(Integer id) {
|
||||
return companyOldNameRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<CompanyOldName> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return SpecificationUtils.andWith(searchText, this::buildSearchSpecification);
|
||||
}
|
||||
|
||||
protected Specification<CompanyOldName> buildSearchSpecification(String searchText) {
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("memo"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public CompanyOldName save(CompanyOldName companyOldName) {
|
||||
return companyOldNameRepository.save(companyOldName);
|
||||
}
|
||||
|
||||
public boolean makePathAbsent(CompanyOldName companyOldName) {
|
||||
String path = companyOldName.getPath();
|
||||
if (StringUtils.hasText(path)) {
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
File dir = makePath(companyOldName);
|
||||
if (dir == null) {
|
||||
return false;
|
||||
}
|
||||
if (!dir.exists()) {
|
||||
return false;
|
||||
}
|
||||
companyOldName.setPath(dir.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
|
||||
public File makePath(CompanyOldName companyOldName) {
|
||||
String oldName = companyOldName.getName();
|
||||
File basePath = companyService.getBasePath();
|
||||
Company company = companyService.findById(companyOldName.getCompanyId());
|
||||
String district = company.getDistrict();
|
||||
if (StringUtils.hasText(district)) {
|
||||
String parentPrefix = CompanyFileUtils.getParentPrefixByDistrict(district);
|
||||
if (parentPrefix != null) {
|
||||
File parent = new File(basePath, parentPrefix);
|
||||
if (!parent.exists()) {
|
||||
if (!parent.mkdir()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
String fileName = CompanyFileUtils.escapeFileName(oldName);
|
||||
File dir = new File(parent, fileName);
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdir()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public List<CompanyOldName> findAllByName(String name) {
|
||||
return companyOldNameRepository.findAllByName(name);
|
||||
}
|
||||
|
||||
public List<CompanyOldName> findAll(Specification<CompanyOldName> spec, Sort sort) {
|
||||
return companyOldNameRepository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
public List<CompanyOldName> findAllByCompany(Company company) {
|
||||
return companyOldNameRepository.findAllByCompanyId(company.getId());
|
||||
}
|
||||
|
||||
public CompanyOldName findMatchByDate(Company company, LocalDate date) {
|
||||
List<CompanyOldName> oldNames = findAllByCompany(company);
|
||||
if (oldNames == null || oldNames.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return oldNames.stream().filter(v -> {
|
||||
if (v.getAmbiguity()) {
|
||||
return false;
|
||||
}
|
||||
if (v.getBeginDate() != null && date.isBefore(v.getBeginDate())) {
|
||||
return false;
|
||||
}
|
||||
if (v.getEndDate() != null && date.isAfter(v.getEndDate())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public void deleteById(int id) {
|
||||
companyOldNameRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public void delete(CompanyOldName entity) {
|
||||
companyOldNameRepository.delete(entity);
|
||||
}
|
||||
|
||||
public List<CompanyOldName> findAllByCompanyAndName(Company company, String oldName) {
|
||||
return companyOldNameRepository.findAllByCompanyIdAndName(company.getId(), oldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 from 的曾用名 关联到 to
|
||||
*
|
||||
* @param from from
|
||||
* @param to to
|
||||
*/
|
||||
public void resetTo(Company from, Company to) {
|
||||
// 曾用名 关联到 to
|
||||
List<CompanyOldName> list = companyOldNameRepository.findAllByCompanyId(from.getId());
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (CompanyOldName oldName : list) {
|
||||
oldName.setMemo(MyStringUtils.appendIfAbsent(oldName.getMemo(), "转自 " + from.getId()));
|
||||
oldName.setCompanyId(to.getId());
|
||||
}
|
||||
companyOldNameRepository.saveAll(list);
|
||||
}
|
||||
|
||||
public void deleteByCompany(Company company) {
|
||||
int deleted = companyOldNameRepository.deleteAllByCompanyId(company.getId());
|
||||
if (deleted > 0) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Delete {} records by company:#{}", deleted, company.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据提供的搜索文本查询公司旧名称列表。
|
||||
* <p>
|
||||
* 该函数使用JPA的Specification接口构建查询条件,查找公司旧名称中包含指定文本的记录。
|
||||
* 查询结果最多返回10条记录。
|
||||
*
|
||||
* @param searchText 用于搜索的文本,将匹配公司旧名称中包含该文本的记录。
|
||||
* @return 包含匹配的公司旧名称的列表,列表中的每个元素都是一个CompanyOldName对象。
|
||||
*/
|
||||
public List<CompanyOldName> search(String searchText) {
|
||||
return companyOldNameRepository.findAll(getSpecification(searchText), Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CompanyOldName> findAll(Specification<CompanyOldName> spec, Pageable pageable) {
|
||||
return companyOldNameRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public CompanyOldName createNew(Company company, String name, boolean ambiguity) {
|
||||
CompanyOldName companyOldName = new CompanyOldName();
|
||||
companyOldName.setCompanyId(company.getId());
|
||||
companyOldName.setName(name);
|
||||
companyOldName.setAmbiguity(ambiguity);
|
||||
return companyOldName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,607 @@
|
||||
package com.ecep.contract.ds.company.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.MyDateTimeUtils;
|
||||
import com.ecep.contract.cloud.rk.CloudRkService;
|
||||
import com.ecep.contract.cloud.tyc.CloudTycService;
|
||||
import com.ecep.contract.cloud.u8.YongYouU8Service;
|
||||
import com.ecep.contract.constant.CompanyVendorConstant;
|
||||
import com.ecep.contract.ds.company.CompanyFileUtils;
|
||||
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.other.service.SysConfService;
|
||||
import com.ecep.contract.ds.vendor.service.CompanyVendorService;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyCustomer;
|
||||
import com.ecep.contract.model.CompanyOldName;
|
||||
import com.ecep.contract.model.CompanyVendor;
|
||||
import com.ecep.contract.util.MyStringUtils;
|
||||
import com.ecep.contract.util.SpecificationUtils;
|
||||
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Path;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
/**
|
||||
* 公司服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "company")
|
||||
public class CompanyService implements IEntityService<Company> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyService.class);
|
||||
private static final String COMPANY_BASE_PATH = "company.base.path";
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyRepository companyRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private SysConfService confService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyFileService companyFileService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractService contractService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyVendorService companyVendorService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyCustomerService companyCustomerService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyOldNameService companyOldNameService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyContactService companyContactService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CloudRkService cloudRkService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CloudTycService cloudTycService;
|
||||
@Lazy
|
||||
@Autowired(required = false)
|
||||
private YongYouU8Service yongYouU8Service;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public Company findById(Integer id) {
|
||||
return companyRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'name-'+#p0")
|
||||
public Company findByName(String name) {
|
||||
return companyRepository.findFirstByName(name).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找名称是 name 的记录
|
||||
*
|
||||
* @param name 查询的公司名称
|
||||
* @return 记录列表
|
||||
*/
|
||||
public List<Company> findAllByName(String name) {
|
||||
return companyRepository.findAllByName(name);
|
||||
}
|
||||
|
||||
public Page<Company> findAll(Specification<Company> spec, Pageable pageable) {
|
||||
return companyRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找
|
||||
* 重复的删除
|
||||
*
|
||||
* @param uniscid 统一社会信用代码
|
||||
* @return 公司对象
|
||||
*/
|
||||
public Company findAndRemoveDuplicateCompanyByUniscid(String uniscid) {
|
||||
// 根据统一社会信用代码去查询
|
||||
List<Company> companies = companyRepository.findAllByUniscid(uniscid);
|
||||
if (companies.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (companies.size() == 1) {
|
||||
return companies.getFirst();
|
||||
} else {
|
||||
List<Company> result = removeDuplicatesByUniscid(companies);
|
||||
if (!result.isEmpty()) {
|
||||
return result.getFirst();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找公司,根据名称或简称查询
|
||||
* <p>
|
||||
* 1. 先按照 name 查找Company记录,如果有多个记录只保留一条,保留规则参考 #removeDuplicatesByUniscid 方法
|
||||
* 2. 第一步没有匹配到时,根据名称从曾用名中查询
|
||||
* 3. 上一步没有匹配到时,根据简称从公司数据库查询匹配简称的公司
|
||||
* 4. 上一步没有匹配到时,根据简称从曾用名中查询
|
||||
* 根据简称去查询,如果有多个记录只保留一条,保留规则参考 #removeDuplicatesByUniscid 方法
|
||||
* 重复的删除
|
||||
*
|
||||
* @param name 企业名称
|
||||
* @param abbName 别名
|
||||
* @return 公司对象
|
||||
*/
|
||||
public Company findAndRemoveDuplicateCompanyByNameOrAbbName(String name, String abbName) {
|
||||
Company updater = null;
|
||||
{
|
||||
// 根据公司全名去查询
|
||||
List<Company> companies = companyRepository.findAllByName(name);
|
||||
if (companies.isEmpty()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No record match by {}", name);
|
||||
}
|
||||
} else if (companies.size() == 1) {
|
||||
updater = companies.getFirst();
|
||||
} else {
|
||||
List<Company> result = removeDuplicatesByUniscid(companies);
|
||||
if (!result.isEmpty()) {
|
||||
updater = result.getFirst();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updater == null) {
|
||||
// 根据公司名称去曾用名中查询
|
||||
List<CompanyOldName> oldNames = companyOldNameService.findAllByName(name);
|
||||
if (!oldNames.isEmpty()) {
|
||||
CompanyOldName oldName = oldNames.getFirst();
|
||||
Optional<Company> optional = companyRepository.findById(oldName.getCompanyId());
|
||||
if (optional.isPresent()) {
|
||||
updater = optional.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updater == null && StringUtils.hasText(abbName) && !Objects.equals(abbName, name)) {
|
||||
// 根据公司全面去查询
|
||||
List<Company> companies = companyRepository.findAllByShortName(abbName);
|
||||
if (!companies.isEmpty()) {
|
||||
updater = companies.removeFirst();
|
||||
}
|
||||
|
||||
if (updater == null) {
|
||||
// 根据公司名称去曾用名中查询
|
||||
List<CompanyOldName> oldNames = companyOldNameService.findAllByName(abbName);
|
||||
if (!oldNames.isEmpty()) {
|
||||
CompanyOldName oldName = null;
|
||||
Optional<CompanyOldName> optional1 = oldNames.stream().filter(CompanyOldName::getAmbiguity)
|
||||
.findFirst();
|
||||
oldName = optional1.orElseGet(oldNames::getFirst);
|
||||
Optional<Company> optional = companyRepository.findById(oldName.getCompanyId());
|
||||
if (optional.isPresent()) {
|
||||
updater = optional.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updater;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 列表中 Uniscid 重复的
|
||||
*/
|
||||
private List<Company> removeDuplicatesByUniscid(List<Company> list) {
|
||||
List<Company> result = new ArrayList<>();
|
||||
List<Company> removes = new ArrayList<>();
|
||||
Set<String> uniqueUniscidSet = new HashSet<>();
|
||||
for (Company company : list) {
|
||||
// 名称相同后,统一社会信用编号 也相同的话,删除
|
||||
if (uniqueUniscidSet.add(company.getUniscid())) {
|
||||
// 没有记录过时
|
||||
result.add(company);
|
||||
} else {
|
||||
// 有重复时
|
||||
removes.add(company);
|
||||
}
|
||||
}
|
||||
|
||||
Company updater = result.getFirst();
|
||||
// 合并重复的
|
||||
for (Company company : removes) {
|
||||
try {
|
||||
merge(company, updater);
|
||||
} catch (Exception e) {
|
||||
logger.error("合并 {} -> {} 时发生错误:{}", company.toPrettyString(), updater.toPrettyString(), e.getMessage(),
|
||||
e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* <p>
|
||||
* 删除前需要把关联数据解除
|
||||
* <ul>
|
||||
* <li>{@link CompanyVendorService#deleteByCompany(Company)}</li>
|
||||
* <li>{@link CompanyCustomerService#deleteByCompany(Company)}</li>
|
||||
* <li>{@link CompanyOldNameService#deleteByCompany(Company)}</li>
|
||||
* <li>{@link CompanyContactService#deleteByCompany(Company)}</li>
|
||||
* <li>{@link ContractService#deleteByCompany(Company)}</li>
|
||||
* <li>{@link CompanyContactService#deleteByCompany(Company)}</li>
|
||||
* </ul>
|
||||
* 或者 把关联数据转移到其他公司
|
||||
* <ul>
|
||||
* <li>{@link CompanyVendorService#resetTo(Company, Company)}</li>
|
||||
* <li>{@link CompanyCustomerService#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>
|
||||
* <li>{@link CompanyContactService#resetTo(Company, Company)}</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @param company 要删除的公司对象
|
||||
*/
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'name-'+#p0.name")
|
||||
})
|
||||
public void delete(Company company) {
|
||||
cloudRkService.deleteByCompany(company);
|
||||
cloudTycService.deleteByCompany(company);
|
||||
yongYouU8Service.deleteByCompany(company);
|
||||
|
||||
companyOldNameService.deleteByCompany(company);
|
||||
companyContactService.deleteByCompany(company);
|
||||
// 供应商和客户
|
||||
companyVendorService.deleteByCompany(company);
|
||||
companyCustomerService.deleteByCompany(company);
|
||||
|
||||
contractService.deleteByCompany(company);
|
||||
companyContactService.deleteByCompany(company);
|
||||
|
||||
companyRepository.delete(company);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Delete Company {}", company);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并 from 到 to
|
||||
* <p>
|
||||
* 下述关联数据重设绑定到 to
|
||||
* <ol>
|
||||
* <li>曾用名</li>
|
||||
* <li>供应商</li>
|
||||
* <li>客户</li>
|
||||
* <li>合同</li>
|
||||
* <li>公司合同</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
*/
|
||||
public void merge(Company from, Company to) {
|
||||
// cloudRkService.findById(from.getId());
|
||||
cloudRkService.resetTo(from, to);
|
||||
cloudTycService.resetTo(from, to);
|
||||
yongYouU8Service.resetTo(from, to);
|
||||
|
||||
companyOldNameService.resetTo(from, to);
|
||||
companyContactService.resetTo(from, to);
|
||||
// 供应商和客户
|
||||
companyVendorService.resetTo(from, to);
|
||||
companyCustomerService.resetTo(from, to);
|
||||
|
||||
contractService.resetTo(from, to);
|
||||
companyContactService.resetTo(from, to);
|
||||
companyRepository.delete(from);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Merge {} to {}", from, to);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存实体对象,异步方法
|
||||
*
|
||||
* @param company 要保存的实体对象
|
||||
* @return 返回异步调用
|
||||
*/
|
||||
public CompletableFuture<Company> asyncSave(Company company) {
|
||||
return CompletableFuture.completedFuture(companyRepository.save(company));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存实体对象
|
||||
*
|
||||
* @param company 要保存的实体对象
|
||||
* @return 返回异步调用
|
||||
*/
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'name-'+#p0.name")
|
||||
})
|
||||
public Company save(Company company) {
|
||||
return companyRepository.save(company);
|
||||
}
|
||||
|
||||
public long count() {
|
||||
return companyRepository.count();
|
||||
}
|
||||
|
||||
public long count(Specification<Company> spec) {
|
||||
return companyRepository.count(spec);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void findAllWithStream(Consumer<Stream<Company>> consumer) {
|
||||
try (Stream<Company> stream = companyRepository.findAllAsStream()) {
|
||||
consumer.accept(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public File getVendorBasePath() {
|
||||
return new File(confService.getString(CompanyVendorConstant.KEY_BASE_PATH));
|
||||
}
|
||||
|
||||
public File getCustomerBasePath() {
|
||||
return new File(confService.getString(CompanyCustomerService.KEY_BASE_PATH));
|
||||
}
|
||||
|
||||
public File getBasePath() {
|
||||
return new File(confService.getString(COMPANY_BASE_PATH));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建公司目录,如果公司目录未设置,或者未存在
|
||||
*
|
||||
* @param company 要创建目录的公司对象
|
||||
* @return 是否创建了目录
|
||||
*/
|
||||
public boolean makePathAbsent(Company company) {
|
||||
String path = company.getPath();
|
||||
if (StringUtils.hasText(path)) {
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
File dir = makePath(company);
|
||||
if (dir == null) {
|
||||
return false;
|
||||
}
|
||||
if (!dir.exists()) {
|
||||
return false;
|
||||
}
|
||||
company.setPath(dir.getAbsolutePath());
|
||||
company.setPathExist(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建企业目录
|
||||
*
|
||||
* @param company 要创建的企业对象
|
||||
* @return 目录
|
||||
*/
|
||||
public File makePath(Company company) {
|
||||
File basePath = getBasePath();
|
||||
if (!basePath.exists()) {
|
||||
return null;
|
||||
}
|
||||
String companyName = company.getName();
|
||||
String district = company.getDistrict();
|
||||
if (StringUtils.hasText(district)) {
|
||||
String parentPrefix = CompanyFileUtils.getParentPrefixByDistrict(district);
|
||||
if (parentPrefix != null) {
|
||||
File parent = new File(basePath, parentPrefix);
|
||||
if (!parent.exists()) {
|
||||
if (!parent.mkdir()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
String fileName = CompanyFileUtils.escapeFileName(companyName);
|
||||
File dir = new File(parent, fileName);
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdir()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动文件到企业目录下
|
||||
*
|
||||
* @param company 企业对象
|
||||
* @param files 要被移动的文件集合,需要从中选择需要的
|
||||
* @param status 状态输出
|
||||
*/
|
||||
public boolean retrieveFromDownloadFiles(Company company, File[] files, Consumer<String> status) {
|
||||
//
|
||||
boolean companyChanged = makePathAbsent(company);
|
||||
|
||||
if (!StringUtils.hasText(company.getPath())) {
|
||||
// fixed 要退出,需要保存
|
||||
if (companyChanged) {
|
||||
save(company);
|
||||
}
|
||||
status.accept("存储目录未设置,请检查");
|
||||
return false;
|
||||
}
|
||||
|
||||
File home = new File(company.getPath());
|
||||
if (!home.exists()) {
|
||||
// fixed 要退出,需要保存
|
||||
if (companyChanged) {
|
||||
company = save(company);
|
||||
}
|
||||
status.accept(company.getPath() + " 不存在,无法访问,请检查或者修改");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean retrieved = companyFileService.retrieveFromDownloadFiles(company, files, status);
|
||||
if (companyChanged) {
|
||||
save(company);
|
||||
}
|
||||
return retrieved;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证企业状态
|
||||
*
|
||||
* @param company 要验证的公司
|
||||
* @param verifyDate 验证日期
|
||||
* @param status 状态输出
|
||||
*/
|
||||
public void verifyEnterpriseStatus(Company company, LocalDate verifyDate, Consumer<String> status) {
|
||||
// 检查营业状态
|
||||
String entStatus = company.getEntStatus();
|
||||
if (StringUtils.hasText(entStatus)) {
|
||||
if (entStatus.contains("注销")) {
|
||||
LocalDate end = company.getOperationPeriodEnd();
|
||||
LocalDate begin = company.getOperationPeriodBegin();
|
||||
if (begin == null || end == null) {
|
||||
// 注销时间未知,无法判断是否在 verifyDate 之后注销
|
||||
status.accept("营业状态异常:" + entStatus);
|
||||
} else {
|
||||
if (!MyDateTimeUtils.dateValidFilter(verifyDate, begin, end, 0)) {
|
||||
status.accept("营业状态异常:" + entStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
status.accept("营业状态异常:未设置");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<Company> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
// 判断是否全是数字
|
||||
boolean isAllDigit = MyStringUtils.isAllDigit(searchText);
|
||||
if (isAllDigit) {
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("id").as(String.class), "%" + searchText + "%"),
|
||||
builder.like(root.get("uniscid"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
|
||||
Specification<Company> spec = null;
|
||||
Set<Integer> idSet = companyOldNameService.search(searchText).stream().map(CompanyOldName::getCompanyId)
|
||||
.collect(Collectors.toSet());
|
||||
if (!idSet.isEmpty()) {
|
||||
spec = SpecificationUtils.or(spec, (root, query, builder) -> {
|
||||
return root.get("id").in(idSet);
|
||||
});
|
||||
}
|
||||
|
||||
List<CompanyVendor> searchedVendors = companyVendorService.search(searchText);
|
||||
if (!searchedVendors.isEmpty()) {
|
||||
spec = SpecificationUtils.or(spec, (root, query, builder) -> {
|
||||
return builder.in(root.get("id")).value(searchedVendors.stream()
|
||||
.map(CompanyVendor::getCompany)
|
||||
.filter(Objects::nonNull)
|
||||
.map(Company::getId)
|
||||
.collect(Collectors.toSet()));
|
||||
});
|
||||
}
|
||||
|
||||
List<CompanyCustomer> searchedCustomers = companyCustomerService.search(searchText);
|
||||
if (!searchedCustomers.isEmpty()) {
|
||||
spec = SpecificationUtils.or(spec, (root, query, builder) -> {
|
||||
return builder.in(root.get("id")).value(searchedCustomers.stream()
|
||||
.map(CompanyCustomer::getCompany)
|
||||
.filter(Objects::nonNull)
|
||||
.map(Company::getId)
|
||||
.collect(Collectors.toSet()));
|
||||
});
|
||||
}
|
||||
|
||||
return SpecificationUtils.or(spec, SpecificationUtils.andWith(searchText, this::buildSearchSpecification));
|
||||
}
|
||||
|
||||
protected Specification<Company> buildSearchSpecification(String searchText) {
|
||||
return (root, query, builder) -> buildSearchPredicate(searchText, root, query, builder);
|
||||
}
|
||||
|
||||
public Predicate buildSearchPredicate(String searchText, Path<Company> root, @Nullable CriteriaQuery<?> query,
|
||||
CriteriaBuilder builder) {
|
||||
return builder.or(
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("shortName"), "%" + searchText + "%"),
|
||||
builder.like(root.get("uniscid"), "%" + searchText + "%"),
|
||||
builder.like(root.get("legalRepresentative"), "%" + searchText + "%"),
|
||||
builder.like(root.get("regAddr"), "%" + searchText + "%"),
|
||||
builder.like(root.get("address"), "%" + searchText + "%"),
|
||||
builder.like(root.get("memo"), "%" + searchText + "%"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检索企业
|
||||
* 企业名称中模糊搜索
|
||||
*
|
||||
* @param searchText 搜索文本
|
||||
* @return 企业列表,返回前10个企业
|
||||
*/
|
||||
public List<Company> search(String searchText) {
|
||||
Specification<Company> spec = getSpecification(searchText);
|
||||
return companyRepository.findAll(spec, Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
|
||||
public Company createNewCompany(String name) {
|
||||
Company company = new Company();
|
||||
company.setName(name);
|
||||
company.setCreated(LocalDate.now());
|
||||
return company;
|
||||
}
|
||||
|
||||
public List<String> getAllNames(Company company) {
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add(company.getName());
|
||||
companyOldNameService.findAllByCompany(company).forEach(oldName -> {
|
||||
// 歧义的曾用名不采用
|
||||
if (oldName.getAmbiguity()) {
|
||||
return;
|
||||
}
|
||||
list.add(oldName.getName());
|
||||
});
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.ecep.contract.ds.company.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.company.repository.InvoiceRepository;
|
||||
import com.ecep.contract.model.Invoice;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "invoice")
|
||||
public class InvoiceService implements IEntityService<Invoice> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(InvoiceService.class);
|
||||
|
||||
@Autowired
|
||||
private InvoiceRepository repository;
|
||||
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public Invoice findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<Invoice> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("code"), "%" + searchText + "%"),
|
||||
builder.like(root.get("description"), "%" + searchText + "%")
|
||||
);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Invoice> findAll(Specification<Invoice> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@CacheEvict(key = "#p0.id")
|
||||
public void delete(Invoice entity) {
|
||||
repository.delete(entity);
|
||||
}
|
||||
|
||||
public List<Invoice> findAll(Specification<Invoice> spec, Sort by) {
|
||||
return repository.findAll(spec, by);
|
||||
}
|
||||
|
||||
public Invoice findByCode(String invoiceNumber) {
|
||||
return repository.findByCode(invoiceNumber);
|
||||
}
|
||||
|
||||
@CacheEvict(key = "#p0.id")
|
||||
public Invoice save(Invoice invoice) {
|
||||
return repository.save(invoice);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package com.ecep.contract.ds.company.tasker;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.cloud.rk.CloudRkService;
|
||||
import com.ecep.contract.cloud.rk.ctx.CloudRkCtx;
|
||||
import com.ecep.contract.cloud.tyc.CloudTycService;
|
||||
import com.ecep.contract.cloud.u8.YongYouU8Service;
|
||||
import com.ecep.contract.cloud.u8.ctx.CompanyCtx;
|
||||
import com.ecep.contract.cloud.u8.ctx.ContractCtx;
|
||||
import com.ecep.contract.cloud.u8.ctx.CustomerCtx;
|
||||
import com.ecep.contract.cloud.u8.ctx.VendorCtx;
|
||||
import com.ecep.contract.constant.CloudServiceConstant;
|
||||
import com.ecep.contract.model.CloudRk;
|
||||
import com.ecep.contract.model.CloudYu;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.ui.Tasker;
|
||||
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 合并更新
|
||||
*/
|
||||
public class CompanyCompositeUpdateTasker extends Tasker<Object> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyCompositeUpdateTasker.class);
|
||||
|
||||
CloudRkCtx cloudRkCtx = new CloudRkCtx();
|
||||
|
||||
@Setter
|
||||
private CloudRkService cloudRkService;
|
||||
@Setter
|
||||
private CloudTycService cloudTycService;
|
||||
@Setter
|
||||
private YongYouU8Service yongYouU8Service;
|
||||
@Setter
|
||||
private Company company;
|
||||
|
||||
@Override
|
||||
protected Object execute(MessageHolder holder) throws Exception {
|
||||
|
||||
updateProgress(0.1, 1);
|
||||
syncFromCloudRk(holder);
|
||||
updateProgress(0.3, 1);
|
||||
syncFromYongYouU8(holder);
|
||||
updateProgress(0.6, 1);
|
||||
syncFromCloudTyc(holder);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void syncFromCloudRk(MessageHolder holder) {
|
||||
holder.debug("1. 从 " + CloudServiceConstant.RK_NAME + " 更新...");
|
||||
try {
|
||||
cloudRkService = getBean(CloudRkService.class);
|
||||
} catch (BeansException e) {
|
||||
holder.warn("未启用 " + CloudServiceConstant.RK_NAME + " 服务");
|
||||
return;
|
||||
}
|
||||
CloudRk cloudRk = cloudRkService.getOrCreateCloudRk(company);
|
||||
if (cloudRk == null) {
|
||||
holder.error("无法创建或获取 CloudRk 对象");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
cloudRkCtx.setCloudRkService(cloudRkService);
|
||||
if (cloudRkCtx.syncCompany(company, cloudRk, holder)) {
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
cloudRk.setDescription(e.getMessage());
|
||||
} finally {
|
||||
cloudRk.setLatestUpdate(Instant.now());
|
||||
cloudRkService.save(cloudRk);
|
||||
}
|
||||
}
|
||||
|
||||
private void syncFromYongYouU8(MessageHolder holder) {
|
||||
holder.debug("2. 从 " + CloudServiceConstant.U8_NAME + " 更新...");
|
||||
try {
|
||||
yongYouU8Service = getBean(YongYouU8Service.class);
|
||||
} catch (BeansException e) {
|
||||
holder.warn("未启用 " + CloudServiceConstant.U8_NAME + " 服务");
|
||||
return;
|
||||
}
|
||||
|
||||
CloudYu cloudYu = yongYouU8Service.getOrCreateCloudYu(company);
|
||||
if (cloudYu == null) {
|
||||
holder.error("无法创建或获取 CloudYu 对象");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
CompanyCtx companyCtx = new CompanyCtx();
|
||||
yongYouU8Service.initialize(companyCtx);
|
||||
if (companyCtx.syncCompany(company, holder)) {
|
||||
holder.info("更新");
|
||||
}
|
||||
|
||||
VendorCtx vendorCtx = new VendorCtx();
|
||||
yongYouU8Service.initialize(vendorCtx);
|
||||
vendorCtx.setCompanyCtx(companyCtx);
|
||||
if (vendorCtx.syncVendor(company, holder)) {
|
||||
cloudYu.setVendorUpdateDate(LocalDate.now());
|
||||
}
|
||||
|
||||
CustomerCtx customerCtx = new CustomerCtx();
|
||||
yongYouU8Service.initialize(customerCtx);
|
||||
customerCtx.setCompanyCtx(companyCtx);
|
||||
if (customerCtx.syncCustomer(company, holder)) {
|
||||
cloudYu.setCustomerUpdateDate(LocalDate.now());
|
||||
}
|
||||
|
||||
ContractCtx contractCtx = new ContractCtx();
|
||||
yongYouU8Service.initialize(contractCtx);
|
||||
contractCtx.syncContract(company, holder);
|
||||
|
||||
cloudYu.setCloudLatest(Instant.now());
|
||||
cloudYu.setExceptionMessage("");
|
||||
} catch (Exception e) {
|
||||
String message = e.getMessage();
|
||||
holder.error("同步过程中发生错误: " + message);
|
||||
// 保留255个字符
|
||||
if (message.length() > 255) {
|
||||
message = message.substring(0, 255);
|
||||
}
|
||||
cloudYu.setExceptionMessage(message);
|
||||
} finally {
|
||||
cloudYu.setLatestUpdate(Instant.now());
|
||||
yongYouU8Service.save(cloudYu);
|
||||
}
|
||||
}
|
||||
|
||||
private void syncFromCloudTyc(MessageHolder holder) {
|
||||
holder.debug("3. 从 " + CloudServiceConstant.TYC_NAME + " 更新...");
|
||||
try {
|
||||
cloudTycService = getBean(CloudTycService.class);
|
||||
} catch (BeansException e) {
|
||||
holder.warn("未启用 " + CloudServiceConstant.TYC_NAME + " 服务");
|
||||
return;
|
||||
}
|
||||
cloudTycService.syncCompany(company, holder);
|
||||
updateProgress(1, 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.ecep.contract.ds.company.tasker;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.ds.company.service.CompanyFileService;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.ui.Tasker;
|
||||
|
||||
/**
|
||||
* 对所有公司的文件进行重置
|
||||
*/
|
||||
public class CompanyFilesRebuildTasker extends Tasker<Object> {
|
||||
private CompanyFileService companyFileService;
|
||||
|
||||
public CompanyFilesRebuildTasker() {
|
||||
updateTitle("合同文件重置");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object execute(MessageHolder holder) throws Exception {
|
||||
Pageable pageRequest = PageRequest.ofSize(200);
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
Specification<Company> spec = null;
|
||||
// Specification<Contract> spec = (root, query, cb) -> {
|
||||
// return cb.greaterThan(root.get("created"), Instant.now().minusSeconds(TimeUnit.DAYS.toSeconds(360)));
|
||||
// };
|
||||
updateTitle("遍历所有公司,对每个可以公司的文件进行“重置”操作");
|
||||
long total = getCompanyService().count(spec);
|
||||
while (true) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Page<Company> page = getCompanyService().findAll(spec, pageRequest);
|
||||
if (page.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (Company company : page) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
String prefix = counter.get() + " / " + total + "> " + company.getName() + " #" + company.getId() + "> ";
|
||||
getCompanyFileService().reBuildingFiles(company, holder.sub(prefix)::info);
|
||||
|
||||
updateProgress(counter.incrementAndGet(), total);
|
||||
}
|
||||
if (!page.hasNext()) {
|
||||
break;
|
||||
}
|
||||
pageRequest = page.nextPageable();
|
||||
}
|
||||
|
||||
return super.call();
|
||||
}
|
||||
|
||||
|
||||
private CompanyFileService getCompanyFileService() {
|
||||
if (companyFileService == null) {
|
||||
companyFileService = getBean(CompanyFileService.class);
|
||||
}
|
||||
return companyFileService;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.ecep.contract.ds.company.tasker;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.ds.company.service.CompanyService;
|
||||
import com.ecep.contract.ds.contract.tasker.ContractVerifyComm;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.ui.Tasker;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class CompanyVerifyTasker extends Tasker<Object> {
|
||||
@Setter
|
||||
private CompanyService companyService;
|
||||
@Getter
|
||||
@Setter
|
||||
private Company company;
|
||||
|
||||
|
||||
ContractVerifyComm comm = new ContractVerifyComm();
|
||||
AtomicBoolean verified = new AtomicBoolean(true);
|
||||
|
||||
public CompanyService getCompanyService() {
|
||||
if (companyService == null) {
|
||||
companyService = getBean(CompanyService.class);
|
||||
}
|
||||
return companyService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
comm.setVerifyCompanyPath(false);
|
||||
comm.setVerifyCompanyStatus(false);
|
||||
comm.setVerifyCompanyCredit(false);
|
||||
return execute(new MessageHolderImpl() {
|
||||
@Override
|
||||
public void addMessage(Level level, String message) {
|
||||
super.addMessage(level, message);
|
||||
if (level.intValue() > Level.INFO.intValue()) {
|
||||
verified.set(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object execute(MessageHolder holder) throws Exception {
|
||||
updateTitle("验证企业是否符合合规要求");
|
||||
|
||||
verify(company, holder);
|
||||
|
||||
if (verified.get()) {
|
||||
updateMessage(Level.CONFIG, "合规验证通过");
|
||||
} else {
|
||||
updateMessage(Level.SEVERE, "合规验证不通过");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 核验公司名下的所有合同
|
||||
*
|
||||
* @param company 公司
|
||||
* @param holder 输出
|
||||
*/
|
||||
private void verify(Company company, MessageHolder holder) {
|
||||
LocalDate now = LocalDate.now();
|
||||
getCompanyService().verifyEnterpriseStatus(company, now, holder::info);
|
||||
|
||||
// 验证所有的合同
|
||||
List<Contract> list = comm.getContractService().findAllByCompany(company);
|
||||
if (list.isEmpty()) {
|
||||
holder.debug("!没有相关合同!");
|
||||
return;
|
||||
}
|
||||
holder.debug("检索到相关合同 " + list.size() + " 个");
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
long total = list.size();
|
||||
for (Contract contract : list) {
|
||||
holder.debug("核验合同:" + contract.getCode() + ", " + contract.getName());
|
||||
comm.verify(company, contract, holder.sub("-- "));
|
||||
updateProgress(counter.incrementAndGet(), total);
|
||||
}
|
||||
updateProgress(1, 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ecep.contract.ds.contract;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.ecep.contract.ds.contract.service.ContractService;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.util.EntityStringConverter;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
public class ContractStringConverter extends EntityStringConverter<Contract> {
|
||||
@Lazy
|
||||
@Autowired
|
||||
ContractService service;
|
||||
|
||||
public ContractStringConverter() {
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
setInitialized(project -> service.findById(project.getId()));
|
||||
setSuggestion(service::search);
|
||||
// TODO 按名称找出,容易出问题
|
||||
setFromString(service::findByName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# drop table if exists CONTRACT_COST;
|
||||
|
||||
create table if not exists PROJECT_COST
|
||||
(
|
||||
ID int auto_increment
|
||||
primary key,
|
||||
CONTRACT_ID int null comment '合同编号',
|
||||
PROJECT_ID int null comment '项目编号',
|
||||
APPLY_DATE date null comment '申请日期',
|
||||
STANDARD_CONTRACT_TEXT bit default b'0' not null comment '是否是标准合同文本',
|
||||
STANDARD_PAY_WAY bit default b'0' not null comment '是否是标准付款方式',
|
||||
NO_STANDARD_PAY_WAY_TEXT varchar(255) null comment '非标准付款方式文本',
|
||||
NO_STANDARD_CONTRACT_TEXT varchar(255) null comment '非标准合同文本',
|
||||
ON_SITE_POSITION_FEE float default 0 not null comment '现场就位费',
|
||||
ON_SITE_SERVICE_FEE float default 0 not null comment '现场服务费',
|
||||
ASSEMBLY_SERVICE_FEE float default 0 not null comment '装机服务费',
|
||||
TECHNICAL_SERVICE_FEE float default 0 not null comment '技术服务费',
|
||||
BID_SERVICE_FEE float default 0 not null comment '投标服务费',
|
||||
FREIGHT_COST float default 0 not null comment '运费',
|
||||
GUARANTEE_LETTER_FEE float default 0 not null comment '保函费',
|
||||
TAX_AND_SURCHARGES float default 0 not null comment '营业税及附加费',
|
||||
GROSS_PROFIT_MARGIN double default 0 not null comment '毛利率',
|
||||
IN_EXCLUSIVE_TAX_AMOUNT double default 0 not null comment '不含税进项总金额',
|
||||
IN_QUANTITY double default 0 not null comment '进项总数',
|
||||
IN_TAX_AMOUNT double default 0 not null comment '含税进项总金额',
|
||||
OUT_EXCLUSIVE_TAX_AMOUNT double default 0 not null comment '不含税出项总金额',
|
||||
OUT_QUANTITY double default 0 not null comment '出项总数',
|
||||
OUT_TAX_AMOUNT double default 0 not null comment '含税出项总金额',
|
||||
constraint CONTRACT_COST_CONTRACT_ID_fk
|
||||
foreign key (CONTRACT_ID) references CONTRACT (ID),
|
||||
constraint PROJECT_COST_PROJECT_ID_fk
|
||||
foreign key (PROJECT_ID) references PROJECT (ID)
|
||||
|
||||
)
|
||||
comment '项目的成本';
|
||||
|
||||
|
||||
/***
|
||||
转换为项目成本
|
||||
*/
|
||||
|
||||
select A.ID, A.PROJECT_ID,C.ID, P.ID from PROJECT_COST as A left join CONTRACT as C on A.CONTRACT_ID = C.ID left join PROJECT as P on C.PROJECT_ID = P.ID
|
||||
|
||||
|
||||
select pc1_0.ID,pc1_0.APPLICANT_ID,pc1_0.APPLY_DATE,pc1_0.ASSEMBLY_SERVICE_FEE,pc1_0.AUTHORIZER_FILE,pc1_0.AUTHORIZER_DATE,pc1_0.AUTHORIZER_ID,pc1_0.BID_SERVICE_FEE,pc1_0.CONTRACT_ID,pc1_0.DESCRIPTION,pc1_0.FREIGHT_COST,pc1_0.GROSS_PROFIT_MARGIN,pc1_0.GUARANTEE_LETTER_FEE,pc1_0.IMPORT_LOCK,pc1_0.IN_EXCLUSIVE_TAX_AMOUNT,pc1_0.IN_QUANTITY,pc1_0.IN_TAX_AMOUNT,pc1_0.NO_STANDARD_CONTRACT_TEXT,pc1_0.NO_STANDARD_PAY_WAY_TEXT,pc1_0.ON_SITE_SERVICE_FEE,pc1_0.OUT_EXCLUSIVE_TAX_AMOUNT,pc1_0.OUT_QUANTITY,pc1_0.OUT_TAX_AMOUNT,pc1_0.PROJECT_ID,pc1_0.STAMP_TAX,pc1_0.STAMP_TAX_FEE,pc1_0.STANDARD_CONTRACT_TEXT,pc1_0.STANDARD_PAY_WAY,pc1_0.TAX_AND_SURCHARGES,pc1_0.TAX_AND_SURCHARGES_FEE,pc1_0.TECHNICAL_SERVICE_FEE,pc1_0.VER
|
||||
from PROJECT_COST pc1_0 where pc1_0.DESCRIPTION like ? escape '' and pc1_0.PROJECT_ID=274
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
CREATE TABLE IF NOT EXISTS CONTRACT_COST_ITEM
|
||||
(
|
||||
ID INT AUTO_INCREMENT NOT NULL,
|
||||
COST_ID INT NULL comment '合同成本id',
|
||||
TITLE VARCHAR(255) NULL comment '名称',
|
||||
SPECIFICATION VARCHAR(255) NULL comment '规格',
|
||||
UNIT VARCHAR(255) NULL comment '单位',
|
||||
IN_EX_TAX_PRICE double default 0 not null comment '不含税进项单价',
|
||||
IN_TAX_RATE double default 0 not null comment '进项税率',
|
||||
IN_TAX_PRICE double default 0 not null comment '不含税进项总价',
|
||||
IN_QUANTITY double default 0 not null comment '进项数量',
|
||||
OUT_EX_TAX_PRICE double default 0 not null comment '不含税出项单价',
|
||||
OUT_TAX_RATE double default 0 not null comment '出项税率',
|
||||
OUT_TAX_PRICE double default 0 not null comment '不含税出项总价',
|
||||
OUT_QUANTITY double default 0 not null comment '出项数量',
|
||||
REMARK VARCHAR(255) NULL comment '备注',
|
||||
CREATE_TIME DATETIME NULL comment '创建时间',
|
||||
CREATE_BY INT NULL comment '创建人',
|
||||
UPDATE_TIME DATETIME NULL comment '更新时间',
|
||||
UPDATE_BY INT NULL comment '更新人',
|
||||
CONSTRAINT pk_contract_cost_item PRIMARY KEY (ID)
|
||||
);
|
||||
|
||||
ALTER TABLE PROJECT_COST_ITEM
|
||||
ADD CONSTRAINT FK_CONTRACT_COST_ITEM_ON_COST FOREIGN KEY (COST_ID) REFERENCES PROJECT_COST (ID);
|
||||
|
||||
ALTER TABLE PROJECT_COST_ITEM
|
||||
ADD CONSTRAINT FK_CONTRACT_COST_ITEM_ON_CREATE_BY FOREIGN KEY (CREATE_BY) REFERENCES EMPLOYEE (ID);
|
||||
|
||||
ALTER TABLE PROJECT_COST_ITEM
|
||||
ADD CONSTRAINT FK_CONTRACT_COST_ITEM_ON_UPDATE_BY FOREIGN KEY (UPDATE_BY) REFERENCES EMPLOYEE (ID);
|
||||
@@ -0,0 +1,76 @@
|
||||
create table SALES_BILL_VOUCHER
|
||||
(
|
||||
ID int auto_increment
|
||||
primary key,
|
||||
CODE varchar(255) null,
|
||||
DESCRIPTION text null,
|
||||
EMPLOYEE_ID int null,
|
||||
MAKER_ID int null,
|
||||
MAKER_DATE datetime null,
|
||||
VERIFIER_ID int null,
|
||||
MODIFY_DATE datetime null,
|
||||
VERIFIER_DATE datetime null,
|
||||
REF_ID int default 0 not null,
|
||||
COMPANY_ID int null,
|
||||
constraint SALES_BILL_VOUCHER_COMPANY_ID_fk
|
||||
foreign key (COMPANY_ID) references COMPANY (ID)
|
||||
on delete set null,
|
||||
constraint SALES_BILL_VOUCHER_EMPLOYEE_ID_fk
|
||||
foreign key (MAKER_ID) references EMPLOYEE (ID)
|
||||
on delete set null,
|
||||
constraint SALES_BILL_VOUCHER_EMPLOYEE_ID_fk_2
|
||||
foreign key (VERIFIER_ID) references EMPLOYEE (ID)
|
||||
on delete set null,
|
||||
constraint SALES_BILL_VOUCHER_EMPLOYEE_ID_fk_3
|
||||
foreign key (EMPLOYEE_ID) references EMPLOYEE (ID)
|
||||
on delete set null
|
||||
);
|
||||
|
||||
create table SALES_BILL_VOUCHER_ITEM
|
||||
(
|
||||
ID int auto_increment
|
||||
primary key,
|
||||
REF_ID int default 0 not null,
|
||||
VOUCHER_ID int null,
|
||||
INVENTORY_ID int null,
|
||||
DESCRIPTION text null,
|
||||
QUANTITY double default 0 not null,
|
||||
PRICE double default 0 not null,
|
||||
constraint SALES_BILL_VOUCHER_ITEM_INVENTORY_ID_fk
|
||||
foreign key (INVENTORY_ID) references INVENTORY (ID)
|
||||
on delete set null,
|
||||
constraint SALES_BILL_VOUCHER_ITEM_SALES_BILL_VOUCHER_ID_fk
|
||||
foreign key (VOUCHER_ID) references SALES_BILL_VOUCHER (ID)
|
||||
on delete cascade
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* 获取采购单的采购单
|
||||
*/
|
||||
select V.*
|
||||
from PURCHASE_BILL_VOUCHER as V
|
||||
join (select distinct VI.VOUCHER_ID
|
||||
from PURCHASE_BILL_VOUCHER_ITEM as VI
|
||||
left join PURCHASE_ORDER_ITEM as OI on VI.PURCHASE_ORDER_ITEM_ID = OI.ID
|
||||
where ORDER_ID = 159) as U on V.ID = U.VOUCHER_ID;
|
||||
/**
|
||||
* 获取采购单的采购单
|
||||
*/
|
||||
select pbv1_0.ID,
|
||||
pbv1_0.CODE,
|
||||
pbv1_0.COMPANY_ID,
|
||||
pbv1_0.DESCRIPTION,
|
||||
pbv1_0.EMPLOYEE_ID,
|
||||
pbv1_0.INVOICE_ID,
|
||||
pbv1_0.MAKER_ID,
|
||||
pbv1_0.MAKER_DATE,
|
||||
pbv1_0.MODIFY_DATE,
|
||||
pbv1_0.REF_ID,
|
||||
pbv1_0.VERIFIER_ID,
|
||||
pbv1_0.VERIFIER_DATE
|
||||
from PURCHASE_BILL_VOUCHER pbv1_0
|
||||
where pbv1_0.ID in ((select distinct pbvi1_0.VOUCHER_ID
|
||||
from PURCHASE_BILL_VOUCHER_ITEM pbvi1_0
|
||||
left join PURCHASE_ORDER_ITEM oi1_0 on oi1_0.ID = pbvi1_0.PURCHASE_ORDER_ITEM_ID
|
||||
where oi1_0.ORDER_ID = ?));
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.ContractBidVendor;
|
||||
|
||||
@Repository
|
||||
public interface ContractBidVendorRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<ContractBidVendor, Integer>, PagingAndSortingRepository<ContractBidVendor, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<ContractBidVendor, Integer>, JpaSpecificationExecutor<ContractBidVendor> {
|
||||
|
||||
List<ContractBidVendor> findByContractId(Integer contractId);
|
||||
|
||||
List<ContractBidVendor> findByContractIdAndCompanyId(Integer contractId, Integer companyId);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.ContractCatalog;
|
||||
|
||||
@Repository
|
||||
public interface ContractCatalogRepository extends MyRepository<ContractCatalog, Integer> {
|
||||
|
||||
Optional<ContractCatalog> findByCode(String code);
|
||||
|
||||
Optional<ContractCatalog> findByName(String name);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ContractFileType;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.ContractFile;
|
||||
|
||||
@Repository
|
||||
public interface ContractFileRepository extends JpaRepository<ContractFile, Integer>, JpaSpecificationExecutor<ContractFile> {
|
||||
List<ContractFile> findByContract(Contract contract);
|
||||
|
||||
List<ContractFile> findAllByContract(Contract contract);
|
||||
|
||||
List<ContractFile> findAllByContractAndType(Contract contract, ContractFileType type);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ContractFileType;
|
||||
import com.ecep.contract.ds.other.repository.BaseEnumEntityRepository;
|
||||
import com.ecep.contract.model.ContractFileTypeLocal;
|
||||
|
||||
@Repository
|
||||
public interface ContractFileTypeLocalRepository
|
||||
extends BaseEnumEntityRepository<ContractFileType, ContractFileTypeLocal, Integer> {
|
||||
@Override
|
||||
default ContractFileType[] getEnumConstants() {
|
||||
return ContractFileType.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
default ContractFileTypeLocal newEntity() {
|
||||
return new ContractFileTypeLocal();
|
||||
}
|
||||
|
||||
ContractFileTypeLocal findByTypeAndLang(ContractFileType type, String lang);
|
||||
|
||||
default ContractFileTypeLocal getCompleteByTypeAndLang(ContractFileType type, String lang) {
|
||||
ContractFileTypeLocal v = findByTypeAndLang(type, lang);
|
||||
if (v == null) {
|
||||
v = newEntity();
|
||||
v.setType(type);
|
||||
v.setLang(lang);
|
||||
v.setValue(type.name());
|
||||
v = save(v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.ContractGroup;
|
||||
|
||||
@Repository
|
||||
public interface ContractGroupRepository extends MyRepository<ContractGroup, Integer> {
|
||||
|
||||
Optional<ContractGroup> findByCode(String code);
|
||||
|
||||
Optional<ContractGroup> findFirstByNameContains(String name);
|
||||
|
||||
Optional<ContractGroup> findByName(String name);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.ContractItem;
|
||||
|
||||
@Repository
|
||||
public interface ContractItemRepository extends JpaRepository<ContractItem, Integer>, JpaSpecificationExecutor<ContractItem> {
|
||||
|
||||
List<ContractItem> findByContractId(int contractId);
|
||||
|
||||
List<ContractItem> findByInventoryId(int inventoryId);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.ContractKind;
|
||||
|
||||
@Repository
|
||||
public interface ContractKindRepository extends MyRepository<ContractKind, Integer> {
|
||||
Optional<ContractKind> findByCode(String code);
|
||||
|
||||
Optional<ContractKind> findByName(String name);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.ContractPayPlan;
|
||||
|
||||
@Repository
|
||||
public interface ContractPayPlanRepository extends MyRepository<ContractPayPlan, Integer> {
|
||||
|
||||
List<ContractPayPlan> findAllByContractId(Integer contractId);
|
||||
|
||||
List<ContractPayPlan> findAllByContract(Contract contract);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ContractPayWay;
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Contract;
|
||||
|
||||
@Repository
|
||||
public interface ContractRepository extends MyRepository<Contract, Integer> {
|
||||
|
||||
Optional<Contract> findByGuid(String guid);
|
||||
|
||||
Optional<Contract> findByProjectIdAndPayWay(int projectId, ContractPayWay payWay);
|
||||
|
||||
List<Contract> findAllByProjectIdAndPayWay(int projectId, ContractPayWay payWay);
|
||||
|
||||
Optional<Contract> findByCode(String code);
|
||||
|
||||
int deleteAllByCompanyId(int companyId);
|
||||
|
||||
List<Contract> findByCodeStartsWith(String code);
|
||||
|
||||
List<Contract> findByPayWayAndCodeStartsWith(ContractPayWay payWay, String code);
|
||||
|
||||
List<Contract> findAllByParentCode(String parentCode);
|
||||
|
||||
Optional<Contract> findFirstByName(String name);
|
||||
|
||||
List<Contract> findAllByCompanyId(int companyId);
|
||||
|
||||
List<Contract> findAllByProjectId(int projectId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.ContractType;
|
||||
|
||||
@Repository
|
||||
public interface ContractTypeRepository extends MyRepository<ContractType, Integer> {
|
||||
|
||||
Optional<ContractType> findByCode(String code);
|
||||
|
||||
Optional<ContractType> findByName(String name);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.ExtendVendorInfo;
|
||||
|
||||
@Repository
|
||||
public interface ExtendVendorInfoRepository extends
|
||||
// JPA interfaces
|
||||
JpaRepository<ExtendVendorInfo, Integer>, JpaSpecificationExecutor<ExtendVendorInfo> {
|
||||
|
||||
Optional<ExtendVendorInfo> findByContractId(Integer contractId);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.PurchaseBillVoucherItem;
|
||||
|
||||
@Repository
|
||||
public interface PurchaseBillVoucherItemRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<PurchaseBillVoucherItem, Integer>,
|
||||
PagingAndSortingRepository<PurchaseBillVoucherItem, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<PurchaseBillVoucherItem, Integer>, JpaSpecificationExecutor<PurchaseBillVoucherItem> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.PurchaseBillVoucher;
|
||||
|
||||
@Repository
|
||||
public interface PurchaseBillVoucherRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<PurchaseBillVoucher, Integer>, PagingAndSortingRepository<PurchaseBillVoucher, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<PurchaseBillVoucher, Integer>, JpaSpecificationExecutor<PurchaseBillVoucher> {
|
||||
|
||||
Optional<PurchaseBillVoucher> findByCode(String code);
|
||||
|
||||
Optional<PurchaseBillVoucher> findByRefId(Integer refId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.PurchaseOrder;
|
||||
import com.ecep.contract.model.PurchaseOrderItem;
|
||||
|
||||
@Repository
|
||||
public interface PurchaseOrderItemRepository extends MyRepository<PurchaseOrderItem, Integer>{
|
||||
|
||||
List<PurchaseOrderItem> findAllByRefId(int refId);
|
||||
|
||||
List<PurchaseOrderItem> findAllByOrder(PurchaseOrder order);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.PurchaseOrder;
|
||||
|
||||
@Repository
|
||||
public interface PurchaseOrderRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<PurchaseOrder, Integer>, PagingAndSortingRepository<PurchaseOrder, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<PurchaseOrder, Integer>, JpaSpecificationExecutor<PurchaseOrder> {
|
||||
|
||||
Optional<PurchaseOrder> findByCode(String code);
|
||||
|
||||
Optional<PurchaseOrder> findByRefId(Integer refId);
|
||||
|
||||
List<PurchaseOrder> findAllByContract(Contract contract);
|
||||
|
||||
List<PurchaseOrder> findByCodeStartsWith(String code);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.SalesBillVoucherItem;
|
||||
|
||||
@Repository
|
||||
public interface SalesBillVoucherItemRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<SalesBillVoucherItem, Integer>,
|
||||
PagingAndSortingRepository<SalesBillVoucherItem, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<SalesBillVoucherItem, Integer>, JpaSpecificationExecutor<SalesBillVoucherItem> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.SalesBillVoucher;
|
||||
|
||||
@Repository
|
||||
public interface SalesBillVoucherRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<SalesBillVoucher, Integer>, PagingAndSortingRepository<SalesBillVoucher, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<SalesBillVoucher, Integer>, JpaSpecificationExecutor<SalesBillVoucher> {
|
||||
|
||||
Optional<SalesBillVoucher> findByCode(String code);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.SalesOrder;
|
||||
import com.ecep.contract.model.SalesOrderItem;
|
||||
|
||||
@Repository
|
||||
public interface SalesOrderItemRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<SalesOrderItem, Integer>, PagingAndSortingRepository<SalesOrderItem, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<SalesOrderItem, Integer>, JpaSpecificationExecutor<SalesOrderItem> {
|
||||
|
||||
Optional<SalesOrderItem> findByCode(String code);
|
||||
|
||||
List<SalesOrderItem> findAllByOrder(SalesOrder order);
|
||||
|
||||
List<SalesOrderItem> findByCodeStartsWith(String code);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ecep.contract.ds.contract.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.SalesOrder;
|
||||
|
||||
@Repository
|
||||
public interface SalesOrderRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<SalesOrder, Integer>, PagingAndSortingRepository<SalesOrder, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<SalesOrder, Integer>, JpaSpecificationExecutor<SalesOrder> {
|
||||
|
||||
Optional<SalesOrder> findByCode(String code);
|
||||
|
||||
List<SalesOrder> findAllByContract(Contract contract);
|
||||
|
||||
List<SalesOrder> findByCodeStartsWith(String code);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.ContractBidVendorRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.ContractBidVendor;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-ven-bid")
|
||||
public class ContractBidVendorService implements IEntityService<ContractBidVendor> {
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractBidVendorRepository repository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public ContractBidVendor findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<ContractBidVendor> getSpecification(String searchText) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ContractBidVendor> findAll(Specification<ContractBidVendor> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'allbycontract-'+#p0.id")
|
||||
public List<ContractBidVendor> findByContract(Contract contract) {
|
||||
return repository.findByContractId(contract.getId());
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'allbycontract-'+#p0.contract.id")
|
||||
})
|
||||
public ContractBidVendor save(ContractBidVendor bidVendor) {
|
||||
return repository.save(bidVendor);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'allbycontract-'+#p0.contract.id")
|
||||
})
|
||||
public void delete(ContractBidVendor bidVendor) {
|
||||
repository.delete(bidVendor);
|
||||
}
|
||||
|
||||
public List<ContractBidVendor> findAll(Specification<ContractBidVendor> spec, Sort sort) {
|
||||
return repository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id")
|
||||
})
|
||||
public void deleteById(int id) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
|
||||
public List<ContractBidVendor> findByContractAndCompany(Contract contract, Company company) {
|
||||
return repository.findByContractIdAndCompanyId(contract.getId(), company.getId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.ds.contract.repository.ContractCatalogRepository;
|
||||
import com.ecep.contract.model.ContractCatalog;
|
||||
|
||||
/**
|
||||
* 合同分类服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-catalog")
|
||||
public class ContractCatalogService {
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractCatalogRepository repository;
|
||||
|
||||
/**
|
||||
* 根据 id 查找 ContractCatalog
|
||||
*/
|
||||
@Cacheable(key = "#p0")
|
||||
public ContractCatalog findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
public ContractCatalog findByName(String name) {
|
||||
return repository.findByName(name).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public ContractCatalog findByCode(String code) {
|
||||
return repository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'catalogs'")
|
||||
public List<ContractCatalog> findAll() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code"),
|
||||
@CacheEvict(key = "'catalogs'"),
|
||||
})
|
||||
public ContractCatalog save(ContractCatalog catalog) {
|
||||
return repository.save(catalog);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code"),
|
||||
@CacheEvict(key = "'catalogs'"),
|
||||
})
|
||||
public void delete(ContractCatalog catalog) {
|
||||
repository.delete(catalog);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.ContractFileType;
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.ContractFileRepository;
|
||||
import com.ecep.contract.ds.contract.repository.ContractFileTypeLocalRepository;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.ContractFile;
|
||||
import com.ecep.contract.model.ContractFileTypeLocal;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-file")
|
||||
public class ContractFileService implements IEntityService<ContractFile> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ContractFileService.class);
|
||||
/**
|
||||
* 销售成本核算审批表模板
|
||||
*/
|
||||
public static final String KEY_CUSTOMER_COST_TEMPLATE = "customer.contract.cost.template";
|
||||
/**
|
||||
* 项目投标审批表模板
|
||||
*/
|
||||
public static final String KEY_CUSTOMER_BID_TEMPLATE = "customer.contract.bid.template";
|
||||
/**
|
||||
* 销售合同审批表模板
|
||||
*/
|
||||
public static final String KEY_CUSTOMER_APPLY_TEMPLATE = "customer.contract.apply.template";
|
||||
/**
|
||||
* 投标报价表模板
|
||||
*/
|
||||
public static final String KEY_QUOTATION_TEMPLATE = "customer.contract.quotation.template";
|
||||
/**
|
||||
* 采购合同审批表模板
|
||||
*/
|
||||
public static final String KEY_VENDOR_APPLY_TEMPLATE = "vendor.contract.apply.template";
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractFileRepository contractFileRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractFileTypeLocalRepository contractFileTypeLocalRepository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public ContractFile findById(Integer id) {
|
||||
return contractFileRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<ContractFile> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("fileName"), "%" + searchText + "%"),
|
||||
builder.like(root.get("description"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ContractFile> findAll(Specification<ContractFile> spec, Pageable pageable) {
|
||||
return contractFileRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<ContractFile> findAll(Specification<ContractFile> spec, Sort by) {
|
||||
return contractFileRepository.findAll(spec, by);
|
||||
}
|
||||
|
||||
public List<ContractFile> findAllByContractAndFileType(Contract contract, ContractFileType contractFileType) {
|
||||
return contractFileRepository.findAllByContractAndType(contract, contractFileType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按销售逻辑处理
|
||||
*/
|
||||
@Deprecated
|
||||
public void verifyAsCustomer(Contract contract, Consumer<String> status) {
|
||||
|
||||
// 检查 成本审批
|
||||
if (!checkFileExist(contract, ContractFileType.CostForm)) {
|
||||
status.accept("销售成本审批表未找到");
|
||||
}
|
||||
// 检查 合同审批表
|
||||
if (!checkFileExist(contract, ContractFileType.ContractApprovalForm)) {
|
||||
status.accept("销售合同审批表未找到");
|
||||
}
|
||||
// 检查 合同
|
||||
if (!checkFileExist(contract, ContractFileType.Contract)) {
|
||||
status.accept("销售合同未找到");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkFileExist(Contract contract, ContractFileType type) {
|
||||
List<ContractFile> files = contractFileRepository.findAllByContractAndType(contract, type);
|
||||
if (files == null || files.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按采购逻辑处理
|
||||
*/
|
||||
@Deprecated
|
||||
public void verifyAsVendor(Contract contract, Consumer<String> status) {
|
||||
// 检查 申请表
|
||||
if (!checkFileExist(contract, ContractFileType.PurchaseRequestForm)) {
|
||||
status.accept("采购申请表未找到");
|
||||
}
|
||||
// 检查 合同审批表
|
||||
if (!checkFileExist(contract, ContractFileType.PurchaseContractApprovalForm)) {
|
||||
status.accept("采购合同审批表未找到");
|
||||
}
|
||||
// 检查 合同
|
||||
if (!checkFileExist(contract, ContractFileType.Contract)) {
|
||||
status.accept("采购合同未找到");
|
||||
}
|
||||
// 检查 提货单
|
||||
// contractFileRepository.findAllByContractAndType(contract,
|
||||
// ContractFileType.DeliveryOrder);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'allbycontract-'+#p0.contract.id")
|
||||
})
|
||||
public void delete(ContractFile file) {
|
||||
contractFileRepository.deleteById(file.getId());
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'allbycontract-'+#p0.contract.id")
|
||||
})
|
||||
public ContractFile save(ContractFile contractFile) {
|
||||
return contractFileRepository.save(contractFile);
|
||||
}
|
||||
|
||||
public void deleteById(int id) {
|
||||
contractFileRepository.deleteById(id);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'allbycontract-'+#p0.id")
|
||||
public List<ContractFile> findAllByContract(Contract contract) {
|
||||
return contractFileRepository.findAllByContract(contract);
|
||||
}
|
||||
|
||||
public List<ContractFile> searchByContract(Contract contract, String userText) {
|
||||
Specification<ContractFile> spec = (root, query, builder) -> {
|
||||
return builder.and(
|
||||
builder.equal(root.get("contract"), contract),
|
||||
builder.or(
|
||||
builder.like(root.get("fileName"), "%" + userText + "%"),
|
||||
builder.like(root.get("description"), "%" + userText + "%")));
|
||||
};
|
||||
return contractFileRepository.findAll(spec);
|
||||
}
|
||||
|
||||
// @Cacheable(key = "'type-locals-'+#p0")
|
||||
// public List<ContractFileTypeLocal> findAllFileTypes(String lang) {
|
||||
// Map<ContractFileType, ContractFileTypeLocal> map =
|
||||
// contractFileTypeLocalRepository.getCompleteMapByLocal(lang);
|
||||
// List<ContractFileTypeLocal> list = new ArrayList<>(map.values());
|
||||
// list.sort((o1, o2) -> Objects.compare(o1.getValue(), o2.getValue(),
|
||||
// String::compareTo));
|
||||
// return list;
|
||||
// }
|
||||
|
||||
@Cacheable(key = "'type-locals-'+#p0")
|
||||
public Map<ContractFileType, ContractFileTypeLocal> findAllFileTypes(String lang) {
|
||||
return contractFileTypeLocalRepository.getCompleteMapByLocal(lang);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "'type-locals-'+#p0.lang"),
|
||||
@CacheEvict(key = "'type-'+#p0.type+'-local-'+#p0.lang"),
|
||||
})
|
||||
public ContractFileTypeLocal save(ContractFileTypeLocal type) {
|
||||
return contractFileTypeLocalRepository.save(type);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'type-'+#p0+'-local-'+#p1")
|
||||
public ContractFileTypeLocal findFileTypeLocalByTypeAndLang(ContractFileType type, String lang) {
|
||||
return contractFileTypeLocalRepository.getCompleteByTypeAndLang(type, lang);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.ContractGroupRepository;
|
||||
import com.ecep.contract.model.ContractGroup;
|
||||
|
||||
/**
|
||||
* 合同分组服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-group")
|
||||
public class ContractGroupService implements IEntityService<ContractGroup> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ContractGroupService.class);
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractGroupRepository repository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public ContractGroup findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ContractGroup> findAll(Specification<ContractGroup> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<ContractGroup> getSpecification(String searchText) {
|
||||
return (root, query, builder)->{
|
||||
return builder.or(
|
||||
builder.like(root.get("code"), "%" + searchText + "%"),
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("title"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
public ContractGroup findByName(String name) {
|
||||
return repository.findByName(name).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public ContractGroup findByCode(String code) {
|
||||
return repository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'groups'")
|
||||
public List<ContractGroup> findAll() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "'groups'"),
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code"),
|
||||
})
|
||||
public ContractGroup save(ContractGroup group) {
|
||||
return repository.save(group);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0"),
|
||||
@CacheEvict(key = "'groups'"),
|
||||
})
|
||||
public void delete(Integer id) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0"),
|
||||
@CacheEvict(key = "'groups'"),
|
||||
@CacheEvict(key = "'code-'+#p0.code"),
|
||||
})
|
||||
public void delete(ContractGroup group) {
|
||||
repository.delete(group);
|
||||
}
|
||||
|
||||
public ContractGroup newContractGroup() {
|
||||
ContractGroup group = new ContractGroup();
|
||||
group.setCode("");
|
||||
group.setName("");
|
||||
group.setTitle("");
|
||||
return group;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.ContractItemRepository;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.ContractItem;
|
||||
import com.ecep.contract.model.Inventory;
|
||||
|
||||
import jakarta.persistence.criteria.Path;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-item")
|
||||
public class ContractItemService implements IEntityService<ContractItem> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ContractItemService.class);
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractItemRepository itemRepository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public ContractItem findById(Integer id) {
|
||||
return itemRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<ContractItem> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return (root, query, builder) -> {
|
||||
Path<Inventory> inventory = root.get("inventory");
|
||||
return builder.or(
|
||||
builder.like(root.get("itemCode"), "%" + searchText + "%"),
|
||||
builder.like(root.get("title"), "%" + searchText + "%"),
|
||||
builder.like(root.get("specification"), "%" + searchText + "%"),
|
||||
builder.like(root.get("unit"), "%" + searchText + "%"),
|
||||
builder.like(root.get("remark"), "%" + searchText + "%"),
|
||||
builder.and(
|
||||
inventory.isNotNull(), builder.or(
|
||||
builder.like(inventory.get("name"), "%" + searchText + "%"),
|
||||
builder.like(inventory.get("code"), "%" + searchText + "%"),
|
||||
builder.like(inventory.get("specification"), "%" + searchText + "%"))));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ContractItem> findAll(Specification<ContractItem> spec, Pageable pageable) {
|
||||
return itemRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<ContractItem> findAllByContract(Contract contract) {
|
||||
return itemRepository.findByContractId(contract.getId());
|
||||
}
|
||||
|
||||
public List<ContractItem> findAllByInventory(Inventory inventory) {
|
||||
return itemRepository.findByInventoryId(inventory.getId());
|
||||
}
|
||||
|
||||
public List<ContractItem> findAll(Specification<ContractItem> spec, Sort sort) {
|
||||
return itemRepository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id")
|
||||
})
|
||||
public ContractItem save(ContractItem item) {
|
||||
return itemRepository.save(item);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id")
|
||||
})
|
||||
public void delete(ContractItem item) {
|
||||
itemRepository.delete(item);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.ContractKindRepository;
|
||||
import com.ecep.contract.model.ContractKind;
|
||||
|
||||
/**
|
||||
* 合同种类服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-kind")
|
||||
public class ContractKindService implements IEntityService<ContractKind> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ContractKindService.class);
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractKindRepository repository;
|
||||
|
||||
@Cacheable(key = "'kind-'+#p0")
|
||||
public ContractKind findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ContractKind> findAll(Specification<ContractKind> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<ContractKind> getSpecification(String searchText) {
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("code"), "%" + searchText + "%"),
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("title"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(ContractKind entity) {
|
||||
repository.delete(entity);
|
||||
}
|
||||
|
||||
public ContractKind findByName(String name) {
|
||||
return repository.findByName(name).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public ContractKind findByCode(String code) {
|
||||
return repository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'kinds'")
|
||||
public List<ContractKind> findAll() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "'kinds'"),
|
||||
@CacheEvict(key = "'kind-'+#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.name"),
|
||||
}
|
||||
)
|
||||
public ContractKind save(ContractKind kind) {
|
||||
return repository.save(kind);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "'kinds'"),
|
||||
@CacheEvict(key = "'kind-'+#p0"),
|
||||
}
|
||||
)
|
||||
public void delete(Integer id) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.ContractPayPlanRepository;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.ContractPayPlan;
|
||||
|
||||
/**
|
||||
* 合同支付计划服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-pay-plan")
|
||||
public class ContractPayPlanService implements IEntityService<ContractPayPlan> {
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractPayPlanRepository repository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
@Override
|
||||
public ContractPayPlan findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<ContractPayPlan> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return (root, query, cb) -> {
|
||||
return cb.or(cb.like(root.get("payTerm"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ContractPayPlan> findAll(Specification<ContractPayPlan> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<ContractPayPlan> findAllByContract(Contract contract) {
|
||||
return repository.findAllByContract(contract);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id")
|
||||
}
|
||||
)
|
||||
@Override
|
||||
public void delete(ContractPayPlan entity) {
|
||||
repository.delete(entity);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id")
|
||||
}
|
||||
)
|
||||
@Override
|
||||
public ContractPayPlan save(ContractPayPlan entity) {
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,412 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.ContractPayWay;
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.ContractRepository;
|
||||
import com.ecep.contract.ds.other.service.SysConfService;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyCustomer;
|
||||
import com.ecep.contract.model.CompanyVendor;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.ContractCatalog;
|
||||
import com.ecep.contract.model.ContractGroup;
|
||||
import com.ecep.contract.model.ContractKind;
|
||||
import com.ecep.contract.model.ContractType;
|
||||
import com.ecep.contract.model.Project;
|
||||
import com.ecep.contract.util.MyStringUtils;
|
||||
import com.ecep.contract.util.SpecificationUtils;
|
||||
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
/**
|
||||
* 合同服务类
|
||||
* 继承基础服务并实现视图模型接口
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract")
|
||||
public class ContractService implements IEntityService<Contract> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ContractService.class);
|
||||
public static final String CONTRACT_BASE_PATH = "contract.base.path";
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractCatalogService contractCatalogService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractTypeService contractTypeService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractGroupService contractGroupService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractKindService contractKindService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractFileService contractFileService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
protected ContractRepository contractRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
protected SysConfService confService;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public Contract findById(Integer id) {
|
||||
return contractRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
public Contract findByName(String name) {
|
||||
return contractRepository.findFirstByName(name).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public Contract findByCode(String code) {
|
||||
return contractRepository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
public Contract findByGuid(String guid) {
|
||||
return contractRepository.findByGuid(guid).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存实体对象,异步方法
|
||||
*/
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code")
|
||||
})
|
||||
public Contract save(Contract contract) {
|
||||
return contractRepository.save(contract);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code")
|
||||
})
|
||||
public void delete(Contract contract) {
|
||||
contractRepository.delete(contract);
|
||||
}
|
||||
|
||||
public long count() {
|
||||
return contractRepository.count();
|
||||
}
|
||||
|
||||
public long count(Specification<Contract> spec) {
|
||||
return contractRepository.count(spec);
|
||||
}
|
||||
|
||||
public Page<Contract> findAll(Specification<Contract> spec, Pageable pageable) {
|
||||
return contractRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<Contract> findAll(Specification<Contract> spec, Sort sort) {
|
||||
return contractRepository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
public List<Contract> findAllByCompany(Company company) {
|
||||
return contractRepository.findAllByCompanyId(company.getId());
|
||||
}
|
||||
|
||||
public List<Contract> findAllByProject(Project project) {
|
||||
return contractRepository.findAllByProjectId(project.getId());
|
||||
}
|
||||
|
||||
public List<Contract> findAllSalesByProject(Project project) {
|
||||
return contractRepository.findAllByProjectIdAndPayWay(project.getId(), ContractPayWay.RECEIVE);
|
||||
}
|
||||
|
||||
public Contract findSalesByProject(Project project) {
|
||||
return contractRepository.findByProjectIdAndPayWay(project.getId(), ContractPayWay.RECEIVE).orElse(null);
|
||||
}
|
||||
|
||||
public File getBasePath() {
|
||||
return new File(confService.getString(CONTRACT_BASE_PATH));
|
||||
}
|
||||
|
||||
public ContractGroup findGroupById(Integer id) {
|
||||
return contractGroupService.findById(id);
|
||||
}
|
||||
|
||||
public ContractGroup findGroupByCode(String groupCode) {
|
||||
return contractGroupService.findByCode(groupCode);
|
||||
}
|
||||
|
||||
public List<ContractGroup> findAllGroups() {
|
||||
return contractGroupService.findAll();
|
||||
}
|
||||
|
||||
public ContractType findTypeById(Integer id) {
|
||||
return contractTypeService.findById(id);
|
||||
}
|
||||
|
||||
public ContractType findTypeByCode(String typeCode) {
|
||||
return contractTypeService.findByCode(typeCode);
|
||||
}
|
||||
|
||||
public ContractKind findKindById(Integer id) {
|
||||
return contractKindService.findById(id);
|
||||
}
|
||||
|
||||
public ContractKind findKindByName(String kindName) {
|
||||
return contractKindService.findByName(kindName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回合同的分类目录
|
||||
*/
|
||||
public File getContractCatalogPath(ContractCatalog catalog, Contract contract) {
|
||||
String parent = catalog.getParent();
|
||||
File dir = getBasePath();
|
||||
if (StringUtils.hasText(parent)) {
|
||||
dir = new File(dir, parent);
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdir()) {
|
||||
System.out.println("unable make directory = " + dir.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
dir = new File(dir, catalog.getPath());
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdir()) {
|
||||
System.out.println("unable make directory = " + dir.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (catalog.isUseYear()) {
|
||||
String code = contract.getCode();
|
||||
String catalogCode = catalog.getCode();
|
||||
int length = catalogCode.length();
|
||||
String yearCode = code.substring(length, length + 2);
|
||||
dir = new File(dir, "20" + yearCode);
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdir()) {
|
||||
System.out.println("unable make directory = " + dir.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找合同的分类
|
||||
*/
|
||||
public ContractCatalog findContractCatalogByContract(Contract contract) {
|
||||
String code = contract.getCode();
|
||||
String catalogCode = null;
|
||||
|
||||
// 第二个字符是数字时,快速处理
|
||||
if (Character.isDigit(code.charAt(1))) {
|
||||
// 只有一个字母表示合同类型
|
||||
catalogCode = code.substring(0, 1);
|
||||
} else {
|
||||
// 使用正则找出 合同类型
|
||||
String regex = "^([A-Z]{1,4})(\\d{4,5})";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(code);
|
||||
if (matcher.find()) {
|
||||
catalogCode = matcher.group(1);
|
||||
System.out.println("字母部分: " + matcher.group(1));
|
||||
System.out.println("数字部分: " + matcher.group(2));
|
||||
}
|
||||
if (catalogCode == null) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("contract {} can't find catalog code", code);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return contractCatalogService.findByCode(catalogCode);
|
||||
}
|
||||
|
||||
public Contract createNew() {
|
||||
Contract contract = new Contract();
|
||||
contract.setCreated(LocalDateTime.now());
|
||||
return contract;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<Contract> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return SpecificationUtils.andWith(searchText, this::buildSearchSpecification);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建搜索规范
|
||||
*/
|
||||
protected Specification<Contract> buildSearchSpecification(String searchText) {
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("code"), "%" + searchText + "%"),
|
||||
builder.like(root.get("parentCode"), "%" + searchText + "%"),
|
||||
builder.like(root.get("description"), "%" + searchText + "%"),
|
||||
builder.like(root.get("guid"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
|
||||
public List<Contract> findAllByCompanyVendor(CompanyVendor vendor, LocalDate beginDate, LocalDate endDate) {
|
||||
Company company = vendor.getCompany();
|
||||
return contractRepository.findAll((root, query, cb) -> {
|
||||
Predicate p = cb.and(
|
||||
cb.equal(root.get("company").get("id"), company.getId()),
|
||||
cb.equal(root.get("payWay"), ContractPayWay.PAY));
|
||||
return applyPredicate(root, cb, p, beginDate, endDate);
|
||||
}, Sort.unsorted());
|
||||
}
|
||||
|
||||
public List<Contract> findAllByCompanyCustomer(CompanyCustomer customer, LocalDate beginDate, LocalDate endDate) {
|
||||
Company company = customer.getCompany();
|
||||
return contractRepository.findAll((root, query, cb) -> {
|
||||
Predicate p = cb.and(
|
||||
cb.equal(root.get("company"), company),
|
||||
cb.equal(root.get("payWay"), ContractPayWay.RECEIVE));
|
||||
return applyPredicate(root, cb, p, beginDate, endDate);
|
||||
}, Sort.unsorted());
|
||||
}
|
||||
|
||||
private Predicate applyPredicate(
|
||||
jakarta.persistence.criteria.Root<Contract> root,
|
||||
jakarta.persistence.criteria.CriteriaBuilder cb,
|
||||
Predicate base, LocalDate beginDate, LocalDate endDate) {
|
||||
if (beginDate == null && endDate == null) {
|
||||
return base;
|
||||
} else if (endDate == null) {
|
||||
return cb.and(base, cb.greaterThanOrEqualTo(root.get("setupDate"), beginDate));
|
||||
} else if (beginDate == null) {
|
||||
return cb.and(base, cb.lessThanOrEqualTo(root.get("setupDate"), endDate));
|
||||
} else {
|
||||
return cb.and(base, cb.between(root.get("setupDate"), beginDate, endDate));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是非子合同编号
|
||||
*/
|
||||
public boolean isSubContractCode(String code) {
|
||||
if (!StringUtils.hasText(code)) {
|
||||
return false;
|
||||
}
|
||||
return code.contains("-");
|
||||
}
|
||||
|
||||
public boolean isSubContract(Contract contract) {
|
||||
return isSubContractCode(contract.getCode());
|
||||
}
|
||||
|
||||
public String getParentCode(Contract contract) {
|
||||
String code = contract.getCode();
|
||||
|
||||
int index = code.indexOf("-");
|
||||
if (index != -1) {
|
||||
return code.substring(0, index);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新合同的主合同编号(从当前合同的额合同编码上推测)
|
||||
*/
|
||||
public boolean updateParentCode(Contract contract) {
|
||||
if (!isSubContract(contract)) {
|
||||
return false;
|
||||
}
|
||||
String parentCode = getParentCode(contract);
|
||||
// fixed
|
||||
if (Objects.equals(contract.getParentCode(), parentCode)) {
|
||||
// 已经相同,跳过
|
||||
return false;
|
||||
}
|
||||
Contract parentContract = null;
|
||||
List<Contract> list = contractRepository.findByCodeStartsWith(parentCode);
|
||||
if (list.isEmpty()) {
|
||||
throw new NoSuchElementException("没有找到以" + parentCode + "开头的合同");
|
||||
}
|
||||
for (Contract c : list) {
|
||||
if (!c.getCode().contains("-")) {
|
||||
parentContract = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (parentContract == null) {
|
||||
throw new NoSuchElementException("没有匹配到以" + parentCode + "开头的合同");
|
||||
}
|
||||
|
||||
if (Objects.equals(contract.getParentCode(), parentContract.getCode())) {
|
||||
return false;
|
||||
}
|
||||
contract.setParentCode(parentContract.getCode());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 company 的 合同
|
||||
*/
|
||||
public void deleteByCompany(Company company) {
|
||||
int deleted = contractRepository.deleteAllByCompanyId(company.getId());
|
||||
if (deleted > 0) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Delete {} records by company:#{}", deleted, company.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置合同关联企业
|
||||
*/
|
||||
public void resetTo(Company from, Company to) {
|
||||
List<Contract> list = contractRepository.findAllByCompanyId(from.getId());
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (Contract contract : list) {
|
||||
contract.setDescription(MyStringUtils.appendIfAbsent(contract.getDescription(), "转自 " + from.getId()));
|
||||
contract.setCompany(to);
|
||||
}
|
||||
contractRepository.saveAll(list);
|
||||
}
|
||||
|
||||
public List<Contract> findAllByParent(Contract contract) {
|
||||
return contractRepository.findAllByParentCode(contract.getCode());
|
||||
}
|
||||
|
||||
public List<Contract> search(String searchText) {
|
||||
Specification<Contract> spec = getSpecification(searchText);
|
||||
return contractRepository.findAll(spec, Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
|
||||
public List<Contract> findByCodeStartsWith(ContractPayWay payWay, String parentCode) {
|
||||
return contractRepository.findByPayWayAndCodeStartsWith(payWay, parentCode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.ContractTypeRepository;
|
||||
import com.ecep.contract.model.ContractType;
|
||||
|
||||
/**
|
||||
* 合同类型服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-type")
|
||||
public class ContractTypeService implements IEntityService<ContractType> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ContractTypeService.class);
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ContractTypeRepository repository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public ContractType findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ContractType> findAll(Specification<ContractType> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public ContractType findByName(String name) {
|
||||
return repository.findByName(name).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public ContractType findByCode(String code) {
|
||||
return repository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'types'")
|
||||
public List<ContractType> findAll() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code"),
|
||||
@CacheEvict(key = "'types'"),
|
||||
})
|
||||
public ContractType save(ContractType type) {
|
||||
return repository.save(type);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0"),
|
||||
@CacheEvict(key = "'types'"),
|
||||
})
|
||||
public void delete(Integer id) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code"),
|
||||
@CacheEvict(key = "'types'"),
|
||||
})
|
||||
public void delete(ContractType type) {
|
||||
repository.delete(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<ContractType> getSpecification(String searchText) {
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("code"), "%" + searchText + "%"),
|
||||
builder.like(root.get("name"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.ds.contract.repository.ExtendVendorInfoRepository;
|
||||
import com.ecep.contract.ds.vendor.service.VendorGroupService;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.ExtendVendorInfo;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-ext-ven-info")
|
||||
public class ExtendVendorInfoService {
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ExtendVendorInfoRepository repository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private VendorGroupService vendorGroupService;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public ExtendVendorInfo findById(int id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'bycontract-'+#p0.id")
|
||||
public ExtendVendorInfo findByContract(Contract contract) {
|
||||
return repository.findByContractId(contract.getId()).orElse(null);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'bycontract-'+#p0.contract.id")
|
||||
})
|
||||
public ExtendVendorInfo save(ExtendVendorInfo bidVendor) {
|
||||
return repository.save(bidVendor);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'bycontract-'+#p0.contract.id")
|
||||
})
|
||||
public void delete(ExtendVendorInfo bidVendor) {
|
||||
repository.delete(bidVendor);
|
||||
}
|
||||
|
||||
public List<ExtendVendorInfo> findAll(Specification<ExtendVendorInfo> spec, Sort sort) {
|
||||
return repository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
public void deleteById(int id) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
|
||||
public ExtendVendorInfo newInstanceByContract(Contract contract) {
|
||||
ExtendVendorInfo info = new ExtendVendorInfo();
|
||||
info.setContract(contract);
|
||||
|
||||
if (StringUtils.hasText(contract.getCode())) {
|
||||
String regex = "-([A-Z]{1,4})(\\d{1,4})";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(contract.getCode());
|
||||
if (matcher.find()) {
|
||||
info.setGroup(vendorGroupService.findByCode(matcher.group(1)));
|
||||
info.setCodeSequenceNumber(Integer.parseInt(matcher.group(2)));
|
||||
}
|
||||
}
|
||||
info.setAssignedProvider(false);
|
||||
info.setPrePurchase(false);
|
||||
return info;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.PurchaseBillVoucherItemRepository;
|
||||
import com.ecep.contract.model.PurchaseBillVoucherItem;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "purchase-bill-voucher-item")
|
||||
public class PurchaseBillVoucherItemService implements IEntityService<PurchaseBillVoucherItem> {
|
||||
@Lazy
|
||||
@Autowired
|
||||
private PurchaseBillVoucherItemRepository repository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
@Override
|
||||
public PurchaseBillVoucherItem findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<PurchaseBillVoucherItem> getSpecification(String searchText) {
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("description"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PurchaseBillVoucherItem> findAll(Specification<PurchaseBillVoucherItem> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'refId-'+#p0.refId")
|
||||
})
|
||||
@Override
|
||||
public void delete(PurchaseBillVoucherItem entity) {
|
||||
repository.delete(entity);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'refId-'+#p0.refId")
|
||||
})
|
||||
@Override
|
||||
public PurchaseBillVoucherItem save(PurchaseBillVoucherItem entity) {
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
public List<PurchaseBillVoucherItem> findAll(Specification<PurchaseBillVoucherItem> spec, Sort sort) {
|
||||
return repository.findAll(spec, sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.PurchaseBillVoucherRepository;
|
||||
import com.ecep.contract.model.PurchaseBillVoucher;
|
||||
|
||||
/**
|
||||
* 采购账单凭证服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "purchase-bill-voucher")
|
||||
public class PurchaseBillVoucherService implements IEntityService<PurchaseBillVoucher> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PurchaseBillVoucherService.class);
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private PurchaseBillVoucherRepository repository;
|
||||
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public PurchaseBillVoucher findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<PurchaseBillVoucher> getSpecification(String searchText) {
|
||||
// if null
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("code"), "%" + searchText + "%"),
|
||||
builder.like(root.get("description"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public PurchaseBillVoucher findByCode(String code) {
|
||||
return repository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'refId-'+#p0")
|
||||
public PurchaseBillVoucher findByRefId(Integer refId) {
|
||||
return repository.findByRefId(refId).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存实体对象,异步方法
|
||||
*
|
||||
* @param voucher 要保存的实体对象
|
||||
* @return 返回异步调用
|
||||
*/
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code"),
|
||||
@CacheEvict(key = "'refId-'+#p0.refId")
|
||||
}
|
||||
)
|
||||
public PurchaseBillVoucher save(PurchaseBillVoucher voucher) {
|
||||
return repository.save(voucher);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code"),
|
||||
@CacheEvict(key = "'refId-'+#p0.refId")
|
||||
}
|
||||
)
|
||||
public void delete(PurchaseBillVoucher order) {
|
||||
repository.delete(order);
|
||||
}
|
||||
|
||||
public long count() {
|
||||
return repository.count();
|
||||
}
|
||||
|
||||
public long count(Specification<PurchaseBillVoucher> spec) {
|
||||
return repository.count(spec);
|
||||
}
|
||||
|
||||
public Page<PurchaseBillVoucher> findAll(Specification<PurchaseBillVoucher> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<PurchaseBillVoucher> findAll(Specification<PurchaseBillVoucher> spec, Sort sort) {
|
||||
return repository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
public List<PurchaseBillVoucher> search(String searchText) {
|
||||
return repository.findAll(getSpecification(searchText), Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.PurchaseOrderItemRepository;
|
||||
import com.ecep.contract.model.PurchaseOrderItem;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-purchase-order-item")
|
||||
public class PurchaseOrderItemService implements IEntityService<PurchaseOrderItem> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PurchaseOrderItemService.class);
|
||||
@Lazy
|
||||
@Autowired
|
||||
private PurchaseOrderItemRepository repository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
@Override
|
||||
public PurchaseOrderItem findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'refId-'+#p0")
|
||||
public PurchaseOrderItem findByRefId(Integer itemRefId) {
|
||||
List<PurchaseOrderItem> list = repository.findAllByRefId(itemRefId);
|
||||
if (list.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
while (list.size() > 1) {
|
||||
PurchaseOrderItem item = list.removeLast();
|
||||
repository.delete(item);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Duplicate PurchaseOrderItem, Delete {}", item);
|
||||
}
|
||||
}
|
||||
return list.getFirst();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Specification<PurchaseOrderItem> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(builder.like(root.get("description"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PurchaseOrderItem> findAll(Specification<PurchaseOrderItem> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'refId-'+#p0.refId")
|
||||
}
|
||||
)
|
||||
@Override
|
||||
public void delete(PurchaseOrderItem entity) {
|
||||
repository.delete(entity);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"), @CacheEvict(key = "'refId-'+#p0.refId")
|
||||
}
|
||||
)
|
||||
@Override
|
||||
public PurchaseOrderItem save(PurchaseOrderItem entity) {
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
public List<PurchaseOrderItem> findAll(Specification<PurchaseOrderItem> spec, Sort sort) {
|
||||
return repository.findAll(spec, sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.PurchaseOrderRepository;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.PurchaseOrder;
|
||||
|
||||
/**
|
||||
* 采购订单服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-purchase-order")
|
||||
public class PurchaseOrdersService implements IEntityService<PurchaseOrder> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PurchaseOrdersService.class);
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private PurchaseOrderRepository purchaseOrderRepository;
|
||||
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public PurchaseOrder findById(Integer id) {
|
||||
return purchaseOrderRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<PurchaseOrder> getSpecification(String searchText) {
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("code"), "%" + searchText + "%"),
|
||||
builder.like(root.get("description"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public PurchaseOrder findByCode(String code) {
|
||||
return purchaseOrderRepository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'refId-'+#p0")
|
||||
public PurchaseOrder findByRefId(Integer refId) {
|
||||
return purchaseOrderRepository.findByRefId(refId).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存实体对象,异步方法
|
||||
*
|
||||
* @param order 要保存的实体对象
|
||||
* @return 返回异步调用
|
||||
*/
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code"),
|
||||
@CacheEvict(key = "'refId-'+#p0.refId")
|
||||
}
|
||||
)
|
||||
public PurchaseOrder save(PurchaseOrder order) {
|
||||
return purchaseOrderRepository.save(order);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code"),
|
||||
@CacheEvict(key = "'refId-'+#p0.refId")
|
||||
}
|
||||
)
|
||||
public void delete(PurchaseOrder order) {
|
||||
purchaseOrderRepository.delete(order);
|
||||
}
|
||||
|
||||
public long count() {
|
||||
return purchaseOrderRepository.count();
|
||||
}
|
||||
|
||||
public long count(Specification<PurchaseOrder> spec) {
|
||||
return purchaseOrderRepository.count(spec);
|
||||
}
|
||||
|
||||
public Page<PurchaseOrder> findAll(Specification<PurchaseOrder> spec, Pageable pageable) {
|
||||
return purchaseOrderRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<PurchaseOrder> findAll(Specification<PurchaseOrder> spec, Sort sort) {
|
||||
return purchaseOrderRepository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
public List<PurchaseOrder> findAllByContract(Contract contract) {
|
||||
return purchaseOrderRepository.findAllByContract(contract);
|
||||
}
|
||||
|
||||
public List<PurchaseOrder> search(String searchText) {
|
||||
Specification<PurchaseOrder> spec = (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("code"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
return purchaseOrderRepository.findAll(spec, Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.SalesOrderRepository;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.SalesOrder;
|
||||
|
||||
/**
|
||||
* 合同服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-sale-order")
|
||||
public class SaleOrdersService implements IEntityService<SalesOrder> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SaleOrdersService.class);
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private SalesOrderRepository salesOrderRepository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public SalesOrder findById(Integer id) {
|
||||
return salesOrderRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<SalesOrder> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("code"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public SalesOrder findByCode(String code) {
|
||||
return salesOrderRepository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存实体对象,异步方法
|
||||
*
|
||||
* @param order 要保存的实体对象
|
||||
* @return 返回异步调用
|
||||
*/
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code")
|
||||
})
|
||||
public SalesOrder save(SalesOrder order) {
|
||||
return salesOrderRepository.save(order);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code")
|
||||
})
|
||||
public void delete(SalesOrder order) {
|
||||
salesOrderRepository.delete(order);
|
||||
}
|
||||
|
||||
public long count() {
|
||||
return salesOrderRepository.count();
|
||||
}
|
||||
|
||||
public long count(Specification<SalesOrder> spec) {
|
||||
return salesOrderRepository.count(spec);
|
||||
}
|
||||
|
||||
public Page<SalesOrder> findAll(Specification<SalesOrder> spec, Pageable pageable) {
|
||||
return salesOrderRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<SalesOrder> findAll(Specification<SalesOrder> spec, Sort sort) {
|
||||
return salesOrderRepository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
public List<SalesOrder> findAllByContract(Contract contract) {
|
||||
return salesOrderRepository.findAllByContract(contract);
|
||||
}
|
||||
|
||||
public List<SalesOrder> search(String searchText) {
|
||||
return salesOrderRepository.findAll(getSpecification(searchText), Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.SalesBillVoucherItemRepository;
|
||||
import com.ecep.contract.ds.contract.repository.SalesBillVoucherRepository;
|
||||
import com.ecep.contract.model.SalesBillVoucher;
|
||||
import com.ecep.contract.model.SalesBillVoucherItem;
|
||||
|
||||
/**
|
||||
* 采购账单凭证服务
|
||||
*/
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "sales-bill-voucher")
|
||||
public class SalesBillVoucherService implements IEntityService<SalesBillVoucher> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SalesBillVoucherService.class);
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private SalesBillVoucherRepository salesBillVoucherRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private SalesBillVoucherItemRepository salesBillVoucherItemRepository;
|
||||
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public SalesBillVoucher findById(Integer id) {
|
||||
return salesBillVoucherRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<SalesBillVoucher> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("code"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public SalesBillVoucher findByCode(String code) {
|
||||
return salesBillVoucherRepository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存实体对象,异步方法
|
||||
*
|
||||
* @param voucher 要保存的实体对象
|
||||
* @return 返回异步调用
|
||||
*/
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code")
|
||||
}
|
||||
)
|
||||
public SalesBillVoucher save(SalesBillVoucher voucher) {
|
||||
return salesBillVoucherRepository.save(voucher);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code")
|
||||
}
|
||||
)
|
||||
public void delete(SalesBillVoucher order) {
|
||||
salesBillVoucherRepository.delete(order);
|
||||
}
|
||||
|
||||
public long count() {
|
||||
return salesBillVoucherRepository.count();
|
||||
}
|
||||
|
||||
public long count(Specification<SalesBillVoucher> spec) {
|
||||
return salesBillVoucherRepository.count(spec);
|
||||
}
|
||||
|
||||
public Page<SalesBillVoucher> findAll(Specification<SalesBillVoucher> spec, Pageable pageable) {
|
||||
return salesBillVoucherRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<SalesBillVoucher> findAll(Specification<SalesBillVoucher> spec, Sort sort) {
|
||||
return salesBillVoucherRepository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
public List<SalesBillVoucher> search(String searchText) {
|
||||
Specification<SalesBillVoucher> spec = (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("code"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
return salesBillVoucherRepository.findAll(spec, Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
|
||||
|
||||
@Cacheable(key = "'item-'+#p0")
|
||||
public SalesBillVoucherItem findItemById(Integer id) {
|
||||
return salesBillVoucherItemRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存实体对象,异步方法
|
||||
*
|
||||
* @param item 要保存的实体对象
|
||||
* @return 返回异步调用
|
||||
*/
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "'item-'+#p0.id")
|
||||
}
|
||||
)
|
||||
public SalesBillVoucherItem save(SalesBillVoucherItem item) {
|
||||
return salesBillVoucherItemRepository.save(item);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "'item-'+#p0.id")
|
||||
}
|
||||
)
|
||||
public void delete(SalesBillVoucherItem order) {
|
||||
salesBillVoucherItemRepository.delete(order);
|
||||
}
|
||||
|
||||
public long countItems() {
|
||||
return salesBillVoucherItemRepository.count();
|
||||
}
|
||||
|
||||
public long countItems(Specification<SalesBillVoucherItem> spec) {
|
||||
return salesBillVoucherItemRepository.count(spec);
|
||||
}
|
||||
|
||||
public Page<SalesBillVoucherItem> findAllItems(Specification<SalesBillVoucherItem> spec, Pageable pageable) {
|
||||
return salesBillVoucherItemRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<SalesBillVoucherItem> findAllItems(Specification<SalesBillVoucherItem> spec, Sort sort) {
|
||||
return salesBillVoucherItemRepository.findAll(spec, sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.ecep.contract.ds.contract.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.contract.repository.SalesOrderItemRepository;
|
||||
import com.ecep.contract.model.SalesOrderItem;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract-sale-order-item")
|
||||
public class SalesOrderItemService implements IEntityService<SalesOrderItem> {
|
||||
@Lazy
|
||||
@Autowired
|
||||
private SalesOrderItemRepository repository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
@Override
|
||||
public SalesOrderItem findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<SalesOrderItem> getSpecification(String searchText) {
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("code"), "%" + searchText + "%"),
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("description"), "%" + searchText + "%")
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<SalesOrderItem> findAll(Specification<SalesOrderItem> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
}
|
||||
)
|
||||
@Override
|
||||
public void delete(SalesOrderItem entity) {
|
||||
repository.delete(entity);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
}
|
||||
)
|
||||
@Override
|
||||
public SalesOrderItem save(SalesOrderItem entity) {
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
public List<SalesOrderItem> findAll(Specification<SalesOrderItem> spec, Sort sort) {
|
||||
return repository.findAll(spec, sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
package com.ecep.contract.ds.contract.tasker;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.ContractPayWay;
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.SpringApp;
|
||||
import com.ecep.contract.cloud.u8.YongYouU8Service;
|
||||
import com.ecep.contract.cloud.u8.ctx.ContractCtx;
|
||||
import com.ecep.contract.cloud.u8.ctx.PurchaseBillVoucherCtx;
|
||||
import com.ecep.contract.cloud.u8.ctx.PurchaseOrderCtx;
|
||||
import com.ecep.contract.cloud.u8.ctx.SalesBillVoucherCtx;
|
||||
import com.ecep.contract.cloud.u8.ctx.SalesOrderCtx;
|
||||
import com.ecep.contract.constant.CloudServiceConstant;
|
||||
import com.ecep.contract.ds.contract.service.ContractService;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.Project;
|
||||
import com.ecep.contract.model.SalesOrder;
|
||||
import com.ecep.contract.ui.Tasker;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public abstract class AbstContractRepairTasker extends Tasker<Object> {
|
||||
@Getter
|
||||
protected boolean filesUpdated = false;
|
||||
@Getter
|
||||
protected boolean itemsUpdated = false;
|
||||
@Getter
|
||||
protected boolean playPlanUpdated = false;
|
||||
@Getter
|
||||
protected boolean saleOrderUpdated = false;
|
||||
|
||||
protected final ContractCtx contractCtx = new ContractCtx();
|
||||
protected SalesOrderCtx salesOrderCtx = null;
|
||||
protected SalesBillVoucherCtx salesBillVoucherCtx = null;
|
||||
protected PurchaseOrderCtx purchaseOrderCtx = null;
|
||||
protected PurchaseBillVoucherCtx purchaseBillVoucherCtx = null;
|
||||
|
||||
SalesOrderCtx getSalesOrderCtx() {
|
||||
if (salesOrderCtx == null) {
|
||||
salesOrderCtx = new SalesOrderCtx();
|
||||
salesOrderCtx.from(contractCtx);
|
||||
}
|
||||
return salesOrderCtx;
|
||||
}
|
||||
|
||||
SalesBillVoucherCtx getSalesBillVoucherCtx() {
|
||||
if (salesBillVoucherCtx == null) {
|
||||
salesBillVoucherCtx = new SalesBillVoucherCtx();
|
||||
salesBillVoucherCtx.from(contractCtx);
|
||||
}
|
||||
return salesBillVoucherCtx;
|
||||
}
|
||||
|
||||
PurchaseOrderCtx getPurchaseOrderCtx() {
|
||||
if (purchaseOrderCtx == null) {
|
||||
purchaseOrderCtx = new PurchaseOrderCtx();
|
||||
purchaseOrderCtx.from(contractCtx);
|
||||
}
|
||||
return purchaseOrderCtx;
|
||||
}
|
||||
|
||||
PurchaseBillVoucherCtx getPurchaseBillVoucherCtx() {
|
||||
if (purchaseBillVoucherCtx == null) {
|
||||
purchaseBillVoucherCtx = new PurchaseBillVoucherCtx();
|
||||
purchaseBillVoucherCtx.from(contractCtx);
|
||||
}
|
||||
return purchaseBillVoucherCtx;
|
||||
}
|
||||
|
||||
public void setContractService(ContractService contractService) {
|
||||
contractCtx.setContractService(contractService);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object execute(MessageHolder holder) throws Exception {
|
||||
try {
|
||||
YongYouU8Service u8Service = SpringApp.getBean(YongYouU8Service.class);
|
||||
u8Service.initialize(contractCtx);
|
||||
} catch (NoSuchBeanDefinitionException ignored) {
|
||||
holder.warn("无法使用 " + CloudServiceConstant.U8_NAME + " 服务");
|
||||
}
|
||||
try {
|
||||
repair(holder);
|
||||
} catch (CannotGetJdbcConnectionException e) {
|
||||
throw new RuntimeException("无法获取的数据库连接", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract void repair(MessageHolder holder);
|
||||
|
||||
/**
|
||||
* rs 数据从 CM_List 表中读取
|
||||
*/
|
||||
protected boolean repairFromCMList(Map<String, Object> rs, MessageHolder holder) {
|
||||
String contractID = (String) rs.get("strContractID");
|
||||
String guid = (String) rs.get("GUID");
|
||||
String contractName = (String) rs.get("strContractName");
|
||||
String state = (String) rs.get("strState");
|
||||
|
||||
holder.info("同步合同 " + contractID + " " + contractName);
|
||||
Contract contract = contractCtx.findOrCreatByGuidOrContractId(guid, contractID, holder);
|
||||
if (contract == null) {
|
||||
holder.warn("未知合同" + contractID + ", " + rs.get("strContractName"));
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean modified = false;
|
||||
if (contractCtx.updateText(contract::getCode, contract::setCode, contractID, holder, "合同编号")) {
|
||||
ContractService contractService = contractCtx.getContractService();
|
||||
Contract dup = contractService.findByCode(contractID);
|
||||
if (dup != null) {
|
||||
if (!Objects.equals(contract, dup)) {
|
||||
contractService.delete(dup);
|
||||
holder.warn("删除重复的合同 " + dup);
|
||||
}
|
||||
}
|
||||
modified = true;
|
||||
}
|
||||
if (contractCtx.updateText(contract::getGuid, contract::setGuid, guid, holder, "GUID")) {
|
||||
ContractService contractService = contractCtx.getContractService();
|
||||
Contract dup = contractService.findByGuid(guid);
|
||||
if (dup != null) {
|
||||
if (!Objects.equals(contract, dup)) {
|
||||
contractService.delete(dup);
|
||||
holder.warn("删除重复的合同 " + dup);
|
||||
}
|
||||
}
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (contractCtx.updateText(contract::getState, contract::setState, state, holder, "合同状态")) {
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
contract = contractCtx.save(contract);
|
||||
}
|
||||
|
||||
Contract parent = null;
|
||||
|
||||
if (contract.getPayWay() == ContractPayWay.PAY) {
|
||||
if (StringUtils.hasText(contract.getParentCode())) {
|
||||
parent = contractCtx.findContractByCode(contract.getParentCode());
|
||||
}
|
||||
}
|
||||
AtomicReference<Contract> refer = new AtomicReference<>(contract);
|
||||
try {
|
||||
return repair(refer, parent, holder, progress -> {
|
||||
});
|
||||
} catch (Exception e) {
|
||||
holder.error(state);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contractProperty
|
||||
* @param holder
|
||||
* @param progress
|
||||
* @return
|
||||
*/
|
||||
public boolean repair(
|
||||
AtomicReference<Contract> contractProperty,
|
||||
Contract parent, MessageHolder holder, Consumer<Double> progress) {
|
||||
boolean repaired = false;
|
||||
boolean modified = false;
|
||||
Contract contract = contractProperty.get();
|
||||
|
||||
progress.accept(0.1);
|
||||
if (contractCtx.updateContractDetailByGuid(contract, contract.getGuid(), holder)) {
|
||||
modified = true;
|
||||
}
|
||||
progress.accept(0.2);
|
||||
if (contractCtx.updateContractExec(contract, holder)) {
|
||||
modified = true;
|
||||
}
|
||||
progress.accept(0.3);
|
||||
if (contractCtx.updateContractAmount(contract, holder)) {
|
||||
modified = true;
|
||||
}
|
||||
progress.accept(0.4);
|
||||
if (contractCtx.updateParentContract(contract, holder)) {
|
||||
modified = true;
|
||||
}
|
||||
if (contractCtx.updateContractPath(contract, holder)) {
|
||||
modified = true;
|
||||
}
|
||||
progress.accept(0.5);
|
||||
if (modified) {
|
||||
contract = contractCtx.save(contract);
|
||||
contractProperty.set(contract);
|
||||
modified = false;
|
||||
repaired = true;
|
||||
}
|
||||
progress.accept(0.6);
|
||||
if (contractCtx.syncContractItems(contract, holder)) {
|
||||
itemsUpdated = true;
|
||||
modified = true;
|
||||
}
|
||||
progress.accept(0.66);
|
||||
if (contractCtx.syncContractPayPlan(contract, holder)) {
|
||||
playPlanUpdated = true;
|
||||
}
|
||||
progress.accept(0.7);
|
||||
if (contractCtx.updateContractProject(contract, parent, holder)) {
|
||||
modified = true;
|
||||
}
|
||||
if (modified) {
|
||||
contract = contractCtx.save(contract);
|
||||
contractProperty.set(contract);
|
||||
modified = false;
|
||||
repaired = true;
|
||||
}
|
||||
progress.accept(0.8);
|
||||
// 销售合同
|
||||
if (contract.getPayWay() == ContractPayWay.RECEIVE) {
|
||||
syncSaleOrder(contract, holder);
|
||||
syncChildrenContract(contract, holder, p -> progress.accept(p * 0.1 + 0.8));
|
||||
|
||||
} else if (contract.getPayWay() == ContractPayWay.PAY) {
|
||||
syncPurchaseOrder(contract, holder);
|
||||
}
|
||||
progress.accept(0.9);
|
||||
if (contractCtx.syncContractFiles(contract, holder)) {
|
||||
filesUpdated = true;
|
||||
repaired = true;
|
||||
}
|
||||
progress.accept(1.0);
|
||||
return repaired;
|
||||
}
|
||||
|
||||
private void syncChildrenContract(Contract parent, MessageHolder holder, Consumer<Double> progress) {
|
||||
ContractService contractService = contractCtx.getContractService();
|
||||
List<Contract> list = contractService.findAllByParent(parent);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Contract v = list.get(i);
|
||||
holder.info("子合同 : " + v.getCode() + " " + v.getName());
|
||||
MessageHolder subHolder = holder.sub(" -- ");
|
||||
boolean modified = false;
|
||||
Project project = parent.getProject();
|
||||
if (project == null) {
|
||||
project = v.getProject();
|
||||
}
|
||||
AtomicReference<Contract> contractProperty = new AtomicReference<>(v);
|
||||
try {
|
||||
repair(contractProperty, parent, subHolder, p -> {
|
||||
});
|
||||
|
||||
v = contractProperty.get();
|
||||
if (contractCtx.updateContractProject(v, project, subHolder)) {
|
||||
modified = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!Hibernate.isInitialized(v)) {
|
||||
v = contractService.findById(v.getId());
|
||||
}
|
||||
throw new RuntimeException("同步子合同失败, contract=" + v.toPrettyString(), e);
|
||||
}
|
||||
if (modified) {
|
||||
try {
|
||||
v = contractCtx.save(v);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("#" + v.getId() + ", v=" + v.getVersion(), e);
|
||||
}
|
||||
modified = false;
|
||||
}
|
||||
progress.accept((double) i / list.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步合同的销售订单
|
||||
*
|
||||
* @param contract 合同
|
||||
* @param holder 消息
|
||||
*/
|
||||
private void syncSaleOrder(Contract contract, MessageHolder holder) {
|
||||
SalesOrderCtx ctx = getSalesOrderCtx();
|
||||
if (ctx.getRepository() == null) {
|
||||
return;
|
||||
}
|
||||
List<SalesOrder> orders = ctx.syncByContract(contract, holder);
|
||||
if (orders == null) {
|
||||
return;
|
||||
}
|
||||
SalesBillVoucherCtx voucherCtx = getSalesBillVoucherCtx();
|
||||
for (SalesOrder order : orders) {
|
||||
voucherCtx.syncBySalesOrder(order, holder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步合同采购订单
|
||||
*
|
||||
* @param contract 合同
|
||||
* @param holder 消息
|
||||
*/
|
||||
private void syncPurchaseOrder(Contract contract, MessageHolder holder) {
|
||||
PurchaseOrderCtx ctx1 = getPurchaseOrderCtx();
|
||||
if (ctx1.getRepository() != null) {
|
||||
ctx1.syncByContract(contract, holder);
|
||||
}
|
||||
|
||||
PurchaseBillVoucherCtx ctx2 = getPurchaseBillVoucherCtx();
|
||||
if (ctx2.getRepository() != null) {
|
||||
ctx2.syncByContract(contract, holder);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.ecep.contract.ds.contract.tasker;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.cloud.u8.ctx.ContractCtx;
|
||||
import com.ecep.contract.ds.contract.service.ContractService;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.ContractGroup;
|
||||
import com.ecep.contract.ui.Tasker;
|
||||
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 对所有合同的文件进行重置
|
||||
*/
|
||||
public class ContractFilesRebuildAllTasker extends Tasker<Object> {
|
||||
@Setter
|
||||
private ContractService contractService;
|
||||
|
||||
private ContractCtx contractCtx;
|
||||
|
||||
@Setter
|
||||
private ContractGroup group;
|
||||
|
||||
ContractCtx getContractCtx() {
|
||||
if (contractCtx == null) {
|
||||
contractCtx = new ContractCtx();
|
||||
contractCtx.setContractService(getContractService());
|
||||
}
|
||||
return contractCtx;
|
||||
}
|
||||
|
||||
public ContractFilesRebuildAllTasker() {
|
||||
updateTitle("合同文件重置");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object execute(MessageHolder holder) {
|
||||
Pageable pageRequest = PageRequest.ofSize(200);
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
updateTitle("遍历所有合同,对每个可以合同的文件进行“重置”操作");
|
||||
|
||||
Specification<Contract> spec = null;
|
||||
if (group != null) {
|
||||
holder.info("= 按合同分组 " + group.getTitle() + " 刷选 =");
|
||||
spec = (root, query, cb) -> {
|
||||
return cb.equal(root.get("group"), group);
|
||||
};
|
||||
}
|
||||
long total = getContractService().count(spec);
|
||||
while (true) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
Page<Contract> page = getContractService().findAll(spec, pageRequest);
|
||||
if (page.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (Contract contract : page) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
MessageHolder subHolder = holder.sub(
|
||||
counter.get() + " / " + total + "> " + contract.getCode() + " #" + contract.getId() + "> ");
|
||||
getContractCtx().syncContractFiles(contract, subHolder);
|
||||
updateProgress(counter.incrementAndGet(), total);
|
||||
}
|
||||
if (!page.hasNext()) {
|
||||
break;
|
||||
}
|
||||
pageRequest = page.nextPageable();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ContractService getContractService() {
|
||||
if (contractService == null) {
|
||||
contractService = getBean(ContractService.class);
|
||||
}
|
||||
return contractService;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.ecep.contract.ds.contract.tasker;
|
||||
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.cloud.u8.ctx.ContractCtx;
|
||||
import com.ecep.contract.ds.contract.service.ContractService;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.ui.Tasker;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 对合同的文件进行重置
|
||||
*/
|
||||
public class ContractFilesRebuildTasker extends Tasker<Object> {
|
||||
@Setter
|
||||
private ContractService contractService;
|
||||
|
||||
@Setter
|
||||
private Contract contract;
|
||||
|
||||
@Getter
|
||||
private boolean repaired = false;
|
||||
|
||||
public ContractFilesRebuildTasker() {
|
||||
updateTitle("合同文件重置");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object execute(MessageHolder holder) {
|
||||
updateTitle("遍历合同的文件进行“重置”操作");
|
||||
|
||||
ContractCtx contractCtx = new ContractCtx();
|
||||
if (contractCtx.syncContractFiles(contract, holder)) {
|
||||
repaired = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ContractService getContractService() {
|
||||
if (contractService == null) {
|
||||
contractService = getBean(ContractService.class);
|
||||
}
|
||||
return contractService;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.ecep.contract.ds.contract.tasker;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.ContractPayWay;
|
||||
import com.ecep.contract.Message;
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.ds.contract.service.ContractService;
|
||||
import com.ecep.contract.model.Contract;
|
||||
|
||||
import jakarta.persistence.criteria.Path;
|
||||
|
||||
/**
|
||||
* 对所有合同进行修复
|
||||
*/
|
||||
public class ContractRepairAllTasker extends AbstContractRepairTasker {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ContractRepairAllTasker.class);
|
||||
|
||||
static class MessageHolderImpl implements MessageHolder {
|
||||
List<Message> messages = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void addMessage(Level level, String message) {
|
||||
Message msg = new Message(level, message);
|
||||
messages.add(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void repair(MessageHolder holder) {
|
||||
updateTitle("同步修复所有合同");
|
||||
|
||||
Pageable pageRequest = PageRequest.ofSize(200);
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
Specification<Contract> spec = (root, query, builder) -> {
|
||||
Path<String> parentCode = root.get("parentCode");
|
||||
Path<ContractPayWay> payWay = root.get("payWay");
|
||||
return builder.or(
|
||||
builder.equal(payWay, ContractPayWay.RECEIVE),
|
||||
builder.and(
|
||||
builder.equal(payWay, ContractPayWay.PAY),
|
||||
builder.or(
|
||||
builder.equal(parentCode, ""),
|
||||
builder.isNull(parentCode))));
|
||||
};
|
||||
|
||||
updateTitle("遍历所有合同,对每个可以合同的文件进行“修复”操作");
|
||||
ContractService contractService = contractCtx.getContractService();
|
||||
long total = contractService.count(spec);
|
||||
while (true) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
Page<Contract> page = contractService.findAll(spec, pageRequest);
|
||||
if (page.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (Contract contract : page) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
MessageHolder subHolder = holder.sub(
|
||||
counter.get() + " / " + total + "> " + contract.getCode() + " #" + contract.getId() + "> ");
|
||||
MessageHolderImpl messageHolder = new MessageHolderImpl();
|
||||
try {
|
||||
Contract parent = null;
|
||||
if (contract.getPayWay() == ContractPayWay.PAY) {
|
||||
if (StringUtils.hasText(contract.getParentCode())) {
|
||||
parent = contractCtx.findContractByCode(contract.getParentCode());
|
||||
}
|
||||
}
|
||||
AtomicReference<Contract> contractProperty = new AtomicReference<>(contract);
|
||||
boolean repaired = repair(contractProperty, parent, messageHolder, progress -> {
|
||||
});
|
||||
String msg = messageHolder.messages.stream()
|
||||
.filter(v -> v.getLevel().intValue() > Level.INFO.intValue())
|
||||
.map(Message::getMessage)
|
||||
.collect(Collectors.joining(", "));
|
||||
if (StringUtils.hasText(msg)) {
|
||||
if (repaired) {
|
||||
subHolder.info(msg);
|
||||
} else {
|
||||
subHolder.error(msg);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
subHolder.error("修复失败 #" + contract.getCode() + ": " + e.getMessage());
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(contract.getCode(), e);
|
||||
}
|
||||
}
|
||||
updateProgress(counter.incrementAndGet(), total);
|
||||
}
|
||||
if (!page.hasNext()) {
|
||||
break;
|
||||
}
|
||||
pageRequest = page.nextPageable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.ecep.contract.ds.contract.tasker;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.cloud.u8.YongYouU8Service;
|
||||
import com.ecep.contract.cloud.u8.ctx.CustomerCtx;
|
||||
import com.ecep.contract.cloud.u8.ctx.VendorCtx;
|
||||
import com.ecep.contract.constant.CloudServiceConstant;
|
||||
import com.ecep.contract.model.CloudYu;
|
||||
import com.ecep.contract.model.Company;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class ContractRepairByCompanyTask extends AbstContractRepairTasker {
|
||||
@Getter
|
||||
@Setter
|
||||
private Company company;
|
||||
@Setter
|
||||
private YongYouU8Service yongYouU8Service;
|
||||
|
||||
|
||||
@Getter
|
||||
boolean repaired = false;
|
||||
|
||||
@Override
|
||||
protected void repair(MessageHolder holder) {
|
||||
updateTitle("同步修复 " + company.getName() + " 下的所有合同");
|
||||
try {
|
||||
yongYouU8Service = getBean(YongYouU8Service.class);
|
||||
} catch (BeansException e) {
|
||||
holder.warn("未启用 " + CloudServiceConstant.U8_NAME + " 服务");
|
||||
return;
|
||||
}
|
||||
|
||||
CloudYu cloudYu = yongYouU8Service.getOrCreateCloudYu(company);
|
||||
if (cloudYu == null) {
|
||||
holder.error("无法创建或获取 CloudYu 对象");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
VendorCtx vendorCtx = new VendorCtx();
|
||||
vendorCtx.from(contractCtx);
|
||||
if (vendorCtx.syncVendor(company, holder)) {
|
||||
cloudYu.setVendorUpdateDate(LocalDate.now());
|
||||
repaired = true;
|
||||
}
|
||||
|
||||
CustomerCtx customerCtx = new CustomerCtx();
|
||||
customerCtx.from(contractCtx);
|
||||
if (customerCtx.syncCustomer(company, holder)) {
|
||||
cloudYu.setCustomerUpdateDate(LocalDate.now());
|
||||
repaired = true;
|
||||
}
|
||||
|
||||
cloudYu.setCloudLatest(Instant.now());
|
||||
cloudYu.setExceptionMessage("");
|
||||
} catch (Exception e) {
|
||||
cloudYu.setExceptionMessage(e.getMessage());
|
||||
} finally {
|
||||
cloudYu.setLatestUpdate(Instant.now());
|
||||
yongYouU8Service.save(cloudYu);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.ecep.contract.ds.contract.tasker;
|
||||
|
||||
import static com.ecep.contract.SpringApp.getBean;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.SpringApp;
|
||||
import com.ecep.contract.ds.company.CompanyFileUtils;
|
||||
import com.ecep.contract.ds.company.service.CompanyService;
|
||||
import com.ecep.contract.ds.contract.service.ContractService;
|
||||
import com.ecep.contract.ds.project.service.ProjectService;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.ContractCatalog;
|
||||
import com.ecep.contract.model.Project;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Setter;
|
||||
|
||||
@Data
|
||||
public class ContractRepairComm {
|
||||
@Setter
|
||||
private ProjectService projectService;
|
||||
@Setter
|
||||
private CompanyService companyService;
|
||||
@Setter
|
||||
private ContractService contractService;
|
||||
|
||||
public ContractService getContractService() {
|
||||
if (contractService == null) {
|
||||
contractService = getBean(ContractService.class);
|
||||
}
|
||||
return contractService;
|
||||
}
|
||||
|
||||
public ProjectService getProjectService() {
|
||||
if (projectService == null) {
|
||||
projectService = SpringApp.getBean(ProjectService.class);
|
||||
}
|
||||
return projectService;
|
||||
}
|
||||
|
||||
private CompanyService getCompanyService() {
|
||||
if (companyService == null) {
|
||||
companyService = SpringApp.getBean(CompanyService.class);
|
||||
}
|
||||
return companyService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建合同目录
|
||||
*
|
||||
* @param contract 合同对象
|
||||
* @return 合同目录
|
||||
*/
|
||||
public boolean makePathAbsent(Contract contract, MessageHolder holder) {
|
||||
if (CompanyFileUtils.exists(contract.getPath())) {
|
||||
return false;
|
||||
}
|
||||
File dir = makePath(contract, holder);
|
||||
if (dir == null) {
|
||||
return false;
|
||||
}
|
||||
if (!dir.exists()) {
|
||||
return false;
|
||||
}
|
||||
contract.setPath(dir.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
|
||||
public Contract save(Contract contract) {
|
||||
return getContractService().save(contract);
|
||||
}
|
||||
|
||||
public Project save(Project project) {
|
||||
return getProjectService().save(project);
|
||||
}
|
||||
|
||||
public File makePath(Contract contract, MessageHolder holder) {
|
||||
File parentDir = null;
|
||||
String contractDirName = contract.getCode();
|
||||
|
||||
if (getContractService().isSubContract(contract)) {
|
||||
// 子合同,需要在主合同目录下
|
||||
String parentCode = contract.getParentCode();
|
||||
if (!StringUtils.hasText(parentCode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Contract parent = getContractService().findByCode(parentCode);
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String parentPath = parent.getPath();
|
||||
if (!StringUtils.hasText(parentPath)) {
|
||||
if (makePathAbsent(parent, holder)) {
|
||||
parent = save(parent);
|
||||
parentPath = parent.getPath();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
parentDir = new File(parentPath);
|
||||
} else {
|
||||
// 主合同
|
||||
ContractCatalog catalog = getContractService().findContractCatalogByContract(contract);
|
||||
if (catalog == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
File catalogPath = getContractService().getContractCatalogPath(catalog, contract);
|
||||
if (catalogPath == null) {
|
||||
return null;
|
||||
}
|
||||
parentDir = catalogPath;
|
||||
contractDirName = contract.getCode() + "-" + CompanyFileUtils.escapeFileName(contract.getName());
|
||||
}
|
||||
|
||||
File path = new File(parentDir, contractDirName);
|
||||
if (!path.exists()) {
|
||||
if (!path.mkdir()) {
|
||||
//
|
||||
holder.warn("unable make directory = " + path.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
public Project findProjectById(Integer projectId) {
|
||||
return getProjectService().findById(projectId);
|
||||
}
|
||||
|
||||
public Company findCompanyById(Integer companyId) {
|
||||
return getCompanyService().findById(companyId);
|
||||
}
|
||||
|
||||
public Contract findContractByGuid(String guid) {
|
||||
return contractService.findByGuid(guid);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.ecep.contract.ds.contract.tasker;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.ContractPayWay;
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.model.Contract;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 合同修复任务
|
||||
*/
|
||||
public class ContractRepairTask extends AbstContractRepairTasker {
|
||||
@Getter
|
||||
@Setter
|
||||
private Contract contract;
|
||||
@Getter
|
||||
boolean repaired = false;
|
||||
|
||||
|
||||
private final ContractRepairComm comm = new ContractRepairComm();
|
||||
|
||||
public ContractRepairTask() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void repair(MessageHolder holder) {
|
||||
updateTitle("修复合同 " + contract.toPrettyString());
|
||||
Contract parent = null;
|
||||
|
||||
if (contract.getPayWay() == ContractPayWay.PAY) {
|
||||
if (StringUtils.hasText(contract.getParentCode())) {
|
||||
parent = contractCtx.findContractByCode(contract.getParentCode());
|
||||
}
|
||||
}
|
||||
|
||||
AtomicReference<Contract> contractProperty = new AtomicReference<>(contract);
|
||||
if (repair(contractProperty, parent, holder, progress -> updateProgress(progress, 1))) {
|
||||
repaired = true;
|
||||
}
|
||||
|
||||
setContract(contractProperty.get());
|
||||
|
||||
updateProgress(1, 1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,848 @@
|
||||
package com.ecep.contract.ds.contract.tasker;
|
||||
|
||||
import com.ecep.contract.*;
|
||||
import com.ecep.contract.ds.company.CompanyFileUtils;
|
||||
import com.ecep.contract.ds.company.service.CompanyExtendInfoService;
|
||||
import com.ecep.contract.ds.company.service.CompanyFileService;
|
||||
import com.ecep.contract.ds.company.service.CompanyService;
|
||||
import com.ecep.contract.ds.contract.service.ContractBidVendorService;
|
||||
import com.ecep.contract.ds.contract.service.ContractFileService;
|
||||
import com.ecep.contract.ds.contract.service.ContractService;
|
||||
import com.ecep.contract.ds.contract.service.ExtendVendorInfoService;
|
||||
import com.ecep.contract.ds.customer.service.CompanyCustomerFileService;
|
||||
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
|
||||
import com.ecep.contract.ds.other.service.EmployeeService;
|
||||
import com.ecep.contract.ds.project.ProjectCostImportItemsFromContractsTasker;
|
||||
import com.ecep.contract.ds.project.service.*;
|
||||
import com.ecep.contract.ds.vendor.service.CompanyVendorService;
|
||||
import com.ecep.contract.ds.vendor.service.VendorGroupRequireFileTypeService;
|
||||
import com.ecep.contract.ds.vendor.service.VendorGroupService;
|
||||
import com.ecep.contract.model.*;
|
||||
import com.ecep.contract.util.NumberStringConverter;
|
||||
import lombok.Data;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.NumberFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Data
|
||||
public class ContractVerifyComm {
|
||||
// Project
|
||||
private ProjectService projectService;
|
||||
private ProjectSaleTypeRequireFileTypeService saleTypeRequireFileTypeService;
|
||||
private SaleTypeService saleTypeService;
|
||||
private ProjectCostService projectCostService;
|
||||
private ProjectQuotationService projectQuotationService;
|
||||
private ProjectBidService projectBidService;
|
||||
// Contract
|
||||
private ContractService contractService;
|
||||
private ContractFileService contractFileService;
|
||||
private ContractBidVendorService contractBidVendorService;
|
||||
|
||||
// Company
|
||||
private CompanyService companyService;
|
||||
private CompanyFileService companyFileService;
|
||||
// Vendor
|
||||
private CompanyVendorService companyVendorService;
|
||||
private VendorGroupService vendorGroupService;
|
||||
private VendorGroupRequireFileTypeService vendorGroupRequireFileTypeService;
|
||||
private ExtendVendorInfoService extendVendorInfoService;
|
||||
// Customer
|
||||
private CompanyCustomerService companyCustomerService;
|
||||
private CompanyCustomerFileService companyCustomerFileService;
|
||||
private CompanyExtendInfoService companyExtendInfoService;
|
||||
// Employee
|
||||
private EmployeeService employeeService;
|
||||
|
||||
private ProjectService getProjectService() {
|
||||
if (projectService == null) {
|
||||
projectService = SpringApp.getBean(ProjectService.class);
|
||||
}
|
||||
return projectService;
|
||||
}
|
||||
|
||||
private SaleTypeService getSaleTypeService() {
|
||||
if (saleTypeService == null) {
|
||||
saleTypeService = SpringApp.getBean(SaleTypeService.class);
|
||||
}
|
||||
return saleTypeService;
|
||||
}
|
||||
|
||||
ProjectCostService getProjectCostService() {
|
||||
if (projectCostService == null) {
|
||||
projectCostService = SpringApp.getBean(ProjectCostService.class);
|
||||
}
|
||||
return projectCostService;
|
||||
}
|
||||
|
||||
ProjectQuotationService getProjectQuotationService() {
|
||||
if (projectQuotationService == null) {
|
||||
projectQuotationService = SpringApp.getBean(ProjectQuotationService.class);
|
||||
}
|
||||
return projectQuotationService;
|
||||
}
|
||||
|
||||
ProjectBidService getProjectBidService() {
|
||||
if (projectBidService == null) {
|
||||
projectBidService = SpringApp.getBean(ProjectBidService.class);
|
||||
}
|
||||
return projectBidService;
|
||||
}
|
||||
|
||||
private ProjectSaleTypeRequireFileTypeService getSaleTypeRequireFileTypeService() {
|
||||
if (saleTypeRequireFileTypeService == null) {
|
||||
saleTypeRequireFileTypeService = SpringApp.getBean(ProjectSaleTypeRequireFileTypeService.class);
|
||||
}
|
||||
return saleTypeRequireFileTypeService;
|
||||
}
|
||||
|
||||
public ContractService getContractService() {
|
||||
if (contractService == null) {
|
||||
contractService = SpringApp.getBean(ContractService.class);
|
||||
}
|
||||
return contractService;
|
||||
}
|
||||
|
||||
private ContractFileService getContractFileService() {
|
||||
if (contractFileService == null) {
|
||||
contractFileService = SpringApp.getBean(ContractFileService.class);
|
||||
}
|
||||
return contractFileService;
|
||||
}
|
||||
|
||||
private ContractBidVendorService getContractBidVendorService() {
|
||||
if (contractBidVendorService == null) {
|
||||
contractBidVendorService = SpringApp.getBean(ContractBidVendorService.class);
|
||||
}
|
||||
return contractBidVendorService;
|
||||
}
|
||||
|
||||
private CompanyService getCompanyService() {
|
||||
if (companyService == null) {
|
||||
companyService = SpringApp.getBean(CompanyService.class);
|
||||
}
|
||||
return companyService;
|
||||
}
|
||||
|
||||
private CompanyFileService getCompanyFileService() {
|
||||
if (companyFileService == null) {
|
||||
companyFileService = SpringApp.getBean(CompanyFileService.class);
|
||||
}
|
||||
return companyFileService;
|
||||
}
|
||||
|
||||
private VendorGroupService getVendorGroupService() {
|
||||
if (vendorGroupService == null) {
|
||||
vendorGroupService = SpringApp.getBean(VendorGroupService.class);
|
||||
}
|
||||
return vendorGroupService;
|
||||
}
|
||||
|
||||
private VendorGroupRequireFileTypeService getVendorGroupRequireFileTypeService() {
|
||||
if (vendorGroupRequireFileTypeService == null) {
|
||||
vendorGroupRequireFileTypeService = SpringApp.getBean(VendorGroupRequireFileTypeService.class);
|
||||
}
|
||||
return vendorGroupRequireFileTypeService;
|
||||
}
|
||||
|
||||
private ExtendVendorInfoService getExtendVendorInfoService() {
|
||||
if (extendVendorInfoService == null) {
|
||||
extendVendorInfoService = SpringApp.getBean(ExtendVendorInfoService.class);
|
||||
}
|
||||
return extendVendorInfoService;
|
||||
}
|
||||
|
||||
private CompanyVendorService getCompanyVendorService() {
|
||||
if (companyVendorService == null) {
|
||||
companyVendorService = SpringApp.getBean(CompanyVendorService.class);
|
||||
}
|
||||
return companyVendorService;
|
||||
}
|
||||
|
||||
private CompanyCustomerService getCompanyCustomerService() {
|
||||
if (companyCustomerService == null) {
|
||||
companyCustomerService = SpringApp.getBean(CompanyCustomerService.class);
|
||||
}
|
||||
return companyCustomerService;
|
||||
}
|
||||
|
||||
private CompanyCustomerFileService getCompanyCustomerFileService() {
|
||||
if (companyCustomerFileService == null) {
|
||||
companyCustomerFileService = SpringApp.getBean(CompanyCustomerFileService.class);
|
||||
}
|
||||
return companyCustomerFileService;
|
||||
}
|
||||
|
||||
private CompanyExtendInfoService getCompanyExtendInfoService() {
|
||||
if (companyExtendInfoService == null) {
|
||||
companyExtendInfoService = SpringApp.getBean(CompanyExtendInfoService.class);
|
||||
}
|
||||
return companyExtendInfoService;
|
||||
}
|
||||
|
||||
private EmployeeService getEmployeeService() {
|
||||
if (employeeService == null) {
|
||||
employeeService = SpringApp.getBean(EmployeeService.class);
|
||||
}
|
||||
return employeeService;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Map<ContractFileType, ContractFileTypeLocal> fileTypeLocalMap = null;
|
||||
private Locale locale = Locale.getDefault();
|
||||
private Contract contract;
|
||||
|
||||
/**
|
||||
* 是否验证企业存储目录
|
||||
*/
|
||||
private boolean verifyCompanyPath = true;
|
||||
/**
|
||||
* 是否验证企业状态
|
||||
*/
|
||||
private boolean verifyCompanyStatus = true;
|
||||
/**
|
||||
* 是否验证企业文件(资信报告)
|
||||
*/
|
||||
private boolean verifyCompanyCredit = true;
|
||||
/**
|
||||
* 是否验证客户
|
||||
*/
|
||||
private boolean verifyCustomer = true;
|
||||
/**
|
||||
* 是否验证客户文件(合同文件)
|
||||
*/
|
||||
private boolean verifyCustomerFiles = true;
|
||||
/**
|
||||
* 是否验证客户子合同日期
|
||||
*/
|
||||
private boolean verifyCustomerSubContractDate = true;
|
||||
/**
|
||||
* 是否验证供应商
|
||||
*/
|
||||
private boolean verifyVendor = true;
|
||||
/**
|
||||
* 是否验证供应商文件(供应商合同)
|
||||
*/
|
||||
private boolean verifyVendorFiles = true;
|
||||
|
||||
/**
|
||||
* 合同合规性检测
|
||||
*
|
||||
* @param contract 要验证的合同对象
|
||||
* @param holder 输出
|
||||
*/
|
||||
public void verify(Contract contract, MessageHolder holder) {
|
||||
LocalDate setupDate = contract.getSetupDate();
|
||||
if (setupDate == null) {
|
||||
holder.error("未设置合同提交日期");
|
||||
return;
|
||||
}
|
||||
|
||||
Company company = contract.getCompany();
|
||||
if (company == null) {
|
||||
holder.error("未关联企业");
|
||||
return;
|
||||
}
|
||||
if (!Hibernate.isInitialized(company)) {
|
||||
company = getCompanyService().findById(company.getId());
|
||||
}
|
||||
verify(company, contract, holder);
|
||||
}
|
||||
|
||||
public void verify(Company company, Contract contract, MessageHolder holder) {
|
||||
LocalDate setupDate = contract.getSetupDate();
|
||||
|
||||
Employee employee = contract.getEmployee();
|
||||
if (employee == null) {
|
||||
holder.error("未关联业务员");
|
||||
}
|
||||
|
||||
if (contract.getAmount() == null || contract.getAmount() <= 0) {
|
||||
holder.error("合同金额小于等于0");
|
||||
}
|
||||
|
||||
CompanyExtendInfo companyExtendInfo = getCompanyExtendInfoService().findByCompany(company);
|
||||
|
||||
if (companyExtendInfo.isDisableVerify()) {
|
||||
holder.debug("公司设定不做校验");
|
||||
} else {
|
||||
if (verifyCompanyPath) {
|
||||
if (!CompanyFileUtils.exists(company.getPath())) {
|
||||
holder.error("公司目录未设置");
|
||||
} else {
|
||||
File basePath = getCompanyService().getBasePath();
|
||||
if (!company.getPath().startsWith(basePath.getAbsolutePath())) {
|
||||
holder.error("公司目录未在规定目录下");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (verifyCompanyStatus) {
|
||||
getCompanyService().verifyEnterpriseStatus(company, setupDate, msg -> {
|
||||
holder.error(company.getName() + ":" + msg);
|
||||
});
|
||||
}
|
||||
|
||||
if (verifyCompanyCredit) {
|
||||
getCompanyFileService().verify(company, contract.getSetupDate(), msg -> {
|
||||
holder.error(company.getName() + ":" + msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 合同类型
|
||||
switch (contract.getPayWay()) {
|
||||
case RECEIVE -> {
|
||||
// 销售合同
|
||||
verifyAsCustomer(company, companyExtendInfo, contract, holder);
|
||||
|
||||
// 销售合同下的采购合同
|
||||
List<Contract> list = getContractService().findAllByParent(contract);
|
||||
if (!list.isEmpty()) {
|
||||
for (Contract v : list) {
|
||||
MessageHolder subHolder = holder.sub(v.getCode() + " -> ");
|
||||
subHolder.info("采购合同 : " + v.getName());
|
||||
verify(v, subHolder);
|
||||
if (CompanyFileUtils.exists(v.getPath())) {
|
||||
if (!v.getPath().startsWith(contract.getPath())) {
|
||||
holder.error("合同目录未在规定目录下");
|
||||
}
|
||||
} else {
|
||||
holder.error("合同目录未设置");
|
||||
}
|
||||
}
|
||||
|
||||
DoubleSummaryStatistics statistics = list.stream().mapToDouble(c -> {
|
||||
return Objects.requireNonNullElse(c.getAmount(), 0.0);
|
||||
}).summaryStatistics();
|
||||
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(locale);
|
||||
|
||||
holder.debug("采购合同金额合计:" + numberFormat.format(statistics.getSum()));
|
||||
holder.debug("采购合同金额平均值:" + numberFormat.format(statistics.getAverage()));
|
||||
holder.debug("采购合同金额最大值:" + numberFormat.format(statistics.getMax()));
|
||||
holder.debug("采购合同金额最小值:" + numberFormat.format(statistics.getMin()));
|
||||
if (contract.getAmount() != null && statistics.getSum() > contract.getAmount()) {
|
||||
holder.warn("采购合同金额合计大于销售合同金额");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PAY -> {
|
||||
verifyAsVendor(company, contract, holder);
|
||||
break;
|
||||
}
|
||||
case OTHER -> {
|
||||
holder.error("合同付款类型:其他");
|
||||
break;
|
||||
}
|
||||
default -> {
|
||||
holder.error("合同付款类型:未设置");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyAsVendor(Company company, Contract contract, MessageHolder holder) {
|
||||
// 供应商,检查评价表
|
||||
ExtendVendorInfo vendorInfo = getExtendVendorInfoService().findByContract(contract);
|
||||
if (vendorInfo == null) {
|
||||
ExtendVendorInfo info = getExtendVendorInfoService().newInstanceByContract(contract);
|
||||
vendorInfo = getExtendVendorInfoService().save(info);
|
||||
holder.info("创建供应商信息 #" + vendorInfo.getId());
|
||||
}
|
||||
VendorGroup group = vendorInfo.getGroup();
|
||||
boolean assignedProvider = vendorInfo.isAssignedProvider();
|
||||
if (assignedProvider) {
|
||||
holder.debug("采购信息中设定为指定供应商");
|
||||
}
|
||||
|
||||
if (group != null) {
|
||||
if (!Hibernate.isInitialized(group)) {
|
||||
group = getVendorGroupService().findById(group.getId());
|
||||
vendorInfo.setGroup(group);
|
||||
}
|
||||
}
|
||||
if (verifyCustomerSubContractDate) {
|
||||
// 检查子合同日期是否在销售合同之后
|
||||
if (!vendorInfo.isPrePurchase()) {
|
||||
String parentCode = contract.getParentCode();
|
||||
if (StringUtils.hasText(parentCode)) {
|
||||
Contract parent = getContractService().findByCode(parentCode);
|
||||
if (parent != null) {
|
||||
if (contract.getSetupDate().isBefore(parent.getSetupDate())) {
|
||||
holder.warn("采购合同:" + contract.getCode() + " 提交日期在销售合同之前");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (verifyVendor) {
|
||||
getCompanyVendorService().verify(contract, holder);
|
||||
}
|
||||
|
||||
if (verifyVendorFiles) {
|
||||
holder.debug("核验文件...");
|
||||
verifyVendorFile(group, assignedProvider, contract, holder);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyVendorFile(VendorGroup group, boolean assignedProvider, Contract contract,
|
||||
MessageHolder holder) {
|
||||
if (group == null) {
|
||||
return;
|
||||
}
|
||||
boolean loseFile = false;
|
||||
List<ContractFile> files = getContractFileService().findAllByContract(contract);
|
||||
List<VendorGroupRequireFileType> list = getVendorGroupRequireFileTypeService().findByGroupId(group.getId());
|
||||
if (list != null && !list.isEmpty()) {
|
||||
for (VendorGroupRequireFileType item : list) {
|
||||
ContractFileType fileType = item.getFileType();
|
||||
if (fileType == null) {
|
||||
continue;
|
||||
}
|
||||
if (fileType == ContractFileType.QuotationSheet && assignedProvider
|
||||
&& group.isRequireQuotationSheetForBid()) {
|
||||
continue;
|
||||
}
|
||||
if (!hasFileType(files, fileType)) {
|
||||
holder.error("供应商" + getFileTypeLocalValue(fileType) + "未上传");
|
||||
loseFile = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 供应商比价
|
||||
if (group.isPriceComparison()) {
|
||||
if (assignedProvider) {
|
||||
holder.debug("指定供应商, 跳过供应商比价");
|
||||
} else {
|
||||
boolean requireQuotation = group.isRequireQuotationSheetForBid();
|
||||
List<ContractBidVendor> bidVendors = getContractBidVendorService().findByContract(contract);
|
||||
if (bidVendors == null || bidVendors.isEmpty()) {
|
||||
holder.error("未上报供应商比价");
|
||||
} else {
|
||||
for (ContractBidVendor bidVendor : bidVendors) {
|
||||
ContractFile contractFile = bidVendor.getQuotationSheet();
|
||||
if (contractFile == null) {
|
||||
if (requireQuotation && bidVendor.getCompany().equals(contract.getCompany())) {
|
||||
holder.debug("供应商类型启用了允许选中供应商不必须要有报价表");
|
||||
} else {
|
||||
holder.error("供应商比价:" + bidVendor.getCompany().getName() + " 未上传/关联报价表");
|
||||
loseFile = true;
|
||||
}
|
||||
} else {
|
||||
if (!Hibernate.isInitialized(contractFile)) {
|
||||
contractFile = getContractFileService().findById(contractFile.getId());
|
||||
}
|
||||
ContractFileType type = contractFile.getType();
|
||||
if (type != ContractFileType.QuotationSheet) {
|
||||
holder.error("供应商比价:" + contractFile.getFileName() + " 报价表记录异常,类型错误");
|
||||
}
|
||||
File file = new File(contract.getPath(), contractFile.getFileName());
|
||||
if (!file.exists()) {
|
||||
holder.error("供应商比价:" + file.getName() + " 报价表记录异常,文件不存在");
|
||||
loseFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (loseFile && files.isEmpty()) {
|
||||
holder.warn("!上传文件空!");
|
||||
}
|
||||
}
|
||||
|
||||
ContractFileTypeLocal getFileTypeLocal(ContractFileType type) {
|
||||
if (fileTypeLocalMap == null) {
|
||||
fileTypeLocalMap = getContractFileService().findAllFileTypes(getLocale().toLanguageTag());
|
||||
}
|
||||
return fileTypeLocalMap.get(type);
|
||||
}
|
||||
|
||||
String getFileTypeLocalValue(ContractFileType type) {
|
||||
ContractFileTypeLocal fileTypeLocal = getFileTypeLocal(type);
|
||||
if (fileTypeLocal == null) {
|
||||
return type.name();
|
||||
}
|
||||
return fileTypeLocal.getValue();
|
||||
}
|
||||
|
||||
private boolean hasFileType(List<ContractFile> files, ContractFileType fileType) {
|
||||
if (files == null || files.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (ContractFile file : files) {
|
||||
if (file.getType() == fileType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void verifyAsCustomer(Company company, CompanyExtendInfo companyExtendInfo, Contract contract,
|
||||
MessageHolder holder) {
|
||||
boolean valiad = true;
|
||||
Project project = contract.getProject();
|
||||
if (project == null) {
|
||||
// 收款的合同时,检查是否关联了项目,如果没有则创建
|
||||
if (contract.getPayWay() == ContractPayWay.RECEIVE) {
|
||||
project = getProjectService().findByCode(contract.getCode());
|
||||
if (project == null) {
|
||||
holder.info("创建关联项目");
|
||||
try {
|
||||
project = getProjectService().newInstanceByContract(contract);
|
||||
project = getProjectService().save(project);
|
||||
} catch (Exception e) {
|
||||
holder.error("创建关联项目失败: " + e.getMessage());
|
||||
throw new RuntimeException("code=" + contract.getCode(), e);
|
||||
}
|
||||
}
|
||||
contract.setProject(project);
|
||||
contract = getContractService().save(contract);
|
||||
}
|
||||
}
|
||||
if (project != null) {
|
||||
if (!Hibernate.isInitialized(project)) {
|
||||
project = getProjectService().findById(project.getId());
|
||||
// fixed
|
||||
contract.setProject(project);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (project != null) {
|
||||
holder.info("验证项目信息:" + project.getCode() + " " + project.getName());
|
||||
verifyProject(contract, project, holder.sub("项目"));
|
||||
|
||||
ProjectSaleType saleType = project.getSaleType();
|
||||
if (saleType != null) {
|
||||
if (CompanyFileUtils.exists(contract.getPath())) {
|
||||
if (!Hibernate.isInitialized(saleType)) {
|
||||
saleType = getSaleTypeService().findById(saleType.getId());
|
||||
project.setSaleType(saleType);
|
||||
}
|
||||
if (!contract.getPath().startsWith(saleType.getPath())) {
|
||||
holder.error("合同目录未在销售类型目录下");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!companyExtendInfo.isDisableVerify()) {
|
||||
if (!verifyCustomerContract(contract, holder)) {
|
||||
valiad = false;
|
||||
}
|
||||
|
||||
if (verifyCustomerFiles) {
|
||||
holder.debug("核验文件...");
|
||||
if (!verifyContractFileAsCustomer(project, contract, holder)) {
|
||||
valiad = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户,检查评估表
|
||||
*/
|
||||
private boolean verifyCustomerContract(Contract contract, MessageHolder holder) {
|
||||
if (!verifyCustomer) {
|
||||
return false;
|
||||
}
|
||||
boolean valid = true;
|
||||
Company company = contract.getCompany();
|
||||
if (company == null) {
|
||||
holder.warn("合同未关联公司");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
CompanyCustomer companyCustomer = getCompanyCustomerService().findByCompany(company);
|
||||
if (companyCustomer == null) {
|
||||
holder.warn("合同未关联客户");
|
||||
valid = false;
|
||||
} else {
|
||||
if (!StringUtils.hasText(companyCustomer.getPath())) {
|
||||
holder.warn("客户未设置文件夹");
|
||||
valid = false;
|
||||
}
|
||||
LocalDate developDate = companyCustomer.getDevelopDate();
|
||||
if (developDate == null) {
|
||||
holder.warn("客户未设置开发日期");
|
||||
valid = false;
|
||||
}
|
||||
if (!verifyCustomerFileByContract(companyCustomer, contract, holder)) {
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
private boolean verifyCustomerFileByContract(CompanyCustomer companyCustomer, Contract contract,
|
||||
MessageHolder holder) {
|
||||
List<LocalDate> verifyDates = new ArrayList<>();
|
||||
LocalDate minDate = LocalDate.of(2022, 1, 1);
|
||||
LocalDate developDate = companyCustomer.getDevelopDate();
|
||||
if (developDate != null) {
|
||||
if (developDate.isAfter(minDate)) {
|
||||
minDate = developDate;
|
||||
}
|
||||
}
|
||||
if (contract.getSetupDate() != null) {
|
||||
LocalDate setupDate = contract.getSetupDate();
|
||||
if (setupDate.isBefore(developDate)) {
|
||||
holder.error("合同提交日期 " + setupDate + " 早于客户开发日期 " + developDate + ".");
|
||||
return false;
|
||||
}
|
||||
if (setupDate.isBefore(minDate)) {
|
||||
holder.debug("合同提交日期 " + setupDate + " 早于 " + minDate + ", 跳过");
|
||||
} else {
|
||||
verifyDates.add(setupDate);
|
||||
}
|
||||
}
|
||||
if (contract.getStartDate() != null) {
|
||||
LocalDate startDate = contract.getStartDate();
|
||||
if (startDate.isBefore(developDate)) {
|
||||
holder.warn("合同起始日期 " + startDate + " 早于客户开发日期 " + developDate + ".");
|
||||
}
|
||||
|
||||
if (startDate.isBefore(minDate)) {
|
||||
holder.debug("合同起始日期 " + startDate + " 早于 " + minDate + ", 跳过");
|
||||
} else {
|
||||
verifyDates.add(startDate);
|
||||
}
|
||||
}
|
||||
if (contract.getOrderDate() != null) {
|
||||
LocalDate orderDate = contract.getOrderDate();
|
||||
if (orderDate.isBefore(developDate)) {
|
||||
holder.error("合同签订日期 " + orderDate + " 早于客户开发日期 " + developDate + ".");
|
||||
return false;
|
||||
}
|
||||
if (orderDate.isBefore(minDate)) {
|
||||
holder.debug("合同签订日期 " + orderDate + " 早于 " + minDate + ", 跳过");
|
||||
} else {
|
||||
verifyDates.add(orderDate);
|
||||
}
|
||||
}
|
||||
|
||||
if (verifyDates.isEmpty()) {
|
||||
holder.warn("合同没有符合可核验的日期");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 客户
|
||||
List<CompanyCustomerFile> files = getCompanyCustomerFileService().findAllByCustomer(companyCustomer);
|
||||
if (files == null || files.isEmpty()) {
|
||||
holder.warn("未见客户评估表");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (LocalDate verifyDate : verifyDates) {
|
||||
CompanyCustomerFile customerFile = files.stream()
|
||||
.filter(v -> v.getSignDate() != null && v.isValid())
|
||||
.filter(v -> v.getType() == CompanyCustomerFileType.EvaluationForm)
|
||||
.filter(v -> MyDateTimeUtils.dateValidFilter(verifyDate, v.getSignDate(),
|
||||
v.getSignDate().plusYears(1), 7))
|
||||
.findFirst().orElse(null);
|
||||
if (customerFile != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CompanyCustomerFile latestFile = files.stream()
|
||||
.filter(v -> v.getSignDate() != null && v.isValid())
|
||||
.filter(v -> v.getType() == CompanyCustomerFileType.EvaluationForm)
|
||||
.max(Comparator.comparing(CompanyCustomerFile::getSignDate))
|
||||
.orElse(null);
|
||||
|
||||
if (latestFile == null) {
|
||||
holder.error("未匹配的客户评估");
|
||||
return false;
|
||||
}
|
||||
|
||||
holder.error("客户评估已过期,最后一个客户评估报告日期:" + latestFile.getSignDate() + ", 检测日期:"
|
||||
+ verifyDates.stream().map(LocalDate::toString).collect(Collectors.joining(", ")));
|
||||
return false;
|
||||
}
|
||||
|
||||
private void verifyProject(Contract contract, Project project, MessageHolder holder) {
|
||||
ProjectSaleType saleType = project.getSaleType();
|
||||
if (saleType == null) {
|
||||
String code = contract.getCode();
|
||||
if (code != null && code.length() > 5) {
|
||||
saleType = getSaleTypeService().findByCode(code.substring(0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
if (saleType == null) {
|
||||
holder.warn("销售类型未设置");
|
||||
}
|
||||
if (project.getAmount() == null || project.getAmount() <= 0) {
|
||||
holder.error("金额小于等于0");
|
||||
}
|
||||
|
||||
//
|
||||
boolean needImport = false;
|
||||
|
||||
ProjectCost autoCost = getProjectCostService().findAutoCostByProject(project);
|
||||
if (autoCost == null) {
|
||||
// 创建 V0 项目成本
|
||||
ProjectCost cost = getProjectCostService().newInstanceByProject(project);
|
||||
cost.setVersion(0);
|
||||
cost.setApplicant(getEmployeeService().findById(EmployeeService.DEFAULT_SYSTEM_EMPLOYEE_ID));
|
||||
cost.setApplyTime(LocalDateTime.now());
|
||||
cost.setDescription("自动导入");
|
||||
autoCost = getProjectCostService().save(cost);
|
||||
needImport = true;
|
||||
} else {
|
||||
// 检查 V0 项目成本
|
||||
if (autoCost.getGrossProfitMargin() <= 0) {
|
||||
NumberFormat instance = NumberFormat.getNumberInstance(getLocale());
|
||||
instance.setMaximumFractionDigits(2);
|
||||
NumberStringConverter converter = new NumberStringConverter(instance);
|
||||
holder.warn("V0项目成本毛利率异常:" + converter.toString(autoCost.getGrossProfitMargin()) + "<=0%");
|
||||
needImport = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needImport && !autoCost.isImportLock()) {
|
||||
ProjectCostImportItemsFromContractsTasker tasker = new ProjectCostImportItemsFromContractsTasker();
|
||||
tasker.setCost(autoCost);
|
||||
|
||||
// 在类中添加以下依赖,假设使用 Spring Security 来获取当前登录用户
|
||||
// 以下代码替换原有的获取当前用户逻辑,假设用户名即为员工 ID
|
||||
// 需根据实际业务调整 UserDetails 中的信息获取方式
|
||||
tasker.setCurrentUser(() -> {
|
||||
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
String username;
|
||||
if (principal instanceof UserDetails) {
|
||||
username = ((UserDetails) principal).getUsername();
|
||||
} else {
|
||||
username = principal.toString();
|
||||
}
|
||||
try {
|
||||
return getEmployeeService().findByName(username);
|
||||
} catch (NumberFormatException e) {
|
||||
// 处理转换失败的情况,可根据实际需求调整
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
autoCost.setApplyTime(LocalDateTime.now());
|
||||
holder.debug("更新V0项目成本");
|
||||
SpringApp.getTaskMonitorCenter().registerAndStartTask(tasker);
|
||||
}
|
||||
|
||||
// 检查最新的项目成本,默认 V1
|
||||
ProjectCost latestCost = getProjectCostService().findLatestByProject(project);
|
||||
if (latestCost == null) {
|
||||
ProjectCost cost = getProjectCostService().newInstanceByProject(project);
|
||||
cost.setVersion(1);
|
||||
Employee applicant = project.getApplicant();
|
||||
if (applicant == null) {
|
||||
applicant = contract.getEmployee();
|
||||
}
|
||||
cost.setApplicant(applicant);
|
||||
cost.setApplyTime(project.getCreated().atTime(LocalTime.now()));
|
||||
latestCost = getProjectCostService().save(cost);
|
||||
} else {
|
||||
//
|
||||
if (latestCost.getGrossProfitMargin() <= 0) {
|
||||
NumberFormat instance = NumberFormat.getNumberInstance(getLocale());
|
||||
instance.setMaximumFractionDigits(2);
|
||||
NumberStringConverter converter = new NumberStringConverter(instance);
|
||||
holder.warn("V" + latestCost.getVersion() + "项目成本毛利率异常:"
|
||||
+ converter.toString(latestCost.getGrossProfitMargin()) + "<=0%");
|
||||
} else if (latestCost.getGrossProfitMargin() >= 50) {
|
||||
NumberFormat instance = NumberFormat.getNumberInstance(getLocale());
|
||||
instance.setMaximumFractionDigits(2);
|
||||
NumberStringConverter converter = new NumberStringConverter(instance);
|
||||
holder.warn("V" + latestCost.getVersion() + "项目成本毛利率异常:"
|
||||
+ converter.toString(latestCost.getGrossProfitMargin()) + ">=50%");
|
||||
}
|
||||
}
|
||||
|
||||
if (project.isUseBid()) {
|
||||
List<ProjectBid> bids = getProjectBidService().findAllByProject(project);
|
||||
if (bids.isEmpty()) {
|
||||
holder.warn("投标未创建");
|
||||
}
|
||||
}
|
||||
if (project.isUseOffer()) {
|
||||
List<ProjectQuotation> quotations = getProjectQuotationService().findAllByProject(project);
|
||||
if (quotations.isEmpty()) {
|
||||
holder.warn("报价未创建");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean verifyContractFileAsCustomer(Project project, Contract contract, MessageHolder holder) {
|
||||
boolean loseFile = false;
|
||||
List<ContractFile> files = getContractFileService().findAllByContract(contract);
|
||||
if (project != null) {
|
||||
// 投标
|
||||
if (project.isUseBid()) {
|
||||
// 投标审批表
|
||||
if (!hasFileType(files, ContractFileType.BidApprovalForm)) {
|
||||
holder.error(getFileTypeLocalValue(ContractFileType.BidApprovalForm) + "未上传");
|
||||
loseFile = true;
|
||||
}
|
||||
// 中标通知书
|
||||
if (!hasFileType(files, ContractFileType.BidAcceptanceLetter)) {
|
||||
holder.error(getFileTypeLocalValue(ContractFileType.BidAcceptanceLetter) + "未上传");
|
||||
loseFile = true;
|
||||
}
|
||||
}
|
||||
// 报价
|
||||
if (project.isUseOffer()) {
|
||||
if (!hasFileType(files, ContractFileType.QuotationApprovalForm)) {
|
||||
holder.error(getFileTypeLocalValue(ContractFileType.QuotationApprovalForm) + "未上传");
|
||||
loseFile = true;
|
||||
}
|
||||
}
|
||||
|
||||
ProjectSaleType saleType = project.getSaleType();
|
||||
if (saleType != null) {
|
||||
List<ProjectSaleTypeRequireFileType> list = getSaleTypeRequireFileTypeService()
|
||||
.findBySaleTypeId(saleType.getId());
|
||||
for (ProjectSaleTypeRequireFileType item : list) {
|
||||
ContractFileType fileType = item.getFileType();
|
||||
if (fileType != null) {
|
||||
if (!hasFileType(files, fileType)) {
|
||||
holder.error(getFileTypeLocalValue(fileType) + "未上传");
|
||||
loseFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!Hibernate.isInitialized(saleType)) {
|
||||
saleType = getSaleTypeService().findById(saleType.getId());
|
||||
}
|
||||
if (saleType.isCriticalProjectDecision()) {
|
||||
if (contract.getAmount() != null && contract.getAmount() >= saleType.getCriticalProjectLimit()) {
|
||||
holder.debug("合同金额 " + contract.getAmount() + " 超过 " + saleType.getCriticalProjectLimit());
|
||||
if (!hasFileType(files, ContractFileType.CriticalProjectDecisionRecord)) {
|
||||
holder.error(getFileTypeLocalValue(ContractFileType.CriticalProjectDecisionRecord) + "未上传");
|
||||
loseFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (loseFile && files.isEmpty()) {
|
||||
holder.warn("!上传文件空!");
|
||||
}
|
||||
|
||||
return !loseFile;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.ecep.contract.ds.contract.tasker;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.ds.contract.service.ContractService;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.ui.Tasker;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class ContractVerifyTasker extends Tasker<Object> {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private Contract contract;
|
||||
ContractVerifyComm comm = new ContractVerifyComm();
|
||||
|
||||
AtomicBoolean verified = new AtomicBoolean(true);
|
||||
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
updateTitle("验证合同 " + contract.getCode() + " 及其子合同是否符合合规要求");
|
||||
return execute(new MessageHolderImpl() {
|
||||
@Override
|
||||
public void addMessage(Level level, String message) {
|
||||
super.addMessage(level, message);
|
||||
if (level.intValue() > Level.INFO.intValue()) {
|
||||
verified.set(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object execute(MessageHolder holder) {
|
||||
comm.verify(contract, holder);
|
||||
if (verified.get()) {
|
||||
updateMessage(Level.CONFIG, "合规验证通过");
|
||||
} else {
|
||||
updateMessage(Level.SEVERE, "合规验证不通过");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void setContractService(ContractService contractService) {
|
||||
comm.setContractService(contractService);
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return comm.getLocale();
|
||||
}
|
||||
|
||||
public void setLocale(Locale locale) {
|
||||
comm.setLocale(locale);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
package com.ecep.contract.ds.contract.tasker;
|
||||
|
||||
import static com.ecep.contract.util.ExcelUtils.setCellValue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.SpringApp;
|
||||
import com.ecep.contract.ds.project.service.DeliverySignMethodService;
|
||||
import com.ecep.contract.ds.project.service.ProductTypeService;
|
||||
import com.ecep.contract.ds.project.service.ProjectCostItemService;
|
||||
import com.ecep.contract.ds.project.service.ProjectCostService;
|
||||
import com.ecep.contract.ds.project.service.ProjectIndustryService;
|
||||
import com.ecep.contract.ds.project.service.ProjectService;
|
||||
import com.ecep.contract.ds.project.service.ProjectTypeService;
|
||||
import com.ecep.contract.ds.project.service.SaleTypeService;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.Contract;
|
||||
import com.ecep.contract.model.Employee;
|
||||
import com.ecep.contract.model.ProductType;
|
||||
import com.ecep.contract.model.Project;
|
||||
import com.ecep.contract.model.ProjectCost;
|
||||
import com.ecep.contract.model.ProjectCostItem;
|
||||
import com.ecep.contract.model.ProjectIndustry;
|
||||
import com.ecep.contract.model.ProjectSaleType;
|
||||
import com.ecep.contract.model.ProjectType;
|
||||
import com.ecep.contract.ui.Tasker;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 合同成本审批表更新任务
|
||||
* 成本审批表为Excel文件,默认更新 #matchedSheetName(成本) sheet,如果没有匹配名称的sheet,则尝试使用第一个sheet
|
||||
*
|
||||
*/
|
||||
public class CustomerContractCostFormUpdateTask extends Tasker<Object> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CustomerContractCostFormUpdateTask.class);
|
||||
|
||||
/**
|
||||
* 对应的合同
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Contract contract;
|
||||
/**
|
||||
* 成本表文件名
|
||||
*/
|
||||
@Setter
|
||||
private String fileName;
|
||||
/**
|
||||
* 模板文件名
|
||||
*/
|
||||
@Setter
|
||||
private String template;
|
||||
/**
|
||||
* 填写日期
|
||||
*/
|
||||
@Setter
|
||||
private LocalDate applyDate;
|
||||
/**
|
||||
* 目标文件
|
||||
*/
|
||||
private File destFile;
|
||||
|
||||
|
||||
/**
|
||||
* 用于匹配成本审批表的Sheet名字,第一包含字符的sheet为要更新的sheet
|
||||
*/
|
||||
@Setter
|
||||
private String matchedSheetName = "成本";
|
||||
@Setter
|
||||
private ProjectService projectService;
|
||||
@Setter
|
||||
private ProjectTypeService projectTypeService;
|
||||
@Setter
|
||||
private SaleTypeService saleTypeService;
|
||||
@Setter
|
||||
private ProjectIndustryService projectIndustryService;
|
||||
@Setter
|
||||
private ProductTypeService productTypeService;
|
||||
@Setter
|
||||
private DeliverySignMethodService deliverySignMethodService;
|
||||
@Setter
|
||||
private ProjectCostService costService;
|
||||
@Setter
|
||||
private ProjectCostItemService costItemService;
|
||||
|
||||
private ProjectService getProjectService() {
|
||||
if (projectService == null) {
|
||||
projectService = SpringApp.getBean(ProjectService.class);
|
||||
}
|
||||
return projectService;
|
||||
}
|
||||
|
||||
private ProjectTypeService getProjectTypeService() {
|
||||
if (projectTypeService == null) {
|
||||
projectTypeService = SpringApp.getBean(ProjectTypeService.class);
|
||||
}
|
||||
return projectTypeService;
|
||||
}
|
||||
|
||||
private SaleTypeService getSaleTypeService() {
|
||||
if (saleTypeService == null) {
|
||||
saleTypeService = SpringApp.getBean(SaleTypeService.class);
|
||||
}
|
||||
return saleTypeService;
|
||||
}
|
||||
|
||||
private ProjectIndustryService getProjectIndustryService() {
|
||||
if (projectIndustryService == null) {
|
||||
projectIndustryService = SpringApp.getBean(ProjectIndustryService.class);
|
||||
}
|
||||
return projectIndustryService;
|
||||
}
|
||||
|
||||
private ProductTypeService getProductTypeService() {
|
||||
if (productTypeService == null) {
|
||||
productTypeService = SpringApp.getBean(ProductTypeService.class);
|
||||
}
|
||||
return productTypeService;
|
||||
}
|
||||
|
||||
private DeliverySignMethodService getDeliverySignMethodService() {
|
||||
if (deliverySignMethodService == null) {
|
||||
deliverySignMethodService = SpringApp.getBean(DeliverySignMethodService.class);
|
||||
}
|
||||
return deliverySignMethodService;
|
||||
}
|
||||
|
||||
private ProjectCostService getCostService() {
|
||||
if (costService == null) {
|
||||
costService = SpringApp.getBean(ProjectCostService.class);
|
||||
}
|
||||
return costService;
|
||||
}
|
||||
private ProjectCostItemService getCostItemService() {
|
||||
if (costItemService == null) {
|
||||
costItemService = SpringApp.getBean(ProjectCostItemService.class);
|
||||
}
|
||||
return costItemService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object execute(MessageHolder holder) throws Exception {
|
||||
updateCostForm(holder);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateCostForm(MessageHolder holder) {
|
||||
if (!StringUtils.hasText(contract.getPath())) {
|
||||
holder.error("供应商目录未设置,请先设置供应商目录");
|
||||
return;
|
||||
}
|
||||
|
||||
File templateFile = new File(template);
|
||||
if (!templateFile.exists()) {
|
||||
holder.warn("评价表模板文件 " + templateFile.getAbsolutePath() + " 不存在,请检查");
|
||||
return;
|
||||
}
|
||||
String template_file_name = templateFile.getName();
|
||||
File dir = new File(contract.getPath());
|
||||
|
||||
destFile = new File(dir, fileName);
|
||||
if (destFile.exists()) {
|
||||
holder.debug("表单文件已经存在,尝试更新...");
|
||||
try (
|
||||
InputStream inp = new FileInputStream(destFile);
|
||||
Workbook wb = WorkbookFactory.create(inp)
|
||||
) {
|
||||
updateCustomerContractCost(wb, holder);
|
||||
holder.info(fileName + "已更新");
|
||||
} catch (Exception e) {
|
||||
holder.error(e.getMessage());
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
} else {
|
||||
holder.debug("根据模板 " + template_file_name + " 创建表单 " + destFile.getName());
|
||||
try (
|
||||
InputStream inp = new FileInputStream(template);
|
||||
Workbook wb = WorkbookFactory.create(inp)
|
||||
) {
|
||||
updateCustomerContractCost(wb, holder);
|
||||
holder.info(fileName + "已更新");
|
||||
} catch (Exception e) {
|
||||
holder.error(e.getMessage());
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void updateCustomerContractCost(
|
||||
Workbook wb,
|
||||
MessageHolder holder) throws IOException {
|
||||
|
||||
Sheet sheet = null;
|
||||
if (StringUtils.hasText(matchedSheetName)) {
|
||||
for (Sheet v : wb) {
|
||||
if (v.getSheetName().contains(matchedSheetName)) {
|
||||
sheet = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sheet == null) {
|
||||
holder.error("检查模板文件,找不到成本页");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
sheet = wb.getSheetAt(0);
|
||||
}
|
||||
|
||||
updateCustomerContractCost(sheet);
|
||||
|
||||
// 输出到文件
|
||||
try (OutputStream fileOut = new FileOutputStream(destFile)) {
|
||||
wb.write(fileOut);
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
holder.error("写文件时发生错误:" + e.getMessage());
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCustomerContractCost(Sheet sheet) {
|
||||
// 项目名
|
||||
String projectName = contract.getName();
|
||||
Project project = contract.getProject();
|
||||
//销售类型
|
||||
ProjectSaleType saleType = null;
|
||||
// 项目类型
|
||||
ProjectType projectType = null;
|
||||
// 使用场所
|
||||
ProjectIndustry industry = null;
|
||||
// 销售类别
|
||||
ProductType productType = null;
|
||||
// 项目地址
|
||||
String address = null;
|
||||
if (project != null) {
|
||||
if (!Hibernate.isInitialized(project)) {
|
||||
project = getProjectService().findById(project.getId());
|
||||
contract.setProject(project);
|
||||
}
|
||||
projectName = project.getName();
|
||||
|
||||
saleType = project.getSaleType();
|
||||
if (saleType != null) {
|
||||
if (!Hibernate.isInitialized(saleType)) {
|
||||
saleType = getSaleTypeService().findById(saleType.getId());
|
||||
project.setSaleType(saleType);
|
||||
}
|
||||
}
|
||||
|
||||
projectType = project.getProjectType();
|
||||
if (projectType != null) {
|
||||
if (!Hibernate.isInitialized(projectType)) {
|
||||
projectType = getProjectTypeService().findById(projectType.getId());
|
||||
project.setProjectType(projectType);
|
||||
}
|
||||
}
|
||||
|
||||
industry = project.getIndustry();
|
||||
if (industry != null) {
|
||||
if (!Hibernate.isInitialized(industry)) {
|
||||
industry = getProjectIndustryService().findById(industry.getId());
|
||||
project.setIndustry(industry);
|
||||
}
|
||||
}
|
||||
|
||||
productType = project.getProductType();
|
||||
if (productType != null) {
|
||||
if (!Hibernate.isInitialized(productType)) {
|
||||
productType = getProductTypeService().findById(productType.getId());
|
||||
project.setProductType(productType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
address = project.getAddress();
|
||||
}
|
||||
|
||||
// 项目名称
|
||||
setCellValue(sheet, "C5", projectName);
|
||||
|
||||
setCellValue(sheet, "M5", saleType == null ? "" : saleType.getName());
|
||||
setCellValue(sheet, "I5", projectType == null ? "" : projectType.getName());
|
||||
setCellValue(sheet, "M6", industry == null ? "" : industry.getName());
|
||||
setCellValue(sheet, "I6", productType == null ? "" : productType.getName());
|
||||
|
||||
setCellValue(sheet, "C7", address);
|
||||
|
||||
|
||||
// 买方
|
||||
Company company = contract.getCompany();
|
||||
if (company != null) {
|
||||
if (!Hibernate.isInitialized(company)) {
|
||||
company = getCompanyService().findById(company.getId());
|
||||
contract.setCompany(company);
|
||||
}
|
||||
setCellValue(sheet, "C6", company.getName());
|
||||
}
|
||||
|
||||
// 销售员
|
||||
Employee employee = contract.getEmployee();
|
||||
if (employee != null) {
|
||||
if (!Hibernate.isInitialized(employee)) {
|
||||
employee = getEmployeeService().findById(employee.getId());
|
||||
contract.setEmployee(employee);
|
||||
}
|
||||
setCellValue(sheet, "M7", employee.getName());
|
||||
}
|
||||
|
||||
|
||||
float taxAndSurcharges = 11;
|
||||
ProjectCost cost = getCostService().findByContract(contract);
|
||||
if (cost != null) {
|
||||
taxAndSurcharges = cost.getTaxAndSurcharges();
|
||||
if (cost.getApplyTime() != null) {
|
||||
applyDate = cost.getApplyTime().toLocalDate();
|
||||
}
|
||||
}
|
||||
setCellValue(sheet, "D40", taxAndSurcharges + "%");
|
||||
|
||||
float stampTax = 0.03f;
|
||||
setCellValue(sheet, "D39", stampTax + "%");
|
||||
|
||||
List<ProjectCostItem> items = getCostItemService().findByCost(cost);
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
ProjectCostItem item = items.get(i);
|
||||
int row = 10 + i;
|
||||
setCellValue(sheet, row, 0, item.getTitle());
|
||||
setCellValue(sheet, row, 2, item.getSpecification());
|
||||
setCellValue(sheet, row, 3, item.getInQuantity());
|
||||
setCellValue(sheet, row, 4, item.getOutExclusiveTaxPrice());
|
||||
setCellValue(sheet, row, 6, item.getOutTaxRate() / 100);
|
||||
setCellValue(sheet, row, 8, item.getInExclusiveTaxPrice());
|
||||
setCellValue(sheet, row, 10, item.getInTaxRate() / 100);
|
||||
}
|
||||
|
||||
if (applyDate != null) {
|
||||
setCellValue(sheet, "I7", applyDate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.ecep.contract.ds.customer;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
|
||||
import com.ecep.contract.model.CustomerCatalog;
|
||||
import com.ecep.contract.util.EntityStringConverter;
|
||||
|
||||
public class CustomerClassStringConverter extends EntityStringConverter<CustomerCatalog> {
|
||||
|
||||
private Function<CustomerCatalog, CustomerCatalog> initialized;
|
||||
private Function<String, CustomerCatalog> fromString;
|
||||
|
||||
@Override
|
||||
public String toString(CustomerCatalog cc) {
|
||||
if (cc == null) {
|
||||
return "-";
|
||||
}
|
||||
if (initialized != null && !Hibernate.isInitialized(cc)) {
|
||||
cc = initialized.apply(cc);
|
||||
}
|
||||
return cc.getCode() + " " + cc.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomerCatalog fromString(String string) {
|
||||
if (fromString == null) {
|
||||
return null;
|
||||
}
|
||||
return fromString.apply(string);
|
||||
}
|
||||
|
||||
public void setFromString(Function<String, CustomerCatalog> fromString) {
|
||||
this.fromString = fromString;
|
||||
}
|
||||
|
||||
public void setInitialized(Function<CustomerCatalog, CustomerCatalog> initialized) {
|
||||
this.initialized = initialized;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
select *, PATH, replace(PATH, '\\测试文件夹\\0-资信评估\\', '\\A-客户资信\\') as NEW_PATH
|
||||
from COMPANY_CUSTOMER
|
||||
where PATH like '%\\\\测试文件夹\\\\0-资信评估\\\\%';
|
||||
|
||||
|
||||
update COMPANY_CUSTOMER
|
||||
set PATH = replace(PATH, '\\测试文件夹\\0-资信评估\\', '\\A-客户资信\\')
|
||||
where PATH like '%\\\\测试文件夹\\\\0-资信评估\\\\%';
|
||||
|
||||
|
||||
|
||||
update COMPANY_CUSTOMER_FILE
|
||||
set FILE_PATH = replace(FILE_PATH, '\\测试文件夹\\0-资信评估\\', '\\A-客户资信\\')
|
||||
where FILE_PATH like '%\\\\测试文件夹\\\\0-资信评估\\\\%';
|
||||
|
||||
|
||||
update COMPANY_CUSTOMER_FILE
|
||||
set EDIT_FILE_PATH = replace(EDIT_FILE_PATH, '\\测试文件夹\\0-资信评估\\', '\\A-客户资信\\')
|
||||
where EDIT_FILE_PATH like '%\\\\测试文件夹\\\\0-资信评估\\\\%';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
SELECT CC.ID, c.NAME, CCE.DEV_DATE, T1.*
|
||||
from COMPANY_CUSTOMER CC
|
||||
left join (
|
||||
select CUSTOMER_ID,SIGN_DATE,LEVEL, CREDIT_LEVEL from COMPANY_CUSTOMER_FILE left join COMPANY_CUSTOMER_EVALUATION_FORM_FILE on COMPANY_CUSTOMER_FILE.ID = COMPANY_CUSTOMER_EVALUATION_FORM_FILE.ID
|
||||
where TYPE = 'EvaluationForm' and VALID=true
|
||||
) as T1 on T1.CUSTOMER_ID = CC.ID
|
||||
left join COMPANY_CUSTOMER_ENTITY CCE on CC.ID = CCE.COMPANY_CUSTOMER_ID
|
||||
left join COMPANY c on CC.COMPANY_ID = c.ID
|
||||
|
||||
order by DEV_DATE desc;
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ecep.contract.ds.customer.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.CompanyCustomer;
|
||||
import com.ecep.contract.model.CompanyCustomerEntity;
|
||||
|
||||
@Repository
|
||||
public interface CompanyCustomerEntityRepository extends MyRepository<CompanyCustomerEntity, Integer>
|
||||
{
|
||||
Optional<CompanyCustomerEntity> findByCode(String code);
|
||||
|
||||
List<CompanyCustomerEntity> findByCustomer(CompanyCustomer customer);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ecep.contract.ds.customer.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.CompanyCustomer;
|
||||
import com.ecep.contract.model.CompanyCustomerEvaluationFormFile;
|
||||
|
||||
@Repository
|
||||
public interface CompanyCustomerEvaluationFormFileRepository extends JpaRepository<CompanyCustomerEvaluationFormFile, Integer>, JpaSpecificationExecutor<CompanyCustomerEvaluationFormFile> {
|
||||
|
||||
List<CompanyCustomerEvaluationFormFile> findAllByCustomerFileCustomer(@Param("customer") CompanyCustomer customer);
|
||||
|
||||
@Query(value = "SELECT * FROM COMPANY_CUSTOMER_FILE ccf left join COMPANY_CUSTOMER_EVALUATION_FORM_FILE CCEFF on ccf.ID = CCEFF.ID " +
|
||||
"where ccf.CUSTOMER_ID=:customer and ccf.TYPE=:fileType", nativeQuery = true)
|
||||
List<CompanyCustomerEvaluationFormFile> findAllByCustomerAndType(@Param("customer") int companyCustomerId, @Param("fileType") String type);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ecep.contract.ds.customer.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.CompanyCustomerFileType;
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.CompanyCustomer;
|
||||
import com.ecep.contract.model.CompanyCustomerFile;
|
||||
|
||||
@Repository
|
||||
public interface CompanyCustomerFileRepository extends MyRepository<CompanyCustomerFile, Integer> {
|
||||
|
||||
List<CompanyCustomerFile> findAllByCustomer(CompanyCustomer companyCustomer);
|
||||
|
||||
List<CompanyCustomerFile> findAllByCustomerAndType(CompanyCustomer customer, CompanyCustomerFileType type);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ecep.contract.ds.customer.repository;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.CompanyCustomerFileType;
|
||||
import com.ecep.contract.ds.other.repository.BaseEnumEntityRepository;
|
||||
import com.ecep.contract.model.CompanyCustomerFileTypeLocal;
|
||||
|
||||
@Repository
|
||||
public interface CompanyCustomerFileTypeLocalRepository
|
||||
extends BaseEnumEntityRepository<CompanyCustomerFileType, CompanyCustomerFileTypeLocal, Integer> {
|
||||
|
||||
@Override
|
||||
default CompanyCustomerFileType[] getEnumConstants() {
|
||||
return CompanyCustomerFileType.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
default CompanyCustomerFileTypeLocal newEntity() {
|
||||
return new CompanyCustomerFileTypeLocal();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ecep.contract.ds.customer.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyCustomer;
|
||||
|
||||
@Repository
|
||||
public interface CompanyCustomerRepository extends MyRepository<CompanyCustomer, Integer> {
|
||||
|
||||
Optional<CompanyCustomer> findByCompany(Company company);
|
||||
|
||||
@Modifying
|
||||
@Transactional
|
||||
int deleteAllByCompany(Company company);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.ecep.contract.ds.customer.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.repository.ListCrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.CustomerCatalog;
|
||||
|
||||
@Repository
|
||||
public interface CustomerCatalogRepository extends
|
||||
// JDBC interfaces
|
||||
ListCrudRepository<CustomerCatalog, Integer>, PagingAndSortingRepository<CustomerCatalog, Integer> {
|
||||
Optional<CustomerCatalog> findByCode(String code);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.ecep.contract.ds.customer.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.customer.repository.CompanyCustomerEntityRepository;
|
||||
import com.ecep.contract.model.CompanyCustomer;
|
||||
import com.ecep.contract.model.CompanyCustomerEntity;
|
||||
import com.ecep.contract.util.SpecificationUtils;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "company-customer-entity")
|
||||
public class CompanyCustomerEntityService implements IEntityService<CompanyCustomerEntity> {
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyCustomerEntityRepository repository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
@Override
|
||||
public CompanyCustomerEntity findById(Integer id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<CompanyCustomerEntity> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
return SpecificationUtils.andWith(searchText, this::buildSearchSpecification);
|
||||
}
|
||||
|
||||
protected Specification<CompanyCustomerEntity> buildSearchSpecification(String searchText) {
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(
|
||||
builder.like(root.get("name"), "%" + searchText + "%"),
|
||||
builder.like(root.get("abbName"), "%" + searchText + "%"),
|
||||
builder.like(root.get("code"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
|
||||
public List<CompanyCustomerEntity> search(String searchText) {
|
||||
Specification<CompanyCustomerEntity> spec = getSpecification(searchText);
|
||||
return repository.findAll(spec, Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CompanyCustomerEntity> findAll(Specification<CompanyCustomerEntity> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code")
|
||||
})
|
||||
@Override
|
||||
public void delete(CompanyCustomerEntity entity) {
|
||||
repository.delete(entity);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code")
|
||||
})
|
||||
@Override
|
||||
public CompanyCustomerEntity save(CompanyCustomerEntity entity) {
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
public List<CompanyCustomerEntity> findAllByCustomer(CompanyCustomer companyCustomer) {
|
||||
return repository.findByCustomer(companyCustomer);
|
||||
}
|
||||
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public CompanyCustomerEntity findByCustomerCode(String customerCode) {
|
||||
return repository.findByCode(customerCode).orElse(null);
|
||||
}
|
||||
|
||||
public void resetTo(CompanyCustomer from, CompanyCustomer to) {
|
||||
List<CompanyCustomerEntity> entities = repository.findByCustomer(from);
|
||||
for (CompanyCustomerEntity entity : entities) {
|
||||
entity.setCustomer(to);
|
||||
}
|
||||
repository.saveAll(entities);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
package com.ecep.contract.ds.customer.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ecep.contract.CompanyCustomerFileType;
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.SpringApp;
|
||||
import com.ecep.contract.ds.company.service.CompanyBasicService;
|
||||
import com.ecep.contract.ds.contract.service.ContractService;
|
||||
import com.ecep.contract.ds.customer.repository.CompanyCustomerEvaluationFormFileRepository;
|
||||
import com.ecep.contract.ds.customer.repository.CompanyCustomerFileRepository;
|
||||
import com.ecep.contract.ds.other.service.SysConfService;
|
||||
import com.ecep.contract.model.CompanyCustomer;
|
||||
import com.ecep.contract.model.CompanyCustomerEvaluationFormFile;
|
||||
import com.ecep.contract.model.CompanyCustomerFile;
|
||||
import com.ecep.contract.model.Contract;
|
||||
|
||||
import jakarta.persistence.criteria.Path;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "company-customer-file")
|
||||
public class CompanyCustomerFileService implements IEntityService<CompanyCustomerFile> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerFileService.class);
|
||||
/**
|
||||
* 客户资信评估表
|
||||
*/
|
||||
public static final String KEY_EVALUATION_FORM_TEMPLATE = "customer.evaluation.form.template";
|
||||
@Lazy
|
||||
@Autowired
|
||||
private SysConfService confService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyCustomerFileRepository companyCustomerFileRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyCustomerEvaluationFormFileRepository companyCustomerEvaluationFormFileRepository;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public CompanyCustomerFile findById(Integer id) {
|
||||
return companyCustomerFileRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<CompanyCustomerFile> getSpecification(String searchText) {
|
||||
return (root, query, builder) -> {
|
||||
return builder.or(builder.like(root.get("filePath"), "%" + searchText + "%"));
|
||||
};
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
}
|
||||
)
|
||||
public void delete(CompanyCustomerFile file) {
|
||||
if (file.getType() == CompanyCustomerFileType.EvaluationForm) {
|
||||
companyCustomerEvaluationFormFileRepository.deleteById(file.getId());
|
||||
}
|
||||
companyCustomerFileRepository.delete(file);
|
||||
}
|
||||
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
}
|
||||
)
|
||||
public CompanyCustomerFile save(CompanyCustomerFile dbFile) {
|
||||
return companyCustomerFileRepository.save(dbFile);
|
||||
}
|
||||
|
||||
public CompanyCustomerEvaluationFormFile save(CompanyCustomerEvaluationFormFile formFile) {
|
||||
return companyCustomerEvaluationFormFileRepository.save(formFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CompanyCustomerFile> findAll(Specification<CompanyCustomerFile> spec, Pageable pageable) {
|
||||
return companyCustomerFileRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public List<CompanyCustomerFile> findAllByCustomer(CompanyCustomer customer) {
|
||||
return companyCustomerFileRepository.findAllByCustomer(customer);
|
||||
}
|
||||
|
||||
public void deleteById(int id) {
|
||||
Optional<CompanyCustomerFile> optional = companyCustomerFileRepository.findById(id);
|
||||
if (optional.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
CompanyCustomerFile customerFile = optional.get();
|
||||
if (customerFile.getType() == CompanyCustomerFileType.EvaluationForm) {
|
||||
companyCustomerEvaluationFormFileRepository.deleteById(id);
|
||||
}
|
||||
companyCustomerFileRepository.delete(customerFile);
|
||||
}
|
||||
|
||||
|
||||
public List<CompanyCustomerFile> findAll(Specification<CompanyCustomerFile> spec, Sort sort) {
|
||||
return companyCustomerFileRepository.findAll(spec, sort);
|
||||
}
|
||||
|
||||
|
||||
public List<CompanyCustomerFile> saveAll(List<CompanyCustomerFile> files) {
|
||||
return companyCustomerFileRepository.saveAll(files);
|
||||
}
|
||||
|
||||
public List<CompanyCustomerFile> findAllByCustomerAndType(CompanyCustomer customer, CompanyCustomerFileType type) {
|
||||
return companyCustomerFileRepository.findAllByCustomerAndType(customer, type);
|
||||
}
|
||||
|
||||
public List<CompanyCustomerEvaluationFormFile> findAllCustomerEvaluationFormFiles(CompanyCustomer companyCustomer) {
|
||||
return findAllByCustomerAndType(companyCustomer, CompanyCustomerFileType.EvaluationForm).stream().map(v -> {
|
||||
return companyCustomerEvaluationFormFileRepository.findById(v.getId()).orElseGet(() -> {
|
||||
CompanyCustomerEvaluationFormFile formFile = new CompanyCustomerEvaluationFormFile();
|
||||
formFile.setCustomerFile(v);
|
||||
formFile.setId(v.getId());
|
||||
return companyCustomerEvaluationFormFileRepository.save(formFile);
|
||||
});
|
||||
}).toList();
|
||||
}
|
||||
|
||||
public CompanyCustomerEvaluationFormFile findCustomerEvaluationFormFileById(int id) {
|
||||
return companyCustomerEvaluationFormFileRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
public CompanyCustomerEvaluationFormFile findCustomerEvaluationFormFileByCustomerFile(CompanyCustomerFile customerFile) {
|
||||
Integer id = customerFile.getId();
|
||||
if (id == null) {
|
||||
CompanyCustomerFile saved = companyCustomerFileRepository.save(customerFile);
|
||||
id = saved.getId();
|
||||
customerFile.setId(id);
|
||||
}
|
||||
|
||||
CompanyCustomerEvaluationFormFile formFile = companyCustomerEvaluationFormFileRepository.findById(id).orElse(null);
|
||||
if (formFile == null) {
|
||||
formFile = new CompanyCustomerEvaluationFormFile();
|
||||
formFile.setId(id);
|
||||
formFile.setCustomerFile(customerFile);
|
||||
companyCustomerEvaluationFormFileRepository.save(formFile);
|
||||
}
|
||||
return formFile;
|
||||
}
|
||||
|
||||
public LocalDate getNextSignDate(CompanyCustomer companyCustomer, Consumer<String> state) {
|
||||
LocalDate miniContractDate = LocalDate.of(2022, 1, 1);
|
||||
// 检索全部合同
|
||||
ContractService contractService = SpringApp.getBean(ContractService.class);
|
||||
List<Contract> contractList = contractService.findAllByCompanyCustomer(companyCustomer, null, null);
|
||||
if (contractList.isEmpty()) {
|
||||
state.accept("未发现已登记的合同");
|
||||
return null;
|
||||
}
|
||||
// 检索评估表
|
||||
List<CompanyCustomerFile> files = findAllByCustomerAndType(companyCustomer, CompanyCustomerFileType.EvaluationForm);
|
||||
CompanyCustomerFile latestFile = files.stream()
|
||||
.filter(v -> v.getSignDate() != null && v.isValid())
|
||||
.max(Comparator.comparing(CompanyCustomerFile::getSignDate))
|
||||
.orElse(null);
|
||||
|
||||
// 没有有效的评估表的评价日期
|
||||
if (latestFile == null) {
|
||||
state.accept("未发现有效的评估表");
|
||||
// 返回最早的合同日期
|
||||
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("最早的合同不存在?");
|
||||
return null;
|
||||
}
|
||||
|
||||
LocalDate setupDate = firstContract.getSetupDate();
|
||||
state.accept("依据合同 " + firstContract.getCode() + " 的日期 " + setupDate + " 推算");
|
||||
return CompanyBasicService.adjustToWorkDay(setupDate.plusDays(-7));
|
||||
}
|
||||
|
||||
// 检查失效日期起的第一个合同
|
||||
LocalDate nextInValidDate = latestFile.getSignDate().plusYears(1);
|
||||
File file = new File(latestFile.getFilePath());
|
||||
state.accept("依据 " + file.getName() + " 的失效期 " + nextInValidDate + " 检索合同");
|
||||
List<Contract> matchedContracts = contractList.stream()
|
||||
.filter(v -> v.getSetupDate().isAfter(nextInValidDate)).toList();
|
||||
// 没有在失效日期后的合同时,使用失效日期
|
||||
if (matchedContracts.isEmpty()) {
|
||||
state.accept("未发现失效期 " + nextInValidDate + " 后的合同");
|
||||
return null;
|
||||
}
|
||||
state.accept("发现匹配合同 " + 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));
|
||||
}
|
||||
|
||||
|
||||
public File getEvaluationFormTemplate() {
|
||||
String path = confService.getString(KEY_EVALUATION_FORM_TEMPLATE);
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
return new File(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定源客户的文件记录转移到目标客户下。
|
||||
*
|
||||
* @param from 源客户对象,其关联的文件将被转移
|
||||
* @param to 目标客户对象,将接收源客户的文件记录
|
||||
*/
|
||||
public void resetTo(CompanyCustomer from, CompanyCustomer to) {
|
||||
List<CompanyCustomerFile> list = companyCustomerFileRepository.findAllByCustomer(from);
|
||||
for (CompanyCustomerFile file : list) {
|
||||
file.setCustomer(to);
|
||||
}
|
||||
companyCustomerFileRepository.saveAll(list);
|
||||
}
|
||||
|
||||
public List<CompanyCustomerEvaluationFormFile> searchEvaluationFile(CompanyCustomer customer, String searchText) {
|
||||
Specification<CompanyCustomerEvaluationFormFile> spec = (root, query, builder) -> {
|
||||
Path<Object> customerFile = root.get("customerFile");
|
||||
return builder.and(
|
||||
builder.isNotNull(customerFile),
|
||||
builder.equal(customerFile.get("customer"), customer),
|
||||
builder.equal(customerFile.get("valid"), true),
|
||||
builder.like(customerFile.get("filePath"), "%" + searchText + "%"));
|
||||
};
|
||||
return companyCustomerEvaluationFormFileRepository.findAll(spec, Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,409 @@
|
||||
package com.ecep.contract.ds.customer.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.ecep.contract.constant.CompanyCustomerConstant;
|
||||
import com.ecep.contract.util.CompanyUtils;
|
||||
import com.ecep.contract.util.FileUtils;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ecep.contract.CompanyCustomerFileType;
|
||||
import com.ecep.contract.IEntityService;
|
||||
import com.ecep.contract.ds.company.CompanyFileUtils;
|
||||
import com.ecep.contract.ds.company.service.CompanyBasicService;
|
||||
import com.ecep.contract.ds.customer.repository.CompanyCustomerEvaluationFormFileRepository;
|
||||
import com.ecep.contract.ds.customer.repository.CompanyCustomerRepository;
|
||||
import com.ecep.contract.ds.customer.repository.CustomerCatalogRepository;
|
||||
import com.ecep.contract.ds.other.service.SysConfService;
|
||||
import com.ecep.contract.model.Company;
|
||||
import com.ecep.contract.model.CompanyBasicFile;
|
||||
import com.ecep.contract.model.CompanyCustomer;
|
||||
import com.ecep.contract.model.CompanyCustomerEntity;
|
||||
import com.ecep.contract.model.CompanyCustomerEvaluationFormFile;
|
||||
import com.ecep.contract.model.CompanyCustomerFile;
|
||||
import com.ecep.contract.model.CustomerCatalog;
|
||||
import com.ecep.contract.util.MyStringUtils;
|
||||
import com.ecep.contract.util.SpecificationUtils;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import jakarta.persistence.criteria.Path;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "company-customer")
|
||||
public class CompanyCustomerService extends CompanyBasicService
|
||||
implements IEntityService<CompanyCustomer> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerService.class);
|
||||
|
||||
public static final String KEY_BASE_PATH = "customer.base.path";
|
||||
public static final String KEY_SALEBOOK_PATH = "customer.salebook.path";
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyCustomerRepository companyCustomerRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyCustomerFileService companyCustomerFileService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyCustomerEvaluationFormFileRepository companyCustomerEvaluationFormFileRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private SysConfService confService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CustomerCatalogRepository customerCatalogRepository;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private CompanyCustomerEntityService companyCustomerEntityService;
|
||||
|
||||
public CompanyCustomer findByCompany(Company company) {
|
||||
return companyCustomerRepository.findByCompany(company).orElse(null);
|
||||
}
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public CompanyCustomer findById(Integer id) {
|
||||
return companyCustomerRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id")
|
||||
})
|
||||
public CompanyCustomer save(CompanyCustomer companyCustomer) {
|
||||
return companyCustomerRepository.save(companyCustomer);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0")
|
||||
})
|
||||
@Override
|
||||
public void delete(CompanyCustomer entity) {
|
||||
companyCustomerRepository.delete(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specification<CompanyCustomer> getSpecification(String searchText) {
|
||||
if (!StringUtils.hasText(searchText)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Specification<CompanyCustomer> nameSpec = (root, query, builder) -> {
|
||||
Path<Company> company = root.get("company");
|
||||
return companyService.buildSearchPredicate(searchText, company, query, builder);
|
||||
};
|
||||
// 判断是否全是数字
|
||||
if (MyStringUtils.isAllDigit(searchText)) {
|
||||
// 全数字就按 Id 查询
|
||||
try {
|
||||
int id = Integer.parseInt(searchText);
|
||||
Specification<CompanyCustomer> idSpec = (root, query, builder) -> {
|
||||
return builder.equal(root.get("id"), id);
|
||||
};
|
||||
nameSpec = nameSpec.or(idSpec);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
List<CompanyCustomerEntity> searched = companyCustomerEntityService.search(searchText);
|
||||
if (!searched.isEmpty()) {
|
||||
nameSpec = SpecificationUtils.or(nameSpec, (root, query, builder) -> {
|
||||
return builder.in(root.get("id")).value(searched.stream()
|
||||
.map(CompanyCustomerEntity::getCustomer)
|
||||
.filter(Objects::nonNull)
|
||||
.map(CompanyCustomer::getId)
|
||||
.collect(Collectors.toSet()));
|
||||
});
|
||||
}
|
||||
return nameSpec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CompanyCustomer> search(String searchText) {
|
||||
Specification<CompanyCustomer> spec = getSpecification(searchText);
|
||||
return companyCustomerRepository.findAll(spec, Pageable.ofSize(10)).getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, F extends CompanyBasicFile<T>, ID> void deleteFile(F file) {
|
||||
CompanyCustomerFile customerFile = (CompanyCustomerFile) file;
|
||||
companyCustomerFileService.delete(customerFile);
|
||||
}
|
||||
|
||||
public File getBasePath() {
|
||||
return new File(confService.getString(KEY_BASE_PATH));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置 客户文件
|
||||
*
|
||||
* @param companyCustomer 客户对象
|
||||
* @param status 输出
|
||||
*/
|
||||
public boolean reBuildingFiles(CompanyCustomer companyCustomer, Consumer<String> status) {
|
||||
List<CompanyCustomerFile> dbFiles = companyCustomerFileService.findAllByCustomer(companyCustomer);
|
||||
Map<String, CompanyCustomerFile> map = new HashMap<>();
|
||||
|
||||
boolean modified = fetchDbFiles(dbFiles, map, status);
|
||||
|
||||
// 客户目录下
|
||||
List<CompanyCustomerFile> retrieveFiles = new ArrayList<>();
|
||||
List<File> needMoveToCompanyPath = new ArrayList<>();
|
||||
|
||||
// TODO 客户有曾用名,可能存在多个目录
|
||||
fetchFiles(companyCustomer.getPath(), needMoveToCompanyPath, retrieveFiles, map, status);
|
||||
|
||||
// 移动文件到公司目录下 to company path
|
||||
moveFileToCompany(companyCustomer.getCompany(), needMoveToCompanyPath);
|
||||
|
||||
status.accept("导入 " + retrieveFiles.size() + " 个文件");
|
||||
|
||||
if (!retrieveFiles.isEmpty()) {
|
||||
// update db
|
||||
retrieveFiles.forEach(v -> v.setCustomer(companyCustomer));
|
||||
companyCustomerFileService.saveAll(retrieveFiles);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, F extends CompanyBasicFile<T>> boolean fillFileAsDefaultType(F dbFile, File file,
|
||||
Consumer<String> status) {
|
||||
dbFile.setType((T) CompanyCustomerFileType.General);
|
||||
fillFile(dbFile, file, null, status);
|
||||
companyCustomerFileService.save((CompanyCustomerFile) dbFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, F extends CompanyBasicFile<T>> boolean fillFileAsEvaluationFile(F customerFile, File file,
|
||||
List<File> fileList, Consumer<String> status) {
|
||||
boolean modified = super.fillFileAsEvaluationFile(customerFile, file, fileList, status);
|
||||
|
||||
if (fileList != null) {
|
||||
File jsonFile = null;
|
||||
// 文件名
|
||||
String fileName = file.getName();
|
||||
// 文件名,不含后缀
|
||||
String name = StringUtils.stripFilenameExtension(fileName);
|
||||
|
||||
String jsonFileName = name + FileUtils.JSON;
|
||||
for (File f : fileList) {
|
||||
// 查找存档文件
|
||||
if (f.getName().equals(jsonFileName)) {
|
||||
jsonFile = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (jsonFile != null) {
|
||||
if (fileList.remove(jsonFile)) {
|
||||
try {
|
||||
updateEvaluationFileByJsonFile(customerFile, jsonFile, status);
|
||||
} catch (IOException e) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
private <T, F extends CompanyBasicFile<T>> void updateEvaluationFileByJsonFile(F customerFile, File jsonFile,
|
||||
Consumer<String> status) throws IOException {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode root = objectMapper.readTree(jsonFile);
|
||||
if (!root.isObject()) {
|
||||
return;
|
||||
}
|
||||
ObjectNode data = (ObjectNode) root;
|
||||
data.remove("file");
|
||||
data.remove("signDate");
|
||||
data.remove("valid");
|
||||
JsonNode type = data.remove("type");
|
||||
|
||||
CompanyCustomerEvaluationFormFile formFile = companyCustomerFileService
|
||||
.findCustomerEvaluationFormFileByCustomerFile((CompanyCustomerFile) customerFile);
|
||||
objectMapper.updateValue(formFile, data);
|
||||
logger.info("load json data from {}", jsonFile.getName());
|
||||
formFile.setCatalog(type.asText());
|
||||
companyCustomerEvaluationFormFileRepository.save(formFile);
|
||||
// companyCustomerEvaluationFormFileRepository.save(formFile);
|
||||
if (jsonFile.delete()) {
|
||||
logger.info("delete json file {}", jsonFile.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, F extends CompanyBasicFile<T>> F fillFileType(File file, List<File> fileList,
|
||||
Consumer<String> status) {
|
||||
CompanyCustomerFile customerFile = new CompanyCustomerFile();
|
||||
customerFile.setType(CompanyCustomerFileType.General);
|
||||
if (fillFile(customerFile, file, fileList, status)) {
|
||||
return (F) customerFile;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, F extends CompanyBasicFile<T>> boolean setFileTypeAsEvaluationForm(F file) {
|
||||
T type = file.getType();
|
||||
if (type != CompanyCustomerFileType.EvaluationForm) {
|
||||
file.setType((T) CompanyCustomerFileType.EvaluationForm);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isEvaluationFile(String fileName) {
|
||||
return (fileName.contains(CompanyCustomerConstant.EVALUATION_FORM_NAME1)
|
||||
|| fileName.contains(CompanyCustomerConstant.EVALUATION_FORM_NAME2))
|
||||
&& (FileUtils.withExtensions(fileName, FileUtils.JPG, FileUtils.JPEG,
|
||||
FileUtils.PDF));
|
||||
}
|
||||
|
||||
public boolean makePathAbsent(CompanyCustomer companyCustomer) {
|
||||
String path = companyCustomer.getPath();
|
||||
if (StringUtils.hasText(path)) {
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
File dir = makePath(companyCustomer);
|
||||
if (dir == null) {
|
||||
return false;
|
||||
}
|
||||
if (!dir.exists()) {
|
||||
return false;
|
||||
}
|
||||
companyCustomer.setPath(dir.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
|
||||
private File makePath(CompanyCustomer companyCustomer) {
|
||||
File basePath = getBasePath();
|
||||
Company company = companyCustomer.getCompany();
|
||||
if (!Hibernate.isInitialized(company)) {
|
||||
company = companyService.findById(company.getId());
|
||||
}
|
||||
|
||||
String companyName = company.getName();
|
||||
String fileName = CompanyUtils.formatCompanyVendorId(companyCustomer.getId()) + "-"
|
||||
+ CompanyFileUtils.escapeFileName(companyName);
|
||||
|
||||
File dir = new File(basePath, fileName);
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdir()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
public Page<CompanyCustomer> findAll(Specification<CompanyCustomer> spec, Pageable pageable) {
|
||||
return companyCustomerRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一个公司的客户信息转移到另一个公司,并保存在数据库中
|
||||
*
|
||||
* @param from 要转移的客户信息所属的公司
|
||||
* @param to 要转移到的公司
|
||||
*/
|
||||
public void resetTo(Company from, Company to) {
|
||||
// 这里使用Optional对象来处理可能为空的情况
|
||||
Optional<CompanyCustomer> fromCustomer = companyCustomerRepository.findByCompany(from);
|
||||
if (fromCustomer.isEmpty()) {
|
||||
// 无效数据
|
||||
return;
|
||||
}
|
||||
Optional<CompanyCustomer> toCustomer = companyCustomerRepository.findByCompany(to);
|
||||
if (toCustomer.isEmpty()) {
|
||||
CompanyCustomer customer = fromCustomer.get();
|
||||
customer.setCompany(to);
|
||||
// 保存更新后的CompanyCustomer对象到数据库
|
||||
companyCustomerRepository.save(customer);
|
||||
return;
|
||||
}
|
||||
|
||||
// 把 fromCustomer 信息合并到 toCustomer
|
||||
resetTo(fromCustomer.get(), toCustomer.get());
|
||||
|
||||
}
|
||||
|
||||
/***
|
||||
* 合并两个CompanyCustomer对象,并将fromCustomer的信息合并到toCustomer中,并保存到数据库中。
|
||||
*
|
||||
* @param from 源客户对象
|
||||
* @param to 目标客户对象
|
||||
*/
|
||||
public void resetTo(CompanyCustomer from, CompanyCustomer to) {
|
||||
// file
|
||||
companyCustomerFileService.resetTo(from, to);
|
||||
// entity
|
||||
companyCustomerEntityService.resetTo(from, to);
|
||||
// 删除源客户对象
|
||||
companyCustomerRepository.delete(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 company 的 客户
|
||||
*/
|
||||
public void deleteByCompany(Company company) {
|
||||
int deleted = companyCustomerRepository.deleteAllByCompany(company);
|
||||
if (deleted > 0) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Delete {} records by company:#{}", deleted, company.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Cacheable(key = "'catalog-'+#p0")
|
||||
public CustomerCatalog findCatalogById(Integer id) {
|
||||
return customerCatalogRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
public List<CustomerCatalog> findAllCatalogs() {
|
||||
return customerCatalogRepository.findAll();
|
||||
}
|
||||
|
||||
@Cacheable(key = "'catalog-code-'+#p0")
|
||||
public CustomerCatalog findCatalogByCode(String code) {
|
||||
return customerCatalogRepository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "'catalog-'+#p0.id"),
|
||||
@CacheEvict(key = "'catalog-code-'+#p0.code")
|
||||
})
|
||||
public CustomerCatalog save(CustomerCatalog catalog) {
|
||||
return customerCatalogRepository.save(catalog);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.ecep.contract.ds.other.controller;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.ecep.contract.ds.other.service.EmployeeService;
|
||||
import com.ecep.contract.model.Employee;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/employee")
|
||||
public class EmployyeController {
|
||||
@Autowired
|
||||
private EmployeeService employeeService;
|
||||
|
||||
@RequestMapping("/findById")
|
||||
public Employee findById(Integer id) {
|
||||
return employeeService.findById(id);
|
||||
}
|
||||
|
||||
@RequestMapping("/list")
|
||||
public Page<Employee> list(
|
||||
Map<String, Object> params,
|
||||
@RequestParam(defaultValue = "0") int pageNumber,
|
||||
@RequestParam(defaultValue = "10") int pageSize) {
|
||||
Specification<Employee> spec = (root, query, cb) -> cb.conjunction();
|
||||
Sort sort = Sort.by(Sort.Order.desc("id"));
|
||||
Pageable pageable = PageRequest.of(pageNumber, pageSize, sort);
|
||||
return employeeService.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
public Employee save(Employee employee) {
|
||||
return employeeService.save(employee);
|
||||
}
|
||||
|
||||
@RequestMapping("/delete")
|
||||
public void delete(Integer id) {
|
||||
Employee employee = employeeService.findById(id);
|
||||
employeeService.delete(employee);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.ecep.contract.ds.other.controller;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
import com.ecep.contract.MessageHolder;
|
||||
import com.ecep.contract.cloud.u8.ctx.InventoryCtx;
|
||||
import com.ecep.contract.ds.other.service.InventoryService;
|
||||
import com.ecep.contract.model.Inventory;
|
||||
import com.ecep.contract.ui.Tasker;
|
||||
|
||||
public class InventorySyncTask extends Tasker<Object> {
|
||||
private InventoryCtx inventoryCtx;
|
||||
|
||||
@Override
|
||||
protected Object execute(MessageHolder holder) throws Exception {
|
||||
inventoryCtx = new InventoryCtx();
|
||||
inventoryCtx.initializeRepository(holder);
|
||||
|
||||
InventoryService service = inventoryCtx.getInventoryService();
|
||||
Pageable pageRequest = PageRequest.ofSize(200);
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
Specification<Inventory> spec = null;
|
||||
long total = service.count(spec);
|
||||
while (true) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
Page<Inventory> page = service.findAll(spec, pageRequest);
|
||||
if (page.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (Inventory inventory : page) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
String prefix = counter.get() + " / " + total + "> #" + inventory.getId() + "> ";
|
||||
MessageHolder subHolder = holder.sub(prefix);
|
||||
syncInventory(inventory, subHolder);
|
||||
|
||||
updateProgress(counter.incrementAndGet(), total);
|
||||
}
|
||||
if (!page.hasNext()) {
|
||||
break;
|
||||
}
|
||||
pageRequest = page.nextPageable();
|
||||
}
|
||||
updateProgress(1, 1);
|
||||
return super.call();
|
||||
}
|
||||
|
||||
private void syncInventory(Inventory inventory, MessageHolder holder) {
|
||||
if (inventoryCtx.syncInventoryDetailByCode(inventory, inventory.getCode(), holder)) {
|
||||
inventoryCtx.getInventoryService().save(inventory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ecep.contract.ds.other.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Bank;
|
||||
|
||||
@Lazy
|
||||
@Repository
|
||||
public interface BankRepository extends MyRepository<Bank, Integer> {
|
||||
Optional<Bank> findFirstByName(String name);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.ecep.contract.ds.other.repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
|
||||
import com.ecep.contract.model.BaseEnumEntity;
|
||||
|
||||
@NoRepositoryBean
|
||||
public interface BaseEnumEntityRepository<N extends Enum<?>, T extends BaseEnumEntity<N>, ID>
|
||||
extends JpaRepository<T, ID> {
|
||||
List<T> findAllByLang(String lang);
|
||||
|
||||
default Map<N, T> getCompleteMapByLocal(String lang) {
|
||||
HashMap<N, T> map = new HashMap<>();
|
||||
for (T t : findAllByLang(lang)) {
|
||||
map.put(t.getType(), t);
|
||||
}
|
||||
|
||||
ArrayList<T> needSaves = new ArrayList<>();
|
||||
for (N type : getEnumConstants()) {
|
||||
T v = map.get(type);
|
||||
if (v == null) {
|
||||
v = newEntity();
|
||||
v.setType(type);
|
||||
v.setLang(lang);
|
||||
v.setValue(type.name());
|
||||
needSaves.add(v);
|
||||
}
|
||||
}
|
||||
if (!needSaves.isEmpty()) {
|
||||
for (T v : saveAll(needSaves)) {
|
||||
map.put(v.getType(), v);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
T newEntity();
|
||||
|
||||
N[] getEnumConstants();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ecep.contract.ds.other.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Department;
|
||||
|
||||
/**
|
||||
* 部门 Repository
|
||||
*/
|
||||
@Lazy
|
||||
@Repository
|
||||
public interface DepartmentRepository extends MyRepository<Department, Integer> {
|
||||
Optional<Department> findByName(String name);
|
||||
|
||||
Optional<Department> findByCode(String code);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.ecep.contract.ds.other.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.Employee;
|
||||
import com.ecep.contract.model.EmployeeAuthBind;
|
||||
|
||||
@Lazy
|
||||
@Repository
|
||||
public interface EmployeeAuthBindRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<EmployeeAuthBind, Integer>, PagingAndSortingRepository<EmployeeAuthBind, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<EmployeeAuthBind, Integer>, JpaSpecificationExecutor<EmployeeAuthBind> {
|
||||
List<EmployeeAuthBind> findAllByEmployee(Employee employee, Sort sort);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ecep.contract.ds.other.repository;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.model.EmployeeLoginHistory;
|
||||
|
||||
@Lazy
|
||||
@Repository
|
||||
public interface EmployeeLoginHistoryRepository extends
|
||||
// JDBC interfaces
|
||||
CrudRepository<EmployeeLoginHistory, Integer>,
|
||||
PagingAndSortingRepository<EmployeeLoginHistory, Integer>,
|
||||
// JPA interfaces
|
||||
JpaRepository<EmployeeLoginHistory, Integer>, JpaSpecificationExecutor<EmployeeLoginHistory> {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.ecep.contract.ds.other.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.Employee;
|
||||
|
||||
@Lazy
|
||||
@Repository
|
||||
public interface EmployeeRepository extends MyRepository<Employee, Integer> {
|
||||
Optional<Employee> findByAccount(String username);
|
||||
|
||||
Optional<Employee> findByName(String name);
|
||||
|
||||
Optional<Employee> findByAlias(String alias);
|
||||
|
||||
Optional<Employee> findByCode(String personCode);
|
||||
|
||||
@Modifying
|
||||
@Query(value = "update EMPLOYEE_LOGIN_HISTORY e set e.LATEST_ACTIVE = now() where e.id = ?1", nativeQuery = true)
|
||||
void updateActive(int sessionId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ecep.contract.ds.other.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.ecep.contract.ds.MyRepository;
|
||||
import com.ecep.contract.model.EmployeeRole;
|
||||
|
||||
@Lazy
|
||||
@Repository
|
||||
public interface EmployeeRoleRepository extends MyRepository<EmployeeRole, Integer> {
|
||||
|
||||
Optional<EmployeeRole> findByName(String name);
|
||||
|
||||
Optional<EmployeeRole> findByCode(String personCode);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user