package cn.superdesk.uniorder.service.invoice.common.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.superdesk.uniorder.common.enums.common.CommonEnabledEnum;
import cn.superdesk.uniorder.common.enums.common.CommonIsDefaultEnum;
import cn.superdesk.uniorder.common.enums.invoice.common.InvoiceTypeMoudelEnum;
import cn.superdesk.uniorder.common.enums.invoice.common.InvoiceTypeMoudelXModeEnum;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.common.lamda.AnLamdaUtils;
import cn.superdesk.uniorder.common.mq.redis.constants.RedisKeyPrefix;
import cn.superdesk.uniorder.common.mq.redis.service.RedisService;
import cn.superdesk.uniorder.common.numerical.AnBeanUtils;
import cn.superdesk.uniorder.common.numerical.AnCollectionUtils;
import cn.superdesk.uniorder.common.numerical.AnStringUtils;
import cn.superdesk.uniorder.common.rest.response.R;
import cn.superdesk.uniorder.common.security.dto.LoginSysUser;
import cn.superdesk.uniorder.dao.entity.invoice.common.InvoiceType;
import cn.superdesk.uniorder.dao.entity.invoice.common.InvoiceTypeExample;
import cn.superdesk.uniorder.dao.entity.sys.SysUser;
import cn.superdesk.uniorder.dao.mapper.invoice.common.InvoiceTypeMapper;
import cn.superdesk.uniorder.dao.mapper.invoice.common.InvoiceTypeMapperEx;
import cn.superdesk.uniorder.dto.param.invoice.common.*;
import cn.superdesk.uniorder.dto.vo.invoice.common.InvoiceTypeOpInvoiceSettingLoadingVo;
import cn.superdesk.uniorder.dto.vo.invoice.common.InvoiceTypePageQueryVo;
import cn.superdesk.uniorder.dto.vo.invoice.common.InvoiceTypeSelectVo;
import cn.superdesk.uniorder.service.invoice.common.InvoiceTypeModeConfigOffLineService;
import cn.superdesk.uniorder.service.invoice.common.InvoiceTypeModeConfigSzhtxxElectronicInvoiceService;
import cn.superdesk.uniorder.service.invoice.common.InvoiceTypeModeConfigSzhtxxPaperInvoiceService;
import cn.superdesk.uniorder.service.invoice.common.InvoiceTypeService;
import cn.superdesk.uniorder.service.sys.SysUserService;
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 java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;


/**
 * @Description: 重构
 * @Author: linjinyu
 * @CreateDate: 2021/7/23 下午4:03
 * @UpdateUser: linjinyu
 * @UpdateDate: 2021/7/23 下午4:03
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Slf4j
@Service
public class InvoiceTypeServiceImpl implements InvoiceTypeService {

    @Autowired
    private InvoiceTypeMapper   invoiceTypeMapper;
    @Autowired
    private InvoiceTypeMapperEx invoiceTypeMapperEx;

    /****************************************** 开票方式 start ******************************************/

    @Autowired
    private InvoiceTypeModeConfigOffLineService                 invoiceTypeModeConfigOffLineService;
    @Autowired
    private InvoiceTypeModeConfigSzhtxxElectronicInvoiceService invoiceTypeModeConfigSzhtxxElectronicInvoiceService;
    @Autowired
    private InvoiceTypeModeConfigSzhtxxPaperInvoiceService      invoiceTypeModeConfigSzhtxxPaperInvoiceService;

    /****************************************** 开票方式   end ******************************************/


    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private RedisService redisService;


    /****************************************** extends BaseService 部分 start ******************************************/

    @Override
    public int insertSelective(InvoiceType entity) {
        return invoiceTypeMapper.insertSelective(entity);
    }

    @Override
    public int updateByPrimaryKeySelective(InvoiceType entity) {
        return invoiceTypeMapper.updateByPrimaryKeySelective(entity);
    }

    @Override
    public void deleteObj(Long id) {
        invoiceTypeMapper.deleteByPrimaryKey(id);
    }

    @Override
    public InvoiceType findById(Long id) {
        return invoiceTypeMapper.selectByPrimaryKey(id);
    }

    @Override
    public PageInfo<InvoiceType> findByPaging(Map<String, Object> conditions, Integer pageNun, Integer pageSize) {
        return null;
    }

    @Override
    public List<InvoiceType> findAll(Map<String, Object> queryMap) {
        return invoiceTypeMapperEx.findAll(queryMap);
    }

    /****************************************** extends BaseService 部分   end ******************************************/


    public void addInvoiceType(InvoiceType entity) {
        invoiceTypeMapper.insertSelective(entity);
    }

    public void updateInvoiceType(InvoiceType entity) {
        InvoiceType originEntity = invoiceTypeMapper.selectByPrimaryKey(entity.getId());
//		AssertUtil.notNull(originEntity);
        AnBeanUtils.copy(entity, originEntity);
        invoiceTypeMapper.updateByPrimaryKey(originEntity);
    }

    public void deleteInvoiceType(Long id) {
        invoiceTypeMapper.deleteByPrimaryKey(id);
    }

    public InvoiceType findInvoiceTypeById(Long id) {
        InvoiceType entity = invoiceTypeMapper.selectByPrimaryKey(id);
//		AssertUtil.notNull(entity);
        return entity;
    }

    @Override
    public R<List<InvoiceType>> pageQuery(InvoiceTypeQueryCriteria queryCriteria, LoginSysUser loginSysUser) {

        PageHelper.startPage(queryCriteria.getPageNumber(), queryCriteria.getPageSize());
        List<InvoiceType>     resultList = invoiceTypeMapperEx.selectQuery(queryCriteria.loading());
        PageInfo<InvoiceType> page       = new PageInfo<InvoiceType>(resultList);
        PageHelper.clearPage();

        return new R<List<InvoiceType>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), resultList);

    }

    @Override
    public List<InvoiceTypeSelectVo> selectQuery(InvoiceTypeQueryCriteria queryCriteria, LoginSysUser loginSysUser) {

        List<InvoiceType> resultList = invoiceTypeMapperEx.selectQuery(queryCriteria.loading());

        List<InvoiceTypeSelectVo> response = new ArrayList<>();

        // 发票种类 X 模块
        resultList.forEach(_entityInvoiceTypeItem -> {

//			客户结算(customerGoods)
//			积分结算(customerCredit)
//			供应商结算(supplierGoods)

            // 是从这里保证有的
            if (StrUtil.isBlank(_entityInvoiceTypeItem.getMoudelXModeIsDefaultStruct())) {
                _entityInvoiceTypeItem.setMoudelXModeIsDefaultStruct(JSONUtil.toJsonStr(initModeFieldIsDefaultStruct()));
            }

            InvoiceTypeMoudelXModeIsDefaultStructModule moudelXModeStructModule = JSONUtil.toBean(_entityInvoiceTypeItem.getMoudelXModeIsDefaultStruct(), InvoiceTypeMoudelXModeIsDefaultStructModule.class);

            List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> modes = new ArrayList<>();

            // 发票种类 -> 模块 -> 方式
            EnumSet.allOf(InvoiceTypeMoudelXModeEnum.class).forEach(_enumModeItem -> {

                String _module    = StrUtil.upperFirst(queryCriteria.getSelectByModule());
                String _modeField = StrUtil.upperFirst(_enumModeItem.getKey());

                String getModuleXModeEnableMethodName = StrUtil.format("get{}Mode{}Enable", _module, _modeField);
                String getModuleMethodName            = StrUtil.format("get{}", _module);

                // 标志001 这里是 发票种类上的开票方式的开关
                Integer checkModuleXModeEnable = ReflectUtil.invoke(_entityInvoiceTypeItem, getModuleXModeEnableMethodName);
                // 标志002 这里是 开票方式结构体
                List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> moudelXModeStructModuleMode = ReflectUtil.invoke(moudelXModeStructModule, getModuleMethodName);

//                log.info("{}-{}-{}", _entityInvoiceTypeItem.getTypeName(), getModuleXModeEnableMethodName, CommonEnabledEnum.get(checkModuleXModeEnable).getDesc());

                if ((ObjectUtil.isNotNull(queryCriteria.getBreakthroughEnabled())
                        && queryCriteria.getBreakthroughEnabled().compareTo(CommonEnabledEnum.启用.getKey()) == 0)
                        ||
                        // 标志001 这里是 开票方式的开关
                        (ObjectUtil.isNotNull(checkModuleXModeEnable)
                                && checkModuleXModeEnable.compareTo(CommonEnabledEnum.启用.getKey()) == 0)) {


                    // 这里是 某个发票种类 下 全部模块 的开票方式 里边有 默认与规则开关
                    // 然而这个是看传入模块过滤出传入模块的
                    List<Predicate<InvoiceTypeMoudelXModeIsDefaultStructModuleMode>> predicatesModuleXModeCModeEq = new ArrayList<>();
                    predicatesModuleXModeCModeEq.add(
                            r -> r.getModeCode() != null
                                    && r.getModeCode().equals(_enumModeItem.getKey()));


                    /**************************************** 这里插入逻辑 过滤 开票方式的开票规则是否启用的问题 start ****************************************/


                    // 是否启用:0-禁用;1-启用
                    Integer _enabled = null;
                    // 是否强行突破是否启用限制:0-不;1-强行突破
                    Integer _breakthroughEnabled;

                    // 默认的情况下 只返回 启用的
                    if (ObjectUtil.isNull(queryCriteria.getBreakthroughEnabled()) || ObjectUtil.isNull(queryCriteria.getEnabled())) {
                        _enabled = CommonEnabledEnum.启用.getKey();
                    }

                    if (ObjectUtil.isNotNull(queryCriteria.getBreakthroughEnabled())) {

                        // 强行突破启用限制的情况
                        if (queryCriteria.getBreakthroughEnabled().compareTo(CommonEnabledEnum.启用.getKey()) == 0) {
                            _enabled = null;
                        }
                    }

                    if (ObjectUtil.isNotNull(_enabled)) {
                        predicatesModuleXModeCModeEq.add(
                                r -> r.getEnabled() != null
                                        && r.getEnabled().compareTo(CommonEnabledEnum.启用.getKey()) == 0);
                    }


                    /**************************************** 这里插入逻辑 过滤 开票方式的开票规则是否启用的问题   end ****************************************/

                    List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> predicatesModuleXModeCModeEqFilter = AnLamdaUtils.filters(moudelXModeStructModuleMode, predicatesModuleXModeCModeEq);


                    // 修名 开票方式的名字 深圳航天信息电子发票 要求改名字 这个鬼 修一下 产品要求要这个名字 反正按产品的来
                    if (CollUtil.isNotEmpty(predicatesModuleXModeCModeEqFilter)) {
                        predicatesModuleXModeCModeEqFilter.forEach(ghost -> {
                            ghost.setModeName(InvoiceTypeMoudelXModeEnum.get(ghost.getModeCode()).getDesc());
                        });
                    }

                    modes.addAll(predicatesModuleXModeCModeEqFilter);
                }
            });

//			customerGoodsIsDefault
            String getModuleIsDefaultMethodName = StrUtil.format("get{}IsDefault", StrUtil.upperFirst(queryCriteria.getSelectByModule()));


            Integer isDefault = ReflectUtil.invoke(_entityInvoiceTypeItem, getModuleIsDefaultMethodName);

            response.add(InvoiceTypeSelectVo.builder()
                    .invoiceTypeId(_entityInvoiceTypeItem.getId())
                    .invoiceTypeName(_entityInvoiceTypeItem.getTypeName())
                    .isDefault(isDefault)
                    .modes(modes)
                    .build());
        });


        return response;

    }

    @Override
    public R<List<InvoiceTypePageQueryVo>> pageQuerySugarUp(InvoiceTypeQueryCriteria queryCriteria, LoginSysUser loginSysUser) {

        R<List<InvoiceType>> originalR = pageQuery(queryCriteria, loginSysUser);

        return new R<List<InvoiceTypePageQueryVo>>(originalR.getCurrentPage(), originalR.getPageSize(), (int) originalR.getCount(), additionalInfoAndConvert(originalR.getData()));
    }

    // 附加信息 Vo
    public List<InvoiceTypePageQueryVo> additionalInfoAndConvert(List<InvoiceType> processList) {

        List<InvoiceTypePageQueryVo> resultList = new ArrayList<>();

        if (CollUtil.isEmpty(processList)) {
            return resultList;
        }

        List<Long> sysUserIds = new ArrayList<>();

        List<Long> createUserIds = processList.stream().filter(o -> o.getCreateUserId() != null).filter(AnLamdaUtils.distinctByKey(o -> o.getCreateUserId())).map(o -> o.getCreateUserId()).collect(Collectors.toList());
        List<Long> updateUserIds = processList.stream().filter(o -> o.getUpdateUserId() != null).filter(AnLamdaUtils.distinctByKey(o -> o.getUpdateUserId())).map(o -> o.getUpdateUserId()).collect(Collectors.toList());

        sysUserIds.addAll(createUserIds);
        sysUserIds.addAll(updateUserIds);

        sysUserIds = sysUserIds.stream().distinct().collect(Collectors.toList());

//        log.info("\n{}", JSONUtil.toJsonStr(sysUserIds));

        Map<Long, SysUser> sysUserMap = sysUserService.convertSysUserIds2MapSysUserId2Entity(sysUserIds);

        for (InvoiceType entity : processList) {

            InvoiceTypePageQueryVo vo = AnBeanUtils.copy(entity, InvoiceTypePageQueryVo.class);

//			vo.setAccountingStatusName(AccountingOrderCustomerAccountingStatusEnum.getDesc(vo.getAccountingStatus()));
//			vo.setInvoiceStatusName(AccountingOrderInvoiceApplyStatusEnum.getDesc(vo.getInvoiceStatus()));
//			vo.setSendEmailStatusName(AccountingOrderIsSendEmailEnum.getDesc(vo.getIsSendEmail()));

            // 再补个

            if (ObjectUtil.isNotNull(sysUserMap.get(vo.getCreateUserId()))) {
                vo.setCreateUserName(sysUserMap.get(vo.getCreateUserId()).getFullname());
            } else if (vo.getCreateUserId().compareTo(1L) == 0) {
                vo.setCreateUserName("系统");
            }

            if (ObjectUtil.isNotNull(sysUserMap.get(vo.getUpdateUserId()))) {
                vo.setUpdateUserName(sysUserMap.get(vo.getUpdateUserId()).getFullname());
            } else if (vo.getCreateUserId().compareTo(1L) == 0) {
                vo.setUpdateUserName("系统");
            }

            resultList.add(vo);
        }

        return resultList;

    }

    /****************************************** 获取部分 start ******************************************/

    public InvoiceTypeModeRuleSuper getInvoiceModeRuleByInvoiceTypeIdAndModuleOrDefault(Long invoiceTypeId, String module, LoginSysUser loginSysUser) {

        InvoiceType invoiceType = findInvoiceTypeById(invoiceTypeId);


        if (StrUtil.isBlank(invoiceType.getMoudelXModeIsDefaultStruct())) {
            invoiceType.setMoudelXModeIsDefaultStruct(JSONUtil.toJsonStr(initModeFieldIsDefaultStruct()));
        }

        // 包体
        InvoiceTypeMoudelXModeIsDefaultStructModule moudelXModeStructModule = JSONUtil.toBean(invoiceType.getMoudelXModeIsDefaultStruct(), InvoiceTypeMoudelXModeIsDefaultStructModule.class);


        String _module = StrUtil.upperFirst(module);
//		String _modeField                     = StrUtil.upperFirst(opCriteria.getSelectByMode());
//		String getModuleXModeEnableMethodName = StrUtil.format("get{}Mode{}Enable", _module, _modeField);
        String getModuleMethodName = StrUtil.format("get{}", _module);

        // 模块 -> all 方式
        List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> moudelXModeStructModuleMode = ReflectUtil.invoke(moudelXModeStructModule, getModuleMethodName);

        // 模块 -> 启用 & 默认
        List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> filterEnableAndIsDufatlt = moudelXModeStructModuleMode.stream()
                .filter(o -> o.getEnabled().compareTo(CommonEnabledEnum.启用.getKey()) == 0 && o.getIsDefault().compareTo(CommonIsDefaultEnum.默认.getKey()) == 0)
                .collect(Collectors.toList());

        if (CollUtil.isNotEmpty(filterEnableAndIsDufatlt)) {

            InvoiceTypeMoudelXModeIsDefaultStructModuleMode _modeStruct = filterEnableAndIsDufatlt.get(0);
//			_modeStruct.getModeCode();
            switch (InvoiceTypeMoudelXModeEnum.get(_modeStruct.getModeCode())) {
                case 线下开票:

                    InvoiceTypeModeConfigOffLineParam configOffLineParam = invoiceTypeModeConfigOffLineService.getByInvoiceTypeOpCriteria(
                            InvoiceTypeOpCriteria.builder()
                                    .invoiceTypeId(invoiceTypeId)
                                    .selectByModule(InvoiceTypeMoudelEnum.积分结算.getKey())
                                    .build(), loginSysUser
                    );
                    return InvoiceTypeModeRuleSuper.builder()
                            .ruleEnable(configOffLineParam.getRuleEnable())
                            .ruleGoodsLines(configOffLineParam.getRuleGoodsLines())
                            .build();

                case 深圳航信电子发票:

                    InvoiceTypeModeConfigSzhtxxElectronicInvoiceParam szhtxxElectronicInvoiceParam = invoiceTypeModeConfigSzhtxxElectronicInvoiceService.getByInvoiceTypeOpCriteria(
                            InvoiceTypeOpCriteria.builder()
                                    .invoiceTypeId(invoiceTypeId)
                                    .selectByModule(InvoiceTypeMoudelEnum.积分结算.getKey())
                                    .build(), loginSysUser
                    );
                    return InvoiceTypeModeRuleSuper.builder()
                            .ruleEnable(szhtxxElectronicInvoiceParam.getRuleEnable())
                            .ruleGoodsLines(szhtxxElectronicInvoiceParam.getRuleGoodsLines())
                            .build();
                case 深圳航信纸质发票:

                    InvoiceTypeModeConfigSzhtxxPaperInvoiceParam szhtxxPaperInvoiceParam = invoiceTypeModeConfigSzhtxxPaperInvoiceService.getByInvoiceTypeOpCriteria(
                            InvoiceTypeOpCriteria.builder()
                                    .invoiceTypeId(invoiceTypeId)
                                    .selectByModule(InvoiceTypeMoudelEnum.积分结算.getKey())
                                    .build(), loginSysUser
                    );
                    return InvoiceTypeModeRuleSuper.builder()
                            .ruleEnable(szhtxxPaperInvoiceParam.getRuleEnable())
                            .ruleGoodsLines(szhtxxPaperInvoiceParam.getRuleGoodsLines())
                            .build();

                default:
                    return InvoiceTypeModeRuleSuper.builder()
                            .ruleEnable(CommonEnabledEnum.启用.getKey())
                            .ruleGoodsLines(0) // 0为不限
                            .build();
            }
        } else {
            return InvoiceTypeModeRuleSuper.builder()
                    .ruleEnable(CommonEnabledEnum.启用.getKey())
                    .ruleGoodsLines(0) // 0为不限
                    .build();
        }


    }

    public InvoiceTypeModeRuleSuper getInvoiceModeRuleByInvoiceTypeIdAndModuleAndMode(Long invoiceTypeId, /* InvoiceTypeMoudelEnum.积分结算.getKey() */String module, String mode, LoginSysUser loginSysUser) {


        // TODO check module mode


        switch (InvoiceTypeMoudelXModeEnum.get(mode)) {
            case 线下开票:

                InvoiceTypeModeConfigOffLineParam configOffLineParam = invoiceTypeModeConfigOffLineService.getByInvoiceTypeOpCriteria(
                        InvoiceTypeOpCriteria
                                .builder()
                                .invoiceTypeId(invoiceTypeId)
                                .selectByModule(module)
                                .build(),
                        loginSysUser
                );
                return InvoiceTypeModeRuleSuper
                        .builder()
                        .ruleEnable(configOffLineParam.getRuleEnable())
                        .ruleGoodsLines(configOffLineParam.getRuleGoodsLines())
                        .build();

            case 深圳航信电子发票:

                InvoiceTypeModeConfigSzhtxxElectronicInvoiceParam szhtxxElectronicInvoiceParam = invoiceTypeModeConfigSzhtxxElectronicInvoiceService.getByInvoiceTypeOpCriteria(
                        InvoiceTypeOpCriteria
                                .builder()
                                .invoiceTypeId(invoiceTypeId)
                                .selectByModule(module)
                                .build(),
                        loginSysUser
                );
                return InvoiceTypeModeRuleSuper.builder()
                        .ruleEnable(szhtxxElectronicInvoiceParam.getRuleEnable())
                        .ruleGoodsLines(szhtxxElectronicInvoiceParam.getRuleGoodsLines())
                        .build();

            case 深圳航信纸质发票:

                InvoiceTypeModeConfigSzhtxxPaperInvoiceParam szhtxxPaperInvoiceParam = invoiceTypeModeConfigSzhtxxPaperInvoiceService.getByInvoiceTypeOpCriteria(
                        InvoiceTypeOpCriteria
                                .builder()
                                .invoiceTypeId(invoiceTypeId)
                                .selectByModule(module)
                                .build(),
                        loginSysUser
                );
                return InvoiceTypeModeRuleSuper
                        .builder()
                        .ruleEnable(szhtxxPaperInvoiceParam.getRuleEnable())
                        .ruleGoodsLines(szhtxxPaperInvoiceParam.getRuleGoodsLines())
                        .build();

            default:
                return InvoiceTypeModeRuleSuper
                        .builder()
                        .ruleEnable(CommonEnabledEnum.启用.getKey())
                        .ruleGoodsLines(0) // 0为不限
                        .build();
        }
    }

    /****************************************** 获取部分 start ******************************************/


    /****************************************** 操作部分-区分模块 start ******************************************/


    @Override
    public int opSetDefault(InvoiceTypeOpCriteria opCriteria, LoginSysUser loginSysUser) {

        // 清除默认
        setAllNormal(opCriteria.getSelectByModule());

        InvoiceType forUpdate = new InvoiceType();

        forUpdate.setId(opCriteria.getInvoiceTypeId());

        setField(forUpdate, opCriteria.getSelectByModule(), "isDefault", CommonIsDefaultEnum.默认.getKey());

        /**************************************** copy吧 start ****************************************/

        String _module = StrUtil.upperFirst(opCriteria.getSelectByModule());

        String setModuleUpdateTimeMethodName     = StrUtil.format("set{}UpdateTime", _module);
        String setModuleUpdateUserIdMethodName   = StrUtil.format("set{}UpdateUserId", _module);
        String setModuleUpdateUserNameMethodName = StrUtil.format("set{}UpdateUserName", _module);

        ReflectUtil.invoke(forUpdate, setModuleUpdateTimeMethodName, DateUtil.date());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserIdMethodName, loginSysUser.getSysUserId());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserNameMethodName, loginSysUser.getFullName());

        /**************************************** copy吧   end ****************************************/

        forUpdate.setUpdateTime(DateUtil.date());
        forUpdate.setUpdateUserId(loginSysUser.getSysUserId());

        return invoiceTypeMapper.updateByPrimaryKeySelective(forUpdate);
    }

    public void setAllNormal(String selectByModule) {

        InvoiceTypeExample          example  = new InvoiceTypeExample();
        InvoiceTypeExample.Criteria criteria = example.createCriteria();


        InvoiceType forExample = new InvoiceType();
        setField(forExample, selectByModule, "isDefault", CommonIsDefaultEnum.正常.getKey());

        invoiceTypeMapper.updateByExampleSelective(forExample, example);
    }

    @Override
    public int opSetNormal(InvoiceTypeOpCriteria opCriteria, LoginSysUser loginSysUser) {

        InvoiceType forUpdate = new InvoiceType();

        forUpdate.setId(opCriteria.getInvoiceTypeId());

        setField(forUpdate, opCriteria.getSelectByModule(), "isDefault", CommonIsDefaultEnum.正常.getKey());

        /**************************************** copy吧 start ****************************************/

        String _module = StrUtil.upperFirst(opCriteria.getSelectByModule());

        String setModuleUpdateTimeMethodName     = StrUtil.format("set{}UpdateTime", _module);
        String setModuleUpdateUserIdMethodName   = StrUtil.format("set{}UpdateUserId", _module);
        String setModuleUpdateUserNameMethodName = StrUtil.format("set{}UpdateUserName", _module);

        ReflectUtil.invoke(forUpdate, setModuleUpdateTimeMethodName, DateUtil.date());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserIdMethodName, loginSysUser.getSysUserId());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserNameMethodName, loginSysUser.getFullName());

        /**************************************** copy吧   end ****************************************/

        forUpdate.setUpdateTime(DateUtil.date());
        forUpdate.setUpdateUserId(loginSysUser.getSysUserId());

        return invoiceTypeMapper.updateByPrimaryKeySelective(forUpdate);

    }

    @Override
    public int opSetEnable(InvoiceTypeOpCriteria opCriteria, LoginSysUser loginSysUser) {

        InvoiceType forUpdate = new InvoiceType();

        forUpdate.setId(opCriteria.getInvoiceTypeId());

        setField(forUpdate, opCriteria.getSelectByModule(), "enable", CommonEnabledEnum.启用.getKey());

        /**************************************** copy吧 start ****************************************/

        String _module = StrUtil.upperFirst(opCriteria.getSelectByModule());

        String setModuleUpdateTimeMethodName     = StrUtil.format("set{}UpdateTime", _module);
        String setModuleUpdateUserIdMethodName   = StrUtil.format("set{}UpdateUserId", _module);
        String setModuleUpdateUserNameMethodName = StrUtil.format("set{}UpdateUserName", _module);

        ReflectUtil.invoke(forUpdate, setModuleUpdateTimeMethodName, DateUtil.date());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserIdMethodName, loginSysUser.getSysUserId());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserNameMethodName, loginSysUser.getFullName());

        /**************************************** copy吧   end ****************************************/

        forUpdate.setUpdateTime(DateUtil.date());
        forUpdate.setUpdateUserId(loginSysUser.getSysUserId());

        return invoiceTypeMapper.updateByPrimaryKeySelective(forUpdate);

    }

    @Override
    public int opSetDisable(InvoiceTypeOpCriteria opCriteria, LoginSysUser loginSysUser) {

        InvoiceType forUpdate = new InvoiceType();

        forUpdate.setId(opCriteria.getInvoiceTypeId());

        setField(forUpdate, opCriteria.getSelectByModule(), "enable", CommonEnabledEnum.禁用.getKey());

        /**************************************** copy吧 start ****************************************/

        String _module = StrUtil.upperFirst(opCriteria.getSelectByModule());

        String setModuleUpdateTimeMethodName     = StrUtil.format("set{}UpdateTime", _module);
        String setModuleUpdateUserIdMethodName   = StrUtil.format("set{}UpdateUserId", _module);
        String setModuleUpdateUserNameMethodName = StrUtil.format("set{}UpdateUserName", _module);

        ReflectUtil.invoke(forUpdate, setModuleUpdateTimeMethodName, DateUtil.date());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserIdMethodName, loginSysUser.getSysUserId());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserNameMethodName, loginSysUser.getFullName());

        /**************************************** copy吧   end ****************************************/

        forUpdate.setUpdateTime(DateUtil.date());
        forUpdate.setUpdateUserId(loginSysUser.getSysUserId());

        return invoiceTypeMapper.updateByPrimaryKeySelective(forUpdate);

    }

    private void setField(InvoiceType forUpdate, String _module, String _field, Integer value) {

//		supplierGoodsEnable
//		supplierGoodsIsDefault

        String _Module            = StrUtil.upperFirst(_module);
        String _Field             = StrUtil.upperFirst(_field);
        String setFieldMethodName = StrUtil.format("set{}{}", _Module, _Field);

        ReflectUtil.invoke(forUpdate, setFieldMethodName, value);
    }


    /****************************************** 操作部分-区分模块   end ******************************************/


    /****************************************** 操作类 进阶 start ******************************************/


    private InvoiceTypeMoudelXModeIsDefaultStructModule initModeFieldIsDefaultStruct() {

        InvoiceTypeMoudelXModeIsDefaultStructModule result = new InvoiceTypeMoudelXModeIsDefaultStructModule();

////		客户结算^_^customerGoods
//		List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> customerGoods;
////		积分结算^_^customerCredit
//		List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> customerCredit;
////		供应商结算^_^supplierGoods
//		List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> supplierGoods;

//		线下开票(offLine)|深圳航信电子发票(szhtxxElectronicInvoice)
//		客户结算(customerGoods)|积分结算(customerCredit)|供应商结算(supplierGoods)


        EnumSet.allOf(InvoiceTypeMoudelEnum.class).forEach(_module -> {

            String setFieldMethodName = StrUtil.format("set{}", StrUtil.upperFirst(_module.getKey()));

            ReflectUtil.invoke(result, setFieldMethodName, EnumSet.allOf(InvoiceTypeMoudelXModeEnum.class).stream().map(_mode ->
                    InvoiceTypeMoudelXModeIsDefaultStructModuleMode
                            .builder()
                            .modeCode(_mode.getKey())
                            .modeName(_mode.getDesc())
                            .enabled(CommonEnabledEnum.启用.getKey())
                            .isDefault(CommonIsDefaultEnum.正常.getKey())
                            .build()
            ).collect(Collectors.toList()));

        });

//        log.info("initModeFieldIsDefaultStruct \n{}", JSONUtil.toJsonStr(result));

        return result;


//		return InvoiceTypeMoudelXModeIsDefaultStructModule.builder()
//				.customerGoods(customerGoods)
//				.customerCredit(customerCredit)
//				.supplierGoods(supplierGoods)
//				.build();

    }

    //	vertical 垂直
    //	horizontal 水平
    private void packingModeFieldIsDefaultStruct() {

    }

    private void unpackingModeFieldIsDefaultStruct() {

    }

    @Override
    public int opInvoiceSettingSetDefault(InvoiceTypeOpCriteria opCriteria, LoginSysUser loginSysUser) {

        InvoiceType existData = this.findInvoiceTypeById(opCriteria.getInvoiceTypeId());

        if (StrUtil.isBlank(existData.getMoudelXModeIsDefaultStruct())) {
            existData.setMoudelXModeIsDefaultStruct(JSONUtil.toJsonStr(initModeFieldIsDefaultStruct()));
        }

        // 包体
        InvoiceTypeMoudelXModeIsDefaultStructModule moudelXModeStructModule = JSONUtil.toBean(existData.getMoudelXModeIsDefaultStruct(), InvoiceTypeMoudelXModeIsDefaultStructModule.class);


        String _module    = StrUtil.upperFirst(opCriteria.getSelectByModule());
        String _modeField = StrUtil.upperFirst(opCriteria.getSelectByMode());

        String getModuleXModeEnableMethodName = StrUtil.format("get{}Mode{}Enable", _module, _modeField);
        String getModuleMethodName            = StrUtil.format("get{}", _module);

        String setModuleUpdateTimeMethodName     = StrUtil.format("set{}UpdateTime", _module);
        String setModuleUpdateUserIdMethodName   = StrUtil.format("set{}UpdateUserId", _module);
        String setModuleUpdateUserNameMethodName = StrUtil.format("set{}UpdateUserName", _module);

        // 模块 -> all 方式
        List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> moudelXModeStructModuleMode = ReflectUtil.invoke(moudelXModeStructModule, getModuleMethodName);

        // 清除默认
        moudelXModeStructModuleMode.forEach(_item -> {
            _item.setIsDefault(CommonIsDefaultEnum.正常.getKey());
        });

        // 过滤
        List<Predicate<InvoiceTypeMoudelXModeIsDefaultStructModuleMode>> predicatesModuleXModeCModeEq = new ArrayList<>();
        predicatesModuleXModeCModeEq.add(r -> r.getModeCode() != null && r.getModeCode().equals(opCriteria.getSelectByMode()));
        List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> predicatesModuleXModeCModeEqFilter = AnLamdaUtils.filters(moudelXModeStructModuleMode, predicatesModuleXModeCModeEq);

        if (CollUtil.isNotEmpty(predicatesModuleXModeCModeEqFilter)) {
            predicatesModuleXModeCModeEqFilter.get(0).setIsDefault(CommonIsDefaultEnum.默认.getKey());
        }


        InvoiceType forUpdate = new InvoiceType();

        forUpdate.setId(opCriteria.getInvoiceTypeId());

        forUpdate.setMoudelXModeIsDefaultStruct(JSONUtil.toJsonStr(moudelXModeStructModule));

        ReflectUtil.invoke(forUpdate, setModuleUpdateTimeMethodName, DateUtil.date());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserIdMethodName, loginSysUser.getSysUserId());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserNameMethodName, loginSysUser.getFullName());

        forUpdate.setUpdateTime(DateUtil.date());
        forUpdate.setUpdateUserId(loginSysUser.getSysUserId());

        return invoiceTypeMapper.updateByPrimaryKeySelective(forUpdate);
    }

    @Override
    public int opInvoiceSettingSetNormal(InvoiceTypeOpCriteria opCriteria, LoginSysUser loginSysUser) {

        InvoiceType existData = this.findInvoiceTypeById(opCriteria.getInvoiceTypeId());

        if (StrUtil.isBlank(existData.getMoudelXModeIsDefaultStruct())) {
            existData.setMoudelXModeIsDefaultStruct(JSONUtil.toJsonStr(initModeFieldIsDefaultStruct()));
        }

        InvoiceTypeMoudelXModeIsDefaultStructModule moudelXModeStructModule = JSONUtil.toBean(existData.getMoudelXModeIsDefaultStruct(), InvoiceTypeMoudelXModeIsDefaultStructModule.class);


        String _module    = StrUtil.upperFirst(opCriteria.getSelectByModule());
        String _modeField = StrUtil.upperFirst(opCriteria.getSelectByMode());

        String getModuleXModeEnableMethodName = StrUtil.format("get{}Mode{}Enable", _module, _modeField);
        String getModuleMethodName            = StrUtil.format("get{}", _module);

        String setModuleUpdateTimeMethodName     = StrUtil.format("set{}UpdateTime", _module);
        String setModuleUpdateUserIdMethodName   = StrUtil.format("set{}UpdateUserId", _module);
        String setModuleUpdateUserNameMethodName = StrUtil.format("set{}UpdateUserName", _module);

        // 模块 -> all 方式
        List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> moudelXModeStructModuleMode = ReflectUtil.invoke(moudelXModeStructModule, getModuleMethodName);

        // 过滤
        List<Predicate<InvoiceTypeMoudelXModeIsDefaultStructModuleMode>> predicatesModuleXModeCModeEq = new ArrayList<>();
        predicatesModuleXModeCModeEq.add(r -> r.getModeCode() != null && r.getModeCode().equals(opCriteria.getSelectByMode()));
        List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> predicatesModuleXModeCModeEqFilter = AnLamdaUtils.filters(moudelXModeStructModuleMode, predicatesModuleXModeCModeEq);

        if (CollUtil.isNotEmpty(predicatesModuleXModeCModeEqFilter)) {
            predicatesModuleXModeCModeEqFilter.get(0).setIsDefault(CommonIsDefaultEnum.正常.getKey());
        }


        InvoiceType forUpdate = new InvoiceType();

        forUpdate.setId(opCriteria.getInvoiceTypeId());

        forUpdate.setMoudelXModeIsDefaultStruct(JSONUtil.toJsonStr(moudelXModeStructModule));

        ReflectUtil.invoke(forUpdate, setModuleUpdateTimeMethodName, DateUtil.date());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserIdMethodName, loginSysUser.getSysUserId());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserNameMethodName, loginSysUser.getFullName());

        forUpdate.setUpdateTime(DateUtil.date());
        forUpdate.setUpdateUserId(loginSysUser.getSysUserId());

        return invoiceTypeMapper.updateByPrimaryKeySelective(forUpdate);
    }

    @Override
    public int opInvoiceSettingSetEnable(InvoiceTypeOpCriteria opCriteria, LoginSysUser loginSysUser) {

        return invoiceSettingModuleXModeSetEable(opCriteria, loginSysUser, CommonEnabledEnum.启用);
    }

    @Override
    public int opInvoiceSettingSetDisable(InvoiceTypeOpCriteria opCriteria, LoginSysUser loginSysUser) {

        return invoiceSettingModuleXModeSetEable(opCriteria, loginSysUser, CommonEnabledEnum.禁用);
    }

    private int invoiceSettingModuleXModeSetEable(InvoiceTypeOpCriteria opCriteria, LoginSysUser loginSysUser, CommonEnabledEnum enabledEnum) {

        InvoiceType existData = this.findInvoiceTypeById(opCriteria.getInvoiceTypeId());

        if (ObjectUtil.isNull(existData)) {
            return 0;
        }

        String _module    = StrUtil.upperFirst(opCriteria.getSelectByModule());
        String _modeField = StrUtil.upperFirst(opCriteria.getSelectByMode());

        String setModuleXModeEnableMethodName = StrUtil.format("set{}Mode{}Enable", _module, _modeField);

        String setModuleUpdateTimeMethodName     = StrUtil.format("set{}UpdateTime", _module);
        String setModuleUpdateUserIdMethodName   = StrUtil.format("set{}UpdateUserId", _module);
        String setModuleUpdateUserNameMethodName = StrUtil.format("set{}UpdateUserName", _module);

        InvoiceType forUpdate = new InvoiceType();

        forUpdate.setId(opCriteria.getInvoiceTypeId());

        ReflectUtil.invoke(forUpdate, setModuleXModeEnableMethodName, enabledEnum.getKey());

        ReflectUtil.invoke(forUpdate, setModuleUpdateTimeMethodName, DateUtil.date());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserIdMethodName, loginSysUser.getSysUserId());
        ReflectUtil.invoke(forUpdate, setModuleUpdateUserNameMethodName, loginSysUser.getFullName());

        forUpdate.setUpdateTime(DateUtil.date());
        forUpdate.setUpdateUserId(loginSysUser.getSysUserId());

        return invoiceTypeMapper.updateByPrimaryKeySelective(forUpdate);


    }

    public InvoiceTypeOpInvoiceSettingLoadingVo opInvoiceSettingLoading(InvoiceTypeOpCriteria opCriteria, LoginSysUser loginSysUser) {

        InvoiceType _entityInvoiceTypeItem = this.findInvoiceTypeById(opCriteria.getInvoiceTypeId());


        /****************************************** 加载 config start ******************************************/

        // InvoiceTypeMoudelXModeEnum
        // 线下开票("offLine", "线下开票"),
        // 深圳航信电子发票("szhtxxElectronicInvoice", "深圳航信电子发票"),
        // 深圳航信纸质发票("szhtxxPaperInvoice", "深圳航信纸质发票"),

        // 线下开票 offLine
        InvoiceTypeModeConfigOffLineParam offLine = invoiceTypeModeConfigOffLineService.getByInvoiceTypeOpCriteria(opCriteria, loginSysUser);

        // 深圳航信电子发票 szhtxxElectronicInvoice
        InvoiceTypeModeConfigSzhtxxElectronicInvoiceParam szhtxxElectronicInvoice = invoiceTypeModeConfigSzhtxxElectronicInvoiceService.getByInvoiceTypeOpCriteria(opCriteria, loginSysUser);

        // 深圳航信纸质发票 szhtxxPaperInvoice
        InvoiceTypeModeConfigSzhtxxPaperInvoiceParam szhtxxPaperInvoice = invoiceTypeModeConfigSzhtxxPaperInvoiceService.getByInvoiceTypeOpCriteria(opCriteria, loginSysUser);

        /******************************************  start ******************************************/

        // 是从这里保证有的
        if (StrUtil.isBlank(_entityInvoiceTypeItem.getMoudelXModeIsDefaultStruct())) {
            _entityInvoiceTypeItem.setMoudelXModeIsDefaultStruct(JSONUtil.toJsonStr(initModeFieldIsDefaultStruct()));
        } else {

        }

        InvoiceTypeMoudelXModeIsDefaultStructModule moudelXModeStructModule = JSONUtil.toBean(_entityInvoiceTypeItem.getMoudelXModeIsDefaultStruct(), InvoiceTypeMoudelXModeIsDefaultStructModule.class);

        List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> modes = new ArrayList<>();

        // 发票种类 -> 模块 -> 方式
        EnumSet.allOf(InvoiceTypeMoudelXModeEnum.class).forEach(_enumModeItem -> {

            String _module    = StrUtil.upperFirst(opCriteria.getSelectByModule());
            String _modeField = StrUtil.upperFirst(_enumModeItem.getKey());

            String getModuleXModeEnableMethodName = StrUtil.format("get{}Mode{}Enable", _module, _modeField);
            String getModuleMethodName            = StrUtil.format("get{}", _module);

            Integer checkModuleXModeEnable = ReflectUtil.invoke(_entityInvoiceTypeItem, getModuleXModeEnableMethodName);

            List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> moudelXModeStructModuleMode = ReflectUtil.invoke(moudelXModeStructModule, getModuleMethodName);

//            log.info("{}-{}-{}", _entityInvoiceTypeItem.getTypeName(), getModuleXModeEnableMethodName, CommonEnabledEnum.get(checkModuleXModeEnable).getDesc());

//			if (ObjectUtil.isNotNull(checkModuleXModeEnable)
//					&& checkModuleXModeEnable.compareTo(CommonEnabledEnum.启用.getKey()) == 0) {

            // 过滤
            List<Predicate<InvoiceTypeMoudelXModeIsDefaultStructModuleMode>> predicatesModuleXModeCModeEq = new ArrayList<>();
            predicatesModuleXModeCModeEq.add(r -> r.getModeCode() != null && r.getModeCode().equals(_enumModeItem.getKey()));

            List<InvoiceTypeMoudelXModeIsDefaultStructModuleMode> predicatesModuleXModeCModeEqFilter = AnLamdaUtils.filters(moudelXModeStructModuleMode, predicatesModuleXModeCModeEq);

            modes.addAll(predicatesModuleXModeCModeEqFilter);
//			}
        });

        /******************************************  start ******************************************/


        return InvoiceTypeOpInvoiceSettingLoadingVo.builder()
                .echo(opCriteria)
                .moudelXModeIsDefaultStruct(modes)
                .offLine(offLine)
                .szhtxxElectronicInvoice(szhtxxElectronicInvoice)
                .szhtxxPaperInvoice(szhtxxPaperInvoice)
                .build();
    }

    /****************************************** 操作类 进阶   end ******************************************/


    /****************************************** 工具方法 start ******************************************/

    public Map<String, InvoiceType> convertToMapFieldTypeName2Entity() {

        Map<String, InvoiceType> result = new HashMap<>();

        InvoiceTypeExample          example  = new InvoiceTypeExample();
        InvoiceTypeExample.Criteria criteria = example.createCriteria();

        List<InvoiceType> resultList = invoiceTypeMapper.selectByExample(example);

        if (AnCollectionUtils.isNotEmpty(resultList)) {
            result = resultList.stream().collect(Collectors.toMap(InvoiceType::getTypeName, v -> v, (k, v) -> v));
        }

        return result;

    }

    /**
     * InvoiceTypeCriteria conditions
     *
     * @return
     */
    public Map<String, String> convertToMapFieldTypeName2JsonString() {

        Map<String, String> result = new HashMap<>();

        Map<String, InvoiceType> tmp = convertToMapFieldTypeName2Entity();

        tmp.forEach((companyName, entity) -> {
            result.put(companyName, AnJsonUtils.toJson(entity));
//			result.put(URLUtil.encode((companyName)), JsonUtils.toJson(entity));
        });

        return result;

    }

    public Map<Long, InvoiceType> convertToMapFieldId2Entity() {

        Map<Long, InvoiceType> result = new HashMap<>();

        InvoiceTypeExample          example  = new InvoiceTypeExample();
        InvoiceTypeExample.Criteria criteria = example.createCriteria();

        List<InvoiceType> resultList = invoiceTypeMapper.selectByExample(example);

        if (AnCollectionUtils.isNotEmpty(resultList)) {
            result = resultList.stream().collect(Collectors.toMap(InvoiceType::getId, v -> v, (k, v) -> v));
        }

        return result;

    }


    /**
     * InvoiceTypeCriteria conditions
     *
     * @return
     */
    public Map<String, String> convertToMapFieldId2JsonString() {

        Map<String, String> result = new HashMap<>();

        Map<Long, InvoiceType> tmp = convertToMapFieldId2Entity();

        tmp.forEach((id, entity) -> {
            result.put(AnStringUtils.getString(id), AnJsonUtils.toJson(entity));
        });

        return result;

    }


    /****************************************** 工具方法   end ******************************************/

    /****************************************** 缓存 start ******************************************/

    public void cacheInit(InvoiceTypeCacheCriteria criteria) {

//		InvoiceTypeCriteria conditions = new InvoiceTypeCriteria();

        List<String> conditions = Arrays.asList("id", "type_name");

        if (StrUtil.isNotBlank(criteria.getHashTableKeyField()) && conditions.contains(criteria.getHashTableKeyField())) {

            switch (RedisKeyPrefix.get(RedisKeyPrefix.关联性校验_发票种类.getKey() + ":" + criteria.getHashTableKeyField())) {
                case 关联性校验_发票种类_种类ID:

                    Map<String, String> mapValueFieldId2String = convertToMapFieldId2JsonString();

                    // 验证 SystemConsts.RedisExpireTime.REFRESH_TOKEN_EXPIRE_TIME
                    redisService.hashSave(mapValueFieldId2String, RedisKeyPrefix.关联性校验_前缀, RedisKeyPrefix.关联性校验_发票种类_种类ID.getKey(), 0);

                    break;
                case 关联性校验_发票种类_种类名称:

                    Map<String, String> mapValueFieldTypeName2String = convertToMapFieldTypeName2JsonString();

                    // 验证 SystemConsts.RedisExpireTime.REFRESH_TOKEN_EXPIRE_TIME
                    redisService.hashSave(mapValueFieldTypeName2String, RedisKeyPrefix.关联性校验_前缀, RedisKeyPrefix.关联性校验_发票种类_种类名称.getKey(), 0);

                    // 测试过 结果与上边一个样
                    //		mapValue.forEach((companyName, entityJsonString) -> {
                    //			cacheService.hashSet(RedisKeyPrefix.关联性校验_前缀.getKey() + ":" + RedisKeyPrefix.关联性校验_发票种类.getKey(), companyName, entityJsonString);
                    //		});

                    break;
            }
        }


    }

    public void cacheRefresh(InvoiceTypeCacheCriteria criteria) {

        cacheRemove(criteria);
        cacheInit(criteria);
    }

    public void cacheRemove(InvoiceTypeCacheCriteria criteria) {

        List<String> conditions = Arrays.asList("id", "type_name");

        if (StrUtil.isNotBlank(criteria.getHashTableKeyField()) && conditions.contains(criteria.getHashTableKeyField())) {

            switch (RedisKeyPrefix.get(RedisKeyPrefix.关联性校验_发票种类.getKey() + ":" + criteria.getHashTableKeyField())) {
                case 关联性校验_发票种类_种类ID:
                    redisService.deleteKey(RedisKeyPrefix.关联性校验_前缀, RedisKeyPrefix.关联性校验_发票种类_种类ID.getKey());
                    break;
                case 关联性校验_发票种类_种类名称:
                    redisService.deleteKey(RedisKeyPrefix.关联性校验_前缀, RedisKeyPrefix.关联性校验_发票种类_种类名称.getKey());
                    break;
            }
        }
    }

    public String cacheGet(InvoiceTypeCacheCriteria criteria) {

//        log.info("hashTable@{}@field@{}@cacheService@{}", criteria.getHashTable() + ":" + criteria.getHashTableKeyField(), criteria.getKeyField(), redisService);

        return (String) redisService.hashGetByKey(criteria.getHashTable() + ":" + criteria.getHashTableKeyField(), criteria.getKeyField());
    }

    /**
     * 套娃呢
     *
     * @param criteria
     * @return
     */
    public InvoiceType cacheGetEntity(InvoiceTypeCacheCriteria criteria) {

        String cacheResult = cacheGet(criteria);

        if (StrUtil.isNotBlank(cacheResult)) {
            return AnJsonUtils.toObject(cacheResult, InvoiceType.class);
        } else {
            return null;
        }
    }

    /****************************************** 缓存   end ******************************************/


}
