package com.bailuntec.balancesheet.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bailuntec.balancesheet.dto.*;
import com.bailuntec.balancesheet.entity.DcBalanceSheet;
import com.bailuntec.balancesheet.mapper.*;
import com.bailuntec.balancesheet.util.DateTimeUtil;
import com.bailuntec.balancesheet.util.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service
public class BalanceSheetService {
    @Value("${url.getCompanyMainBody}")
    private String getCompanyMainBodyUrl;
    @Value("${url.getBankAccountBalance}")
    private String getBankAccountBalanceUrl;
    @Value("${url.getPayPalBalance}")
    private String getPayPalBalanceUrl;
    @Value("${url.getWithdrawOnWaySummary}")
    private String getWithdrawOnWaySummaryUrl;
    @Value("${url.getBorrowBalance}")
    private String getBorrowBalanceUrl;
    @Value("${url.getExchangeRate}")
    private String getExchangeRateUrl;
    @Value("${url.getPlatformAndSite}")
    private String getPlatformAndSiteUrl;
    @Value("${url.getSupplierTransaction}")
    private String getSupplierTransactionUrl;
    @Value("${url.getOtherCost}")
    private String getOtherCostUrl;
    @Value("${url.getOtherBuy}")
    private String getOtherBuyUrl;
    @Value("${url.getNoPayCost}")
    private String getNoPayCostUrl;
    @Value("${url.getLogisticsSupplierTransaction}")
    private String getLogisticsSupplierTransactionUrl;
    @Value("${url.getSemiSku}")
    private String getSemiSkuUrl;
    @Value("${url.getSemiSupOfferLog}")
    private String getSemiSupOfferLogUrl;
    @Value("${url.getSemiStockLog}")
    private String getSemiStockLogUrl;
    @Value("${url.getSellerAccount}")
    private String getSellerAccountUrl;
    @Value("${url.getSemiPurchaseDetail}")
    private String getSemiPurchaseDetailUrl;

    @Autowired
    private DcCompanyMainBodyMapper dcCompanyMainBodyMapper;
    @Autowired
    private DcBankAccountBalanceMapper dcBankAccountBalanceMapper;
    @Autowired
    private DcWithdrawOnWayMapper dcWithdrawOnWayMapper;
    @Autowired
    private DcShortTermBorrowMapper dcShortTermBorrowMapper;
    @Autowired
    private DcBalanceSheetMapper dcBalanceSheetMapper;
    @Autowired
    private DcExchangeRateMapper dcExchangeRateMapper;
    @Autowired
    private DcInventoryBalanceMapper dcInventoryBalanceMapper;
    @Autowired
    private  DcPlatformBalanceMapper dcPlatformBalanceMapper;
    @Autowired
    private DcPlatformAndSiteMapper dcPlatformAndSiteMapper;
    @Autowired
    private DcSupplierTransactionMapper dcSupplierTransactionMapper;
    @Autowired
    private DcBaseCostMapper dcBaseCostMapper;
    @Autowired
    private DcOtherCostMapper dcOtherCostMapper;
    @Autowired
    private DcLogisticsSupplierTransactionMapper dcLogisticsSupplierTransactionMapper;
//    @Autowired
//    private DcSemiSkuMapper dcSemiSkuMapper;
    @Autowired
    private DcSemiSupplierOfferLogMapper dcSemiSupplierOfferLogMapper;
    @Autowired
    private DcSemiStockLogMapper dcSemiStockLogMapper;
    @Autowired
    private DcSemiDailyStockMapper dcSemiDailyStockMapper;
    @Autowired
    private DcBaseBuyMapper dcBaseBuyMapper;
    @Autowired
    private DcFixedAssetsDetailMapper dcFixedAssetsDetailMapper;
    @Autowired
    private DcBaseSellerAccountMapper dcBaseSellerAccountMapper;
    @Autowired
    private DcSemiPurchaseDetailMapper dcSemiPurchaseDetailMapper;
    @Autowired
    private DcSemiDailyTransferMapper dcSemiDailyTransferMapper;

    private static Logger logger = LoggerFactory.getLogger(BalanceSheetService.class);

    @Scheduled(cron = "0 0 0 * * *") // 每天凌晨0点运行一次
    public void doScheduledTask0000() {
        // 获取并保存当天汇率
        Date today = DateTimeUtil.getCurrentDay();
        getExchangeRate(today);

        Date lastDay = DateTimeUtil.getCurrentLastDay();
        Date twoDaysAgo = DateTimeUtil.addDays(lastDay, -1);

        // 银行账户余额
        getBankAccountBalance(lastDay);

        // 提现在途
        getWithdrawOnWaySummary(lastDay);

        // 短期借款余额
        getShortBorrowBalance(lastDay);

        // 获取PayPal账户余额
        getPayPalBalance(lastDay);

        // 其他应收款、其他应付款
        getOtherCost(twoDaysAgo, lastDay, today);

        // 固定资产
        getFixedAssets(twoDaysAgo, lastDay, today);

        // 生成资产负债表
        generateBalanceSheet(0, "百伦供应链", lastDay);

        getSemiInventoryBalance(lastDay, today); // 获取半成品存货
        getSemiTransferAmount(lastDay, today); // 获取半成品在途
    }


    @Scheduled(cron = "0 30 1 * * *") // 每天凌晨1点半运行一次
    public void doScheduledTask0100() {
        Date lastDay = DateTimeUtil.getCurrentLastDay();
        getInventoryBalance(lastDay); // 获取成品存货
        updateInventoryBalance(lastDay); // 更新资产负债表存货
        getLogisticsSupplierTransaction(lastDay); // 获取物流供应商往来数据：应付账款
        getSupplierTransaction(lastDay); // 获取供应商往来数据：应付账款和预付账款
        updateSuppliserTransactionOfBalanceSheet(lastDay); // 更新资产负债表应付账款和预付账款
    }

    @Scheduled(cron = "0 0 2 * * *") // 每天凌晨2点运行一次
    public void doScheduledTask0200() {
        getCompanyMainBody(); // 获取公司主体
        getPlatformAndSites(); // 获取销售平台和站点信息
        getSellerAccount(); // 获取销售账号
    }


    /**
     *  获取公司主体
     */
    public void getCompanyMainBody(){
        try {
            CwSystemApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpPost(getCompanyMainBodyUrl, null), CwSystemApiResultDTO.class);
            if(responseDTO.getSuccess() && responseDTO.getData().size() > 0){
                List<CompanyMainBodyDTO> companyMainBodyDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), CompanyMainBodyDTO.class);
                dcCompanyMainBodyMapper.insertOrUpdateCompany(companyMainBodyDTOList);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取公司主体出错" + e.getMessage());
        }
    }

    /**
     *  获取销售平台和站点信息
     */
    public void getPlatformAndSites() {
        try {
            CwSystemApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getPlatformAndSiteUrl), CwSystemApiResultDTO.class);
            if (responseDTO.getSuccess() && responseDTO.getData().size() > 0) {
                List<PlatformAndSiteDTO> platformAndSiteDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), PlatformAndSiteDTO.class);
                dcPlatformAndSiteMapper.insertPlatformAndSites(platformAndSiteDTOList);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取销售平台和站点信息出错" + e.getMessage());
        }
    }

    /**
     * 获取销售账号
     */
    public void getSellerAccount(){
        try {
            CwSystemApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getSellerAccountUrl), CwSystemApiResultDTO.class);
            if(responseDTO.getSuccess() && responseDTO.getData().size() > 0){
                List<SellerAccountDTO> sellerAccountDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), SellerAccountDTO.class);
                dcBaseSellerAccountMapper.insertOrUpdateSellerAccount(sellerAccountDTOList);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取销售账号出错" + e.getMessage());
        }
    }

   /**
     * 获取并保存为特定日期的汇率
     */
    public void getExchangeRate(Date date){
        try {
            List<ExchangeRateDTO> exchangeRateDTOList = JSONObject.parseArray(JSONObject.parseObject(HttpUtil.httpGet(getExchangeRateUrl), String.class), ExchangeRateDTO.class);
            if(exchangeRateDTOList != null && exchangeRateDTOList.size() > 0){
                dcExchangeRateMapper.insertToCnyExchangeRates(exchangeRateDTOList, date);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取转人民币汇率出错" + e.getMessage());
        }
    }

    /**
     * 获取银行账户余额
     * @param date 统计数据的日期
     */
    public void getBankAccountBalance(Date date) {
        try {
            CwSystemApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getBankAccountBalanceUrl), CwSystemApiResultDTO.class);
            if(responseDTO.getSuccess() && responseDTO.getData().size() > 0){
                List<BankAccountBalanceDTO> bankAccountBalanceDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), BankAccountBalanceDTO.class);
                dcBankAccountBalanceMapper.insertBankAccountBalance(bankAccountBalanceDTOList, date);
                // 删除需要过滤的数据
                dcBankAccountBalanceMapper.deleteUnusedData(date);
                dcBankAccountBalanceMapper.deleteUnusedData1(date);
                dcBankAccountBalanceMapper.deleteUnusedData2(date);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取银行账户余额出错" + e.getMessage());
        }
    }


    /**
     * 获取提现在途最新数据
     * @param date 数据统计的日期
     */
    public void getWithdrawOnWaySummary(Date date) {
        try {
            CwSystemApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getWithdrawOnWaySummaryUrl), CwSystemApiResultDTO.class);
            if(responseDTO.getSuccess() && responseDTO.getData().size() > 0){
                List<WithdrawOnWayDTO> withdrawOnWayDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), WithdrawOnWayDTO.class);
                dcWithdrawOnWayMapper.insertWithdrawOnWay(withdrawOnWayDTOList, date);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取提现在途出错" + e.getMessage());
            return;
        }
        // 更新提现在途公司主体value
        dcWithdrawOnWayMapper.updateWithdrawOnWayCompany();
    }

    /**
     * 获取公司主体短期借款余额
     * @param date 统计数据的日期
     */
    @Transactional
    public void getShortBorrowBalance(Date date) {
        try {
            CwSystemApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getBorrowBalanceUrl), CwSystemApiResultDTO.class);
            if(responseDTO.getSuccess() && responseDTO.getData().size() > 0){
                List<BorrowBalanceDTO> borrowBalanceDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), BorrowBalanceDTO.class);
                dcShortTermBorrowMapper.insertShortTermBorrow(borrowBalanceDTOList, date);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取短期借款余额出错" + e.getMessage());
        }
    }

    /**
     * 获取PayPal账号余额
     */
    public void getPayPalBalance(Date date){
        try {
            List<PayPalBalanceDTO> payPalBalanceDTOList = JSONObject.parseArray(JSONObject.parseObject(HttpUtil.httpGet(getPayPalBalanceUrl), String.class), PayPalBalanceDTO.class);
            if(payPalBalanceDTOList != null && payPalBalanceDTOList.size() > 0){
                dcPlatformBalanceMapper.insertPayPalBalance(payPalBalanceDTOList, date);
                dcPlatformBalanceMapper.updatePayPalBalance(date);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取PayPal账号余额出错" + e.getMessage());
        }
    }

    /**
     * 获取成品仓存货
     */
    public void getInventoryBalance(Date date){
        // 检验日期date的转人民币汇率是否存在，不存在则获取当前的汇率保存为日期date的汇率
        Long count = dcExchangeRateMapper.countLastDayExchageRate(date);
        if(count == 0){
            getExchangeRate(date);
        }
        // 货品库存
        dcInventoryBalanceMapper.insertInventoryBalance(date);
        // 货品调拨在途
        dcInventoryBalanceMapper.insertTransferInventoryBalance(date);
    }

    /**
     * 获取半成品存货
     * @param date
     */
    public void getSemiInventoryBalance(Date date, Date datePlusOne){
        boolean isOk = true;
        String param = "?btime=" + DateTimeUtil.dateToString(date, DateTimeUtil.DATE_FORMAT) + "&etime=" + DateTimeUtil.dateToString(datePlusOne, DateTimeUtil.DATE_FORMAT);
        /*try {
            SemiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getSemiSkuUrl + param), SemiResultDTO.class);
            if(responseDTO.getSuccess() && responseDTO.getData().size() > 0){
                List<SemiSkuDTO> semiSkuDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), SemiSkuDTO.class);
                dcSemiSkuMapper.insertOrUpdateSemiSku(semiSkuDTOList);
            }
            System.out.println(">>>>>获取半成品原料SKU完成");
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取半成品原料SKU出错" + e.getMessage());
            getDataSuccess = false;
        }*/
        try {
            SemiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getSemiSupOfferLogUrl + param), SemiResultDTO.class);
            if(responseDTO.getSuccess() && responseDTO.getData().size() > 0){
                List<SemiSupOfferLogDTO> semiSupOfferLogDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), SemiSupOfferLogDTO.class);
                dcSemiSupplierOfferLogMapper.insertOrUpdateSemiSupplierOfferLog(semiSupOfferLogDTOList);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取半成品供应商报价流水出错" + e.getMessage());
            isOk = false;
        }
        int rows = 5000;
        int page = 1;
        try {
            SemiPageResultDTO responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getSemiStockLogUrl + param +
                    "&page=" + page + "&rows=" + rows), SemiPageResultDTO.class);
            if(responseDTO.getSuccess() && responseDTO.getData().getTotalItems() > 0){
                dcSemiStockLogMapper.insertOrUpdateSemiStockLog(responseDTO.getData().getItems());
                int totalPages = responseDTO.getData().getTotalPages();
                responseDTO = null;
                while(page < totalPages){
                    page += 1;
                    try {
                        responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getSemiStockLogUrl + param + "&page=" + page + "&rows=" + rows), SemiPageResultDTO.class);
                        dcSemiStockLogMapper.insertOrUpdateSemiStockLog(responseDTO.getData().getItems());
                        responseDTO = null;
                    } catch (Exception e){
                        e.printStackTrace();
                        logger.error(">>>>>获取半成品库存流水出错，请求分页数：" + page + "\n" + e.getMessage());
                        isOk = false;
                        continue;
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取半成品库存流水出错，请求分页数：" + page + "\n" + e.getMessage());
            isOk = false;
        }
        // 生成半成品每日存货
        if(isOk){
            dcSemiDailyStockMapper.insertSemiDailyStock(date);
        }
    }

    /**
     * 获取半成品在途
     * @param date
     */
    public void getSemiTransferAmount(Date date, Date datePlusOne){
        boolean isOk = true;
        String param = "?btime=" + DateTimeUtil.dateToString(date, DateTimeUtil.DATE_FORMAT) + "&etime=" + DateTimeUtil.dateToString(datePlusOne, DateTimeUtil.DATE_FORMAT);
        int rows = 5000;
        int page = 1;
        try {
            SemiPurchasePageResultDTO responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getSemiPurchaseDetailUrl + param +
                    "&page=" + page + "&rows=" + rows), SemiPurchasePageResultDTO.class);
            if(responseDTO.getResult() && responseDTO.getList().getTotalItems() > 0){
                dcSemiPurchaseDetailMapper.insertOrUpdateSemiPurchaseDetail(responseDTO.getList().getItems());
                int totalPages = responseDTO.getList().getTotalPages();
                responseDTO = null;
                while(page < totalPages){
                    page += 1;
                    try {
                        responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getSemiPurchaseDetailUrl + param + "&page=" + page + "&rows=" + rows), SemiPurchasePageResultDTO.class);
                        dcSemiPurchaseDetailMapper.insertOrUpdateSemiPurchaseDetail(responseDTO.getList().getItems());
                        responseDTO = null;
                    } catch (Exception e){
                        e.printStackTrace();
                        logger.error(">>>>>获取半成品采购明细出错，请求分页数：" + page + "\n" + e.getMessage());
                        isOk = false;
                        continue;
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取半成品采购明细出错，请求分页数：" + page + "\n" + e.getMessage());
            isOk = false;
        }
        if (isOk){
            dcSemiDailyTransferMapper.insertSemiDailyTransfer(date);
        }
    }

    /**
     * 更新资产负债表：存货金额、FBA在库金额、非FBA在库金额、FBA在途金额、非FBA在途金额、半成品在库金额、半成品在途金额
     * @param date
     */
    public void updateInventoryBalance(Date date){
        DcBalanceSheet dcBalanceSheet = new DcBalanceSheet();
        // FBA在库金额
        BigDecimal fbaInventoryAmountSum = dcInventoryBalanceMapper.getFbaInventoryAmountSum(date);
        if(fbaInventoryAmountSum == null) fbaInventoryAmountSum = BigDecimal.ZERO;
        dcBalanceSheet.setFbaInventoryAmount(fbaInventoryAmountSum);
        // 非FBA在库金额
        BigDecimal notFbaInventoryAmountSum = dcInventoryBalanceMapper.getNotFbaInventoryAmountSum(date);
        if(notFbaInventoryAmountSum == null) notFbaInventoryAmountSum = BigDecimal.ZERO;
        dcBalanceSheet.setNotFbaInventoryAmount(notFbaInventoryAmountSum);
        // FBA在途金额
        BigDecimal fbaTransferAmountSum = dcInventoryBalanceMapper.getFbaTransferAmountSum(date);
        if(fbaTransferAmountSum == null) fbaTransferAmountSum = BigDecimal.ZERO;
        dcBalanceSheet.setFbaTransferAmount(fbaTransferAmountSum);
        // 非FBA在途金额
        BigDecimal notFbaTransferAmountSum = dcInventoryBalanceMapper.getNotFbaTransferAmountSum(date);
        if(notFbaTransferAmountSum == null) notFbaTransferAmountSum = BigDecimal.ZERO;
        dcBalanceSheet.setNotFbaTransferAmount(notFbaTransferAmountSum);
        // 半成品在库金额
        BigDecimal semiInventoryAmountSum = dcSemiDailyStockMapper.getSemiDailyStockSum(date);
        if(semiInventoryAmountSum == null) semiInventoryAmountSum = BigDecimal.ZERO;
        dcBalanceSheet.setSemiInventoryAmount(semiInventoryAmountSum);
        // 半成品在途金额 吴通改为半成品在途金额设置为0。
        BigDecimal semiTransferAmountSum =  BigDecimal.ZERO;
//        BigDecimal semiTransferAmountSum = dcSemiDailyTransferMapper.getSemiDailyTransferSum(date);
//        if(semiTransferAmountSum == null) semiTransferAmountSum = BigDecimal.ZERO;
        dcBalanceSheet.setSemiTransferAmount(semiTransferAmountSum);
        // 库存金额
        BigDecimal inventoryBalanceSum = fbaInventoryAmountSum.add(notFbaInventoryAmountSum).add(fbaTransferAmountSum).add(notFbaTransferAmountSum).add(semiInventoryAmountSum).add(semiTransferAmountSum);
        dcBalanceSheet.setInventoryAmount(inventoryBalanceSum);
        dcBalanceSheet.setCompanyValue(0);
        dcBalanceSheet.setStatisticalTime(date);
        dcBalanceSheetMapper.updateByCompanyAndDaySelective(dcBalanceSheet);
    }

    /**
     * 获取物流供应商往来数据：应付账款和预付账款
     * @param date
     */
    public void getLogisticsSupplierTransaction(Date date){
        // 逢周六日，取周五数据
        boolean isWeek = false;
        Date dataDate = null; // 数据的标识日期
        if (DateTimeUtil.isEqualsWeekDay(date, Calendar.SATURDAY)){
            isWeek = true;
            dataDate = date;
            date = DateTimeUtil.addDays(date, -1);
        }else if(DateTimeUtil.isEqualsWeekDay(date, Calendar.SUNDAY)){
            isWeek = true;
            dataDate = date;
            date = DateTimeUtil.addDays(date, -2);
        }
        try {
            // 参数：{"day":"2019-01-17"}
            JSONObject param = new JSONObject();
            param.put("day", DateTimeUtil.dateToString(date, DateTimeUtil.DATE_FORMAT));
            PurchaseApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpPost(getLogisticsSupplierTransactionUrl, param.toString()), PurchaseApiResultDTO.class);
            if(responseDTO.getIsSuccessed() && responseDTO.getData().size() > 0){
                List<LogisticsSupplierTransactionDTO> logisticsSupplierTransactionDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), LogisticsSupplierTransactionDTO.class);
                if(isWeek){
                    for (LogisticsSupplierTransactionDTO logisticsSupplierTransactionDTO : logisticsSupplierTransactionDTOList){
                        logisticsSupplierTransactionDTO.setDay(dataDate);
                    }
                }
                dcLogisticsSupplierTransactionMapper.insertOrUpdateLogisticsSupplierTransaction(logisticsSupplierTransactionDTOList);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取物流供应商往来数据出错" + e.getMessage());
        }
    }

    /**
     * 获取供应商往来数据：应付账款和预付账款
     * @param date
     */
    public void getSupplierTransaction(Date date){
        try {
            // 参数：{"startTime":"2019-01-17"(必须),"endTime":""(可选),"supplierName":""(可选)}
            JSONObject param = new JSONObject();
            param.put("startTime", DateTimeUtil.dateToString(date, DateTimeUtil.DATE_FORMAT));
            PurchaseApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpPost(getSupplierTransactionUrl, param.toString()), PurchaseApiResultDTO.class);
            if(responseDTO.getIsSuccessed() && responseDTO.getData().size() > 0){
                List<SupplierTransactionDTO> supplierTransactionDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), SupplierTransactionDTO.class);
                dcSupplierTransactionMapper.insertOrUpdateSupplierTransaction(supplierTransactionDTOList);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取供应商往来数据出错" + e.getMessage());
        }
    }

    /**
     * 更新资产负债表：应付账款和预付账款
     * @param date
     */
    public void updateSuppliserTransactionOfBalanceSheet(Date date){
        DcBalanceSheet dcBalanceSheet = new DcBalanceSheet();//物流供应商、成品供应商、半成品供应商
        // 成品供应商应付款项
        BigDecimal finishedAccountsPayableSum = dcSupplierTransactionMapper.getFinishedAccountsPayableSum(date);
        if(finishedAccountsPayableSum == null) finishedAccountsPayableSum = BigDecimal.ZERO;
        dcBalanceSheet.setFinishedAccountsPayable(finishedAccountsPayableSum);
        // 半成品供应商应付款项
        BigDecimal semiAccountsPayableSum = dcSupplierTransactionMapper.getSemiAccountsPayableSum(date);
        if(semiAccountsPayableSum == null) semiAccountsPayableSum = BigDecimal.ZERO;
        dcBalanceSheet.setSemiAccountsPayable(semiAccountsPayableSum);
        // 物流供应商应付款项
        BigDecimal logisticsAccountsPayableSum = dcLogisticsSupplierTransactionMapper.getLogisticsAccountsPayableSum(date);
        if(logisticsAccountsPayableSum == null) logisticsAccountsPayableSum = BigDecimal.ZERO;
        dcBalanceSheet.setLogisticsAccountsPayable(logisticsAccountsPayableSum);
        // 应付款项
        BigDecimal accountsPayableSum = finishedAccountsPayableSum.add(semiAccountsPayableSum).add(logisticsAccountsPayableSum);
        dcBalanceSheet.setAccountsPayable(accountsPayableSum);

        // 成品供应商预付款项
        BigDecimal finishedPrepaymentSum = dcSupplierTransactionMapper.getFinishedPrepaymentSum(date);
        if(finishedPrepaymentSum == null) finishedPrepaymentSum = BigDecimal.ZERO;
        dcBalanceSheet.setFinishedPrepayment(finishedPrepaymentSum);
        // 半成品供应商预付款项
        BigDecimal semiPrepaymentSum = dcSupplierTransactionMapper.getSemiPrepaymentSum(date);
        if(semiPrepaymentSum == null) semiPrepaymentSum = BigDecimal.ZERO;
        dcBalanceSheet.setSemiPrepayment(semiPrepaymentSum);
        // 物流供应商预付款项
        BigDecimal logisticsPrepaymentSum = dcLogisticsSupplierTransactionMapper.getLogisticsPrepaymentSum(date);
        if(logisticsPrepaymentSum == null) logisticsPrepaymentSum = BigDecimal.ZERO;
        dcBalanceSheet.setLogisticsPrepayment(logisticsPrepaymentSum);
        // 预付款项
        BigDecimal prepaymentSum = finishedPrepaymentSum.add(semiPrepaymentSum).add(logisticsPrepaymentSum);
        dcBalanceSheet.setPrepayment(prepaymentSum);

        dcBalanceSheet.setCompanyValue(0);
        dcBalanceSheet.setStatisticalTime(date);
        dcBalanceSheetMapper.updateByCompanyAndDaySelective(dcBalanceSheet);
    }

    /**
     * 获取其他应付款和其他应收款
     * @param date
     * @param datePlusOne
     */
    @Transactional
    public void getOtherCost(Date dateSubOne, Date date, Date datePlusOne) {
        try{
            List<String> noPayCostNoList = dcBaseCostMapper.getNoPayCostNo();
            if (noPayCostNoList.size() > 0){
                StringBuffer sb = new StringBuffer("?costNoList=");
                for (String costNo : noPayCostNoList){
                    sb.append(costNo + ",");
                }
                String param = sb.toString();
                param = param.substring(0, param.length() - 1);
                FeeSystemApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getNoPayCostUrl + param), FeeSystemApiResultDTO.class);
                if(responseDTO.getSuccess() && responseDTO.getData().size() > 0){
                    List<CostDTO> costDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), CostDTO.class);

                    // 插入原待出纳支付状态付款单对应的已完成状态付款单
                    dcBaseCostMapper.insertDcBaseCost(costDTOList, date);

                    // 更新完成支付的待出纳支付状态的付款单为已冲销
                    List<String> paidCostNoList = new ArrayList<>();
                    for (CostDTO costDTO : costDTOList){
                        paidCostNoList.add(costDTO.getCostNo());
                    }
                    dcBaseCostMapper.signNoPayCostToPaid(paidCostNoList);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取原待出纳支付状态的付款单在费用系统的已支付状态数据出错" + e.getMessage());
            return;
        }
        try {
            FeeSystemApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getOtherCostUrl +
                    "?startDate=" + DateTimeUtil.dateToString(date, DateTimeUtil.DATE_FORMAT) +
                    "&endDate=" + DateTimeUtil.dateToString(datePlusOne, DateTimeUtil.DATE_FORMAT)), FeeSystemApiResultDTO.class);
            if(responseDTO.getSuccess() && responseDTO.getData().size() > 0){
                List<CostDTO> costDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), CostDTO.class);
                dcBaseCostMapper.insertDcBaseCost(costDTOList, date);
                // 标记待出纳支付状态的付款单为待冲销
                dcBaseCostMapper.signNoPayCost(date);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取费用系统费用单数据出错" + e.getMessage());
            return;
        }
        // 删除要过滤的公司主体数据
        dcBaseCostMapper.deleteUnusedCost(date);
        // 生成一级明细
        dcOtherCostMapper.insertOneDayOtherReceive(date, dateSubOne);
        dcOtherCostMapper.insertOneDayOtherPay(date, dateSubOne);
    }

    /**
     * 获取费用系统采购单：固定资产
     * @param date
     * @param datePlusOne
     */
    public void getFixedAssets(Date dateSubOne, Date date, Date datePlusOne){
        try {
            FeeSystemApiResultDTO<JSONArray> responseDTO = JSONObject.parseObject(HttpUtil.httpGet(getOtherBuyUrl +
                    "?startDate=" + DateTimeUtil.dateToString(date, DateTimeUtil.DATE_FORMAT) +
                    "&endDate=" + DateTimeUtil.dateToString(datePlusOne, DateTimeUtil.DATE_FORMAT)), FeeSystemApiResultDTO.class);
            if(responseDTO.getSuccess() && responseDTO.getData().size() > 0){
                List<BuyDTO> buyDTOList = JSONObject.parseArray(responseDTO.getData().toJSONString(), BuyDTO.class);
                dcBaseBuyMapper.insertDcBaseBuy(buyDTOList, date);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(">>>>>获取费用系统采购单数据出错" + e.getMessage());
            return;
        }
        // 生成一级明细
        dcFixedAssetsDetailMapper.insertFixedAssetsDetail(date, dateSubOne);
    }

    /**
     * 生成资产负债表
     * @param companyValue 公司主体value
     * @param companyName 公司主体名称
     * @param date 统计数据的日期
     */
    @Transactional
    public void generateBalanceSheet(Integer companyValue, String companyName, Date date) {
        // 生成资产负债表
        dcBalanceSheetMapper.insertBalanceSheet(companyValue, companyName, date);

        DcBalanceSheet dcBalanceSheet = new DcBalanceSheet();
        // 银行账户余额汇总
        BigDecimal bankAccountBalanceSum = dcBankAccountBalanceMapper.getBalanceSum(date);
        if(bankAccountBalanceSum == null) bankAccountBalanceSum = BigDecimal.ZERO;
        dcBalanceSheet.setBankAccountBalance(bankAccountBalanceSum);
        // 提现在途金额汇总
        BigDecimal withdrawOnWaySum = dcWithdrawOnWayMapper.getWithdrawOnWaySum(date);
        if(withdrawOnWaySum == null) withdrawOnWaySum = BigDecimal.ZERO;
        dcBalanceSheet.setWithdrawAmount(withdrawOnWaySum);
        // 第三方平台余额
        BigDecimal platformBalanceSum = dcPlatformBalanceMapper.getPlatformBalanceSum(date);
        if(platformBalanceSum == null) platformBalanceSum = BigDecimal.ZERO;
        dcBalanceSheet.setPlatformBalance(platformBalanceSum);
        // 货币资金
        dcBalanceSheet.setMonetaryFund(bankAccountBalanceSum.add(withdrawOnWaySum).add(platformBalanceSum)); // 货币资金 = 银行余额 + 提现在途 + 第三方平台余额
        // 短期借款
        BigDecimal shortBorrowBalanceSum = dcShortTermBorrowMapper.getShortTermBorrowBalanceSum(date);
        if(shortBorrowBalanceSum == null) shortBorrowBalanceSum = BigDecimal.ZERO;
        dcBalanceSheet.setShortTermBorrow(shortBorrowBalanceSum);
        // 其他应收款、其他应付款
        BigDecimal otherAccountsReceivable = dcOtherCostMapper.getOtherAccountsReceivableSum(date); // 其他应收款
        if(otherAccountsReceivable == null) otherAccountsReceivable = BigDecimal.ZERO;
        dcBalanceSheet.setOtherAccountsReceivable(otherAccountsReceivable);
        BigDecimal otherAccountsPayable = dcOtherCostMapper.getOtherAccountsPayableSum(date); // 其他应付款
        if(otherAccountsPayable == null) otherAccountsPayable = BigDecimal.ZERO;
        dcBalanceSheet.setOtherAccountsPayable(otherAccountsPayable);
        // 固定资产
        BigDecimal fixedAssetsSum = dcFixedAssetsDetailMapper.getFixedAssetsSum(date);
        if(fixedAssetsSum == null) fixedAssetsSum = BigDecimal.ZERO;
        dcBalanceSheet.setFixedAssets(fixedAssetsSum);

        dcBalanceSheet.setCompanyValue(companyValue);
        dcBalanceSheet.setStatisticalTime(date);

        // 更新资产负债表统计字段
        dcBalanceSheetMapper.updateByCompanyAndDaySelective(dcBalanceSheet);
    }

    /**
     * 更新调整后的供应商往来数据，以及资产负债表中的应付账款和预付账款
     */
    @Transactional
    public void adjustSupplierTransaction(List<SupplierTransactionDTO> supplierTransactionDTOList){
        dcSupplierTransactionMapper.insertOrUpdateSupplierTransaction(supplierTransactionDTOList);
        Set<Date> updateDateSet = new HashSet<>();
        for (SupplierTransactionDTO supplierTransactionDTO : supplierTransactionDTOList){
            updateDateSet.add(supplierTransactionDTO.getDay());
        }
        for (Date date : updateDateSet){
            updateSuppliserTransactionOfBalanceSheet(date);
        }
    }

    /**
     * 更新调整后的物流供应商往来数据，以及资产负债表中的应付账款和预付账款
     */
    @Transactional
    public void adjustLogisticsSupplierTransaction(List<LogisticsSupplierTransactionDTO> logisticsSupplierTransactionDTOList){
        dcLogisticsSupplierTransactionMapper.insertOrUpdateLogisticsSupplierTransaction(logisticsSupplierTransactionDTOList);
        Set<Date> updateDateSet = new HashSet<>();
        Date dataDate = null;
        List<LogisticsSupplierTransactionDTO> weekendData = new ArrayList<>();
        for (LogisticsSupplierTransactionDTO logisticsSupplierTransactionDTO : logisticsSupplierTransactionDTOList){
            dataDate = logisticsSupplierTransactionDTO.getDay();
            updateDateSet.add(dataDate);
            // 由于周六日数据取自周五数据，因此逢更新周五数据，则自动更新周末数据
            if (DateTimeUtil.isEqualsWeekDay(dataDate, Calendar.FRIDAY)){
                // 星期六数据
                dataDate = DateTimeUtil.addDays(dataDate, 1);
                logisticsSupplierTransactionDTO.setDay(dataDate);
                weekendData.add(logisticsSupplierTransactionDTO);
                updateDateSet.add(dataDate);
            }
        }
        if (weekendData.size() > 0){
            // 插入或更新星期六数据
            dcLogisticsSupplierTransactionMapper.insertOrUpdateLogisticsSupplierTransaction(weekendData);
            // 星期日数据
            for (LogisticsSupplierTransactionDTO weekendDTO : weekendData){
                dataDate = weekendDTO.getDay();
                dataDate = DateTimeUtil.addDays(dataDate, 1);
                weekendDTO.setDay(dataDate);
                updateDateSet.add(dataDate);
            }
            // 插入或更新星期日数据
            dcLogisticsSupplierTransactionMapper.insertOrUpdateLogisticsSupplierTransaction(weekendData);
        }
        for (Date date : updateDateSet){
            updateSuppliserTransactionOfBalanceSheet(date);
        }
    }

}
