ContractRunner.java 16.3 KB
package vion.cron;

import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.core.text.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import vion.constant.RedisKeyEnum;
import vion.model.*;
import vion.model.Dictionary;
import vion.service.*;

import java.math.BigDecimal;
import java.sql.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 从crm系统定时同步合同信息
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class ContractRunner {

    private final IContractService contractService;
    private final IDictionaryService dictionaryService;
    private final IContractPaymentService contractPaymentService;
    private final IRContractUserService contractUserService;
    private final IRContractStoreService contractStoreService;
    private final IStoreService storeService;
    private final IPaymentService paymentService;
    private final RedisTemplate redisTemplate;

    @Scheduled(cron = "0 0 * * * *")
    public void contractSync() {
        log.info("【开始】从crm系统同步合同信息");
        Map<String, Contract> no2ContactMap = contractService.list().stream().collect(Collectors.toMap(Contract::getContractNo, Function.identity()));
        Map<String, Integer> contractTypeMap = dictionaryService.lambdaQuery().eq(Dictionary::getType, "contract_type").list()
                .stream().collect(Collectors.toMap(Dictionary::getValue, Dictionary::getKey));

        List<Contract> insOrUpdContractList = new ArrayList<>();
        String modifyTime = Opt.ofNullable((String) redisTemplate.opsForValue().get(RedisKeyEnum.CONTRACT_SYNC_TIME.getVal()))
                .orElse("1970-01-01 00:00:00");
        String url = "jdbc:sqlserver://47.92.144.255:1433;databaseName=UFDATA_001_2020;encrypt=false";
        String username = "vion-reader";
        String password = "vion-reader";
        try (Connection connection = DriverManager.getConnection(url, username, password)) {
            String sql = StrUtil.format(
                    "select t5.hetongpingshen_name as name,t1.hetongluru_name as contract_no,t1.hetongluru_char12 as type,t1.hetongluru_date01 as sign_date,t1.hetongluru_char01 as warranty_period,t1.hetongluru_start_date as maintain_sdate,t1.hetongluru_end_date as maintain_edate,t1.hetongluru_dec01 as total_amount,t5.hetongpingshen_dec02 as sign_ratio,t5.hetongpingshen_dec03 as arrive_ratio,t5.hetongpingshen_dec04 as system_check_ratio,t5.hetongpingshen_dec05 as project_check_ratio,t5.hetongpingshen_dec06 as warranty_ratio,t5.hetongpingshen_dec07 as maintain1_ratio,t5.hetongpingshen_dec09 as maintain2_ratio,t5.hetongpingshen_dec10 as maintain3_ratio,t2.cCusAbbName as customer_name,t4.cUser_Name as sale_name,t1.create_time as entry_time,t5.hetongpingshen_date01 as sign_date1,t5.hetongpingshen_date04 as arrive_date,t5.hetongpingshen_date05 as system_check_date,t5.hetongpingshen_date06 as project_check_date,t5.hetongpingshen_date07 as warranty_date,t5.hetongpingshen_date08 as maintain_date1, t6.hetongpingshen_date09 as maintain_date2,t6.hetongpingshen_date10 as maintain_date3,t1.modify_time as original_mod_time" +
                            " from tcu_hetongluru t1 left join Customer t2 on t1.account_id = t2.cCusCode left join tc_opportunity t3 on t1.hetongluru_char04 = t3.ufcode left join UA_User_Ex t4 on t1.owner_user_id = t4.cUser_Id left join tcu_hetongpingshen t5 on t1.hetongluru_name = t5.hetongpingshen_char05 left join tcu_hetongpingshen_attr t6 on t5.hetongpingshen_id = t6.hetongpingshen_id where t1.modify_time > '{}' order by t1.modify_time desc", modifyTime);
            try (Statement statement = connection.createStatement()) {
                ResultSet resultSet = statement.executeQuery(sql);
                while (resultSet.next()) {
                    String contractNo = resultSet.getString("contract_no");
                    Contract contract = new Contract();
                    Optional.ofNullable(resultSet.getString("name"))
                            .filter(StrUtil::isNotBlank)
                            .ifPresentOrElse(contract::setName, () -> contract.setName(contractNo));

                    contract.setContractNo(contractNo);
                    contract.setType(contractTypeMap.getOrDefault(resultSet.getString("type"), 0));
                    contract.setSignDate(resultSet.getDate("sign_date"));
                    String warrantyPeriod = resultSet.getString("warranty_period");
                    if (StrUtil.isNotBlank(warrantyPeriod) && warrantyPeriod.contains("个月")) {
                        String substring = warrantyPeriod.substring(0, (warrantyPeriod.length() - 2));
                        contract.setWarrantyPeriod(Integer.parseInt(substring));
                    }
                    contract.setMaintainSdate(resultSet.getDate("maintain_sdate"));
                    contract.setMaintainEdate(resultSet.getDate("maintain_edate"));
                    contract.setStatus(1);
                    contract.setTotalAmount(resultSet.getBigDecimal("total_amount"));
                    contract.setSignRatio(resultSet.getBigDecimal("sign_ratio"));
                    contract.setSignDate1(resultSet.getDate("sign_date1"));
                    contract.setArriveRatio(resultSet.getBigDecimal("arrive_ratio"));
                    contract.setArriveDate(resultSet.getDate("arrive_date"));
                    contract.setSystemCheckRatio(resultSet.getBigDecimal("system_check_ratio"));
                    contract.setSystemCheckDate(resultSet.getDate("system_check_date"));
                    contract.setProjectCheckRatio(resultSet.getBigDecimal("project_check_ratio"));
                    contract.setProjectCheckDate(resultSet.getDate("project_check_date"));
                    contract.setWarrantyRatio(resultSet.getBigDecimal("warranty_ratio"));
                    contract.setWarrantyDate(resultSet.getDate("warranty_date"));
                    contract.setMaintainRatio1(resultSet.getBigDecimal("maintain1_ratio"));
                    contract.setMaintainDate1(resultSet.getDate("maintain_date1"));
                    contract.setMaintainRatio2(resultSet.getBigDecimal("maintain2_ratio"));
                    contract.setMaintainDate2(resultSet.getDate("maintain_date2"));
                    contract.setMaintainRatio3(resultSet.getBigDecimal("maintain3_ratio"));
                    contract.setMaintainDate3(resultSet.getDate("maintain_date3"));
                    contract.setPaidAmount(BigDecimal.ZERO);
                    contract.setReceivableAmount(BigDecimal.ZERO);
                    contract.setOutstandingAmount(resultSet.getBigDecimal("total_amount"));
                    contract.setSubject("北京文安智能技术股份有限公司");
                    contract.setCustomerName(resultSet.getString("customer_name"));
                    contract.setSaleName(resultSet.getString("sale_name"));
                    contract.setCreateUser(-1L);
                    contract.setModifyUser(-1L);
                    contract.setEntryTime(resultSet.getTimestamp("entry_time"));
                    contract.setOriginalModTime(resultSet.getTimestamp("original_mod_time"));
                    insOrUpdContractList.add(contract);
                }
            }
        } catch (SQLException e) {
            log.error("合同信息同步失败:", e);
            return;
        }

        if (CollUtil.isEmpty(insOrUpdContractList)) {
            log.info("没有需要插入或更新的合同");
            return;
        }

        List<Long> updContractIdList = new ArrayList<>();
        insOrUpdContractList.forEach(v -> {
            if (no2ContactMap.containsKey(v.getContractNo())) {
                Long contractId = no2ContactMap.get(v.getContractNo()).getId();
                v.setId(contractId);
                // 已有合同不更新状态
                v.setStatus(null);
                updContractIdList.add(contractId);
            }
        });
        // 合同更新,同步调用一下更新项目的维保状态
        Opt.ofEmptyAble(updContractIdList)
                .map(contractIdList -> contractStoreService.lambdaQuery().in(RContractStore::getContractId, contractIdList).list())
                .map(csList -> csList.stream().map(RContractStore::getStoreId).collect(Collectors.toList()))
                .filter(CollUtil::isNotEmpty)
                .ifPresent(storeService::calMaintainStatus);

        contractService.saveOrUpdateBatch(insOrUpdContractList, 500);
        insOrUpdContractList.forEach(v -> {
            // 合同状态不为空,代表此条记录为新增,需要同步销售人信息到 r_contract_user 表中
            if (ObjUtil.isNotNull(v.getStatus())) {
                RContractUser contractUser = new RContractUser();
                String userId = Opt.ofNullable(redisTemplate.opsForValue().get(RedisKeyEnum.DING_PREFIX.getVal() + RedisKeyEnum.USER_NAME.getVal() + v.getSaleName()))
                        .map(u -> (User) u)
                        .map(User::getUserid)
                        .orElse(null);
                contractUser.setUserId(userId);
                contractUser.setUsername(v.getSaleName());
                contractUser.setEnterDate(v.getSignDate());
                contractUser.setContractId(v.getId());
                contractUser.setContractNo(v.getContractNo());
                contractUserService.save(contractUser);
            }
        });

        List<ContractPayment> existContractPaymentList = contractPaymentService.list();
        Map<Long, Map<Integer, Long>> contractId2PaymentMap = existContractPaymentList.stream().collect(Collectors.groupingBy(ContractPayment::getContractId, Collectors.toMap(ContractPayment::getPaymentType, ContractPayment::getId)));

        // 合同付款比例
        List<ContractPayment> contractPaymentList = new ArrayList<>();
        for (Contract contract : insOrUpdContractList) {
            // 签订
            ContractPayment contractSignPayment = new ContractPayment();
            contractSignPayment.setId(contractId2PaymentMap.getOrDefault(contract.getId(), new HashMap<>()).get(1));
            contractSignPayment.setContractId(contract.getId());
            contractSignPayment.setPaymentType(1);
            contractSignPayment.setPaymentRatio(Opt.ofNullable(contract.getSignRatio()).orElse(BigDecimal.ZERO));
            contractSignPayment.setPaymentDate(contract.getSignDate1());
            contractSignPayment.setNodeDate(contract.getSignDate());
            contractPaymentList.add(contractSignPayment);

            // 到货
            ContractPayment contractArrivePayment = new ContractPayment();
            contractArrivePayment.setId(contractId2PaymentMap.getOrDefault(contract.getId(), new HashMap<>()).get(2));
            contractArrivePayment.setContractId(contract.getId());
            contractArrivePayment.setPaymentType(2);
            contractArrivePayment.setPaymentRatio(Opt.ofNullable(contract.getArriveRatio()).orElse(BigDecimal.ZERO));
            contractArrivePayment.setPaymentDate(contract.getArriveDate());
            contractPaymentList.add(contractArrivePayment);

            // 系统验收
            ContractPayment contractSystemCheckPayment = new ContractPayment();
            contractSystemCheckPayment.setId(contractId2PaymentMap.getOrDefault(contract.getId(), new HashMap<>()).get(3));
            contractSystemCheckPayment.setContractId(contract.getId());
            contractSystemCheckPayment.setPaymentType(3);
            contractSystemCheckPayment.setPaymentRatio(Opt.ofNullable(contract.getSystemCheckRatio()).orElse(BigDecimal.ZERO));
            contractSystemCheckPayment.setPaymentDate(contract.getSystemCheckDate());
            contractPaymentList.add(contractSystemCheckPayment);

            // 项目验收
            ContractPayment contractProjectCheckPayment = new ContractPayment();
            contractProjectCheckPayment.setId(contractId2PaymentMap.getOrDefault(contract.getId(), new HashMap<>()).get(4));
            contractProjectCheckPayment.setContractId(contract.getId());
            contractProjectCheckPayment.setPaymentType(4);
            contractProjectCheckPayment.setPaymentRatio(Opt.ofNullable(contract.getProjectCheckRatio()).orElse(BigDecimal.ZERO));
            contractProjectCheckPayment.setPaymentDate(contract.getProjectCheckDate());
            contractPaymentList.add(contractProjectCheckPayment);

            // 质保
            ContractPayment contractWarrantyPayment = new ContractPayment();
            contractWarrantyPayment.setId(contractId2PaymentMap.getOrDefault(contract.getId(), new HashMap<>()).get(5));
            contractWarrantyPayment.setContractId(contract.getId());
            contractWarrantyPayment.setPaymentType(5);
            contractWarrantyPayment.setPaymentRatio(Opt.ofNullable(contract.getWarrantyRatio()).orElse(BigDecimal.ZERO));
            contractWarrantyPayment.setPaymentDate(contract.getWarrantyDate());
            contractPaymentList.add(contractWarrantyPayment);

            // 第一笔维保款
            ContractPayment contractMaintainPayment1 = new ContractPayment();
            contractMaintainPayment1.setId(contractId2PaymentMap.getOrDefault(contract.getId(), new HashMap<>()).get(6));
            contractMaintainPayment1.setContractId(contract.getId());
            contractMaintainPayment1.setPaymentType(6);
            contractMaintainPayment1.setPaymentRatio(Opt.ofNullable(contract.getMaintainRatio1()).orElse(BigDecimal.ZERO));
            contractMaintainPayment1.setPaymentDate(contract.getMaintainDate1());
            contractPaymentList.add(contractMaintainPayment1);

            // 第二笔维保款
            ContractPayment contractMaintainPayment2 = new ContractPayment();
            contractMaintainPayment2.setId(contractId2PaymentMap.getOrDefault(contract.getId(), new HashMap<>()).get(7));
            contractMaintainPayment2.setContractId(contract.getId());
            contractMaintainPayment2.setPaymentType(7);
            contractMaintainPayment2.setPaymentRatio(Opt.ofNullable(contract.getMaintainRatio2()).orElse(BigDecimal.ZERO));
            contractMaintainPayment2.setPaymentDate(contract.getMaintainDate2());
            contractPaymentList.add(contractMaintainPayment2);

            // 第三笔维保款
            ContractPayment contractMaintainPayment3 = new ContractPayment();
            contractMaintainPayment3.setId(contractId2PaymentMap.getOrDefault(contract.getId(), new HashMap<>()).get(8));
            contractMaintainPayment3.setContractId(contract.getId());
            contractMaintainPayment3.setPaymentType(8);
            contractMaintainPayment3.setPaymentRatio(Opt.ofNullable(contract.getMaintainRatio3()).orElse(BigDecimal.ZERO));
            contractMaintainPayment3.setPaymentDate(contract.getMaintainDate3());
            contractPaymentList.add(contractMaintainPayment3);
        }
        contractPaymentService.saveOrUpdateBatch(contractPaymentList);

        List<Payment> paymentList = paymentService.list();
        Map<String, BigDecimal> no2PaymentMap = paymentList.stream().collect(Collectors.groupingBy(Payment::getContractNo, Collectors.reducing(BigDecimal.ZERO, Payment::getPaymentAmount, BigDecimal::add)));

        insOrUpdContractList.forEach(c -> {
            String contractNo = c.getContractNo();
            Contract exist = contractService.lambdaQuery().eq(Contract::getContractNo, contractNo).one();
            Contract updDto = new Contract();
            updDto.setId(exist.getId());
            updDto.setPaidAmount(no2PaymentMap.getOrDefault(contractNo, BigDecimal.ZERO));
            contractPaymentService.calMoney(exist, updDto);
            contractService.updateById(updDto);
        });

        log.info("【结束】从crm系统同步合同信息");
        redisTemplate.opsForValue().set(RedisKeyEnum.CONTRACT_SYNC_TIME.getVal(), DateUtil.formatDateTime(insOrUpdContractList.get(0).getOriginalModTime()));
    }

    @Scheduled(cron = "0 0 1 * * ?")
    public void calMaintainStatus() {
        log.info("【开始】计算门店维保状态");
        storeService.calMaintainStatus(ListUtil.empty());
        log.info("【结束】计算门店维保状态");

    }
}