package com.dk.mdm.service.mac;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
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.OtherReceivableConvert;
import com.dk.mdm.infrastructure.convert.mac.OtherReceivableItemConvert;
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.OtherReceivableItemQuery;
import com.dk.mdm.model.query.mac.OtherReceivableQuery;
import com.dk.mdm.model.query.mac.RecPayHandleItemQuery;
import com.dk.mdm.model.query.mac.RecPayItemQuery;
import com.dk.mdm.model.response.mac.*;
import com.dk.mdm.model.vo.mac.OtherReceivableItemVO;
import com.dk.mdm.model.vo.mac.OtherReceivableVO;
import com.dk.mdm.model.vo.mac.RecPayItemVO;
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 OtherReceivableService extends BaseService<OtherReceivable> {

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

    @Override
    public BaseMapper<OtherReceivable> getRepository() {
        return otherReceivableMapper;
    }

    @Autowired
    private OtherReceivableMapper otherReceivableMapper;

    @Autowired
    private OtherReceivableItemMapper otherReceivableItemMapper;

    @Autowired
    private CommonService commonService;

    @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 RecPayHandleItemMapper recPayHandleItemMapper;

    @Autowired
    private RecPayMapper recPayMapper;

    @Autowired
    private RecPayHandleItemService recPayHandleItemService;

    @Autowired
    private ReceiptService receiptService;

    @Autowired
    private RecPayItemService recPayItemService;

    @Autowired
    private RecPayItemMapper recPayItemMapper;

    @Autowired
    private RecPayItemConvert recPayItemConvert;

    @Autowired
    private OtherReceivableConvert otherReceivableConvert;

    @Autowired
    private OtherReceivableItemConvert otherReceivableItemConvert;

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

    /**
     * @desc : 查询明细（货物、收款、附件）
     * @author : 付斌
     * @date : 2024-02-28 13:25
     */
    @Pagination
    public ResponseResultVO<Map<String, Object>> selectOtherReceivableInfoById(String id) {
        Map<String, Object> result = new HashMap<>();
        // 商品明细
        List<OtherReceivableItemResponse> otherReceivableItem = otherReceivableItemMapper.selectByCond(new OtherReceivableItemQuery().setReceivableId(id));
        result.put("otherReceivableItem", otherReceivableItem);

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

    /**
     * @desc : 新建方法
     * @author : 付斌
     * @date : 2023/1/9 10:49
     */
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public ResponseResultVO<?> insert(OtherReceivableVO otherReceivableVO) {
        // 收款金额不能大于收入金额
        if(otherReceivableVO.getSumAmtRec().compareTo(otherReceivableVO.getSumAmtReceivable()) == 1){
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.RECEIVABLE_NO_LESS_RECEIPT.getMessage());
        }

        // 获取单号
        Map<String, Object> codeMap = commonService.getUniqueNoteCode(Constant.docNameConstant.OTHERRECEIVABLE.getName(), false);
        otherReceivableVO.setReceivableId(codeMap.get("outId").toString()).setReceivableNo(codeMap.get("outNote").toString())
                .setObjectType(Constant.ObjectType.CUS.getName());
        // 转化实体
        OtherReceivable otherReceivable = otherReceivableConvert.convertToPo(otherReceivableVO);
        // 总单保存
        super.insert(otherReceivable);

        // 明细保存
        if (otherReceivableVO.getItemList() != null && otherReceivableVO.getItemList().size() > 0) {
            for (OtherReceivableItemVO otherReceivableItemVO : otherReceivableVO.getItemList()) {
                OtherReceivableItem otherReceivableItem = otherReceivableItemConvert.convertToPo(otherReceivableItemVO);
                otherReceivableItem.setReceivableId(otherReceivable.getReceivableId()).setCpId(otherReceivable.getCpId());
                otherReceivableItemMapper.insert(otherReceivableItem);
            }
        }

        // 应收记账
        accountService.accReceivable(otherReceivable.getReceivableId(), Constant.InventoryDocCode.OTHER_RECEIVABLE.getTableName());

        // 如果有收款，再做应收付款
        if (otherReceivableVO.getReceiptList() != null && otherReceivableVO.getReceiptList().size() > 0) {
            /***********************************  收款的处理 begin ************************************/
            RecPay recPay = new RecPay();
            // 获取单号
            codeMap = commonService.getUniqueNoteCode(Constant.docNameConstant.RECPAY.getName(), false);
            recPay.setRpId(codeMap.get("outId").toString()).setRpNo(codeMap.get("outNote").toString())
                    .setRpType(Constant.RpType.SHOU_KUAN.getName()).setObjectId(otherReceivableVO.getObjectId())
                    .setOrgId(otherReceivableVO.getOrgId()).setStaffId(otherReceivableVO.getStaffId())
                    .setSumAmtRec(otherReceivableVO.getSumAmtRec()).setSumAmtReceivableHandle(otherReceivableVO.getSumAmtRec())
                    .setAccDate(otherReceivableVO.getAccDate()).setBiznisType(Constant.InventoryDocCode.OTHER_RECEIVABLE.getTableName())
                    .setBiznisId(otherReceivableVO.getReceivableId()).setBiznisNo(otherReceivableVO.getReceivableNo())
                    .setMakeStaff(otherReceivableVO.getMakeStaff()).setCpId(otherReceivableVO.getCpId());
            // 总单保存
            recPayMapper.insert(recPay);

            for (RecPayItemVO recPayItemVO : otherReceivableVO.getReceiptList()) {
                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(recPay.getObjectId()).setOrgId(recPay.getOrgId()).setStaffId(recPay.getStaffId())
                        .setAccDate(recPay.getAccDate()).setRecStatus(Constant.recStatuse.QUE_DING.getName()).setAmtRec(recPayItem.getAmtRec())
                        .setBiznisType("t_mac_rec_pay_item").setBiznisId(recPayItem.getItemId()).setBiznisNo(recPay.getRpNo())
                        .setMakeStaff(recPay.getMakeStaff()).setCpId(recPay.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(recPay.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(recPay.getObjectId());
            // 更新账款总表上收款的相关字段
            Account accountUpdate = new Account();
            accountUpdate.setReceipt(accountForUpdate.getReceipt().add(recPay.getSumAmtRec()))// 总收款金额
                    .setReceiptResidue(accountForUpdate.getReceiptResidue().add(recPay.getSumAmtRec()))//  可退金额
                    .setObjectId(accountForUpdate.getObjectId());
            accountService.updateByUuid(accountUpdate);
            /***********************************  收款的处理 end ************************************/

            /***********************************  应收收款的处理 begin ************************************/
            OtherReceivable otherReceivableForUpdate = otherReceivableMapper.selectByIdForUpdate(otherReceivableVO.getReceivableId());

            // 应收收款的处理
            RecPayHandleItem recPayHandleItem = new RecPayHandleItem();
            recPayHandleItem.setRpId(recPay.getRpId()).setAccItemId(otherReceivableForUpdate.getAccItemId())
                    .setAmtReceivableHandle(recPay.getSumAmtRec()).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())
                    .setItemId(recPayHandleItem.getAccItemId());
            // 剩余金额 = 应收金额-应收收款金额
            accountItemUpdate.setAmtResidue(accountItemForUpdate.getAmtShould().subtract(accountItemUpdate.getAmtHandle()));
            accountItemService.updateByUuid(accountItemUpdate);

            // 更新总账上
            accountForUpdate = accountMapper.selectByIdForUpdate(recPay.getObjectId());
            accountUpdate = new Account();
            accountUpdate.setReceivableHandle(accountForUpdate.getReceivableHandle().add(recPayHandleItem.getAmtReceivableHandle()))// 总应收收款金额
                    .setReceivableWaive(accountForUpdate.getReceivableWaive())//  总应收优惠金额
                    .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<?> update(OtherReceivableVO otherReceivableVO) {
        OtherReceivable otherReceivableForUpdate = otherReceivableMapper.selectByIdForUpdate(otherReceivableVO.getReceivableId());
        // 并发校验
        if (!otherReceivableForUpdate.getFlgValid()) {
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.ISFLGVALID_FALSE.getMessage());
        }
        // 期初数据不允许编辑
        if (otherReceivableForUpdate.getBusinessType() == 0) {
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.INVOICE_ISQICHU.getMessage());
        }
        // 收款金额不能大于收入金额
        if(otherReceivableVO.getSumAmtRec().compareTo(otherReceivableVO.getSumAmtReceivable()) == 1){
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), ErrorCodeEnum.RECEIVABLE_NO_LESS_RECEIPT.getMessage());
        }

        /***********************************  应收收款的处理 begin ************************************/
        // 如果收款了，先把收款作废掉
        RecPay recPayForUpdate = recPayMapper.selectByBiznisIdForUpdate(otherReceivableVO.getReceivableId(), false);
        if(recPayForUpdate != null && recPayForUpdate.getFlgValid()){
            // 查出并锁定所有应收核销明细
            AccountItem accountItemForUpdate;
            List<RecPayHandleItem> recPayHandleItemForUpdateList = recPayHandleItemMapper.selectByZIdForUpdate(recPayForUpdate.getRpId());
            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(recPayForUpdate.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());
                }
            }
            // 更新总账表的总收款额和可用额
            accountService.updateReceipt(recPayForUpdate.getObjectId());
            // 更新账户余额
            for (String macId : macList) {
                accountService.updateMac(macId);
            }
            // 作废
            RecPay recPayUpdate = new RecPay();
            recPayUpdate.setFlgValid(false).setRpId(recPayForUpdate.getRpId());
            receiptService.updateByUuid(recPayUpdate);
        }
        /***********************************  应收收款的处理 end ************************************/

        // 先更新收款单总表，否则id又更错了
        OtherReceivable otherReceivable = otherReceivableConvert.convertToPo(otherReceivableVO);
        super.update(otherReceivable, new UpdateWrapper<OtherReceivable>().lambda().eq(OtherReceivable::getReceivableId,
                UUID.fromString(otherReceivable.getReceivableId())));

        // 应收反记账
        accountService.reverseReceivable(otherReceivableVO.getReceivableId(), Constant.InventoryDocCode.OTHER_RECEIVABLE.getTableName());

        // 将之前的明细全部删除
        List<OtherReceivableItem> otherReceivableItemOriginalList = otherReceivableItemMapper.selectByZIdForUpdate(otherReceivableVO.getReceivableId());
        for (OtherReceivableItem otherReceivableItem : otherReceivableItemOriginalList) {
            otherReceivableItemMapper.deleteById(otherReceivableItem.getItemId());
        }

        // 明细保存
        if (otherReceivableVO.getItemList() != null && otherReceivableVO.getItemList().size() > 0) {
            for (OtherReceivableItemVO otherReceivableItemVO : otherReceivableVO.getItemList()) {
                OtherReceivableItem otherReceivableItem = otherReceivableItemConvert.convertToPo(otherReceivableItemVO);
                otherReceivableItem.setItemId(null).setReceivableId(otherReceivableVO.getReceivableId()).setCpId(otherReceivableVO.getCpId());
                otherReceivableItemMapper.insert(otherReceivableItem);
            }
        }

        // 应收记账
        accountService.accReceivable(otherReceivableVO.getReceivableId(), Constant.InventoryDocCode.OTHER_RECEIVABLE.getTableName());

        // 如果有收款，再做应收收款
        if (otherReceivableVO.getReceiptList() != null && otherReceivableVO.getReceiptList().size() > 0) {
            /***********************************  收款的处理 begin ************************************/
            RecPay recPay = new RecPay();
            // 获取单号
            Map<String, Object> codeMap = commonService.getUniqueNoteCode(Constant.docNameConstant.RECPAY.getName(), false);
            recPay.setRpId(codeMap.get("outId").toString()).setRpNo(codeMap.get("outNote").toString())
                    .setRpType(Constant.RpType.SHOU_KUAN.getName()).setObjectId(otherReceivableVO.getObjectId())
                    .setOrgId(otherReceivableVO.getOrgId()).setStaffId(otherReceivableVO.getStaffId())
                    .setSumAmtRec(otherReceivableVO.getSumAmtRec()).setSumAmtReceivableHandle(otherReceivableVO.getSumAmtRec())
                    .setAccDate(otherReceivableVO.getAccDate()).setBiznisType(Constant.InventoryDocCode.OTHER_RECEIVABLE.getTableName())
                    .setBiznisId(otherReceivableVO.getReceivableId()).setBiznisNo(otherReceivableVO.getReceivableNo())
                    .setMakeStaff(otherReceivableVO.getMakeStaff()).setCpId(otherReceivableVO.getCpId());

            // 总单保存
            recPayMapper.insert(recPay);

            for (RecPayItemVO recPayItemVO : otherReceivableVO.getReceiptList()) {
                RecPayItem recPayItem = recPayItemConvert.convertToPo(recPayItemVO);
                recPayItem.setItemId(null).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(recPay.getObjectId()).setOrgId(recPay.getOrgId()).setStaffId(recPay.getStaffId())
                        .setAccDate(recPay.getAccDate()).setRecStatus(Constant.recStatuse.QUE_DING.getName()).setAmtRec(recPayItem.getAmtRec())
                        .setBiznisType("t_mac_rec_pay_item").setBiznisId(recPayItem.getItemId()).setBiznisNo(recPay.getRpNo())
                        .setMakeStaff(recPay.getMakeStaff()).setCpId(recPay.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(recPay.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(recPay.getObjectId());
            // 更新账款总表上收款的相关字段
            Account accountUpdate = new Account();
            accountUpdate.setReceipt(accountForUpdate.getReceipt().add(recPay.getSumAmtRec()))// 总收款金额
                    .setReceiptResidue(accountForUpdate.getReceiptResidue().add(recPay.getSumAmtRec()))//  可退金额
                    .setObjectId(accountForUpdate.getObjectId());
            accountService.updateByUuid(accountUpdate);
            /***********************************  收款的处理 end ************************************/

            /***********************************  应收收款的处理 begin ************************************/
            otherReceivableForUpdate = otherReceivableMapper.selectByIdForUpdate(otherReceivableVO.getReceivableId());
            // 应收收款的处理
            RecPayHandleItem recPayHandleItem = new RecPayHandleItem();
            recPayHandleItem.setRpId(recPay.getRpId()).setAccItemId(otherReceivableForUpdate.getAccItemId())
                    .setAmtReceivableHandle(recPay.getSumAmtRec()).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())
                    .setItemId(recPayHandleItem.getAccItemId());
            // 剩余金额 = 应收金额-应收收款金额
            accountItemUpdate.setAmtResidue(accountItemForUpdate.getAmtShould().subtract(accountItemUpdate.getAmtHandle()));
            accountItemService.updateByUuid(accountItemUpdate);

            // 更新总账上
            accountForUpdate = accountMapper.selectByIdForUpdate(recPay.getObjectId());
            accountUpdate = new Account();
            accountUpdate.setReceivableHandle(accountForUpdate.getReceivableHandle().add(recPayHandleItem.getAmtReceivableHandle()))// 总应收收款金额
                    .setReceivableWaive(accountForUpdate.getReceivableWaive())//  总应收优惠金额
                    .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 : 2024-03-02 17:27
     */
    public ResponseResultVO<?> getOtherReceivableForUpdate(String id) {
        Map<String, Object> dataInfo = new HashMap<>();
        OtherReceivableResponse otherReceivableResponse = otherReceivableMapper.selectById(id);

        // 判断是否能大编辑
        otherReceivableResponse.setDaEdit(true);
        if (otherReceivableResponse.getAccItemId() != null) {
            // 查出新建时是否收款了
            RecPay recPayForUpdate = recPayMapper.selectByBiznisIdForUpdate(id, false);
            // 查出有多少次收款
            List<RecPayHandleItemResponse> RecPayHandleItemResponseList = recPayHandleItemMapper.selectByCond(new RecPayHandleItemQuery().setAccItemId(otherReceivableResponse.getAccItemId()));
            if (RecPayHandleItemResponseList != null && RecPayHandleItemResponseList.size() > 0) {
                // 如果有收款，并且新建时没收款，则不能大编辑
                if(recPayForUpdate == null){
                    otherReceivableResponse.setDaEdit(false);
                }else{
                    for(RecPayHandleItemResponse  recPayHandleItemResponse :RecPayHandleItemResponseList){
                        // 如果核销id不是第一次收款id,不能大编辑
                        if(!recPayHandleItemResponse.getRpId().equals(recPayForUpdate.getRpId())){
                            otherReceivableResponse.setDaEdit(false);
                        }
                    }
                }
            }
        }
        dataInfo.put("data", otherReceivableResponse);

        // 收入明细
        List<OtherReceivableItemResponse> otherReceivableItemResponseList = otherReceivableItemMapper.selectByCond(new OtherReceivableItemQuery().setReceivableId(id));
        dataInfo.put("dataItem", otherReceivableItemResponseList);

        // 收款明细
        RecPay recPayForUpdate = recPayMapper.selectByBiznisId(id);
        if (recPayForUpdate != null) {
            List<RecPayItemResponse> recPayItemResponseList = recPayItemMapper.selectByCond(new RecPayItemQuery().setRpId(recPayForUpdate.getRpId()));
            dataInfo.put("receiptItem", recPayItemResponseList);
        } else {
            dataInfo.put("receiptItem", new ArrayList<RecPayResponse>());
        }

        return ResponseResultUtil.success(dataInfo);
    }

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

        /***********************************  应收收款的处理 begin ************************************/
        RecPay recPayForUpdate = recPayMapper.selectByBiznisIdForUpdate(id, false);
        if(recPayForUpdate != null && recPayForUpdate.getFlgValid()){
            // 查出并锁定所有应收核销明细
            AccountItem accountItemForUpdate;
            List<RecPayHandleItem> recPayHandleItemForUpdateList = recPayHandleItemMapper.selectByZIdForUpdate(recPayForUpdate.getRpId());
            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(recPayForUpdate.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());
                }
            }
            // 更新总账表的总收款额和可用额
            accountService.updateReceipt(recPayForUpdate.getObjectId());
            // 更新账户余额
            for (String macId : macList) {
                accountService.updateMac(macId);
            }
            // 作废
            RecPay recPayUpdate = new RecPay();
            recPayUpdate.setFlgValid(false).setRpId(recPayForUpdate.getRpId());
            receiptService.updateByUuid(recPayUpdate);
        }
        /***********************************  应收收款的处理 end ************************************/

        // 应收反记账
        accountService.reverseReceivable(id, "t_mac_other_receivable");

        // 作废
        OtherReceivable otherReceivableUpdate = new OtherReceivable();
        otherReceivableUpdate.setFlgValid(false).setReceivableId(id);
        super.updateByUuid(otherReceivableUpdate);
        return ResponseResultUtil.success();
    }
}
