新增家族宝箱功能

This commit is contained in:
tianfeng 2025-12-24 14:55:15 +08:00
parent b1a8bc5f54
commit 5f9b076a16
23 changed files with 821 additions and 0 deletions

View File

@ -722,6 +722,16 @@ public enum GoldOrigin {
* 房间红包
*/
ROOM_RED_PACKET("Room red packet"),
/**
* 家族宝箱贡献
*/
FAMILY_BOX_CONTRIBUTE("Family box contribute"),
/**
* 家族宝箱奖励
*/
FAMILY_BOX_REWARD("Family box reward"),
;
private final String desc;

View File

@ -9,6 +9,7 @@ import com.red.circle.other.app.dto.clientobject.family.FamilyCreateRulesCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyLeaderboardCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyLevelParentCacheCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyListCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyBoxStatusCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyMemberCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyMsgListCO;
import com.red.circle.other.app.dto.clientobject.family.MyFamilyApplyCO;
@ -18,6 +19,7 @@ import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO;
import com.red.circle.other.app.dto.cmd.family.ApplyJoinFamilyCmd;
import com.red.circle.other.app.dto.cmd.family.CancelFamilyApplyCmd;
import com.red.circle.other.app.dto.cmd.family.ReapplyFamilyCmd;
import com.red.circle.other.app.dto.cmd.family.FamilyBoxClaimCmd;
import com.red.circle.other.app.dto.cmd.family.FamilyAdminQueryCmd;
import com.red.circle.other.app.dto.cmd.family.FamilyBaseInfoQueryCmd;
import com.red.circle.other.app.dto.cmd.family.FamilyCreateCmd;
@ -228,6 +230,30 @@ public class FamilyRestController extends BaseController {
familyService.userExit(cmd);
}
/**
* 投入宝箱金币.
*/
@PostMapping("/box/contribute")
public void boxContribute(@RequestBody AppExtCommand cmd) {
familyService.boxContribute(cmd);
}
/**
* 查询宝箱状态.
*/
@GetMapping("/box/status")
public FamilyBoxStatusCO boxStatus(AppExtCommand cmd) {
return familyService.boxStatus(cmd);
}
/**
* 领取宝箱奖励.
*/
@PostMapping("/box/claim")
public void boxClaim(@RequestBody @Validated FamilyBoxClaimCmd cmd) {
familyService.boxClaim(cmd);
}
/**
* 成员在家族中的基本信息.
*

View File

@ -0,0 +1,87 @@
package com.red.circle.other.app.command.family;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.other.app.dto.cmd.family.FamilyBoxClaimCmd;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxDaily;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxUserReward;
import com.red.circle.other.infra.database.rds.entity.family.FamilyMemberInfo;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxDailyService;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxUserContributeService;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxUserRewardService;
import com.red.circle.other.infra.database.rds.service.family.FamilyMemberInfoService;
import com.red.circle.other.infra.enums.family.FamilyBoxConfigEnum;
import com.red.circle.other.inner.asserts.FamilyErrorCode;
import com.red.circle.tool.core.tuple.PennyAmount;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.time.LocalDate;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* 领取宝箱奖励.
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class FamilyBoxClaimExe {
private final FamilyMemberInfoService familyMemberInfoService;
private final FamilyBoxDailyService familyBoxDailyService;
private final FamilyBoxUserContributeService familyBoxUserContributeService;
private final FamilyBoxUserRewardService familyBoxUserRewardService;
private final WalletGoldClient walletGoldClient;
@Transactional(rollbackFor = Exception.class)
public void execute(FamilyBoxClaimCmd cmd) {
FamilyBoxConfigEnum config = FamilyBoxConfigEnum.getByLevel(cmd.getLevel());
ResponseAssert.notNull(CommonErrorCode.DATA_ERROR, config);
FamilyMemberInfo memberInfo = familyMemberInfoService.getFamilyMemberByUserId(cmd.getReqUserId());
ResponseAssert.notNull(FamilyErrorCode.NOT_EXIST_FAMILY_INFO_DATA, memberInfo);
LocalDate today = LocalDate.now();
ResponseAssert.isTrue(FamilyErrorCode.NOT_EXIST_FAMILY_INFO_DATA,
familyBoxUserContributeService.hasContributed(memberInfo.getFamilyId(), cmd.getReqUserId(), today));
FamilyBoxDaily dailyRecord = familyBoxDailyService.getByFamilyAndDate(memberInfo.getFamilyId(), today);
Integer contributeCount = Objects.nonNull(dailyRecord) ? dailyRecord.getContributeCount() : 0;
ResponseAssert.isTrue(CommonErrorCode.DATA_ERROR, contributeCount >= config.getRequiredCount());
ResponseAssert.isFalse(FamilyErrorCode.REPEAT_APPLICATION,
familyBoxUserRewardService.hasClaimed(memberInfo.getFamilyId(), cmd.getReqUserId(), today, cmd.getLevel()));
String recordId = memberInfo.getFamilyId() + "_" + cmd.getReqUserId() + "_" + today + "_" + cmd.getLevel();
addUserGold(cmd.getReqUserId(), cmd.getReqSysOrigin().getOrigin(), config.getRewardGold(), recordId);
familyBoxUserRewardService.save(new FamilyBoxUserReward()
.setFamilyId(memberInfo.getFamilyId())
.setUserId(cmd.getReqUserId())
.setBoxDate(today)
.setLevel(cmd.getLevel())
.setRewardGold(config.getRewardGold())
.setSysOrigin(cmd.getReqSysOrigin().getOrigin()));
}
private void addUserGold(Long userId, String sysOrigin, Integer amount, String recordId) {
GoldReceiptCmd build = GoldReceiptCmd.builder()
.appIncome()
.userId(userId)
.amount(PennyAmount.ofDollar(amount.longValue()))
.eventId(recordId)
.sysOrigin(SysOriginPlatformEnum.valueOf(sysOrigin))
.origin(GoldOrigin.FAMILY_BOX_REWARD)
.build();
walletGoldClient.changeBalance(build);
}
}

View File

@ -0,0 +1,75 @@
package com.red.circle.other.app.command.family;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.infra.common.family.FamilyCommon;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxUserContribute;
import com.red.circle.other.infra.database.rds.entity.family.FamilyMemberInfo;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxDailyService;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxUserContributeService;
import com.red.circle.other.infra.database.rds.service.family.FamilyMemberInfoService;
import com.red.circle.other.infra.enums.family.FamilyBoxConfigEnum;
import com.red.circle.other.inner.asserts.FamilyErrorCode;
import com.red.circle.tool.core.tuple.PennyAmount;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.time.LocalDate;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* 投入宝箱金币.
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class FamilyBoxContributeExe {
private final FamilyCommon familyCommon;
private final FamilyMemberInfoService familyMemberInfoService;
private final FamilyBoxDailyService familyBoxDailyService;
private final FamilyBoxUserContributeService familyBoxUserContributeService;
private final WalletGoldClient walletGoldClient;
@Transactional(rollbackFor = Exception.class)
public void execute(AppExtCommand cmd) {
FamilyMemberInfo memberInfo = familyMemberInfoService.getFamilyMemberByUserId(cmd.getReqUserId());
ResponseAssert.notNull(FamilyErrorCode.NOT_EXIST_FAMILY_INFO_DATA, memberInfo);
LocalDate today = LocalDate.now();
ResponseAssert.isFalse(FamilyErrorCode.REPEAT_APPLICATION,
familyBoxUserContributeService.hasContributed(memberInfo.getFamilyId(), cmd.getReqUserId(), today));
String recordId = memberInfo.getFamilyId() + "_" + cmd.getReqUserId() + "_" + today;
consumeGold(cmd.getReqUserId(), cmd.getReqSysOrigin().getOrigin(), recordId);
familyBoxUserContributeService.save(new FamilyBoxUserContribute()
.setFamilyId(memberInfo.getFamilyId())
.setUserId(cmd.getReqUserId())
.setBoxDate(today)
.setGoldAmount(FamilyBoxConfigEnum.CONTRIBUTE_GOLD)
.setSysOrigin(cmd.getReqSysOrigin().getOrigin()));
familyBoxDailyService.incrementContributeCount(
memberInfo.getFamilyId(), today, cmd.getReqSysOrigin().getOrigin());
}
private void consumeGold(Long userId, String sysOrigin, String recordId) {
GoldReceiptCmd build = GoldReceiptCmd.builder()
.appExpenditure()
.userId(userId)
.amount(PennyAmount.ofDollar(FamilyBoxConfigEnum.CONTRIBUTE_GOLD.longValue()))
.eventId(recordId)
.sysOrigin(SysOriginPlatformEnum.valueOf(sysOrigin))
.origin(GoldOrigin.FAMILY_BOX_CONTRIBUTE)
.build();
walletGoldClient.changeBalance(build);
}
}

View File

@ -0,0 +1,72 @@
package com.red.circle.other.app.command.family;
import com.google.common.collect.Lists;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.app.dto.clientobject.family.FamilyBoxChestCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyBoxStatusCO;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxDaily;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxUserReward;
import com.red.circle.other.infra.database.rds.entity.family.FamilyMemberInfo;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxDailyService;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxUserContributeService;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxUserRewardService;
import com.red.circle.other.infra.database.rds.service.family.FamilyMemberInfoService;
import com.red.circle.other.infra.enums.family.FamilyBoxConfigEnum;
import com.red.circle.other.inner.asserts.FamilyErrorCode;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 查询宝箱状态.
*/
@Component
@RequiredArgsConstructor
public class FamilyBoxStatusExe {
private final FamilyMemberInfoService familyMemberInfoService;
private final FamilyBoxDailyService familyBoxDailyService;
private final FamilyBoxUserContributeService familyBoxUserContributeService;
private final FamilyBoxUserRewardService familyBoxUserRewardService;
public FamilyBoxStatusCO execute(AppExtCommand cmd) {
FamilyMemberInfo memberInfo = familyMemberInfoService.getFamilyMemberByUserId(cmd.getReqUserId());
ResponseAssert.notNull(FamilyErrorCode.NOT_EXIST_FAMILY_INFO_DATA, memberInfo);
LocalDate today = LocalDate.now();
FamilyBoxDaily dailyRecord = familyBoxDailyService.getByFamilyAndDate(memberInfo.getFamilyId(), today);
Integer contributeCount = Objects.nonNull(dailyRecord) ? dailyRecord.getContributeCount() : 0;
Boolean userContributed = familyBoxUserContributeService.hasContributed(
memberInfo.getFamilyId(), cmd.getReqUserId(), today);
List<FamilyBoxUserReward> claimedList = familyBoxUserRewardService.listByUserAndDate(
memberInfo.getFamilyId(), cmd.getReqUserId(), today);
Set<Integer> claimedLevels = claimedList.stream()
.map(FamilyBoxUserReward::getLevel)
.collect(Collectors.toSet());
List<FamilyBoxChestCO> chests = Lists.newArrayList();
for (FamilyBoxConfigEnum config : FamilyBoxConfigEnum.values()) {
chests.add(new FamilyBoxChestCO()
.setLevel(config.getLevel())
.setRequiredCount(config.getRequiredCount())
.setRewardGold(config.getRewardGold())
.setUnlocked(contributeCount >= config.getRequiredCount())
.setClaimed(claimedLevels.contains(config.getLevel())));
}
return new FamilyBoxStatusCO()
.setContributeCount(contributeCount)
.setUserContributed(userContributed)
.setChests(chests);
}
}

View File

@ -29,11 +29,15 @@ import com.red.circle.other.app.command.family.MyFamilyApplyListExe;
import com.red.circle.other.app.command.family.CancelFamilyApplyExe;
import com.red.circle.other.app.command.family.ReapplyFamilyExe;
import com.red.circle.other.app.command.family.FamilyListExe;
import com.red.circle.other.app.command.family.FamilyBoxContributeExe;
import com.red.circle.other.app.command.family.FamilyBoxStatusExe;
import com.red.circle.other.app.command.family.FamilyBoxClaimExe;
import com.red.circle.other.app.dto.clientobject.family.FamilyBaseInfoCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyCreateRulesCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyLeaderboardCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyLevelParentCacheCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyListCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyBoxStatusCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyMemberCO;
import com.red.circle.other.app.dto.clientobject.family.FamilyMsgListCO;
import com.red.circle.other.app.dto.clientobject.family.MyFamilyApplyCO;
@ -43,6 +47,7 @@ import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO;
import com.red.circle.other.app.dto.cmd.family.ApplyJoinFamilyCmd;
import com.red.circle.other.app.dto.cmd.family.CancelFamilyApplyCmd;
import com.red.circle.other.app.dto.cmd.family.ReapplyFamilyCmd;
import com.red.circle.other.app.dto.cmd.family.FamilyBoxClaimCmd;
import com.red.circle.other.app.dto.cmd.family.FamilyAdminQueryCmd;
import com.red.circle.other.app.dto.cmd.family.FamilyBaseInfoQueryCmd;
import com.red.circle.other.app.dto.cmd.family.FamilyCreateCmd;
@ -110,6 +115,9 @@ public class FamilyServiceImpl implements FamilyService {
private final CancelFamilyApplyExe cancelFamilyApplyExe;
private final ReapplyFamilyExe reapplyFamilyExe;
private final FamilyListExe familyListExe;
private final FamilyBoxContributeExe familyBoxContributeExe;
private final FamilyBoxStatusExe familyBoxStatusExe;
private final FamilyBoxClaimExe familyBoxClaimExe;
private final DistributedLockUtil distributedLockUtil;
@Override
@ -269,4 +277,24 @@ public class FamilyServiceImpl implements FamilyService {
return familyListExe.execute(cmd);
}
@Override
public void boxContribute(AppExtCommand cmd) {
String key = "FAMILY_BOX_CONTRIBUTE" + ":" + cmd.getReqUserId();
distributedLockUtil.executeWithLock(key, () -> {
familyBoxContributeExe.execute(cmd);
});
}
@Override
public FamilyBoxStatusCO boxStatus(AppExtCommand cmd) {
return familyBoxStatusExe.execute(cmd);
}
@Override
public void boxClaim(FamilyBoxClaimCmd cmd) {
String key = "FAMILY_BOX_CLAIM" + ":" + cmd.getReqUserId();
distributedLockUtil.executeWithLock(key, () -> {
familyBoxClaimExe.execute(cmd);
});
}
}

View File

@ -0,0 +1,37 @@
package com.red.circle.other.app.dto.clientobject.family;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 宝箱信息.
*/
@Data
@Accessors(chain = true)
public class FamilyBoxChestCO {
/**
* 宝箱等级(1/2/3).
*/
private Integer level;
/**
* 需要投入人数.
*/
private Integer requiredCount;
/**
* 奖励金币数.
*/
private Integer rewardGold;
/**
* 是否已解锁.
*/
private Boolean unlocked;
/**
* 当前用户是否已领取.
*/
private Boolean claimed;
}

View File

@ -0,0 +1,28 @@
package com.red.circle.other.app.dto.clientobject.family;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 宝箱状态信息.
*/
@Data
@Accessors(chain = true)
public class FamilyBoxStatusCO {
/**
* 当日投入人数.
*/
private Integer contributeCount;
/**
* 当前用户是否已投入.
*/
private Boolean userContributed;
/**
* 宝箱列表.
*/
private List<FamilyBoxChestCO> chests;
}

View File

@ -0,0 +1,20 @@
package com.red.circle.other.app.dto.cmd.family;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 领取宝箱奖励.
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class FamilyBoxClaimCmd extends AppExtCommand {
/**
* 宝箱等级(1/2/3).
*/
@NotNull(message = "宝箱等级不能为空")
private Integer level;
}

View File

@ -155,4 +155,19 @@ public interface FamilyService {
* 家族列表.
*/
PageResult<FamilyListCO> familyList(FamilyListCmd cmd);
/**
* 投入家族宝箱金币.
*/
void boxContribute(AppExtCommand cmd);
/**
* 查询家族宝箱状态.
*/
FamilyBoxStatusCO boxStatus(AppExtCommand cmd);
/**
* 领取家族宝箱奖励.
*/
void boxClaim(FamilyBoxClaimCmd cmd);
}

View File

@ -0,0 +1,12 @@
package com.red.circle.other.infra.database.rds.dao.family;
import com.red.circle.framework.mybatis.dao.BaseDAO;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxDaily;
import org.apache.ibatis.annotations.Mapper;
/**
* 家族宝箱每日记录 Mapper.
*/
public interface FamilyBoxDailyDAO extends BaseDAO<FamilyBoxDaily> {
}

View File

@ -0,0 +1,12 @@
package com.red.circle.other.infra.database.rds.dao.family;
import com.red.circle.framework.mybatis.dao.BaseDAO;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxUserContribute;
import org.apache.ibatis.annotations.Mapper;
/**
* 用户宝箱投入记录 Mapper.
*/
public interface FamilyBoxUserContributeDAO extends BaseDAO<FamilyBoxUserContribute> {
}

View File

@ -0,0 +1,12 @@
package com.red.circle.other.infra.database.rds.dao.family;
import com.red.circle.framework.mybatis.dao.BaseDAO;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxUserReward;
import org.apache.ibatis.annotations.Mapper;
/**
* 用户宝箱领取记录 Mapper.
*/
public interface FamilyBoxUserRewardDAO extends BaseDAO<FamilyBoxUserReward> {
}

View File

@ -0,0 +1,53 @@
package com.red.circle.other.infra.database.rds.entity.family;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.red.circle.framework.mybatis.entity.TimestampBaseEntity;
import java.time.LocalDate;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 家族宝箱每日记录表.
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("family_box_daily")
public class FamilyBoxDaily extends TimestampBaseEntity {
private static final long serialVersionUID = 1L;
/**
* 主键标识.
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 来源系统.
*/
@TableField("sys_origin")
private String sysOrigin;
/**
* 家族ID.
*/
@TableField("family_id")
private Long familyId;
/**
* 宝箱日期.
*/
@TableField("box_date")
private LocalDate boxDate;
/**
* 当日投入人数.
*/
@TableField("contribute_count")
private Integer contributeCount;
}

View File

@ -0,0 +1,59 @@
package com.red.circle.other.infra.database.rds.entity.family;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.red.circle.framework.mybatis.entity.TimestampBaseEntity;
import java.time.LocalDate;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 用户宝箱投入记录表.
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("family_box_user_contribute")
public class FamilyBoxUserContribute extends TimestampBaseEntity {
private static final long serialVersionUID = 1L;
/**
* 主键标识.
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 来源系统.
*/
@TableField("sys_origin")
private String sysOrigin;
/**
* 家族ID.
*/
@TableField("family_id")
private Long familyId;
/**
* 用户ID.
*/
@TableField("user_id")
private Long userId;
/**
* 投入日期.
*/
@TableField("box_date")
private LocalDate boxDate;
/**
* 投入金币数.
*/
@TableField("gold_amount")
private Integer goldAmount;
}

View File

@ -0,0 +1,65 @@
package com.red.circle.other.infra.database.rds.entity.family;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.red.circle.framework.mybatis.entity.TimestampBaseEntity;
import java.time.LocalDate;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 用户宝箱领取记录表.
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("family_box_user_reward")
public class FamilyBoxUserReward extends TimestampBaseEntity {
private static final long serialVersionUID = 1L;
/**
* 主键标识.
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 来源系统.
*/
@TableField("sys_origin")
private String sysOrigin;
/**
* 家族ID.
*/
@TableField("family_id")
private Long familyId;
/**
* 用户ID.
*/
@TableField("user_id")
private Long userId;
/**
* 领取日期.
*/
@TableField("box_date")
private LocalDate boxDate;
/**
* 宝箱等级(1/2/3).
*/
@TableField("level")
private Integer level;
/**
* 奖励金币数.
*/
@TableField("reward_gold")
private Integer rewardGold;
}

View File

@ -0,0 +1,15 @@
package com.red.circle.other.infra.database.rds.service.family;
import com.red.circle.framework.mybatis.service.BaseService;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxDaily;
import java.time.LocalDate;
/**
* 家族宝箱每日记录 服务类.
*/
public interface FamilyBoxDailyService extends BaseService<FamilyBoxDaily> {
FamilyBoxDaily getByFamilyAndDate(Long familyId, LocalDate boxDate);
void incrementContributeCount(Long familyId, LocalDate boxDate, String sysOrigin);
}

View File

@ -0,0 +1,13 @@
package com.red.circle.other.infra.database.rds.service.family;
import com.red.circle.framework.mybatis.service.BaseService;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxUserContribute;
import java.time.LocalDate;
/**
* 用户宝箱投入记录 服务类.
*/
public interface FamilyBoxUserContributeService extends BaseService<FamilyBoxUserContribute> {
Boolean hasContributed(Long familyId, Long userId, LocalDate boxDate);
}

View File

@ -0,0 +1,16 @@
package com.red.circle.other.infra.database.rds.service.family;
import com.red.circle.framework.mybatis.service.BaseService;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxUserReward;
import java.time.LocalDate;
import java.util.List;
/**
* 用户宝箱领取记录 服务类.
*/
public interface FamilyBoxUserRewardService extends BaseService<FamilyBoxUserReward> {
Boolean hasClaimed(Long familyId, Long userId, LocalDate boxDate, Integer level);
List<FamilyBoxUserReward> listByUserAndDate(Long familyId, Long userId, LocalDate boxDate);
}

View File

@ -0,0 +1,45 @@
package com.red.circle.other.infra.database.rds.service.family.impl;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.other.infra.database.rds.dao.family.FamilyBoxDailyDAO;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxDaily;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxDailyService;
import java.time.LocalDate;
import java.util.Objects;
import org.springframework.stereotype.Service;
/**
* 家族宝箱每日记录 服务实现类.
*/
@Service
public class FamilyBoxDailyServiceImpl extends BaseServiceImpl<FamilyBoxDailyDAO, FamilyBoxDaily>
implements FamilyBoxDailyService {
@Override
public FamilyBoxDaily getByFamilyAndDate(Long familyId, LocalDate boxDate) {
return query()
.eq(FamilyBoxDaily::getFamilyId, familyId)
.eq(FamilyBoxDaily::getBoxDate, boxDate)
.getOne();
}
@Override
public void incrementContributeCount(Long familyId, LocalDate boxDate, String sysOrigin) {
FamilyBoxDaily record = getByFamilyAndDate(familyId, boxDate);
if (Objects.isNull(record)) {
record = new FamilyBoxDaily()
.setFamilyId(familyId)
.setBoxDate(boxDate)
.setSysOrigin(sysOrigin)
.setContributeCount(1);
save(record);
} else {
update()
.setSql("contribute_count = contribute_count + 1")
.eq(FamilyBoxDaily::getFamilyId, familyId)
.eq(FamilyBoxDaily::getBoxDate, boxDate)
.execute();
}
}
}

View File

@ -0,0 +1,27 @@
package com.red.circle.other.infra.database.rds.service.family.impl;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.other.infra.database.rds.dao.family.FamilyBoxUserContributeDAO;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxUserContribute;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxUserContributeService;
import java.time.LocalDate;
import java.util.Objects;
import org.springframework.stereotype.Service;
/**
* 用户宝箱投入记录 服务实现类.
*/
@Service
public class FamilyBoxUserContributeServiceImpl extends
BaseServiceImpl<FamilyBoxUserContributeDAO, FamilyBoxUserContribute>
implements FamilyBoxUserContributeService {
@Override
public Boolean hasContributed(Long familyId, Long userId, LocalDate boxDate) {
return Objects.nonNull(query()
.eq(FamilyBoxUserContribute::getFamilyId, familyId)
.eq(FamilyBoxUserContribute::getUserId, userId)
.eq(FamilyBoxUserContribute::getBoxDate, boxDate)
.getOne());
}
}

View File

@ -0,0 +1,39 @@
package com.red.circle.other.infra.database.rds.service.family.impl;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.other.infra.database.rds.dao.family.FamilyBoxUserRewardDAO;
import com.red.circle.other.infra.database.rds.entity.family.FamilyBoxUserReward;
import com.red.circle.other.infra.database.rds.service.family.FamilyBoxUserRewardService;
import com.red.circle.tool.core.collection.CollectionUtils;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
import org.springframework.stereotype.Service;
/**
* 用户宝箱领取记录 服务实现类.
*/
@Service
public class FamilyBoxUserRewardServiceImpl extends
BaseServiceImpl<FamilyBoxUserRewardDAO, FamilyBoxUserReward>
implements FamilyBoxUserRewardService {
@Override
public Boolean hasClaimed(Long familyId, Long userId, LocalDate boxDate, Integer level) {
return Objects.nonNull(query()
.eq(FamilyBoxUserReward::getFamilyId, familyId)
.eq(FamilyBoxUserReward::getUserId, userId)
.eq(FamilyBoxUserReward::getBoxDate, boxDate)
.eq(FamilyBoxUserReward::getLevel, level)
.getOne());
}
@Override
public List<FamilyBoxUserReward> listByUserAndDate(Long familyId, Long userId, LocalDate boxDate) {
return query()
.eq(FamilyBoxUserReward::getFamilyId, familyId)
.eq(FamilyBoxUserReward::getUserId, userId)
.eq(FamilyBoxUserReward::getBoxDate, boxDate)
.list();
}
}

View File

@ -0,0 +1,55 @@
package com.red.circle.other.infra.enums.family;
import lombok.Getter;
/**
* 家族宝箱配置枚举.
*/
@Getter
public enum FamilyBoxConfigEnum {
LEVEL_1(1, 5, 50, "宝箱1"),
LEVEL_2(2, 10, 50, "宝箱2"),
LEVEL_3(3, 20, 100, "宝箱3");
/**
* 等级.
*/
private final Integer level;
/**
* 需要投入人数.
*/
private final Integer requiredCount;
/**
* 奖励金币数.
*/
private final Integer rewardGold;
/**
* 描述.
*/
private final String description;
FamilyBoxConfigEnum(Integer level, Integer requiredCount, Integer rewardGold, String description) {
this.level = level;
this.requiredCount = requiredCount;
this.rewardGold = rewardGold;
this.description = description;
}
public static FamilyBoxConfigEnum getByLevel(Integer level) {
for (FamilyBoxConfigEnum config : values()) {
if (config.level.equals(level)) {
return config;
}
}
return null;
}
/**
* 投入金币固定数量.
*/
public static final Integer CONTRIBUTE_GOLD = 50;
}