package com.dk.mdm.service.mac;

import com.dk.common.exception.BaseBusinessException;
import com.dk.common.infrastructure.annotaiton.Pagination;
import com.dk.common.infrastructure.constant.Constant;
import com.dk.common.infrastructure.enums.ErrorCodeEnum;
import com.dk.common.model.pojo.PageList;
import com.dk.common.response.ResponseCodeEnum;
import com.dk.common.response.ResponseResultUtil;
import com.dk.common.response.ResponseResultVO;
import com.dk.mdm.infrastructure.convert.mac.RecPayConvert;
import com.dk.mdm.infrastructure.convert.mac.RecPayHandleItemConvert;
import com.dk.mdm.infrastructure.convert.mac.RecPayItemConvert;
import com.dk.mdm.mapper.mac.*;
import com.dk.mdm.mapper.mst.MoneyAccountItemMapper;
import com.dk.mdm.mapper.mst.MoneyAccountMapper;
import com.dk.mdm.model.pojo.mac.*;
import com.dk.common.service.BaseService;
import com.dk.common.mapper.BaseMapper;
import com.dk.mdm.model.pojo.mst.MoneyAccount;
import com.dk.mdm.model.pojo.mst.MoneyAccountItem;
import com.dk.mdm.model.query.mac.RecPayHandleItemQuery;
import com.dk.mdm.model.query.mac.RecPayItemQuery;
import com.dk.mdm.model.query.mac.RecPayQuery;
import com.dk.mdm.model.response.mac.RecPayHandleItemResponse;
import com.dk.mdm.model.response.mac.RecPayItemResponse;
import com.dk.mdm.model.response.mac.RecPayResponse;
import com.dk.mdm.model.vo.mac.RecPayHandleItemVO;
import com.dk.mdm.model.vo.mac.RecPayItemVO;
import com.dk.mdm.model.vo.mac.RecPayVO;
import com.dk.mdm.service.common.CommonService;
import com.dk.mdm.service.mst.MoneyAccountService;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@Transactional
public class ReceiptService extends BaseService<RecPay> {

    @Override
    public String getPrimaryKey() {
        return "rp_id";
    }

    @Override
    public BaseMapper<RecPay> getRepository() {
        return recPayMapper;
    }

    @Autowired
    private RecPayMapper recPayMapper;

    @Autowired
    private RecPayItemService recPayItemService;

    @Autowired
    private RecPayItemMapper recPayItemMapper;

    @Autowired
    private AccountService accountService;

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private AccountItemService accountItemService;

    @Autowired
    private MoneyAccountMapper moneyAccountMapper;

    @Autowired
    private AccountItemMapper accountItemMapper;

    @Autowired
    private MoneyAccountService moneyAccountService;

    @Autowired
    private MoneyAccountItemMapper moneyAccountItemMapper;

    @Autowired
    private RecPayHandleItemService recPayHandleItemService;

    @Autowired
    private RecPayHandleItemMapper recPayHandleItemMapper;

    @Autowired
    private CommonService commonService;

    @Autowired
    private RecPayConvert recPayConvert;

    @Autowired
    private RecPayItemConvert recPayItemConvert;

    @Autowired
    private RecPayHandleItemConvert recPayHandleItemConvert;

    /**
     * @desc : 条件查询
     * @author : 付斌
     * @date : 2023/1/9 10:40
     */
    @Pagination
    public ResponseResultVO<PageList<RecPayResponse>> selectByCond(RecPayQuery recPayQuery) {
        return super.mergeListWithCount(recPayQuery, recPayMapper.selectByCond(recPayQuery),
                recPayMapper.countByCond(recPayQuery));
    }

    /**
     * @desc : 查询收款明细
     * @author : 付斌
     * @date : 2024-02-28 13:25
     */
    @Pagination
    public ResponseResultVO selectById(String id) {
        Map<String, Object> result = new HashMap<>();
        RecPayResponse recPayResponse = recPayMapper.selectById(id);
        result.put("data", recPayResponse);
        // 收款明细
        List<RecPayItemResponse> recPayItem = recPayItemMapper.selectByCond(new RecPayItemQuery().setRpId(id));
        result.put("recPayItem", recPayItem);

        // 应收核销明细
        List<RecPayHandleItemResponse> recPayHandleItem = recPayHandleItemMapper.selectByCond(new RecPayHandleItemQuery().setRpId(id));
        result.put("recPayHandleItem", recPayHandleItem);

        // 附件
        return ResponseResultUtil.success(result);
    }

    /**
     * @desc : 查询收款明细
     * @author : 付斌
     * @date : 2024-02-28 13:25
     */
    @Pagination
    public ResponseResultVO<Map<String, Object>> selectRpInfoById(String id) {
        Map<String, Object> result = new HashMap<>();
        // 收款明细
        List<RecPayItemResponse> recPayItem = recPayItemMapper.selectByCond(new RecPayItemQuery().setRpId(id));
        result.put("recPayItem", recPayItem);

        // 应收核销明细
        List<RecPayHandleItemResponse> recPayHandleItem = recPayHandleItemMapper.selectByCond(new RecPayHandleItemQuery().setRpId(id));
        result.put("recPayHandleItem", recPayHandleItem);

        // 附件
        return ResponseResultUtil.success(result);
    }

    /**
     * @desc : 新建客户收款
     * @author : 付斌
     * @date : 2023/1/9 10:49
     */
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public ResponseResultVO<?> insertReceipt(RecPayVO recPayVO) {

        // 获取单号
        Map<String, Object> codeMap = commonService.getUniqueNoteCode(Constant.docNameConstant.RECPAY.getName(), false);
        recPayVO.setRpId(codeMap.get("outId").toString()).setRpNo(codeMap.get("outNote").toString());
        // 转化实体
        RecPay recPay = recPayConvert.convertToPo(recPayVO);
        // 总单保存
        super.insert(recPay);

        // 明细保存
        if (recPayVO.getItemList() != null && recPayVO.getItemList().size() > 0) {
            for (RecPayItemVO recPayItemVO : recPayVO.getItemList()) {
                RecPayItem recPayItem = recPayItemConvert.convertToPo(recPayItemVO);
                recPayItem.setRpId(recPay.getRpId()).setCpId(recPay.getCpId()).setMakeStaff(recPay.getMakeStaff()).setAccDate(recPay.getAccDate());
                recPayItemMapper.insert(recPayItem);

                // 插入账款明细
                AccountItem accountItem = new AccountItem();
                accountItem.setAccItemType(Constant.accItemType.SHOU_KUAN.getName())
                        .setObjectId(recPayVO.getObjectId()).setOrgId(recPayVO.getOrgId()).setStaffId(recPayVO.getStaffId())
                        .setAccDate(recPayVO.getAccDate()).setRecStatus(Constant.recStatuse.QUE_DING.getName()).setAmtRec(recPayItem.getAmtRec())
                        .setBiznisType("t_mac_rec_pay_item").setBiznisId(recPayItem.getItemId()).setBiznisNo(recPayVO.getRpNo())
                        .setMakeStaff(recPayVO.getMakeStaff()).setCpId(recPayVO.getCpId());
                accountItemMapper.insert(accountItem);

                // 更新收款单上的账款明细Id
                RecPayItem recPayItemUpdate = new RecPayItem();
                recPayItemUpdate.setAccItemId(accountItem.getItemId()).setItemId(recPayItem.getItemId());
                recPayItemService.updateByUuid(recPayItemUpdate);

                // 插入资金流水
                MoneyAccountItem moneyAccountItem = new MoneyAccountItem();
                moneyAccountItem.setMacId(recPayItem.getMacId()).setFlowType(Constant.FlowType.SHOU_FU_KUAN.getName())
                        .setInvoiceId(recPayItem.getItemId()).setAmtInflow(recPayItem.getAmtRec()).setAccDate(recPayVO.getAccDate())
                        .setMakeStaff(recPayItem.getMakeStaff()).setCpId(recPayItem.getCpId());
                moneyAccountItemMapper.insert(moneyAccountItem);

                // 更新资金账户
                MoneyAccount moneyAccountForUpdate = moneyAccountMapper.selectByIdForUpdate(recPayItem.getMacId());
                MoneyAccount moneyAccountUpdate = new MoneyAccount();
                moneyAccountUpdate.setBalance(moneyAccountForUpdate.getBalance().add(recPayItem.getAmtRec()))
                        .setMacId(moneyAccountForUpdate.getMacId());
                moneyAccountService.updateByUuid(moneyAccountUpdate);
            }
        }

        // 插入账款总表
        Account accountForUpdate = accountService.getCusAccountForUpdate(recPayVO.getObjectId());
        // 更新账款总表上收款的相关字段
        Account accountUpdate = new Account();
        accountUpdate.setReceipt(accountForUpdate.getReceipt().add(recPayVO.getSumAmtRec()))// 总收款金额
                .setReceiptResidue(accountForUpdate.getReceiptResidue().add(recPayVO.getSumAmtRec()))//  可退金额
                .setObjectId(accountForUpdate.getObjectId());
        accountService.updateByUuid(accountUpdate);
        return ResponseResultUtil.success();
    }

    /**
     * @desc :  新建客户退款
     * @author : 付斌
     * @date : 2023/1/9 10:49
     */
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public ResponseResultVO<?> insertRefund(RecPayVO recPayVO) {

        // 查总账，看可退金额是否满足
        Account accountForUpdate = accountMapper.selectByIdForUpdate(recPayVO.getObjectId());
//        if (accountForUpdate == null || accountForUpdate.getReceiptResidue().compareTo(recPayVO.getSumAmtRec().abs()) == -1) {
//            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.RESIDUE_NO_LESS.getMessage());
//        }

        // 获取单号
        Map<String, Object> codeMap = commonService.getUniqueNoteCode(Constant.docNameConstant.RECPAY.getName(), false);
        recPayVO.setRpId(codeMap.get("outId").toString()).setRpNo(codeMap.get("outNote").toString());
        // 转化实体
        RecPay recPay = recPayConvert.convertToPo(recPayVO);
        // 总单保存
        super.insert(recPay);

        // 明细保存
        if (recPayVO.getItemList() != null && recPayVO.getItemList().size() > 0) {
            for (RecPayItemVO recPayItemVO : recPayVO.getItemList()) {
                RecPayItem recPayItem = recPayItemConvert.convertToPo(recPayItemVO);
                recPayItem.setRpId(recPay.getRpId()).setCpId(recPay.getCpId()).setMakeStaff(recPay.getMakeStaff()).setAccDate(recPay.getAccDate());
                recPayItemMapper.insert(recPayItem);

                // 插入账款明细
                AccountItem accountItem = new AccountItem();
                accountItem.setAccItemType(Constant.accItemType.SHOU_KUAN.getName())
                        .setObjectId(recPayVO.getObjectId()).setOrgId(recPayVO.getOrgId()).setStaffId(recPayVO.getStaffId())
                        .setAccDate(recPayVO.getAccDate()).setRecStatus(Constant.recStatuse.QUE_DING.getName()).setAmtRec(recPayItem.getAmtRec())
                        .setBiznisType("t_mac_rec_pay_item").setBiznisId(recPayItem.getItemId()).setBiznisNo(recPayVO.getRpNo())
                        .setMakeStaff(recPayVO.getMakeStaff()).setCpId(recPayVO.getCpId());
                accountItemMapper.insert(accountItem);

                // 更新收款单上的账款明细Id
                RecPayItem recPayItemUpdate = new RecPayItem();
                recPayItemUpdate.setAccItemId(accountItem.getItemId()).setItemId(recPayItem.getItemId());
                recPayItemService.updateByUuid(recPayItemUpdate);

                // 插入资金流水
                MoneyAccountItem moneyAccountItem = new MoneyAccountItem();
                moneyAccountItem.setMacId(recPayItem.getMacId()).setFlowType(Constant.FlowType.SHOU_FU_KUAN.getName())
                        .setInvoiceId(recPayItem.getItemId()).setAmtInflow(recPayItem.getAmtRec()).setAccDate(recPayVO.getAccDate())
                        .setMakeStaff(recPayItem.getMakeStaff()).setCpId(recPayItem.getCpId());
                moneyAccountItemMapper.insert(moneyAccountItem);

                // 更新资金账户
                MoneyAccount moneyAccountForUpdate = moneyAccountMapper.selectByIdForUpdate(recPayItem.getMacId());
                MoneyAccount moneyAccountUpdate = new MoneyAccount();
                moneyAccountUpdate.setBalance(moneyAccountForUpdate.getBalance().add(recPayItem.getAmtRec()))
                        .setMacId(moneyAccountForUpdate.getMacId());

                // 如果账户不允许为负数
                if (!moneyAccountForUpdate.getFlgNegative()) {
                    // 如果余额小于0 ，则提示余额不足
                    if (moneyAccountUpdate.getBalance().compareTo(BigDecimal.ZERO) == -1) {
                        throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.MAC_BALANCE_NO_LESS.getMessage());
                    }
                }
                moneyAccountService.updateByUuid(moneyAccountUpdate);
            }
        }

        // 更新账款总表上收款的相关字段
        Account accountUpdate = new Account();
        accountUpdate.setReceipt(accountForUpdate.getReceipt().add(recPayVO.getSumAmtRec()))// 总收款金额
                .setReceiptResidue(accountForUpdate.getReceiptResidue().add(recPayVO.getSumAmtRec()))//  可退金额
                .setObjectId(accountForUpdate.getObjectId());
        accountService.updateByUuid(accountUpdate);
        return ResponseResultUtil.success();
    }

    /**
     * @desc : 编辑客户收款/退款
     * @author : 付斌
     * @date : 2023/1/9 10:49
     */
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public ResponseResultVO<?> update(RecPayVO recPayVO) {
        RecPay recPayForUpdate = recPayMapper.selectByIdForUpdate(recPayVO.getRpId());
        // 并发校验
        if (!recPayForUpdate.getFlgValid()) {
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.ISFLGVALID_FALSE.getMessage());
        }
        if(recPayForUpdate.getBiznisId() != null){
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.INVOICE_FORBID_EDIT.getMessage());
        }

        // 将之前的明细全部删除
        List<RecPayItem> recPayItemOriginalList = recPayItemMapper.selectByZIdForUpdate(recPayVO.getRpId());
        // 需要重新计算的资金账户
        List<String> macList = new ArrayList<>();
        for (RecPayItem recPayItem : recPayItemOriginalList) {
            // 删除收付款明细
            recPayItemMapper.deleteById(recPayItem.getItemId());
            // 删除账款明细
            accountItemMapper.deleteById(recPayItem.getAccItemId());
            // 删除账户流水
            moneyAccountItemMapper.deleteByInvoiceId(recPayItem.getItemId());

            if (!macList.contains(recPayItem.getMacId())) {
                macList.add(recPayItem.getMacId());
            }
        }

        // 新增明细
        for (RecPayItemVO recPayItemVO : recPayVO.getItemList()) {
            RecPayItem recPayItem = recPayItemConvert.convertToPo(recPayItemVO);
            recPayItem.setItemId(null).setRpId(recPayVO.getRpId()).setCpId(recPayVO.getCpId());
            recPayItemMapper.insert(recPayItem);

            // 插入账款明细
            AccountItem accountItem = new AccountItem();
            accountItem.setAccItemType(Constant.accItemType.SHOU_KUAN.getName())
                    .setObjectId(recPayVO.getObjectId()).setOrgId(recPayVO.getOrgId()).setStaffId(recPayVO.getStaffId())
                    .setAccDate(recPayVO.getAccDate()).setRecStatus(Constant.recStatuse.QUE_DING.getName()).setAmtRec(recPayItem.getAmtRec())
                    .setBiznisType("t_mac_rec_pay_item").setBiznisId(recPayItem.getItemId()).setBiznisNo(recPayVO.getRpNo())
                    .setMakeStaff(recPayVO.getMakeStaff()).setCpId(recPayVO.getCpId());
            accountItemMapper.insert(accountItem);

            // 更新收款单上的账款明细Id
            RecPayItem recPayItemUpdate = new RecPayItem();
            recPayItemUpdate.setAccItemId(accountItem.getItemId()).setItemId(recPayItem.getItemId());
            recPayItemService.updateByUuid(recPayItemUpdate);

            // 插入资金流水
            MoneyAccountItem moneyAccountItem = new MoneyAccountItem();
            moneyAccountItem.setMacId(recPayItem.getMacId()).setFlowType(Constant.FlowType.SHOU_FU_KUAN.getName())
                    .setInvoiceId(recPayItem.getItemId()).setAmtInflow(recPayItem.getAmtRec()).setAccDate(recPayVO.getAccDate())
                    .setMakeStaff(recPayItem.getMakeStaff()).setCpId(recPayItem.getCpId());
            moneyAccountItemMapper.insert(moneyAccountItem);

            if (!macList.contains(recPayItem.getMacId())) {
                macList.add(recPayItem.getMacId());
            }
        }

        // 更新总账表的总收款额和可用额
        accountService.updateReceipt(recPayVO.getObjectId());
        // 更新账户余额
        for (String macId : macList) {
            accountService.updateMac(macId);
        }

        // 更新收款单总表
        RecPay recPay = recPayConvert.convertToPo(recPayVO);
        return ResponseResultUtil.success(super.updateByUuid(recPay));
    }

    /**
     * @desc : 获取订单信息（编辑用）
     * @author : 付斌
     * @date : 2024-03-02 17:27
     */
    public ResponseResultVO<?> getRpForUpdate(String id) {
        Map<String, Object> dataInfo = new HashMap<>();
        RecPayResponse recPayResponse = recPayMapper.selectById(id);
        dataInfo.put("data", recPayResponse);

        // 收款明细
        List<RecPayItemResponse> recPayItemResponse = recPayItemMapper.selectByCond(new RecPayItemQuery().setRpId(id));
        dataInfo.put("dataItem", recPayItemResponse);

        return ResponseResultUtil.success(dataInfo);
    }

    /**
     * @desc : 新建应收核销(收款+核销应收)
     * @author : 付斌
     * @date : 2023/1/9 10:49
     */
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public ResponseResultVO<?> insertReceivableReceipt(RecPayVO recPayVO) {

        /*********************  收款的处理 begin **********************/
        // 获取单号
        Map<String, Object> codeMap = commonService.getUniqueNoteCode(Constant.docNameConstant.RECPAY.getName(), false);
        recPayVO.setRpId(codeMap.get("outId").toString()).setRpNo(codeMap.get("outNote").toString());
        // 转化实体
        RecPay recPay = recPayConvert.convertToPo(recPayVO);
        // 总单保存
        super.insert(recPay);

        // 明细保存
        if (recPayVO.getItemList() != null && recPayVO.getItemList().size() > 0) {
            for (RecPayItemVO recPayItemVO : recPayVO.getItemList()) {
                RecPayItem recPayItem = recPayItemConvert.convertToPo(recPayItemVO);
                recPayItem.setRpId(recPay.getRpId()).setCpId(recPay.getCpId()).setMakeStaff(recPay.getMakeStaff()).setAccDate(recPay.getAccDate());
                recPayItemMapper.insert(recPayItem);

                // 插入账款明细
                AccountItem accountItem = new AccountItem();
                accountItem.setAccItemType(Constant.accItemType.SHOU_KUAN.getName())
                        .setObjectId(recPayVO.getObjectId()).setOrgId(recPayVO.getOrgId()).setStaffId(recPayVO.getStaffId())
                        .setAccDate(recPayVO.getAccDate()).setRecStatus(Constant.recStatuse.QUE_DING.getName()).setAmtRec(recPayItem.getAmtRec())
                        .setBiznisType("t_mac_rec_pay_item").setBiznisId(recPayItem.getItemId()).setBiznisNo(recPayVO.getRpNo())
                        .setMakeStaff(recPayVO.getMakeStaff()).setCpId(recPayVO.getCpId());
                accountItemMapper.insert(accountItem);

                // 更新收款单上的账款明细Id
                RecPayItem recPayItemUpdate = new RecPayItem();
                recPayItemUpdate.setAccItemId(accountItem.getItemId()).setItemId(recPayItem.getItemId());
                recPayItemService.updateByUuid(recPayItemUpdate);

                // 插入资金流水
                MoneyAccountItem moneyAccountItem = new MoneyAccountItem();
                moneyAccountItem.setMacId(recPayItem.getMacId()).setFlowType(Constant.FlowType.SHOU_FU_KUAN.getName())
                        .setInvoiceId(recPayItem.getItemId()).setAmtInflow(recPayItem.getAmtRec()).setAccDate(recPayVO.getAccDate())
                        .setMakeStaff(recPayItem.getMakeStaff()).setCpId(recPayItem.getCpId());
                moneyAccountItemMapper.insert(moneyAccountItem);

                // 更新资金账户
                MoneyAccount moneyAccountForUpdate = moneyAccountMapper.selectByIdForUpdate(recPayItem.getMacId());
                MoneyAccount moneyAccountUpdate = new MoneyAccount();
                moneyAccountUpdate.setBalance(moneyAccountForUpdate.getBalance().add(recPayItem.getAmtRec()))
                        .setMacId(moneyAccountForUpdate.getMacId());

                // 如果账户不允许为负数
                if (!moneyAccountForUpdate.getFlgNegative()) {
                    // 如果余额小于0 ，则提示余额不足
                    if (moneyAccountUpdate.getBalance().compareTo(BigDecimal.ZERO) == -1) {
                        throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.MAC_BALANCE_NO_LESS.getMessage());
                    }
                }
                moneyAccountService.updateByUuid(moneyAccountUpdate);
            }
        }

        // 插入账款总表
        Account accountForUpdate = accountService.getCusAccountForUpdate(recPayVO.getObjectId());
        // 更新账款总表上收款的相关字段
        Account accountUpdate = new Account();
        accountUpdate.setReceipt(accountForUpdate.getReceipt().add(recPayVO.getSumAmtRec()))// 总收款金额
                .setReceiptResidue(accountForUpdate.getReceiptResidue().add(recPayVO.getSumAmtRec()))//  可退金额
                .setObjectId(accountForUpdate.getObjectId());
        accountService.updateByUuid(accountUpdate);
        /*********************  收款的处理 end **********************/


        /*********************  应收收款的处理 begin **********************/
        // 应收收款的处理
        if (recPayVO.getReceivableList() != null && recPayVO.getReceivableList().size() > 0) {
            for (RecPayHandleItemVO recPayHandleItemVO : recPayVO.getReceivableList()) {
                RecPayHandleItem recPayHandleItem = recPayHandleItemConvert.convertToPo(recPayHandleItemVO);
                recPayHandleItem.setItemId(null).setRpId(recPay.getRpId()).setCpId(recPay.getCpId()).setAccDate(recPay.getAccDate());
                recPayHandleItemMapper.insert(recPayHandleItem);

                // 账款明细的核销金额和优惠金额
                AccountItem accountItemForUpdate = accountItemMapper.selectByIdForUpdate(recPayHandleItem.getAccItemId());
                AccountItem accountItemUpdate = new AccountItem();
                // 核销金额，超出剩余应收金额
                if (accountItemForUpdate.getAmtResidue().compareTo(recPayHandleItem.getAmtReceivableHandle()) == -1) {
                    throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.AMT_HANDLE_NO_LESS_AMT_SHOULD.getMessage());
                }
                accountItemUpdate.setAmtHandle(accountItemForUpdate.getAmtHandle().add(recPayHandleItem.getAmtReceivableHandle()))
                        .setAmtWaive(accountItemForUpdate.getAmtWaive().add(recPayHandleItem.getAmtWaive()))
                        .setItemId(recPayHandleItem.getAccItemId());
                // 剩余金额 = 应收金额-应收收款金额
                accountItemUpdate.setAmtResidue(accountItemForUpdate.getAmtShould().subtract(accountItemUpdate.getAmtHandle()));
                accountItemService.updateByUuid(accountItemUpdate);
            }

            // 计算明细的核销金额，优惠金额合计
            RecPayHandleItemVO recPayHandleItemVO = recPayVO.getReceivableList().stream().reduce((x, y) -> {
                RecPayHandleItemVO item = new RecPayHandleItemVO();
                item.setAmtReceivableHandle(x.getAmtReceivableHandle().add(y.getAmtReceivableHandle()));
                item.setAmtWaive(x.getAmtWaive().add(y.getAmtWaive()));
                return item;
            }).get();

            // 更新总账上
            accountForUpdate = accountMapper.selectByIdForUpdate(recPayVO.getObjectId());
            accountUpdate = new Account();
            accountUpdate.setReceivableHandle(accountForUpdate.getReceivableHandle().add(recPayHandleItemVO.getAmtReceivableHandle()))// 总应收收款金额
                    .setReceivableWaive(accountForUpdate.getReceivableWaive().add(recPayHandleItemVO.getAmtWaive()))//  总应收优惠金额
                    .setObjectId(accountForUpdate.getObjectId());
            // 剩余应收 = 总应收账款-总应收收款金额
            accountUpdate.setReceivableResidue(accountForUpdate.getReceivable().subtract(accountUpdate.getReceivableHandle()));
            // 可退金额 = 总收款金额-总应收收款金额+总应收优惠金额
            accountUpdate.setReceiptResidue(accountForUpdate.getReceipt().subtract(accountUpdate.getReceivableHandle()).add(accountUpdate.getReceivableWaive()));

            // 更新前的最后校验
            // 剩余应收为负数，则不能保存
//            if (accountUpdate.getReceivableResidue().compareTo(BigDecimal.ZERO) == -1) {
//                throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.AMT_HANDLE_NO_LESS_AMT_SHOULD.getMessage());
//            }
            // 可用金额为负数，则不能保存
            if (accountUpdate.getReceiptResidue().compareTo(BigDecimal.ZERO) == -1) {
                throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.RESIDUE_NO_LESS.getMessage());
            }
            accountService.updateByUuid(accountUpdate);
        }
        /*********************  应收收款的处理 end **********************/
        return ResponseResultUtil.success();
    }

    /**
     * @desc : 更新应收核销(小编辑)
     * @author : 付斌
     * @date : 2023/1/9 10:49
     */
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public ResponseResultVO<?> updateReceivableReceipt(RecPayVO recPayVO) {
        // 先只改备注和附件
        RecPay recPay = new RecPay();
        recPay.setRemarks(recPayVO.getRemarks()).setAnnexPaths(recPayVO.getAnnexPaths()).setRpId(recPayVO.getRpId());
        super.updateByUuid(recPay);
        return ResponseResultUtil.success();
    }

    /**
     * @desc : 作废
     * @author : 付斌
     * @date : 2024-03-08 16:38
     */
    public ResponseResultVO<?> invalid(String id) {
        RecPay recPayForUpdate = recPayMapper.selectByIdForUpdate(id);
        // 并发校验
        if (!recPayForUpdate.getFlgValid()) {
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.ISFLGVALID_FALSE.getMessage());
        }
        if(recPayForUpdate.getBiznisId() != null){
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.INVOICE_FORBID_EDIT.getMessage());
        }
        // 如果所在月份已结账，则不能作废 todo

        // 查出并锁定所有应收核销明细
        AccountItem accountItemForUpdate;
        List<RecPayHandleItem> recPayHandleItemForUpdateList = recPayHandleItemMapper.selectByZIdForUpdate(id);
        for (RecPayHandleItem recPayHandleItemForUpdate : recPayHandleItemForUpdateList) {
            // 更新账款明细应收收款
            accountItemForUpdate = accountItemMapper.selectByIdForUpdate(recPayHandleItemForUpdate.getAccItemId());
            AccountItem accountItemUpdate = new AccountItem();
            accountItemUpdate.setAmtHandle(accountItemForUpdate.getAmtHandle().subtract(recPayHandleItemForUpdate.getAmtReceivableHandle()))
                    .setAmtWaive(accountItemForUpdate.getAmtWaive().subtract(recPayHandleItemForUpdate.getAmtWaive()))
                    .setItemId(recPayHandleItemForUpdate.getAccItemId());
            accountItemUpdate.setAmtResidue(accountItemForUpdate.getAmtShould().subtract(accountItemUpdate.getAmtHandle()).subtract(accountItemUpdate.getAmtWaive()));
            accountItemService.updateByUuid(accountItemUpdate);

            // 将核销明细有效标识置为false
            RecPayHandleItem recPayHandleItemUpdate = new RecPayHandleItem();
            recPayHandleItemUpdate.setFlgValid(false).setItemId(recPayHandleItemForUpdate.getItemId());
            recPayHandleItemService.updateByUuid(recPayHandleItemUpdate);
        }

        // 把总帐上的钱加回来
        Account accountForUpdate = accountMapper.selectByIdForUpdate(recPayForUpdate.getObjectId());
        Account accountUpdate = new Account();
        accountUpdate.setReceivableHandle(accountForUpdate.getReceivableHandle().subtract(recPayForUpdate.getSumAmtReceivableHandle()))// 总应收收款金额
                .setReceivableWaive(accountForUpdate.getReceivableWaive().subtract(recPayForUpdate.getSumWaiveAmt()))//  总应收优惠金额
                .setObjectId(accountForUpdate.getObjectId());
        // 剩余应收 = 总应收账款-总应收收款金额
        accountUpdate.setReceivableResidue(accountForUpdate.getReceivable().subtract(accountUpdate.getReceivableHandle()));
        // 可退金额 = 总收款金额-总应收收款金额+总应收优惠金额
        accountUpdate.setReceiptResidue(accountForUpdate.getReceipt().subtract(accountUpdate.getReceivableHandle()).add(accountUpdate.getReceivableWaive()));

        // 更新前的最后校验
        // 剩余应收为负数，则不能保存
//        if (accountUpdate.getReceivableResidue().compareTo(BigDecimal.ZERO) == -1) {
//            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.AMT_HANDLE_NO_LESS_AMT_SHOULD.getMessage());
//        }
        // 可用金额为负数，则不能保存
        if (accountUpdate.getReceiptResidue().compareTo(BigDecimal.ZERO) == -1) {
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.RESIDUE_NO_LESS.getMessage());
        }
        accountService.updateByUuid(accountUpdate);

        // 将之前的明细全部删除
        List<RecPayItem> recPayItemOriginalList = recPayItemMapper.selectByZIdForUpdate(id);
        // 需要重新计算的资金账户
        List<String> macList = new ArrayList<>();
        for (RecPayItem recPayItem : recPayItemOriginalList) {
            // 删除收付款明细
            recPayItemMapper.deleteById(recPayItem.getItemId());
            // 删除账款明细
            accountItemMapper.deleteById(recPayItem.getAccItemId());
            // 删除账户流水
            moneyAccountItemMapper.deleteByInvoiceId(recPayItem.getItemId());

            if (!macList.contains(recPayItem.getMacId())) {
                macList.add(recPayItem.getMacId());
            }
        }
        // 更新总账表的总收款额和可用额
        accountService.updateReceipt(recPayForUpdate.getObjectId());
        // 更新账户余额
        for (String macId : macList) {
            accountService.updateMac(macId);
        }
        // 作废
        RecPay recPayUpdate = new RecPay();
        recPayUpdate.setFlgValid(false).setRpId(id);
        super.updateByUuid(recPayUpdate);
        return ResponseResultUtil.success();
    }

    /**
     * @desc : 获取应收收款（编辑用）
     * @author : 付斌
     * @date : 2024-02-28 13:25
     */
    @Pagination
    public ResponseResultVO getReceivableReceiptForUpdate(String id) {
        Map<String, Object> result = new HashMap<>();
        RecPayResponse recPayResponse = recPayMapper.selectById(id);
        result.put("data", recPayResponse);
        // 收款明细
        List<RecPayItemResponse> recPayItem = recPayItemMapper.selectByCond(new RecPayItemQuery().setRpId(id));
        result.put("dataItem", recPayItem);

        // 应收核销明细
        List<RecPayHandleItemResponse> recPayHandleItem = recPayHandleItemMapper.selectByCond(new RecPayHandleItemQuery().setRpId(id));
        result.put("recPayHandleItem", recPayHandleItem);

        // 附件
        return ResponseResultUtil.success(result);
    }

}
