Compare commits
8 Commits
32a1094edc
...
f6995c519a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6995c519a | ||
|
|
35ceb5d80f | ||
|
|
ad73326eae | ||
|
|
a9320d58ec | ||
|
|
e3942ff651 | ||
|
|
527a0b916d | ||
|
|
a51c252b36 | ||
|
|
1e94443ee5 |
@ -39,10 +39,10 @@ public class LoginAccessValidationService {
|
|||||||
"香港", "澳门", "澳門", "台湾", "台灣", "Hong Kong", "Macau", "Macao", "Taiwan"
|
"香港", "澳门", "澳門", "台湾", "台灣", "Hong Kong", "Macau", "Macao", "Taiwan"
|
||||||
);
|
);
|
||||||
private static final List<String> BLOCKED_COUNTRY_CODES = List.of(
|
private static final List<String> BLOCKED_COUNTRY_CODES = List.of(
|
||||||
"MO", "SG"
|
"MO"
|
||||||
);
|
);
|
||||||
private static final List<String> BLOCKED_COUNTRY_NAMES = List.of(
|
private static final List<String> BLOCKED_COUNTRY_NAMES = List.of(
|
||||||
"澳门", "澳門", "Macau", "Macao", "新加坡", "Singapore"
|
"澳门", "澳門", "Macau", "Macao"
|
||||||
);
|
);
|
||||||
private static final List<IpGeoProvider> IP_GEO_PROVIDERS = List.of(
|
private static final List<IpGeoProvider> IP_GEO_PROVIDERS = List.of(
|
||||||
new IpGeoProvider("ip.sb", "https://api.ip.sb/geoip/%s"),
|
new IpGeoProvider("ip.sb", "https://api.ip.sb/geoip/%s"),
|
||||||
|
|||||||
@ -98,12 +98,12 @@ public class LoginAccessValidationServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void blockSingaporeCountryCode() {
|
public void allowSingaporeCountryCode() {
|
||||||
JSONObject data = JSON.parseObject("""
|
JSONObject data = JSON.parseObject("""
|
||||||
{"country_id":"SG","country":"Singapore","region":""}
|
{"country_id":"SG","country":"Singapore","region":""}
|
||||||
""");
|
""");
|
||||||
|
|
||||||
assertTrue(LoginAccessValidationService.isBlockedIpRegion(data));
|
assertFalse(LoginAccessValidationService.isBlockedIpRegion(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -23,4 +23,9 @@ public class LoginLogQryCmd extends PageCommand {
|
|||||||
*/
|
*/
|
||||||
private String deviceId;
|
private String deviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录 IP.
|
||||||
|
*/
|
||||||
|
private String ip;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,9 @@ import com.red.circle.framework.dto.ResultResponse;
|
|||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceDecrCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceDecrCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceIncrCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceIncrCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
||||||
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
||||||
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceStatisticsDTO;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -56,9 +57,16 @@ public interface UserBankBalanceClientApi {
|
|||||||
@GetMapping("/getTotalBalance")
|
@GetMapping("/getTotalBalance")
|
||||||
ResultResponse<Long> getTotalBalance(@RequestParam("userId") Long userId);
|
ResultResponse<Long> getTotalBalance(@RequestParam("userId") Long userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查看用户银行卡账户.
|
* 查看用户银行卡账户.
|
||||||
*/
|
*/
|
||||||
@PostMapping("/listBalance")
|
@PostMapping("/listBalance")
|
||||||
ResultResponse<List<UserBankBalanceDTO>> listBalance(@RequestBody UserBankBalanceQryCmd query);
|
ResultResponse<List<UserBankBalanceDTO>> listBalance(@RequestBody UserBankBalanceQryCmd query);
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* 用户银行卡账户统计.
|
||||||
|
*/
|
||||||
|
@PostMapping("/calculateStatistics")
|
||||||
|
ResultResponse<UserBankBalanceStatisticsDTO> calculateStatistics(
|
||||||
|
@RequestBody UserBankBalanceQryCmd query);
|
||||||
|
}
|
||||||
|
|||||||
@ -37,8 +37,23 @@ public class UserBankBalanceQryCmd extends CommonCommand {
|
|||||||
*/
|
*/
|
||||||
private Long lastId;
|
private Long lastId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每页大小.
|
* 每页大小.
|
||||||
*/
|
*/
|
||||||
private Integer limit;
|
private Integer limit;
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* 页码.
|
||||||
|
*/
|
||||||
|
private Integer pageNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序字段.
|
||||||
|
*/
|
||||||
|
private String sortField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序方向.
|
||||||
|
*/
|
||||||
|
private String sortOrder;
|
||||||
|
}
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
package com.red.circle.wallet.inner.model.dto;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户银行账户统计.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class UserBankBalanceStatisticsDTO implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得总额.
|
||||||
|
*/
|
||||||
|
private BigDecimal totalEarnPoints;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消费总额.
|
||||||
|
*/
|
||||||
|
private BigDecimal totalConsumptionPoints;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 余额总额.
|
||||||
|
*/
|
||||||
|
private BigDecimal totalBalance;
|
||||||
|
}
|
||||||
@ -53,11 +53,18 @@ public class SysGiftConfigRestController extends BaseController {
|
|||||||
|
|
||||||
@OpsOperationReqLog(value = "修改礼物信息")
|
@OpsOperationReqLog(value = "修改礼物信息")
|
||||||
@PutMapping
|
@PutMapping
|
||||||
public void updateGift(@RequestBody SysGiftConfigCO param) {
|
public void updateGift(@RequestBody SysGiftConfigCO param) {
|
||||||
param.setUpdateUser(getReqUserId());
|
param.setUpdateUser(getReqUserId());
|
||||||
sysGiftConfigService.updateGift(param);
|
sysGiftConfigService.updateGift(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OpsOperationReqLog(value = "修改礼物排序权重")
|
||||||
|
@PutMapping("/sort")
|
||||||
|
public void updateGiftSort(@RequestBody SysGiftConfigCO param) {
|
||||||
|
param.setUpdateUser(getReqUserId());
|
||||||
|
sysGiftConfigService.updateGiftSort(param);
|
||||||
|
}
|
||||||
|
|
||||||
@OpsOperationReqLog(value = "新增礼物信息")
|
@OpsOperationReqLog(value = "新增礼物信息")
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public void addGift(@RequestBody SysGiftConfigCO param) {
|
public void addGift(@RequestBody SysGiftConfigCO param) {
|
||||||
|
|||||||
@ -15,10 +15,11 @@ import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
|||||||
import com.red.circle.wallet.inner.model.cmd.UserBankMoneyCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankMoneyCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankRunningWaterQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankRunningWaterQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankTransferCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankTransferCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawGoldApplyQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawGoldApplyQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawMoneyApplyExportQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawMoneyApplyExportQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawMoneyApplyQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawMoneyApplyQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.enums.UserBankWaterEvent;
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceStatisticsDTO;
|
||||||
|
import com.red.circle.wallet.inner.model.enums.UserBankWaterEvent;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@ -57,12 +58,20 @@ public class UserBankBalanceRestController extends BaseController {
|
|||||||
* 用户余额列表.
|
* 用户余额列表.
|
||||||
*/
|
*/
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
public List<UserBankBalanceCO> page(UserBankBalanceQryCmd query) {
|
public List<UserBankBalanceCO> page(UserBankBalanceQryCmd query) {
|
||||||
return userBankBalanceBackService.listUserBankBalance(query);
|
return userBankBalanceBackService.listUserBankBalance(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户余额列表-导出.
|
* 用户余额统计.
|
||||||
|
*/
|
||||||
|
@GetMapping("/statistics")
|
||||||
|
public UserBankBalanceStatisticsDTO statistics(UserBankBalanceQryCmd query) {
|
||||||
|
return userBankBalanceBackService.calculateStatistics(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户余额列表-导出.
|
||||||
*/
|
*/
|
||||||
@GetMapping("/export")
|
@GetMapping("/export")
|
||||||
public void export(HttpServletResponse response, String sysOrigin) throws IOException {
|
public void export(HttpServletResponse response, String sysOrigin) throws IOException {
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import com.red.circle.console.app.service.admin.UserAccountService;
|
|||||||
import com.red.circle.console.inner.error.ConsoleErrorCode;
|
import com.red.circle.console.inner.error.ConsoleErrorCode;
|
||||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
import com.red.circle.other.inner.endpoint.live.RoomManagerClient;
|
import com.red.circle.other.inner.endpoint.live.RoomManagerClient;
|
||||||
|
import com.red.circle.other.inner.endpoint.material.gift.GiftBackpackClient;
|
||||||
import com.red.circle.other.inner.endpoint.material.props.*;
|
import com.red.circle.other.inner.endpoint.material.props.*;
|
||||||
import com.red.circle.other.inner.endpoint.user.user.SysUserProfileClient;
|
import com.red.circle.other.inner.endpoint.user.user.SysUserProfileClient;
|
||||||
import com.red.circle.other.inner.enums.material.BadgeBackpackExpireTypeEnum;
|
import com.red.circle.other.inner.enums.material.BadgeBackpackExpireTypeEnum;
|
||||||
@ -69,6 +70,7 @@ public class PropsGiveServiceImpl implements PropsGiveService {
|
|||||||
private final PropsNobleVipClient propsNobleVipClient;
|
private final PropsNobleVipClient propsNobleVipClient;
|
||||||
private final RoomThemeBackpackClient roomThemeBackpackClient;
|
private final RoomThemeBackpackClient roomThemeBackpackClient;
|
||||||
private final PropsCommodityStoreClient propsCommodityStoreClient;
|
private final PropsCommodityStoreClient propsCommodityStoreClient;
|
||||||
|
private final GiftBackpackClient giftBackpackClient;
|
||||||
private final UserAccountService userAccountService;
|
private final UserAccountService userAccountService;
|
||||||
private final PropCouponClient propCouponClient;
|
private final PropCouponClient propCouponClient;
|
||||||
|
|
||||||
@ -109,6 +111,7 @@ public class PropsGiveServiceImpl implements PropsGiveService {
|
|||||||
.setType(cmd.getType())
|
.setType(cmd.getType())
|
||||||
.setSecondaryType(cmd.getSecondaryType())
|
.setSecondaryType(cmd.getSecondaryType())
|
||||||
.setContent(cmd.getContent())
|
.setContent(cmd.getContent())
|
||||||
|
.setQuantity(cmd.getQuantity())
|
||||||
.setSysOrigin(cmd.getSysOrigin())
|
.setSysOrigin(cmd.getSysOrigin())
|
||||||
.setReceiverAccounts(cmd.getReceiverAccounts())
|
.setReceiverAccounts(cmd.getReceiverAccounts())
|
||||||
.setVipOrigin(cmd.getVipOrigin())
|
.setVipOrigin(cmd.getVipOrigin())
|
||||||
@ -127,7 +130,7 @@ public class PropsGiveServiceImpl implements PropsGiveService {
|
|||||||
ResponseAssert.isFalse(UserErrorCode.USER_INFO_NOT_FOUND, StringUtils.isBlank(sysOrigin));
|
ResponseAssert.isFalse(UserErrorCode.USER_INFO_NOT_FOUND, StringUtils.isBlank(sysOrigin));
|
||||||
|
|
||||||
// 后台赠送道具校验权限
|
// 后台赠送道具校验权限
|
||||||
if (!"BADGE".equals(cmd.getType())) {
|
if (!"BADGE".equals(cmd.getType()) && !"GIFT".equals(cmd.getType())) {
|
||||||
checkUserAccountAlias(cmd);
|
checkUserAccountAlias(cmd);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -165,6 +168,10 @@ public class PropsGiveServiceImpl implements PropsGiveService {
|
|||||||
propsBackpackClient.givePropsNotify(cmd.getReceiverId(),cmd.getSecondaryType(),cmd.getExchangeDays(), Long.valueOf(cmd.getContent()));
|
propsBackpackClient.givePropsNotify(cmd.getReceiverId(),cmd.getSecondaryType(),cmd.getExchangeDays(), Long.valueOf(cmd.getContent()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (Objects.equals(cmd.getType(), PropsActivityRewardEnum.GIFT.name())) {
|
||||||
|
handleGift(cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (Objects.equals(cmd.getType(), PropsActivityRewardEnum.GOLD.name())) {
|
if (Objects.equals(cmd.getType(), PropsActivityRewardEnum.GOLD.name())) {
|
||||||
handleGold(cmd);
|
handleGold(cmd);
|
||||||
return;
|
return;
|
||||||
@ -388,6 +395,21 @@ public class PropsGiveServiceImpl implements PropsGiveService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleGift(PropsGiveUserCmd cmd) {
|
||||||
|
Long giftId = DataTypeUtils.toLong(cmd.getContent());
|
||||||
|
ResponseAssert.isFalse(ConsoleErrorCode.RESOURCES_SHELF_NOT_EXISTENT,
|
||||||
|
Objects.isNull(giftId) || Objects.equals(giftId, 0L));
|
||||||
|
|
||||||
|
Integer quantity = Objects.nonNull(cmd.getQuantity())
|
||||||
|
? cmd.getQuantity()
|
||||||
|
: cmd.getExchangeDays();
|
||||||
|
ResponseAssert.isFalse(ConsoleErrorCode.NUMBER_VIOLATION_ERROR,
|
||||||
|
Objects.isNull(quantity) || quantity <= 0);
|
||||||
|
|
||||||
|
ResponseAssert.requiredSuccess(
|
||||||
|
giftBackpackClient.incrGift(cmd.getReceiverId(), giftId, quantity));
|
||||||
|
}
|
||||||
|
|
||||||
private void isUserNormal(Long userId) {
|
private void isUserNormal(Long userId) {
|
||||||
UserProfileDTO userProfile = ResponseAssert.requiredSuccess(
|
UserProfileDTO userProfile = ResponseAssert.requiredSuccess(
|
||||||
userProfileClient.getByUserId(userId));
|
userProfileClient.getByUserId(userId));
|
||||||
|
|||||||
@ -83,10 +83,10 @@ public class SysGiftConfigServiceImpl implements SysGiftConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateGift(SysGiftConfigCO param) {
|
public void updateGift(SysGiftConfigCO param) {
|
||||||
ResponseAssert.notNull(GiftErrorCode.BAD_REQUEST, param.getId());
|
ResponseAssert.notNull(GiftErrorCode.BAD_REQUEST, param.getId());
|
||||||
GiftConfigDTO orlGiftConfig = ResponseAssert.requiredSuccess(
|
GiftConfigDTO orlGiftConfig = ResponseAssert.requiredSuccess(
|
||||||
giftConfigClient.getById(param.getId()));
|
giftConfigClient.getById(param.getId()));
|
||||||
ResponseAssert.notNull(GiftErrorCode.GIFT_NOT_FOUND, orlGiftConfig);
|
ResponseAssert.notNull(GiftErrorCode.GIFT_NOT_FOUND, orlGiftConfig);
|
||||||
GiftConfigDTO newGiftConfig = getGiftConfig(param);
|
GiftConfigDTO newGiftConfig = getGiftConfig(param);
|
||||||
if (StringUtils.isNotBlank(param.getAccount())){
|
if (StringUtils.isNotBlank(param.getAccount())){
|
||||||
@ -99,12 +99,25 @@ public class SysGiftConfigServiceImpl implements SysGiftConfigService {
|
|||||||
ResponseAssert.isTrue(CommonErrorCode.UPDATE_FAILURE,
|
ResponseAssert.isTrue(CommonErrorCode.UPDATE_FAILURE,
|
||||||
ResponseAssert.requiredSuccess(giftConfigClient.updateGift(newGiftConfig)));
|
ResponseAssert.requiredSuccess(giftConfigClient.updateGift(newGiftConfig)));
|
||||||
giftConfigClient.removeGiftCache();
|
giftConfigClient.removeGiftCache();
|
||||||
|
|
||||||
removeRemainingInventory(orlGiftConfig, newGiftConfig);
|
removeRemainingInventory(orlGiftConfig, newGiftConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addGift(SysGiftConfigCO param) {
|
public void updateGiftSort(SysGiftConfigCO param) {
|
||||||
|
ResponseAssert.notNull(GiftErrorCode.BAD_REQUEST, param.getId());
|
||||||
|
ResponseAssert.notNull(GiftErrorCode.BAD_REQUEST, param.getSort());
|
||||||
|
GiftConfigDTO giftConfig = ResponseAssert.requiredSuccess(
|
||||||
|
giftConfigClient.getById(param.getId()));
|
||||||
|
ResponseAssert.notNull(GiftErrorCode.GIFT_NOT_FOUND, giftConfig);
|
||||||
|
giftConfig.setSort(param.getSort());
|
||||||
|
ResponseAssert.isTrue(CommonErrorCode.UPDATE_FAILURE,
|
||||||
|
ResponseAssert.requiredSuccess(giftConfigClient.updateGift(giftConfig)));
|
||||||
|
giftConfigClient.removeGiftCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addGift(SysGiftConfigCO param) {
|
||||||
GiftConfigDTO giftConfig = getGiftConfig(param);
|
GiftConfigDTO giftConfig = getGiftConfig(param);
|
||||||
if (GiftTabEnum.EXCLUSIVE.equals(param.getGiftTab())) {
|
if (GiftTabEnum.EXCLUSIVE.equals(param.getGiftTab())) {
|
||||||
UserProfileDTO userProfile = userProfileClient.getByAccount(param.getSysOrigin(),
|
UserProfileDTO userProfile = userProfileClient.getByAccount(param.getSysOrigin(),
|
||||||
|
|||||||
@ -96,9 +96,9 @@ public class UserBankBalanceBackServiceImpl implements UserBankBalanceBackServic
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserBankBalanceCO> listUserBankBalance(UserBankBalanceQryCmd query) {
|
public List<UserBankBalanceCO> listUserBankBalance(UserBankBalanceQryCmd query) {
|
||||||
List<UserBankBalanceDTO> userBankBalances = ResponseAssert.requiredSuccess(
|
List<UserBankBalanceDTO> userBankBalances = ResponseAssert.requiredSuccess(
|
||||||
userBankBalanceClient.listBalance(query));
|
userBankBalanceClient.listBalance(query));
|
||||||
if (CollectionUtils.isEmpty(userBankBalances)) {
|
if (CollectionUtils.isEmpty(userBankBalances)) {
|
||||||
return Lists.newArrayList();
|
return Lists.newArrayList();
|
||||||
}
|
}
|
||||||
@ -122,11 +122,16 @@ public class UserBankBalanceBackServiceImpl implements UserBankBalanceBackServic
|
|||||||
.setUserProfile(userProfile)
|
.setUserProfile(userProfile)
|
||||||
.setCreateTime(userBankBalance.getCreateTime())
|
.setCreateTime(userBankBalance.getCreateTime())
|
||||||
.setUpdateTime(userBankBalance.getUpdateTime());
|
.setUpdateTime(userBankBalance.getUpdateTime());
|
||||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
private Set<Long> getBankUserIds(List<UserBankBalanceDTO> userBankBalances) {
|
public UserBankBalanceStatisticsDTO calculateStatistics(UserBankBalanceQryCmd query) {
|
||||||
|
return ResponseAssert.requiredSuccess(userBankBalanceClient.calculateStatistics(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Set<Long> getBankUserIds(List<UserBankBalanceDTO> userBankBalances) {
|
||||||
return userBankBalances.stream().map(UserBankBalanceDTO::getId).collect(Collectors.toSet());
|
return userBankBalances.stream().map(UserBankBalanceDTO::getId).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -41,6 +41,11 @@ public class PropsGiveUserCmd extends Command {
|
|||||||
@NotNull(message = "exchangeDays required.")
|
@NotNull(message = "exchangeDays required.")
|
||||||
private Integer exchangeDays;
|
private Integer exchangeDays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 礼物数量.
|
||||||
|
*/
|
||||||
|
private Integer quantity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 道具类型.
|
* 道具类型.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -25,13 +25,18 @@ public interface SysGiftConfigService {
|
|||||||
*/
|
*/
|
||||||
PageResult<SysGiftConfigCO> pageGiftInfo(GiftConsoleQryCmd query);
|
PageResult<SysGiftConfigCO> pageGiftInfo(GiftConsoleQryCmd query);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改礼物信息.
|
* 修改礼物信息.
|
||||||
*/
|
*/
|
||||||
void updateGift(SysGiftConfigCO param);
|
void updateGift(SysGiftConfigCO param);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增礼物信息.
|
* 修改礼物排序权重.
|
||||||
|
*/
|
||||||
|
void updateGiftSort(SysGiftConfigCO param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增礼物信息.
|
||||||
*/
|
*/
|
||||||
void addGift(SysGiftConfigCO param);
|
void addGift(SysGiftConfigCO param);
|
||||||
|
|
||||||
|
|||||||
@ -9,10 +9,11 @@ import com.red.circle.wallet.inner.model.cmd.ApprovalMoneyApplyCmd;
|
|||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankMoneyCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankMoneyCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankRunningWaterQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankRunningWaterQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankTransferCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankTransferCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawGoldApplyQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawGoldApplyQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawMoneyApplyExportQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawMoneyApplyExportQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawMoneyApplyQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawMoneyApplyQryCmd;
|
||||||
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceStatisticsDTO;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -25,13 +26,18 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
*/
|
*/
|
||||||
public interface UserBankBalanceBackService {
|
public interface UserBankBalanceBackService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询用户银行账户余额.
|
* 查询用户银行账户余额.
|
||||||
*/
|
*/
|
||||||
List<UserBankBalanceCO> listUserBankBalance(UserBankBalanceQryCmd query);
|
List<UserBankBalanceCO> listUserBankBalance(UserBankBalanceQryCmd query);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出余额列表.
|
* 统计用户银行账户余额.
|
||||||
|
*/
|
||||||
|
UserBankBalanceStatisticsDTO calculateStatistics(UserBankBalanceQryCmd query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出余额列表.
|
||||||
*/
|
*/
|
||||||
void exportUserBankBalance(HttpServletResponse response, String sysOrigin);
|
void exportUserBankBalance(HttpServletResponse response, String sysOrigin);
|
||||||
|
|
||||||
|
|||||||
@ -60,9 +60,11 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@RocketMqMessageListener(groupId = TeamBillSettleSink.INPUT, tag = TeamBillSettleSink.TAG)
|
@RocketMqMessageListener(groupId = TeamBillSettleSink.INPUT, tag = TeamBillSettleSink.TAG)
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TeamBillSettleListener implements MessageListener {
|
public class TeamBillSettleListener implements MessageListener {
|
||||||
|
|
||||||
private final String tag = "团队账单";
|
private static final boolean SALARY_SETTLEMENT_PAUSED = true;
|
||||||
|
|
||||||
|
private final String tag = "团队账单";
|
||||||
private final TeamProfileService teamProfileService;
|
private final TeamProfileService teamProfileService;
|
||||||
private final MessageEventProcess messageEventProcess;
|
private final MessageEventProcess messageEventProcess;
|
||||||
private final TeamBillCycleService teamBillCycleService;
|
private final TeamBillCycleService teamBillCycleService;
|
||||||
@ -76,9 +78,14 @@ public class TeamBillSettleListener implements MessageListener {
|
|||||||
private final SalaryDiamondRunningWaterClient salaryDiamondRunningWaterClient;
|
private final SalaryDiamondRunningWaterClient salaryDiamondRunningWaterClient;
|
||||||
private final BillDiamondBalanceService billDiamondBalanceService;
|
private final BillDiamondBalanceService billDiamondBalanceService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Action consume(ConsumerMessage message) {
|
public Action consume(ConsumerMessage message) {
|
||||||
return messageEventProcess.consume(
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
|
log.warn("team_bill_settle_message skipped: salary settlement is temporarily paused");
|
||||||
|
return Action.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return messageEventProcess.consume(
|
||||||
MessageEventProcessDescribe.builder()
|
MessageEventProcessDescribe.builder()
|
||||||
.logTag(tag)
|
.logTag(tag)
|
||||||
.consumeMsgTimeoutMinute(30)
|
.consumeMsgTimeoutMinute(30)
|
||||||
|
|||||||
@ -77,9 +77,11 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@RocketMqMessageListener(groupId = TeamSalaryPaymentSink.INPUT, tag = TeamSalaryPaymentSink.TAG)
|
@RocketMqMessageListener(groupId = TeamSalaryPaymentSink.INPUT, tag = TeamSalaryPaymentSink.TAG)
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TeamSalaryPaymentListener implements MessageListener {
|
public class TeamSalaryPaymentListener implements MessageListener {
|
||||||
|
|
||||||
private final PropsSendCommon propsSendCommon;
|
private static final boolean SALARY_SETTLEMENT_PAUSED = true;
|
||||||
|
|
||||||
|
private final PropsSendCommon propsSendCommon;
|
||||||
private final TeamMemberService teamMemberService;
|
private final TeamMemberService teamMemberService;
|
||||||
private final TeamProfileService teamProfileService;
|
private final TeamProfileService teamProfileService;
|
||||||
private final MessageEventProcess messageEventProcess;
|
private final MessageEventProcess messageEventProcess;
|
||||||
@ -95,9 +97,14 @@ public class TeamSalaryPaymentListener implements MessageListener {
|
|||||||
private final BillDiamondBalanceService billDiamondBalanceService;
|
private final BillDiamondBalanceService billDiamondBalanceService;
|
||||||
private final BillDiamondBalanceDetailsService billDiamondBalanceDetailsService;
|
private final BillDiamondBalanceDetailsService billDiamondBalanceDetailsService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Action consume(ConsumerMessage message) {
|
public Action consume(ConsumerMessage message) {
|
||||||
return messageEventProcess.consume(
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
|
log.warn("team_salary_payment_message skipped: salary settlement is temporarily paused");
|
||||||
|
return Action.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return messageEventProcess.consume(
|
||||||
MessageEventProcessDescribe.builder()
|
MessageEventProcessDescribe.builder()
|
||||||
.logTag("满足政策的团队工资实时发送")
|
.logTag("满足政策的团队工资实时发送")
|
||||||
.consumeMsgTimeoutMinute(30)
|
.consumeMsgTimeoutMinute(30)
|
||||||
@ -522,7 +529,7 @@ public class TeamSalaryPaymentListener implements MessageListener {
|
|||||||
|
|
||||||
// 是否已经发送过代理部份工资
|
// 是否已经发送过代理部份工资
|
||||||
if (Boolean.FALSE.equals(
|
if (Boolean.FALSE.equals(
|
||||||
checkRepeatPayment(teamProfile, payment, policy, memberTargetId, Boolean.FALSE))) {
|
checkRepeatPayment(teamProfile, payment, policy, Boolean.FALSE))) {
|
||||||
|
|
||||||
String detailsId = IdWorkerUtils.getIdStr();
|
String detailsId = IdWorkerUtils.getIdStr();
|
||||||
|
|
||||||
@ -570,7 +577,7 @@ public class TeamSalaryPaymentListener implements MessageListener {
|
|||||||
|
|
||||||
// 是否已经发送过该成员工资
|
// 是否已经发送过该成员工资
|
||||||
if (Boolean.FALSE.equals(
|
if (Boolean.FALSE.equals(
|
||||||
checkRepeatPayment(teamProfile, payment, policy, memberTargetId, Boolean.TRUE))) {
|
checkRepeatPayment(teamProfile, payment, policy, Boolean.TRUE))) {
|
||||||
|
|
||||||
String detailsId = IdWorkerUtils.getIdStr();
|
String detailsId = IdWorkerUtils.getIdStr();
|
||||||
|
|
||||||
@ -627,7 +634,7 @@ public class TeamSalaryPaymentListener implements MessageListener {
|
|||||||
|
|
||||||
// 是否已经发送过该成员工资
|
// 是否已经发送过该成员工资
|
||||||
if (Boolean.TRUE.equals(
|
if (Boolean.TRUE.equals(
|
||||||
checkRepeatPayment(teamProfile, payment, policy, memberTargetId, Boolean.TRUE))) {
|
checkRepeatPayment(teamProfile, payment, policy, Boolean.TRUE))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,26 +732,16 @@ public class TeamSalaryPaymentListener implements MessageListener {
|
|||||||
* @param teamProfile 团队
|
* @param teamProfile 团队
|
||||||
* @param payment 支付信息
|
* @param payment 支付信息
|
||||||
* @param policy 政策
|
* @param policy 政策
|
||||||
* @param memberTargetId 成员工作id
|
* @param isPayMember 支付工资成员验证
|
||||||
* @param isPayMember 支付工资成员验证
|
* @return true 重复发送, false 允许发送
|
||||||
* @return true 重复发送, false 允许发送
|
*/
|
||||||
*/
|
private Boolean checkRepeatPayment(TeamProfile teamProfile, TeamSalaryPayment payment,
|
||||||
private Boolean checkRepeatPayment(TeamProfile teamProfile, TeamSalaryPayment payment,
|
TeamPolicy policy, Boolean isPayMember) {
|
||||||
TeamPolicy policy, String memberTargetId, Boolean isPayMember) {
|
|
||||||
|
return teamSalaryPaymentService
|
||||||
// if (Objects.equals(payment.getUserId(), 1681823277871214593L) ||
|
.checkRepeatPayment(payment.getId(), payment.getUserId(), teamProfile.getRegion(),
|
||||||
// Objects.equals(payment.getUserId(), 1684848110911922177L) ||
|
policy.getLevel(), isPayMember);
|
||||||
// Objects.equals(payment.getUserId(), 1630240619660009473L)) {
|
}
|
||||||
|
|
||||||
return teamSalaryPaymentService
|
|
||||||
.checkRepeatPayment(payment.getId(), payment.getUserId(), teamProfile.getRegion(),
|
|
||||||
policy.getLevel(), memberTargetId, isPayMember);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// return teamSalaryPaymentService
|
|
||||||
// .checkRepeatPayment(payment.getId(), payment.getUserId(), teamProfile.getRegion(),
|
|
||||||
// policy.getLevel(), isPayMember);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于当前等级获得上一个等级政策.
|
* 基于当前等级获得上一个等级政策.
|
||||||
|
|||||||
@ -18,9 +18,11 @@ import org.springframework.stereotype.Component;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AdminSalarySettlementTask {
|
public class AdminSalarySettlementTask {
|
||||||
|
|
||||||
private final AdminSalarySettlementService adminSalarySettlementService;
|
private static final boolean SALARY_SETTLEMENT_PAUSED = true;
|
||||||
|
|
||||||
|
private final AdminSalarySettlementService adminSalarySettlementService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每月1号2点执行上月整月结算.
|
* 每月1号2点执行上月整月结算.
|
||||||
@ -28,7 +30,12 @@ public class AdminSalarySettlementTask {
|
|||||||
@Scheduled(cron = "0 0 2 1 * ?", zone = "Asia/Riyadh")
|
@Scheduled(cron = "0 0 2 1 * ?", zone = "Asia/Riyadh")
|
||||||
@TaskCacheLock(key = "ADMIN_SALARY_SETTLEMENT", expireSecond = 86400)
|
@TaskCacheLock(key = "ADMIN_SALARY_SETTLEMENT", expireSecond = 86400)
|
||||||
public void processAdminSalarySettlement() {
|
public void processAdminSalarySettlement() {
|
||||||
long startTime = System.currentTimeMillis();
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
|
log.warn("admin_salary_settlement skipped: salary settlement is temporarily paused");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
log.warn("========== 管理员工资结算定时任务开始 ==========");
|
log.warn("========== 管理员工资结算定时任务开始 ==========");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -61,8 +68,13 @@ public class AdminSalarySettlementTask {
|
|||||||
/**
|
/**
|
||||||
* 测试方法(手动触发).
|
* 测试方法(手动触发).
|
||||||
*/
|
*/
|
||||||
public void processAdminSalarySettlementTest(Integer billBelong) {
|
public void processAdminSalarySettlementTest(Integer billBelong) {
|
||||||
String billTitle = TeamBillCycleUtils.parseBillBelongToDateRangeStr(billBelong);
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
|
log.warn("admin_salary_settlement_test skipped: salary settlement is temporarily paused");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String billTitle = TeamBillCycleUtils.parseBillBelongToDateRangeStr(billBelong);
|
||||||
adminSalarySettlementService.processAllAdminSettlement(billBelong, billTitle);
|
adminSalarySettlementService.processAllAdminSettlement(billBelong, billTitle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,9 +18,11 @@ import org.springframework.stereotype.Component;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class BdLeaderSalarySettlementTask {
|
public class BdLeaderSalarySettlementTask {
|
||||||
|
|
||||||
private final BdLeaderSalarySettlementService bdLeaderSalarySettlementService;
|
private static final boolean SALARY_SETTLEMENT_PAUSED = true;
|
||||||
|
|
||||||
|
private final BdLeaderSalarySettlementService bdLeaderSalarySettlementService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每月1号1点执行上月整月结算.
|
* 每月1号1点执行上月整月结算.
|
||||||
@ -28,7 +30,12 @@ public class BdLeaderSalarySettlementTask {
|
|||||||
@Scheduled(cron = "0 0 1 1 * ?", zone = "Asia/Riyadh")
|
@Scheduled(cron = "0 0 1 1 * ?", zone = "Asia/Riyadh")
|
||||||
@TaskCacheLock(key = "BD_LEADER_SALARY_SETTLEMENT", expireSecond = 86400)
|
@TaskCacheLock(key = "BD_LEADER_SALARY_SETTLEMENT", expireSecond = 86400)
|
||||||
public void processBdLeaderSalarySettlement() {
|
public void processBdLeaderSalarySettlement() {
|
||||||
long startTime = System.currentTimeMillis();
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
|
log.warn("bd_leader_salary_settlement skipped: salary settlement is temporarily paused");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
log.warn("========== BD Leader工资结算定时任务开始 ==========");
|
log.warn("========== BD Leader工资结算定时任务开始 ==========");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -61,8 +68,13 @@ public class BdLeaderSalarySettlementTask {
|
|||||||
/**
|
/**
|
||||||
* 测试方法(手动触发).
|
* 测试方法(手动触发).
|
||||||
*/
|
*/
|
||||||
public void processBdLeaderSalarySettlementTest(Integer billBelong) {
|
public void processBdLeaderSalarySettlementTest(Integer billBelong) {
|
||||||
String billTitle = TeamBillCycleUtils.parseBillBelongToDateRangeStr(billBelong);
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
|
log.warn("bd_leader_salary_settlement_test skipped: salary settlement is temporarily paused");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String billTitle = TeamBillCycleUtils.parseBillBelongToDateRangeStr(billBelong);
|
||||||
bdLeaderSalarySettlementService.processAllBdLeaderSettlement(billBelong, billTitle);
|
bdLeaderSalarySettlementService.processAllBdLeaderSettlement(billBelong, billTitle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,9 +18,11 @@ import org.springframework.stereotype.Component;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class BdSalarySettlementTask {
|
public class BdSalarySettlementTask {
|
||||||
|
|
||||||
private final BdSalarySettlementService bdSalarySettlementService;
|
private static final boolean SALARY_SETTLEMENT_PAUSED = true;
|
||||||
|
|
||||||
|
private final BdSalarySettlementService bdSalarySettlementService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每月1号0点30分执行上月整月结算.
|
* 每月1号0点30分执行上月整月结算.
|
||||||
@ -28,7 +30,12 @@ public class BdSalarySettlementTask {
|
|||||||
@Scheduled(cron = "0 30 0 1 * ?", zone = "Asia/Riyadh")
|
@Scheduled(cron = "0 30 0 1 * ?", zone = "Asia/Riyadh")
|
||||||
@TaskCacheLock(key = "BD_SALARY_SETTLEMENT", expireSecond = 86400)
|
@TaskCacheLock(key = "BD_SALARY_SETTLEMENT", expireSecond = 86400)
|
||||||
public void processBdSalarySettlement() {
|
public void processBdSalarySettlement() {
|
||||||
long startTime = System.currentTimeMillis();
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
|
log.warn("bd_salary_settlement skipped: salary settlement is temporarily paused");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
log.warn("========== BD工资结算定时任务开始 ==========");
|
log.warn("========== BD工资结算定时任务开始 ==========");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -61,8 +68,13 @@ public class BdSalarySettlementTask {
|
|||||||
/**
|
/**
|
||||||
* 测试方法(手动触发).
|
* 测试方法(手动触发).
|
||||||
*/
|
*/
|
||||||
public void processBdSalarySettlementTest(Integer billBelong) {
|
public void processBdSalarySettlementTest(Integer billBelong) {
|
||||||
String billTitle = TeamBillCycleUtils.parseBillBelongToDateRangeStr(billBelong);
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
|
log.warn("bd_salary_settlement_test skipped: salary settlement is temporarily paused");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String billTitle = TeamBillCycleUtils.parseBillBelongToDateRangeStr(billBelong);
|
||||||
bdSalarySettlementService.processAllBdSettlement(billBelong, billTitle);
|
bdSalarySettlementService.processAllBdSettlement(billBelong, billTitle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,9 +29,11 @@ import org.springframework.stereotype.Component;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class TeamBillTask {
|
public class TeamBillTask {
|
||||||
|
|
||||||
private final TeamSalaryMqMessage otherMqMessage;
|
private static final boolean SALARY_SETTLEMENT_PAUSED = true;
|
||||||
|
|
||||||
|
private final TeamSalaryMqMessage otherMqMessage;
|
||||||
private final TeamProfileService teamProfileService;
|
private final TeamProfileService teamProfileService;
|
||||||
private final TeamBillCycleService teamBillCycleService;
|
private final TeamBillCycleService teamBillCycleService;
|
||||||
private final GiftGiveRunningWaterService giftGiveRunningWaterService;
|
private final GiftGiveRunningWaterService giftGiveRunningWaterService;
|
||||||
@ -55,8 +57,13 @@ public class TeamBillTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void processTeamBill() {
|
private void processTeamBill() {
|
||||||
log.warn("开始执行账单处理:{},{}", ZonedDateTimeUtils.nowAsiaRiyadhToInt(), LocalDateTime.now());
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
|
log.warn("process_team_bill skipped: salary settlement is temporarily paused");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.warn("开始执行账单处理:{},{}", ZonedDateTimeUtils.nowAsiaRiyadhToInt(), LocalDateTime.now());
|
||||||
// 出单
|
// 出单
|
||||||
teamBillCycleService.billStatusPayOut();
|
teamBillCycleService.billStatusPayOut();
|
||||||
|
|
||||||
@ -65,10 +72,15 @@ public class TeamBillTask {
|
|||||||
log.warn("结束账单处理");
|
log.warn("结束账单处理");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processTeamBillRetry() {
|
public void processTeamBillRetry() {
|
||||||
// 创建本月账单,发出结算信号
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
consumeProcessPayOutBill();
|
log.warn("process_team_bill_retry skipped: salary settlement is temporarily paused");
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建本月账单,发出结算信号
|
||||||
|
consumeProcessPayOutBill();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建本月账单,发出结算信号.
|
* 创建本月账单,发出结算信号.
|
||||||
|
|||||||
@ -24,10 +24,12 @@ import org.springframework.stereotype.Component;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class TeamSalaryPaymentTask {
|
public class TeamSalaryPaymentTask {
|
||||||
|
|
||||||
private final TeamProfileService teamProfileService;
|
private static final boolean SALARY_SETTLEMENT_PAUSED = true;
|
||||||
private final TeamSalaryMqMessage teamSalaryMqMessage;
|
|
||||||
|
private final TeamProfileService teamProfileService;
|
||||||
|
private final TeamSalaryMqMessage teamSalaryMqMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每天凌晨0点过30秒执行一次,处理团队工资结算.
|
* 每天凌晨0点过30秒执行一次,处理团队工资结算.
|
||||||
@ -35,6 +37,11 @@ public class TeamSalaryPaymentTask {
|
|||||||
@Scheduled(cron = "30 1 0 * * ?", zone = "Asia/Riyadh")
|
@Scheduled(cron = "30 1 0 * * ?", zone = "Asia/Riyadh")
|
||||||
@TaskCacheLock(key = "TEAM_SALARY_PAYMENT_TASK", expireSecond = 10800)
|
@TaskCacheLock(key = "TEAM_SALARY_PAYMENT_TASK", expireSecond = 10800)
|
||||||
public void teamSalaryPaymentTask() {
|
public void teamSalaryPaymentTask() {
|
||||||
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
|
log.warn("team_salary_payment_task skipped: salary settlement is temporarily paused");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
log.warn("exec team_salary_payment_task start");
|
log.warn("exec team_salary_payment_task start");
|
||||||
|
|
||||||
@ -66,9 +73,13 @@ public class TeamSalaryPaymentTask {
|
|||||||
log.warn("exec team_salary_payment_task end with {}",System.currentTimeMillis()-startTime);
|
log.warn("exec team_salary_payment_task end with {}",System.currentTimeMillis()-startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void teamSalaryPaymentTaskTest() {
|
public void teamSalaryPaymentTaskTest() {
|
||||||
|
if (SALARY_SETTLEMENT_PAUSED) {
|
||||||
log.warn("支付团队工资 start,时间:{}", TimestampUtils.now());
|
log.warn("team_salary_payment_task_test skipped: salary settlement is temporarily paused");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.warn("支付团队工资 start,时间:{}", TimestampUtils.now());
|
||||||
|
|
||||||
// 是否本月一号
|
// 是否本月一号
|
||||||
Boolean thisMonthFirstDay = Objects.equals(ZonedDateTimeUtils.nowAsiaRiyadhToInt(),
|
Boolean thisMonthFirstDay = Objects.equals(ZonedDateTimeUtils.nowAsiaRiyadhToInt(),
|
||||||
|
|||||||
@ -84,9 +84,10 @@ public class PropsActivitySendCommon {
|
|||||||
private final RoomProfileManagerService roomProfileManagerService;
|
private final RoomProfileManagerService roomProfileManagerService;
|
||||||
private final ActivitySourceGroupGateway activitySourceGroupGateway;
|
private final ActivitySourceGroupGateway activitySourceGroupGateway;
|
||||||
private final PropsMaterialInfraConvertor propsMaterialInfraConvertor;
|
private final PropsMaterialInfraConvertor propsMaterialInfraConvertor;
|
||||||
private final PropsVipActualEquityService propsVipActualEquityService;
|
private final PropsVipActualEquityService propsVipActualEquityService;
|
||||||
private final ActivityReceiveRewardLogService activityReceiveRewardLogService;
|
private final VipActivityRewardCommon vipActivityRewardCommon;
|
||||||
private final PropsActivityRewardConfigService propsActivityRewardConfigService;
|
private final ActivityReceiveRewardLogService activityReceiveRewardLogService;
|
||||||
|
private final PropsActivityRewardConfigService propsActivityRewardConfigService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 领取活动奖励.
|
* 领取活动奖励.
|
||||||
@ -145,12 +146,20 @@ public class PropsActivitySendCommon {
|
|||||||
* 发送单个-活动道具.
|
* 发送单个-活动道具.
|
||||||
*/
|
*/
|
||||||
public void sendActivitySingle(SendRewardSingle param) {
|
public void sendActivitySingle(SendRewardSingle param) {
|
||||||
if (Objects.isNull(param.getRewardConfig())) {
|
if (Objects.isNull(param.getRewardConfig())) {
|
||||||
throw new IllegalArgumentException("Send rewardConfig is null.");
|
throw new IllegalArgumentException("Send rewardConfig is null.");
|
||||||
}
|
}
|
||||||
PropsActivityRewardConfig rewardConfig = param.getRewardConfig();
|
PropsActivityRewardConfig rewardConfig = param.getRewardConfig();
|
||||||
sendGroup(param, Collections.singletonList(toPrizeDescribe(rewardConfig)));
|
if (isVipLevelReward(param, rewardConfig)) {
|
||||||
}
|
vipActivityRewardCommon.gift(param.getSysOrigin(),
|
||||||
|
param.getAcceptUserId(),
|
||||||
|
param.getTrackId(),
|
||||||
|
rewardConfig.getContent(),
|
||||||
|
param.getOrigin());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendGroup(param, Collections.singletonList(toPrizeDescribe(rewardConfig)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送奖励.
|
* 发送奖励.
|
||||||
@ -159,17 +168,33 @@ public class PropsActivitySendCommon {
|
|||||||
List<PropsActivityRewardConfig> configs = propsActivityRewardConfigService.listByGroupId(
|
List<PropsActivityRewardConfig> configs = propsActivityRewardConfigService.listByGroupId(
|
||||||
param.getResourceGroupId());
|
param.getResourceGroupId());
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(configs)) {
|
if (CollectionUtils.isEmpty(configs)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
propsSendCommon.send(new PrizeDescribeRewardCmd()
|
|
||||||
.setTrackId(param.getTrackId())
|
List<PropsActivityRewardConfig> vipConfigs = configs.stream()
|
||||||
.setAcceptUserId(param.getAcceptUserId())
|
.filter(config -> isVipLevelReward(param, config))
|
||||||
.setOrigin(param.getOrigin())
|
.toList();
|
||||||
.setSysOrigin(param.getSysOrigin())
|
vipConfigs.forEach(config -> vipActivityRewardCommon.gift(param.getSysOrigin(),
|
||||||
.setPrizes(toListPrizeDescribe(configs))
|
param.getAcceptUserId(),
|
||||||
);
|
param.getTrackId(),
|
||||||
}
|
config.getContent(),
|
||||||
|
param.getOrigin()));
|
||||||
|
|
||||||
|
List<PropsActivityRewardConfig> normalConfigs = configs.stream()
|
||||||
|
.filter(config -> !isVipLevelReward(param, config))
|
||||||
|
.toList();
|
||||||
|
if (CollectionUtils.isEmpty(normalConfigs)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
propsSendCommon.send(new PrizeDescribeRewardCmd()
|
||||||
|
.setTrackId(param.getTrackId())
|
||||||
|
.setAcceptUserId(param.getAcceptUserId())
|
||||||
|
.setOrigin(param.getOrigin())
|
||||||
|
.setSysOrigin(param.getSysOrigin())
|
||||||
|
.setPrizes(toListPrizeDescribe(normalConfigs))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,10 +221,16 @@ public class PropsActivitySendCommon {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PropsActivityRewardEnum.PROPS.eq(key)) {
|
if (PropsActivityRewardEnum.PROPS.eq(key)) {
|
||||||
sendProps(param, prizeArrays);
|
sendVipLevelRewards(param, prizeArrays);
|
||||||
return;
|
List<PrizeDescribe> normalProps = prizeArrays.stream()
|
||||||
}
|
.filter(prize -> !isVipLevelReward(param, prize))
|
||||||
|
.toList();
|
||||||
|
if (CollectionUtils.isNotEmpty(normalProps)) {
|
||||||
|
sendProps(param, normalProps);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (PropsActivityRewardEnum.FRAGMENTS.eq(key)) {
|
if (PropsActivityRewardEnum.FRAGMENTS.eq(key)) {
|
||||||
|
|
||||||
@ -272,14 +303,36 @@ public class PropsActivitySendCommon {
|
|||||||
return configs.stream().map(this::toPrizeDescribe).collect(Collectors.toList());
|
return configs.stream().map(this::toPrizeDescribe).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private PrizeDescribe toPrizeDescribe(PropsActivityRewardConfig config) {
|
private PrizeDescribe toPrizeDescribe(PropsActivityRewardConfig config) {
|
||||||
return new PrizeDescribe()
|
return new PrizeDescribe()
|
||||||
.setTrackId(config.getGroupId())
|
.setTrackId(config.getGroupId())
|
||||||
.setType(config.getType())
|
.setType(config.getType())
|
||||||
.setDetailType(config.getDetailType())
|
.setDetailType(config.getDetailType())
|
||||||
.setContent(config.getContent())
|
.setContent(config.getContent())
|
||||||
.setQuantity(config.getQuantity());
|
.setQuantity(config.getQuantity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendVipLevelRewards(SendRewardAbstract param, List<PrizeDescribe> prizeArrays) {
|
||||||
|
prizeArrays.stream()
|
||||||
|
.filter(prize -> isVipLevelReward(param, prize))
|
||||||
|
.forEach(prize -> vipActivityRewardCommon.gift(param.getSysOrigin(),
|
||||||
|
param.getAcceptUserId(),
|
||||||
|
param.getTrackId(),
|
||||||
|
prize.getContent(),
|
||||||
|
param.getOrigin()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVipLevelReward(SendRewardAbstract param, PropsActivityRewardConfig config) {
|
||||||
|
return Objects.nonNull(param.getSysOrigin())
|
||||||
|
&& vipActivityRewardCommon.isVipDetail(config.getType(), config.getDetailType())
|
||||||
|
&& vipActivityRewardCommon.existsEnabledConfig(param.getSysOrigin(), config.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVipLevelReward(SendRewardAbstract param, PrizeDescribe prize) {
|
||||||
|
return Objects.nonNull(param.getSysOrigin())
|
||||||
|
&& vipActivityRewardCommon.isVipDetail(prize.getType(), prize.getDetailType())
|
||||||
|
&& vipActivityRewardCommon.existsEnabledConfig(param.getSysOrigin(), prize.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
private void sendEmoji(SendRewardAbstract param, List<PrizeDescribe> val) {
|
private void sendEmoji(SendRewardAbstract param, List<PrizeDescribe> val) {
|
||||||
val.forEach(props ->
|
val.forEach(props ->
|
||||||
|
|||||||
@ -0,0 +1,346 @@
|
|||||||
|
package com.red.circle.other.infra.common.activity;
|
||||||
|
|
||||||
|
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||||
|
import com.red.circle.common.business.enums.SendPropsOrigin;
|
||||||
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
|
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||||
|
import com.red.circle.framework.core.response.ResponseErrorCode;
|
||||||
|
import com.red.circle.framework.mybatis.constant.PageConstant;
|
||||||
|
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.badge.BadgeBackpack;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.props.PropsBackpack;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.props.RunningWaterUserProps;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.UserVipState;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.VipLevelConfig;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.VipOrderRecord;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.badge.BadgeBackpackService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.props.PropsBackpackService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.props.RunningWaterUserPropsService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.vip.UserVipStateService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.vip.VipLevelConfigService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.vip.VipOrderRecordService;
|
||||||
|
import com.red.circle.other.inner.enums.material.BadgeBackpackExpireType;
|
||||||
|
import com.red.circle.other.inner.enums.material.PropsCommodityType;
|
||||||
|
import com.red.circle.tool.core.date.TimestampUtils;
|
||||||
|
import com.red.circle.tool.core.parse.DataTypeUtils;
|
||||||
|
import com.red.circle.tool.core.sequence.IdWorkerUtils;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends operator-managed VIP rewards from resource groups.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class VipActivityRewardCommon {
|
||||||
|
|
||||||
|
public static final String VIP_DETAIL_TYPE = "NOBLE_VIP";
|
||||||
|
|
||||||
|
private static final int DEFAULT_DURATION_DAYS = 30;
|
||||||
|
private static final String STATUS_ACTIVE = "ACTIVE";
|
||||||
|
private static final String STATUS_SUCCESS = "SUCCESS";
|
||||||
|
private static final String ORDER_TYPE_RESOURCE_GROUP = "RESOURCE_GROUP";
|
||||||
|
private static final String EVENT_PREFIX = "RESOURCE-GROUP-VIP-";
|
||||||
|
private static final String WATER_ORIGIN = "VIP_PURCHASE";
|
||||||
|
private static final String WATER_ORIGIN_DESC = "VIP purchase";
|
||||||
|
private static final Timestamp MYSQL_DATETIME_MAX = Timestamp.valueOf("2038-01-19 00:00:00");
|
||||||
|
|
||||||
|
private final UserProfileGateway userProfileGateway;
|
||||||
|
private final BadgeBackpackService badgeBackpackService;
|
||||||
|
private final PropsBackpackService propsBackpackService;
|
||||||
|
private final UserVipStateService userVipStateService;
|
||||||
|
private final VipLevelConfigService vipLevelConfigService;
|
||||||
|
private final VipOrderRecordService vipOrderRecordService;
|
||||||
|
private final RunningWaterUserPropsService runningWaterUserPropsService;
|
||||||
|
|
||||||
|
public boolean isVipDetail(String type, String detailType) {
|
||||||
|
return Objects.equals("PROPS", type) && Objects.equals(VIP_DETAIL_TYPE, detailType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean existsEnabledConfig(SysOriginPlatformEnum sysOrigin, String content) {
|
||||||
|
Long configId = DataTypeUtils.toLong(content);
|
||||||
|
return Objects.nonNull(vipLevelConfigService.getEnabledById(sysOrigin.name(), configId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void gift(SysOriginPlatformEnum sysOrigin, Long userId, Long trackId, String content,
|
||||||
|
SendPropsOrigin origin) {
|
||||||
|
Long configId = DataTypeUtils.toLong(content);
|
||||||
|
VipLevelConfig config = vipLevelConfigService.getEnabledById(sysOrigin.name(), configId);
|
||||||
|
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_MAPPING_INFO, config);
|
||||||
|
|
||||||
|
int durationDays = durationDays(config);
|
||||||
|
Timestamp now = TimestampUtils.now();
|
||||||
|
UserVipState currentState = getUserVipState(sysOrigin.name(), userId);
|
||||||
|
boolean currentActive = isActive(currentState, now);
|
||||||
|
int fromLevel = currentActive ? Objects.requireNonNullElse(currentState.getLevel(), 0) : 0;
|
||||||
|
|
||||||
|
ResponseAssert.isFalse(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
|
||||||
|
currentActive && fromLevel > Objects.requireNonNullElse(config.getLevel(), 0));
|
||||||
|
|
||||||
|
Timestamp startAt = currentActive && Objects.nonNull(currentState.getStartAt())
|
||||||
|
? currentState.getStartAt()
|
||||||
|
: now;
|
||||||
|
Timestamp expireAt = capExpireTime(resolveExpireAt(currentState, config, currentActive, now));
|
||||||
|
Long orderId = IdWorkerUtils.getId();
|
||||||
|
String eventId = EVENT_PREFIX + orderId;
|
||||||
|
|
||||||
|
vipOrderRecordService.save(buildOrder(orderId, eventId, sysOrigin.name(), userId, fromLevel,
|
||||||
|
config, startAt, expireAt, now));
|
||||||
|
upsertUserVipState(currentState, sysOrigin.name(), userId, config, startAt, expireAt, now);
|
||||||
|
giftVipResources(userId, trackId, config, expireAt, durationDays, now, origin);
|
||||||
|
userProfileGateway.removeCacheAll(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private VipOrderRecord buildOrder(Long orderId, String eventId, String sysOrigin, Long userId,
|
||||||
|
Integer fromLevel, VipLevelConfig config, Timestamp startAt, Timestamp expireAt,
|
||||||
|
Timestamp now) {
|
||||||
|
VipOrderRecord order = new VipOrderRecord()
|
||||||
|
.setId(orderId)
|
||||||
|
.setEventId(eventId)
|
||||||
|
.setSysOrigin(sysOrigin)
|
||||||
|
.setUserId(userId)
|
||||||
|
.setOrderType(ORDER_TYPE_RESOURCE_GROUP)
|
||||||
|
.setFromLevel(fromLevel)
|
||||||
|
.setToLevel(config.getLevel())
|
||||||
|
.setDurationDays(durationDays(config))
|
||||||
|
.setOriginalPriceGold(Objects.requireNonNullElse(config.getPriceGold(), 0L))
|
||||||
|
.setPaidGold(0L)
|
||||||
|
.setStatus(STATUS_SUCCESS)
|
||||||
|
.setStartAt(startAt)
|
||||||
|
.setExpireAt(expireAt)
|
||||||
|
.setErrorMessage("");
|
||||||
|
order.setCreateTime(now);
|
||||||
|
order.setUpdateTime(now);
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void upsertUserVipState(UserVipState currentState, String sysOrigin, Long userId,
|
||||||
|
VipLevelConfig config, Timestamp startAt, Timestamp expireAt, Timestamp now) {
|
||||||
|
UserVipState state = Objects.nonNull(currentState)
|
||||||
|
? currentState
|
||||||
|
: new UserVipState().setId(IdWorkerUtils.getId());
|
||||||
|
if (Objects.isNull(currentState)) {
|
||||||
|
state.setCreateTime(now);
|
||||||
|
}
|
||||||
|
state.setSysOrigin(sysOrigin);
|
||||||
|
state.setUserId(userId);
|
||||||
|
state.setLevel(config.getLevel());
|
||||||
|
state.setLevelCode(levelCode(config));
|
||||||
|
state.setDisplayName(displayName(config));
|
||||||
|
state.setStatus(STATUS_ACTIVE);
|
||||||
|
state.setStartAt(startAt);
|
||||||
|
state.setExpireAt(expireAt);
|
||||||
|
copyResources(state, config);
|
||||||
|
state.setUpdateTime(now);
|
||||||
|
if (Objects.nonNull(currentState)) {
|
||||||
|
userVipStateService.updateSelectiveById(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
userVipStateService.save(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyResources(UserVipState state, VipLevelConfig config) {
|
||||||
|
state.setBadgeResourceId(config.getBadgeResourceId());
|
||||||
|
state.setBadgeName(config.getBadgeName());
|
||||||
|
state.setBadgeUrl(config.getBadgeUrl());
|
||||||
|
state.setShortBadgeResourceId(config.getShortBadgeResourceId());
|
||||||
|
state.setShortBadgeName(config.getShortBadgeName());
|
||||||
|
state.setShortBadgeUrl(config.getShortBadgeUrl());
|
||||||
|
state.setAvatarFrameResourceId(config.getAvatarFrameResourceId());
|
||||||
|
state.setAvatarFrameName(config.getAvatarFrameName());
|
||||||
|
state.setAvatarFrameUrl(config.getAvatarFrameUrl());
|
||||||
|
state.setEntryEffectResourceId(config.getEntryEffectResourceId());
|
||||||
|
state.setEntryEffectName(config.getEntryEffectName());
|
||||||
|
state.setEntryEffectUrl(config.getEntryEffectUrl());
|
||||||
|
state.setChatBubbleResourceId(config.getChatBubbleResourceId());
|
||||||
|
state.setChatBubbleName(config.getChatBubbleName());
|
||||||
|
state.setChatBubbleUrl(config.getChatBubbleUrl());
|
||||||
|
state.setFloatPictureResourceId(config.getFloatPictureResourceId());
|
||||||
|
state.setFloatPictureName(config.getFloatPictureName());
|
||||||
|
state.setFloatPictureUrl(config.getFloatPictureUrl());
|
||||||
|
state.setBackgroundCardResourceId(config.getBackgroundCardResourceId());
|
||||||
|
state.setBackgroundCardName(config.getBackgroundCardName());
|
||||||
|
state.setBackgroundCardUrl(config.getBackgroundCardUrl());
|
||||||
|
state.setEffectImageResourceId(config.getEffectImageResourceId());
|
||||||
|
state.setEffectImageName(config.getEffectImageName());
|
||||||
|
state.setEffectImageUrl(config.getEffectImageUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void giftVipResources(Long userId, Long trackId, VipLevelConfig config,
|
||||||
|
Timestamp expireAt, Integer days, Timestamp now, SendPropsOrigin origin) {
|
||||||
|
for (VipResourceGrant resource : vipResourcesFromConfig(config)) {
|
||||||
|
if (resource.badge) {
|
||||||
|
giveBadge(userId, resource.resourceId, expireAt, days);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
giveProp(userId, trackId, resource.resourceId, resource.type, expireAt, days, now, origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<VipResourceGrant> vipResourcesFromConfig(VipLevelConfig config) {
|
||||||
|
return List.of(
|
||||||
|
VipResourceGrant.badge(config.getBadgeResourceId()),
|
||||||
|
VipResourceGrant.badge(config.getShortBadgeResourceId()),
|
||||||
|
VipResourceGrant.prop(config.getAvatarFrameResourceId(), PropsCommodityType.AVATAR_FRAME),
|
||||||
|
VipResourceGrant.prop(config.getEntryEffectResourceId(), PropsCommodityType.RIDE),
|
||||||
|
VipResourceGrant.prop(config.getChatBubbleResourceId(), PropsCommodityType.CHAT_BUBBLE),
|
||||||
|
VipResourceGrant.prop(config.getFloatPictureResourceId(), PropsCommodityType.FLOAT_PICTURE),
|
||||||
|
VipResourceGrant.prop(config.getBackgroundCardResourceId(), PropsCommodityType.DATA_CARD)
|
||||||
|
).stream().filter(VipResourceGrant::valid).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void giveBadge(Long userId, Long badgeId, Timestamp expireAt, Integer days) {
|
||||||
|
badgeBackpackService.activationTemporaryAndUse(userId, badgeId, days);
|
||||||
|
BadgeBackpack backpack = badgeBackpackService.getByUserIdByBadgeId(userId, badgeId);
|
||||||
|
if (Objects.isNull(backpack)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
backpack.setUseProps(Boolean.TRUE);
|
||||||
|
backpack.setExpireType(BadgeBackpackExpireType.TEMPORARY.name());
|
||||||
|
backpack.setExpireTime(expireAt);
|
||||||
|
badgeBackpackService.updateSelectiveById(backpack);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void giveProp(Long userId, Long trackId, Long propsId, PropsCommodityType type,
|
||||||
|
Timestamp expireAt, Integer days, Timestamp now, SendPropsOrigin origin) {
|
||||||
|
PropsBackpack oldBackpack = propsBackpackService.getUserProps(userId, propsId, type);
|
||||||
|
boolean useProps = resolveUseProps(userId, propsId, type, oldBackpack, now);
|
||||||
|
propsBackpackService.addPropsBackpack(new PropsBackpack()
|
||||||
|
.setUserId(userId)
|
||||||
|
.setPropsId(propsId)
|
||||||
|
.setType(type.name())
|
||||||
|
.setExpireTime(expireAt)
|
||||||
|
.setUseProps(useProps)
|
||||||
|
.setAllowGive(Boolean.FALSE));
|
||||||
|
|
||||||
|
RunningWaterUserProps water = new RunningWaterUserProps()
|
||||||
|
.setUserId(userId)
|
||||||
|
.setPropsId(propsId)
|
||||||
|
.setPropsCandy(BigDecimal.ZERO)
|
||||||
|
.setType(type.name())
|
||||||
|
.setOrigin(Objects.nonNull(origin) ? origin.name() : WATER_ORIGIN)
|
||||||
|
.setOriginDesc(Objects.nonNull(origin) ? origin.getDesc() : WATER_ORIGIN_DESC)
|
||||||
|
.setDays(days);
|
||||||
|
water.setCreateTime(now);
|
||||||
|
water.setUpdateTime(now);
|
||||||
|
water.setCreateUser(Objects.requireNonNullElse(trackId, 0L));
|
||||||
|
water.setUpdateUser(0L);
|
||||||
|
runningWaterUserPropsService.save(water);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean resolveUseProps(Long userId, Long propsId, PropsCommodityType type,
|
||||||
|
PropsBackpack oldBackpack, Timestamp now) {
|
||||||
|
if (Objects.nonNull(oldBackpack)) {
|
||||||
|
return Boolean.TRUE.equals(oldBackpack.getUseProps());
|
||||||
|
}
|
||||||
|
List<PropsBackpack> notExpiredSameType = propsBackpackService.query()
|
||||||
|
.eq(PropsBackpack::getUserId, userId)
|
||||||
|
.eq(PropsBackpack::getType, type.name())
|
||||||
|
.gt(PropsBackpack::getExpireTime, now)
|
||||||
|
.list();
|
||||||
|
return notExpiredSameType.stream()
|
||||||
|
.noneMatch(item -> Boolean.TRUE.equals(item.getUseProps())
|
||||||
|
&& !Objects.equals(item.getPropsId(), propsId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserVipState getUserVipState(String sysOrigin, Long userId) {
|
||||||
|
return userVipStateService.query()
|
||||||
|
.eq(UserVipState::getSysOrigin, sysOrigin)
|
||||||
|
.eq(UserVipState::getUserId, userId)
|
||||||
|
.last(PageConstant.LIMIT_ONE)
|
||||||
|
.getOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isActive(UserVipState state, Timestamp now) {
|
||||||
|
return Objects.nonNull(state)
|
||||||
|
&& STATUS_ACTIVE.equals(state.getStatus())
|
||||||
|
&& Objects.nonNull(state.getExpireAt())
|
||||||
|
&& state.getExpireAt().after(now)
|
||||||
|
&& Objects.nonNull(state.getLevel())
|
||||||
|
&& state.getLevel() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timestamp resolveExpireAt(UserVipState currentState, VipLevelConfig config,
|
||||||
|
boolean currentActive, Timestamp now) {
|
||||||
|
Timestamp plusDuration = plusDays(now, durationDays(config));
|
||||||
|
if (!currentActive) {
|
||||||
|
return plusDuration;
|
||||||
|
}
|
||||||
|
if (Objects.equals(currentState.getLevel(), config.getLevel())) {
|
||||||
|
return plusDays(max(currentState.getExpireAt(), now), durationDays(config));
|
||||||
|
}
|
||||||
|
return max(currentState.getExpireAt(), plusDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int durationDays(VipLevelConfig config) {
|
||||||
|
Integer days = config.getDurationDays();
|
||||||
|
return Objects.nonNull(days) && days > 0 ? days : DEFAULT_DURATION_DAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String levelCode(VipLevelConfig config) {
|
||||||
|
if (Objects.nonNull(config.getLevelCode()) && !config.getLevelCode().isBlank()) {
|
||||||
|
return config.getLevelCode();
|
||||||
|
}
|
||||||
|
return "VIP" + Objects.requireNonNullElse(config.getLevel(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String displayName(VipLevelConfig config) {
|
||||||
|
if (Objects.nonNull(config.getDisplayName()) && !config.getDisplayName().isBlank()) {
|
||||||
|
return config.getDisplayName();
|
||||||
|
}
|
||||||
|
return "VIP " + Objects.requireNonNullElse(config.getLevel(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timestamp max(Timestamp first, Timestamp second) {
|
||||||
|
if (Objects.isNull(first)) {
|
||||||
|
return second;
|
||||||
|
}
|
||||||
|
if (Objects.isNull(second)) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
return first.after(second) ? first : second;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timestamp plusDays(Timestamp value, int days) {
|
||||||
|
return Timestamp.from(value.toInstant().plus(Duration.ofDays(days)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timestamp capExpireTime(Timestamp expireTime) {
|
||||||
|
if (Objects.isNull(expireTime)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return expireTime.after(MYSQL_DATETIME_MAX) ? MYSQL_DATETIME_MAX : expireTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class VipResourceGrant {
|
||||||
|
|
||||||
|
private final Long resourceId;
|
||||||
|
private final PropsCommodityType type;
|
||||||
|
private final boolean badge;
|
||||||
|
|
||||||
|
private VipResourceGrant(Long resourceId, PropsCommodityType type, boolean badge) {
|
||||||
|
this.resourceId = resourceId;
|
||||||
|
this.type = type;
|
||||||
|
this.badge = badge;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static VipResourceGrant badge(Long resourceId) {
|
||||||
|
return new VipResourceGrant(resourceId, null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static VipResourceGrant prop(Long resourceId, PropsCommodityType type) {
|
||||||
|
return new VipResourceGrant(resourceId, type, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean valid() {
|
||||||
|
return Objects.nonNull(resourceId) && resourceId > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.dao.vip;
|
||||||
|
|
||||||
|
import com.red.circle.framework.mybatis.dao.BaseDAO;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.UserVipState;
|
||||||
|
|
||||||
|
public interface UserVipStateDAO extends BaseDAO<UserVipState> {
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.dao.vip;
|
||||||
|
|
||||||
|
import com.red.circle.framework.mybatis.dao.BaseDAO;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.VipLevelConfig;
|
||||||
|
|
||||||
|
public interface VipLevelConfigDAO extends BaseDAO<VipLevelConfig> {
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.dao.vip;
|
||||||
|
|
||||||
|
import com.red.circle.framework.mybatis.dao.BaseDAO;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.VipOrderRecord;
|
||||||
|
|
||||||
|
public interface VipOrderRecordDAO extends BaseDAO<VipOrderRecord> {
|
||||||
|
}
|
||||||
@ -0,0 +1,130 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.entity.vip;
|
||||||
|
|
||||||
|
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 java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User VIP state.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("user_vip_state")
|
||||||
|
public class UserVipState implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.INPUT)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@TableField("sys_origin")
|
||||||
|
private String sysOrigin;
|
||||||
|
|
||||||
|
@TableField("user_id")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@TableField("level")
|
||||||
|
private Integer level;
|
||||||
|
|
||||||
|
@TableField("level_code")
|
||||||
|
private String levelCode;
|
||||||
|
|
||||||
|
@TableField("display_name")
|
||||||
|
private String displayName;
|
||||||
|
|
||||||
|
@TableField("status")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@TableField("start_at")
|
||||||
|
private Timestamp startAt;
|
||||||
|
|
||||||
|
@TableField("expire_at")
|
||||||
|
private Timestamp expireAt;
|
||||||
|
|
||||||
|
@TableField("badge_resource_id")
|
||||||
|
private Long badgeResourceId;
|
||||||
|
|
||||||
|
@TableField("badge_name")
|
||||||
|
private String badgeName;
|
||||||
|
|
||||||
|
@TableField("badge_url")
|
||||||
|
private String badgeUrl;
|
||||||
|
|
||||||
|
@TableField("short_badge_resource_id")
|
||||||
|
private Long shortBadgeResourceId;
|
||||||
|
|
||||||
|
@TableField("short_badge_name")
|
||||||
|
private String shortBadgeName;
|
||||||
|
|
||||||
|
@TableField("short_badge_url")
|
||||||
|
private String shortBadgeUrl;
|
||||||
|
|
||||||
|
@TableField("avatar_frame_resource_id")
|
||||||
|
private Long avatarFrameResourceId;
|
||||||
|
|
||||||
|
@TableField("avatar_frame_name")
|
||||||
|
private String avatarFrameName;
|
||||||
|
|
||||||
|
@TableField("avatar_frame_url")
|
||||||
|
private String avatarFrameUrl;
|
||||||
|
|
||||||
|
@TableField("entry_effect_resource_id")
|
||||||
|
private Long entryEffectResourceId;
|
||||||
|
|
||||||
|
@TableField("entry_effect_name")
|
||||||
|
private String entryEffectName;
|
||||||
|
|
||||||
|
@TableField("entry_effect_url")
|
||||||
|
private String entryEffectUrl;
|
||||||
|
|
||||||
|
@TableField("chat_bubble_resource_id")
|
||||||
|
private Long chatBubbleResourceId;
|
||||||
|
|
||||||
|
@TableField("chat_bubble_name")
|
||||||
|
private String chatBubbleName;
|
||||||
|
|
||||||
|
@TableField("chat_bubble_url")
|
||||||
|
private String chatBubbleUrl;
|
||||||
|
|
||||||
|
@TableField("float_picture_resource_id")
|
||||||
|
private Long floatPictureResourceId;
|
||||||
|
|
||||||
|
@TableField("float_picture_name")
|
||||||
|
private String floatPictureName;
|
||||||
|
|
||||||
|
@TableField("float_picture_url")
|
||||||
|
private String floatPictureUrl;
|
||||||
|
|
||||||
|
@TableField("background_card_resource_id")
|
||||||
|
private Long backgroundCardResourceId;
|
||||||
|
|
||||||
|
@TableField("background_card_name")
|
||||||
|
private String backgroundCardName;
|
||||||
|
|
||||||
|
@TableField("background_card_url")
|
||||||
|
private String backgroundCardUrl;
|
||||||
|
|
||||||
|
@TableField("effect_image_resource_id")
|
||||||
|
private Long effectImageResourceId;
|
||||||
|
|
||||||
|
@TableField("effect_image_name")
|
||||||
|
private String effectImageName;
|
||||||
|
|
||||||
|
@TableField("effect_image_url")
|
||||||
|
private String effectImageUrl;
|
||||||
|
|
||||||
|
@TableField("create_time")
|
||||||
|
private Timestamp createTime;
|
||||||
|
|
||||||
|
@TableField("update_time")
|
||||||
|
private Timestamp updateTime;
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.entity.vip;
|
||||||
|
|
||||||
|
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 java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VIP level config.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("vip_level_config")
|
||||||
|
public class VipLevelConfig implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.INPUT)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@TableField("sys_origin")
|
||||||
|
private String sysOrigin;
|
||||||
|
|
||||||
|
@TableField("level")
|
||||||
|
private Integer level;
|
||||||
|
|
||||||
|
@TableField("level_code")
|
||||||
|
private String levelCode;
|
||||||
|
|
||||||
|
@TableField("display_name")
|
||||||
|
private String displayName;
|
||||||
|
|
||||||
|
@TableField("enabled")
|
||||||
|
private Boolean enabled;
|
||||||
|
|
||||||
|
@TableField("duration_days")
|
||||||
|
private Integer durationDays;
|
||||||
|
|
||||||
|
@TableField("price_gold")
|
||||||
|
private Long priceGold;
|
||||||
|
|
||||||
|
@TableField("badge_resource_id")
|
||||||
|
private Long badgeResourceId;
|
||||||
|
|
||||||
|
@TableField("badge_name")
|
||||||
|
private String badgeName;
|
||||||
|
|
||||||
|
@TableField("badge_url")
|
||||||
|
private String badgeUrl;
|
||||||
|
|
||||||
|
@TableField("short_badge_resource_id")
|
||||||
|
private Long shortBadgeResourceId;
|
||||||
|
|
||||||
|
@TableField("short_badge_name")
|
||||||
|
private String shortBadgeName;
|
||||||
|
|
||||||
|
@TableField("short_badge_url")
|
||||||
|
private String shortBadgeUrl;
|
||||||
|
|
||||||
|
@TableField("avatar_frame_resource_id")
|
||||||
|
private Long avatarFrameResourceId;
|
||||||
|
|
||||||
|
@TableField("avatar_frame_name")
|
||||||
|
private String avatarFrameName;
|
||||||
|
|
||||||
|
@TableField("avatar_frame_url")
|
||||||
|
private String avatarFrameUrl;
|
||||||
|
|
||||||
|
@TableField("entry_effect_resource_id")
|
||||||
|
private Long entryEffectResourceId;
|
||||||
|
|
||||||
|
@TableField("entry_effect_name")
|
||||||
|
private String entryEffectName;
|
||||||
|
|
||||||
|
@TableField("entry_effect_url")
|
||||||
|
private String entryEffectUrl;
|
||||||
|
|
||||||
|
@TableField("chat_bubble_resource_id")
|
||||||
|
private Long chatBubbleResourceId;
|
||||||
|
|
||||||
|
@TableField("chat_bubble_name")
|
||||||
|
private String chatBubbleName;
|
||||||
|
|
||||||
|
@TableField("chat_bubble_url")
|
||||||
|
private String chatBubbleUrl;
|
||||||
|
|
||||||
|
@TableField("float_picture_resource_id")
|
||||||
|
private Long floatPictureResourceId;
|
||||||
|
|
||||||
|
@TableField("float_picture_name")
|
||||||
|
private String floatPictureName;
|
||||||
|
|
||||||
|
@TableField("float_picture_url")
|
||||||
|
private String floatPictureUrl;
|
||||||
|
|
||||||
|
@TableField("background_card_resource_id")
|
||||||
|
private Long backgroundCardResourceId;
|
||||||
|
|
||||||
|
@TableField("background_card_name")
|
||||||
|
private String backgroundCardName;
|
||||||
|
|
||||||
|
@TableField("background_card_url")
|
||||||
|
private String backgroundCardUrl;
|
||||||
|
|
||||||
|
@TableField("effect_image_resource_id")
|
||||||
|
private Long effectImageResourceId;
|
||||||
|
|
||||||
|
@TableField("effect_image_name")
|
||||||
|
private String effectImageName;
|
||||||
|
|
||||||
|
@TableField("effect_image_url")
|
||||||
|
private String effectImageUrl;
|
||||||
|
|
||||||
|
@TableField("create_time")
|
||||||
|
private Timestamp createTime;
|
||||||
|
|
||||||
|
@TableField("update_time")
|
||||||
|
private Timestamp updateTime;
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.entity.vip;
|
||||||
|
|
||||||
|
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 java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VIP order record.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("vip_order_record")
|
||||||
|
public class VipOrderRecord implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.INPUT)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@TableField("event_id")
|
||||||
|
private String eventId;
|
||||||
|
|
||||||
|
@TableField("sys_origin")
|
||||||
|
private String sysOrigin;
|
||||||
|
|
||||||
|
@TableField("user_id")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@TableField("order_type")
|
||||||
|
private String orderType;
|
||||||
|
|
||||||
|
@TableField("from_level")
|
||||||
|
private Integer fromLevel;
|
||||||
|
|
||||||
|
@TableField("to_level")
|
||||||
|
private Integer toLevel;
|
||||||
|
|
||||||
|
@TableField("duration_days")
|
||||||
|
private Integer durationDays;
|
||||||
|
|
||||||
|
@TableField("original_price_gold")
|
||||||
|
private Long originalPriceGold;
|
||||||
|
|
||||||
|
@TableField("paid_gold")
|
||||||
|
private Long paidGold;
|
||||||
|
|
||||||
|
@TableField("status")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@TableField("start_at")
|
||||||
|
private Timestamp startAt;
|
||||||
|
|
||||||
|
@TableField("expire_at")
|
||||||
|
private Timestamp expireAt;
|
||||||
|
|
||||||
|
@TableField("error_message")
|
||||||
|
private String errorMessage;
|
||||||
|
|
||||||
|
@TableField("create_time")
|
||||||
|
private Timestamp createTime;
|
||||||
|
|
||||||
|
@TableField("update_time")
|
||||||
|
private Timestamp updateTime;
|
||||||
|
}
|
||||||
@ -28,6 +28,7 @@ public class LoginLoggerServiceImpl extends BaseServiceImpl<LoginLoggerDAO, Logi
|
|||||||
return query()
|
return query()
|
||||||
.eq(Objects.nonNull(cmd.getUserId()), LoginLogger::getUserId, cmd.getUserId())
|
.eq(Objects.nonNull(cmd.getUserId()), LoginLogger::getUserId, cmd.getUserId())
|
||||||
.eq(StringUtils.isNotBlank(cmd.getDeviceId()), LoginLogger::getDeviceId, cmd.getDeviceId())
|
.eq(StringUtils.isNotBlank(cmd.getDeviceId()), LoginLogger::getDeviceId, cmd.getDeviceId())
|
||||||
|
.eq(StringUtils.isNotBlank(cmd.getIp()), LoginLogger::getIp, cmd.getIp())
|
||||||
.orderByDesc(LoginLogger::getCreateTime)
|
.orderByDesc(LoginLogger::getCreateTime)
|
||||||
.page(cmd.getPageQuery());
|
.page(cmd.getPageQuery());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.service.vip;
|
||||||
|
|
||||||
|
import com.red.circle.framework.mybatis.service.BaseService;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.UserVipState;
|
||||||
|
|
||||||
|
public interface UserVipStateService extends BaseService<UserVipState> {
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.service.vip;
|
||||||
|
|
||||||
|
import com.red.circle.framework.mybatis.service.BaseService;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.VipLevelConfig;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface VipLevelConfigService extends BaseService<VipLevelConfig> {
|
||||||
|
|
||||||
|
Map<Long, VipLevelConfig> mapByIds(Set<Long> ids);
|
||||||
|
|
||||||
|
Map<Long, VipLevelConfig> mapBySysOriginAndIds(String sysOrigin, Set<Long> ids);
|
||||||
|
|
||||||
|
VipLevelConfig getEnabledById(String sysOrigin, Long id);
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.service.vip;
|
||||||
|
|
||||||
|
import com.red.circle.framework.mybatis.service.BaseService;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.VipOrderRecord;
|
||||||
|
|
||||||
|
public interface VipOrderRecordService extends BaseService<VipOrderRecord> {
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.service.vip.impl;
|
||||||
|
|
||||||
|
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
|
||||||
|
import com.red.circle.other.infra.database.rds.dao.vip.UserVipStateDAO;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.UserVipState;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.vip.UserVipStateService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserVipStateServiceImpl extends BaseServiceImpl<UserVipStateDAO, UserVipState>
|
||||||
|
implements UserVipStateService {
|
||||||
|
}
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.service.vip.impl;
|
||||||
|
|
||||||
|
import com.red.circle.framework.mybatis.constant.PageConstant;
|
||||||
|
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
|
||||||
|
import com.red.circle.other.infra.database.rds.dao.vip.VipLevelConfigDAO;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.VipLevelConfig;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.vip.VipLevelConfigService;
|
||||||
|
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class VipLevelConfigServiceImpl extends BaseServiceImpl<VipLevelConfigDAO, VipLevelConfig>
|
||||||
|
implements VipLevelConfigService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, VipLevelConfig> mapByIds(Set<Long> ids) {
|
||||||
|
if (CollectionUtils.isEmpty(ids)) {
|
||||||
|
return CollectionUtils.newHashMap();
|
||||||
|
}
|
||||||
|
return Optional.ofNullable(query().in(VipLevelConfig::getId, ids).list())
|
||||||
|
.map(list -> list.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toMap(VipLevelConfig::getId, item -> item, (first, second) -> first)))
|
||||||
|
.orElseGet(CollectionUtils::newHashMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, VipLevelConfig> mapBySysOriginAndIds(String sysOrigin, Set<Long> ids) {
|
||||||
|
if (CollectionUtils.isEmpty(ids) || Objects.isNull(sysOrigin)) {
|
||||||
|
return CollectionUtils.newHashMap();
|
||||||
|
}
|
||||||
|
return Optional.ofNullable(query()
|
||||||
|
.eq(VipLevelConfig::getSysOrigin, sysOrigin)
|
||||||
|
.in(VipLevelConfig::getId, ids)
|
||||||
|
.list())
|
||||||
|
.map(list -> list.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toMap(VipLevelConfig::getId, item -> item, (first, second) -> first)))
|
||||||
|
.orElseGet(CollectionUtils::newHashMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VipLevelConfig getEnabledById(String sysOrigin, Long id) {
|
||||||
|
if (Objects.isNull(id) || Objects.isNull(sysOrigin)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return query()
|
||||||
|
.eq(VipLevelConfig::getSysOrigin, sysOrigin)
|
||||||
|
.eq(VipLevelConfig::getId, id)
|
||||||
|
.eq(VipLevelConfig::getEnabled, Boolean.TRUE)
|
||||||
|
.last(PageConstant.LIMIT_ONE)
|
||||||
|
.getOne();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package com.red.circle.other.infra.database.rds.service.vip.impl;
|
||||||
|
|
||||||
|
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
|
||||||
|
import com.red.circle.other.infra.database.rds.dao.vip.VipOrderRecordDAO;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.vip.VipOrderRecord;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.vip.VipOrderRecordService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class VipOrderRecordServiceImpl extends BaseServiceImpl<VipOrderRecordDAO, VipOrderRecord>
|
||||||
|
implements VipOrderRecordService {
|
||||||
|
}
|
||||||
@ -3,16 +3,21 @@ package com.red.circle.other.infra.gateway.props;
|
|||||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||||
import com.red.circle.common.business.enums.PropsActivityRewardEnum;
|
import com.red.circle.common.business.enums.PropsActivityRewardEnum;
|
||||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||||
import com.red.circle.other.domain.gateway.props.ActivitySourceGroupGateway;
|
import com.red.circle.other.domain.gateway.props.ActivitySourceGroupGateway;
|
||||||
import com.red.circle.other.infra.common.props.PropsResourcesCommon;
|
import com.red.circle.other.infra.common.activity.VipActivityRewardCommon;
|
||||||
|
import com.red.circle.other.infra.common.props.PropsResourcesCommon;
|
||||||
import com.red.circle.other.infra.convertor.material.PropsActivityInfraConvertor;
|
import com.red.circle.other.infra.convertor.material.PropsActivityInfraConvertor;
|
||||||
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardConfig;
|
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardConfig;
|
||||||
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardGroup;
|
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardGroup;
|
||||||
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRuleConfig;
|
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRuleConfig;
|
||||||
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRewardConfigService;
|
import com.red.circle.other.infra.database.rds.entity.props.PropsSourceRecord;
|
||||||
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRewardGroupService;
|
import com.red.circle.other.infra.database.rds.entity.vip.VipLevelConfig;
|
||||||
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRuleConfigService;
|
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRewardConfigService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRewardGroupService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRuleConfigService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.props.PropsSourceRecordService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.vip.VipLevelConfigService;
|
||||||
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
|
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
|
||||||
import com.red.circle.other.inner.model.cmd.material.PropsResourcesMergeCmd;
|
import com.red.circle.other.inner.model.cmd.material.PropsResourcesMergeCmd;
|
||||||
import com.red.circle.other.inner.model.dto.activity.props.ActivityPropsGroup;
|
import com.red.circle.other.inner.model.dto.activity.props.ActivityPropsGroup;
|
||||||
@ -50,11 +55,13 @@ import org.springframework.stereotype.Component;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGateway {
|
public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGateway {
|
||||||
|
|
||||||
private final PropsResourcesCommon propsResourcesCommon;
|
private final PropsResourcesCommon propsResourcesCommon;
|
||||||
private final PropsActivityInfraConvertor propsActivityInfraConvertor;
|
private final PropsActivityInfraConvertor propsActivityInfraConvertor;
|
||||||
private final PropsActivityRuleConfigService propsActivityRuleConfigService;
|
private final PropsSourceRecordService propsSourceRecordService;
|
||||||
private final PropsActivityRewardGroupService propsActivityRewardGroupService;
|
private final VipLevelConfigService vipLevelConfigService;
|
||||||
private final PropsActivityRewardConfigService propsActivityRewardConfigService;
|
private final PropsActivityRuleConfigService propsActivityRuleConfigService;
|
||||||
|
private final PropsActivityRewardGroupService propsActivityRewardGroupService;
|
||||||
|
private final PropsActivityRewardConfigService propsActivityRewardConfigService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActivityPropsRule getByRuleId(Long id) {
|
public ActivityPropsRule getByRuleId(Long id) {
|
||||||
@ -122,16 +129,21 @@ public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGatewa
|
|||||||
List<PropsActivityRewardGroup> rewardGroups = propsActivityRewardGroupService
|
List<PropsActivityRewardGroup> rewardGroups = propsActivityRewardGroupService
|
||||||
.listByIds(groupIds);
|
.listByIds(groupIds);
|
||||||
|
|
||||||
Map<Long, List<PropsActivityRewardConfig>> rewardGroupConfigMap = propsActivityRewardConfigService
|
Map<Long, List<PropsActivityRewardConfig>> rewardGroupConfigMap = propsActivityRewardConfigService
|
||||||
.mapGroupByIds(groupIds);
|
.mapGroupByIds(groupIds);
|
||||||
|
|
||||||
PropsResourcesMergeDTO propsResourcesMerge = propsResourcesCommon.mapMergeByIds(
|
Map<Long, VipLevelConfig> vipConfigMap = vipLevelConfigService.mapBySysOriginAndIds(sysOrigin,
|
||||||
new PropsResourcesMergeCmd()
|
getVipLevelConfigIds(rewardGroupConfigMap));
|
||||||
.setSysOrigin(sysOrigin)
|
Map<Long, PropsSourceRecord> vipCoverMap = propsSourceRecordService.mapByIds(
|
||||||
.setPropsIds(getPropsAllIds(rewardGroupConfigMap))
|
getVipCoverResourceIds(vipConfigMap.values()));
|
||||||
.setGiftIds(
|
|
||||||
getActivityRewardContentToId(rewardGroupConfigMap, PropsActivityRewardEnum.GIFT))
|
PropsResourcesMergeDTO propsResourcesMerge = propsResourcesCommon.mapMergeByIds(
|
||||||
.setBadgeIds(
|
new PropsResourcesMergeCmd()
|
||||||
|
.setSysOrigin(sysOrigin)
|
||||||
|
.setPropsIds(getPropsAllIds(rewardGroupConfigMap, vipConfigMap.keySet()))
|
||||||
|
.setGiftIds(
|
||||||
|
getActivityRewardContentToId(rewardGroupConfigMap, PropsActivityRewardEnum.GIFT))
|
||||||
|
.setBadgeIds(
|
||||||
getActivityRewardContentToId(rewardGroupConfigMap, PropsActivityRewardEnum.BADGE))
|
getActivityRewardContentToId(rewardGroupConfigMap, PropsActivityRewardEnum.BADGE))
|
||||||
.setEmojiIds(
|
.setEmojiIds(
|
||||||
getActivityRewardContentToId(rewardGroupConfigMap, PropsActivityRewardEnum.EMOJI))
|
getActivityRewardContentToId(rewardGroupConfigMap, PropsActivityRewardEnum.EMOJI))
|
||||||
@ -144,11 +156,12 @@ public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGatewa
|
|||||||
|
|
||||||
List<PropsActivityRewardConfig> rewardConfigs = rewardGroupConfigMap
|
List<PropsActivityRewardConfig> rewardConfigs = rewardGroupConfigMap
|
||||||
.get(activityPropsGroup.getId());
|
.get(activityPropsGroup.getId());
|
||||||
|
|
||||||
activityPropsGroup.setActivityRewardProps(rewardConfigs.stream()
|
activityPropsGroup.setActivityRewardProps(rewardConfigs.stream()
|
||||||
.map(rewardConfig -> getActivityRewardProps(propsResourcesMerge, rewardConfig))
|
.map(rewardConfig -> getActivityRewardProps(propsResourcesMerge, vipConfigMap,
|
||||||
.filter(Objects::nonNull)
|
vipCoverMap, rewardConfig))
|
||||||
.collect(Collectors.toList()));
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
return activityPropsGroup;
|
return activityPropsGroup;
|
||||||
})
|
})
|
||||||
@ -161,12 +174,18 @@ public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGatewa
|
|||||||
.get(groupId);
|
.get(groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActivityRewardProps getActivityRewardProps(PropsResourcesMergeDTO propsSource,
|
private ActivityRewardProps getActivityRewardProps(PropsResourcesMergeDTO propsSource,
|
||||||
PropsActivityRewardConfig rewardConfig) {
|
Map<Long, VipLevelConfig> vipConfigMap,
|
||||||
|
Map<Long, PropsSourceRecord> vipCoverMap,
|
||||||
if (PropsActivityRewardEnum.PROPS.eq(rewardConfig.getType())
|
PropsActivityRewardConfig rewardConfig) {
|
||||||
|| PropsActivityRewardEnum.PROP_COUPON.eq(rewardConfig.getType())
|
|
||||||
|| PropsActivityRewardEnum.FRAGMENTS.eq(rewardConfig.getType())
|
if (isVipLevelReward(rewardConfig, vipConfigMap)) {
|
||||||
|
return buildActivityVip(vipConfigMap, vipCoverMap, rewardConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PropsActivityRewardEnum.PROPS.eq(rewardConfig.getType())
|
||||||
|
|| PropsActivityRewardEnum.PROP_COUPON.eq(rewardConfig.getType())
|
||||||
|
|| PropsActivityRewardEnum.FRAGMENTS.eq(rewardConfig.getType())
|
||||||
|| PropsActivityRewardEnum.CUSTOMIZE.eq(rewardConfig.getType())) {
|
|| PropsActivityRewardEnum.CUSTOMIZE.eq(rewardConfig.getType())) {
|
||||||
return buildActivityProps(propsSource.getProps(), rewardConfig);
|
return buildActivityProps(propsSource.getProps(), rewardConfig);
|
||||||
}
|
}
|
||||||
@ -208,8 +227,8 @@ public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGatewa
|
|||||||
return activityRewardProps;
|
return activityRewardProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActivityRewardProps buildActivityGift(
|
private ActivityRewardProps buildActivityGift(
|
||||||
Map<Long, GiftConfigDTO> giftConfigMap, PropsActivityRewardConfig rewardConfig) {
|
Map<Long, GiftConfigDTO> giftConfigMap, PropsActivityRewardConfig rewardConfig) {
|
||||||
|
|
||||||
GiftConfigDTO giftConfig = giftConfigMap.get(DataTypeUtils.toLong(rewardConfig.getContent()));
|
GiftConfigDTO giftConfig = giftConfigMap.get(DataTypeUtils.toLong(rewardConfig.getContent()));
|
||||||
|
|
||||||
@ -221,8 +240,25 @@ public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGatewa
|
|||||||
giftConfig.getGiftCandy().multiply(BigDecimal.valueOf(rewardConfig.getQuantity()))
|
giftConfig.getGiftCandy().multiply(BigDecimal.valueOf(rewardConfig.getQuantity()))
|
||||||
.setScale(0, RoundingMode.DOWN));
|
.setScale(0, RoundingMode.DOWN));
|
||||||
activityRewardProps.setDetailType(rewardConfig.getDetailType());
|
activityRewardProps.setDetailType(rewardConfig.getDetailType());
|
||||||
return activityRewardProps;
|
return activityRewardProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ActivityRewardProps buildActivityVip(
|
||||||
|
Map<Long, VipLevelConfig> vipConfigMap,
|
||||||
|
Map<Long, PropsSourceRecord> vipCoverMap,
|
||||||
|
PropsActivityRewardConfig rewardConfig) {
|
||||||
|
VipLevelConfig vipConfig = vipConfigMap.get(DataTypeUtils.toLong(rewardConfig.getContent()));
|
||||||
|
ResponseAssert.notNull(CommonErrorCode.CONFIGURATION_ERROR, vipConfig);
|
||||||
|
ActivityRewardProps activityRewardProps = propsActivityInfraConvertor
|
||||||
|
.toActivityRewardProps(rewardConfig);
|
||||||
|
activityRewardProps.setCover(resolveVipCover(vipConfig, vipCoverMap));
|
||||||
|
activityRewardProps.setQuantity(durationDays(vipConfig));
|
||||||
|
activityRewardProps.setAmount(BigDecimal.valueOf(Objects.requireNonNullElse(
|
||||||
|
vipConfig.getPriceGold(), 0L)));
|
||||||
|
activityRewardProps.setRemark(displayName(vipConfig));
|
||||||
|
activityRewardProps.setDetailType(rewardConfig.getDetailType());
|
||||||
|
return activityRewardProps;
|
||||||
|
}
|
||||||
|
|
||||||
private ActivityRewardProps buildEmoji(Map<Long, EmojiGroupDTO> emojiGroupMap,
|
private ActivityRewardProps buildEmoji(Map<Long, EmojiGroupDTO> emojiGroupMap,
|
||||||
PropsActivityRewardConfig rewardConfig) {
|
PropsActivityRewardConfig rewardConfig) {
|
||||||
@ -282,19 +318,28 @@ public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGatewa
|
|||||||
return activityRewardProps;
|
return activityRewardProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<Long> getPropsAllIds(
|
private Set<Long> getPropsAllIds(
|
||||||
Map<Long, List<PropsActivityRewardConfig>> rewardGroupConfigMap) {
|
Map<Long, List<PropsActivityRewardConfig>> rewardGroupConfigMap,
|
||||||
return getPropsAllIds(
|
Set<Long> vipConfigIds) {
|
||||||
rewardGroupConfigMap.values().stream().flatMap(Collection::stream).collect(
|
return getPropsAllIds(
|
||||||
Collectors.toList())
|
rewardGroupConfigMap.values().stream().flatMap(Collection::stream).collect(
|
||||||
);
|
Collectors.toList()),
|
||||||
}
|
vipConfigIds
|
||||||
|
);
|
||||||
|
}
|
||||||
private Set<Long> getPropsAllIds(List<PropsActivityRewardConfig> rewardConfigs) {
|
|
||||||
Set<Long> propsIds = getActivityRewardContentToId(rewardConfigs, PropsActivityRewardEnum.PROPS);
|
|
||||||
Set<Long> couponIds = getActivityRewardContentToId(rewardConfigs, PropsActivityRewardEnum.PROP_COUPON);
|
private Set<Long> getPropsAllIds(List<PropsActivityRewardConfig> rewardConfigs,
|
||||||
propsIds.addAll(couponIds);
|
Set<Long> vipConfigIds) {
|
||||||
|
Set<Long> propsIds = rewardConfigs.stream()
|
||||||
|
.filter(conf -> PropsActivityRewardEnum.PROPS.eq(conf.getType()))
|
||||||
|
.filter(conf -> !isVipLevelReward(conf, vipConfigIds))
|
||||||
|
.map(propsActivityRewardConfig -> DataTypeUtils
|
||||||
|
.toLong(propsActivityRewardConfig.getContent()))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
Set<Long> couponIds = getActivityRewardContentToId(rewardConfigs, PropsActivityRewardEnum.PROP_COUPON);
|
||||||
|
propsIds.addAll(couponIds);
|
||||||
|
|
||||||
Set<Long> fragmentIds = getActivityRewardContentToId(rewardConfigs,
|
Set<Long> fragmentIds = getActivityRewardContentToId(rewardConfigs,
|
||||||
PropsActivityRewardEnum.FRAGMENTS);
|
PropsActivityRewardEnum.FRAGMENTS);
|
||||||
@ -319,8 +364,8 @@ public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGatewa
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<Long> getActivityRewardContentToId(
|
private Set<Long> getActivityRewardContentToId(
|
||||||
List<PropsActivityRewardConfig> rewardGroupConfigList,
|
List<PropsActivityRewardConfig> rewardGroupConfigList,
|
||||||
PropsActivityRewardEnum type) {
|
PropsActivityRewardEnum type) {
|
||||||
if (CollectionUtils.isEmpty(rewardGroupConfigList)) {
|
if (CollectionUtils.isEmpty(rewardGroupConfigList)) {
|
||||||
return CollectionUtils.newHashSet();
|
return CollectionUtils.newHashSet();
|
||||||
@ -331,7 +376,90 @@ public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGatewa
|
|||||||
.toLong(propsActivityRewardConfig.getContent()))
|
.toLong(propsActivityRewardConfig.getContent()))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<Long> getVipLevelConfigIds(
|
||||||
|
Map<Long, List<PropsActivityRewardConfig>> rewardGroupConfigMap) {
|
||||||
|
return rewardGroupConfigMap.values().stream()
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.filter(config -> PropsActivityRewardEnum.PROPS.eq(config.getType()))
|
||||||
|
.filter(config -> Objects.equals(config.getDetailType(),
|
||||||
|
VipActivityRewardCommon.VIP_DETAIL_TYPE))
|
||||||
|
.map(config -> DataTypeUtils.toLong(config.getContent()))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<Long> getVipCoverResourceIds(Collection<VipLevelConfig> vipConfigs) {
|
||||||
|
if (CollectionUtils.isEmpty(vipConfigs)) {
|
||||||
|
return CollectionUtils.newHashSet();
|
||||||
|
}
|
||||||
|
return vipConfigs.stream()
|
||||||
|
.map(this::firstVipResourceId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(id -> id > 0)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVipLevelReward(PropsActivityRewardConfig rewardConfig,
|
||||||
|
Map<Long, VipLevelConfig> vipConfigMap) {
|
||||||
|
return isVipLevelReward(rewardConfig, vipConfigMap.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVipLevelReward(PropsActivityRewardConfig rewardConfig, Set<Long> vipConfigIds) {
|
||||||
|
return PropsActivityRewardEnum.PROPS.eq(rewardConfig.getType())
|
||||||
|
&& Objects.equals(rewardConfig.getDetailType(), VipActivityRewardCommon.VIP_DETAIL_TYPE)
|
||||||
|
&& vipConfigIds.contains(DataTypeUtils.toLong(rewardConfig.getContent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long firstVipResourceId(VipLevelConfig vipConfig) {
|
||||||
|
return Stream.of(
|
||||||
|
vipConfig.getBadgeResourceId(),
|
||||||
|
vipConfig.getShortBadgeResourceId(),
|
||||||
|
vipConfig.getAvatarFrameResourceId(),
|
||||||
|
vipConfig.getEntryEffectResourceId(),
|
||||||
|
vipConfig.getChatBubbleResourceId(),
|
||||||
|
vipConfig.getFloatPictureResourceId(),
|
||||||
|
vipConfig.getBackgroundCardResourceId(),
|
||||||
|
vipConfig.getEffectImageResourceId())
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(id -> id > 0)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveVipCover(VipLevelConfig vipConfig,
|
||||||
|
Map<Long, PropsSourceRecord> vipCoverMap) {
|
||||||
|
PropsSourceRecord sourceRecord = vipCoverMap.get(firstVipResourceId(vipConfig));
|
||||||
|
if (Objects.nonNull(sourceRecord) && Objects.nonNull(sourceRecord.getCover())) {
|
||||||
|
return sourceRecord.getCover();
|
||||||
|
}
|
||||||
|
return Stream.of(
|
||||||
|
vipConfig.getBadgeUrl(),
|
||||||
|
vipConfig.getShortBadgeUrl(),
|
||||||
|
vipConfig.getAvatarFrameUrl(),
|
||||||
|
vipConfig.getEntryEffectUrl(),
|
||||||
|
vipConfig.getChatBubbleUrl(),
|
||||||
|
vipConfig.getFloatPictureUrl(),
|
||||||
|
vipConfig.getBackgroundCardUrl(),
|
||||||
|
vipConfig.getEffectImageUrl())
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(value -> !value.isBlank())
|
||||||
|
.findFirst()
|
||||||
|
.orElse("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int durationDays(VipLevelConfig vipConfig) {
|
||||||
|
Integer days = vipConfig.getDurationDays();
|
||||||
|
return Objects.nonNull(days) && days > 0 ? days : 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String displayName(VipLevelConfig vipConfig) {
|
||||||
|
if (Objects.nonNull(vipConfig.getDisplayName()) && !vipConfig.getDisplayName().isBlank()) {
|
||||||
|
return vipConfig.getDisplayName();
|
||||||
|
}
|
||||||
|
return "VIP " + Objects.requireNonNullElse(vipConfig.getLevel(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Set<Long> getGroupIds(List<PropsActivityRuleConfig> ruleConfigs) {
|
private Set<Long> getGroupIds(List<PropsActivityRuleConfig> ruleConfigs) {
|
||||||
|
|||||||
@ -32,10 +32,10 @@ public class IpCountryUtils {
|
|||||||
"香港", "澳门", "澳門", "台湾", "台灣", "Hong Kong", "Macau", "Macao", "Taiwan"
|
"香港", "澳门", "澳門", "台湾", "台灣", "Hong Kong", "Macau", "Macao", "Taiwan"
|
||||||
);
|
);
|
||||||
private static final List<String> BLOCKED_COUNTRY_CODES = List.of(
|
private static final List<String> BLOCKED_COUNTRY_CODES = List.of(
|
||||||
"MO", "SG"
|
"MO"
|
||||||
);
|
);
|
||||||
private static final List<String> BLOCKED_COUNTRY_NAMES = List.of(
|
private static final List<String> BLOCKED_COUNTRY_NAMES = List.of(
|
||||||
"澳门", "澳門", "Macau", "Macao", "新加坡", "Singapore"
|
"澳门", "澳門", "Macau", "Macao"
|
||||||
);
|
);
|
||||||
private static final List<IpGeoProvider> IP_GEO_PROVIDERS = List.of(
|
private static final List<IpGeoProvider> IP_GEO_PROVIDERS = List.of(
|
||||||
new IpGeoProvider("ip.sb", "https://api.ip.sb/geoip/%s"),
|
new IpGeoProvider("ip.sb", "https://api.ip.sb/geoip/%s"),
|
||||||
|
|||||||
@ -92,10 +92,10 @@ public class IpCountryUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void blockSingaporeCountryCode() {
|
public void allowSingaporeCountryCode() {
|
||||||
IpCountryUtils.IpGeoData data = new IpCountryUtils.IpGeoData("SG", "Singapore", "", "test");
|
IpCountryUtils.IpGeoData data = new IpCountryUtils.IpGeoData("SG", "Singapore", "", "test");
|
||||||
|
|
||||||
assertTrue(IpCountryUtils.isBlockedIpRegion(data));
|
assertFalse(IpCountryUtils.isBlockedIpRegion(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -2,24 +2,27 @@ package com.red.circle.other.app.inner.service.material.props.impl;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.red.circle.common.business.enums.PropsActivityRewardEnum;
|
import com.red.circle.common.business.enums.PropsActivityRewardEnum;
|
||||||
import com.red.circle.framework.dto.PageResult;
|
import com.red.circle.framework.dto.PageResult;
|
||||||
import com.red.circle.other.app.inner.convertor.material.PropsInnerConvertor;
|
import com.red.circle.other.infra.common.activity.VipActivityRewardCommon;
|
||||||
import com.red.circle.other.app.inner.service.material.props.PropsActivityRewardGroupClientService;
|
import com.red.circle.other.app.inner.convertor.material.PropsInnerConvertor;
|
||||||
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardConfig;
|
import com.red.circle.other.app.inner.service.material.props.PropsActivityRewardGroupClientService;
|
||||||
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardGroup;
|
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardConfig;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardGroup;
|
||||||
import com.red.circle.other.infra.database.rds.entity.badge.BadgeConfig;
|
import com.red.circle.other.infra.database.rds.entity.badge.BadgeConfig;
|
||||||
import com.red.circle.other.infra.database.rds.entity.badge.BadgePictureConfig;
|
import com.red.circle.other.infra.database.rds.entity.badge.BadgePictureConfig;
|
||||||
import com.red.circle.other.infra.database.rds.entity.emoji.EmojiGroup;
|
import com.red.circle.other.infra.database.rds.entity.emoji.EmojiGroup;
|
||||||
import com.red.circle.other.infra.database.rds.entity.gift.GiftConfig;
|
import com.red.circle.other.infra.database.rds.entity.gift.GiftConfig;
|
||||||
import com.red.circle.other.infra.database.rds.entity.props.PropsSourceRecord;
|
import com.red.circle.other.infra.database.rds.entity.props.PropsSourceRecord;
|
||||||
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRewardConfigService;
|
import com.red.circle.other.infra.database.rds.entity.vip.VipLevelConfig;
|
||||||
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRewardGroupService;
|
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRewardConfigService;
|
||||||
import com.red.circle.other.infra.database.rds.service.badge.BadgeConfigService;
|
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRewardGroupService;
|
||||||
import com.red.circle.other.infra.database.rds.service.badge.BadgePictureConfigService;
|
import com.red.circle.other.infra.database.rds.service.badge.BadgeConfigService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.badge.BadgePictureConfigService;
|
||||||
import com.red.circle.other.infra.database.rds.service.emoji.EmojiGroupService;
|
import com.red.circle.other.infra.database.rds.service.emoji.EmojiGroupService;
|
||||||
import com.red.circle.other.infra.database.rds.service.gift.GiftConfigService;
|
import com.red.circle.other.infra.database.rds.service.gift.GiftConfigService;
|
||||||
import com.red.circle.other.infra.database.rds.service.props.PropsSourceRecordService;
|
import com.red.circle.other.infra.database.rds.service.props.PropsSourceRecordService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.vip.VipLevelConfigService;
|
||||||
import com.red.circle.other.inner.model.cmd.material.PropsActivityRewardGroupParamCmd;
|
import com.red.circle.other.inner.model.cmd.material.PropsActivityRewardGroupParamCmd;
|
||||||
import com.red.circle.other.inner.model.cmd.material.PropsActivityRewardGroupQryCmd;
|
import com.red.circle.other.inner.model.cmd.material.PropsActivityRewardGroupQryCmd;
|
||||||
import com.red.circle.other.inner.model.dto.material.ActivityGroupKeyValueDTO;
|
import com.red.circle.other.inner.model.dto.material.ActivityGroupKeyValueDTO;
|
||||||
@ -28,16 +31,18 @@ import com.red.circle.other.inner.model.dto.material.PropsActivityRewardGroupDTO
|
|||||||
import com.red.circle.tool.core.collection.CollectionUtils;
|
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||||
import com.red.circle.tool.core.date.TimestampUtils;
|
import com.red.circle.tool.core.date.TimestampUtils;
|
||||||
import com.red.circle.tool.core.parse.DataTypeUtils;
|
import com.red.circle.tool.core.parse.DataTypeUtils;
|
||||||
import com.red.circle.tool.core.text.StringUtils;
|
import com.red.circle.tool.core.text.StringUtils;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -56,9 +61,10 @@ public class PropsActivityRewardGroupClientServiceImpl implements
|
|||||||
|
|
||||||
private final EmojiGroupService emojiGroupService;
|
private final EmojiGroupService emojiGroupService;
|
||||||
private final GiftConfigService giftConfigService;
|
private final GiftConfigService giftConfigService;
|
||||||
private final BadgeConfigService badgeConfigService;
|
private final BadgeConfigService badgeConfigService;
|
||||||
private final PropsInnerConvertor propsInnerConvertor;
|
private final PropsInnerConvertor propsInnerConvertor;
|
||||||
private final PropsSourceRecordService propsSourceRecordService;
|
private final VipLevelConfigService vipLevelConfigService;
|
||||||
|
private final PropsSourceRecordService propsSourceRecordService;
|
||||||
private final BadgePictureConfigService badgePictureConfigService;
|
private final BadgePictureConfigService badgePictureConfigService;
|
||||||
private final PropsActivityRewardGroupService propsActivityRewardGroupService;
|
private final PropsActivityRewardGroupService propsActivityRewardGroupService;
|
||||||
private final PropsActivityRewardConfigService propsActivityRewardConfigService;
|
private final PropsActivityRewardConfigService propsActivityRewardConfigService;
|
||||||
@ -215,14 +221,21 @@ public class PropsActivityRewardGroupClientServiceImpl implements
|
|||||||
List<PropsActivityRewardConfig> propsActivityRewardConfigs = propsActivityRewardConfigService.listByGroupIds(
|
List<PropsActivityRewardConfig> propsActivityRewardConfigs = propsActivityRewardConfigService.listByGroupIds(
|
||||||
groupIds);
|
groupIds);
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(propsActivityRewardConfigs)) {
|
if (CollectionUtils.isEmpty(propsActivityRewardConfigs)) {
|
||||||
return Lists.newArrayList();
|
return Lists.newArrayList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<Long> sourceIds = propsActivityRewardConfigs.stream().filter(config ->
|
Map<Long, VipLevelConfig> vipConfigMap = vipLevelConfigService.mapByIds(
|
||||||
Objects.equals(config.getType(), PropsActivityRewardEnum.PROPS.name()) || Objects.equals(config.getType(), PropsActivityRewardEnum.PROP_COUPON.name()))
|
getVipLevelConfigIds(propsActivityRewardConfigs));
|
||||||
.map(config -> Long.valueOf(config.getContent()))
|
Map<Long, PropsSourceRecord> vipCoverMap = propsSourceRecordService.mapByIds(
|
||||||
.collect(Collectors.toSet());
|
getVipCoverResourceIds(vipConfigMap.values()));
|
||||||
|
|
||||||
|
Set<Long> sourceIds = propsActivityRewardConfigs.stream().filter(config ->
|
||||||
|
(Objects.equals(config.getType(), PropsActivityRewardEnum.PROPS.name())
|
||||||
|
&& !isVipLevelReward(config, vipConfigMap))
|
||||||
|
|| Objects.equals(config.getType(), PropsActivityRewardEnum.PROP_COUPON.name()))
|
||||||
|
.map(config -> Long.valueOf(config.getContent()))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
Set<Long> fragmentsIds = propsActivityRewardConfigs.stream().filter(config ->
|
Set<Long> fragmentsIds = propsActivityRewardConfigs.stream().filter(config ->
|
||||||
Objects.equals(config.getType(), PropsActivityRewardEnum.FRAGMENTS.name()))
|
Objects.equals(config.getType(), PropsActivityRewardEnum.FRAGMENTS.name()))
|
||||||
@ -262,12 +275,17 @@ public class PropsActivityRewardGroupClientServiceImpl implements
|
|||||||
.collect(Collectors.toSet()));
|
.collect(Collectors.toSet()));
|
||||||
|
|
||||||
return propsActivityRewardConfigs.stream().map(config -> {
|
return propsActivityRewardConfigs.stream().map(config -> {
|
||||||
PropsActivityRewardConfigInfoDTO propsActivity = propsInnerConvertor.toPropsActivityRewardConfigInfoDTO(
|
PropsActivityRewardConfigInfoDTO propsActivity = propsInnerConvertor.toPropsActivityRewardConfigInfoDTO(
|
||||||
config);
|
config);
|
||||||
propsActivity.setSort(Objects.isNull(propsActivity.getSort()) ? 0 : propsActivity.getSort());
|
propsActivity.setSort(Objects.isNull(propsActivity.getSort()) ? 0 : propsActivity.getSort());
|
||||||
if (Objects.equals(config.getType(), PropsActivityRewardEnum.PROPS.name()) || Objects.equals(config.getType(), PropsActivityRewardEnum.PROP_COUPON.name())) {
|
if (isVipLevelReward(config, vipConfigMap)) {
|
||||||
PropsSourceRecord sourceRecord = sourceRecordMap
|
setVipConfig(propsActivity, vipConfigMap.get(Long.valueOf(config.getContent())),
|
||||||
.get(Long.valueOf(config.getContent()));
|
vipCoverMap);
|
||||||
|
return propsActivity;
|
||||||
|
}
|
||||||
|
if (Objects.equals(config.getType(), PropsActivityRewardEnum.PROPS.name()) || Objects.equals(config.getType(), PropsActivityRewardEnum.PROP_COUPON.name())) {
|
||||||
|
PropsSourceRecord sourceRecord = sourceRecordMap
|
||||||
|
.get(Long.valueOf(config.getContent()));
|
||||||
if (Objects.nonNull(sourceRecord)) {
|
if (Objects.nonNull(sourceRecord)) {
|
||||||
propsActivity.setCover(sourceRecord.getCover());
|
propsActivity.setCover(sourceRecord.getCover());
|
||||||
propsActivity.setSourceUrl(sourceRecord.getSourceUrl());
|
propsActivity.setSourceUrl(sourceRecord.getSourceUrl());
|
||||||
@ -330,6 +348,102 @@ public class PropsActivityRewardGroupClientServiceImpl implements
|
|||||||
propsActivity.setAmount(giftConfig.getGiftCandy());
|
propsActivity.setAmount(giftConfig.getGiftCandy());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.error("礼物数据错误:{}", config);
|
log.error("礼物数据错误:{}", config);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private Set<Long> getVipLevelConfigIds(List<PropsActivityRewardConfig> configs) {
|
||||||
|
return configs.stream()
|
||||||
|
.filter(config -> Objects.equals(config.getType(), PropsActivityRewardEnum.PROPS.name()))
|
||||||
|
.filter(config -> Objects.equals(config.getDetailType(),
|
||||||
|
VipActivityRewardCommon.VIP_DETAIL_TYPE))
|
||||||
|
.map(config -> DataTypeUtils.toLong(config.getContent()))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<Long> getVipCoverResourceIds(Collection<VipLevelConfig> vipConfigs) {
|
||||||
|
if (CollectionUtils.isEmpty(vipConfigs)) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
return vipConfigs.stream()
|
||||||
|
.map(this::firstVipResourceId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(id -> id > 0)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVipLevelReward(PropsActivityRewardConfig config,
|
||||||
|
Map<Long, VipLevelConfig> vipConfigMap) {
|
||||||
|
return Objects.equals(config.getType(), PropsActivityRewardEnum.PROPS.name())
|
||||||
|
&& Objects.equals(config.getDetailType(), VipActivityRewardCommon.VIP_DETAIL_TYPE)
|
||||||
|
&& vipConfigMap.containsKey(DataTypeUtils.toLong(config.getContent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setVipConfig(PropsActivityRewardConfigInfoDTO propsActivity,
|
||||||
|
VipLevelConfig vipConfig, Map<Long, PropsSourceRecord> vipCoverMap) {
|
||||||
|
propsActivity.setCover(resolveVipCover(vipConfig, vipCoverMap));
|
||||||
|
propsActivity.setSourceUrl(resolveVipSourceUrl(vipConfig, vipCoverMap));
|
||||||
|
propsActivity.setAmount(BigDecimal.valueOf(Objects.requireNonNullElse(
|
||||||
|
vipConfig.getPriceGold(), 0L)));
|
||||||
|
propsActivity.setQuantity(durationDays(vipConfig));
|
||||||
|
propsActivity.setName(displayName(vipConfig));
|
||||||
|
propsActivity.setRemark(displayName(vipConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long firstVipResourceId(VipLevelConfig vipConfig) {
|
||||||
|
return Stream.of(
|
||||||
|
vipConfig.getBadgeResourceId(),
|
||||||
|
vipConfig.getShortBadgeResourceId(),
|
||||||
|
vipConfig.getAvatarFrameResourceId(),
|
||||||
|
vipConfig.getEntryEffectResourceId(),
|
||||||
|
vipConfig.getChatBubbleResourceId(),
|
||||||
|
vipConfig.getFloatPictureResourceId(),
|
||||||
|
vipConfig.getBackgroundCardResourceId(),
|
||||||
|
vipConfig.getEffectImageResourceId())
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(id -> id > 0)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveVipCover(VipLevelConfig vipConfig,
|
||||||
|
Map<Long, PropsSourceRecord> vipCoverMap) {
|
||||||
|
PropsSourceRecord sourceRecord = vipCoverMap.get(firstVipResourceId(vipConfig));
|
||||||
|
if (Objects.nonNull(sourceRecord) && StringUtils.isNotBlank(sourceRecord.getCover())) {
|
||||||
|
return sourceRecord.getCover();
|
||||||
|
}
|
||||||
|
return resolveVipSourceUrl(vipConfig, vipCoverMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveVipSourceUrl(VipLevelConfig vipConfig,
|
||||||
|
Map<Long, PropsSourceRecord> vipCoverMap) {
|
||||||
|
PropsSourceRecord sourceRecord = vipCoverMap.get(firstVipResourceId(vipConfig));
|
||||||
|
if (Objects.nonNull(sourceRecord) && StringUtils.isNotBlank(sourceRecord.getSourceUrl())) {
|
||||||
|
return sourceRecord.getSourceUrl();
|
||||||
|
}
|
||||||
|
return Stream.of(
|
||||||
|
vipConfig.getBadgeUrl(),
|
||||||
|
vipConfig.getShortBadgeUrl(),
|
||||||
|
vipConfig.getAvatarFrameUrl(),
|
||||||
|
vipConfig.getEntryEffectUrl(),
|
||||||
|
vipConfig.getChatBubbleUrl(),
|
||||||
|
vipConfig.getFloatPictureUrl(),
|
||||||
|
vipConfig.getBackgroundCardUrl(),
|
||||||
|
vipConfig.getEffectImageUrl())
|
||||||
|
.filter(StringUtils::isNotBlank)
|
||||||
|
.findFirst()
|
||||||
|
.orElse("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int durationDays(VipLevelConfig vipConfig) {
|
||||||
|
Integer days = vipConfig.getDurationDays();
|
||||||
|
return Objects.nonNull(days) && days > 0 ? days : 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String displayName(VipLevelConfig vipConfig) {
|
||||||
|
if (StringUtils.isNotBlank(vipConfig.getDisplayName())) {
|
||||||
|
return vipConfig.getDisplayName();
|
||||||
|
}
|
||||||
|
return "VIP " + Objects.requireNonNullElse(vipConfig.getLevel(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package com.red.circle.wallet.app.service;
|
package com.red.circle.wallet.app.service;
|
||||||
|
|
||||||
import com.red.circle.framework.dto.PageResult;
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
|
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||||
|
import com.red.circle.framework.dto.PageResult;
|
||||||
import com.red.circle.wallet.app.command.salary.SalaryExchangeGoldCmdExe;
|
import com.red.circle.wallet.app.command.salary.SalaryExchangeGoldCmdExe;
|
||||||
import com.red.circle.wallet.app.command.salary.SalaryIssueCmdExe;
|
import com.red.circle.wallet.app.command.salary.SalaryIssueCmdExe;
|
||||||
import com.red.circle.wallet.app.command.salary.SalaryTransferGoldCmdExe;
|
import com.red.circle.wallet.app.command.salary.SalaryTransferGoldCmdExe;
|
||||||
@ -22,8 +24,10 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class SalaryAccountServiceImpl implements SalaryAccountService {
|
public class SalaryAccountServiceImpl implements SalaryAccountService {
|
||||||
|
|
||||||
|
private static final boolean SALARY_WALLET_OUT_PAUSED = true;
|
||||||
|
|
||||||
private final SalaryAccountBalanceQryExe salaryAccountBalanceQryExe;
|
private final SalaryAccountBalanceQryExe salaryAccountBalanceQryExe;
|
||||||
private final SalaryRunningWaterQryExe salaryRunningWaterQryExe;
|
private final SalaryRunningWaterQryExe salaryRunningWaterQryExe;
|
||||||
private final SalaryIssueCmdExe salaryIssueCmdExe;
|
private final SalaryIssueCmdExe salaryIssueCmdExe;
|
||||||
@ -52,15 +56,21 @@ public class SalaryAccountServiceImpl implements SalaryAccountService {
|
|||||||
return salaryRunningWaterQryExe.execute(cmd);
|
return salaryRunningWaterQryExe.execute(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserBankWithdrawResultCO transferGold(SalaryWithdrawCmd cmd) {
|
public UserBankWithdrawResultCO transferGold(SalaryWithdrawCmd cmd) {
|
||||||
return salaryTransferGoldCmdExe.execute(cmd);
|
rejectPausedSalaryWalletOut();
|
||||||
}
|
return salaryTransferGoldCmdExe.execute(cmd);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public UserBankExchangeGoldResultCO exchangeGold(SalaryWithdrawCmd cmd) {
|
@Override
|
||||||
return salaryExchangeGoldCmdExe.execute(cmd);
|
public UserBankExchangeGoldResultCO exchangeGold(SalaryWithdrawCmd cmd) {
|
||||||
}
|
rejectPausedSalaryWalletOut();
|
||||||
|
return salaryExchangeGoldCmdExe.execute(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rejectPausedSalaryWalletOut() {
|
||||||
|
ResponseAssert.isTrue(CommonErrorCode.SYSTEM_IS_DOWN, !SALARY_WALLET_OUT_PAUSED);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getTotalIncome(Long userId, String salaryType, String salaryEvent, String startTime, String endTime) {
|
public BigDecimal getTotalIncome(Long userId, String salaryType, String salaryEvent, String startTime, String endTime) {
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
package com.red.circle.wallet.app.service;
|
package com.red.circle.wallet.app.service;
|
||||||
|
|
||||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||||
import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
|
import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
|
||||||
import com.red.circle.framework.core.dto.CommonCommand;
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
import com.red.circle.framework.dto.PageResult;
|
import com.red.circle.framework.core.dto.CommonCommand;
|
||||||
|
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||||
|
import com.red.circle.framework.dto.PageResult;
|
||||||
import com.red.circle.wallet.app.command.bank.UserBankExchangeGoldCmdExe;
|
import com.red.circle.wallet.app.command.bank.UserBankExchangeGoldCmdExe;
|
||||||
import com.red.circle.wallet.app.command.bank.query.UserBankCheckExchangeGoldQryExe;
|
import com.red.circle.wallet.app.command.bank.query.UserBankCheckExchangeGoldQryExe;
|
||||||
import com.red.circle.wallet.app.command.bank.query.UserBankCheckTransferQryExe;
|
import com.red.circle.wallet.app.command.bank.query.UserBankCheckTransferQryExe;
|
||||||
@ -29,8 +31,10 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class SalaryDiamondServiceImpl implements SalaryDiamondService {
|
public class SalaryDiamondServiceImpl implements SalaryDiamondService {
|
||||||
|
|
||||||
|
private static final boolean SALARY_EXCHANGE_PAUSED = true;
|
||||||
|
|
||||||
private final UserBillAgentSalaryDiamondCheckExchangeGoldQryExe userBillAgentSalaryDiamondCheckExchangeGoldQryExe;
|
private final UserBillAgentSalaryDiamondCheckExchangeGoldQryExe userBillAgentSalaryDiamondCheckExchangeGoldQryExe;
|
||||||
private final UserSalaryDiamondBalanceQryExe userSalaryDiamondBalanceQryExe;
|
private final UserSalaryDiamondBalanceQryExe userSalaryDiamondBalanceQryExe;
|
||||||
private final UserSalaryDiamondRunningWaterQryExe userSalaryDiamondRunningWaterQryExe;
|
private final UserSalaryDiamondRunningWaterQryExe userSalaryDiamondRunningWaterQryExe;
|
||||||
@ -85,25 +89,33 @@ public class SalaryDiamondServiceImpl implements SalaryDiamondService {
|
|||||||
return userBankCheckTransferQryExe.executeDiamond(cmd);
|
return userBankCheckTransferQryExe.executeDiamond(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserBankExchangeGoldResultCO exchangeGold(UserBankExchangeGoldCmd cmd) {
|
public UserBankExchangeGoldResultCO exchangeGold(UserBankExchangeGoldCmd cmd) {
|
||||||
return userBankExchangeGoldCmdExe.executeDiamond(cmd);
|
rejectPausedSalaryExchange();
|
||||||
}
|
return userBankExchangeGoldCmdExe.executeDiamond(cmd);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public UserBankExchangeGoldResultCO exchangeGoldYolo(UserBankExchangeGoldCmd cmd) {
|
@Override
|
||||||
return userBankExchangeGoldCmdExe.exchangeGoldYolo(cmd);
|
public UserBankExchangeGoldResultCO exchangeGoldYolo(UserBankExchangeGoldCmd cmd) {
|
||||||
}
|
rejectPausedSalaryExchange();
|
||||||
|
return userBankExchangeGoldCmdExe.exchangeGoldYolo(cmd);
|
||||||
@Override
|
}
|
||||||
public UserBankExchangeGoldResultCO agentBillExchangeGold(UserBillExchangeGoldCmd cmd) {
|
|
||||||
return userBankExchangeGoldCmdExe.agentBillExchangeGold(cmd);
|
@Override
|
||||||
}
|
public UserBankExchangeGoldResultCO agentBillExchangeGold(UserBillExchangeGoldCmd cmd) {
|
||||||
|
rejectPausedSalaryExchange();
|
||||||
@Override
|
return userBankExchangeGoldCmdExe.agentBillExchangeGold(cmd);
|
||||||
public UserBankExchangeGoldResultCO memberWorkExchangeGold(UserBillExchangeGoldCmd cmd) {
|
}
|
||||||
return userBankExchangeGoldCmdExe.memberWorkExchangeGold(cmd);
|
|
||||||
}
|
@Override
|
||||||
|
public UserBankExchangeGoldResultCO memberWorkExchangeGold(UserBillExchangeGoldCmd cmd) {
|
||||||
|
rejectPausedSalaryExchange();
|
||||||
|
return userBankExchangeGoldCmdExe.memberWorkExchangeGold(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rejectPausedSalaryExchange() {
|
||||||
|
ResponseAssert.isTrue(CommonErrorCode.SYSTEM_IS_DOWN, !SALARY_EXCHANGE_PAUSED);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserBankWithdrawResultCO withdraw(UserBankWithdrawCmd cmd) {
|
public UserBankWithdrawResultCO withdraw(UserBankWithdrawCmd cmd) {
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
package com.red.circle.wallet.app.service;
|
package com.red.circle.wallet.app.service;
|
||||||
|
|
||||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||||
import com.red.circle.framework.core.dto.CommonCommand;
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
import com.red.circle.other.inner.model.dto.user.SysExchangeGoldTipDTO;
|
import com.red.circle.framework.core.dto.CommonCommand;
|
||||||
|
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||||
|
import com.red.circle.other.inner.model.dto.user.SysExchangeGoldTipDTO;
|
||||||
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||||
import com.red.circle.wallet.app.command.bank.*;
|
import com.red.circle.wallet.app.command.bank.*;
|
||||||
import com.red.circle.wallet.app.command.bank.query.UserBankCheckExchangeGoldQryExe;
|
import com.red.circle.wallet.app.command.bank.query.UserBankCheckExchangeGoldQryExe;
|
||||||
@ -37,8 +39,10 @@ import org.springframework.stereotype.Service;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class UserBankServiceImpl implements UserBankService {
|
public class UserBankServiceImpl implements UserBankService {
|
||||||
|
|
||||||
|
private static final boolean USER_TO_COIN_SELLER_TRANSFER_PAUSED = true;
|
||||||
|
|
||||||
private final UserBankWaterQryExe userBankWaterQryExe;
|
private final UserBankWaterQryExe userBankWaterQryExe;
|
||||||
private final UserBankBalanceQryExe userBankBalanceQryExe;
|
private final UserBankBalanceQryExe userBankBalanceQryExe;
|
||||||
private final UserBankWithdrawCmdExe userBankWithdrawCmdExe;
|
private final UserBankWithdrawCmdExe userBankWithdrawCmdExe;
|
||||||
@ -86,10 +90,15 @@ public class UserBankServiceImpl implements UserBankService {
|
|||||||
return userBankWithdrawTransferCmdExe.execute(cmd);
|
return userBankWithdrawTransferCmdExe.execute(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserBankWithdrawResultCO transferGold(UserBankWithdrawTransferCmd cmd) {
|
public UserBankWithdrawResultCO transferGold(UserBankWithdrawTransferCmd cmd) {
|
||||||
return userBankTransferGoldCmdExe.execute(cmd);
|
rejectPausedUserToCoinSellerTransfer();
|
||||||
}
|
return userBankTransferGoldCmdExe.execute(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rejectPausedUserToCoinSellerTransfer() {
|
||||||
|
ResponseAssert.isTrue(CommonErrorCode.SYSTEM_IS_DOWN, !USER_TO_COIN_SELLER_TRANSFER_PAUSED);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserBankWithdrawResultCO diamondTransfer(UserBankWithdrawTransferCmd cmd) {
|
public UserBankWithdrawResultCO diamondTransfer(UserBankWithdrawTransferCmd cmd) {
|
||||||
|
|||||||
@ -3,8 +3,9 @@ package com.red.circle.wallet.infra.database.mongo.service.bank;
|
|||||||
import com.red.circle.tool.core.tuple.PennyAmount;
|
import com.red.circle.tool.core.tuple.PennyAmount;
|
||||||
import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankBalance;
|
import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankBalance;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
||||||
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
||||||
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceStatisticsDTO;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -52,11 +53,16 @@ public interface UserBankBalanceService {
|
|||||||
*/
|
*/
|
||||||
Map<Long, BankBalanceDTO> mapBalance(Collection<Long> userIds);
|
Map<Long, BankBalanceDTO> mapBalance(Collection<Long> userIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查看用户银行卡账户.
|
* 查看用户银行卡账户.
|
||||||
*/
|
*/
|
||||||
List<UserBankBalanceDTO> listBalance(UserBankBalanceQryCmd query);
|
List<UserBankBalanceDTO> listBalance(UserBankBalanceQryCmd query);
|
||||||
|
|
||||||
List<UserBankBalance> listAll();
|
/**
|
||||||
|
* 统计用户银行卡账户.
|
||||||
|
*/
|
||||||
|
UserBankBalanceStatisticsDTO calculateStatistics(UserBankBalanceQryCmd query);
|
||||||
|
|
||||||
|
List<UserBankBalance> listAll();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,20 +8,24 @@ import com.red.circle.tool.core.date.TimestampUtils;
|
|||||||
import com.red.circle.tool.core.tuple.PennyAmount;
|
import com.red.circle.tool.core.tuple.PennyAmount;
|
||||||
import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankBalance;
|
import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankBalance;
|
||||||
import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankBalanceService;
|
import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankBalanceService;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
||||||
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
||||||
import java.util.Collection;
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceStatisticsDTO;
|
||||||
import java.util.List;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.bson.Document;
|
import org.bson.Document;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.mongodb.core.FindAndModifyOptions;
|
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.data.mongodb.core.FindAndModifyOptions;
|
||||||
import org.springframework.data.mongodb.core.query.Criteria;
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
import org.springframework.data.mongodb.core.query.Query;
|
||||||
import org.springframework.data.mongodb.core.query.Update;
|
import org.springframework.data.mongodb.core.query.Update;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -33,10 +37,14 @@ import org.springframework.stereotype.Service;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class UserBankBalanceServiceImpl implements UserBankBalanceService {
|
public class UserBankBalanceServiceImpl implements UserBankBalanceService {
|
||||||
|
|
||||||
private final MongoTemplate mongoTemplate;
|
private static final int DEFAULT_LIMIT = 20;
|
||||||
private final MongoPrimaryService mongoPrimaryService;
|
private static final Set<String> SORTABLE_FIELDS = Set.of(
|
||||||
|
"balance", "earnPoints", "consumptionPoints");
|
||||||
|
|
||||||
|
private final MongoTemplate mongoTemplate;
|
||||||
|
private final MongoPrimaryService mongoPrimaryService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean incr(Long userId, String sysOrigin, PennyAmount amount) {
|
public boolean incr(Long userId, String sysOrigin, PennyAmount amount) {
|
||||||
@ -112,32 +120,27 @@ public class UserBankBalanceServiceImpl implements UserBankBalanceService {
|
|||||||
balance -> BankBalanceDTO.of(balance.getBalance())));
|
balance -> BankBalanceDTO.of(balance.getBalance())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserBankBalanceDTO> listBalance(UserBankBalanceQryCmd query) {
|
public List<UserBankBalanceDTO> listBalance(UserBankBalanceQryCmd query) {
|
||||||
|
|
||||||
Criteria criteria = Criteria.where("sysOrigin").is(query.getSysOrigin());
|
boolean sorted = isSorted(query);
|
||||||
|
Criteria criteria = buildCriteria(query);
|
||||||
if (Objects.nonNull(query.getUserId())) {
|
if (!sorted && Objects.nonNull(query) && Objects.nonNull(query.getLastId())
|
||||||
if (Objects.nonNull(query.getLastId())) {
|
&& Objects.isNull(query.getUserId())) {
|
||||||
query.setLastId(null);
|
criteria.and("id").lt(query.getLastId());
|
||||||
criteria.and("id").lt(query.getLastId());
|
}
|
||||||
} else {
|
|
||||||
query.setLastId(null);
|
Query mongoQuery = Query.query(criteria)
|
||||||
criteria.and("id").is(query.getUserId());
|
.with(buildSort(query, sorted))
|
||||||
}
|
.limit(getLimit(query));
|
||||||
}
|
if (sorted) {
|
||||||
|
mongoQuery.skip((long) (getPageNo(query) - 1) * getLimit(query));
|
||||||
if (Objects.nonNull(query.getLastId())) {
|
}
|
||||||
criteria.and("id").lt(query.getLastId());
|
|
||||||
}
|
return mongoTemplate.find(mongoQuery, UserBankBalance.class).stream()
|
||||||
|
.map(balance -> new UserBankBalanceDTO()
|
||||||
return mongoTemplate.find(Query.query(criteria)
|
.setBalance(BankBalanceDTO.of(
|
||||||
.with(Sort.by(Sort.Order.desc("id")))
|
balance.getBalance()).getAccurateBalance())
|
||||||
.limit(query.getLimit()),
|
|
||||||
UserBankBalance.class).stream()
|
|
||||||
.map(balance -> new UserBankBalanceDTO()
|
|
||||||
.setBalance(BankBalanceDTO.of(
|
|
||||||
balance.getBalance()).getAccurateBalance())
|
|
||||||
.setSysOrigin(balance.getSysOrigin())
|
.setSysOrigin(balance.getSysOrigin())
|
||||||
.setId(balance.getId())
|
.setId(balance.getId())
|
||||||
.setEarnPoints(BankBalanceDTO.of(balance.getEarnPoints()).getAccurateBalance())
|
.setEarnPoints(BankBalanceDTO.of(balance.getEarnPoints()).getAccurateBalance())
|
||||||
@ -146,12 +149,83 @@ public class UserBankBalanceServiceImpl implements UserBankBalanceService {
|
|||||||
.setCreateTime(balance.getCreateTime())
|
.setCreateTime(balance.getCreateTime())
|
||||||
.setUpdateTime(balance.getUpdateTime())
|
.setUpdateTime(balance.getUpdateTime())
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserBankBalance> listAll() {
|
public UserBankBalanceStatisticsDTO calculateStatistics(UserBankBalanceQryCmd query) {
|
||||||
|
Document document = mongoTemplate.aggregate(
|
||||||
|
Aggregation.newAggregation(
|
||||||
|
Aggregation.match(buildCriteria(query)),
|
||||||
|
Aggregation.group()
|
||||||
|
.sum("earnPoints").as("totalEarnPoints")
|
||||||
|
.sum("consumptionPoints").as("totalConsumptionPoints")
|
||||||
|
.sum("balance").as("totalBalance")
|
||||||
|
),
|
||||||
|
UserBankBalance.class,
|
||||||
|
Document.class)
|
||||||
|
.getUniqueMappedResult();
|
||||||
|
|
||||||
|
return new UserBankBalanceStatisticsDTO()
|
||||||
|
.setTotalEarnPoints(getAccurateAmount(document, "totalEarnPoints"))
|
||||||
|
.setTotalConsumptionPoints(getAccurateAmount(document, "totalConsumptionPoints"))
|
||||||
|
.setTotalBalance(getAccurateAmount(document, "totalBalance"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Criteria buildCriteria(UserBankBalanceQryCmd query) {
|
||||||
|
Criteria criteria = new Criteria();
|
||||||
|
if (Objects.isNull(query)) {
|
||||||
|
return criteria;
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(query.getSysOrigin())) {
|
||||||
|
criteria.and("sysOrigin").is(query.getSysOrigin());
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(query.getUserId())) {
|
||||||
|
criteria.and("id").is(query.getUserId());
|
||||||
|
}
|
||||||
|
return criteria;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Sort buildSort(UserBankBalanceQryCmd query, boolean sorted) {
|
||||||
|
if (!sorted) {
|
||||||
|
return Sort.by(Sort.Order.desc("id"));
|
||||||
|
}
|
||||||
|
Sort.Direction direction = "ascend".equalsIgnoreCase(query.getSortOrder())
|
||||||
|
? Sort.Direction.ASC
|
||||||
|
: Sort.Direction.DESC;
|
||||||
|
return Sort.by(new Sort.Order(direction, query.getSortField()), Sort.Order.desc("id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSorted(UserBankBalanceQryCmd query) {
|
||||||
|
if (Objects.isNull(query) || Objects.isNull(query.getSortField())
|
||||||
|
|| Objects.isNull(query.getSortOrder())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return SORTABLE_FIELDS.contains(query.getSortField())
|
||||||
|
&& ("ascend".equalsIgnoreCase(query.getSortOrder())
|
||||||
|
|| "descend".equalsIgnoreCase(query.getSortOrder()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getLimit(UserBankBalanceQryCmd query) {
|
||||||
|
return Objects.nonNull(query) && Objects.nonNull(query.getLimit()) && query.getLimit() > 0
|
||||||
|
? query.getLimit()
|
||||||
|
: DEFAULT_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPageNo(UserBankBalanceQryCmd query) {
|
||||||
|
return Objects.nonNull(query) && Objects.nonNull(query.getPageNo()) && query.getPageNo() > 0
|
||||||
|
? query.getPageNo()
|
||||||
|
: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal getAccurateAmount(Document document, String key) {
|
||||||
|
return BankBalanceDTO.of(Objects.isNull(document) ? 0L : getLongValue(document, key))
|
||||||
|
.getAccurateBalance();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<UserBankBalance> listAll() {
|
||||||
return mongoTemplate.find(Query.query(new Criteria()),
|
return mongoTemplate.find(Query.query(new Criteria()),
|
||||||
UserBankBalance.class);
|
UserBankBalance.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,9 @@ import com.red.circle.wallet.inner.endpoint.bank.api.UserBankBalanceClientApi;
|
|||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceDecrCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceDecrCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceIncrCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceIncrCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
||||||
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
||||||
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceStatisticsDTO;
|
||||||
import com.red.circle.wallet.inner.service.wallet.UserBankBalanceClientService;
|
import com.red.circle.wallet.inner.service.wallet.UserBankBalanceClientService;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -56,8 +57,14 @@ public class UserBankBalanceClientEndpoint implements UserBankBalanceClientApi {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultResponse<List<UserBankBalanceDTO>> listBalance(UserBankBalanceQryCmd query) {
|
public ResultResponse<List<UserBankBalanceDTO>> listBalance(UserBankBalanceQryCmd query) {
|
||||||
return ResultResponse.success(userBankBalanceClientService.listBalance(query));
|
return ResultResponse.success(userBankBalanceClientService.listBalance(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public ResultResponse<UserBankBalanceStatisticsDTO> calculateStatistics(
|
||||||
|
UserBankBalanceQryCmd query) {
|
||||||
|
return ResultResponse.success(userBankBalanceClientService.calculateStatistics(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -3,8 +3,9 @@ package com.red.circle.wallet.inner.service.wallet;
|
|||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceDecrCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceDecrCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceIncrCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceIncrCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
||||||
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
||||||
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceStatisticsDTO;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,8 +41,13 @@ public interface UserBankBalanceClientService {
|
|||||||
*/
|
*/
|
||||||
BankBalanceDTO decr(UserBankBalanceDecrCmd cmd);
|
BankBalanceDTO decr(UserBankBalanceDecrCmd cmd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查看用户银行卡账户.
|
* 查看用户银行卡账户.
|
||||||
*/
|
*/
|
||||||
List<UserBankBalanceDTO> listBalance(UserBankBalanceQryCmd query);
|
List<UserBankBalanceDTO> listBalance(UserBankBalanceQryCmd query);
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* 统计用户银行卡账户.
|
||||||
|
*/
|
||||||
|
UserBankBalanceStatisticsDTO calculateStatistics(UserBankBalanceQryCmd query);
|
||||||
|
}
|
||||||
|
|||||||
@ -4,8 +4,9 @@ import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankBalanceSe
|
|||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceDecrCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceDecrCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceIncrCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceIncrCmd;
|
||||||
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
||||||
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
||||||
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO;
|
||||||
|
import com.red.circle.wallet.inner.model.dto.UserBankBalanceStatisticsDTO;
|
||||||
import com.red.circle.wallet.inner.service.wallet.UserBankBalanceClientService;
|
import com.red.circle.wallet.inner.service.wallet.UserBankBalanceClientService;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -44,8 +45,13 @@ public class UserBankBalanceClientServiceImpl implements UserBankBalanceClientSe
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserBankBalanceDTO> listBalance(UserBankBalanceQryCmd query) {
|
public List<UserBankBalanceDTO> listBalance(UserBankBalanceQryCmd query) {
|
||||||
return userBankBalanceService.listBalance(query);
|
return userBankBalanceService.listBalance(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public UserBankBalanceStatisticsDTO calculateStatistics(UserBankBalanceQryCmd query) {
|
||||||
|
return userBankBalanceService.calculateStatistics(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -1,9 +1,20 @@
|
|||||||
package com.red.circle.wallet.infra.database.mongo.service.bank.impl;
|
package com.red.circle.wallet.infra.database.mongo.service.bank.impl;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import com.red.circle.component.mongodb.config.MongoPrimaryService;
|
||||||
|
import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankBalance;
|
||||||
|
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceQryCmd;
|
||||||
|
import java.util.List;
|
||||||
import org.bson.Document;
|
import org.bson.Document;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
|
import org.springframework.data.mongodb.core.query.Query;
|
||||||
|
|
||||||
class UserBankBalanceServiceImplTest {
|
class UserBankBalanceServiceImplTest {
|
||||||
|
|
||||||
@ -27,4 +38,18 @@ class UserBankBalanceServiceImplTest {
|
|||||||
|
|
||||||
assertEquals(0L, UserBankBalanceServiceImpl.getLongValue(document, "balance"));
|
assertEquals(0L, UserBankBalanceServiceImpl.getLongValue(document, "balance"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listBalanceUsesDefaultSortWhenSortFieldsAreMissing() {
|
||||||
|
MongoTemplate mongoTemplate = mock(MongoTemplate.class);
|
||||||
|
when(mongoTemplate.find(any(Query.class), eq(UserBankBalance.class))).thenReturn(List.of());
|
||||||
|
UserBankBalanceServiceImpl service = new UserBankBalanceServiceImpl(
|
||||||
|
mongoTemplate, mock(MongoPrimaryService.class));
|
||||||
|
|
||||||
|
List<?> result = service.listBalance(new UserBankBalanceQryCmd()
|
||||||
|
.setSysOrigin("LIKEI")
|
||||||
|
.setLimit(1));
|
||||||
|
|
||||||
|
assertTrue(result.isEmpty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user