package cc.mrbird.febs.mall.service.impl; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.common.enumerates.DataDictionaryEnum; import cc.mrbird.febs.common.enumerates.FlowTypeEnum; import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum; import cc.mrbird.febs.common.enumerates.ScoreFlowTypeEnum; import cc.mrbird.febs.common.exception.FebsException; import cc.mrbird.febs.common.utils.LoginUserUtil; import cc.mrbird.febs.common.utils.MallUtils; import cc.mrbird.febs.mall.dto.ScoreSettingDto; import cc.mrbird.febs.mall.dto.signActivity.ApiSignDataDto; import cc.mrbird.febs.mall.dto.signActivity.ApiSignListDto; import cc.mrbird.febs.mall.entity.*; import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper; import cc.mrbird.febs.mall.mapper.MallMemberWalletMapper; import cc.mrbird.febs.mall.mapper.MallScoreSignRecordMapper; import cc.mrbird.febs.mall.service.IApiMallMemberWalletService; import cc.mrbird.febs.mall.service.IMallMoneyFlowService; import cc.mrbird.febs.mall.service.IScoreService; import cc.mrbird.febs.mall.vo.ApiActivityInfoVo; import cc.mrbird.febs.mall.vo.ScoreSignVo; import cc.mrbird.febs.mall.vo.signActivity.ApiGetRunDateVo; import cc.mrbird.febs.mall.vo.signActivity.ApiSignListVo; import cc.mrbird.febs.mall.vo.signActivity.ApiSignVo; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUnit; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * @author wzy * @date 2022-05-09 **/ @Slf4j @Service @RequiredArgsConstructor public class ScoreServiceImpl implements IScoreService { private final MallMemberWalletMapper mallMemberWalletMapper; private final DataDictionaryCustomMapper dataDictionaryCustomMapper; private final MallScoreSignRecordMapper mallScoreSignRecordMapper; private final IMallMoneyFlowService mallMoneyFlowService; private final IApiMallMemberWalletService walletService; @Override public ScoreSignVo scoreSign() { MallMember member = LoginUserUtil.getLoginUser(); MallMemberWallet wallet = mallMemberWalletMapper.selectWalletByMemberId(member.getId()); MallScoreSignRecord mallScoreSignRecord = mallScoreSignRecordMapper.selectRecentSignRecord(member.getId()); ScoreSignVo scoreSign = new ScoreSignVo(); scoreSign.setMineScore(wallet.getPrizeScore().intValue()); if (mallScoreSignRecord == null) { scoreSign.setHasSignDays(0); } else { mallScoreSignRecord = judgeScoreIsContinuity(mallScoreSignRecord); scoreSign.setHasSignDays(mallScoreSignRecord.getTotalCnt()); } DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.SCORE_SIGN_SETTING.getType(), DataDictionaryEnum.SCORE_SIGN_SETTING.getCode()); if (dic != null) { scoreSign.setSetting(JSONObject.parseObject(dic.getValue(), ScoreSettingDto.class)); } return scoreSign; } @Override public List signData(ApiSignDataDto dto) { Long memberId = LoginUserUtil.getLoginUser().getId(); DateTime dateTime = DateUtil.parseDate(dto.getDateStr()); DateTime startTime = DateUtil.beginOfMonth(dateTime); DateTime endTime = DateUtil.endOfMonth(dateTime); long between = DateUtil.between(startTime, endTime, DateUnit.DAY); List apiGetRunDateVos = generateDateList(startTime, between); List typeList = Arrays.asList(ScoreFlowTypeEnum.SIGN_SCORE.getValue(), ScoreFlowTypeEnum.SIGN_EXPERIENCE.getValue()); List mallMoneyFlows = mallMoneyFlowService.getBaseMapper().selectList( new LambdaQueryWrapper() .eq(MallMoneyFlow::getMemberId, memberId) .in(MallMoneyFlow::getType, typeList) .ge(MallMoneyFlow::getCreatedTime, startTime) .le(MallMoneyFlow::getCreatedTime, endTime) ); if(CollUtil.isNotEmpty(mallMoneyFlows)){ calculateProfits(apiGetRunDateVos,mallMoneyFlows); } return apiGetRunDateVos; } /** * 生成日期列表 * * @param startDate 开始日期 * @param days 从开始日期算起的天数 * @return 一个包含日期信息的ApiGetRunDateVo对象列表 */ private List generateDateList(DateTime startDate, long days) { // 使用IntStream生成从0到days(包含days)的整数流,表示每一天 return IntStream.range(0, (int) days + 1) // 将每个整数映射为一个ApiGetRunDateVo对象 .mapToObj(i -> { // 创建ApiGetRunDateVo对象 ApiGetRunDateVo apiGetRunDateVo = new ApiGetRunDateVo(); // 计算日期:从起始日期开始偏移i天 DateTime dateTime = DateUtil.offsetDay(startDate, i); // 格式化日期为"yyyy-MM-dd"字符串,并设置到对象中 apiGetRunDateVo.setDateStr(DateUtil.format(dateTime, "yyyy-MM-dd")); // 初始化碳积分为0 apiGetRunDateVo.setScore(BigDecimal.ZERO); // 返回构建好的对象 return apiGetRunDateVo; }) // 将流中的对象收集到一个列表中 .collect(Collectors.toList()); } /** * 计算每日累计碳积分 * * @param dateList 日期列表,包含了每日的碳积分信息 * @param mallMoneyFlows 商城资金流列表,包含了每笔碳积分信息 */ private void calculateProfits(List dateList, List mallMoneyFlows) { // 将日期列表转换为映射,以便通过日期快速访问每日碳积分信息 Map dateMap = dateList.stream() .collect(Collectors.toMap(ApiGetRunDateVo::getDateStr, vo -> vo)); // 遍历mallMoneyFlows for (MallMoneyFlow item : mallMoneyFlows) { // 格式化当前项的创建时间,提取日期 String date = DateUtil.format(item.getCreatedTime(), "yyyy-MM-dd"); // 从日期映射中获取对应的每日碳积分信息 ApiGetRunDateVo apiGetRunDateVo = dateMap.get(date); // 如果找到了对应的每日碳积分信息 if (apiGetRunDateVo != null) { // 获取当前日期的碳积分 BigDecimal score = apiGetRunDateVo.getScore(); // 计算新的碳积分,将碳积分与碳积分相加,并向下取整到个位数 BigDecimal profit = score.add(item.getAmount().abs()).setScale(0,BigDecimal.ROUND_DOWN); // 更新每日碳积分信息的利润值 apiGetRunDateVo.setScore(profit); } } } @Override public MallScoreSignRecord judgeScoreIsContinuity(MallScoreSignRecord mallScoreSignRecord) { if (mallScoreSignRecord.getSignTime() == null) { return mallScoreSignRecord; } // 若最新签到日期,与当天相差大于一天,则更新数据库(避免定时器更新失败) if (DateUtil.betweenDay(mallScoreSignRecord.getSignTime(), new Date(), true) > 1) { mallScoreSignRecord.setTotalCnt(0); mallScoreSignRecordMapper.updateById(mallScoreSignRecord); } return mallScoreSignRecord; } @Override public FebsResponse signList(ApiSignListDto dto) { Long memberId = LoginUserUtil.getLoginUser().getId(); ArrayList apiSignListVos = new ArrayList<>(); // 创建分页对象,传入当前页和每页大小 Page page = new Page<>(dto.getPageNow(), dto.getPageSize()); LambdaQueryWrapper mallMoneyFlowLambdaQueryWrapper = new LambdaQueryWrapper<>(); List integers = Arrays.asList(ScoreFlowTypeEnum.SIGN_SCORE.getValue(), ScoreFlowTypeEnum.SIGN_EXPERIENCE.getValue()); mallMoneyFlowLambdaQueryWrapper .select(MallMoneyFlow::getCreatedTime, MallMoneyFlow::getRemark) .eq(MallMoneyFlow::getMemberId, memberId) .in(MallMoneyFlow::getType, integers) .orderByDesc(MallMoneyFlow::getId) ; Page mallMoneyFlowPage = mallMoneyFlowService.getBaseMapper().selectPage(page, mallMoneyFlowLambdaQueryWrapper); if(CollUtil.isNotEmpty(mallMoneyFlowPage.getRecords())){ mallMoneyFlowPage.getRecords().forEach(item -> { ApiSignListVo apiSignListVo = new ApiSignListVo(); apiSignListVo.setRemark(item.getRemark()); apiSignListVo.setCreatedTime(item.getCreatedTime()); apiSignListVos.add(apiSignListVo); }); } return new FebsResponse().success().data(apiSignListVos); } @Override @Transactional(rollbackFor = Exception.class) public FebsResponse sign() { MallMember member = LoginUserUtil.getLoginUser(); DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.SCORE_SIGN_SETTING.getType(), DataDictionaryEnum.SCORE_SIGN_SETTING.getCode()); if (dic == null) { throw new FebsException("暂未设置积分"); } MallScoreSignRecord mallScoreSignRecord = mallScoreSignRecordMapper.selectRecentSignRecord(member.getId()); if (mallScoreSignRecord == null) { mallScoreSignRecord = new MallScoreSignRecord(); } if (mallScoreSignRecord.getSignTime() != null && DateUtil.betweenDay(mallScoreSignRecord.getSignTime(), new Date(), true) == 0) { throw new FebsException("今天已签到"); } mallScoreSignRecord = judgeScoreIsContinuity(mallScoreSignRecord); ScoreSettingDto scoreSetting = JSONObject.parseObject(dic.getValue(),ScoreSettingDto.class); int days = mallScoreSignRecord.getTotalCnt() == null ? 1 : mallScoreSignRecord.getTotalCnt() + 1; switch (days) { case 1: if (scoreSetting.getSignInOne() == null) { throw new FebsException("积分未设置"); } mallScoreSignRecord.setScore(scoreSetting.getSignInOne()); break; case 2: if (scoreSetting.getSignInTwo() == null) { throw new FebsException("积分未设置"); } mallScoreSignRecord.setScore(scoreSetting.getSignInTwo()); break; case 3: if (scoreSetting.getSignInThree() == null) { throw new FebsException("积分未设置"); } mallScoreSignRecord.setScore(scoreSetting.getSignInThree()); break; case 4: if (scoreSetting.getSignInFour() == null) { throw new FebsException("积分未设置"); } mallScoreSignRecord.setScore(scoreSetting.getSignInFour()); break; case 5: if (scoreSetting.getSignInFive() == null) { throw new FebsException("积分未设置"); } mallScoreSignRecord.setScore(scoreSetting.getSignInFive()); break; case 6: if (scoreSetting.getSignInSix() == null) { throw new FebsException("积分未设置"); } mallScoreSignRecord.setScore(scoreSetting.getSignInSix()); break; case 7: if (scoreSetting.getSignInSeven() == null) { throw new FebsException("积分未设置"); } mallScoreSignRecord.setScore(scoreSetting.getSignInSeven()); break; default: if (scoreSetting.getSignInOne() == null) { throw new FebsException("积分未设置"); } if(days > 7){ mallScoreSignRecord.setScore(scoreSetting.getSignInSeven()); }else{ mallScoreSignRecord.setScore(scoreSetting.getSignInOne()); } break; } mallScoreSignRecord.setMemberId(member.getId()); mallScoreSignRecord.setTotalCnt(days); mallScoreSignRecord.setSignTime(new Date()); mallScoreSignRecordMapper.insert(mallScoreSignRecord); /** * 1:会员经验 2:会员积分 */ Integer mostSignIn = scoreSetting.getMostSignIn(); BigDecimal amount = BigDecimal.valueOf(mallScoreSignRecord.getScore()); if(mostSignIn == 1){ walletService.add(amount, member.getId(), "score"); mallMoneyFlowService.addMoneyFlow( member.getId(), amount, ScoreFlowTypeEnum.SIGN_EXPERIENCE.getValue(), MallUtils.getOrderNum("s"), FlowTypeEnum.SCORE.getValue(), StrUtil.format(ScoreFlowTypeEnum.SIGN_EXPERIENCE.getDesc(),amount), 2); } if(mostSignIn == 2){ walletService.add(amount, member.getId(), "prizeScore"); mallMoneyFlowService.addMoneyFlow( member.getId(), amount, ScoreFlowTypeEnum.SIGN_SCORE.getValue(), MallUtils.getOrderNum("s"), FlowTypeEnum.PRIZE_SCORE.getValue(), StrUtil.format(ScoreFlowTypeEnum.SIGN_SCORE.getDesc(),amount), 2); } ApiSignVo apiSignVo = new ApiSignVo(); apiSignVo.setMineScore(mallScoreSignRecord.getScore()); apiSignVo.setMostSignIn(mostSignIn); return new FebsResponse().success().data(apiSignVo); } }