|  |  | 
 |  |  | package cc.mrbird.febs.mall.service.impl; | 
 |  |  |  | 
 |  |  | import cc.mrbird.febs.common.enumerates.AgentLevelEnum; | 
 |  |  | import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum; | 
 |  |  | import cc.mrbird.febs.common.enumerates.*; | 
 |  |  | import cc.mrbird.febs.common.tree.MatrixTree; | 
 |  |  | import cc.mrbird.febs.common.tree.MemberNode; | 
 |  |  | import cc.mrbird.febs.common.utils.AppContants; | 
 |  |  | import cc.mrbird.febs.mall.entity.AgentInfo; | 
 |  |  | import cc.mrbird.febs.mall.entity.DataDictionaryCustom; | 
 |  |  | import cc.mrbird.febs.mall.entity.MallMember; | 
 |  |  | import cc.mrbird.febs.mall.entity.MallOrderInfo; | 
 |  |  | import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper; | 
 |  |  | import cc.mrbird.febs.mall.mapper.MallMemberMapper; | 
 |  |  | import cc.mrbird.febs.mall.mapper.MallMemberWalletMapper; | 
 |  |  | import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; | 
 |  |  | import cc.mrbird.febs.mall.service.IAgentService; | 
 |  |  | import cc.mrbird.febs.mall.service.IApiMallMemberService; | 
 |  |  | import cc.mrbird.febs.mall.service.IApiMallMemberWalletService; | 
 |  |  | import cc.mrbird.febs.common.utils.MallUtils; | 
 |  |  | import cc.mrbird.febs.mall.entity.*; | 
 |  |  | import cc.mrbird.febs.mall.mapper.*; | 
 |  |  | import cc.mrbird.febs.mall.service.*; | 
 |  |  | import cc.mrbird.febs.mall.vo.AdminMallMoneyFlowVo; | 
 |  |  | import cc.mrbird.febs.mall.vo.AdminTeamEqualsPerkVo; | 
 |  |  | import cc.mrbird.febs.system.mapper.UserMapper; | 
 |  |  | import cn.hutool.core.collection.CollUtil; | 
 |  |  | import cn.hutool.core.util.ObjectUtil; | 
 |  |  | import cn.hutool.core.util.StrUtil; | 
 |  |  | import cn.hutool.json.JSONUtil; | 
 |  |  | import com.alibaba.fastjson.JSONObject; | 
 |  |  | import jdk.nashorn.internal.ir.IfNode; | 
 |  |  | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 
 |  |  | import lombok.RequiredArgsConstructor; | 
 |  |  | import lombok.extern.slf4j.Slf4j; | 
 |  |  | import org.apache.ibatis.session.ExecutorType; | 
 |  |  | import org.apache.ibatis.session.SqlSession; | 
 |  |  | import org.mybatis.spring.SqlSessionTemplate; | 
 |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
 |  |  | import org.springframework.stereotype.Service; | 
 |  |  | import org.springframework.transaction.annotation.Transactional; | 
 |  |  |  | 
 |  |  | import java.math.BigDecimal; | 
 |  |  | import java.math.RoundingMode; | 
 |  |  | import java.util.ArrayList; | 
 |  |  | import java.util.HashMap; | 
 |  |  | import java.util.List; | 
 |  |  | import java.util.Map; | 
 |  |  | import java.util.*; | 
 |  |  | import java.util.stream.Collectors; | 
 |  |  |  | 
 |  |  | /** | 
 |  |  |  * @author wzy | 
 |  |  | 
 |  |  |  | 
 |  |  |     private final DataDictionaryCustomMapper dataDictionaryCustomMapper; | 
 |  |  |     private final MallMemberMapper memberMapper; | 
 |  |  |     private final MallOrderInfoMapper orderInfoMapper; | 
 |  |  |     private final IApiMallMemberWalletService memberWalletService; | 
 |  |  |     private final IApiMallMemberService memberService; | 
 |  |  |     private final MallOrderInfoMapper mallOrderInfoMapper; | 
 |  |  |  | 
 |  |  |     private final IMallMoneyFlowService mallMoneyFlowService; | 
 |  |  |     private final MallMemberWalletMapper mallMemberWalletMapper; | 
 |  |  |     private final SqlSessionTemplate sqlSessionTemplate; | 
 |  |  |     private final MallMoneyFlowMapper mallMoneyFlowMapper; | 
 |  |  |     private final MallMqRecordMapper mallMqRecordMapper; | 
 |  |  |  | 
 |  |  |     private final MatrixTreeNodeMapper matrixTreeNodeMapper; | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     @Transactional(rollbackFor = Exception.class) | 
 |  |  |     public void autoUpAgentLevel(Long memberId) { | 
 |  |  |         log.info("###代理自动升级###"); | 
 |  |  |         MallMember member = memberMapper.selectById(memberId); | 
 |  |  |         if(StrUtil.isBlank(member.getReferrerIds())) { | 
 |  |  |  | 
 |  |  |         MatrixTree tree = MatrixTree.getInstance(); | 
 |  |  |         MemberNode node = tree.getNode(member.getInviteId()); | 
 |  |  |         if (node != null) { | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         List<String> ids = StrUtil.split(member.getReferrerIds(), ','); | 
 |  |  |         List<MallMember> parentMembers = memberMapper.selectByInviteIds(ids); | 
 |  |  |         for (MallMember parent : parentMembers) { | 
 |  |  |             // 未激活用户无法升级 | 
 |  |  |             if (AgentLevelEnum.ZERO_LEVEL.name().equals(member.getLevel())) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             DataDictionaryCustom nextLevel = dataDictionaryCustomMapper.selectNextAgentLevelInfo(parent.getLevel()); | 
 |  |  |             if (nextLevel == null) { | 
 |  |  |                 log.info("当前层级无下一级:{}", parent.getLevel()); | 
 |  |  |                 return; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             AgentInfo agentInfo = JSONObject.parseObject(nextLevel.getValue(), AgentInfo.class); | 
 |  |  |             if (!orderCntFinish(parent, agentInfo)) { | 
 |  |  |                 return; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (!agentCntFinish(parent, agentInfo)) { | 
 |  |  |                 return; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             parent.setLevel(nextLevel.getCode()); | 
 |  |  |             memberMapper.updateById(parent); | 
 |  |  |         MatrixTreeNode matrixTreeNode = matrixTreeNodeMapper.selectByTreeNode(memberId); | 
 |  |  |         if (matrixTreeNode != null) { | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         node = new MemberNode(); | 
 |  |  |         node.setInviteId(member.getInviteId()); | 
 |  |  |         node.setPhone(member.getPhone()); | 
 |  |  |         node.setRefererId(member.getReferrerId()); | 
 |  |  |         node.setMemberId(member.getId()); | 
 |  |  |         MemberNode parentNode = tree.addNode(node); | 
 |  |  |  | 
 |  |  |         matrixTreeNode = new MatrixTreeNode(); | 
 |  |  |         matrixTreeNode.setTreeNode(memberId); | 
 |  |  |         matrixTreeNode.setParentNode(parentNode.getMemberId()); | 
 |  |  |         matrixTreeNodeMapper.insert(matrixTreeNode); | 
 |  |  |  | 
 |  |  |         List<DataDictionaryCustom> dicList = dataDictionaryCustomMapper.selectDicByType(AppContants.AGENT_LEVEL); | 
 |  |  |         DataDictionaryCustom dic = null; | 
 |  |  |         for (DataDictionaryCustom dataDictionaryCustom : dicList) { | 
 |  |  |             if (Integer.parseInt(dataDictionaryCustom.getValue()) == parentNode.CHILD.size()) { | 
 |  |  |                 dic = dataDictionaryCustom; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         if (dic == null) { | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         MallMember parentMember = memberMapper.selectById(parentNode.getMemberId()); | 
 |  |  |         parentMember.setChildNodeCnt(parentNode.CHILD.size()); | 
 |  |  |         parentMember.setLevel(dic.getCode()); | 
 |  |  |         memberMapper.updateById(parentMember); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 判断用户直推下单数量或团队下单数量是否达标 | 
 |  |  |      * 判断直推人数是否达标 | 
 |  |  |      * | 
 |  |  |      * @param member | 
 |  |  |      * @return | 
 |  |  |      */ | 
 |  |  |     private boolean orderCntFinish(MallMember member, AgentInfo agentInfo) { | 
 |  |  |         Integer cnt = 0; | 
 |  |  |         if (AgentInfo.ORDER_TYPE_DIRECT.equals(agentInfo.getOrderType())) { | 
 |  |  |             cnt = orderInfoMapper.selectCntDirect(member.getInviteId()); | 
 |  |  |         } else { | 
 |  |  |             cnt = orderInfoMapper.selectCntDirectOrTeam(agentInfo.getOrderType(), member.getInviteId()); | 
 |  |  |     private boolean directMemberCnt(MallMember member, AgentInfo agentInfo) { | 
 |  |  |         List<MallMember> childs = memberMapper.selectByRefererId(member.getInviteId()); | 
 |  |  |         if (CollUtil.isEmpty(childs)) { | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         if (cnt >= agentInfo.getOrderCnt()) { | 
 |  |  |         if (childs.size() >= agentInfo.getDirectCnt()) { | 
 |  |  |             return true; | 
 |  |  |         } | 
 |  |  |         log.info("用户{}订单未达标, 当前数量为:{},要求数量:{}, 当前等级为:{}", member.getPhone(), cnt, agentInfo.getOrderCnt(), member.getLevel()); | 
 |  |  |  | 
 |  |  |         log.info("用户:{}直推数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getLevel(), childs.size(), agentInfo.getDirectCnt()); | 
 |  |  |         return false; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | 
 |  |  |      * @return | 
 |  |  |      */ | 
 |  |  |     private boolean agentCntFinish(MallMember member, AgentInfo agentInfo) { | 
 |  |  |         if (agentInfo.getLastCnt() == null) { | 
 |  |  |         if (agentInfo.getLastAgentCnt() == null || agentInfo.getLastAgentCnt() == 0) { | 
 |  |  |             return true; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         if (i >= agentInfo.getLastCnt()) { | 
 |  |  |         if (i >= agentInfo.getLastAgentCnt()) { | 
 |  |  |             return true; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         log.info("用户:{}代理数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getLevel(), i, agentInfo.getLastCnt()); | 
 |  |  |         log.info("用户:{}代理数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getLevel(), i, agentInfo.getLastAgentCnt()); | 
 |  |  |         return false; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 团队贡献点是否达标 | 
 |  |  |      * | 
 |  |  |      * @param agentInfo | 
 |  |  |      * @return | 
 |  |  |      */ | 
 |  |  |     private boolean teamIncome(MallMember member, AgentInfo agentInfo) { | 
 |  |  |  | 
 |  |  |         List<MallMember> mallMembers = memberMapper.selectAllChildAgentListByInviteId(member.getInviteId()); | 
 |  |  |         List<Long> ids = mallMembers.stream().map(MallMember::getId).collect(Collectors.toList()); | 
 |  |  |         List<MallMemberWallet> mallMemberWallets = mallMemberWalletMapper.selectMemberWalletsByIds(ids); | 
 |  |  |  | 
 |  |  |         int starSum = mallMemberWallets.stream().mapToInt(MallMemberWallet::getStar).sum(); | 
 |  |  |         BigDecimal teamIncome = agentInfo.getTeamIncome(); | 
 |  |  |         if (teamIncome.compareTo(new BigDecimal(starSum)) <= 0) { | 
 |  |  |             return true; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         log.info("用户:{}团队贡献点未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getLevel(), starSum, teamIncome); | 
 |  |  |         return false; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     @Transactional(rollbackFor = Exception.class) | 
 |  |  |     public void returnMoneyToAgent(Long orderId) { | 
 |  |  |         MallOrderInfo orderInfo = orderInfoMapper.selectById(orderId); | 
 |  |  |  | 
 |  |  |         MallMember member = memberMapper.selectById(orderInfo.getMemberId()); | 
 |  |  |         if (StrUtil.isBlank(member.getReferrerIds())) { | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         // 直推奖励 | 
 |  |  |         directReturnMoney(member, orderInfo); | 
 |  |  |         // 团队奖励 | 
 |  |  |         teamReturnMoney(member, orderInfo); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 直推奖励 | 
 |  |  |      * @param member | 
 |  |  |      */ | 
 |  |  |     private void directReturnMoney(MallMember member, MallOrderInfo orderInfo) { | 
 |  |  |         MallMember parent = memberMapper.selectInfoByInviteId(member.getReferrerId()); | 
 |  |  |         if (AgentLevelEnum.FIRST_LEVEL.name().equals(parent.getLevel()) || AgentLevelEnum.ZERO_LEVEL.name().equals(parent.getLevel())) { | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         AgentInfo agentInfo = getAgentInfo(parent.getLevel()); | 
 |  |  |         if (agentInfo == null) { | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         BigDecimal returnMoney = agentInfo.getDirectIncome().divide(BigDecimal.valueOf(100), 2,RoundingMode.DOWN).multiply(orderInfo.getAmount()); | 
 |  |  |         memberWalletService.addBalance(returnMoney, parent.getId()); | 
 |  |  |  | 
 |  |  |         memberService.addMoneyFlow(parent.getId(), returnMoney, MoneyFlowTypeEnum.BONUS.getValue(), orderInfo.getOrderNo(), null, null, orderInfo.getMemberId(), null); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 团队奖励 | 
 |  |  |      * | 
 |  |  |      */ | 
 |  |  |     public void teamReturnMoney(MallMember member, MallOrderInfo orderInfo) { | 
 |  |  |         List<String> inviteIds = StrUtil.split(member.getReferrerIds(), ','); | 
 |  |  |         List<MallMember> agentList = memberMapper.selectMemberParentAgentList(inviteIds); | 
 |  |  |         if (CollUtil.isEmpty(agentList)) { | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         Map<String, Map<Long, BigDecimal>> needReturn = new HashMap<>(); | 
 |  |  |         for (MallMember mallMember : agentList) { | 
 |  |  |             String level = mallMember.getLevel(); | 
 |  |  |  | 
 |  |  |             Map<Long, BigDecimal> amount = needReturn.get(level); | 
 |  |  |  | 
 |  |  |             // 按照代理关系,返到第二级,平级奖 | 
 |  |  |             if (amount == null) { | 
 |  |  |                 amount = new HashMap<>(); | 
 |  |  |                 AgentInfo agentInfo = getAgentInfo(level); | 
 |  |  |                 if (agentInfo == null) { | 
 |  |  |                     continue; | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |                 BigDecimal returnMoney; | 
 |  |  |                 if (AgentInfo.TEAM_INCOME_TYPE_AMOUNT.equals(agentInfo.getTeamIncomeType())) { | 
 |  |  |                     returnMoney = agentInfo.getTeamIncome(); | 
 |  |  |                 } else { | 
 |  |  |                     returnMoney = agentInfo.getTeamIncome().divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN).multiply(orderInfo.getAmount()); | 
 |  |  |                 } | 
 |  |  |                 amount.put(mallMember.getId(), returnMoney); | 
 |  |  |             } else { | 
 |  |  |                 if (!AgentLevelEnum.SECOND_LEVEL.name().equals(mallMember.getLevel())) { | 
 |  |  |                     amount.put(mallMember.getId(), BigDecimal.ONE); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             // 代理两级 | 
 |  |  |             if (amount.size() > 2) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             needReturn.put(level, amount); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         if(needReturn.isEmpty()) { | 
 |  |  |            return; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         for (Map.Entry<String, Map<Long, BigDecimal>> entry : needReturn.entrySet()) { | 
 |  |  |             for (Map.Entry<Long, BigDecimal> amount : entry.getValue().entrySet()) { | 
 |  |  |                 memberWalletService.addBalance(amount.getValue(), amount.getKey()); | 
 |  |  |  | 
 |  |  |                 memberService.addMoneyFlow(amount.getKey(), amount.getValue(), MoneyFlowTypeEnum.ACHIEVE.getValue(), orderInfo.getOrderNo(), null, null, orderInfo.getMemberId(), null); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private AgentInfo getAgentInfo(String level) { | 
 |  |  |         DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.AGENT_LEVEL_REQUIRE, level); | 
 |  |  |         if (dic == null) { | 
 |  |  |             log.info("当前用户父级等级:{}", level); | 
 |  |  |             return null; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         return JSONObject.parseObject(dic.getValue(), AgentInfo.class); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public void rankReturnMoney(Long orderId) { | 
 |  |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     @Transactional(rollbackFor = Exception.class) | 
 |  |  |     public void perkMoneyConsumer(long orderId) { | 
 |  |  |         long start = System.currentTimeMillis(); | 
 |  |  |         MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectById(orderId); | 
 |  |  |         if(ObjectUtil.isEmpty(mallOrderInfo)){ | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  | //        if(2 != mallOrderInfo.getStatus()){ | 
 |  |  | //            return; | 
 |  |  | //        } | 
 |  |  |         /** | 
 |  |  |          * 分享补贴 直推消费额10% | 
 |  |  |          */ | 
 |  |  |         BigDecimal amount = mallOrderInfo.getAmount().subtract(mallOrderInfo.getScoreAmount()); | 
 |  |  |  | 
 |  |  |         Long memberId = mallOrderInfo.getMemberId(); | 
 |  |  |         MallMember mallMember = memberMapper.selectById(memberId); | 
 |  |  |         //补贴对象 直属上级 | 
 |  |  |         MallMember mallMemberUp = memberMapper.selectInfoByInviteId(mallMember.getReferrerId()); | 
 |  |  |         if(ObjectUtil.isNotEmpty(mallMemberUp)){ | 
 |  |  |             //分享补贴百分比 | 
 |  |  |             DataDictionaryCustom sharePerkDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( | 
 |  |  |                     DataDictionaryEnum.SHARE_PERK.getType(), | 
 |  |  |                     DataDictionaryEnum.SHARE_PERK.getCode()); | 
 |  |  |             String sharePerk = ObjectUtil.isEmpty(sharePerkDic.getValue()) ? "0" : sharePerkDic.getValue(); | 
 |  |  |             BigDecimal sharePerkPercent = new BigDecimal(sharePerk).abs().divide(new BigDecimal(100)); | 
 |  |  |             //分享补贴金额 | 
 |  |  |             BigDecimal sharePerkAmount = amount.multiply(sharePerkPercent).setScale(2, BigDecimal.ROUND_DOWN);; | 
 |  |  |  | 
 |  |  |             //所有合伙人补贴至消费礼包的三倍额度需要复购一次。 | 
 |  |  |             MallMemberWallet mallMemberWallet = mallMemberWalletMapper.selectWalletByMemberId(mallMemberUp.getId()); | 
 |  |  |             BigDecimal totalScore = mallMemberWallet.getTotalScore(); | 
 |  |  |             if(totalScore.compareTo(sharePerkAmount) < 0){ | 
 |  |  |                 sharePerkAmount = totalScore; | 
 |  |  |             } | 
 |  |  |             if(BigDecimal.ZERO.compareTo(sharePerkAmount) < 0){ | 
 |  |  |                 //减少补贴额度 | 
 |  |  |                 mallMemberWalletMapper.reduceTotalScoreById(sharePerkAmount, mallMemberWallet.getId()); | 
 |  |  |  | 
 |  |  |                 reduceStar(mallMemberUp.getId(),sharePerkAmount); | 
 |  |  |  | 
 |  |  |                 mallMemberWalletMapper.addBalanceById(sharePerkAmount, mallMemberWallet.getId()); | 
 |  |  |  | 
 |  |  |                 mallMoneyFlowService.addMoneyFlow( | 
 |  |  |                         mallMemberUp.getId(), | 
 |  |  |                         sharePerkAmount, | 
 |  |  |                         MoneyFlowTypeEnum.DYNAMIC_ACHIEVE.getValue(), | 
 |  |  |                         mallOrderInfo.getOrderNo(), | 
 |  |  |                         "直推奖", | 
 |  |  |                         "补贴额度:"+totalScore, | 
 |  |  |                         memberId, | 
 |  |  |                         2, | 
 |  |  |                         FlowTypeEnum.BALANCE.getValue(), | 
 |  |  |                         1); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         /** | 
 |  |  |          * 星级奖励 | 
 |  |  |          *  从最顶级级别的合伙人开始补贴 | 
 |  |  |          *      补贴完,把已经补贴的合伙人加入下一个级别 | 
 |  |  |          */ | 
 |  |  |         List<MallMember> sevenLevelRecord = getStarRecord(null,  MemberLevelEnum.SEVEN_LEVEL.name(), amount, mallOrderInfo.getOrderNo(), memberId,MoneyFlowTypeEnum.STAR_PERK_SEVEN.getValue()); | 
 |  |  |         List<MallMember> sixLevelRecord = getStarRecord(sevenLevelRecord,  MemberLevelEnum.SIX_LEVEL.name(), amount, mallOrderInfo.getOrderNo(), memberId,MoneyFlowTypeEnum.STAR_PERK_SIX.getValue()); | 
 |  |  |         List<MallMember> fifthLevelRecord = getStarRecord(sixLevelRecord,  MemberLevelEnum.FIFTH_LEVEL.name(), amount, mallOrderInfo.getOrderNo(), memberId,MoneyFlowTypeEnum.STAR_PERK_FIVE.getValue()); | 
 |  |  |         List<MallMember> fourLevelRecord = getStarRecord(fifthLevelRecord,  MemberLevelEnum.FOUR_LEVEL.name(), amount, mallOrderInfo.getOrderNo(), memberId,MoneyFlowTypeEnum.STAR_PERK_FOUR.getValue()); | 
 |  |  |         List<MallMember> thirdLevelRecord = getStarRecord(fourLevelRecord,  MemberLevelEnum.THIRD_LEVEL.name(), amount, mallOrderInfo.getOrderNo(), memberId,MoneyFlowTypeEnum.STAR_PERK_THREE.getValue()); | 
 |  |  |         List<MallMember> secondLevelRecord = getStarRecord(thirdLevelRecord,  MemberLevelEnum.SECOND_LEVEL.name(), amount, mallOrderInfo.getOrderNo(), memberId,MoneyFlowTypeEnum.STAR_PERK_TWO.getValue()); | 
 |  |  |  | 
 |  |  |         /** | 
 |  |  |          * 团队补贴 | 
 |  |  |          */ | 
 |  |  |         //团队补贴百分比 | 
 |  |  |         DataDictionaryCustom teamPerkDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( | 
 |  |  |                 DataDictionaryEnum.TEAM_PERK.getType(), | 
 |  |  |                 DataDictionaryEnum.TEAM_PERK.getCode()); | 
 |  |  |         String teamPerk = ObjectUtil.isEmpty(teamPerkDic.getValue()) ? "0" : teamPerkDic.getValue(); | 
 |  |  |         BigDecimal teamPerkPercent = new BigDecimal(teamPerk).abs().divide(new BigDecimal(100)); | 
 |  |  |         //分享补贴金额 | 
 |  |  |         BigDecimal teamPerkAmount = amount.multiply(teamPerkPercent); | 
 |  |  |         //团队补贴对象 | 
 |  |  |         List<MallMember> mallMemberTeamPerkList = mallMemberTeamPerkListInfo(memberId); | 
 |  |  |         if(CollUtil.isNotEmpty(mallMemberTeamPerkList)){ | 
 |  |  |             List<Long> mallMemberTeamPerkIds = mallMemberTeamPerkList.stream().map(MallMember::getId).collect(Collectors.toList()); | 
 |  |  |             List<MallMemberWallet> mallMemberWallets = mallMemberWalletMapper.selectMemberWalletsByIds(mallMemberTeamPerkIds); | 
 |  |  |             flowTotalScoreBalance( | 
 |  |  |                     mallMemberWallets, | 
 |  |  |                     teamPerkAmount, | 
 |  |  |                     MoneyFlowTypeEnum.TEAM_PERK.getValue(), | 
 |  |  |                     mallOrderInfo.getOrderNo(), | 
 |  |  |                     memberId | 
 |  |  |             ); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         long end = System.currentTimeMillis(); | 
 |  |  |         log.info("============订单:{},时间:{}===========",mallOrderInfo.getOrderNo(),(end - start)/1000); | 
 |  |  |         MallMqRecord mallMqRecord = mallMqRecordMapper.selectByOrderId(orderId); | 
 |  |  |         if(ObjectUtil.isNotEmpty(mallMqRecord)){ | 
 |  |  |             mallMqRecord.setState(1); | 
 |  |  |             mallMqRecordMapper.updateById(mallMqRecord); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 下单人所在团队里面的已经存在的各个等级的会员集合里面的第一个会员获取2% | 
 |  |  |      */ | 
 |  |  |     public List<MallMember> mallMemberTeamPerkListInfo(Long memberId){ | 
 |  |  |         List<MallMember> mallMemberTeamPerk = new ArrayList<>(); | 
 |  |  |         MallMember mallMember = memberMapper.selectById(memberId); | 
 |  |  |         List<String> ids = StrUtil.split(mallMember.getReferrerIds(), ','); | 
 |  |  |         if(CollUtil.isNotEmpty(ids)){ | 
 |  |  |             List<MallMember> mallMembers = memberMapper.selectByInviteIds(ids); | 
 |  |  |             /** | 
 |  |  |              * 根据等级分组,获取对应的<级别,会员数组>map | 
 |  |  |              */ | 
 |  |  |             Map<String, List<MallMember>> collect = mallMembers.stream().collect(Collectors.groupingBy(MallMember::getLevel)); | 
 |  |  |             Set<String> set = collect.keySet(); // 得到所有key的集合 | 
 |  |  |             for (String key : set) { | 
 |  |  |                 /** | 
 |  |  |                  * 团队补贴从二星开始 | 
 |  |  |                  */ | 
 |  |  |                 int compareLevel = MemberLevelEnum.SECOND_LEVEL.compareLevel(key, MemberLevelEnum.SECOND_LEVEL.getType()); | 
 |  |  |                 if(compareLevel > 0){ | 
 |  |  |                     List<MallMember> value = collect.get(key); | 
 |  |  |                     mallMemberTeamPerk.add(value.get(0)); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         return mallMemberTeamPerk; | 
 |  |  |     } | 
 |  |  |     /** | 
 |  |  |      * 递归获取对应的团队补贴对象 | 
 |  |  |      * 下单 | 
 |  |  |      *  下单人的上级集合里面每个等级的第一个会员 | 
 |  |  |      * @param memberId | 
 |  |  |      * @param mallMemberTeamPerk | 
 |  |  |      * @return | 
 |  |  |      */ | 
 |  |  |     public List<MallMember> mallMemberTeamPerkList(Long memberId,List<MallMember> mallMemberTeamPerk){ | 
 |  |  |         MallMember mallMember = memberMapper.selectById(memberId); | 
 |  |  |         if(ObjectUtil.isEmpty(mallMember.getReferrerId())){ | 
 |  |  |             return mallMemberTeamPerk; | 
 |  |  |         } | 
 |  |  |         String referrerId = mallMember.getReferrerId(); | 
 |  |  |         MallMember mallMemberParent = memberMapper.selectInfoByInviteId(referrerId); | 
 |  |  |  | 
 |  |  |         if(MemberLevelEnum.SECOND_LEVEL.compareLevel(mallMemberParent.getLevel(),mallMember.getLevel()) > 0){ | 
 |  |  |             mallMemberTeamPerk.add(mallMemberParent); | 
 |  |  |         } | 
 |  |  |         if(!referrerId.equals(mallMember.getInviteId())){ | 
 |  |  |             mallMemberTeamPerkList(mallMemberParent.getId(),mallMemberTeamPerk); | 
 |  |  |         } | 
 |  |  |         return mallMemberTeamPerk; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 星级奖励 | 
 |  |  |      * @param mallMembersOlds 高一级别的用户 | 
 |  |  |      * @param LevelParam    当前级别 | 
 |  |  |      * @param amount    补贴金额的基数 | 
 |  |  |      * @param orderNo   订单编号 | 
 |  |  |      * @param memberId  会员id | 
 |  |  |      * @return | 
 |  |  |      */ | 
 |  |  |     public List<MallMember> getStarRecord(List<MallMember> mallMembersOlds,String LevelParam,BigDecimal amount,String orderNo,Long memberId,int starPerkType){ | 
 |  |  |  | 
 |  |  |         //根据用户的level获取用户 | 
 |  |  |         List<MallMember> mallMemberStars = memberMapper.selectMemberWithLevel(LevelParam); | 
 |  |  |         if(CollUtil.isNotEmpty(mallMembersOlds)){ | 
 |  |  |             for(MallMember mallMemberOld : mallMembersOlds){ | 
 |  |  |                 mallMemberStars.add(mallMemberOld); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         if(CollUtil.isNotEmpty(mallMemberStars)){ | 
 |  |  |  | 
 |  |  |             List<Long> mallMemberStarIds = mallMemberStars.stream().map(MallMember::getId).collect(Collectors.toList()); | 
 |  |  |             //排除掉本身 | 
 |  |  |             mallMemberStarIds.remove(memberId); | 
 |  |  |             if(CollUtil.isEmpty(mallMemberStarIds)){ | 
 |  |  |                 return mallMemberStars; | 
 |  |  |             } | 
 |  |  |             //当前等级的总贡献点 | 
 |  |  |             List<MallMemberWallet> mallMemberWallets = mallMemberWalletMapper.selectMemberWalletsByIds(mallMemberStarIds); | 
 |  |  |             Integer starSum = mallMemberWallets.stream().mapToInt(MallMemberWallet::getStar).sum(); | 
 |  |  |             if(starSum <= 0){ | 
 |  |  |                 return mallMemberStars; | 
 |  |  |             } | 
 |  |  |             //星级补贴比例 | 
 |  |  |             DataDictionaryCustom starPerkDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( | 
 |  |  |                     "AGENT_LEVEL_REQUIRE", | 
 |  |  |                     LevelParam); | 
 |  |  |             String starPerkStr = starPerkDic.getValue(); | 
 |  |  |             AgentInfo agentInfo = JSONObject.parseObject(starPerkStr, AgentInfo.class); | 
 |  |  |             BigDecimal profitProp = agentInfo.getProfitProp().abs().divide(new BigDecimal(100)); | 
 |  |  |             //当前等级的星级补贴 | 
 |  |  |             BigDecimal starPerkAmountSum = amount.multiply(profitProp); | 
 |  |  |             //当前等级的每一个贡献点的补贴金额 | 
 |  |  |             BigDecimal starPerkAmountAva = starPerkAmountSum.divide(new BigDecimal(starSum),BigDecimal.ROUND_DOWN).setScale(2, BigDecimal.ROUND_DOWN); | 
 |  |  |             /** | 
 |  |  |              * 给当前等级的每个用户发放星级奖励 | 
 |  |  |              * 生成星级奖励的流水 | 
 |  |  |              */ | 
 |  |  |             if(CollUtil.isNotEmpty(mallMemberWallets)){ | 
 |  |  |                 //给当前等级的每个用户发放星级奖励 | 
 |  |  |                 int count = 0; | 
 |  |  |                 List<Map<String,Object>> result = new ArrayList<>(); | 
 |  |  |                 List<Map<String,Object>> resultReduce = new ArrayList<>(); | 
 |  |  |                 List<MallMoneyFlow> mallMoneyFlows = new ArrayList<>(); | 
 |  |  |                 for(MallMemberWallet mallMemberWallet : mallMemberWallets){ | 
 |  |  |                     Map<String,Object> hashMap = new HashMap<>(); | 
 |  |  |                     Integer starCnt = mallMemberWallet.getStar(); | 
 |  |  |                     //当前用户的星级奖励 | 
 |  |  |                     BigDecimal starPerkAmount = starPerkAmountAva | 
 |  |  |                             .multiply(new BigDecimal(starCnt)).abs().setScale(2, BigDecimal.ROUND_DOWN); | 
 |  |  |                     BigDecimal totalScorePerk = mallMemberWallet.getTotalScore(); | 
 |  |  |                     if(totalScorePerk.compareTo(starPerkAmount) < 0){ | 
 |  |  |                         starPerkAmount = totalScorePerk; | 
 |  |  |                     } | 
 |  |  |                     if(BigDecimal.ZERO.compareTo(starPerkAmount) < 0){ | 
 |  |  |                         hashMap.put("id",mallMemberWallet.getId()); | 
 |  |  |                         hashMap.put("starPerkAmount",starPerkAmount); | 
 |  |  |                         result.add(hashMap); | 
 |  |  |                         resultReduce.add(hashMap); | 
 |  |  |                         //生成星级奖励的流水对象 | 
 |  |  |                         MallMoneyFlow mallMoneyFlow = new MallMoneyFlow(); | 
 |  |  |                         mallMoneyFlow.setMemberId(mallMemberWallet.getMemberId()); | 
 |  |  |                         mallMoneyFlow.setAmount(starPerkAmount); | 
 |  |  |                         mallMoneyFlow.setType(starPerkType); | 
 |  |  |                         mallMoneyFlow.setOrderNo(orderNo); | 
 |  |  |                         mallMoneyFlow.setRtMemberId(memberId); | 
 |  |  |                         mallMoneyFlow.setStatus(2); | 
 |  |  |                         mallMoneyFlow.setRemark("补贴额度:"+mallMemberWallet.getTotalScore()); | 
 |  |  |                         mallMoneyFlow.setFlowType(FlowTypeEnum.BALANCE.getValue()); | 
 |  |  |                         mallMoneyFlows.add(mallMoneyFlow); | 
 |  |  |  | 
 |  |  |                         reduceStar(mallMemberWallet.getMemberId(),starPerkAmount); | 
 |  |  |                     } | 
 |  |  |                     count = count + 1; | 
 |  |  |                     if (count % 1000 == 0 || count == mallMemberWallets.size()) { | 
 |  |  |                         if(CollUtil.isNotEmpty(result)){ | 
 |  |  |                             int resultCount = mallMemberWalletMapper.updateStarByList(result); | 
 |  |  |                             if(resultCount>0){ | 
 |  |  |                                 log.info("============余额新增============第{}条数据===========",resultCount); | 
 |  |  |                             } | 
 |  |  |                             //每更新完一批数据,在result内进行删除操作。 | 
 |  |  |                             result.clear(); | 
 |  |  |  | 
 |  |  |                             int resultReduceCount = mallMemberWalletMapper.updateTotalScoreByList(resultReduce); | 
 |  |  |                             if(resultReduceCount>0){ | 
 |  |  |                                 log.info("============额度减少============第{}条数据===========",resultReduceCount); | 
 |  |  |                             } | 
 |  |  |                             //每更新完一批数据,在result内进行删除操作。 | 
 |  |  |                             resultReduce.clear(); | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |                 if(CollUtil.isNotEmpty(mallMoneyFlows)){ | 
 |  |  |                     SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH,false); | 
 |  |  |                     MallMoneyFlowMapper mallMoneyFlowMapper = sqlSession.getMapper(MallMoneyFlowMapper.class); | 
 |  |  |  | 
 |  |  |                     for(int i = 1; i <= mallMoneyFlows.size(); i++){ | 
 |  |  |                         mallMoneyFlowMapper.insertMoneyFlow(mallMoneyFlows.get(i-1)); | 
 |  |  |                         if (i % 1000 == 0 || i == mallMoneyFlows.size()) { | 
 |  |  |                             log.info("============插入流水============第{}条数据===========",mallMoneyFlows.size()); | 
 |  |  |                             sqlSession.commit(); | 
 |  |  |                             sqlSession.clearCache(); | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                     sqlSession.close(); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         return mallMemberStars; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 统一处理补贴,流水,余额 | 
 |  |  |      *      增加的余额是一样的 | 
 |  |  |      * @param mallMemberWallets | 
 |  |  |      * @param amount | 
 |  |  |      * @param flowType | 
 |  |  |      * @param orderNo | 
 |  |  |      * @param memberId | 
 |  |  |      */ | 
 |  |  |     @Override | 
 |  |  |     public void flowTotalScoreBalance(List<MallMemberWallet> mallMemberWallets,BigDecimal amount,int flowType,String orderNo,Long memberId){ | 
 |  |  |         //给当前等级的每个用户发放星级奖励 | 
 |  |  |         int count = 0; | 
 |  |  |         List<Map<String,Object>> result = new ArrayList<>(); | 
 |  |  |         List<Map<String,Object>> resultReduce = new ArrayList<>(); | 
 |  |  |         List<MallMoneyFlow> mallMoneyFlows = new ArrayList<>(); | 
 |  |  |         for(MallMemberWallet mallMemberWallet : mallMemberWallets){ | 
 |  |  |             Map<String,Object> hashMap = new HashMap<>(); | 
 |  |  |             BigDecimal totalScorePerk = mallMemberWallet.getTotalScore(); | 
 |  |  |             if(totalScorePerk.compareTo(amount) < 0){ | 
 |  |  |                 amount = totalScorePerk; | 
 |  |  |             } | 
 |  |  |             if(BigDecimal.ZERO.compareTo(amount) < 0){ | 
 |  |  |                 hashMap.put("id",mallMemberWallet.getId()); | 
 |  |  |                 hashMap.put("starPerkAmount",amount); | 
 |  |  |                 result.add(hashMap); | 
 |  |  |                 resultReduce.add(hashMap); | 
 |  |  |                 //生成星级奖励的流水对象 | 
 |  |  |                 MallMoneyFlow mallMoneyFlow = new MallMoneyFlow(); | 
 |  |  |                 mallMoneyFlow.setMemberId(mallMemberWallet.getMemberId()); | 
 |  |  |                 mallMoneyFlow.setAmount(amount); | 
 |  |  |                 mallMoneyFlow.setType(flowType); | 
 |  |  |                 mallMoneyFlow.setOrderNo(orderNo); | 
 |  |  |                 mallMoneyFlow.setRtMemberId(memberId); | 
 |  |  |                 mallMoneyFlow.setStatus(2); | 
 |  |  |                 mallMoneyFlow.setRemark("补贴额度:"+mallMemberWallet.getTotalScore()); | 
 |  |  |                 mallMoneyFlow.setFlowType(FlowTypeEnum.BALANCE.getValue()); | 
 |  |  |                 mallMoneyFlows.add(mallMoneyFlow); | 
 |  |  |  | 
 |  |  |                 reduceStar(mallMemberWallet.getMemberId(),amount); | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |             count = count + 1; | 
 |  |  |             if (count % 1000 == 0 || count == mallMemberWallets.size()) { | 
 |  |  |                 if(CollUtil.isNotEmpty(result)){ | 
 |  |  |                     int resultCount = mallMemberWalletMapper.updateStarByList(result); | 
 |  |  |                     if(resultCount>0){ | 
 |  |  |                         log.info("============余额新增============第{}条数据===========",resultCount); | 
 |  |  |                     } | 
 |  |  |                     //每更新完一批数据,在result内进行删除操作。 | 
 |  |  |                     result.clear(); | 
 |  |  |  | 
 |  |  |                     int resultReduceCount = mallMemberWalletMapper.updateTotalScoreByList(resultReduce); | 
 |  |  |                     if(resultReduceCount>0){ | 
 |  |  |                         log.info("============额度减少============第{}条数据===========",resultReduceCount); | 
 |  |  |                     } | 
 |  |  |                     //每更新完一批数据,在result内进行删除操作。 | 
 |  |  |                     resultReduce.clear(); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         if(CollUtil.isNotEmpty(mallMoneyFlows)){ | 
 |  |  |             SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH,false); | 
 |  |  |             MallMoneyFlowMapper mallMoneyFlowMapper = sqlSession.getMapper(MallMoneyFlowMapper.class); | 
 |  |  |  | 
 |  |  |             for(int i = 1; i <= mallMoneyFlows.size(); i++){ | 
 |  |  |                 mallMoneyFlowMapper.insertMoneyFlow(mallMoneyFlows.get(i-1)); | 
 |  |  |                 if (i % 1000 == 0 || i == mallMoneyFlows.size()) { | 
 |  |  |                     log.info("============插入流水============第{}条数据===========",mallMoneyFlows.size()); | 
 |  |  |                     sqlSession.commit(); | 
 |  |  |                     sqlSession.clearCache(); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             sqlSession.close(); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public void reduceStar(Long memberId,BigDecimal totalScore) { | 
 |  |  |         /** | 
 |  |  |          *获取用户的全部未用完的补贴额度流水 | 
 |  |  |          */ | 
 |  |  |         MallMemberWallet mallMemberWallet = mallMemberWalletMapper.selectWalletByMemberId(memberId); | 
 |  |  |         List<MallMoneyFlow> mallMoneyFlows = mallMoneyFlowMapper.selectMoneyFlowByMemberIdAndIsRetrun(memberId,2); | 
 |  |  |         //如果补贴额度全部用完则更新用户的贡献点为零 | 
 |  |  |         if(CollUtil.isEmpty(mallMoneyFlows)){ | 
 |  |  |             mallMemberWalletMapper.reduceStarByMemberId(mallMemberWallet.getStar(), memberId); | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |         for(MallMoneyFlow mallMoneyFlow : mallMoneyFlows){ | 
 |  |  |             String remark = mallMoneyFlow.getRemark(); | 
 |  |  |             BigDecimal remarkNum = new BigDecimal(remark); | 
 |  |  |             //如果补贴额度小于记录的剩余补贴额度 | 
 |  |  |             if(totalScore.compareTo(remarkNum) < 0){ | 
 |  |  |                 remarkNum = remarkNum.subtract(totalScore).setScale(2,BigDecimal.ROUND_DOWN); | 
 |  |  |                 mallMoneyFlowMapper.updateRemarkById(remarkNum.toString(),mallMoneyFlow.getId()); | 
 |  |  |                 break; | 
 |  |  |             } | 
 |  |  |             //如果补贴额度等于等于记录的剩余补贴额度 | 
 |  |  |             if(totalScore.compareTo(remarkNum) == 0){ | 
 |  |  |                 remarkNum = remarkNum.subtract(totalScore).setScale(2,BigDecimal.ROUND_DOWN); | 
 |  |  |                 mallMoneyFlowMapper.updateRemarkAndIsReturnById(remarkNum.toString(),mallMoneyFlow.getId()); | 
 |  |  |  | 
 |  |  |                 //减少用户的贡献点 | 
 |  |  |                 String orderNo = mallMoneyFlow.getOrderNo(); | 
 |  |  |                 MallMoneyFlow mallMoneyFlowStar = mallMoneyFlowMapper.selectByOrderNoAndMemberId(orderNo,memberId,2); | 
 |  |  |                 BigDecimal amount = mallMoneyFlowStar.getAmount(); | 
 |  |  |                 mallMemberWalletMapper.reduceStarByMemberId(amount.intValue(), memberId); | 
 |  |  |                 //更新记录的返利状态为已返利 | 
 |  |  |                 mallMoneyFlowMapper.updateRemarkAndIsReturnById("0",mallMoneyFlowStar.getId()); | 
 |  |  |                 break; | 
 |  |  |             } | 
 |  |  |             //如果补贴额度大于记录的剩余补贴额度 | 
 |  |  |             if(totalScore.compareTo(remarkNum) > 0){ | 
 |  |  |                 mallMoneyFlowMapper.updateRemarkAndIsReturnById("0",mallMoneyFlow.getId()); | 
 |  |  |  | 
 |  |  |                 //减少用户的贡献点 | 
 |  |  |                 String orderNo = mallMoneyFlow.getOrderNo(); | 
 |  |  |                 MallMoneyFlow mallMoneyFlowStar = mallMoneyFlowMapper.selectByOrderNoAndMemberId(orderNo,memberId,2); | 
 |  |  |                 BigDecimal amount = mallMoneyFlowStar.getAmount(); | 
 |  |  |                 mallMemberWalletMapper.reduceStarByMemberId(amount.intValue(), memberId); | 
 |  |  |                 //更新记录的返利状态为已返利 | 
 |  |  |                 mallMoneyFlowMapper.updateRemarkAndIsReturnById("0",mallMoneyFlowStar.getId()); | 
 |  |  |                 totalScore = totalScore.subtract(remarkNum); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  | } |