package com.fjhx.account.service.account.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.account.entity.account.bo.AccountRunningWaterBo;
import com.fjhx.account.entity.account.dto.AccountRunningWaterDto;
import com.fjhx.account.entity.account.dto.AccountRunningWaterSelectDto;
import com.fjhx.account.entity.account.po.AccountManagement;
import com.fjhx.account.entity.account.po.AccountRemainder;
import com.fjhx.account.entity.account.po.AccountRunningWater;
import com.fjhx.account.entity.account.vo.AccountRunningWaterVo;
import com.fjhx.account.entity.tax.po.TaxRefundDetails;
import com.fjhx.account.entity.transaction.po.Transaction;
import com.fjhx.account.entity.transaction.po.TransactionDepartment;
import com.fjhx.account.mapper.account.AccountRunningWaterMapper;
import com.fjhx.account.service.account.AccountManagementService;
import com.fjhx.account.service.account.AccountRemainderService;
import com.fjhx.account.service.account.AccountRunningWaterService;
import com.fjhx.account.service.tax.TaxRefundDetailsService;
import com.fjhx.account.service.transaction.TransactionDepartmentService;
import com.fjhx.account.service.transaction.TransactionService;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.common.entity.corporation.po.Corporation;
import com.fjhx.common.enums.PushBusinessTypeEnum;
import com.fjhx.common.service.corporation.CorporationService;
import com.fjhx.common.utils.Assert;
import com.fjhx.common.utils.ExchangeRateUtil;
import com.fjhx.item.util.excel.util.ExcelUtil;
import com.fjhx.socket.core.PushTypeEnum;
import com.fjhx.socket.core.WebSocketPush;
import com.fjhx.tenant.entity.dict.dto.DictTenantDataSelectDto;
import com.fjhx.tenant.entity.dict.vo.DictTenantDataVo;
import com.fjhx.tenant.service.dict.DictTenantDataService;
import com.ruoyi.common.core.domain.BaseSelectDto;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 账户资金流水表 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-06
 */
@Service
public class AccountRunningWaterServiceImpl extends ServiceImpl<AccountRunningWaterMapper, AccountRunningWater> implements AccountRunningWaterService {

    @Autowired
    private AccountRemainderService accountRemainderService;

    @Autowired
    private DictTenantDataService dictTenantDataService;

    @Autowired
    private CorporationService corporationService;

    @Autowired
    private AccountManagementService accountManagementService;
    @Autowired
    private TaxRefundDetailsService taxRefundDetailsService;
    @Autowired
    private TransactionService transactionService;
    @Autowired
    private TransactionDepartmentService transactionDepartmentService;

    @Override
    public Page<AccountRunningWaterVo> getPage(AccountRunningWaterSelectDto dto) {
        QueryWrapper<Object> wrapper = Wrappers.query();
        // 资金账户
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getAccountManagementId()), "arw.account_management_id", dto.getAccountManagementId());
        // 交易类型
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getStatus()), "arw.status", dto.getStatus());
        // 是否合同到账
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getReceived()), "arw.received", dto.getReceived());
        // 币种
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getCurrency()), "arw.currency", dto.getCurrency());
        //是否认领
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getIsClaim()), "arw.is_claim", dto.getIsClaim());
        //交易开始金额
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getBeginAmount()), "arw.amount", dto.getBeginAmount());
        //交易结束金额
        wrapper.le(ObjectUtil.isNotEmpty(dto.getEndAmount()), "arw.amount", dto.getEndAmount());
        //交易开始时间
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getStartTime()), "arw.transaction_time", dto.getStartTime());
        //交易结束时间
        wrapper.le(ObjectUtil.isNotEmpty(dto.getStopTime()), "arw.transaction_time", dto.getStopTime());
        //对方账户名称
        wrapper.like(ObjectUtil.isNotEmpty(dto.getName()), "arw.name", dto.getName());
        //摘要
        wrapper.like(ObjectUtil.isNotEmpty(dto.getRemarks()), "arw.remarks", dto.getRemarks());
        if (StringUtils.isNotEmpty(dto.getKeyword())) {
            wrapper.and(wrapper1 -> wrapper1.like("arw.remarks", dto.getKeyword()).or().like("arw.name", dto.getKeyword()));
        }
        if (ObjectUtil.isNotEmpty(dto.getDataType()) && dto.getDataType() == 1) {// 到账认领数据
            wrapper.eq("arw.received", 10);
            //到账认领状态使用自定义排序 0未认领 2部分认领 1已认领
            wrapper.orderByAsc("field(arw.is_claim,0,2,1)");
            //到账时间倒序
            wrapper.orderByDesc("arw.transaction_time");
        }
        // todo ERP-》资金管理-》资金流水分页 要求按交易时间排序，我也不懂上面if排序是在哪调用的，先在else里加吧
        else {
            wrapper.orderByDesc("arw.transaction_time", "arw.id");
        }

        Page<AccountRunningWaterVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<AccountRunningWaterVo> records = page.getRecords();
        //赋值归属公司名称
        corporationService.attributeAssign(records, AccountRunningWaterVo::getCorporationId, (item, corporation) -> {
            item.setCorporationName(corporation.getName());
        });
        return page;
    }

    /**
     * 账户流水分页
     */
    @Override
    public Page<AccountRunningWaterVo> getPage1(AccountRunningWaterSelectDto dto) {
        Assert.notEmpty(dto.getAccountManagementId(), "资金账户不能为空");
        Assert.notEmpty(dto.getCurrency(), "币种不能为空");
        // 获取账户余额
        AccountRemainder accountRemainder = accountRemainderService.getOne(q -> q
                .eq(AccountRemainder::getAccountManagementId, dto.getAccountManagementId())
                .eq(AccountRemainder::getCurrency, dto.getCurrency()));

        BigDecimal remainder;
        if (accountRemainder == null) {
            remainder = BigDecimal.ZERO;
        } else {
            remainder = accountRemainder.getRemainder();
        }

        QueryWrapper<Object> wrapper = Wrappers.query();
        // 资金账户
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getAccountManagementId()), "arw.account_management_id", dto.getAccountManagementId());
        // 币种
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getCurrency()), "arw.currency", dto.getCurrency());
        wrapper.orderByDesc("arw.transaction_time");

        //获取当前分页之前的数据先处理余额
        Integer size = (dto.getPageNum() - 1) * dto.getPageSize();
        List<AccountRunningWater> amounts = baseMapper.getAccountRunningWaterAmount(wrapper, size);
        //收入合
        BigDecimal incomeSum = amounts.stream().filter(item -> "10".equals(item.getStatus())).map(AccountRunningWater::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        //支出合
        BigDecimal expenditureSum = amounts.stream().filter(item -> "20".equals(item.getStatus())).map(AccountRunningWater::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        remainder = remainder.subtract(incomeSum).add(expenditureSum);

        //获取分页数据
        Page<AccountRunningWaterVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<AccountRunningWaterVo> records = page.getRecords();
        for (AccountRunningWaterVo record : records) {
            record.setRemainder(remainder);
            //根据当前余额 反向计算 每条记录操作后的余额 收入减 支出加
            remainder = "10".equals(record.getStatus()) ? remainder.subtract(record.getAmount()) : remainder.add(record.getAmount());
        }
        //赋值归属公司名称
        corporationService.attributeAssign(records, AccountRunningWaterVo::getCorporationId, (item, corporation) -> {
            item.setCorporationName(corporation.getName());
        });
        return page;
    }

    @Override
    public AccountRunningWaterVo detail(Long id) {
        AccountRunningWaterVo result = baseMapper.getDetail(id);
        //赋值归属公司名称
        Corporation corporation = corporationService.getById(result.getCorporationId());
        if (ObjectUtil.isNotEmpty(corporation)) {
            result.setCorporationName(corporation.getName());
        }
        //赋值往来单位名称
        TransactionDepartment transactionDepartment = transactionDepartmentService.getById(result.getTransactionDeptId());
        if (ObjectUtil.isNotEmpty(transactionDepartment)) {
            result.setTransactionDeptName(transactionDepartment.getName());
        }
        return result;
    }

    /**
     * 账户资金流水表新增
     */
    @Override
    @DSTransactional
    public void add(AccountRunningWaterDto dto) {
        if (StringUtils.isEmpty(dto.getCurrency())) {
            throw new ServiceException("币种不能为空");
        }
        dto.setRate(ExchangeRateUtil.getCnyToCodeRate(dto.getCurrency()));
        // 修改账户余额表的余额
        AccountRemainder accountRemainder = accountRemainderService.getOne(q -> q
                .eq(AccountRemainder::getAccountManagementId, dto.getAccountManagementId())
                .eq(AccountRemainder::getCurrency, dto.getCurrency())
        );

        if (ObjectUtil.isEmpty(accountRemainder)) {
            throw new ServiceException("该账户不存在此币种，请前往资金账户添加");
        }
        BigDecimal amount = dto.getAmount();
        String status = dto.getStatus();
        BigDecimal remainder = accountRemainder.getRemainder();

        accountRemainder.setStatus(status);
        accountRemainder.setChangeRemainder(amount);

        if (status.equals("10")) {
            accountRemainder.setRemainder(remainder.add(amount));
        } else if (status.equals("20")) {
            if (remainder.compareTo(amount) < 0) {
                throw new ServiceException("账户余额不足");
            }
            accountRemainder.setRemainder(remainder.subtract(amount));
        }
        accountRemainderService.updateById(accountRemainder);

        //如果是合同到账 类型设置为到账认领
        if ("10".equals(dto.getReceived())) {
            dto.setType("30");
        }

        this.save(dto);

        //如果是往来
        if (ObjectUtil.isNotEmpty(dto.getIsTransaction()) && 1 == dto.getIsTransaction()) {
            //创建往来数据
            Transaction transaction = new Transaction();
            transaction.setDepartmentId(dto.getTransactionDeptId());
            transaction.setType("10".equals(dto.getStatus()) ? 0 : 1);
            transaction.setCurrency(dto.getCurrency());
            transaction.setAmount(dto.getAmount());
            transaction.setIsFlowingWater(1);
            transaction.setAccountId(dto.getAccountManagementId());
            transaction.setRemark(dto.getRemarks());
            transaction.setAccountRunningWaterId(dto.getId());

            Assert.notEmpty(dto.getDeptType(), "往来单位类型不能为空");
            transaction.setDeptType(dto.getDeptType());

            //赋值归属公司
            AccountManagement accountManagement = accountManagementService.getById(dto.getAccountManagementId());
            transaction.setCorporationId(accountManagement.getCorporationId());

            transactionService.save(transaction);
        }

        // 发送消息推送
        sendSocket(dto);
    }


    private void sendSocket(AccountRunningWaterDto dto) {

        if (ObjectUtil.notEqual(dto.getStatus(), "10") || ObjectUtil.notEqual(dto.getReceived(), "10")) {
            return;
        }

        // 账户id
        Long accountManagementId = dto.getAccountManagementId();
        AccountManagement accountManagement = accountManagementService.getById(accountManagementId);
        if (accountManagement == null) {
            throw new ServiceException("没有找到公司账户");
        }

        // 归属公司
        Long corporationId = accountManagement.getCorporationId();
        if (corporationId == null) {
            throw new ServiceException("归属公司id为空");
        }
        Corporation corporation = corporationService.getById(corporationId);
        if (corporation == null) {
            throw new ServiceException("没有找到归属公司");
        }

        String msg = "{} - {}账户有一笔新的到账（金额：{} {}），请相应业务员进行认领。";

        // WebSocketServer.sendInfoGroup(0, StrUtil.format(
        //         msg, corporation.getName(), accountManagement.getName(), dto.getCurrency(), dto.getAmount()));

        WebSocketPush.byTenant(
                PushTypeEnum.MESSAGE,
                StrUtil.format(msg, corporation.getName(), accountManagement.getName(), dto.getCurrency(), dto.getAmount()),
                PushBusinessTypeEnum.TO_THE_ACCOUNT.getType()
        );

    }


    /**
     * 账户资金流水表编辑
     */
    @Override
    @DSTransactional
    public void edit(AccountRunningWaterDto accountRunningWaterDto) {
        //先回滚历史数据
        //获取历史的流水信息信息
        AccountRunningWater oldAccountRunningWater = getById(accountRunningWaterDto.getId());
        //回滚余额 修改操作类型 收入变支出 支出变收入
        String status = "10".equals(oldAccountRunningWater.getStatus()) ? "20" : "10";
        oldAccountRunningWater.setStatus(status);
        //回滚原数据
        changeRemainder(oldAccountRunningWater);

        //再操作修改后数据
        changeRemainder(accountRunningWaterDto);

        this.updateById(accountRunningWaterDto);

        //修改往来信息
        if (0 == accountRunningWaterDto.getIsTransaction()) {
            //如果不是往来（删除往来数据，防止原来是往来改为不是往来）
            transactionService.remove(q -> q.eq(Transaction::getAccountRunningWaterId, accountRunningWaterDto.getId()));
        } else {
            //如果是往来（添加/修改）往来信息，防止原来不是往来修改成往来
            Transaction transaction = transactionService.getOne(q -> q.eq(Transaction::getAccountRunningWaterId, accountRunningWaterDto.getId()));
            transaction = ObjectUtil.isNotEmpty(transaction) ? transaction : new Transaction();

            transaction.setDepartmentId(accountRunningWaterDto.getTransactionDeptId());
            transaction.setType("10".equals(accountRunningWaterDto.getStatus()) ? 0 : 1);
            transaction.setCurrency(accountRunningWaterDto.getCurrency());
            transaction.setAmount(accountRunningWaterDto.getAmount());
            transaction.setIsFlowingWater(1);
            transaction.setAccountId(accountRunningWaterDto.getAccountManagementId());
            transaction.setRemark(accountRunningWaterDto.getRemarks());
            transaction.setAccountRunningWaterId(accountRunningWaterDto.getId());
            transactionService.saveOrUpdate(transaction);
        }
    }

    @DSTransactional
    @Override
    public void delete(Long id) {
        AccountRunningWater accountRunningWater = getById(id);
        Assert.notEmpty(accountRunningWater, "获取不到该流水信息");

        //回滚余额 修改操作类型 收入变支出 支出变收入
        String status = "10".equals(accountRunningWater.getStatus()) ? "20" : "10";
        accountRunningWater.setStatus(status);

        //操作余额
        changeRemainder(accountRunningWater);

        this.removeById(id);

        //删除往来
        if (1 == accountRunningWater.getIsTransaction()) {
            transactionService.remove(q -> q.eq(Transaction::getAccountRunningWaterId, id));
        }
    }

    /**
     * 到账任领统计
     */
    @Override
    public List<AccountRunningWater> claimStatistics(BaseSelectDto dto) {
        QueryWrapper<AccountRunningWater> query = Wrappers.query();
        query.groupBy("is_claim");
        query.select("is_claim,count(*) count");
        //到账认领统计
        return baseMapper.selectList(query);

    }

    @Override
    public void exportExcel(AccountRunningWaterSelectDto dto, HttpServletResponse httpServletResponse) {
        QueryWrapper<Object> wrapper = Wrappers.query();
        //资金账户
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getAccountManagementId()), "arw.account_management_id", dto.getAccountManagementId());
        //交易类型
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getStatus()), "arw.status", dto.getStatus());
        //是否合同到账
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getReceived()), "arw.received", dto.getReceived());
        //币种
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getCurrency()), "arw.currency", dto.getCurrency());
        //是否认领
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getIsClaim()), "arw.is_claim", dto.getIsClaim());
        //交易开始金额
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getBeginAmount()), "arw.amount", dto.getBeginAmount());
        //交易结束金额
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getEndAmount()), "arw.amount", dto.getEndAmount());
        //交易开始时间
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getBeginTime()), "arw.create_time", dto.getBeginTime());
        //交易结束金额
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getEndTime()), "arw.create_time", dto.getEndTime());
        //对方账户名称
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getName()), "arw.name", dto.getName());
        //摘要
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getRemarks()), "arw.name", dto.getRemarks());
        if (StringUtils.isNotEmpty(dto.getKeyword())) {
            wrapper.and(wrapper1 -> wrapper1.like("arw.remarks", dto.getKeyword()).or().like("arw.name", dto.getKeyword()));
        }
        if (ObjectUtil.isNotEmpty(dto.getDataType()) && dto.getDataType() == 1) {//到账认领数据
            wrapper.eq("arw.received", 10);
            wrapper.orderByAsc("arw.is_claim", "arw.create_time");
        }
        List<AccountRunningWaterVo> records = this.baseMapper.getList(wrapper);

        //赋值字典数据
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        List<DictTenantDataVo> dictTenantDataVos = getDict("account_currency");
        if (dictTenantDataVos.size() == 0) {
            throw new ServiceException("数据有误：没有配置币种字典，请先配置");
        }
        Map<String, List<DictTenantDataVo>> dictTenantDataVoMap = dictTenantDataVos.stream()
                .collect(Collectors.groupingBy(DictTenantDataVo::getDictKey));
        DynamicDataSourceContextHolder.poll();
        for (AccountRunningWaterVo accountRunningWaterVo : records) {
            List<DictTenantDataVo> dictTenantDataVoList = dictTenantDataVoMap.get(accountRunningWaterVo.getCurrency());
            if (ObjectUtil.isNotEmpty(dictTenantDataVoList)) {
                accountRunningWaterVo.setCurrency(dictTenantDataVoList.get(0).getDictValue());
            }
        }

        //导出Excel
        List<AccountRunningWaterBo> accountRunningWaterBos = BeanUtil.copyToList(records, AccountRunningWaterBo.class);
        for (AccountRunningWaterBo accountRunningWaterBo : accountRunningWaterBos) {
            //重新赋值收支类型
            accountRunningWaterBo.setStatus("10".equals(accountRunningWaterBo.getStatus()) ? "收入" : "支出");
            //重新赋值是否合同到账
            accountRunningWaterBo.setReceived("10".equals(accountRunningWaterBo.getReceived()) ? "是" : "否");
        }
        ExcelUtil.export(httpServletResponse, accountRunningWaterBos, AccountRunningWaterBo.class);
    }

    // 根据字典编码获取字典的数据
    private List<DictTenantDataVo> getDict(String code) {
        DictTenantDataSelectDto dto = new DictTenantDataSelectDto();
        dto.setDictCode(code);
        List<DictTenantDataVo> dictTenantDataServiceList = dictTenantDataService.getList(dto);
        return dictTenantDataServiceList;
    }

    /**
     * 退税添加
     */
    @DSTransactional
    @Override
    public void taxRefund(AccountRunningWaterDto dto) {
        dto.setStatus("10");
        dto.setType("40");//退税
        add(dto);
        List<TaxRefundDetails> taxRefundDetailsList = dto.getTaxRefundDetailsList();
        taxRefundDetailsList.forEach(item -> item.setAccountRunningWaterId(dto.getId()));
        taxRefundDetailsService.saveBatch(taxRefundDetailsList);
    }

    /**
     * 内部转账
     */
    @DSTransactional
    @Override
    public void internalTransfer(AccountRunningWaterDto dto) {
        AccountManagement outAccountManagement = accountManagementService.getById(dto.getAccountManagementId());
        AccountManagement inAccountManagement = accountManagementService.getById(dto.getInAccountManagementId());

        //生成转出流水
        dto.setStatus("20");//支出
        dto.setType("50");//内部转账
        //操作余额
        changeRemainder(dto);

        this.save(dto);

        //如果手续费不为0生成手续费
        if (ObjectUtil.isNotEmpty(dto.getCommissionAmount()) && dto.getCommissionAmount().compareTo(BigDecimal.ZERO) != 0) {
            AccountRunningWater commissionAccountRunningWater = new AccountRunningWater();
            commissionAccountRunningWater.setStatus("20");
            commissionAccountRunningWater.setType("50");//内部转账
            commissionAccountRunningWater.setRemarks(dto.getRemarks());
            commissionAccountRunningWater.setTransactionTime(dto.getTransactionTime());

            commissionAccountRunningWater.setAccountManagementId(dto.getAccountManagementId());
            commissionAccountRunningWater.setAmount(dto.getCommissionAmount());
            Assert.notEmpty(dto.getCommissionCurrency(), "手续费币种不能为空");
            commissionAccountRunningWater.setCurrency(dto.getCommissionCurrency());
            commissionAccountRunningWater.setRemarks("手续费");
            //操作余额
            changeRemainder(commissionAccountRunningWater);
            this.save(commissionAccountRunningWater);
        }

        //生成收入流水
        AccountRunningWater inAccountRunningWater = new AccountRunningWater();
        inAccountRunningWater.setStatus("10");
        inAccountRunningWater.setType("50");//内部转账
        inAccountRunningWater.setRemarks(dto.getRemarks());
        inAccountRunningWater.setTransactionTime(dto.getTransactionTime());

        inAccountRunningWater.setAccountManagementId(dto.getInAccountManagementId());
        inAccountRunningWater.setAmount(dto.getInAmount());
        Assert.notEmpty(dto.getInCurrency(), "收入币种不能为空");
        inAccountRunningWater.setCurrency(dto.getInCurrency());
        //操作余额
        changeRemainder(inAccountRunningWater);

        this.save(inAccountRunningWater);

        //如果是往来
        if (ObjectUtil.isNotEmpty(dto.getIsTransaction()) && 1 == dto.getIsTransaction()) {
            dto.setDeptType(1);
            dto.setTransactionDeptId(inAccountManagement.getCorporationId());
            this.updateById(dto);
            inAccountRunningWater.setDeptType(1);
            inAccountRunningWater.setTransactionDeptId(outAccountManagement.getCorporationId());
            this.updateById(inAccountRunningWater);

            //转入转出归属公司不同生成往来记录
            if (inAccountManagement.getCorporationId() != outAccountManagement.getCorporationId()) {
                //创建转入往来数据
                Transaction transaction = new Transaction();
                transaction.setType(1);//支出
                transaction.setCurrency(dto.getCurrency());
                transaction.setAmount(dto.getAmount());
                transaction.setIsFlowingWater(1);
                transaction.setAccountId(dto.getAccountManagementId());
                transaction.setRemark(dto.getRemarks());
                transaction.setAccountRunningWaterId(dto.getId());
                transaction.setDeptType(1);

                //赋值归属公司（转出账户归属公司）
                transaction.setCorporationId(outAccountManagement.getCorporationId());
                //赋值往来单位（转入账户归属公司）
                transaction.setDepartmentId(inAccountManagement.getCorporationId());

                transactionService.save(transaction);

                //创建转出往来数据
                Transaction transaction1 = new Transaction();
                transaction1.setType(0);//收入
                transaction1.setCurrency(inAccountRunningWater.getCurrency());
                transaction1.setAmount(inAccountRunningWater.getAmount());
                transaction1.setIsFlowingWater(1);
                transaction1.setAccountId(inAccountRunningWater.getAccountManagementId());
                transaction1.setRemark(inAccountRunningWater.getRemarks());
                transaction1.setAccountRunningWaterId(inAccountRunningWater.getId());
                transaction1.setDeptType(1);

                //赋值归属公司（转入账户归属公司）
                transaction1.setCorporationId(inAccountManagement.getCorporationId());
                //赋值往来单位（转出账户归属公司）
                transaction1.setDepartmentId(outAccountManagement.getCorporationId());

                transactionService.save(transaction1);
            }
        }

    }

    /**
     * 余额操作
     */
    @Override
    public void changeRemainder(AccountRunningWater accountRunningWater) {
        // 修改账户余额表的余额
        AccountRemainder accountRemainder = accountRemainderService.getOne(q -> q
                .eq(AccountRemainder::getAccountManagementId, accountRunningWater.getAccountManagementId())
                .eq(AccountRemainder::getCurrency, accountRunningWater.getCurrency())
        );
        if (ObjectUtil.isEmpty(accountRemainder)) {
            throw new ServiceException("该账户不存在此币种，请前往资金账户添加");
        }
        BigDecimal amount = accountRunningWater.getAmount();
        String status = accountRunningWater.getStatus();
        BigDecimal remainder = accountRemainder.getRemainder();

        accountRemainder.setStatus(status);
        accountRemainder.setChangeRemainder(amount);

        boolean update = false;
        if ("10".equals(accountRunningWater.getStatus())) {
            //收入操作
            update = accountRemainderService.update(q -> q
                    .setSql("remainder = remainder + " + accountRunningWater.getAmount())
                    .setSql("change_remainder = " + accountRunningWater.getAmount())
                    .eq(AccountRemainder::getId, accountRemainder.getId())
            );
        } else {
            //支出操作
            BigDecimal subtract = remainder.subtract(amount);
            if (subtract.compareTo(BigDecimal.ZERO) < 0) {
                throw new ServiceException("账户余额不足");
            }

            update = accountRemainderService.update(q -> q
                    .setSql("remainder = remainder - " + accountRunningWater.getAmount())
                    .setSql("change_remainder = " + accountRunningWater.getAmount())
                    .eq(AccountRemainder::getId, accountRemainder.getId())
                    .apply("remainder - {0} >= 0", accountRunningWater.getAmount())
            );
        }
        Assert.eqTrue(update, "余额操作失败,请重试！！！");
    }

}
