游戏薪资fixed

游戏薪资
This commit is contained in:
2025-07-31 19:02:22 +08:00
parent b2e29e074d
commit 2109ed97af
61 changed files with 3023 additions and 0 deletions

View File

@@ -286,6 +286,8 @@ public class UserCheckAdminService {
throw new AdminServiceException("用户钻石余额不为0不能改变分区");
} else if (userPurse.getGuildUsd() > 0d){
throw new AdminServiceException("用户金币公会薪资不为0不能改变分区");
} else if (userPurse.getGameUsd() > 0d){
throw new AdminServiceException("用户游戏薪资不为0不能改变分区");
}
FamilyClanDecorateVo clanVo = familyClanService.getFamilyClanDecorateVo(users.getUid(), users.getUid());

View File

@@ -978,6 +978,12 @@ public enum BusiStatus {
GUILD_H5_INVITE_EMAIL_ALREADY_BOUND(33001, "该邮箱地址不是新的"),
GUILD_H5_INVITE_JOIN_GUILD_NOT_EXIST(33002, "邀请人公会不存在"),
GAME_USD_RECV_EXPIRE(20516, "RECEIVE EXPIRE"),
GAME_USD_RECV_EXIST(20516, "HAS RECEIVE"),
GAME_USD_CURRENT_DAY_RECEIVE_LIMIT(20516, "CURRENT DAY RECEIVE LIMIT"),
;
private final int value;

View File

@@ -1382,9 +1382,12 @@ public class Constant {
public static final String GUILD_USD_TO_RECHARGE_USER_LIMIT_CONFIG = "guild_usd_to_recharge_user_limit_config";
public static final String USER_SET_LIMIT_CONFIG = "user_set_limit_config";
public static final String OFFICIAL_GOLD_ROLE_LIMIT_CONFIG = "official_gold_role_limit_config";
public static final String GAME_USD_TO_RECHARGE_USER_LIMIT = "game_usd_to_recharge_user_limit";
}
public static class WithDrawStatus {

View File

@@ -58,6 +58,7 @@ public enum RedisKey {
lock_user_diamond, // 钻石分布式锁
lock_user_crystal, // 水晶分布式锁
lock_user_guild_usd, // 公会usd分布式锁
lock_user_game_usd, // 游戏usd分布式锁
lock_gift_message, // 消费送礼物消息锁
mq_gift_status, // 礼物消息的状态
mq_prize_status, // 中奖消息的状态
@@ -1465,6 +1466,8 @@ public enum RedisKey {
lock_user_pack, //礼包锁
v5pay_lock, //v5pay支付锁
game_usd_recv_lock, //游戏薪资锁
;
public String getKey() {

View File

@@ -0,0 +1,18 @@
package com.accompany.business.constant.guildgame;
import com.accompany.common.utils.DateTimeUtil;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class GameTimeUtil {
public static String getCycleDate(ZonedDateTime zdt) {
return zdt.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0)
.format(DateTimeFormatter.ofPattern(DateTimeUtil.DEFAULT_DATE_PATTERN));
}
public static String getStatDate(ZonedDateTime zdt){
return zdt.format(DateTimeFormatter.ofPattern(DateTimeUtil.DEFAULT_DATE_PATTERN));
}
}

View File

@@ -0,0 +1,74 @@
package com.accompany.business.constant.guildgame;
import com.accompany.business.constant.guild.GuildConstant;
import com.accompany.core.enumeration.BillObjTypeEnum;
import com.accompany.core.enumeration.CurrencyEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Set;
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum GameUsdOperateTypeEnum {
RECEIVE_USD(1, null, Set.of(GuildConstant.RoleType.OWNER, GuildConstant.RoleType.MANAGER, GuildConstant.RoleType.NORMAL), null,
false, null, CurrencyEnum.GAME_USD, null,
null, BillObjTypeEnum.GAME_RECE_USD_IN),
USD_TO_PLATFORM(2, GuildConstant.UsdTab.PERSONAL, Set.of(GuildConstant.RoleType.OWNER, GuildConstant.RoleType.MANAGER, GuildConstant.RoleType.NORMAL), null,
true, CurrencyEnum.GAME_USD, CurrencyEnum.DIAMOND, new BigDecimal("31000"),
BillObjTypeEnum.GAME_USD_EXCHANGE_GOLD_OUT, BillObjTypeEnum.GAME_USD_EXCHANGE_GOLD_IN),//1:31000
USD_TO_RECHARGE_USER(3, GuildConstant.UsdTab.PERSONAL, Set.of(GuildConstant.RoleType.OWNER, GuildConstant.RoleType.MANAGER, GuildConstant.RoleType.NORMAL), null,
true, CurrencyEnum.GAME_USD, CurrencyEnum.DIAMOND, new BigDecimal("30000"),
BillObjTypeEnum.GAME_USD_TO_RECHARGE_USER_OUT, BillObjTypeEnum.GAME_USD_TO_RECHARGE_USER_IN),//1:1000
USD_TO_GUILD_OWNER(4, GuildConstant.UsdTab.AGENT, Set.of(GuildConstant.RoleType.MANAGER, GuildConstant.RoleType.NORMAL), null,
false, CurrencyEnum.GAME_USD, CurrencyEnum.GAME_USD, BigDecimal.ONE,
BillObjTypeEnum.GAME_USD_TO_GUILD_OWNER_OUT, BillObjTypeEnum.GAME_USD_TO_GUILD_OWNER_IN),
//USD_WITHDRAW(5, GuildConstant.UsdTab.AGENT, Set.of(GuildConstant.RoleType.OWNER), null,
// false, CurrencyEnum.GAME_USD, null, null,
// BillObjTypeEnum.GAME_USD_TO_PLATFORM_OUT, null),
//OWNER_USD_WITHDRAW(5, GuildConstant.UsdTab.AGENT, Set.of(GuildConstant.RoleType.OWNER), Set.of(1, 2, 3),
// false, CurrencyEnum.GAME_USD, null, null,
// BillObjTypeEnum.GAME_USD_TO_PLATFORM_OUT, null),
OWNER_USD_WITHDRAW(5, GuildConstant.UsdTab.AGENT, Set.of(GuildConstant.RoleType.OWNER), null,
false, CurrencyEnum.GAME_USD, null, null,
BillObjTypeEnum.GAME_USD_TO_PLATFORM_OUT, null),
USD_WITHDRAW_REJECT(7, null, null, null,
false, null, CurrencyEnum.GAME_USD, null,
null, BillObjTypeEnum.GAME_USD_TO_PLATFORM_IN),
//MEMBER_USD_WITHDRAW(8, GuildConstant.UsdTab.AGENT, Set.of(GuildConstant.RoleType.MANAGER, GuildConstant.RoleType.NORMAL), Set.of(1, 2, 3),
// false, CurrencyEnum.GAME_USD, null, null,
// BillObjTypeEnum.GAME_USD_TO_PLATFORM_OUT, null),
MEMBER_USD_WITHDRAW(8, GuildConstant.UsdTab.AGENT, Set.of(GuildConstant.RoleType.MANAGER, GuildConstant.RoleType.NORMAL), null,
false, CurrencyEnum.GAME_USD, null, null,
BillObjTypeEnum.GAME_USD_TO_PLATFORM_OUT, null),
;
private int type;
private String tabKey;
private Set<Byte> roleTypeSet;
private Set<Integer> dayOfMonthSet;
private boolean canCustom;
private CurrencyEnum outputCurrency;
private CurrencyEnum inputCurrency;
private BigDecimal ratio;
private BillObjTypeEnum outBillObjType;
private BillObjTypeEnum inBillObjType;
public boolean isCanCustom() {
return canCustom;
}
}

View File

@@ -0,0 +1,30 @@
package com.accompany.business.constant.guildgame;
import com.accompany.common.constant.Constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum GameWithdrawAccountFieldEnum {
COUNTRY("country", Constant.status.invalid),
ACCOUNT("account", Constant.status.valid),
BANK_ACCOUNT("bank_account", Constant.status.delete),
BANK_NAME("bank_name", Constant.status.delete),
SWIFT_CODE("swift_code", Constant.status.delete),
FULL_NAME("full_name", Constant.status.delete),
ADDRESS("address", Constant.status.delete),
DOCUMENT_ID("document_id", Constant.status.delete),
ACCOUNT_TYPE("account_type", Constant.status.delete),
ACCOUNT_NO("account_no", Constant.status.delete),
ACCOUNT_NAME("account_name", Constant.status.delete),
;
private String fieldName;
private byte type;
}

View File

@@ -0,0 +1,68 @@
package com.accompany.business.constant.guildgame;
import com.accompany.business.constant.CountryEnum;
import com.accompany.core.enumeration.PartitionEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.List;
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum GameWithdrawAccountTypeEnum {
//PAYONNER("payonner", PartitionEnum.ARAB.getId() + PartitionEnum.TURKEY.getId(), List.of(CountryEnum.AE,CountryEnum.EG,CountryEnum.QA,CountryEnum.SA,CountryEnum.TR,CountryEnum.YE,CountryEnum.AZ, CountryEnum.CY,CountryEnum.Other),
// List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.ACCOUNT, GuildWithdrawAccountFieldEnum.FULL_NAME)),
VODAFONE("vodafone", PartitionEnum.ARAB.getId(), List.of(CountryEnum.EG),
List.of(GameWithdrawAccountFieldEnum.COUNTRY, GameWithdrawAccountFieldEnum.ACCOUNT)),
/*BANK("bank", PartitionEnum.ARAB.getId() + PartitionEnum.TURKEY.getId(), List.of(CountryEnum.AE,CountryEnum.QA,CountryEnum.SA,CountryEnum.TR,CountryEnum.YE, CountryEnum.AZ, CountryEnum.CY),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.BANK_ACCOUNT, GuildWithdrawAccountFieldEnum.BANK_NAME,
GuildWithdrawAccountFieldEnum.SWIFT_CODE, GuildWithdrawAccountFieldEnum.FULL_NAME, GuildWithdrawAccountFieldEnum.ADDRESS)),
USDT("usdt", PartitionEnum.ARAB.getId(), List.of(CountryEnum.AE,CountryEnum.EG,CountryEnum.QA,CountryEnum.SA,CountryEnum.TR,CountryEnum.YE,CountryEnum.Other),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.ACCOUNT)),
BANK_TRANSFER_LIRA("Bank Transfer Lira", PartitionEnum.TURKEY.getId(), List.of(CountryEnum.TR,CountryEnum.Other),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.BANK_ACCOUNT, GuildWithdrawAccountFieldEnum.FULL_NAME)),
CARD_USD("Card Usd", PartitionEnum.TURKEY.getId(), List.of(CountryEnum.TR,CountryEnum.Other),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.BANK_ACCOUNT, GuildWithdrawAccountFieldEnum.FULL_NAME)),
BANK_EN2("bank", PartitionEnum.ENGLISH.getId(), List.of(CountryEnum.BD,CountryEnum.ID,CountryEnum.MY,CountryEnum.PH,CountryEnum.PK, CountryEnum.VN, CountryEnum.IN, CountryEnum.NG),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.BANK_ACCOUNT, GuildWithdrawAccountFieldEnum.BANK_NAME,
GuildWithdrawAccountFieldEnum.SWIFT_CODE, GuildWithdrawAccountFieldEnum.FULL_NAME, GuildWithdrawAccountFieldEnum.ADDRESS)),
USDT_EN2("usdt", PartitionEnum.ENGLISH.getId(), List.of(CountryEnum.US, CountryEnum.CA, CountryEnum.GR, CountryEnum.NG),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.ACCOUNT, GuildWithdrawAccountFieldEnum.ACCOUNT_NAME)),
PAYONNER_EN2("payonner", PartitionEnum.ENGLISH.getId(), List.of(CountryEnum.BD,CountryEnum.ID,CountryEnum.MY,CountryEnum.PH,CountryEnum.PK, CountryEnum.VN, CountryEnum.IN, CountryEnum.NG,CountryEnum.Other),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.ACCOUNT, GuildWithdrawAccountFieldEnum.FULL_NAME)),
EPAY_EN2("epay", PartitionEnum.ENGLISH.getId(), List.of(CountryEnum.BD,CountryEnum.ID,CountryEnum.MY,CountryEnum.PH,CountryEnum.PK, CountryEnum.VN, CountryEnum.IN, CountryEnum.NG),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.BANK_ACCOUNT)),
GCASH_EN2("gcash", PartitionEnum.ENGLISH.getId(), List.of(CountryEnum.PH),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.BANK_ACCOUNT, GuildWithdrawAccountFieldEnum.FULL_NAME)),
DANA_EN2("DANA", PartitionEnum.ENGLISH.getId(), List.of(CountryEnum.ID),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.BANK_ACCOUNT, GuildWithdrawAccountFieldEnum.FULL_NAME)),
EASYPAISA_EN2("easypaisa", PartitionEnum.ENGLISH.getId(), List.of(CountryEnum.PK),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.BANK_ACCOUNT, GuildWithdrawAccountFieldEnum.FULL_NAME)),
PIX("pix", PartitionEnum.ENGLISH.getId(), List.of(CountryEnum.BR),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.DOCUMENT_ID, GuildWithdrawAccountFieldEnum.ACCOUNT_TYPE,
GuildWithdrawAccountFieldEnum.ACCOUNT_NO, GuildWithdrawAccountFieldEnum.ACCOUNT_NAME)),
ZALO("zalo", PartitionEnum.ENGLISH.getId() + PartitionEnum.ENGLISH.getId(), List.of(CountryEnum.VN),
List.of(GuildWithdrawAccountFieldEnum.COUNTRY, GuildWithdrawAccountFieldEnum.ACCOUNT_NO, GuildWithdrawAccountFieldEnum.ACCOUNT_NAME)),*/
;
private String type;
private Integer partitionFlag;
private List<CountryEnum> country;
private List<GameWithdrawAccountFieldEnum> fieldList;
}

View File

@@ -0,0 +1,23 @@
package com.accompany.business.dto.guild;
import lombok.Data;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
public class GameUsdToRechargeUserLimitConfigDto {
private Map<Integer, GameUsdToRechargeUserLimitConfigDto> partitionMap = new HashMap<>();
private BigDecimal dayNumLimit;
private List<Integer> memberEnableDayOfMonth;
private List<Integer> ownerEnableDayOfMonth;
public GameUsdToRechargeUserLimitConfigDto getByPartitionId(int partitionId) {
return partitionMap.getOrDefault(partitionId, this);
}
}

View File

@@ -28,6 +28,8 @@ public class UserPurse {
private Double guildUsd;
private Double gameUsd;
private Boolean firstCharge;
private Date updateTime;
@@ -41,6 +43,8 @@ public class UserPurse {
return diamonds;
} else if (CurrencyEnum.GUILD_USD.equals(currency)) {
return guildUsd;
} else if (CurrencyEnum.GAME_USD.equals(currency)) {
return gameUsd;
}
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}

View File

@@ -0,0 +1,43 @@
package com.accompany.business.model.guildgame;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 游戏工资表实体类
*
* @author
* @since 2025-07-30
*/
@Data
public class GameDiamondSalary implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 玩游戏次数
*/
private Integer playGameNum;
private Integer partitionId;
/**
* 等级
*/
private String level;
/**
* 钻石目标
*/
private BigDecimal diamondNum;
/**
* 基础工资
*/
private BigDecimal baseSalary;
/**
* 创建时间
*/
private Date createTime;
}

View File

@@ -0,0 +1,52 @@
package com.accompany.business.model.guildgame;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 公会钻石流水统计按天实体类
*
* @author
* @since 2025-07-30
*/
@Data
public class GameDiamondStatDay implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id" , type = IdType.AUTO)
private Long id;
private String cycleDate;
private Integer partitionId;
/**
* 统计日期
*/
private String statDate;
private Long guildMemberId;
private Long uid;
/**
* 所属厅id
*/
private Integer guildId;
/**
* 玩游戏次数
*/
private Integer playGameNum;
private BigDecimal diamondNum;
/**
* 领取状态
*/
private Byte receiveStatus;
/**
* 创建时间
*/
private Date createTime;
private Date updateTime;
}

View File

@@ -0,0 +1,46 @@
package com.accompany.business.model.guildgame;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 实体类
*
* @author
* @since 2025-07-30
*/
@Data
public class GameUsdBillRecord implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id" , type = IdType.AUTO)
private Long id;
private String no;
private Integer type;
private Integer partitionId;
private Long guildMemberId;
private Integer guildId;
private Long uid;
private Long targetGuildMemberId;
private Long targetUid;
private String cycleDate;
private String statDate;
private BigDecimal beforeUsd;
private BigDecimal operateUsd;
private BigDecimal afterUsd;
private Byte currency;
private BigDecimal beforeCurrency;
private BigDecimal operateCurrency;
private BigDecimal afterCurrency;
private Date createTime;
private Long recordId;
private String remark;
}

View File

@@ -0,0 +1,39 @@
package com.accompany.business.model.guildgame;
import com.accompany.business.constant.guildgame.GameUsdOperateTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 实体类
*
* @author
* @since 2025-07-30
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class GameUsdProd implements Serializable {
private static final long serialVersionUID = 1L;
private Integer type;
private BigDecimal gameUsdNum;
private Integer partitionId;
private BigDecimal currencyNum;
private BigDecimal extraCurrencyNum;
private Boolean enable;
public GameUsdProd(GameUsdOperateTypeEnum typeEnum, BigDecimal gameUsdNum, Integer partitionId) {
this.partitionId = partitionId;
this.type = typeEnum.getType();
this.gameUsdNum = gameUsdNum;
this.currencyNum = gameUsdNum.multiply(typeEnum.getRatio());
this.extraCurrencyNum = BigDecimal.ZERO;
this.enable = true;
}
}

View File

@@ -0,0 +1,27 @@
package com.accompany.business.model.guildgame;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 实体类
*
* @author
* @since 2025-07-30
*/
@Data
public class GameUsdWithdrawAccount implements Serializable {
private static final long serialVersionUID = 1L;
private Long uid;
private String accountType;
private String accountCountry;
private Boolean enable;
private String accountFields;
private Date createTime;
}

View File

@@ -0,0 +1,32 @@
package com.accompany.business.model.guildgame;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 实体类
*
* @author
* @since 2025-07-30
*/
@Data
public class GameUsdWithdrawAccountConfig implements Serializable {
private static final long serialVersionUID = 1L;
private String accountType;
private Integer partitionId;
private String country;
private String currency;
private BigDecimal usdRatio;
private BigDecimal feeRate;
private Boolean enable;
private Integer seq;
private Date updateTime;
private Integer adminId;
}

View File

@@ -0,0 +1,42 @@
package com.accompany.business.model.guildgame;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 实体类
*
* @author
* @since 2025-07-30
*/
@Data
public class GameUsdWithdrawRecord implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id" , type = IdType.AUTO)
private Long id;
private Integer partitionId;
private Integer guildId;
private Long uid;
private BigDecimal gameUsdNum;
private String remark;
private Byte status;
private Date createTime;
private Date updateTime;
private String operator;
private String accountType;
private String accountCountry;
private String accountInfos;
private String currency;
private BigDecimal currencyNum;
private BigDecimal withdrawRate;
private BigDecimal withdrawNum;
}

View File

@@ -0,0 +1,27 @@
package com.accompany.business.vo.guildgame;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
@ApiModel
@Data
public class GameUsdAccountCycleUsdStatVo {
@ApiModelProperty("周期")
private String cycleDate;
@ApiModelProperty("总收入")
private BigDecimal totalIncome;
@ApiModelProperty("总支出")
private BigDecimal settledIncome;
@ApiModelProperty("剩余")
private BigDecimal remainingIncome;
public GameUsdAccountCycleUsdStatVo(String cycleDate) {
this.cycleDate = cycleDate;
this.totalIncome = BigDecimal.ZERO;
this.settledIncome = BigDecimal.ZERO;
this.remainingIncome = BigDecimal.ZERO;
}
}

View File

@@ -0,0 +1,36 @@
package com.accompany.business.vo.guildgame;
import com.accompany.business.vo.SimpleUserVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
@ApiModel
@Data
public class GameUsdBillRecordVo {
@ApiModelProperty("单号")
private String no;
@ApiModelProperty("类型枚举")
private Integer type;
@ApiModelProperty("me")
private SimpleUserVo me;
@ApiModelProperty("对象官方提现时为null")
private SimpleUserVo target;
@ApiModelProperty("变化前")
private BigDecimal beforeUsdNum;
@ApiModelProperty("变化量")
private BigDecimal operateUsdNum;
@ApiModelProperty("变化后")
private BigDecimal afterUsdNum;
@ApiModelProperty("时间")
private String createTime;
@ApiModelProperty("提现状态")
private Byte status;
}

View File

@@ -0,0 +1,28 @@
package com.accompany.business.vo.guildgame;
import com.accompany.business.vo.SimpleUserVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@ApiModel
@Data
public class GameUsdOperateBillRecordVo {
@ApiModelProperty("单号")
private String no;
@ApiModelProperty("自己")
private SimpleUserVo me;
@ApiModelProperty("对象官方提现时为null")
private SimpleUserVo target;
@ApiModelProperty("数量")
private BigDecimal gameUsdNum;
@ApiModelProperty("货币")
private BigDecimal currencyNum;
@ApiModelProperty("时间")
private Date createTime;
}

View File

@@ -0,0 +1,39 @@
package com.accompany.business.vo.guildgame;
import com.accompany.business.vo.SimpleUserVo;
import com.accompany.payment.vo.RechargeUserVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@ApiModel
@Data
public class GameUsdOperateTabVo {
@ApiModelProperty("公会成员编号")
private Long guildMemberId;
@ApiModelProperty("公会id")
private Integer guildId;
private Long uid;
@ApiModelProperty("公会长")
private SimpleUserVo guildOwner;
@ApiModelProperty("代储列表")
private List<RechargeUserVo> rechargeUserList;
@ApiModelProperty("转赠代理限制tip")
private String rechargeUserLimitTip;
@ApiModelProperty("usd余额")
private Double gameUsdNum;
@ApiModelProperty("标签页")
private List<GameUsdProdTabVo> typeTab;
@ApiModelProperty("提现账户")
private List<GuildMemberGameUsdWithdrawAccountVo> withdrawAccountList;
}

View File

@@ -0,0 +1,26 @@
package com.accompany.business.vo.guildgame;
import com.accompany.business.model.guildgame.GameUsdProd;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@ApiModel
@Data
public class GameUsdProdChannelVo {
@ApiModelProperty("功能标签")
private String tabKey;
@ApiModelProperty("类型1=领取usd2=usd兑换金币3=usd代储结算4=usd会长结算5=usd平台结算")
private int type;
@ApiModelProperty("是否有自定义")
private boolean canCustom;
@ApiModelProperty("usd到货币比例")
private BigDecimal ratio;
@ApiModelProperty("挡位列表")
private List<GameUsdProd> prodList;
}

View File

@@ -0,0 +1,20 @@
package com.accompany.business.vo.guildgame;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@ApiModel
@Data
public class GameUsdProdTabVo {
@ApiModelProperty("tab")
private String tabKey;
@ApiModelProperty("seq")
private Integer seq;
@ApiModelProperty("a")
private List<GameUsdProdChannelVo> channelList;
}

View File

@@ -0,0 +1,26 @@
package com.accompany.business.vo.guildgame;
import com.accompany.business.vo.SimpleUserVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@ApiModel
@Data
public class GameUsdRechargeUserRecordVo {
@ApiModelProperty("对象官方提现时为null")
private SimpleUserVo target;
@ApiModelProperty("guildUsd变化量")
private BigDecimal gameUsdNum;
@ApiModelProperty("gold变化量")
private BigDecimal goldNum;
@ApiModelProperty("时间")
private Date createTime;
}

View File

@@ -0,0 +1,39 @@
package com.accompany.business.vo.guildgame;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@ApiModel
@Data
public class GameUsdWithdrawAccountVo {
private Long uid;
@ApiModelProperty("类型")
private String type;
@ApiModelProperty("国家")
private String country;
@ApiModelProperty("国家选项")
private List<Country> countryOptionalList;
@ApiModelProperty("字段对象")
private JSONObject fields;
@Data
public static class Country {
private String value;
private String name;
private String currency;
private BigDecimal usdRatio;
private BigDecimal feeRate;
private Integer seq;
}
}

View File

@@ -0,0 +1,29 @@
package com.accompany.business.vo.guildgame;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import java.math.BigDecimal;
@Builder
@ApiModel
@Data
public class GuildGameDayDetailVo {
@ApiModelProperty("统计日期")
private String statDate;
@ApiModelProperty("领取状态:0-未领取,1-已领取, 2-已过期, 4-当天不可领取")
private Byte receiveStatus;
@ApiModelProperty("薪资")
private BigDecimal daySalary;
@ApiModelProperty("游戏次数")
private Integer playGameNum;
@ApiModelProperty("游戏名称")
private String gameName;
}

View File

@@ -0,0 +1,22 @@
package com.accompany.business.vo.guildgame;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class GuildGameDayVo {
@ApiModelProperty("月份")
private String monthDate;
@ApiModelProperty("每日数据")
private List<GuildGameDayDetailVo> dayDetailList;
@ApiModelProperty("已领取薪资")
private BigDecimal receivedSalary;
@ApiModelProperty("总游戏次数")
private Integer totalPlayGameNum;
@ApiModelProperty("游戏名称")
private String gameName;
}

View File

@@ -0,0 +1,25 @@
package com.accompany.business.vo.guildgame;
import com.accompany.business.vo.SimpleUserVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
@ApiModel
@Data
public class GuildGameSalaryVo extends SimpleUserVo {
/**
* 薪资
*/
@ApiModelProperty("游戏薪资")
private BigDecimal gameSalary = BigDecimal.ZERO;
@ApiModelProperty("用户公会关联ID")
private Long guildMemberId;
@ApiModelProperty("游戏数据")
private GuildGameDayVo gameDayVo;
}

View File

@@ -0,0 +1,26 @@
package com.accompany.business.vo.guildgame;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
@ApiModel
@Data
public class GuildMemberGameUsdWithdrawAccountVo {
@ApiModelProperty("账户类型")
private String type;
@ApiModelProperty("")
private String name;
@ApiModelProperty("货币")
private String currency;
@ApiModelProperty("汇率")
private BigDecimal usdRatio;
@ApiModelProperty("手续费")
private BigDecimal withdrawRate;
@ApiModelProperty("是否已绑定")
private Boolean hasBound;
}

View File

@@ -42,4 +42,8 @@ public interface UserPurseMapper extends BaseMapper<UserPurse> {
UserPurse queryByUid(@Param("uid") Long uid);
int addGameUsd(@Param("uid") Long uid, @Param("gameUsd") Double gameUsd);
int minusGameUsd(@Param("uid") Long uid, @Param("gameUsd") Double gameUsd);
}

View File

@@ -0,0 +1,14 @@
package com.accompany.business.mybatismapper.guildgame;
import com.accompany.business.model.guildgame.GameDiamondSalary;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* 游戏工资表 Mapper 接口
*
* @author
* @since 2025-07-30
*/
public interface GameDiamondSalaryMapper extends BaseMapper<GameDiamondSalary> {
}

View File

@@ -0,0 +1,21 @@
package com.accompany.business.mybatismapper.guildgame;
import com.accompany.business.model.guildgame.GameDiamondStatDay;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.Date;
/**
* 公会钻石流水统计按天 Mapper 接口
*
* @author
* @since 2025-07-30
*/
public interface GameDiamondStatDayMapper extends BaseMapper<GameDiamondStatDay> {
Integer addGameDiamondStatDay(@Param("uid") Long uid, @Param("guildMemberId") Long guildMemberId, @Param("cycleDate") String cycleDate,
@Param("statDate") String statDate, @Param("partitionId") Integer partitionId,@Param("guildId") Integer guildId,
@Param("playGameNum") Integer playGameNum, @Param("diamondNum") BigDecimal diamondNum, @Param("time") Date time);
}

View File

@@ -0,0 +1,41 @@
package com.accompany.business.mybatismapper.guildgame;
import com.accompany.business.model.guildgame.GameUsdBillRecord;
import com.accompany.business.vo.guild.AnchorSalaryBillAdminVo;
import com.accompany.business.vo.guildgame.GameUsdAccountCycleUsdStatVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
/**
* Mapper 接口
*
* @author
* @since 2025-07-30
*/
public interface GameUsdBillRecordMapper extends BaseMapper<GameUsdBillRecord> {
List<GameUsdBillRecord> listRechargeUserOrderByUsdDesc(@Param("uidList") List<Long> rechargeUserUidList, @Param("cycleDate") String cycleDate, @Param("type") Integer type);
Page<GameUsdBillRecord> listPage(@Param("ipage") Page<GameUsdBillRecord> ipage, @Param("partitionId") Integer partitionId, @Param("dateCycle") String dateCycle,
@Param("uid") Long uid, @Param("receiveUid") Long receiveUid, @Param("startTime") String startTime,
@Param("endTime") String endTime, @Param("salaryOperateType") Integer salaryOperateType, @Param("hallId") Long hallId);
List<GameUsdAccountCycleUsdStatVo> getCycleUsdStatInCycleDateList(@Param("memberId") Long memberId, @Param("cycleDateList") List<String> cycleDateList);
Double sum(@Param("partitionId")Integer partitionId, @Param("uid") Long uid, @Param("receiveUid") Long receiveUid, @Param("startTime") String startTime, @Param("endTime") String endTime,
@Param("salaryOperateType") Integer salaryOperateType);
Page<AnchorSalaryBillAdminVo> anchorSummary(@Param("page") Page<AnchorSalaryBillAdminVo> page,
@Param("dateCycle") String dateCycle, @Param("uid") Long uid, @Param("hallId") Integer hallId, @Param("partitionId") Integer partitionId);
Double sumRechargeUsd(@Param("receiveUid") Long receiveUid, @Param("cycleDate") String cycleDate, @Param("salaryOperateType") Integer salaryOperateType);
List<GameUsdBillRecord> sumReceiveGameUsdGroupByTargetUid(@Param("partitionId") Integer partitionId,
@Param("startTime") Date startTime,
@Param("endTime") Date endTime);
}

View File

@@ -0,0 +1,14 @@
package com.accompany.business.mybatismapper.guildgame;
import com.accompany.business.model.guildgame.GameUsdProd;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* Mapper 接口
*
* @author
* @since 2025-07-30
*/
public interface GameUsdProdMapper extends BaseMapper<GameUsdProd> {
}

View File

@@ -0,0 +1,14 @@
package com.accompany.business.mybatismapper.guildgame;
import com.accompany.business.model.guildgame.GameUsdWithdrawAccountConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* Mapper 接口
*
* @author
* @since 2025-07-30
*/
public interface GameUsdWithdrawAccountConfigMapper extends BaseMapper<GameUsdWithdrawAccountConfig> {
}

View File

@@ -0,0 +1,14 @@
package com.accompany.business.mybatismapper.guildgame;
import com.accompany.business.model.guildgame.GameUsdWithdrawAccount;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* Mapper 接口
*
* @author
* @since 2025-07-30
*/
public interface GameUsdWithdrawAccountMapper extends BaseMapper<GameUsdWithdrawAccount> {
}

View File

@@ -0,0 +1,14 @@
package com.accompany.business.mybatismapper.guildgame;
import com.accompany.business.model.guildgame.GameUsdWithdrawRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* Mapper 接口
*
* @author
* @since 2025-07-30
*/
public interface GameUsdWithdrawRecordMapper extends BaseMapper<GameUsdWithdrawRecord> {
}

View File

@@ -0,0 +1,47 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.model.guildgame.GameDiamondSalary;
import com.accompany.business.mybatismapper.guildgame.GameDiamondSalaryMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* 游戏工资表 服务实现类
*
* @author
* @since 2025-07-30
*/
@Service
public class GameDiamondSalaryService extends ServiceImpl<GameDiamondSalaryMapper, GameDiamondSalary> {
public GameDiamondSalary calDiamondSalary(Integer playGameNum, Integer partitionId){
TreeMap<Integer, GameDiamondSalary> diamondSalaryMap = getDiamondSalaryMap(partitionId);
Map.Entry<Integer, GameDiamondSalary> curDiamondLevel = diamondSalaryMap.headMap(playGameNum, true).lastEntry();
return curDiamondLevel.getValue();
}
public TreeMap<Integer, GameDiamondSalary> getDiamondSalaryMap(Integer partitionId) {
List<GameDiamondSalary> salaryList = lambdaQuery()
.eq(GameDiamondSalary::getPartitionId, partitionId).list();
return getMap(salaryList);
}
public TreeMap<Integer, GameDiamondSalary> getMap(List<GameDiamondSalary> salaryList) {
TreeMap<Integer, GameDiamondSalary> map = new TreeMap<>();
if (CollectionUtils.isEmpty(salaryList)){
return map;
}
for (GameDiamondSalary salary : salaryList) {
map.put(salary.getPlayGameNum(), salary);
}
return map;
}
}

View File

@@ -0,0 +1,27 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.model.guildgame.GameDiamondStatDay;
import com.baomidou.mybatisplus.extension.service.IService;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 公会钻石流水统计按天 服务类
*
* @author
* @since 2025-07-30
*/
public interface GameDiamondStatDayService extends IService<GameDiamondStatDay> {
Integer addGameDiamondStatDay(Long uid, Long guildMemberId, Date dataDate, Integer partitionId,
Integer guildId, Integer playGameNum, BigDecimal diamondNum);
List<GameDiamondStatDay> getGuildGameMonthList(Long guildMemberId, String cycleDate);
List<GameDiamondStatDay> queryByGuildMemberIdAndCycleDate(Long guildMemberId, String cycleDate);
GameDiamondStatDay queryByGuildMemberIdAndStatDate(Long guildMemberId, String cycleDate, String statDate);
}

View File

@@ -0,0 +1,373 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.constant.guildgame.GameTimeUtil;
import com.accompany.business.constant.guildgame.GameUsdOperateTypeEnum;
import com.accompany.business.model.UserPurse;
import com.accompany.business.model.guildgame.GameUsdBillRecord;
import com.accompany.business.model.guildgame.GameUsdWithdrawRecord;
import com.accompany.business.mybatismapper.guildgame.GameUsdBillRecordMapper;
import com.accompany.business.param.BasePageParams;
import com.accompany.business.service.user.UsersService;
import com.accompany.business.util.CycleTimeUtil;
import com.accompany.business.vo.guild.AnchorSalaryBillAdminVo;
import com.accompany.business.vo.guildgame.GameUsdAccountCycleUsdStatVo;
import com.accompany.business.vo.guildgame.GameUsdBillRecordVo;
import com.accompany.business.vo.guildgame.GameUsdRechargeUserRecordVo;
import com.accompany.common.constant.Constant;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.DateTimeUtil;
import com.accompany.core.enumeration.CurrencyEnum;
import com.accompany.core.enumeration.PartitionEnum;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.model.PartitionInfo;
import com.accompany.core.model.Users;
import com.accompany.core.service.partition.PartitionInfoService;
import com.accompany.payment.service.RechargeUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* 服务类
*
* @author
* @since 2025-07-30
*/
@Service
public class GameUsdBillRecordService extends ServiceImpl<GameUsdBillRecordMapper, GameUsdBillRecord> {
@Autowired
private UsersService usersService;
@Autowired
private PartitionInfoService partitionInfoService;
@Autowired
private RechargeUserService rechargeUserService;
@Autowired
private GameUsdWithdrawRecordService gameUsdWithdrawRecordService;
public GameUsdBillRecord insert(String no, Integer partitionId, Long memberId, Integer guildId, Long uid, Long targetMemberId, Long targetUid, GameUsdOperateTypeEnum typeEnum,
UserPurse before, UserPurse after, BigDecimal gameUsdNum, BigDecimal currencyNum, Long recordId, String remark, Date statDate) {
GameUsdBillRecord record = new GameUsdBillRecord();
record.setNo(no);
record.setType(typeEnum.getType());
record.setGuildMemberId(memberId);
record.setGuildId(guildId);
record.setUid(uid);
record.setPartitionId(partitionId);
record.setTargetGuildMemberId(targetMemberId);
record.setTargetUid(targetUid);
if (statDate != null) {
Users u = usersService.getNotNullUsersByUid(null != uid ? uid : targetUid);
PartitionEnum partitionEnum = PartitionEnum.getByPartitionId(u.getPartitionId());
ZonedDateTime zdt = DateTimeUtil.convertWithZoneId(statDate, partitionEnum.getZoneId());
record.setCycleDate(GameTimeUtil.getCycleDate(zdt));
record.setStatDate(GameTimeUtil.getStatDate(zdt));
}
boolean usdIsOutput = CurrencyEnum.GAME_USD.equals(typeEnum.getOutputCurrency());
BigDecimal afterUsdNum = BigDecimal.valueOf((usdIsOutput ? before : after).getGameUsd());
record.setAfterUsd(afterUsdNum);
BigDecimal operateUsdNum = usdIsOutput ? gameUsdNum.negate() : gameUsdNum;
record.setOperateUsd(operateUsdNum);
BigDecimal beforeUsdNum = afterUsdNum.subtract(operateUsdNum);
record.setBeforeUsd(beforeUsdNum);
if (null != currencyNum) {
boolean currencyIsInput = typeEnum.getOutputCurrency().equals(CurrencyEnum.GAME_USD);
CurrencyEnum currency = currencyIsInput ? typeEnum.getInputCurrency() : typeEnum.getOutputCurrency();
record.setCurrency(currency.getValue());
BigDecimal afterCurrency = BigDecimal.valueOf((currencyIsInput ? after : before).getNumByCurrency(currency));
record.setAfterCurrency(afterCurrency);
BigDecimal operateCurrency = currencyIsInput ? currencyNum : currencyNum.negate();
record.setOperateCurrency(operateCurrency);
BigDecimal beforeCurrency = afterCurrency.subtract(operateCurrency);
record.setBeforeCurrency(beforeCurrency);
}
record.setCreateTime(new Date());
record.setRecordId(recordId);
record.setRemark(remark);
save(record);
return record;
}
public GameUsdBillRecord queryOne(Long guildMemberId, Long uid, String cycleDate, String statDate, GameUsdOperateTypeEnum typeEnum) {
LambdaQueryWrapper<GameUsdBillRecord> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GameUsdBillRecord::getGuildMemberId, guildMemberId);
queryWrapper.eq(GameUsdBillRecord::getUid, uid)
.eq(GameUsdBillRecord::getType, typeEnum.getType())
.eq(GameUsdBillRecord::getCycleDate, cycleDate)
.eq(GameUsdBillRecord::getStatDate, statDate);
return baseMapper.selectOne(queryWrapper, false);
}
/**
* KEY 为 guildMemberId_statDate
* @param guildMemberId
* @param uid
* @param cycleDate
* @param typeEnum
* @return
*/
public Map<String, GameUsdBillRecord> queryStatDateMap(Long guildMemberId, Long uid, String cycleDate, GameUsdOperateTypeEnum typeEnum) {
LambdaQueryWrapper<GameUsdBillRecord> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GameUsdBillRecord::getGuildMemberId, guildMemberId);
queryWrapper.eq(GameUsdBillRecord::getUid, uid)
.eq(GameUsdBillRecord::getType, typeEnum.getType())
.eq(GameUsdBillRecord::getCycleDate, cycleDate);
List<GameUsdBillRecord> gameUsdBillRecords = baseMapper.selectList(queryWrapper);
if (CollectionUtils.isEmpty(gameUsdBillRecords)) {
return Collections.emptyMap();
}
return gameUsdBillRecords.stream().collect(Collectors.toMap(x -> String.format("%s_%s", x.getGuildMemberId(), x.getStatDate()),
x -> x));
}
public List<GameUsdBillRecord> listRechargeUserOrderByUsdDesc(List<Long> rechargeUserUidList, String zoneId){
String cycleDate = CycleTimeUtil.getCurCycleDateByZoneId(zoneId);
return this.baseMapper.listRechargeUserOrderByUsdDesc(rechargeUserUidList, cycleDate, GameUsdOperateTypeEnum.USD_TO_RECHARGE_USER.getType());
}
public Page<GameUsdBillRecordVo> pageBillRecordByType(Long uid, Byte type, Integer page, Integer pageSize) {
Page<GameUsdBillRecordVo> voPage = new Page<>(page, pageSize);
Page<GameUsdBillRecord> poPage = new Page<>(page, pageSize);
LambdaQueryWrapper<GameUsdBillRecord> queryWrapper = new LambdaQueryWrapper<GameUsdBillRecord>()
.eq(Constant.status.valid.equals(type), GameUsdBillRecord::getTargetUid, uid)
.in(Constant.status.valid.equals(type), GameUsdBillRecord::getType,
List.of(GameUsdOperateTypeEnum.RECEIVE_USD.getType(), GameUsdOperateTypeEnum.USD_TO_GUILD_OWNER.getType(),
GameUsdOperateTypeEnum.USD_WITHDRAW_REJECT.getType()))
.eq(Constant.status.invalid.equals(type), GameUsdBillRecord::getUid, uid)
.in(Constant.status.invalid.equals(type), GameUsdBillRecord::getType,
List.of(GameUsdOperateTypeEnum.USD_TO_PLATFORM.getType(), GameUsdOperateTypeEnum.USD_TO_GUILD_OWNER.getType(),
GameUsdOperateTypeEnum.USD_TO_RECHARGE_USER.getType(), GameUsdOperateTypeEnum.OWNER_USD_WITHDRAW.getType(),
GameUsdOperateTypeEnum.MEMBER_USD_WITHDRAW.getType()))
.orderByDesc(GameUsdBillRecord::getId);
this.page(poPage, queryWrapper);
if (org.springframework.util.CollectionUtils.isEmpty(poPage.getRecords())){
return voPage;
}
List<GameUsdBillRecord> recordList = poPage.getRecords();
Set<Long> uidSet = new HashSet<>();
uidSet.add(uid);
for (GameUsdBillRecord record : recordList) {
Long targetUid = Constant.status.valid.equals(type)? record.getUid(): record.getTargetUid();
if (null == targetUid){
continue;
}
uidSet.add(targetUid);
}
Map<Long, Users> usersMap = usersService.getUsersMapByUids(new ArrayList<>(uidSet));
Users user = usersMap.get(uid);
PartitionEnum partitionEnum = PartitionEnum.getByPartitionId(user.getPartitionId());
List<Long> recordIdList = recordList.stream().map(GameUsdBillRecord::getRecordId).distinct().collect(Collectors.toList());
Map<Long, Byte> withdrawRecordMap = !org.springframework.util.CollectionUtils.isEmpty(recordIdList)?
gameUsdWithdrawRecordService.lambdaQuery().in(GameUsdWithdrawRecord::getId, recordIdList)
.list().stream().collect(Collectors.toMap(GameUsdWithdrawRecord::getId, GameUsdWithdrawRecord::getStatus))
:Collections.emptyMap();
List<GameUsdBillRecordVo> voList = new ArrayList<>();
for (GameUsdBillRecord record: recordList){
GameUsdBillRecordVo vo = new GameUsdBillRecordVo();
vo.setNo(record.getNo());
vo.setType(record.getType());
Users me = usersMap.get(uid);
if (null != me){
vo.setMe(usersService.getSimpleUserVo(me));
}
Long targetUid = Constant.status.valid.equals(type)? record.getUid(): record.getTargetUid();
Users u = usersMap.get(targetUid);
if (null != u){
vo.setTarget(usersService.getSimpleUserVo(u));
}
if (Constant.status.valid.equals(type)
&& record.getType().equals(GameUsdOperateTypeEnum.USD_TO_GUILD_OWNER.getType())){
vo.setBeforeUsdNum(record.getBeforeCurrency());
vo.setOperateUsdNum(record.getOperateCurrency());
vo.setAfterUsdNum(record.getAfterCurrency());
} else {
vo.setBeforeUsdNum(record.getBeforeUsd());
vo.setOperateUsdNum(record.getOperateUsd());
vo.setAfterUsdNum(record.getAfterUsd());
}
ZonedDateTime zdt = DateTimeUtil.convertWithZoneId(record.getCreateTime(), partitionEnum.getZoneId());
vo.setCreateTime(zdt.format(DateTimeUtil.datetimeFormatter));
if ((record.getType().equals(GameUsdOperateTypeEnum.OWNER_USD_WITHDRAW.getType())
|| record.getType().equals(GameUsdOperateTypeEnum.MEMBER_USD_WITHDRAW.getType()))
|| record.getType().equals(GameUsdOperateTypeEnum.USD_WITHDRAW_REJECT.getType())
&& null != record.getRecordId()){
vo.setStatus(withdrawRecordMap.getOrDefault(record.getRecordId(), Constant.status.delete));
}
voList.add(vo);
}
voPage.setRecords(voList);
voPage.setCurrent(poPage.getCurrent());
voPage.setSize(poPage.getSize());
return voPage;
}
public Page<GameUsdRechargeUserRecordVo> pageRechargeUserRecordByType(Long uid, Date startDate, Date endDate, Integer page, Integer pageSize) {
Users me = usersService.getNotNullUsersByUid(uid);
PartitionInfo partitionInfo = partitionInfoService.getById(me.getPartitionId());
if (null == partitionInfo || !Constant.ClanMode.GUILD.equals(partitionInfo.getClanMode())
|| !rechargeUserService.isRechargeUser(uid)) {
throw new ServiceException(BusiStatus.FAMILY_PERMISSION_DENIED);
}
Page<GameUsdRechargeUserRecordVo> voPage = new Page<>(page, pageSize);
Page<GameUsdBillRecord> poPage = new Page<>(page, pageSize);
LambdaQueryWrapper<GameUsdBillRecord> queryWrapper = new LambdaQueryWrapper<GameUsdBillRecord>()
.eq(GameUsdBillRecord::getTargetUid, uid)
.eq(GameUsdBillRecord::getType, GameUsdOperateTypeEnum.USD_TO_RECHARGE_USER.getType())
.gt(null != startDate, GameUsdBillRecord::getCreateTime, startDate)
.lt(null != endDate, GameUsdBillRecord::getCreateTime, endDate)
.orderByDesc(GameUsdBillRecord::getId);
this.page(poPage, queryWrapper);
if (org.springframework.util.CollectionUtils.isEmpty(poPage.getRecords())){
return voPage;
}
List<GameUsdBillRecord> recordList = poPage.getRecords();
List<Long> uidList = recordList.stream().map(GameUsdBillRecord::getUid).distinct().collect(Collectors.toList());
Map<Long, Users> usersMap = usersService.getUsersMapByUids(uidList);
List<GameUsdRechargeUserRecordVo> voList = new ArrayList<>();
for (GameUsdBillRecord record: recordList){
GameUsdRechargeUserRecordVo vo = new GameUsdRechargeUserRecordVo();
Users u = usersMap.get(record.getUid());
if (null != u){
vo.setTarget(usersService.getSimpleUserVo(u));
}
vo.setGameUsdNum(record.getOperateUsd());
vo.setGoldNum(record.getOperateCurrency());
vo.setCreateTime(record.getCreateTime());
voList.add(vo);
}
voPage.setRecords(voList);
voPage.setCurrent(poPage.getCurrent());
voPage.setSize(poPage.getSize());
return voPage;
}
public List<GameUsdAccountCycleUsdStatVo> getCycleUsdStatInCycleDateList(Long memberId, List<String> cycleDateList) {
return baseMapper.getCycleUsdStatInCycleDateList(memberId, cycleDateList);
}
public Page<AnchorSalaryBillAdminVo> listPage(BasePageParams pageParams, Long uid, Long receiveUid, Integer salaryOperateType, Long hallId) {
Page<GameUsdBillRecord> ipage = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());
Page<GameUsdBillRecord> anchorSalaryBillPage = this.baseMapper.listPage(ipage, pageParams.getPartitionId(), pageParams.getDateCycle(),
uid, receiveUid, pageParams.getStartTime(), pageParams.getEndTime(), salaryOperateType,hallId);
List<AnchorSalaryBillAdminVo> anchorSalaryBillVos = converAdminBillVo(anchorSalaryBillPage.getRecords());
Page<AnchorSalaryBillAdminVo> page = new Page<>();
page.setTotal(anchorSalaryBillPage.getTotal());
page.setRecords(anchorSalaryBillVos);
fillUserInfo(page.getRecords());
fillReceiveUserInfo(page.getRecords());
return page;
}
public Double sum(Integer partitionId, Long uid, Long receiveUid, String startTime, String endTime, Integer salaryOperateType) {
return baseMapper.sum(partitionId, uid, receiveUid, startTime, endTime, salaryOperateType);
}
public Double sumRechargeUsd(Long receiveUid, String cycleDate, Integer salaryOperateType) {
return baseMapper.sumRechargeUsd(receiveUid, cycleDate, salaryOperateType);
}
private void fillReceiveUserInfo(List<AnchorSalaryBillAdminVo> anchorSalaryBillVos) {
List<Long> uids = anchorSalaryBillVos.stream().map(AnchorSalaryBillAdminVo::getReceiveUid).filter(Objects::nonNull).collect(Collectors.toList());
if (org.springframework.util.CollectionUtils.isEmpty(uids)){
return;
}
Map<Long, Users> cacheByUid = usersService.getUsersMapByUids(uids);
for (AnchorSalaryBillAdminVo anchorSalaryBillVo : anchorSalaryBillVos) {
Users users = cacheByUid.get(anchorSalaryBillVo.getReceiveUid());
if (users!=null){
anchorSalaryBillVo.setReceiveErbano(users.getErbanNo());
anchorSalaryBillVo.setReceiveNick(users.getNick());
}
}
}
private void fillUserInfo(List<AnchorSalaryBillAdminVo> anchorSalaryBillVos) {
List<Long> uids = anchorSalaryBillVos.stream().map(AnchorSalaryBillAdminVo::getUid).collect(Collectors.toList());
Map<Long, Users> cacheByUid = usersService.getUsersMapByUids(uids);
Map<Integer, String> partitionDescMap = partitionInfoService.listAll().stream().collect(Collectors.toMap(PartitionInfo::getId, PartitionInfo::getDesc));
for (AnchorSalaryBillAdminVo anchorSalaryBillVo : anchorSalaryBillVos) {
Users users = cacheByUid.get(anchorSalaryBillVo.getUid());
if (users!=null){
anchorSalaryBillVo.setErbano(users.getErbanNo());
anchorSalaryBillVo.setNick(users.getNick());
anchorSalaryBillVo.setPartitionDesc(partitionDescMap.get(users.getPartitionId()));
}
}
}
private List<AnchorSalaryBillAdminVo> converAdminBillVo(List<GameUsdBillRecord> anchorSalaryBills) {
List<AnchorSalaryBillAdminVo> anchorSalaryBillAdminVos = new ArrayList<>();
for (GameUsdBillRecord anchorSalaryBill : anchorSalaryBills) {
AnchorSalaryBillAdminVo anchorSalaryBillAdminVo = new AnchorSalaryBillAdminVo();
anchorSalaryBillAdminVo.setCreateTime(anchorSalaryBill.getCreateTime());
anchorSalaryBillAdminVo.setCreateTimeStr(DateTimeUtil.convertWithZoneId(anchorSalaryBill.getCreateTime()
, PartitionEnum.getByPartitionId(anchorSalaryBill.getPartitionId()).getZoneId()).format(DateTimeUtil.datetimeFormatter));
anchorSalaryBillAdminVo.setNo(anchorSalaryBill.getNo());
anchorSalaryBillAdminVo.setTradeUsb(anchorSalaryBill.getOperateUsd().doubleValue());
anchorSalaryBillAdminVo.setGold(null != anchorSalaryBill.getOperateCurrency()? anchorSalaryBill.getOperateCurrency().longValue(): 0L);
anchorSalaryBillAdminVo.setUid(anchorSalaryBill.getUid());
anchorSalaryBillAdminVo.setReceiveUid(anchorSalaryBill.getTargetUid());
anchorSalaryBillAdminVo.setBeforeUsb(anchorSalaryBill.getBeforeUsd().doubleValue());
anchorSalaryBillAdminVo.setAfterUsb(anchorSalaryBill.getAfterUsd().doubleValue());
anchorSalaryBillAdminVo.setAfterDiamond(null != anchorSalaryBill.getAfterCurrency()? anchorSalaryBill.getAfterCurrency().doubleValue(): 0d);
anchorSalaryBillAdminVo.setExDiamond(null != anchorSalaryBill.getOperateCurrency()? anchorSalaryBill.getOperateCurrency().doubleValue(): 0d);
anchorSalaryBillAdminVos.add(anchorSalaryBillAdminVo);
}
return anchorSalaryBillAdminVos;
}
public Page<AnchorSalaryBillAdminVo> anchorSummary(Page<AnchorSalaryBillAdminVo> page, String dateCycle, Long uid, Integer hallId, Integer partitionId) {
return baseMapper.anchorSummary(page, dateCycle, uid, hallId, partitionId);
}
}

View File

@@ -0,0 +1,293 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.constant.guild.GuildConstant;
import com.accompany.business.constant.guildgame.GameUsdOperateTypeEnum;
import com.accompany.business.model.UserPurse;
import com.accompany.business.model.guild.GuildMember;
import com.accompany.business.model.guildgame.GameDiamondStatDay;
import com.accompany.business.model.guildgame.GameUsdBillRecord;
import com.accompany.business.model.guildgame.GameUsdProd;
import com.accompany.business.model.guildgame.GameUsdWithdrawRecord;
import com.accompany.business.service.SendSysMsgService;
import com.accompany.business.service.guild.GuildMemberService;
import com.accompany.business.service.purse.UserPurseService;
import com.accompany.business.service.record.BillRecordService;
import com.accompany.business.service.user.UsersService;
import com.accompany.business.vo.guildgame.GameUsdOperateBillRecordVo;
import com.accompany.business.vo.guildgame.GameUsdProdChannelVo;
import com.accompany.common.config.SystemConfig;
import com.accompany.common.constant.AppEnum;
import com.accompany.common.redis.RedisKey;
import com.accompany.common.result.BusiResult;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.DateTimeUtil;
import com.accompany.common.utils.EnvComponent;
import com.accompany.common.utils.UUIDUtil;
import com.accompany.core.enumeration.BillObjTypeEnum;
import com.accompany.core.enumeration.CurrencyEnum;
import com.accompany.core.enumeration.I18nAlertEnum;
import com.accompany.core.enumeration.PartitionEnum;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.model.Users;
import com.accompany.core.util.I18NMessageSourceUtil;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import static com.accompany.core.enumeration.BillObjTypeEnum.GAME_RECE_USD_IN;
@Service
public class GameUsdOperateService {
@Autowired
private GameDiamondStatDayService gameDiamondStatDayService;
@Autowired
private GuildMemberService guildMemberService;
@Autowired
private UsersService usersService;
@Autowired
private UserPurseService userPurseService;
@Autowired
private RedissonClient redissonClient;
@Autowired
private GameUsdBillRecordService gameUsdBillRecordService;
@Autowired
private EnvComponent envComponent;
@Autowired
private GameUsdToRechargeUserLimitService gameUsdToRechargeUserLimitService;
@Autowired
private BillRecordService billRecordService;
@Autowired
private GameUsdWithdrawBizService gameUsdWithdrawBizService;
@Autowired
private GameUsdProdService gameUsdProdService;
@Autowired
private SendSysMsgService sendSysMsgService;
public BusiResult receiveGameUsd(Long uid, Long guildMemberId, String statDate, Double usd) throws InterruptedException {
String lockKey = RedisKey.game_usd_recv_lock.getKey(guildMemberId.toString(), statDate);
boolean locked = false;
RLock lock = redissonClient.getLock(lockKey);
try {
locked = lock.tryLock(5, TimeUnit.SECONDS);
if (!locked) {
throw new ServiceException(BusiStatus.SERVERBUSY);
}
GuildMember guildMember = guildMemberService.getById(guildMemberId);
if (guildMember == null || !guildMember.getEnable() || !guildMember.getUid().equals(uid)) {
throw new ServiceException(BusiStatus.HALL_PERMISSION_DENIED);
}
Users users = usersService.getUsersByUid(uid);
Integer partitionId = users.getPartitionId();
PartitionEnum partitionEnum = PartitionEnum.getByPartitionId(partitionId);
Date time = new Date();
ZonedDateTime nowZonedDateTime = DateTimeUtil.convertWithZoneId(time, partitionEnum.getZoneId());
if (nowZonedDateTime.format(DateTimeUtil.dateFormatter).equals(statDate)) {
throw new ServiceException(BusiStatus.GAME_USD_CURRENT_DAY_RECEIVE_LIMIT);
}
ZonedDateTime thirtyDaysAgoInZone = nowZonedDateTime.minusDays(30);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate localDate = LocalDate.parse(statDate, formatter);
ZonedDateTime statTimeInZone = localDate.atStartOfDay(ZoneId.of(partitionEnum.getZoneId()));
boolean expire = statTimeInZone.isBefore(thirtyDaysAgoInZone);
if (expire) {
throw new ServiceException(BusiStatus.GAME_USD_RECV_EXPIRE);
}
String cycleDate = statTimeInZone.withDayOfMonth(1).format(DateTimeUtil.dateFormatter);
GameDiamondStatDay gameDiamondStatDay = gameDiamondStatDayService.queryByGuildMemberIdAndStatDate(guildMemberId, cycleDate, statDate);
if (gameDiamondStatDay == null) {
throw new ServiceException(BusiStatus.INVALID_REQUEST);
}
if (gameDiamondStatDay.getReceiveStatus() == 1) {
throw new ServiceException(BusiStatus.GAME_USD_RECV_EXIST);
}
gameDiamondStatDay.setReceiveStatus((byte)1);
gameDiamondStatDay.setUpdateTime(time);
gameDiamondStatDayService.updateById(gameDiamondStatDay);
UserPurse before = userPurseService.addGameUsd(uid, BigDecimal.valueOf(usd), GAME_RECE_USD_IN);
gameUsdBillRecordService.insert(UUIDUtil.get(), partitionId, guildMemberId, guildMember.getGuildId(), uid,
guildMemberId, uid, GameUsdOperateTypeEnum.RECEIVE_USD, before, before, BigDecimal.valueOf(usd), null,
gameDiamondStatDay.getId(), null, time);
} finally {
if (locked) {
lock.unlock();
}
}
return BusiResult.success();
}
@Transactional(rollbackFor = Exception.class)
public GameUsdOperateBillRecordVo operateUsd(Long uid, Long targetUid, Integer type, BigDecimal gameUsdNum, String accountType) {
GuildMember guildMember = guildMemberService.getVaildGuildMemberByUid(uid);
if (null == guildMember) {
throw new ServiceException(BusiStatus.FAMILY_PERMISSION_DENIED);
}
Optional<GameUsdOperateTypeEnum> typeEnumOptional = Arrays.stream(GameUsdOperateTypeEnum.values()).filter(operateType-> StringUtils.isNotBlank(operateType.getTabKey()))
.filter(operateType->operateType.getType() == type).findFirst();
if (typeEnumOptional.isEmpty()){
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
GameUsdOperateTypeEnum typeEnum = typeEnumOptional.get();
if (!typeEnum.getRoleTypeSet().contains(guildMember.getRoleType())){
throw new ServiceException(BusiStatus.FAMILY_PERMISSION_DENIED);
}
Users u = usersService.getNotNullUsersByUid(uid);
PartitionEnum partitionEnum = PartitionEnum.getByPartitionId(u.getPartitionId());
if ((GameUsdOperateTypeEnum.OWNER_USD_WITHDRAW.equals(typeEnum) || GameUsdOperateTypeEnum.MEMBER_USD_WITHDRAW.equals(typeEnum))
&& !envComponent.getDevOrNativeEnv()){
ZonedDateTime now = ZonedDateTime.now(ZoneId.of(partitionEnum.getZoneId()));
Integer dayOfMonth = now.getDayOfMonth();
if (null!= typeEnum.getDayOfMonthSet()
&& !typeEnum.getDayOfMonthSet().contains(dayOfMonth)){
throw new ServiceException(BusiStatus.GUILD_USD_WITHDRAW_NOT_IN_TIME);
}
}
GameUsdProdChannelVo channelVo = this.buildProdChannelByType(guildMember.getPartitionId(), typeEnum);
Optional<GameUsdProd> prodOptional = channelVo.getProdList().stream().filter(prod->prod.getGameUsdNum().equals(gameUsdNum)).findFirst();
if (prodOptional.isEmpty() && !typeEnum.isCanCustom()) {
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
GameUsdProd prod = prodOptional.orElseGet(()->new GameUsdProd(typeEnum, gameUsdNum, guildMember.getPartitionId()));
UserPurse userPurse = userPurseService.queryUserPurse(uid);
BigDecimal ownGameUsdNum = BigDecimal.valueOf(userPurse.getGameUsd());
if (prod.getGameUsdNum().compareTo(ownGameUsdNum) > 0) {
throw new ServiceException(BusiStatus.NOT_ENOUGH_GUILD_USD);
}
//代储校验
GuildMember targetMember = null;
if (GameUsdOperateTypeEnum.USD_TO_PLATFORM.equals(typeEnum)){
targetMember = guildMember;
} else if (GameUsdOperateTypeEnum.USD_TO_GUILD_OWNER.equals(typeEnum)) {
if (null == targetUid){
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
targetMember = guildMemberService.getVaildGuildMemberByUid(targetUid);
if (null == targetMember || !GuildConstant.RoleType.OWNER.equals(targetMember.getRoleType())
|| !guildMember.getGuildId().equals(targetMember.getGuildId())) {
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
} else if (GameUsdOperateTypeEnum.USD_TO_RECHARGE_USER.equals(typeEnum)) {
gameUsdToRechargeUserLimitService.valid(guildMember, targetUid, gameUsdNum);
}
Long finalTargetUid = targetUid;
UserPurse before = userPurseService.subGameUsd(uid, gameUsdNum, typeEnum.getOutBillObjType(), BusiStatus.NOT_ENOUGH_GUILD_USD,
(up)-> billRecordService.insertGeneralBillRecord(uid, finalTargetUid, typeEnum.getOutBillObjType(), gameUsdNum.doubleValue(), up));
UserPurse after = null;
BigDecimal currencyNum = null;
if (null != typeEnum.getInputCurrency()){
if (GameUsdOperateTypeEnum.USD_TO_PLATFORM.equals(typeEnum)){
targetUid = uid;
}
currencyNum = prod.getCurrencyNum().add(prod.getExtraCurrencyNum());
// todo
double currencyNumDouble = currencyNum.doubleValue();
after = CurrencyEnum.GAME_USD.equals(typeEnum.getInputCurrency())?
userPurseService.addGameUsd(targetUid, currencyNumDouble, typeEnum.getInBillObjType(),
(up) -> billRecordService.insertGeneralBillRecord(up.getUid(), uid, typeEnum.getInBillObjType(), currencyNumDouble, up)):
userPurseService.addDiamond(targetUid, currencyNumDouble, typeEnum.getInBillObjType(),
(up) -> billRecordService.insertGeneralBillRecord(up.getUid(), uid, typeEnum.getInBillObjType(), currencyNumDouble, up));
}
Long recordId = null;
if (GameUsdOperateTypeEnum.OWNER_USD_WITHDRAW.equals(typeEnum) || GameUsdOperateTypeEnum.MEMBER_USD_WITHDRAW.equals(typeEnum)) {
GameUsdWithdrawRecord record = gameUsdWithdrawBizService.insertRecord(guildMember.getPartitionId(), guildMember.getGuildId(), guildMember.getUid(), gameUsdNum, accountType);
recordId = record.getId();
}
String objId = UUIDUtil.get();
GameUsdBillRecord billRecord = gameUsdBillRecordService.insert(objId, guildMember.getPartitionId(), guildMember.getId(), guildMember.getGuildId(), uid,
null != targetMember? targetMember.getId(): null, targetUid, typeEnum, before, after, gameUsdNum, currencyNum, recordId, null, null);
if (GameUsdOperateTypeEnum.USD_TO_GUILD_OWNER.equals(typeEnum) || GameUsdOperateTypeEnum.USD_TO_RECHARGE_USER.equals(typeEnum)) {
//小秘书
String content = I18NMessageSourceUtil.getMessage(I18nAlertEnum.GUILD_USD_TO_RECHARGE_USER_TIP, new Object[]{u.getNick(), u.getErbanNo(), gameUsdNum.toPlainString()}, targetUid);
String skipUrl = String.format("%s://%s%s", envComponent.getDevOrNativeEnv()? "http": "https", AppEnum.getCurApp().getH5Domain(),
GameUsdOperateTypeEnum.USD_TO_GUILD_OWNER.equals(typeEnum)?
GuildConstant.SkipUrl.BILL_RECORD_URL: GuildConstant.SkipUrl.RECHARGE_USER_RECORD_URL);
sendSysMsgService.sendPersonTextMsgWithSkipUrl(SystemConfig.secretaryUid, targetUid, content, skipUrl);
}
return buildBillRecordVo(billRecord);
}
private GameUsdProdChannelVo buildProdChannelByType(Integer partitionId, GameUsdOperateTypeEnum typeEnum){
GameUsdProdChannelVo prodPanel = new GameUsdProdChannelVo();
prodPanel.setType(typeEnum.getType());
prodPanel.setCanCustom(typeEnum.isCanCustom());
prodPanel.setRatio(typeEnum.getRatio());
List<GameUsdProd> prodList = gameUsdProdService.listVaildProdByType(partitionId, typeEnum.getType());
prodPanel.setProdList(prodList);
return prodPanel;
}
private GameUsdOperateBillRecordVo buildBillRecordVo(GameUsdBillRecord billRecord) {
GameUsdOperateBillRecordVo vo = new GameUsdOperateBillRecordVo();
vo.setNo(billRecord.getNo());
vo.setMe(usersService.getSimpleUserByUid(billRecord.getUid()));
if (null != billRecord.getTargetUid()){
vo.setTarget(usersService.getSimpleUserByUid(billRecord.getTargetUid()));
}
vo.setGameUsdNum(billRecord.getOperateUsd());
vo.setCurrencyNum(billRecord.getOperateCurrency());
vo.setCreateTime(billRecord.getCreateTime());
return vo;
}
public void settlementGold(Integer guildId, Long uid, BigDecimal goldNum) {
GuildMember guildMember = guildMemberService.getVaildGuildMemberByUid(uid);
if (null == guildMember || !GuildConstant.RoleType.OWNER.equals(guildMember.getRoleType())
|| !guildMember.getGuildId().equals(guildId)) {
throw new ServiceException(BusiStatus.FAMILY_PERMISSION_DENIED);
}
userPurseService.addGold(uid, goldNum.doubleValue(), BillObjTypeEnum.GUILD_SETTLEMENT_GOLD_IN);
}
public void withdrawReject(Integer guildId, Long uid, BigDecimal gameUsdNum) {
GuildMember guildMember = guildMemberService.lambdaQuery()
.eq(GuildMember::getUid, uid)
.eq(GuildMember::getGuildId, guildId)
.orderByDesc(GuildMember::getUpdateTime)
.last("limit 1")
.one();
if (null == guildMember) {
throw new ServiceException(BusiStatus.FAMILY_PERMISSION_DENIED);
}
UserPurse before = userPurseService.addGameUsd(uid, gameUsdNum, BillObjTypeEnum.GUILD_USD_TO_PLATFORM_IN);
String objId = UUIDUtil.get();
gameUsdBillRecordService.insert(objId, guildMember.getPartitionId(), null, guildId, null, guildMember.getId(), uid, GameUsdOperateTypeEnum.USD_WITHDRAW_REJECT,
null, before, gameUsdNum, null, null, null, null);
}
}

View File

@@ -0,0 +1,38 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.model.guildgame.GameUsdProd;
import com.accompany.business.mybatismapper.guildgame.GameUsdProdMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 服务实现类
*
* @author
* @since 2025-07-30
*/
@Service
public class GameUsdProdService extends ServiceImpl<GameUsdProdMapper, GameUsdProd> {
public List<GameUsdProd> listVaildProdByType(Integer partitionId, Integer type) {
return lambdaQuery()
.eq(GameUsdProd::getPartitionId, partitionId)
.eq(GameUsdProd::getType, type)
.eq(GameUsdProd::getEnable, Boolean.TRUE)
.list();
}
public Map<Integer, List<GameUsdProd>> mapVaildProdInTypes(Integer partitionId, List<Integer> types) {
return lambdaQuery()
.eq(GameUsdProd::getPartitionId, partitionId)
.in(GameUsdProd::getType, types)
.eq(GameUsdProd::getEnable, Boolean.TRUE)
.list()
.stream().collect(Collectors.groupingBy(GameUsdProd::getType));
}
}

View File

@@ -0,0 +1,283 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.constant.guildgame.GameUsdOperateTypeEnum;
import com.accompany.business.model.UserPurse;
import com.accompany.business.model.guild.Guild;
import com.accompany.business.model.guild.GuildMember;
import com.accompany.business.model.guildgame.GameDiamondSalary;
import com.accompany.business.model.guildgame.GameDiamondStatDay;
import com.accompany.business.model.guildgame.GameUsdBillRecord;
import com.accompany.business.model.guildgame.GameUsdProd;
import com.accompany.business.service.guild.GuildMemberService;
import com.accompany.business.service.guild.GuildService;
import com.accompany.business.service.purse.UserPurseService;
import com.accompany.business.service.user.UsersService;
import com.accompany.business.vo.SimpleUserVo;
import com.accompany.business.vo.guildgame.*;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.DateTimeUtil;
import com.accompany.common.utils.StringUtils;
import com.accompany.core.enumeration.PartitionEnum;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.model.PartitionInfo;
import com.accompany.core.model.Users;
import com.accompany.core.service.partition.PartitionInfoService;
import com.accompany.payment.service.RechargeUserService;
import com.accompany.payment.vo.RechargeUserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j
@Service
public class GameUsdService {
@Autowired
private GameDiamondStatDayService gameDiamondStatDayService;
@Autowired
private GuildMemberService guildMemberService;
@Autowired
private UsersService usersService;
@Autowired
private UserPurseService userPurseService;
@Autowired
private GameDiamondSalaryService gameDiamondSalaryService;
@Autowired
private GameUsdWithdrawAccountService gameUsdWithdrawAccountService;
@Autowired
private GuildService guildService;
@Autowired
private GameUsdProdService guildUsdProdService;
@Autowired
private RechargeUserService rechargeUserService;
@Resource(name = "bizExecutor")
private ThreadPoolExecutor bizExecutor;
@Autowired
private GameUsdBillRecordService guildUsdBillRecordService;
@Autowired
private PartitionInfoService partitionInfoService;
@Autowired
private GameUsdToRechargeUserLimitService guildUsdToRechargeUserLimitService;
public GuildGameSalaryVo getGameUsdInfo(Long uid, String monthDate) {
GuildMember guildMember = guildMemberService.getVaildGuildMemberByUid(uid);
if (guildMember == null) {
throw new ServiceException(BusiStatus.HALL_PERMISSION_DENIED);
}
Users users = usersService.getUsersByUid(uid);
if (users == null) {
throw new ServiceException(BusiStatus.USERNOTEXISTS);
}
Integer partitionId = users.getPartitionId();
PartitionEnum partitionEnum = PartitionEnum.getByPartitionId(partitionId);
ZonedDateTime nowZoneDateTime = DateTimeUtil.convertWithZoneId(new Date(), partitionEnum.getZoneId());
if (StringUtils.isEmpty(monthDate)) {
ZonedDateTime zonedDateTime = nowZoneDateTime.withDayOfMonth(1);
monthDate = zonedDateTime.format(DateTimeUtil.dateFormatter);
} else {
monthDate = String.format("%s-01", monthDate);
}
GuildGameSalaryVo guildGameSalaryVo = new GuildGameSalaryVo();
guildGameSalaryVo.fillUserInfo(users);
UserPurse userPurse = userPurseService.queryUserPurse(uid);
guildGameSalaryVo.setGameSalary(BigDecimal.valueOf(userPurse.getGameUsd()));
guildGameSalaryVo.setGuildMemberId(guildMember.getId());
GuildGameDayVo guildGameDayVo = new GuildGameDayVo();
guildGameSalaryVo.setGameDayVo(guildGameDayVo);
guildGameDayVo.setMonthDate(monthDate);
guildGameDayVo.setDayDetailList(this.getGameDayDetailList(guildMember.getId(), monthDate, partitionId, nowZoneDateTime));
guildGameDayVo.setReceivedSalary(guildGameDayVo.getDayDetailList().stream()
.filter(x -> x.getReceiveStatus() == 1)
.map(GuildGameDayDetailVo::getDaySalary)
.reduce(BigDecimal.ZERO, BigDecimal::add));
guildGameDayVo.setTotalPlayGameNum(guildGameDayVo.getDayDetailList().stream()
.mapToInt(GuildGameDayDetailVo::getPlayGameNum)
.sum());
return guildGameSalaryVo;
}
private List<GuildGameDayDetailVo> getGameDayDetailList(Long guildMemberId, String monthDate, Integer partitionId, ZonedDateTime nowZoneDateTime) {
List<GuildGameDayDetailVo> resultList = new ArrayList<>();
List<GameDiamondStatDay> guildGameMonthList = gameDiamondStatDayService.getGuildGameMonthList(guildMemberId, monthDate);
if (CollectionUtils.isEmpty(guildGameMonthList)) {
return resultList;
}
TreeMap<Integer, GameDiamondSalary> salaryMap = gameDiamondSalaryService.getDiamondSalaryMap(partitionId);
PartitionEnum partitionEnum = PartitionEnum.getByPartitionId(partitionId);
ZonedDateTime thirtyDaysAgoInZone = nowZoneDateTime.minusDays(30);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
guildGameMonthList.forEach(gameDiamondStatDay -> {
GuildGameDayDetailVo guildGameDayDetailVo = GuildGameDayDetailVo.builder()
.statDate(gameDiamondStatDay.getStatDate())
.playGameNum(gameDiamondStatDay.getPlayGameNum())
.daySalary(salaryMap.headMap(gameDiamondStatDay.getPlayGameNum(), true).lastEntry().getValue().getBaseSalary())
.build();
LocalDate localDate = LocalDate.parse(gameDiamondStatDay.getStatDate(), formatter);
ZonedDateTime statTimeInZone = localDate.atStartOfDay(ZoneId.of(partitionEnum.getZoneId()));
boolean expire = statTimeInZone.isBefore(thirtyDaysAgoInZone);
if (nowZoneDateTime.format(DateTimeUtil.dateFormatter).equalsIgnoreCase(gameDiamondStatDay.getStatDate())) {
guildGameDayDetailVo.setReceiveStatus((byte) 4);
} else {
guildGameDayDetailVo.setReceiveStatus(expire ? 2 : gameDiamondStatDay.getReceiveStatus());
}
resultList.add(guildGameDayDetailVo);
});
return resultList;
}
public GameUsdOperateTabVo getUsdOperateTabVo(Long uid) {
GuildMember guildMember = guildMemberService.getVaildGuildMemberByUid(uid);
if (null == guildMember){
throw new ServiceException(BusiStatus.FAMILY_PERMISSION_DENIED);
}
Guild guild = guildService.getVaildGuildById(guildMember.getGuildId());
if (null == guild){
throw new ServiceException(BusiStatus.FAMILY_PERMISSION_DENIED);
}
GameUsdOperateTabVo vo = new GameUsdOperateTabVo();
vo.setGuildMemberId(guildMember.getId());
vo.setGuildId(guild.getId());
vo.setUid(uid);
CountDownLatch cdl = new CountDownLatch(3);
bizExecutor.execute(()->{
try {
SimpleUserVo guildOwner = usersService.getSimpleUserByUid(guild.getOwnerUid());
vo.setGuildOwner(guildOwner);
UserPurse userPurse = userPurseService.queryUserPurse(uid);
vo.setGameUsdNum(userPurse.getGameUsd());
List<GuildMemberGameUsdWithdrawAccountVo> withdrawAccount = gameUsdWithdrawAccountService.listUserAccountVo(uid);
vo.setWithdrawAccountList(withdrawAccount);
} catch (Exception e){
log.error("[getUsdOperateTabVo] guildOwner和userPurse 获取异常", e);
} finally {
cdl.countDown();
}
});
bizExecutor.execute(()->{
try {
String limitTip = guildUsdToRechargeUserLimitService.getLimitTIp(guildMember);
vo.setRechargeUserLimitTip(limitTip);
if (org.apache.commons.lang3.StringUtils.isNotBlank(limitTip)){
return;
}
List<RechargeUserVo> rechargeUserList = listRechargeUser(uid);
vo.setRechargeUserList(rechargeUserList);
} catch (Exception e){
log.error("[getUsdOperateTabVo] rechargeUser 获取异常", e);
} finally {
cdl.countDown();
}
});
bizExecutor.execute(()->{
try {
List<GameUsdProdTabVo> tabVoList = buildTabByRoleType(uid, guildMember.getPartitionId(), guildMember.getRoleType());
vo.setTypeTab(tabVoList);
} catch (Exception e){
log.error("[getUsdOperateTabVo] tabVoList 获取异常", e);
} finally {
cdl.countDown();
}
});
try {
cdl.await(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("[getUsdOperateTabVo] await 超时");
throw new RuntimeException(e);
}
return vo;
}
private List<GameUsdProdTabVo> buildTabByRoleType(Long uid, Integer partitionId, Byte roleType) {
List<GameUsdOperateTypeEnum> typeEnums = Arrays.stream(GameUsdOperateTypeEnum.values()).filter(typeEnum-> Objects.nonNull(typeEnum.getTabKey()))
.filter(typeEnum-> typeEnum.getRoleTypeSet().contains(roleType))
.collect(Collectors.toList());
Map<String, List<GameUsdProdChannelVo>> channelMap = buildProdChannelInTypes(partitionId, typeEnums);
return channelMap.entrySet().stream().map(entry->{
GameUsdProdTabVo tabVo = new GameUsdProdTabVo();
tabVo.setTabKey(entry.getKey());
tabVo.setChannelList(entry.getValue());
return tabVo;
}).sorted(Comparator.comparing(GameUsdProdTabVo::getTabKey).reversed())
.collect(Collectors.toList());
}
public Map<String, List<GameUsdProdChannelVo>> buildProdChannelInTypes(Integer partitionId, List<GameUsdOperateTypeEnum> typeEnums){
List<Integer> types = typeEnums.stream().map(GameUsdOperateTypeEnum::getType).collect(Collectors.toList());
Map<Integer, List<GameUsdProd>> prodMap = guildUsdProdService.mapVaildProdInTypes(partitionId, types);
return typeEnums.stream().filter(typeEnum->prodMap.containsKey(typeEnum.getType()))
.map(typeEnum->{
GameUsdProdChannelVo channelVo = new GameUsdProdChannelVo();
channelVo.setTabKey(typeEnum.getTabKey());
channelVo.setType(typeEnum.getType());
channelVo.setCanCustom(typeEnum.isCanCustom());
channelVo.setRatio(typeEnum.getRatio());
channelVo.setProdList(prodMap.get(typeEnum.getType()));
return channelVo;
}).collect(Collectors.groupingBy(GameUsdProdChannelVo::getTabKey));
}
private List<RechargeUserVo> listRechargeUser(Long uid){
Users u = usersService.getNotNullUsersByUid(uid);
PartitionInfo partitionInfo = partitionInfoService.getById(u.getPartitionId());
if (null == partitionInfo){
return Collections.emptyList();
}
List<RechargeUserVo> rechargeUserVoList = rechargeUserService.listByPartitionIdByGuildTab(u.getPartitionId());
if (org.springframework.util.CollectionUtils.isEmpty(rechargeUserVoList)){
return rechargeUserVoList;
}
List<Long> uidList = rechargeUserVoList.stream().map(RechargeUserVo::getUid).collect(Collectors.toList());
List<GameUsdBillRecord> recordList = guildUsdBillRecordService.listRechargeUserOrderByUsdDesc(uidList, partitionInfo.getZoneId());
if (org.springframework.util.CollectionUtils.isEmpty(recordList)){
return rechargeUserVoList;
}
return rechargeUserVoList.stream().sorted(Comparator.comparing(RechargeUserVo::getStarLevelSeq).reversed())
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,114 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.constant.guild.GuildConstant;
import com.accompany.business.constant.guildgame.GameUsdOperateTypeEnum;
import com.accompany.business.dto.guild.GameUsdToRechargeUserLimitConfigDto;
import com.accompany.business.model.guild.GuildMember;
import com.accompany.business.mybatismapper.guildgame.GameUsdBillRecordMapper;
import com.accompany.common.constant.Constant;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.DateTimeUtil;
import com.accompany.core.enumeration.I18nAlertEnum;
import com.accompany.core.enumeration.PartitionEnum;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.service.SysConfService;
import com.accompany.core.util.I18NMessageSourceUtil;
import com.accompany.payment.service.RechargeUserService;
import com.alibaba.fastjson2.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class GameUsdToRechargeUserLimitService {
@Autowired
private SysConfService sysConfService;
@Autowired
private RechargeUserService rechargeUserService;
@Autowired
private GameUsdBillRecordMapper guildUsdBillRecordMapper;
public String getLimitTIp(GuildMember guildMember) {
GameUsdToRechargeUserLimitConfigDto configDto = getConfig().getByPartitionId(guildMember.getPartitionId());
if (null == configDto){
return null;
}
List<Integer> enableDayOfMonth = GuildConstant.RoleType.OWNER.equals(guildMember.getRoleType())?
configDto.getOwnerEnableDayOfMonth():
configDto.getMemberEnableDayOfMonth();
if (CollectionUtils.isEmpty(enableDayOfMonth)){
return null;
}
PartitionEnum partitionEnum = PartitionEnum.getByPartitionId(guildMember.getPartitionId());
ZonedDateTime zdt = DateTimeUtil.getDateTimeByZoneId(partitionEnum.getZoneId());
if (enableDayOfMonth.contains(zdt.getDayOfMonth())){
return null;
}
String enableDayOfMonthStr = enableDayOfMonth.stream().sorted().map(String::valueOf).collect(Collectors.joining(","));
return I18NMessageSourceUtil.getMessage(I18nAlertEnum.GUILD_USD_TO_RECHARGE_USER_DAY_OF_MONTH_LIMIT, new Object[]{enableDayOfMonthStr}, guildMember.getPartitionId());
}
public void valid(GuildMember guildMember, Long targetUid, BigDecimal guildUsdNum) {
if (null == targetUid || !rechargeUserService.isRechargeUser(targetUid)){
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
//todo numberEveryDayLimit
GameUsdToRechargeUserLimitConfigDto configDto = getConfig().getByPartitionId(guildMember.getPartitionId());
if (null == configDto){
return;
}
List<Integer> enableDayOfMonth = GuildConstant.RoleType.OWNER.equals(guildMember.getRoleType())?
configDto.getOwnerEnableDayOfMonth():
configDto.getMemberEnableDayOfMonth();
if (CollectionUtils.isEmpty(enableDayOfMonth)){
return;
}
PartitionEnum partitionEnum = PartitionEnum.getByPartitionId(guildMember.getPartitionId());
ZonedDateTime zdt = DateTimeUtil.getDateTimeByZoneId(partitionEnum.getZoneId());
if (!enableDayOfMonth.contains(zdt.getDayOfMonth())){
String enableDayOfMonthStr = enableDayOfMonth.stream().sorted().map(String::valueOf).collect(Collectors.joining(","));
String errorMsg = I18NMessageSourceUtil.getMessage(I18nAlertEnum.GUILD_USD_TO_RECHARGE_USER_DAY_OF_MONTH_LIMIT, new Object[]{enableDayOfMonthStr}, guildMember.getPartitionId());
throw new ServiceException(errorMsg);
}
if (null == configDto.getDayNumLimit() || BigDecimal.ZERO.compareTo(configDto.getDayNumLimit()) <= 0){
return;
}
ZonedDateTime todayStartTime = zdt.withHour(0).withMinute(0).withSecond(0).withNano(0);
Date systemStartTime = DateTimeUtil.converLocalDateTimeToDate(todayStartTime.withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime());
String systemStartTimeStr = DateTimeUtil.convertDateTime(systemStartTime);
ZonedDateTime todayEndTime = zdt.withHour(23).withMinute(59).withSecond(59).withNano(999999999);
Date systemEndTime = DateTimeUtil.converLocalDateTimeToDate(todayEndTime.withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime());
String systemEndTimeStr = DateTimeUtil.convertDateTime(systemEndTime);
Double todayNum = guildUsdBillRecordMapper.sum(guildMember.getPartitionId(), guildMember.getUid(), null,
systemStartTimeStr, systemEndTimeStr, GameUsdOperateTypeEnum.USD_TO_RECHARGE_USER.getType());
BigDecimal todayNumB = null == todayNum? BigDecimal.ZERO: BigDecimal.valueOf(todayNum);
BigDecimal judgeNum = todayNumB.add(guildUsdNum);
if (judgeNum.compareTo(configDto.getDayNumLimit()) > 0){
String errorMsg = I18NMessageSourceUtil.getMessage(I18nAlertEnum.GUILD_USD_TO_RECHARGE_USER_DAY_NUM_LIMIT, null, guildMember.getPartitionId());
throw new ServiceException(errorMsg);
}
}
public GameUsdToRechargeUserLimitConfigDto getConfig(){
String configStr = sysConfService.getSysConfValueById(Constant.SysConfId.GAME_USD_TO_RECHARGE_USER_LIMIT);
if (!StringUtils.hasText(configStr)){
throw new ServiceException(BusiStatus.SERVERERROR);
}
return JSON.parseObject(configStr, GameUsdToRechargeUserLimitConfigDto.class);
}
}

View File

@@ -0,0 +1,39 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.model.guildgame.GameUsdWithdrawAccountConfig;
import com.accompany.business.mybatismapper.guildgame.GameUsdWithdrawAccountConfigMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 服务实现类
*
* @author
* @since 2025-07-30
*/
@Service
public class GameUsdWithdrawAccountConfigService extends ServiceImpl<GameUsdWithdrawAccountConfigMapper, GameUsdWithdrawAccountConfig> {
public List<GameUsdWithdrawAccountConfig> listAccountConfig(List<String> accountTypeList,
Integer partitionId){
return lambdaQuery()
.in(GameUsdWithdrawAccountConfig::getAccountType, accountTypeList)
.eq(GameUsdWithdrawAccountConfig::getPartitionId, partitionId)
.eq(GameUsdWithdrawAccountConfig::getEnable, Boolean.TRUE)
.orderByAsc(GameUsdWithdrawAccountConfig::getSeq)
.list();
}
public GameUsdWithdrawAccountConfig getAccountConfig(String accountType,
Integer partitionId,
String country){
return lambdaQuery()
.eq(GameUsdWithdrawAccountConfig::getAccountType, accountType)
.eq(GameUsdWithdrawAccountConfig::getPartitionId, partitionId)
.eq(GameUsdWithdrawAccountConfig::getCountry, country)
.one();
}
}

View File

@@ -0,0 +1,185 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.constant.CountryEnum;
import com.accompany.business.constant.guildgame.GameWithdrawAccountFieldEnum;
import com.accompany.business.constant.guildgame.GameWithdrawAccountTypeEnum;
import com.accompany.business.model.guildgame.GameUsdWithdrawAccount;
import com.accompany.business.model.guildgame.GameUsdWithdrawAccountConfig;
import com.accompany.business.mybatismapper.guildgame.GameUsdWithdrawAccountMapper;
import com.accompany.business.service.user.UsersService;
import com.accompany.business.vo.guildgame.GameUsdWithdrawAccountVo;
import com.accompany.business.vo.guildgame.GuildMemberGameUsdWithdrawAccountVo;
import com.accompany.common.status.BusiStatus;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.model.Users;
import com.accompany.core.util.PartitionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* 服务实现类
*
* @author
* @since 2025-07-30
*/
@Service
public class GameUsdWithdrawAccountService extends ServiceImpl<GameUsdWithdrawAccountMapper, GameUsdWithdrawAccount> {
@Autowired
private UsersService usersService;
@Autowired
private GameUsdWithdrawAccountConfigService configService;
public List<GuildMemberGameUsdWithdrawAccountVo> listUserAccountVo(Long uid) {
Users u = usersService.getNotNullUsersByUid(uid);
List<String> accountTypeList = Arrays.stream(GameWithdrawAccountTypeEnum.values())
.filter(accountType-> PartitionUtil.inPartition(accountType.getPartitionFlag(), u.getPartitionId()))
.map(GameWithdrawAccountTypeEnum::name)
.collect(Collectors.toList());
List<GameUsdWithdrawAccountConfig> accountConfigList = configService.listAccountConfig(accountTypeList, u.getPartitionId());
if (CollectionUtils.isEmpty(accountConfigList)){
return Collections.emptyList();
}
Map<String, List<GameUsdWithdrawAccountConfig>> accountConfigMap = accountConfigList.stream()
.collect(Collectors.groupingBy(GameUsdWithdrawAccountConfig::getAccountType));
Map<String, GameUsdWithdrawAccount> accountMap = lambdaQuery()
.eq(GameUsdWithdrawAccount::getUid, uid)
.in(GameUsdWithdrawAccount::getAccountType, accountTypeList)
.eq(GameUsdWithdrawAccount::getEnable, Boolean.TRUE)
.list().stream().collect(Collectors.toMap(GameUsdWithdrawAccount::getAccountType, a -> a));
return accountConfigMap.keySet().stream()
.map(accountType -> {
GameWithdrawAccountTypeEnum typeEnum = GameWithdrawAccountTypeEnum.valueOf(accountType);
GuildMemberGameUsdWithdrawAccountVo vo = new GuildMemberGameUsdWithdrawAccountVo();
vo.setType(accountType);
vo.setName(typeEnum.getType());
boolean hasBound = accountMap.containsKey(accountType);
vo.setHasBound(hasBound);
if (!hasBound) {
return vo;
}
GameUsdWithdrawAccount account = accountMap.get(accountType);
Optional<GameUsdWithdrawAccountConfig> configOptional = accountConfigMap.get(accountType)
.stream().filter(v -> v.getCountry().equals(account.getAccountCountry())).findFirst();
if (configOptional.isEmpty()) {
return vo;
}
GameUsdWithdrawAccountConfig config = configOptional.get();
vo.setCurrency(config.getCurrency());
vo.setUsdRatio(config.getUsdRatio());
vo.setWithdrawRate(config.getFeeRate());
return vo;
}).toList();
}
public GameUsdWithdrawAccountVo getAccountByType(Long uid, String type) {
Users u = usersService.getNotNullUsersByUid(uid);
GameWithdrawAccountTypeEnum typeEnum = GameWithdrawAccountTypeEnum.valueOf(type);
JSONObject accountFields = new JSONObject();
for (GameWithdrawAccountFieldEnum fieldEnum : typeEnum.getFieldList()) {
accountFields.put(fieldEnum.getFieldName(), "");
}
GameUsdWithdrawAccountVo accountVo = new GameUsdWithdrawAccountVo();
accountVo.setUid(uid);
accountVo.setType(typeEnum.name());
GameUsdWithdrawAccount account = lambdaQuery().eq(GameUsdWithdrawAccount::getUid, uid)
.eq(GameUsdWithdrawAccount::getAccountType, typeEnum.name())
.eq(GameUsdWithdrawAccount::getEnable, Boolean.TRUE)
.one();
if (null != account){
accountVo.setCountry(account.getAccountCountry());
JSONObject userFields = JSONObject.parseObject(account.getAccountFields());
accountFields.putAll(userFields);
}
List<GameUsdWithdrawAccountConfig> countryConfigList = configService.listAccountConfig(List.of(typeEnum.name()), u.getPartitionId());
if (null != accountVo.getCountry() && countryConfigList.stream()
.noneMatch(config -> config.getCountry().equals(accountVo.getCountry()))){
throw new ServiceException(BusiStatus.GUILD_USD_WITHDRAW_ACCOUNT_TYPE_ERROR);
}
accountVo.setCountryOptionalList(countryConfigList.stream().map(config -> {
GameUsdWithdrawAccountVo.Country country = new GameUsdWithdrawAccountVo.Country();
country.setValue(config.getCountry());
CountryEnum countryEnum = CountryEnum.valueOf(config.getCountry());
country.setName(countryEnum.getName());
country.setCurrency(config.getCurrency());
country.setUsdRatio(config.getUsdRatio());
country.setFeeRate(config.getFeeRate());
country.setSeq(config.getSeq());
return country;
}).sorted(Comparator.comparing(GameUsdWithdrawAccountVo.Country::getSeq))
.toList());
accountVo.setFields(accountFields);
return accountVo;
}
public void bound(GameUsdWithdrawAccountVo account) {
GameWithdrawAccountTypeEnum typeEnum = GameWithdrawAccountTypeEnum.valueOf(account.getType());
GameUsdWithdrawAccount db = lambdaQuery().eq(GameUsdWithdrawAccount::getUid, account.getUid())
.eq(GameUsdWithdrawAccount::getAccountType, typeEnum.name())
.one();
if (null != db && db.getEnable()){
throw new ServiceException(BusiStatus.PARAMERROR);
}
if (null == db){
db = new GameUsdWithdrawAccount();
db.setUid(account.getUid());
db.setAccountType(typeEnum.name());
db.setAccountCountry(account.getFields().getString("country"));
db.setEnable(Boolean.TRUE);
db.setAccountFields(account.getFields().toJSONString());
db.setCreateTime(new Date());
save(db);
return;
}
lambdaUpdate().set(GameUsdWithdrawAccount::getEnable, Boolean.TRUE)
.set(GameUsdWithdrawAccount::getAccountCountry, account.getFields().getString("country"))
.set(GameUsdWithdrawAccount::getAccountFields, account.getFields().toJSONString())
.set(GameUsdWithdrawAccount::getCreateTime, new Date())
.eq(GameUsdWithdrawAccount::getUid, db.getUid())
.eq(GameUsdWithdrawAccount::getAccountType, typeEnum.name())
.update();
}
public void unbound(GameUsdWithdrawAccountVo account) {
GameWithdrawAccountTypeEnum typeEnum = GameWithdrawAccountTypeEnum.valueOf(account.getType());
lambdaUpdate().set(GameUsdWithdrawAccount::getEnable, Boolean.FALSE)
.eq(GameUsdWithdrawAccount::getUid, account.getUid())
.eq(GameUsdWithdrawAccount::getAccountType, typeEnum.name())
.update();
}
}

View File

@@ -0,0 +1,42 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.model.guildgame.GameUsdWithdrawAccount;
import com.accompany.business.model.guildgame.GameUsdWithdrawAccountConfig;
import com.accompany.business.model.guildgame.GameUsdWithdrawRecord;
import com.accompany.business.mybatismapper.guildgame.GameUsdWithdrawRecordMapper;
import com.accompany.common.status.BusiStatus;
import com.accompany.core.exception.ServiceException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
@Service
public class GameUsdWithdrawBizService extends ServiceImpl<GameUsdWithdrawRecordMapper, GameUsdWithdrawRecord> {
@Autowired
private GameUsdWithdrawRecordService recordService;
@Autowired
private GameUsdWithdrawAccountConfigService accountConfigService;
@Autowired
private GameUsdWithdrawAccountService accountService;
public GameUsdWithdrawRecord insertRecord(Integer partitionId, Integer guildId, Long uid, BigDecimal guildUsdNum, String accountType) {
GameUsdWithdrawAccount account = accountService.lambdaQuery()
.eq(GameUsdWithdrawAccount::getUid, uid)
.eq(GameUsdWithdrawAccount::getAccountType, accountType)
.eq(GameUsdWithdrawAccount::getEnable, Boolean.TRUE)
.one();
if (null == account){
throw new ServiceException(BusiStatus.PARAMERROR);
}
GameUsdWithdrawAccountConfig config = accountConfigService.getAccountConfig(accountType, partitionId, account.getAccountCountry());
if (null == config || !Boolean.TRUE.equals(config.getEnable())){
throw new ServiceException(BusiStatus.GUILD_USD_WITHDRAW_ACCOUNT_TYPE_ERROR);
}
return recordService.insertRecord(partitionId, guildId, uid, guildUsdNum, account);
}
}

View File

@@ -0,0 +1,68 @@
package com.accompany.business.service.guildgame;
import com.accompany.business.model.guildgame.GameUsdWithdrawAccount;
import com.accompany.business.model.guildgame.GameUsdWithdrawAccountConfig;
import com.accompany.business.model.guildgame.GameUsdWithdrawRecord;
import com.accompany.business.mybatismapper.guildgame.GameUsdWithdrawRecordMapper;
import com.accompany.common.constant.Constant;
import com.accompany.common.status.BusiStatus;
import com.accompany.core.exception.ServiceException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
/**
* 服务实现类
*
* @author
* @since 2025-07-30
*/
@Service
public class GameUsdWithdrawRecordService extends ServiceImpl<GameUsdWithdrawRecordMapper, GameUsdWithdrawRecord> {
@Autowired
private GameUsdWithdrawAccountConfigService guildUsdWithdrawAccountConfigService;
public GameUsdWithdrawRecord insertRecord(Integer partitionId, Integer guildId, Long uid, BigDecimal guildUsdNum,
GameUsdWithdrawAccount account) {
Date now = new Date();
GameUsdWithdrawAccountConfig fee = guildUsdWithdrawAccountConfigService.getAccountConfig(account.getAccountType(), partitionId, account.getAccountCountry());
if (null == fee){
throw new ServiceException(BusiStatus.SERVERBUSY);
}
BigDecimal rate = BigDecimal.ONE.subtract(fee.getFeeRate());
BigDecimal usdRate = fee.getUsdRatio();
BigDecimal currencyNum = guildUsdNum.multiply(usdRate).setScale(2, RoundingMode.DOWN);
BigDecimal withdrawNum = guildUsdNum.multiply(rate).multiply(usdRate).setScale(2, RoundingMode.DOWN);
GameUsdWithdrawRecord record = new GameUsdWithdrawRecord();
record.setPartitionId(partitionId);
record.setGuildId(guildId);
record.setUid(uid);
record.setGameUsdNum(guildUsdNum);
record.setStatus(Constant.status.delete);
record.setCreateTime(now);
record.setUpdateTime(now);
record.setRemark(null);
record.setOperator(null);
record.setAccountType(account.getAccountType());
record.setAccountCountry(account.getAccountCountry());
record.setAccountInfos(account.getAccountFields());
record.setCurrency(fee.getCurrency());
record.setCurrencyNum(currencyNum);
record.setWithdrawRate(fee.getFeeRate());
record.setWithdrawNum(withdrawNum);
save(record);
return record;
}
}

View File

@@ -0,0 +1,62 @@
package com.accompany.business.service.guildgame.impl;
import com.accompany.business.constant.guildgame.GameTimeUtil;
import com.accompany.business.model.guildgame.GameDiamondStatDay;
import com.accompany.business.mybatismapper.guildgame.GameDiamondStatDayMapper;
import com.accompany.business.service.guildgame.GameDiamondStatDayService;
import com.accompany.common.utils.DateTimeUtil;
import com.accompany.core.enumeration.PartitionEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;
/**
* 公会钻石流水统计按天 服务实现类
*
* @author
* @since 2025-07-30
*/
@Service
public class GameDiamondStatDayServiceImpl extends ServiceImpl<GameDiamondStatDayMapper, GameDiamondStatDay> implements GameDiamondStatDayService {
@Override
public Integer addGameDiamondStatDay(Long uid, Long guildMemberId, Date dataDate, Integer partitionId,
Integer guildId, Integer playGameNum, BigDecimal diamondNum) {
ZonedDateTime zonedDateTime = DateTimeUtil.convertWithZoneId(dataDate, PartitionEnum.getByPartitionId(partitionId).getZoneId());
String statDate = GameTimeUtil.getStatDate(zonedDateTime);
String cycleDate = GameTimeUtil.getCycleDate(zonedDateTime);;
return baseMapper.addGameDiamondStatDay(uid, guildMemberId, cycleDate, statDate, partitionId, guildId, playGameNum, diamondNum, dataDate);
}
@Override
public List<GameDiamondStatDay> getGuildGameMonthList(Long guildMemberId, String cycleDate) {
LambdaQueryWrapper<GameDiamondStatDay> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GameDiamondStatDay::getGuildMemberId, guildMemberId);
queryWrapper.eq(GameDiamondStatDay::getCycleDate, cycleDate);
return baseMapper.selectList(queryWrapper);
}
@Override
public List<GameDiamondStatDay> queryByGuildMemberIdAndCycleDate(Long guildMemberId, String cycleDate) {
LambdaQueryWrapper<GameDiamondStatDay> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GameDiamondStatDay::getGuildMemberId, guildMemberId);
queryWrapper.eq(GameDiamondStatDay::getCycleDate, cycleDate);
queryWrapper.orderByDesc(GameDiamondStatDay::getStatDate);
return baseMapper.selectList(queryWrapper);
}
@Override
public GameDiamondStatDay queryByGuildMemberIdAndStatDate(Long guildMemberId, String cycleDate, String statDate) {
LambdaQueryWrapper<GameDiamondStatDay> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GameDiamondStatDay::getGuildMemberId, guildMemberId);
queryWrapper.eq(GameDiamondStatDay::getCycleDate, cycleDate);
queryWrapper.eq(GameDiamondStatDay::getStatDate, statDate);
return baseMapper.selectOne(queryWrapper, false);
}
}

View File

@@ -100,6 +100,7 @@ public class UserPurseService extends ServiceImpl<UserPurseMapper,UserPurse> {
userPurse.setCrystals(0D);
userPurse.setGolds(0D);
userPurse.setGuildUsd(0D);
userPurse.setGameUsd(0D);
userPurse.setFirstCharge(true);
userPurse.setUpdateTime(new Date());
save(userPurse);
@@ -373,6 +374,74 @@ public class UserPurseService extends ServiceImpl<UserPurseMapper,UserPurse> {
return after;
}
public UserPurse addGameUsd(Long uid, BigDecimal guildUsdNum, BillObjTypeEnum objTypeEnum) {
return SpringContextHolder.getBean(UserPurseService.class).addGameUsd(uid, guildUsdNum.doubleValue(), objTypeEnum, null);
}
@Frozen
@Transactional(rollbackFor = Exception.class, transactionManager = "mybatisplusTransactionManager")
public UserPurse subGameUsd(Long uid, BigDecimal gameUsdNum, BillObjTypeEnum objTypeEnum,
BusiStatus busiStatus, Consumer<UserPurse> billConsumer) {
if (BigDecimal.ZERO.compareTo(gameUsdNum) > 0) {
throw new ServiceException(BusiStatus.AMOUNT_PARAM_ERROR);
}
String desc = objTypeEnum.getDesc();
UserPurse after = withLock(uid, RedisKey.lock_user_game_usd, userPurse -> {
BigDecimal purseGameUsd = BigDecimal.valueOf(userPurse.getGameUsd());
if (purseGameUsd.compareTo(gameUsdNum) < 0){
throw new ServiceException(busiStatus);
}
log.info("subGameUsd 操作前,buss:{},userPurse:{}", desc, gson.toJson(userPurse));
int ret = baseMapper.minusGameUsd(uid, gameUsdNum.doubleValue());
boolean result = SqlHelper.retBool(ret);
if (!result){
throw new ServiceException(BusiStatus.SERVERBUSY);
}
BigDecimal afterGameUsd = purseGameUsd.subtract(gameUsdNum);
userPurse.setGameUsd(afterGameUsd.doubleValue());
userPurse.setUpdateTime(new Date());
log.info("subGold 操作后,buss:{},userPurse:{}", desc, gson.toJson(userPurse));
return userPurse;
});
if (null != billConsumer) {
billConsumer.accept(after);
} else {
billRecordService.insertGeneralBillRecord(uid, objTypeEnum, gameUsdNum.doubleValue(), after);
}
return after;
}
@Transactional(rollbackFor = Exception.class, transactionManager = "mybatisplusTransactionManager")
public UserPurse addGameUsd(Long uid, double gameUsdNum, BillObjTypeEnum billObjTypeEnum, Consumer<UserPurse> billConsume) {
if (gameUsdNum < 0D) {
throw new ServiceException(BusiStatus.AMOUNT_PARAM_ERROR);
}
UserPurse after = withLock(uid, RedisKey.lock_user_game_usd, userPurse -> {
log.info("addGameUsd 操作前,buss:{},userPurse:{}", billObjTypeEnum.getDesc(), gson.toJson(userPurse));
int ret = baseMapper.addGameUsd(uid, gameUsdNum);
boolean result = SqlHelper.retBool(ret);
if (!result){
throw new ServiceException(BusiStatus.SERVERBUSY);
}
log.info("addGame 操作后,buss:{},userPurse:{}", billObjTypeEnum.getDesc(), gson.toJson(userPurse));
userPurse.setGameUsd(DoubleUtil.add(userPurse.getGameUsd(), gameUsdNum));
userPurse.setUpdateTime(new Date());
return userPurse;
});
if (null != billConsume) {
billConsume.accept(after);
} else {
billRecordService.insertGeneralBillRecord(uid, billObjTypeEnum, gameUsdNum, after);
}
return after;
}
@Frozen
@Transactional(rollbackFor = Exception.class, transactionManager = "mybatisplusTransactionManager")
public UserPurse excGoldToDiamond(Long uid, Double exchangeNum, Double convertNum, BusiStatus busiStatus) {

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.accompany.business.mybatismapper.guildgame.GameDiamondSalaryMapper">
</mapper>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.accompany.business.mybatismapper.guildgame.GameDiamondStatDayMapper">
<update id="addGameDiamondStatDay">
INSERT INTO `game_diamond_stat_day` (`cycle_date`, `stat_date`, `guild_member_id`, `partition_id`, `uid`,
`guild_id`, `play_game_num`,`diamond_num`, `create_time`, `update_time`)
VALUES (#{cycleDate}, #{statDate}, #{guildMemberId}, #{partitionId}, #{uid}, #{guildId}, #{playGameNum}, #{diamondNum}, #{time},
#{time}) ON DUPLICATE KEY
UPDATE
play_game_num = play_game_num + values (play_game_num),
diamond_num = diamond_num + values (diamond_num),
update_time = values (update_time)
</update>
</mapper>

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.accompany.business.mybatismapper.guildgame.GameUsdBillRecordMapper">
<select id="listRechargeUserOrderByUsdDesc"
resultType="com.accompany.business.model.guildgame.GameUsdBillRecord">
select r.target_uid, sum(operate_currency) `operate_currency` from game_usd_bill_record r
where r.target_uid in <foreach collection="uidList" item="uid" open="(" separator="," close=")">#{uid}</foreach>
and r.cycle_date = #{cycleDate}
and r.type = #{type}
group by r.target_uid
</select>
<select id="getCycleUsdStatInCycleDateList"
resultType="com.accompany.business.vo.guildgame.GameUsdAccountCycleUsdStatVo">
select *, `totalIncome` - `settledIncome` `remainingIncome` from
(select r.cycle_date `cycleDate`,
sum(case when type in (1, 6, 8) or (type = 4 and target_guild_member_id = #{memberId}) then abs(operate_usd) else 0 end) `totalIncome`,
sum(case when type in (2, 5, 3) or (type = 4 and guild_member_id = #{memberId}) then abs(operate_usd) else 0 end) `settledIncome`
from game_usd_bill_record r
where (r.guild_member_id = #{memberId} or r.target_guild_member_id = #{memberId})
and r.cycle_date in <foreach collection="cycleDateList" item="cycleDate" open="(" separator="," close=")">#{cycleDate}</foreach>
group by r.cycle_date) r
</select>
<select id="listPage" resultType="com.accompany.business.model.guildgame.GameUsdBillRecord">
select * from game_usd_bill_record
<where>
<if test="receiveUid != null">
and target_uid = #{receiveUid}
</if>
<if test="uid != null">
and uid = #{uid}
</if>
<if test="partitionId != null">
and partition_id = #{partitionId}
</if>
<if test="startTime != null">
and create_time >=#{startTime}
</if>
<if test="endTime != null">
and create_time &lt;=#{endTime}
</if>
<if test="salaryOperateType != null">
<if test="salaryOperateType == 5">
and `type` in (5,8)
</if>
<if test="salaryOperateType != 5">
and `type` =#{salaryOperateType}
</if>
</if>
<if test="dateCycle != null">
and cycle_date =#{dateCycle}
</if>
<if test="hallId != null">
and guild_id =#{hallId}
</if>
</where>
order by create_time desc
</select>
<select id="sum" resultType="java.lang.Double">
select ifnull(sum(operate_usd),0) from game_usd_bill_record
<where>
<if test="receiveUid != null">
and target_uid = #{receiveUid}
</if>
<if test="uid != null">
and uid = #{uid}
</if>
<if test="partitionId != null">
and partition_id = #{partitionId}
</if>
<if test="startTime != null">
and create_time >=#{startTime}
</if>
<if test="endTime != null">
and create_time &lt;=#{endTime}
</if>
<if test="salaryOperateType != null">
and `type` =#{salaryOperateType}
</if>
</where>
order by create_time desc
</select>
<select id="anchorSummary" resultType="com.accompany.business.vo.guild.AnchorSalaryBillAdminVo">
SELECT hm.uid,hm.guild_id hallId, hm.guild_id agencyId,
IFNULL(a.diamondToUsb,0) diamondToUsb,
IFNULL(a.usbToGold,0) usbToGold,
IFNULL(a.usbToAgent,0) usbToAgent,
IFNULL(a.usbToOwner,0) usbToOwner,
IFNULL(a.officialWithdram,0) officialWithdram FROM guild_member hm
LEFT JOIN
(select uid,guild_id,
sum(IF( FIND_IN_SET( type, 1), operate_usd, 0 )) diamondToUsb,
sum(IF( FIND_IN_SET( type, 2), operate_usd, 0 )) usbToGold,
sum(IF( FIND_IN_SET( type, 3), operate_usd, 0 )) usbToAgent,
sum(IF( FIND_IN_SET( type, 4), operate_usd, 0 )) usbToOwner,
sum(IF( FIND_IN_SET( type, 5) or FIND_IN_SET(type, 7) or FIND_IN_SET( type, 8), operate_usd, 0 )) officialWithdram
from game_usd_bill_record r
where r.cycle_date = #{dateCycle}
<if test="hallId != null">
and r.guild_id =#{hallId}
</if>
<if test="uid != null">
and r.uid = #{uid}
</if>
<if test="partitionId != null">
and r.partition_id = #{partitionId}
</if>
group by uid ,guild_id) a ON hm.uid = a.uid AND hm.guild_id = a.guild_id
WHERE 1 = 1
<if test="hallId != null">
AND hm.guild_id = #{hallId}
</if>
<if test="uid != null">
and hm.uid = #{uid}
</if>
<if test="partitionId != null">
and hm.partition_id = #{partitionId}
</if>
group by hm.uid,hm.guild_id
</select>
<select id="sumRechargeUsd" resultType="java.lang.Double">
select ifnull(sum(operate_usd),0) from game_usd_bill_record
where target_uid = #{receiveUid}
<if test="cycleDate != null">
and cycle_date =#{cycleDate}
</if>
<if test="salaryOperateType != null">
and `type` =#{salaryOperateType}
</if>
</select>
<select id="sumReceiveGameUsdGroupByTargetUid"
resultType="com.accompany.business.model.guildgame.GameUsdBillRecord">
select partition_id, target_uid, abs(sum(operate_usd)) operate_usd
from game_usd_bill_record r
where r.create_time between #{startTime} and #{endTime}
and r.partition_id = #{partitionId}
and r.`type` = 3
group by partition_id, target_uid
</select>
</mapper>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.accompany.business.mybatismapper.guildgame.GameUsdProdMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.accompany.business.mybatismapper.guildgame.GameUsdWithdrawAccountConfigMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.accompany.business.mybatismapper.guildgame.GameUsdWithdrawAccountMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.accompany.business.mybatismapper.guildgame.GameUsdWithdrawRecordMapper">
</mapper>

View File

@@ -83,4 +83,12 @@
group by u.partition_id
</select>
<update id="addGameUsd">
update user_purse set game_usd = game_usd + #{gameUsd},update_time=now() where uid=#{uid}
</update>
<update id="minusGameUsd">
update user_purse set game_usd = game_usd - #{gameUsd},update_time=now()
where uid=#{uid} and game_usd &gt;= #{gameUsd}
</update>
</mapper>

View File

@@ -0,0 +1,80 @@
package com.accompany.business.controller.guild;
import com.accompany.business.service.guildgame.GameUsdOperateService;
import com.accompany.business.service.guildgame.GameUsdService;
import com.accompany.business.vo.guildgame.GameUsdOperateBillRecordVo;
import com.accompany.business.vo.guildgame.GameUsdOperateTabVo;
import com.accompany.business.vo.guildgame.GuildGameSalaryVo;
import com.accompany.common.annotation.Authorization;
import com.accompany.common.result.BusiResult;
import com.accompany.common.status.BusiStatus;
import com.accompany.core.exception.ServiceException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import static com.accompany.common.constant.ApplicationConstant.PublicParameters.PUB_UID;
@Api(tags = "游戏薪资", value = "游戏薪资")
@RequestMapping("/guildGameUsd")
@RestController
public class GameUsdController {
@Autowired
private GameUsdService gameUsdService;
@Autowired
private GameUsdOperateService gameUsdOperateService;
@ApiImplicitParams({
@ApiImplicitParam(name = "monthDate", value = "月份yyyy-MM", required = true, dataType = "String")
})
@ApiOperation(value = "游戏薪资信息", httpMethod = "GET")
@GetMapping("/info")
public GuildGameSalaryVo getGameUsdInfo(@RequestHeader(PUB_UID) Long uid, String monthDate) {
return gameUsdService.getGameUsdInfo(uid, monthDate);
}
@Authorization()
@ApiOperation(value = "领取游戏薪资", httpMethod = "POST")
@ApiImplicitParams({
@ApiImplicitParam(name = "statDate", value = "领取日期yyyy-MM-dd", required = true, dataType = "String"),
@ApiImplicitParam(name = "guildMemberId", value = "公会成员编号", required = true, dataType = "Long"),
@ApiImplicitParam(name = "usd", value = "领取薪资", required = true, dataType = "Double")
})
@PostMapping("/receive")
public BusiResult receiveGameUsd(@RequestHeader(PUB_UID) Long uid, Long guildMemberId, String statDate, Double usd) throws InterruptedException {
return gameUsdOperateService.receiveGameUsd(uid, guildMemberId, statDate, usd);
}
@ApiOperation("获取usd操作的功能标签tab")
@Authorization
@GetMapping("/getTab")
public BusiResult<GameUsdOperateTabVo> getUsdTab(@RequestHeader(PUB_UID) Long uid){
GameUsdOperateTabVo vo = gameUsdService.getUsdOperateTabVo(uid);
return BusiResult.success(vo);
}
@ApiOperation("usd操作")
@ApiImplicitParams({
@ApiImplicitParam(name = "type", value = "操作类型", required = true),
@ApiImplicitParam(name = "targetUid", value = "对象uid"),
@ApiImplicitParam(name = "gameUsdNum", value = "公会usd数目", required = true),
})
@Authorization
@PostMapping("/operate")
public BusiResult<GameUsdOperateBillRecordVo> operateUsd(@RequestHeader(PUB_UID) Long uid, Integer type, Long targetUid, BigDecimal gameUsdNum,
String accountType) {
if (null == type || null == gameUsdNum || BigDecimal.ZERO.compareTo(gameUsdNum) >= 0){
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
GameUsdOperateBillRecordVo billRecordVo = gameUsdOperateService.operateUsd(uid, targetUid, type, gameUsdNum.setScale(2), accountType);
return BusiResult.success(billRecordVo);
}
}

View File

@@ -0,0 +1,51 @@
package com.accompany.business.controller.guild;
import com.accompany.business.service.guildgame.GameUsdBillRecordService;
import com.accompany.business.vo.guildgame.GameUsdBillRecordVo;
import com.accompany.common.annotation.Authorization;
import com.accompany.common.constant.Constant;
import com.accompany.common.result.BusiResult;
import com.accompany.common.status.BusiStatus;
import com.accompany.core.base.UidContextHolder;
import com.accompany.core.exception.ServiceException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Api(tags = "游戏薪资-usd账单", value = "游戏薪资-usd账单")
@RequestMapping("/game/usd/bill")
@RestController
public class GameUsdRecordController {
@Autowired
private GameUsdBillRecordService service;
@ApiOperation("获取账单")
@ApiImplicitParams({
@ApiImplicitParam(name = "type", value = "收入 1 or 支出 2", required = true),
@ApiImplicitParam(name = "page", value = "页码"),
@ApiImplicitParam(name = "pageSize", value = "页长"),
})
@Authorization
@GetMapping("/page")
public BusiResult<List<GameUsdBillRecordVo>> page(Byte type,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize) {
if (null == type || (!Constant.status.valid.equals(type) && !Constant.status.invalid.equals(type))) {
throw new ServiceException(BusiStatus.PARAMERROR);
}
Long uid = UidContextHolder.get();
Page<GameUsdBillRecordVo> pageInfo = service.pageBillRecordByType(uid, type, page, pageSize);
return BusiResult.success(pageInfo.getRecords());
}
}

View File

@@ -0,0 +1,68 @@
package com.accompany.business.controller.guild;
import com.accompany.business.service.guildgame.GameUsdWithdrawAccountService;
import com.accompany.business.vo.guildgame.GameUsdWithdrawAccountVo;
import com.accompany.common.annotation.Authorization;
import com.accompany.common.result.BusiResult;
import com.accompany.common.status.BusiStatus;
import com.accompany.core.base.UidContextHolder;
import com.accompany.core.exception.ServiceException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
@Api(tags = "游戏薪资-提现", value = "游戏薪资-提现")
@RequestMapping("/game/usd/withdrawAccount")
@RestController
public class GameUsdWithdrawAccountController {
@Autowired
private GameUsdWithdrawAccountService accountService;
@ApiOperation("根据类型获取")
@Authorization
@GetMapping("/get")
public BusiResult<GameUsdWithdrawAccountVo> getAccount(String type){
if (!StringUtils.hasText(type)){
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
Long uid = UidContextHolder.get();
GameUsdWithdrawAccountVo vo = accountService.getAccountByType(uid, type);
return BusiResult.success(vo);
}
@ApiOperation("绑定")
@Authorization
@PostMapping("/bound")
public BusiResult<Void> bound(@RequestBody GameUsdWithdrawAccountVo account){
if (null == account.getUid() || !StringUtils.hasText(account.getType())
|| CollectionUtils.isEmpty(account.getFields())){
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
Long uid = UidContextHolder.get();
if (!uid.equals(account.getUid())){
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
accountService.bound(account);
return BusiResult.success();
}
@ApiOperation("解绑")
@Authorization
@PostMapping("/unbound")
public BusiResult<Void> unbound(@RequestBody GameUsdWithdrawAccountVo account){
if (null == account.getUid() || !StringUtils.hasText(account.getType())){
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
Long uid = UidContextHolder.get();
if (!uid.equals(account.getUid())){
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
accountService.unbound(account);
return BusiResult.success();
}
}