package cn.superdesk.uniorder.service.accounting.unified.supplier.Impl;

import cn.superdesk.libs.common.json.JsonUtils;
import cn.superdesk.uniorder.common.R;
import cn.superdesk.uniorder.common.enums.order.UnifiedOrderAccountingStateEnum;
import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderAccountingStatusEnum;
import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderSupplierDimCreateByEnum;
import cn.superdesk.uniorder.dao.entity.accounting.unified.supplier.*;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrder;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderExample;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderGoods;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderGoodsExample;
import cn.superdesk.uniorder.dao.mapper.accounting.unified.supplier.*;
import cn.superdesk.uniorder.dao.mapper.base.*;
import cn.superdesk.uniorder.dto.vo.accounting.unified.supplier.AccountingUnifiedSuplierCheckAmountErrorForFix;
import cn.superdesk.uniorder.dto.vo.accounting.unified.supplier.AccountingUnifiedSuplierHead;
import cn.superdesk.uniorder.dto.vo.unified.UnifiedSupplierCreateDimGoodsParamJsonStruct;
import cn.superdesk.uniorder.dto.vo.unified.UnifiedSupplierStatementOfAccountVo;
import cn.superdesk.uniorder.pattern.state.accounting.context.StatementOfAccountContext;
import cn.superdesk.uniorder.service.accounting.unified.supplier.AccountingUnifiedSupplierService;
import cn.superdesk.uniorder.service.base.UnifiedOrderCreditService;
import cn.superdesk.uniorder.service.base.UnifiedOrderGoodsService;
import cn.superdesk.uniorder.service.base.UnifiedOrderService;
import cn.superdesk.uniorder.utils.lamda.LamdaUtils;
import cn.superdesk.uniorder.utils.uniorder.SuperdeskStringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @Description: 供应商结算>对账单
 * @Author: linjinyu 补充与修改
 * @CreateDate: 4/24/20 2:16 PM
 * @UpdateUser: linjinyu
 * @UpdateDate: 4/24/20 2:16 PM
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Slf4j
@Service
public class AccountingUnifiedSupplierServiceImpl implements AccountingUnifiedSupplierService {

    @Autowired
    UnifiedOrderMapper                   unifiedOrderMapper;
    @Autowired
    UnifiedOrderMapperEx                 unifiedOrderMapperEx;
    @Autowired
    UnifiedOrderMapperExSupplierDimOrder unifiedOrderMapperExSupplierDimOrder;
    @Autowired
    UnifiedOrderService                  unifiedOrderService;

    @Autowired
    UnifiedOrderGoodsMapper   unifiedOrderGoodsMapper;
    @Autowired
    UnifiedOrderGoodsMapperEx unifiedOrderGoodsMapperEx;
    @Autowired
    UnifiedOrderGoodsService  unifiedOrderGoodsService;

    @Autowired
    UnifiedOrderCreditMapper  unifiedOrderCreditMapper;
    @Autowired
    UnifiedOrderCreditService unifiedOrderCreditService;

    @Autowired
    AccountingUnifiedSupplierMapper        accountingUnifiedSupplierMapper;
    @Autowired
    AccountingUnifiedSupplierMapperEx      accountingUnifiedSupplierMapperEx;
    @Autowired
    AccountingUnifiedSupplierOrderMapper   accountingUnifiedSupplierOrderMapper;
    @Autowired
    AccountingUnifiedSupplierOrderMapperEx accountingUnifiedSupplierOrderMapperEx;
    @Autowired
    AccountingUnifiedSupplierXGoodsMapper  accountingUnifiedSupplierXGoodsMapper;

    @Override
    public PageInfo<AccountingUnifiedSupplier> findByPaging(Map<String, Object> params, Integer pageNo, Integer pageSize) {

        return null;
    }

    @Override
    public void deleteObj(Long id) {

        accountingUnifiedSupplierMapper.deleteByPrimaryKey(id);
    }

    @Override
    public void updateObj(AccountingUnifiedSupplier statementOfAccount) {

        accountingUnifiedSupplierMapper.updateByPrimaryKeySelective(statementOfAccount);
    }

    @Override
    public AccountingUnifiedSupplier findById(Long id) {

        return accountingUnifiedSupplierMapper.selectByPrimaryKey(id);
    }

    @Override
    public void addObj(AccountingUnifiedSupplier statementOfAccount) {

        accountingUnifiedSupplierMapper.insert(statementOfAccount);
    }

    @Override
    public List<AccountingUnifiedSupplier> findAll(Map<String, Object> queryMap) {

        return null;
    }

    @Override
    public R<List<UnifiedSupplierStatementOfAccountVo>> getStatementOfAccountList(Map<String, Object> params, int pageNo,
                                                                                  int pageSize) {

        PageHelper.startPage(pageNo, pageSize);


        //
        List<UnifiedSupplierStatementOfAccountVo> ls = accountingUnifiedSupplierMapperEx.getStatementOfAccountList(params);

        PageInfo<UnifiedSupplierStatementOfAccountVo> page = new PageInfo<UnifiedSupplierStatementOfAccountVo>(ls);
        PageHelper.clearPage();
        return new R<List<UnifiedSupplierStatementOfAccountVo>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), ls);
    }

    @Override
    public AccountingUnifiedSuplierHead getStatementOfAccountHeadSum(Map<String, Object> params) {

        return accountingUnifiedSupplierMapperEx.getStatementOfAccountHeadSum(params);
    }

    /**
     * 平台工作人员 - 为供应商 - 创建对帐单()
     *
     * @param statementOfAccount
     * @param ids
     * @return
     */
    @Transactional
    @Override
    public AccountingUnifiedSupplier opCreateAccountingDimOrder(AccountingUnifiedSupplier statementOfAccount, /* uo.id */String ids) {

        statementOfAccount.setDimCreateBy(AccountingOrderSupplierDimCreateByEnum.订单.getKey());

        // 对账单 信息在上一步已经好了
        accountingUnifiedSupplierMapper.insert(statementOfAccount);

        List<Long>        sysUnifiedOrderIds           = SuperdeskStringUtils.stringArrayConvertToLongList(ids, ",");
        Map<String, Long> mapOrderSn2SysUnifiedOrderId = unifiedOrderService.convertSysUnifiedOrderIds2MapOrderSn2SysUnifiedOrderId(sysUnifiedOrderIds);
        List<String>      processOrderSn               = unifiedOrderService.convertSysUnifiedOrderIds2OrderSn(sysUnifiedOrderIds);


        Map<String, Object> params = new HashMap<>();
        params.put("accountingOrderSn", statementOfAccount.getAccountingOrderSn());
        params.put("ids", sysUnifiedOrderIds); // 这个是 uo.id ids.split(",")
        // 对账单 X 订单
        accountingUnifiedSupplierOrderMapperEx.createRelation(params);

        // 对账单 X [订单] X 商品 mark by linjinyu 20201029 由于时间赶 先这样弄 一条条没效率
        List<UnifiedOrderGoods> processUnifiedOrderGoodsList = unifiedOrderGoodsService.findByOrderSns(processOrderSn);
        for (UnifiedOrderGoods processUnifiedOrderGoods : processUnifiedOrderGoodsList) {

            AccountingUnifiedSupplierXGoods xGoods = new AccountingUnifiedSupplierXGoods();

            xGoods.setAccountingOrderId(statementOfAccount.getId());
            xGoods.setAccountingOrderSn(statementOfAccount.getAccountingOrderSn());

            xGoods.setUnifiedOrderId(mapOrderSn2SysUnifiedOrderId.get(processUnifiedOrderGoods.getOrderSn()));
            xGoods.setOrderSn(processUnifiedOrderGoods.getOrderSn());

            xGoods.setUnifiedOrderGoodsId(processUnifiedOrderGoods.getId());

            xGoods.setCreateUserId(1L);
            xGoods.setCreateTime(new Date());
            xGoods.setUpdateUserId(1L);
            xGoods.setCreateTime(new Date());

            accountingUnifiedSupplierXGoodsMapper.insert(xGoods);

        }


        // 更新 订单 供应商对账状态
        unifiedOrderService.updateAccountingStateSupplierBySysUnifiedOrderIds(sysUnifiedOrderIds, UnifiedOrderAccountingStateEnum.已对账);


        // 更新 商品 供应商对账状态
        unifiedOrderGoodsService.updateAccountingStateSupplierByOrderSn(processOrderSn, UnifiedOrderAccountingStateEnum.已对账);


        // 更新 流水 供应商对账状态 20200925 供应商结算 创建对账单 如果 积分流水 有的话 关联 更新状态 为 已对账状态
        unifiedOrderCreditService.updateAccountingStateSupplierByOrderSn(processOrderSn, UnifiedOrderAccountingStateEnum.已对账);


        return statementOfAccount;
    }

    @Transactional
    @Override
    public AccountingUnifiedSupplier opCreateAccountingDimGoods(AccountingUnifiedSupplier statementOfAccount, List<UnifiedSupplierCreateDimGoodsParamJsonStruct> requestParams) {

        statementOfAccount.setDimCreateBy(AccountingOrderSupplierDimCreateByEnum.商品.getKey());

        // 对账单 信息在上一步已经好了
        accountingUnifiedSupplierMapper.insert(statementOfAccount);

        /****************************************** 差异部分 Dim Goods start ******************************************/


        List<Long> sysUnifiedOrderIds      = requestParams.stream().filter(LamdaUtils.distinctByKey(o -> o.getUnifiedOrderId())).map(UnifiedSupplierCreateDimGoodsParamJsonStruct::getUnifiedOrderId).collect(Collectors.toList());
        List<Long> sysUnifiedOrderGoodsIds = requestParams.stream().filter(LamdaUtils.distinctByKey(o -> o.getUnifiedOrderGoodsId())).map(UnifiedSupplierCreateDimGoodsParamJsonStruct::getUnifiedOrderGoodsId).collect(Collectors.toList());
        List<Long> processOutGoodsIds      = requestParams.stream().filter(LamdaUtils.distinctByKey(o -> o.getGoodsId())).map(UnifiedSupplierCreateDimGoodsParamJsonStruct::getGoodsId).collect(Collectors.toList());

        List<String> processOrderSn = unifiedOrderService.convertSysUnifiedOrderIds2OrderSn(sysUnifiedOrderIds);

        Map<Long, String> mapSysUnifiedOrderId2OrderSn = unifiedOrderService.convertSysUnifiedOrderIds2MapSysUnifiedOrderId2OrderSn(sysUnifiedOrderIds);

        Map<String, Object> params = new HashMap<>();
        params.put("accountingOrderSn", statementOfAccount.getAccountingOrderSn());
        params.put("ids", sysUnifiedOrderIds); // 这个是 uo.id

        // 对账单 X 订单  TODO 如果开放了 商品维度对账，这个大概是错的 但这样插入是对的 程序是对的 ， 但再回到订单维度，逻辑可能是错的
        accountingUnifiedSupplierOrderMapperEx.createRelation(params);

        // 对账单 X [订单] X 商品
        for (UnifiedSupplierCreateDimGoodsParamJsonStruct structItem : requestParams) {

            AccountingUnifiedSupplierXGoods xGoods = new AccountingUnifiedSupplierXGoods();

            xGoods.setAccountingOrderId(statementOfAccount.getId());
            xGoods.setAccountingOrderSn(statementOfAccount.getAccountingOrderSn());

            xGoods.setUnifiedOrderId(structItem.getUnifiedOrderId());
            xGoods.setOrderSn(mapSysUnifiedOrderId2OrderSn.get(structItem.getUnifiedOrderId()));

            xGoods.setUnifiedOrderGoodsId(structItem.getUnifiedOrderGoodsId());

            xGoods.setCreateUserId(1L);
            xGoods.setCreateTime(new Date());
            xGoods.setUpdateUserId(1L);
            xGoods.setCreateTime(new Date());

            accountingUnifiedSupplierXGoodsMapper.insert(xGoods);

        }


        // TODO 更新 订单 供应商对账状态 这个是错的，商品维度可能有部分对账的情况
        unifiedOrderService.updateAccountingStateSupplierBySysUnifiedOrderIds(sysUnifiedOrderIds, UnifiedOrderAccountingStateEnum.已对账);


        // 更新 商品 供应商对账状态
        unifiedOrderGoodsService.updateAccountingStateSupplierByOrderSnAndOutGoodsIds(processOrderSn, processOutGoodsIds, UnifiedOrderAccountingStateEnum.已对账);


        // 更新 流水 供应商对账状态 20200925 供应商结算 创建对账单 如果 积分 流水 有的话 关联 更新状态 为 已对账状态
        unifiedOrderCreditService.updateAccountingStateSupplierByOrderSnAndOutGoodsIds(processOrderSn, processOutGoodsIds, UnifiedOrderAccountingStateEnum.已对账);


        /****************************************** 差异部分 Dim Goods   end ******************************************/

        return statementOfAccount;
    }

    /**
     * 这个是用于 编辑 对账单 一条一条
     *
     * @param statementOfAccount
     * @param order
     * @param add
     * @param userId
     */
    @Transactional
    @Override
    public void opEditAccounting(
            AccountingUnifiedSupplier statementOfAccount,
            UnifiedOrder order,
            /* 方向 1 新增 非1 删除 加入 orderSn 对映的商品 */ String add,
            Long userId) {

        if (add.equals("1")) {

            // 恢复 订单为 已对账订单
            UnifiedOrder unifiedOrder = new UnifiedOrder();
            unifiedOrder.setId(order.getId());
            unifiedOrder.setAccountingStateSupplier(UnifiedOrderAccountingStateEnum.已对账.getKey());
            unifiedOrder.setUpdateTime(new Date());
            unifiedOrder.setUpdateUserId(userId);
            unifiedOrderMapper.updateByPrimaryKeySelective(unifiedOrder);

            // 添加 对账单 X 订单关系
            AccountingUnifiedSupplierOrder accountingUnifiedSupplierOrder = new AccountingUnifiedSupplierOrder();
            accountingUnifiedSupplierOrder.setAmount(order.getAmount());
            accountingUnifiedSupplierOrder.setCostAmount(order.getCostAmount());
            accountingUnifiedSupplierOrder.setOrderSn(order.getOrderSn());
            accountingUnifiedSupplierOrder.setAccountingOrderSn(statementOfAccount.getAccountingOrderSn());

            accountingUnifiedSupplierOrderMapper.insert(accountingUnifiedSupplierOrder);

            // TODO 是不需要更新对账单的订单数与金额

        } else {

            // 恢复 订单为 未对账订单
            UnifiedOrder unifiedOrder = new UnifiedOrder();
            unifiedOrder.setId(order.getId());
            unifiedOrder.setAccountingStateSupplier(UnifiedOrderAccountingStateEnum.未对账.getKey());
            unifiedOrder.setUpdateTime(new Date());
            unifiedOrder.setUpdateUserId(userId);
            unifiedOrderMapper.updateByPrimaryKeySelective(unifiedOrder);

            // 删除 对账单 X 订单关系
            AccountingUnifiedSupplierOrderExample deleteByExample = new AccountingUnifiedSupplierOrderExample();
            deleteByExample.createCriteria()
                    .andOrderSnEqualTo(order.getOrderSn())
                    .andAccountingOrderSnEqualTo(statementOfAccount.getAccountingOrderSn());
            accountingUnifiedSupplierOrderMapper.deleteByExample(deleteByExample);

            // TODO 是不需要更新对账单的订单数与金额
        }

    }

    @Transactional
    @Override
    public void opRejectAccounting(AccountingUnifiedSupplier statementOfAccount) {

    }

    @Transactional
    @Override
    public void opAgainAccounting(AccountingUnifiedSupplier statementOfAccount) {

    }

    @Transactional
    @Override
    public void opCancelAccounting(AccountingUnifiedSupplier statementOfAccount) {

    }

    /**
     * 拒绝接受;不予考虑
     * <p>
     * 重新对账 取消对账 申诉对账 等 操作指向
     * <p>
     * 取消操作 -> 对账单状态 -> 已取消(-1, "已取消"), void opCancel(AccountingUnifiedSupplier statementOfAccount);
     * 重新对账 -> 对账单状态 -> 已取消(-1, "已取消"), void opAgain(AccountingUnifiedSupplier statementOfAccount);
     *
     * @param statementOfAccount
     */
    @Transactional
    @Override
    private void opRejectFaceInner(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {

        log.info("##################### cn/superdesk/uniorder/service/unified/impl/UnifiedSupplierDzServiceImpl.java start #####################");
        log.info("params UnifiedSupplierDz:\n" + JsonUtils.toPrettyJson(statementOfAccount));

        // 重新对帐嘛 这边先是更新一下这个 供应商对帐单 状态 状态是什么呢? 这个是要查一下
//        accountingUnifiedSupplierMapper.updateByPrimaryKeySelective(statementOfAccount);


        /****************************************** 更新 供应商 对账单 状态 start ******************************************/
        AccountingUnifiedSupplier forUpdate = new AccountingUnifiedSupplier();
        forUpdate.setId(statementOfAccount.getId());
        forUpdate.setAccountingStatus(AccountingOrderAccountingStatusEnum.已取消.getKey());
        forUpdate.setUpdateTime(new Date());
        forUpdate.setUpdateUserId(opUserId);

        updateObj(forUpdate);
        /****************************************** 更新 供应商 对账单 状态   end ******************************************/

        // 拿 供应商对帐单 sn 来查出 这个对帐单 的订单
        Map<String, Object> params = new HashMap<>();
        params.put("accountingOrderSn", statementOfAccount.getAccountingOrderSn());

        // 此为一个中间表吧 反正不是原始的订单
        // 只有四个字段
        // 1. 供应商对帐单SN
        // 2. 原始订单SN(来源各业务系统)
        // 3. 销售价?(整个订单?包含运费什么的吗?)
        // 4. 成品价?
        List<AccountingUnifiedSupplierOrder> statementOfAccountXOrders = accountingUnifiedSupplierOrderMapperEx.findAll(params);


        // TODO 一个个更新有点慢 by linjinyu 20200923
//		for (AccountingUnifiedSupplierOrder item : orders) {
//
//			UnifiedOrder unifiedOrder = unifiedOrderMapperEx.selectByPrimaryOrderSn(item.getOrderSn());
//			if (unifiedOrder == null) break;
//			unifiedOrder.setAccountingStateSupplier(UnifiedOrderAccountingState.未对账.getKey());
//			unifiedOrderMapper.updateByPrimaryKey(unifiedOrder);
//		}

        /****************************************** 重构 上边的逻辑 20200925 start ******************************************/
        List<String> processOrderSn = statementOfAccountXOrders.stream()
                .filter(LamdaUtils.distinctByKey(o -> o.getOrderSn()))
                .map(AccountingUnifiedSupplierOrder::getOrderSn)
                .collect(Collectors.toList());

        UnifiedOrderExample forUpdateAccountingStateOrderExample = new UnifiedOrderExample();
        forUpdateAccountingStateOrderExample.createCriteria()
                .andOrderSnIn(processOrderSn);
        UnifiedOrder forUpdateAccountingStateOrderEntity = new UnifiedOrder();
        forUpdateAccountingStateOrderEntity.setAccountingStateSupplier(UnifiedOrderAccountingStateEnum.未对账.getKey());
        unifiedOrderMapper.updateByExampleSelective(forUpdateAccountingStateOrderEntity, forUpdateAccountingStateOrderExample);

        // TODO 20200925 供应商结算 对账单 重新对账 如果 积分 流水 有的话 关联 更新状态 为 未对账状态
        // TODO 还是先查一下会好一点 有再去做状态更新的
//		UnifiedOrderCreditExample forUpdateAccountingStateCreditExample = new UnifiedOrderCreditExample();
//		forUpdateAccountingStateCreditExample.createCriteria()
//				.andOrderSnIn(processOrderSn);
//		UnifiedOrderCredit forUpdateAccountingStateCreditEntity = new UnifiedOrderCredit();
//		forUpdateAccountingStateCreditEntity.setAccountingStateSupplier(UnifiedOrderAccountingState.未对账.getKey());
//		unifiedOrderCreditMapper.updateByExampleSelective(forUpdateAccountingStateCreditEntity, forUpdateAccountingStateCreditExample);

        unifiedOrderCreditService.updateAccountingStateSupplierByOrderSn(processOrderSn, UnifiedOrderAccountingStateEnum.未对账);
        /****************************************** 重构 上边的逻辑 20200925   end ******************************************/

        log.info("##################### cn/superdesk/uniorder/service/unified/impl/UnifiedSupplierDzServiceImpl.java end   #####################");
    }


    /****************************************** 状态机 公共方法 重用 start ******************************************/

    @Transactional
    @Override
    public void opCancelByStateMachine(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {

        opRejectFaceInner(statementOfAccount, opUserId);
    }

    @Transactional
    @Override
    public void opAgainByStateMachine(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {

        opRejectFaceInner(statementOfAccount, opUserId);
    }

    @Transactional
    @Override
    public void opSubmitByStateMachine(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {

        AccountingUnifiedSupplier forUpdate = new AccountingUnifiedSupplier();
        forUpdate.setId(statementOfAccount.getId());
        forUpdate.setAccountingStatus(AccountingOrderAccountingStatusEnum.未确认.getKey());
        forUpdate.setUpdateTime(new Date());
        forUpdate.setUpdateUserId(opUserId);

        updateObj(forUpdate);
    }

    @Transactional
    @Override
    public void opConfirmByStateMachine(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {

        AccountingUnifiedSupplier forUpdate = new AccountingUnifiedSupplier();
        forUpdate.setId(statementOfAccount.getId());
        forUpdate.setAccountingStatus(AccountingOrderAccountingStatusEnum.已确认.getKey());
        forUpdate.setUpdateTime(new Date());
        forUpdate.setUpdateUserId(opUserId);

        updateObj(forUpdate);
    }

    @Transactional
    @Override
    public void opAppealByStateMachine(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {

        AccountingUnifiedSupplier forUpdate = new AccountingUnifiedSupplier();
        forUpdate.setId(statementOfAccount.getId());
        forUpdate.setAccountingStatus(AccountingOrderAccountingStatusEnum.已拒绝.getKey());
        forUpdate.setUpdateTime(new Date());
        forUpdate.setUpdateUserId(opUserId);

        updateObj(forUpdate);
    }
    /****************************************** 状态机 公共方法 重用   end ******************************************/


    /****************************************** 状态机 start ******************************************/
    // 创建操作 -> 对账单状态 -> 待提交(3, "待提交"),
    public void opCreate(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {


    }

    // 提交操作 -> 对账单状态 -> 未确认(0, "未确认"),// 已提交
    public void opSubmit(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {
        StatementOfAccountContext context = new StatementOfAccountContext(statementOfAccount, opUserId);
        context.opSubmit();
    }

    // 取消操作 -> 对账单状态 -> 已取消(-1, "已取消"),
    public void opCancel(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {
        StatementOfAccountContext context = new StatementOfAccountContext(statementOfAccount, opUserId);
        context.opCancel();
    }

    // 重新对账操作 -> 对账单状态 -> 已取消(-1, "已取消"),
    public void opAgain(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {
        StatementOfAccountContext context = new StatementOfAccountContext(statementOfAccount, opUserId);
        context.opAgain();
    }

    // 确认操作 -> 对账单状态 -> 已确认(1, "已确认"),
    public void opConfirm(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {
        StatementOfAccountContext context = new StatementOfAccountContext(statementOfAccount, opUserId);
        context.opConfirm();
    }

    // 申诉操作 -> 对账单状态 -> 已拒绝(2, "已拒绝"),
    public void opAppeal(AccountingUnifiedSupplier statementOfAccount, Long opUserId) {
        StatementOfAccountContext context = new StatementOfAccountContext(statementOfAccount, opUserId);
        context.opAppeal();
    }

    /****************************************** 状态机   end ******************************************/


    public List<AccountingUnifiedSuplierCheckAmountErrorForFix> checkAmountErrorForFix(Map<String, Object> params) {
        return accountingUnifiedSupplierOrderMapperEx.checkAmountErrorForFix(params);
    }

    /**
     * 补丁程序
     * 侨城汇
     */
    public void patchDimOrder2Goods() {

        // TODO 先找出 全部 对账单(有效) X orders

        AccountingUnifiedSupplierExample example00 = new AccountingUnifiedSupplierExample();
        example00.createCriteria()
                .andAccountingStatusNotEqualTo(AccountingOrderAccountingStatusEnum.已取消.getKey());
        List<AccountingUnifiedSupplier> accountingUnifiedSupplierList = accountingUnifiedSupplierMapper.selectByExample(example00);


        for (AccountingUnifiedSupplier item00 : accountingUnifiedSupplierList) {

            AccountingUnifiedSupplierOrderExample example1 = new AccountingUnifiedSupplierOrderExample();
            example1.createCriteria()
                    .andAccountingOrderSnEqualTo(item00.getAccountingOrderSn());
            List<AccountingUnifiedSupplierOrder> accountingUnifiedSupplierOrderList = accountingUnifiedSupplierOrderMapper.selectByExample(example1);

            for (AccountingUnifiedSupplierOrder item01 : accountingUnifiedSupplierOrderList) {

                UnifiedOrderGoodsExample example2 = new UnifiedOrderGoodsExample();
                example2.createCriteria()
                        .andOrderSnEqualTo(item01.getOrderSn());
                List<UnifiedOrderGoods> unifiedOrderGoodsList = unifiedOrderGoodsMapper.selectByExample(example2);


                UnifiedOrderExample example3 = new UnifiedOrderExample();
                example3.createCriteria()
                        .andOrderSnEqualTo(item01.getOrderSn());
                List<UnifiedOrder> unifiedOrderList = unifiedOrderMapper.selectByExample(example3);
                UnifiedOrder       item03           = unifiedOrderList.get(0);


                for (UnifiedOrderGoods item02 : unifiedOrderGoodsList) {

                    AccountingUnifiedSupplierXGoods xGoods = new AccountingUnifiedSupplierXGoods();

                    xGoods.setAccountingOrderId(item00.getId());
                    xGoods.setAccountingOrderSn(item00.getAccountingOrderSn());

                    xGoods.setUnifiedOrderId(item03.getId());
                    xGoods.setOrderSn(item01.getOrderSn());

                    xGoods.setUnifiedOrderGoodsId(item02.getId());

                    xGoods.setCreateUserId(1L);
                    xGoods.setCreateTime(new Date());
                    xGoods.setUpdateUserId(1L);
                    xGoods.setCreateTime(new Date());

                    accountingUnifiedSupplierXGoodsMapper.insert(xGoods);

                }

                UnifiedOrderGoods goods = new UnifiedOrderGoods();
                goods.setAccountingStateSupplier(UnifiedOrderAccountingStateEnum.已对账.getKey());
                unifiedOrderGoodsMapper.updateByExampleSelective(goods, example2);
            }

        }


        // 再按 orders 去更新 goods?


    }

}
