Compare commits
5 Commits
0bf810261f
...
3588d0aeee
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3588d0aeee | ||
|
|
dfb71f55a8 | ||
|
|
3168637944 | ||
|
|
dca9f12cb5 | ||
|
|
a0461ce68c |
@ -1,7 +1,11 @@
|
|||||||
package com.red.circle.external.inner.endpoint.message.api;
|
package com.red.circle.external.inner.endpoint.message.api;
|
||||||
|
|
||||||
import com.red.circle.framework.dto.ResultResponse;
|
import com.red.circle.framework.dto.ResultResponse;
|
||||||
|
import com.red.circle.external.inner.model.cmd.message.CustomC2cMsgBodyCmd;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,4 +33,10 @@ public interface ImMessageClientApi {
|
|||||||
@RequestParam("toAccount") Long toAccount,
|
@RequestParam("toAccount") Long toAccount,
|
||||||
@RequestParam("text") String text);
|
@RequestParam("text") String text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 C2C 自定义消息.
|
||||||
|
*/
|
||||||
|
@PostMapping("/sendCustomMessage")
|
||||||
|
ResultResponse<Void> sendCustomMessage(@RequestBody @Valid CustomC2cMsgBodyCmd cmd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,82 @@
|
|||||||
|
package com.red.circle.external.inner.model.cmd.message;
|
||||||
|
|
||||||
|
import com.red.circle.framework.dto.Command;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import java.io.Serial;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C2C custom IM message.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class CustomC2cMsgBodyCmd extends Command {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NotBlank(message = "fromAccount required.")
|
||||||
|
private String fromAccount;
|
||||||
|
|
||||||
|
@NotBlank(message = "toAccount required.")
|
||||||
|
private String toAccount;
|
||||||
|
|
||||||
|
@NotBlank(message = "desc required.")
|
||||||
|
private String desc;
|
||||||
|
|
||||||
|
@NotNull(message = "data required.")
|
||||||
|
private Object data;
|
||||||
|
|
||||||
|
public static CustomC2cMsgBodyBuilder builder() {
|
||||||
|
return new CustomC2cMsgBodyBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CustomC2cMsgBodyBuilder {
|
||||||
|
|
||||||
|
private String fromAccount;
|
||||||
|
private String toAccount;
|
||||||
|
private String desc;
|
||||||
|
private Object data;
|
||||||
|
|
||||||
|
public CustomC2cMsgBodyBuilder fromAccount(String fromAccount) {
|
||||||
|
this.fromAccount = fromAccount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomC2cMsgBodyBuilder fromAccount(Long fromAccount) {
|
||||||
|
this.fromAccount = String.valueOf(fromAccount);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomC2cMsgBodyBuilder toAccount(String toAccount) {
|
||||||
|
this.toAccount = toAccount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomC2cMsgBodyBuilder toAccount(Long toAccount) {
|
||||||
|
this.toAccount = String.valueOf(toAccount);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomC2cMsgBodyBuilder desc(String desc) {
|
||||||
|
this.desc = desc;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomC2cMsgBodyBuilder data(Object data) {
|
||||||
|
this.data = data;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomC2cMsgBodyCmd build() {
|
||||||
|
CustomC2cMsgBodyCmd cmd = new CustomC2cMsgBodyCmd();
|
||||||
|
cmd.setFromAccount(this.fromAccount);
|
||||||
|
cmd.setToAccount(this.toAccount);
|
||||||
|
cmd.setDesc(this.desc);
|
||||||
|
cmd.setData(this.data);
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -222,6 +222,21 @@ public enum EnumConfigKey {
|
|||||||
*/
|
*/
|
||||||
CP_PRICE,
|
CP_PRICE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CP 关系解绑金币.
|
||||||
|
*/
|
||||||
|
CP_DISMISS_CONSUME_GOLD,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Brother 关系解绑金币.
|
||||||
|
*/
|
||||||
|
BROTHER_DISMISS_CONSUME_GOLD,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sisters 关系解绑金币.
|
||||||
|
*/
|
||||||
|
SISTERS_DISMISS_CONSUME_GOLD,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aswat 超级管理员ID.
|
* Aswat 超级管理员ID.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -755,6 +755,11 @@ public enum GoldOrigin {
|
|||||||
*/
|
*/
|
||||||
CP_LOVE_LETTER("CP love letter"),
|
CP_LOVE_LETTER("CP love letter"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解除 CP/Brother/Sisters 关系.
|
||||||
|
*/
|
||||||
|
CP_DISMISS("CP dismiss"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cp榜单(周榜和季度榜)
|
* cp榜单(周榜和季度榜)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -5,15 +5,20 @@ import com.red.circle.console.app.dto.clienobject.app.activity.cp.ResidentCpLeve
|
|||||||
import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpConfigSaveCmd;
|
import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpConfigSaveCmd;
|
||||||
import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpLevelConfigSaveCmd;
|
import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpLevelConfigSaveCmd;
|
||||||
import com.red.circle.console.app.service.app.sys.CpCabinConfigService;
|
import com.red.circle.console.app.service.app.sys.CpCabinConfigService;
|
||||||
|
import com.red.circle.console.app.service.app.sys.SysEnumConfigService;
|
||||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
import com.red.circle.framework.core.response.ResponseErrorCode;
|
import com.red.circle.framework.core.response.ResponseErrorCode;
|
||||||
import com.red.circle.framework.dto.PageQuery;
|
import com.red.circle.framework.dto.PageQuery;
|
||||||
import com.red.circle.framework.dto.PageResult;
|
import com.red.circle.framework.dto.PageResult;
|
||||||
|
import com.red.circle.other.inner.enums.config.EnumConfigKey;
|
||||||
import com.red.circle.other.inner.model.cmd.sys.SysCpCabinConfigQryCmd;
|
import com.red.circle.other.inner.model.cmd.sys.SysCpCabinConfigQryCmd;
|
||||||
|
import com.red.circle.other.inner.model.dto.sys.EnumConfigDTO;
|
||||||
import com.red.circle.other.inner.model.dto.sys.SysCpCabinConfigDTO;
|
import com.red.circle.other.inner.model.dto.sys.SysCpCabinConfigDTO;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -35,8 +40,14 @@ public class ResidentCpActivityServiceImpl implements ResidentCpActivityService
|
|||||||
private static final int CP_LEVEL_COUNT = 6;
|
private static final int CP_LEVEL_COUNT = 6;
|
||||||
private static final int CP_MIN_LEVEL = 0;
|
private static final int CP_MIN_LEVEL = 0;
|
||||||
private static final int QUERY_LIMIT = 50;
|
private static final int QUERY_LIMIT = 50;
|
||||||
|
private static final String CONFIG_GROUP_NAME = "CP";
|
||||||
|
private static final String CONFIG_DATA_TYPE = "int";
|
||||||
|
private static final String RELATION_TYPE_CP = "CP";
|
||||||
|
private static final String RELATION_TYPE_BROTHER = "BROTHER";
|
||||||
|
private static final String RELATION_TYPE_SISTERS = "SISTERS";
|
||||||
|
|
||||||
private final CpCabinConfigService cpCabinConfigService;
|
private final CpCabinConfigService cpCabinConfigService;
|
||||||
|
private final SysEnumConfigService sysEnumConfigService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResidentCpConfigCO getConfig(String sysOrigin) {
|
public ResidentCpConfigCO getConfig(String sysOrigin) {
|
||||||
@ -50,6 +61,7 @@ public class ResidentCpActivityServiceImpl implements ResidentCpActivityService
|
|||||||
return new ResidentCpConfigCO()
|
return new ResidentCpConfigCO()
|
||||||
.setConfigured(!configs.isEmpty())
|
.setConfigured(!configs.isEmpty())
|
||||||
.setSysOrigin(normalizedSysOrigin)
|
.setSysOrigin(normalizedSysOrigin)
|
||||||
|
.setDismissConsumeGolds(getDismissConsumeGolds(normalizedSysOrigin))
|
||||||
.setLevels(levels);
|
.setLevels(levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +95,7 @@ public class ResidentCpActivityServiceImpl implements ResidentCpActivityService
|
|||||||
cpCabinConfigService.addCpCabin(config);
|
cpCabinConfigService.addCpCabin(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
saveDismissConsumeGolds(normalizedSysOrigin, cmd.getDismissConsumeGolds());
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SysCpCabinConfigDTO> listCpCabinConfigs(String sysOrigin) {
|
private List<SysCpCabinConfigDTO> listCpCabinConfigs(String sysOrigin) {
|
||||||
@ -135,6 +148,95 @@ public class ResidentCpActivityServiceImpl implements ResidentCpActivityService
|
|||||||
requiredValue >= previousRequiredValue);
|
requiredValue >= previousRequiredValue);
|
||||||
previousRequiredValue = requiredValue;
|
previousRequiredValue = requiredValue;
|
||||||
}
|
}
|
||||||
|
validateDismissConsumeGolds(cmd.getDismissConsumeGolds());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Long> getDismissConsumeGolds(String sysOrigin) {
|
||||||
|
Map<String, Long> result = defaultDismissConsumeGolds();
|
||||||
|
dismissConsumeGoldKeys().forEach((relationType, key) -> result.put(relationType,
|
||||||
|
enumConfigGoldValue(sysEnumConfigService.getByCode(key.name(), sysOrigin))));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveDismissConsumeGolds(String sysOrigin, Map<String, Long> dismissConsumeGolds) {
|
||||||
|
if (Objects.isNull(dismissConsumeGolds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dismissConsumeGoldKeys().forEach((relationType, key) -> {
|
||||||
|
if (dismissConsumeGolds.containsKey(relationType)) {
|
||||||
|
saveDismissConsumeGold(sysOrigin, key, dismissConsumeGolds.get(relationType));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveDismissConsumeGold(String sysOrigin, EnumConfigKey key, Long value) {
|
||||||
|
Long normalizedValue = defaultGold(value);
|
||||||
|
EnumConfigDTO enumConfig = sysEnumConfigService.getByCode(key.name(), sysOrigin);
|
||||||
|
boolean exists = Objects.nonNull(enumConfig) && Objects.nonNull(enumConfig.getId());
|
||||||
|
if (!exists) {
|
||||||
|
enumConfig = new EnumConfigDTO();
|
||||||
|
}
|
||||||
|
enumConfig.setSysOrigin(sysOrigin)
|
||||||
|
.setName(key.name())
|
||||||
|
.setTitle(dismissConsumeGoldTitle(key))
|
||||||
|
.setVal(String.valueOf(normalizedValue))
|
||||||
|
.setDescription(dismissConsumeGoldTitle(key))
|
||||||
|
.setDataType(CONFIG_DATA_TYPE)
|
||||||
|
.setReturnApp(Boolean.FALSE)
|
||||||
|
.setGroupName(CONFIG_GROUP_NAME);
|
||||||
|
if (exists) {
|
||||||
|
sysEnumConfigService.updateSysEnumConfig(enumConfig);
|
||||||
|
} else {
|
||||||
|
sysEnumConfigService.saveSysEnumConfig(enumConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateDismissConsumeGolds(Map<String, Long> dismissConsumeGolds) {
|
||||||
|
if (Objects.isNull(dismissConsumeGolds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dismissConsumeGolds.forEach((relationType, gold) -> {
|
||||||
|
ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
|
||||||
|
"relationType is not supported.",
|
||||||
|
dismissConsumeGoldKeys().containsKey(normalizeRelationType(relationType)));
|
||||||
|
ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
|
||||||
|
"dismissConsumeGold must be greater than or equal to zero.",
|
||||||
|
defaultGold(gold) >= 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long enumConfigGoldValue(EnumConfigDTO enumConfig) {
|
||||||
|
if (Objects.isNull(enumConfig) || StringUtils.isBlank(enumConfig.getVal())) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return new BigDecimal(enumConfig.getVal()).longValue();
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Long> defaultDismissConsumeGolds() {
|
||||||
|
Map<String, Long> result = new LinkedHashMap<>();
|
||||||
|
dismissConsumeGoldKeys().keySet().forEach(relationType -> result.put(relationType, 0L));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, EnumConfigKey> dismissConsumeGoldKeys() {
|
||||||
|
Map<String, EnumConfigKey> result = new LinkedHashMap<>();
|
||||||
|
result.put(RELATION_TYPE_CP, EnumConfigKey.CP_DISMISS_CONSUME_GOLD);
|
||||||
|
result.put(RELATION_TYPE_BROTHER, EnumConfigKey.BROTHER_DISMISS_CONSUME_GOLD);
|
||||||
|
result.put(RELATION_TYPE_SISTERS, EnumConfigKey.SISTERS_DISMISS_CONSUME_GOLD);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String dismissConsumeGoldTitle(EnumConfigKey key) {
|
||||||
|
return switch (key) {
|
||||||
|
case CP_DISMISS_CONSUME_GOLD -> "CP 解绑金币";
|
||||||
|
case BROTHER_DISMISS_CONSUME_GOLD -> "Brother 解绑金币";
|
||||||
|
case SISTERS_DISMISS_CONSUME_GOLD -> "Sisters 解绑金币";
|
||||||
|
default -> "关系解绑金币";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ResidentCpLevelConfigSaveCmd> sortedLevels(
|
private List<ResidentCpLevelConfigSaveCmd> sortedLevels(
|
||||||
@ -157,6 +259,24 @@ public class ResidentCpActivityServiceImpl implements ResidentCpActivityService
|
|||||||
return requiredValue == null ? 0L : requiredValue;
|
return requiredValue == null ? 0L : requiredValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Long defaultGold(Long gold) {
|
||||||
|
return gold == null ? 0L : gold;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeRelationType(String relationType) {
|
||||||
|
if (StringUtils.isBlank(relationType)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String normalized = relationType.trim().toUpperCase();
|
||||||
|
if (Objects.equals(normalized, "BROTHERS")) {
|
||||||
|
return RELATION_TYPE_BROTHER;
|
||||||
|
}
|
||||||
|
if (Objects.equals(normalized, "SISTER")) {
|
||||||
|
return RELATION_TYPE_SISTERS;
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
private String defaultLevelName(Integer level, String levelName) {
|
private String defaultLevelName(Integer level, String levelName) {
|
||||||
if (StringUtils.isNotBlank(levelName)) {
|
if (StringUtils.isNotBlank(levelName)) {
|
||||||
return levelName.trim();
|
return levelName.trim();
|
||||||
|
|||||||
@ -37,6 +37,11 @@ public class SysEnumConfigServiceImpl implements SysEnumConfigService {
|
|||||||
return ResponseAssert.requiredSuccess(enumConfigClient.getViolationAvatar(violationPicture));
|
return ResponseAssert.requiredSuccess(enumConfigClient.getViolationAvatar(violationPicture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnumConfigDTO getByCode(String name, String sysOrigin) {
|
||||||
|
return ResponseAssert.requiredSuccess(enumConfigClient.getByCode(name, sysOrigin));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveSysEnumConfig(EnumConfigDTO sysEnumConfig) {
|
public void saveSysEnumConfig(EnumConfigDTO sysEnumConfig) {
|
||||||
ResponseAssert.requiredSuccess(enumConfigClient.saveSysEnumConfig(sysEnumConfig));
|
ResponseAssert.requiredSuccess(enumConfigClient.saveSysEnumConfig(sysEnumConfig));
|
||||||
|
|||||||
@ -3,7 +3,9 @@ package com.red.circle.console.app.dto.clienobject.app.activity.cp;
|
|||||||
import com.red.circle.framework.dto.ClientObject;
|
import com.red.circle.framework.dto.ClientObject;
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@ -24,4 +26,9 @@ public class ResidentCpConfigCO extends ClientObject {
|
|||||||
private String sysOrigin;
|
private String sysOrigin;
|
||||||
|
|
||||||
private List<ResidentCpLevelConfigCO> levels = new ArrayList<>();
|
private List<ResidentCpLevelConfigCO> levels = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relation dismiss gold config. Key: CP/BROTHER/SISTERS.
|
||||||
|
*/
|
||||||
|
private Map<String, Long> dismissConsumeGolds = new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import jakarta.validation.constraints.NotEmpty;
|
|||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
@ -25,4 +26,9 @@ public class ResidentCpConfigSaveCmd implements Serializable {
|
|||||||
@Valid
|
@Valid
|
||||||
@NotEmpty(message = "levels required.")
|
@NotEmpty(message = "levels required.")
|
||||||
private List<ResidentCpLevelConfigSaveCmd> levels;
|
private List<ResidentCpLevelConfigSaveCmd> levels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relation dismiss gold config. Key: CP/BROTHER/SISTERS.
|
||||||
|
*/
|
||||||
|
private Map<String, Long> dismissConsumeGolds;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,8 @@ public interface SysEnumConfigService {
|
|||||||
|
|
||||||
String getViolationAvatar(EnumConfigKey violationPicture);
|
String getViolationAvatar(EnumConfigKey violationPicture);
|
||||||
|
|
||||||
|
EnumConfigDTO getByCode(String name, String sysOrigin);
|
||||||
|
|
||||||
void saveSysEnumConfig(EnumConfigDTO sysEnumConfig);
|
void saveSysEnumConfig(EnumConfigDTO sysEnumConfig);
|
||||||
|
|
||||||
void updateSysEnumConfig(EnumConfigDTO sysEnumConfig);
|
void updateSysEnumConfig(EnumConfigDTO sysEnumConfig);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.red.circle.external.inner.endpoint.message;
|
package com.red.circle.external.inner.endpoint.message;
|
||||||
|
|
||||||
import com.red.circle.external.inner.endpoint.message.api.ImMessageClientApi;
|
import com.red.circle.external.inner.endpoint.message.api.ImMessageClientApi;
|
||||||
|
import com.red.circle.external.inner.model.cmd.message.CustomC2cMsgBodyCmd;
|
||||||
import com.red.circle.external.inner.service.message.ImMessageClientService;
|
import com.red.circle.external.inner.service.message.ImMessageClientService;
|
||||||
import com.red.circle.framework.dto.ResultResponse;
|
import com.red.circle.framework.dto.ResultResponse;
|
||||||
import com.red.circle.tool.core.parse.DataTypeUtils;
|
import com.red.circle.tool.core.parse.DataTypeUtils;
|
||||||
@ -36,4 +37,10 @@ public class ImMessageClientEndpoint implements ImMessageClientApi {
|
|||||||
return ResultResponse.success();
|
return ResultResponse.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultResponse<Void> sendCustomMessage(CustomC2cMsgBodyCmd cmd) {
|
||||||
|
imMessageClientService.sendCustomMessage(cmd);
|
||||||
|
return ResultResponse.success();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package com.red.circle.external.inner.service.message;
|
package com.red.circle.external.inner.service.message;
|
||||||
|
|
||||||
|
import com.red.circle.external.inner.model.cmd.message.CustomC2cMsgBodyCmd;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* im 消息服务.
|
* im 消息服务.
|
||||||
*
|
*
|
||||||
@ -12,4 +14,9 @@ public interface ImMessageClientService {
|
|||||||
*/
|
*/
|
||||||
void sendMessageText(String fromAccount, String toAccount, String text);
|
void sendMessageText(String fromAccount, String toAccount, String text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 C2C 自定义消息.
|
||||||
|
*/
|
||||||
|
void sendCustomMessage(CustomC2cMsgBodyCmd cmd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,13 @@
|
|||||||
package com.red.circle.external.inner.service.message.impl;
|
package com.red.circle.external.inner.service.message.impl;
|
||||||
|
|
||||||
import com.red.circle.component.instant.msg.tencet.service.endpoint.api.im.account.ImMessageManagerService;
|
import com.red.circle.component.instant.msg.tencet.service.endpoint.api.im.account.ImMessageManagerService;
|
||||||
|
import com.red.circle.component.instant.msg.tencet.service.param.ImMessageParam;
|
||||||
|
import com.red.circle.component.instant.msg.tencet.service.param.MessageBody;
|
||||||
|
import com.red.circle.component.instant.msg.tencet.service.param.OfflinePushInfo;
|
||||||
|
import com.red.circle.external.inner.model.cmd.message.CustomC2cMsgBodyCmd;
|
||||||
import com.red.circle.external.inner.service.message.ImMessageClientService;
|
import com.red.circle.external.inner.service.message.ImMessageClientService;
|
||||||
|
import com.red.circle.tool.core.num.NumUtils;
|
||||||
|
import com.red.circle.tool.core.parse.DataTypeUtils;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -23,4 +29,20 @@ public class ImMessageClientServiceImpl implements ImMessageClientService {
|
|||||||
imMessageManagerService.sendMessageText(fromAccount, toAccount, text).subscribe();
|
imMessageManagerService.sendMessageText(fromAccount, toAccount, text).subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendCustomMessage(CustomC2cMsgBodyCmd cmd) {
|
||||||
|
ImMessageParam param = ImMessageParam.builder()
|
||||||
|
.fromAccount(cmd.getFromAccount())
|
||||||
|
.toAccount(cmd.getToAccount())
|
||||||
|
.offlinePushInfo(OfflinePushInfo.builder()
|
||||||
|
.pushFlag(0)
|
||||||
|
.build())
|
||||||
|
.msgRandom(DataTypeUtils.toInteger(NumUtils.getRandomNumberString(9)))
|
||||||
|
.build()
|
||||||
|
.addMsgBody(MessageBody.customBody(cmd.getDesc(), cmd.getData()));
|
||||||
|
imMessageManagerService.sendMessage(param)
|
||||||
|
.subscribe(res -> log.warn("sendCustomMessage response result:{}", res),
|
||||||
|
res -> log.error("sendCustomMessage error cmd={}, result={}", cmd, res));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -189,6 +189,7 @@ public class BlessingsGiftGiveCmdExe {
|
|||||||
giftConfig.setSpecial(giftConfigCache.getSpecial());
|
giftConfig.setSpecial(giftConfigCache.getSpecial());
|
||||||
giftConfig.setType(giftConfigCache.getType());
|
giftConfig.setType(giftConfigCache.getType());
|
||||||
giftConfig.setGiftTab(giftConfigCache.getGiftTab());
|
giftConfig.setGiftTab(giftConfigCache.getGiftTab());
|
||||||
|
giftConfig.setCpRelationType(giftConfigCache.getCpRelationType());
|
||||||
return giftConfig;
|
return giftConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,11 +6,13 @@ import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExt
|
|||||||
import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum;
|
import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum;
|
||||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||||
|
import com.red.circle.other.app.common.cp.CpRelationGoldConfig;
|
||||||
import com.red.circle.other.app.dto.clientobject.user.relation.cp.CpDismissApplyCO;
|
import com.red.circle.other.app.dto.clientobject.user.relation.cp.CpDismissApplyCO;
|
||||||
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyDismissCmd;
|
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyDismissCmd;
|
||||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||||
import com.red.circle.other.domain.model.user.UserProfile;
|
import com.red.circle.other.domain.model.user.UserProfile;
|
||||||
import com.red.circle.other.infra.common.user.UserGiftBackpackCommon;
|
import com.red.circle.other.infra.common.user.UserGiftBackpackCommon;
|
||||||
|
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
|
||||||
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
|
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
|
||||||
import com.red.circle.other.infra.database.cache.service.user.UserCpValueCacheService;
|
import com.red.circle.other.infra.database.cache.service.user.UserCpValueCacheService;
|
||||||
import com.red.circle.other.infra.database.mongo.service.user.count.WeekCpValueCountService;
|
import com.red.circle.other.infra.database.mongo.service.user.count.WeekCpValueCountService;
|
||||||
@ -23,7 +25,12 @@ import com.red.circle.other.infra.database.rds.service.user.user.CpValueService;
|
|||||||
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
|
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
|
||||||
import com.red.circle.tool.core.collection.MapBuilder;
|
import com.red.circle.tool.core.collection.MapBuilder;
|
||||||
import com.red.circle.tool.core.date.TimestampUtils;
|
import com.red.circle.tool.core.date.TimestampUtils;
|
||||||
|
import com.red.circle.tool.core.tuple.PennyAmount;
|
||||||
|
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
||||||
|
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
|
||||||
|
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -51,6 +58,8 @@ public class DismissCpApplyCmdExe {
|
|||||||
private final CpCabinAchieveService cpCabinAchieveService;
|
private final CpCabinAchieveService cpCabinAchieveService;
|
||||||
private final UserProfileGateway userProfileGateway;
|
private final UserProfileGateway userProfileGateway;
|
||||||
private final CpRelationshipCacheService cpRelationshipCacheService;
|
private final CpRelationshipCacheService cpRelationshipCacheService;
|
||||||
|
private final WalletGoldClient walletGoldClient;
|
||||||
|
private final EnumConfigCacheService enumConfigCacheService;
|
||||||
|
|
||||||
public CpDismissApplyCO execute(CpApplyDismissCmd cmd) {
|
public CpDismissApplyCO execute(CpApplyDismissCmd cmd) {
|
||||||
String relationType = parseRelationType(cmd.getRelationType());
|
String relationType = parseRelationType(cmd.getRelationType());
|
||||||
@ -66,6 +75,11 @@ public class DismissCpApplyCmdExe {
|
|||||||
return buildDismissedResult(cmd.getCpUserId(), relationType, TimestampUtils.now().getTime());
|
return buildDismissedResult(cmd.getCpUserId(), relationType, TimestampUtils.now().getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String sysOrigin = resolveSysOrigin(cmd, cpRelationship);
|
||||||
|
BigDecimal dismissConsumeGold = dismissConsumeGold(relationType, sysOrigin);
|
||||||
|
deductDismissGold(cmd.requiredReqUserId(), cpRelationship, relationType,
|
||||||
|
dismissConsumeGold, sysOrigin);
|
||||||
|
|
||||||
// 更新申请状态为解散
|
// 更新申请状态为解散
|
||||||
cpApplyService.dismiss(cmd.requiredReqUserId(), relationType);
|
cpApplyService.dismiss(cmd.requiredReqUserId(), relationType);
|
||||||
|
|
||||||
@ -118,6 +132,49 @@ public class DismissCpApplyCmdExe {
|
|||||||
Arrays.asList(relationship.getUserId(), relationship.getCpUserId()));
|
Arrays.asList(relationship.getUserId(), relationship.getCpUserId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BigDecimal dismissConsumeGold(String relationType, String sysOrigin) {
|
||||||
|
return CpRelationGoldConfig.defaultGold(enumConfigCacheService.getValueBigDecimal(
|
||||||
|
CpRelationGoldConfig.dismissConsumeGoldKey(relationType), sysOrigin));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deductDismissGold(Long userId, CpRelationship relationship, String relationType,
|
||||||
|
BigDecimal dismissConsumeGold, String sysOrigin) {
|
||||||
|
if (dismissConsumeGold.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ResponseAssert.requiredSuccess(walletGoldClient.changeBalance(GoldReceiptCmd.builder()
|
||||||
|
.appExpenditure()
|
||||||
|
.userId(userId)
|
||||||
|
.sysOrigin(sysOrigin)
|
||||||
|
.eventId(dismissEventId(relationship, relationType))
|
||||||
|
.origin(GoldOrigin.CP_DISMISS)
|
||||||
|
.amount(PennyAmount.ofDollar(dismissConsumeGold))
|
||||||
|
.build()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String dismissEventId(CpRelationship relationship, String relationType) {
|
||||||
|
if (Objects.nonNull(relationship.getId())) {
|
||||||
|
return "CP_DISMISS:" + relationship.getId();
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(relationship.getCpValId())) {
|
||||||
|
return "CP_DISMISS:" + relationship.getCpValId();
|
||||||
|
}
|
||||||
|
return "CP_DISMISS:" + relationType + ":" + relationship.getUserId() + ":"
|
||||||
|
+ relationship.getCpUserId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveSysOrigin(CpApplyDismissCmd cmd, CpRelationship relationship) {
|
||||||
|
try {
|
||||||
|
return cmd.requireReqSysOrigin();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
return resolveRelationshipSysOrigin(relationship);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveRelationshipSysOrigin(CpRelationship relationship) {
|
||||||
|
return Objects.toString(relationship.getSysOrigin(), "");
|
||||||
|
}
|
||||||
|
|
||||||
private CpDismissApplyCO buildDismissedResult(Long cpUserId, String relationType,
|
private CpDismissApplyCO buildDismissedResult(Long cpUserId, String relationType,
|
||||||
Long dismissEndTime) {
|
Long dismissEndTime) {
|
||||||
return new CpDismissApplyCO()
|
return new CpDismissApplyCO()
|
||||||
|
|||||||
@ -6,9 +6,11 @@ import com.red.circle.framework.core.asserts.ResponseAssert;
|
|||||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||||
import com.red.circle.mq.business.model.event.user.CpApplyEvent;
|
import com.red.circle.mq.business.model.event.user.CpApplyEvent;
|
||||||
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
|
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
|
||||||
|
import com.red.circle.other.app.common.cp.CpRelationC2cNoticeUtils;
|
||||||
import com.red.circle.other.app.common.cp.CpRelationBroadcastMqClient;
|
import com.red.circle.other.app.common.cp.CpRelationBroadcastMqClient;
|
||||||
import com.red.circle.other.app.dto.cmd.user.relation.cp.ProcessApplyCmd;
|
import com.red.circle.other.app.dto.cmd.user.relation.cp.ProcessApplyCmd;
|
||||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||||
|
import com.red.circle.other.domain.model.user.UserProfile;
|
||||||
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
|
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
|
||||||
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
||||||
import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship;
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship;
|
||||||
@ -25,6 +27,7 @@ import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
|
|||||||
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -67,16 +70,21 @@ public class ProcessCpApplyCmd {
|
|||||||
ResponseAssert.isTrue(CommonErrorCode.STATE_ERROR,
|
ResponseAssert.isTrue(CommonErrorCode.STATE_ERROR,
|
||||||
Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name()));
|
Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name()));
|
||||||
|
|
||||||
// 检查是否是复合申请
|
boolean agree = isAgree(cmd);
|
||||||
CpRelationship dismissingCp = cpRelationshipService.getDismissingCp(
|
boolean isReconcile = false;
|
||||||
cpApply.getSendApplyUserId(), cpApply.getAcceptApplyUserId(), relationType);
|
|
||||||
boolean isReconcile = Objects.nonNull(dismissingCp);
|
|
||||||
|
|
||||||
if (!isReconcile) {
|
if (agree) {
|
||||||
// 非复合申请:CP已存在
|
// 检查是否是复合申请
|
||||||
|
CpRelationship dismissingCp = cpRelationshipService.getDismissingCp(
|
||||||
|
cpApply.getSendApplyUserId(), cpApply.getAcceptApplyUserId(), relationType);
|
||||||
|
isReconcile = Objects.nonNull(dismissingCp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (agree && !isReconcile) {
|
||||||
|
// 非复合申请:两人之间只能存在一种正常关系
|
||||||
ResponseAssert.isFalse(UserRelationErrorCode.ME_OR_YOU_CP_EXISTED,
|
ResponseAssert.isFalse(UserRelationErrorCode.ME_OR_YOU_CP_EXISTED,
|
||||||
cpRelationshipService.existsCp(cpApply.getSendApplyUserId(), cpApply.getAcceptApplyUserId(),
|
cpRelationshipService.existsRelationship(cpApply.getSendApplyUserId(),
|
||||||
relationType));
|
cpApply.getAcceptApplyUserId()));
|
||||||
|
|
||||||
int maxCount = relationMaxCount(relationType);
|
int maxCount = relationMaxCount(relationType);
|
||||||
ResponseAssert.isFalse(UserRelationErrorCode.CP_LIMIT_EXCEEDED,
|
ResponseAssert.isFalse(UserRelationErrorCode.CP_LIMIT_EXCEEDED,
|
||||||
@ -89,8 +97,9 @@ public class ProcessCpApplyCmd {
|
|||||||
ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE,
|
ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE,
|
||||||
cpApplyService.changeStatusById(cmd.getApplyId(), getStatus(cmd)));
|
cpApplyService.changeStatusById(cmd.getApplyId(), getStatus(cmd)));
|
||||||
|
|
||||||
if (!isAgree(cmd)) {
|
if (!agree) {
|
||||||
returnGoldCoins(cmd, cpApply);
|
returnGoldCoins(cmd, cpApply);
|
||||||
|
sendProcessNotice(cpApply, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,23 +114,51 @@ public class ProcessCpApplyCmd {
|
|||||||
cmd.requireReqSysOrigin(), relationType);
|
cmd.requireReqSysOrigin(), relationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
refuseStatusWaitIfLimitReached(cmd, cpApply, relationType);
|
List<Long> refusedApplyIds = cpApplyService.refuseOtherWaitBetweenUsers(cpApply.getId(),
|
||||||
|
cpApply.getSendApplyUserId(), cpApply.getAcceptApplyUserId());
|
||||||
|
boolean refusedByLimit = refuseStatusWaitIfLimitReached(cmd, cpApply, relationType);
|
||||||
|
if (!refusedApplyIds.isEmpty() || refusedByLimit) {
|
||||||
|
scheduleReimburse(cmd, cpApply.getId());
|
||||||
|
}
|
||||||
|
|
||||||
cpRelationshipCacheService.remove(Arrays.asList(cpApply.getSendApplyUserId(), cpApply.getAcceptApplyUserId()));
|
cpRelationshipCacheService.remove(Arrays.asList(cpApply.getSendApplyUserId(), cpApply.getAcceptApplyUserId()));
|
||||||
cpRelationBroadcastMqClient.publish(cmd.requireReqSysOrigin(), cpApply.getId(),
|
cpRelationBroadcastMqClient.publish(cmd.requireReqSysOrigin(), cpApply.getId(),
|
||||||
cpApply.getSendApplyUserId(), cpApply.getAcceptApplyUserId(), relationType);
|
cpApply.getSendApplyUserId(), cpApply.getAcceptApplyUserId(), relationType);
|
||||||
|
sendProcessNotice(cpApply, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refuseStatusWaitIfLimitReached(ProcessApplyCmd cmd, CpApply cpApply,
|
private void sendProcessNotice(CpApply cpApply, boolean agree) {
|
||||||
|
try {
|
||||||
|
UserProfile senderProfile = userProfileGateway.getByUserId(cpApply.getSendApplyUserId());
|
||||||
|
UserProfile acceptProfile = userProfileGateway.getByUserId(cpApply.getAcceptApplyUserId());
|
||||||
|
if (Objects.isNull(senderProfile) || Objects.isNull(acceptProfile)) {
|
||||||
|
log.info("[CP] skip process c2c notice, applyId={}, senderProfile={}, acceptProfile={}",
|
||||||
|
cpApply.getId(), Objects.nonNull(senderProfile), Objects.nonNull(acceptProfile));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
imMessageClient.sendCustomMessage(agree
|
||||||
|
? CpRelationC2cNoticeUtils.buildAccepted(cpApply, senderProfile, acceptProfile)
|
||||||
|
: CpRelationC2cNoticeUtils.buildRejected(cpApply, senderProfile, acceptProfile));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("[CP] send process c2c notice failed, applyId={}, agree={}, reason={}",
|
||||||
|
cpApply.getId(), agree, ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean refuseStatusWaitIfLimitReached(ProcessApplyCmd cmd, CpApply cpApply,
|
||||||
String relationType) {
|
String relationType) {
|
||||||
if (cpRelationshipService.countCp(cpApply.getAcceptApplyUserId(), relationType)
|
if (cpRelationshipService.countCp(cpApply.getAcceptApplyUserId(), relationType)
|
||||||
< relationMaxCount(relationType)) {
|
< relationMaxCount(relationType)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
cpApplyService.refuseStatusWait(cmd.requiredReqUserId(), relationType);
|
cpApplyService.refuseStatusWait(cmd.requiredReqUserId(), relationType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleReimburse(ProcessApplyCmd cmd, Long applyId) {
|
||||||
userMqMessageService.cpApplyDelayed(
|
userMqMessageService.cpApplyDelayed(
|
||||||
new CpApplyEvent()
|
new CpApplyEvent()
|
||||||
.setId(cpApply.getId())
|
.setId(applyId)
|
||||||
.setSysOrigin(SysOriginPlatformEnum.valueOf(cmd.requireReqSysOrigin())),
|
.setSysOrigin(SysOriginPlatformEnum.valueOf(cmd.requireReqSysOrigin())),
|
||||||
TimestampUtils.nowPlusMinutes(1));
|
TimestampUtils.nowPlusMinutes(1));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,14 @@
|
|||||||
package com.red.circle.other.app.command.user;
|
package com.red.circle.other.app.command.user;
|
||||||
|
|
||||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||||
import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient;
|
import com.red.circle.external.inner.endpoint.message.ImMessageClient;
|
||||||
import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExtTemplateTypeCmd;
|
|
||||||
import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum;
|
|
||||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||||
import com.red.circle.mq.business.model.event.user.CpApplyEvent;
|
import com.red.circle.mq.business.model.event.user.CpApplyEvent;
|
||||||
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
|
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
|
||||||
|
import com.red.circle.other.app.common.cp.CpRelationC2cNoticeUtils;
|
||||||
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
|
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
|
||||||
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyCmd;
|
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyCmd;
|
||||||
import com.red.circle.other.app.util.OfficialNoticeUtils;
|
|
||||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||||
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
|
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
|
||||||
@ -20,19 +18,16 @@ import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
|||||||
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
|
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
|
||||||
import com.red.circle.other.infra.enums.user.user.CpApplyStatus;
|
import com.red.circle.other.infra.enums.user.user.CpApplyStatus;
|
||||||
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
|
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
|
||||||
|
import com.red.circle.other.inner.asserts.user.UserRelationErrorCode;
|
||||||
import com.red.circle.other.inner.enums.config.EnumConfigKey;
|
import com.red.circle.other.inner.enums.config.EnumConfigKey;
|
||||||
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||||
import com.red.circle.tool.core.date.TimestampUtils;
|
import com.red.circle.tool.core.date.TimestampUtils;
|
||||||
import com.red.circle.other.inner.asserts.user.UserRelationErrorCode;
|
|
||||||
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
||||||
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
|
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
|
||||||
import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO;
|
import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO;
|
||||||
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -51,7 +46,7 @@ public class SendCpApplyCmdExe {
|
|||||||
private static final int FRIEND_MAX_COUNT = 3;
|
private static final int FRIEND_MAX_COUNT = 3;
|
||||||
|
|
||||||
private final CpApplyService cpApplyService;
|
private final CpApplyService cpApplyService;
|
||||||
private final OfficialNoticeClient officialNoticeClient;
|
private final ImMessageClient imMessageClient;
|
||||||
private final WalletGoldClient walletGoldClient;
|
private final WalletGoldClient walletGoldClient;
|
||||||
private final UserMqMessageService userMqMessageService;
|
private final UserMqMessageService userMqMessageService;
|
||||||
private final CpRelationshipService cpRelationshipService;
|
private final CpRelationshipService cpRelationshipService;
|
||||||
@ -69,8 +64,20 @@ public class SendCpApplyCmdExe {
|
|||||||
return autoCreateFromCpGift(sendUserId, acceptUserId, sysOrigin, CpRelationshipType.CP.name());
|
return autoCreateFromCpGift(sendUserId, acceptUserId, sysOrigin, CpRelationshipType.CP.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean autoCreateFromCpGift(Long sendUserId, Long acceptUserId, String sysOrigin,
|
||||||
|
BigDecimal applyConsumeGold) {
|
||||||
|
return autoCreateFromCpGift(sendUserId, acceptUserId, sysOrigin, CpRelationshipType.CP.name(),
|
||||||
|
applyConsumeGold);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean autoCreateFromCpGift(Long sendUserId, Long acceptUserId, String sysOrigin,
|
public boolean autoCreateFromCpGift(Long sendUserId, Long acceptUserId, String sysOrigin,
|
||||||
String relationTypeValue) {
|
String relationTypeValue) {
|
||||||
|
return autoCreateFromCpGift(sendUserId, acceptUserId, sysOrigin, relationTypeValue,
|
||||||
|
BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean autoCreateFromCpGift(Long sendUserId, Long acceptUserId, String sysOrigin,
|
||||||
|
String relationTypeValue, BigDecimal applyConsumeGold) {
|
||||||
if (Objects.equals(sendUserId, acceptUserId)) {
|
if (Objects.equals(sendUserId, acceptUserId)) {
|
||||||
log.info(
|
log.info(
|
||||||
"[CP] skip auto create cp apply from self gift, sendUserId={}, relationType={}",
|
"[CP] skip auto create cp apply from self gift, sendUserId={}, relationType={}",
|
||||||
@ -78,7 +85,7 @@ public class SendCpApplyCmdExe {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
process(sendUserId, acceptUserId, sysOrigin, relationTypeValue, false);
|
process(sendUserId, acceptUserId, sysOrigin, relationTypeValue, false, applyConsumeGold);
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
log.info(
|
log.info(
|
||||||
@ -90,6 +97,11 @@ public class SendCpApplyCmdExe {
|
|||||||
|
|
||||||
private void process(Long sendUserId, Long acceptUserId, String sysOrigin, String relationTypeValue,
|
private void process(Long sendUserId, Long acceptUserId, String sysOrigin, String relationTypeValue,
|
||||||
boolean chargeGold) {
|
boolean chargeGold) {
|
||||||
|
process(sendUserId, acceptUserId, sysOrigin, relationTypeValue, chargeGold, BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void process(Long sendUserId, Long acceptUserId, String sysOrigin, String relationTypeValue,
|
||||||
|
boolean chargeGold, BigDecimal giftApplyConsumeGold) {
|
||||||
CpRelationshipType relationType = parseRelationType(relationTypeValue);
|
CpRelationshipType relationType = parseRelationType(relationTypeValue);
|
||||||
|
|
||||||
// 不可用操作自己
|
// 不可用操作自己
|
||||||
@ -111,10 +123,9 @@ public class SendCpApplyCmdExe {
|
|||||||
boolean isReconcile = Objects.nonNull(dismissingCp);
|
boolean isReconcile = Objects.nonNull(dismissingCp);
|
||||||
|
|
||||||
if (!isReconcile) {
|
if (!isReconcile) {
|
||||||
// 非复合申请:检查CP是否已存在
|
// 非复合申请:两人之间只能存在一种正常关系
|
||||||
ResponseAssert.isFalse(UserRelationErrorCode.ME_OR_YOU_CP_EXISTED,
|
ResponseAssert.isFalse(UserRelationErrorCode.ME_OR_YOU_CP_EXISTED,
|
||||||
cpRelationshipService
|
cpRelationshipService.existsRelationship(sendUserId, acceptUserId));
|
||||||
.existsCp(sendUserId, acceptUserId, relationType.name()));
|
|
||||||
|
|
||||||
validateRelationLimit(sendUserId, acceptUserId, relationType);
|
validateRelationLimit(sendUserId, acceptUserId, relationType);
|
||||||
}
|
}
|
||||||
@ -127,7 +138,7 @@ public class SendCpApplyCmdExe {
|
|||||||
ResponseAssert.isFalse(UserRelationErrorCode.OTHER_SIDE_ALREADY_APPLIED,
|
ResponseAssert.isFalse(UserRelationErrorCode.OTHER_SIDE_ALREADY_APPLIED,
|
||||||
cpApplyService.exists(sendUserId, acceptUserId, relationType.name()));
|
cpApplyService.exists(sendUserId, acceptUserId, relationType.name()));
|
||||||
|
|
||||||
BigDecimal applyConsumeGold = BigDecimal.ZERO;
|
BigDecimal applyConsumeGold = normalizeApplyConsumeGold(giftApplyConsumeGold);
|
||||||
if (chargeGold) {
|
if (chargeGold) {
|
||||||
WalletReceiptResDTO receipt = ResponseAssert.requiredSuccess(
|
WalletReceiptResDTO receipt = ResponseAssert.requiredSuccess(
|
||||||
walletGoldClient.changeBalance(GoldReceiptCmd.builder()
|
walletGoldClient.changeBalance(GoldReceiptCmd.builder()
|
||||||
@ -159,21 +170,8 @@ public class SendCpApplyCmdExe {
|
|||||||
|
|
||||||
cpApplyService.save(cpApply);
|
cpApplyService.save(cpApply);
|
||||||
|
|
||||||
Map<Object, Object> map = OfficialNoticeUtils.buildUserProfile(userProfile);
|
sendCpBuildIm(sendUserId, acceptUserId, cpApply.getId(), userProfile, acceptUserProfile,
|
||||||
map.put("applyType", isReconcile ? "RECONCILE" : "APPLY");
|
isReconcile, relationType, applyText);
|
||||||
map.put("relationType", relationType.name());
|
|
||||||
map.put("acceptUserId", acceptUserProfile.getId());
|
|
||||||
map.put("acceptAccount", acceptUserProfile.getAccount());
|
|
||||||
map.put("acceptActualAccount", acceptUserProfile.actualAccount());
|
|
||||||
map.put("acceptNickname", acceptUserProfile.getUserNickname());
|
|
||||||
map.put("acceptUserAvatar", acceptUserProfile.getUserAvatar());
|
|
||||||
officialNoticeClient.send(NoticeExtTemplateTypeCmd.builder()
|
|
||||||
.toAccount(acceptUserId)
|
|
||||||
.noticeType(OfficialNoticeTypeEnum.CP_BUILD)
|
|
||||||
.templateParam(map)
|
|
||||||
.expand(cpApply.getId())
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
|
|
||||||
userMqMessageService.cpApplyDelayed(
|
userMqMessageService.cpApplyDelayed(
|
||||||
new CpApplyEvent()
|
new CpApplyEvent()
|
||||||
@ -182,6 +180,20 @@ public class SendCpApplyCmdExe {
|
|||||||
TimestampUtils.nowPlusDays(1));
|
TimestampUtils.nowPlusDays(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendCpBuildIm(Long sendUserId, Long acceptUserId, Long applyId,
|
||||||
|
UserProfileDTO userProfile, UserProfileDTO acceptUserProfile, boolean isReconcile,
|
||||||
|
CpRelationshipType relationType, String title) {
|
||||||
|
imMessageClient.sendCustomMessage(CpRelationC2cNoticeUtils.buildInvitePending(sendUserId,
|
||||||
|
acceptUserId, applyId, userProfile, acceptUserProfile, isReconcile, relationType, title));
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal normalizeApplyConsumeGold(BigDecimal applyConsumeGold) {
|
||||||
|
if (Objects.isNull(applyConsumeGold) || applyConsumeGold.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
return applyConsumeGold;
|
||||||
|
}
|
||||||
|
|
||||||
private void validateRelationLimit(Long sendUserId, Long acceptUserId,
|
private void validateRelationLimit(Long sendUserId, Long acceptUserId,
|
||||||
CpRelationshipType relationType) {
|
CpRelationshipType relationType) {
|
||||||
int maxCount = relationMaxCount(relationType);
|
int maxCount = relationMaxCount(relationType);
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
package com.red.circle.other.app.command.user.query;
|
package com.red.circle.other.app.command.user.query;
|
||||||
|
|
||||||
|
import com.red.circle.other.app.common.cp.CpRelationGoldConfig;
|
||||||
import com.red.circle.other.app.dto.clientobject.user.relation.cp.CpRightsConfigCO;
|
import com.red.circle.other.app.dto.clientobject.user.relation.cp.CpRightsConfigCO;
|
||||||
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpRightsConfigQueryCmd;
|
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpRightsConfigQueryCmd;
|
||||||
|
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
|
||||||
import com.red.circle.other.infra.database.rds.entity.user.user.CpCabinConfig;
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpCabinConfig;
|
||||||
import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship;
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship;
|
||||||
import com.red.circle.other.infra.database.rds.entity.user.user.CpValue;
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpValue;
|
||||||
@ -32,6 +34,7 @@ public class UserCpRightsConfigQueryExe {
|
|||||||
private final CpCabinConfigService cpCabinConfigService;
|
private final CpCabinConfigService cpCabinConfigService;
|
||||||
private final CpRelationshipService cpRelationshipService;
|
private final CpRelationshipService cpRelationshipService;
|
||||||
private final CpValueService cpValueService;
|
private final CpValueService cpValueService;
|
||||||
|
private final EnumConfigCacheService enumConfigCacheService;
|
||||||
|
|
||||||
public CpRightsConfigCO execute(CpRightsConfigQueryCmd cmd) {
|
public CpRightsConfigCO execute(CpRightsConfigQueryCmd cmd) {
|
||||||
String relationType = CpRelationshipType.normalize(cmd.getRelationType());
|
String relationType = CpRelationshipType.normalize(cmd.getRelationType());
|
||||||
@ -47,10 +50,16 @@ public class UserCpRightsConfigQueryExe {
|
|||||||
.relationshipStatus(Objects.isNull(relationship) ? RELATIONSHIP_STATUS_NONE
|
.relationshipStatus(Objects.isNull(relationship) ? RELATIONSHIP_STATUS_NONE
|
||||||
: relationship.getStatus())
|
: relationship.getStatus())
|
||||||
.intimacyValue(intimacyValue)
|
.intimacyValue(intimacyValue)
|
||||||
|
.dismissConsumeGold(dismissConsumeGold(relationType, cmd.requireReqSysOrigin()))
|
||||||
.levels(toLevels(relationType, configs, Objects.nonNull(relationship), intimacyValue))
|
.levels(toLevels(relationType, configs, Objects.nonNull(relationship), intimacyValue))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Long dismissConsumeGold(String relationType, String sysOrigin) {
|
||||||
|
return CpRelationGoldConfig.defaultGoldLong(enumConfigCacheService.getValueBigDecimal(
|
||||||
|
CpRelationGoldConfig.dismissConsumeGoldKey(relationType), sysOrigin));
|
||||||
|
}
|
||||||
|
|
||||||
private CpRelationship findRelationship(Long reqUserId, Long cpUserId, String relationType) {
|
private CpRelationship findRelationship(Long reqUserId, Long cpUserId, String relationType) {
|
||||||
if (Objects.isNull(reqUserId)) {
|
if (Objects.isNull(reqUserId)) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -0,0 +1,205 @@
|
|||||||
|
package com.red.circle.other.app.common.cp;
|
||||||
|
|
||||||
|
import com.red.circle.external.inner.model.cmd.message.CustomC2cMsgBodyCmd;
|
||||||
|
import com.red.circle.other.domain.model.user.UserProfile;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
||||||
|
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
|
||||||
|
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||||
|
import com.red.circle.tool.core.json.JacksonUtils;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
public final class CpRelationC2cNoticeUtils {
|
||||||
|
|
||||||
|
public static final String NOTICE_TYPE = "CP_BUILD";
|
||||||
|
public static final String ACTION_INVITE_PENDING = "INVITE_PENDING";
|
||||||
|
public static final String ACTION_RELATION_ESTABLISHED = "RELATION_ESTABLISHED";
|
||||||
|
public static final String ACTION_RELATION_REJECTED = "RELATION_REJECTED";
|
||||||
|
public static final String ACTION_RELATION_EXPIRED = "RELATION_EXPIRED";
|
||||||
|
|
||||||
|
private CpRelationC2cNoticeUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomC2cMsgBodyCmd buildInvitePending(Long fromUserId, Long toUserId,
|
||||||
|
Long applyId, UserProfileDTO senderProfile, UserProfileDTO acceptProfile,
|
||||||
|
boolean isReconcile, CpRelationshipType relationType, String title) {
|
||||||
|
Map<String, Object> content = senderContent(senderProfile);
|
||||||
|
content.put("applyType", isReconcile ? "RECONCILE" : "APPLY");
|
||||||
|
content.put("relationType", relationType.name());
|
||||||
|
putAcceptProfile(content, acceptProfile);
|
||||||
|
|
||||||
|
Map<String, Object> payload = basePayload(applyId, relationType.name(), title,
|
||||||
|
ACTION_INVITE_PENDING, "PENDING", content);
|
||||||
|
putSenderProfile(payload, senderProfile);
|
||||||
|
putAcceptProfile(payload, acceptProfile);
|
||||||
|
return buildMessage(fromUserId, toUserId, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomC2cMsgBodyCmd buildAccepted(CpApply cpApply, UserProfile senderProfile,
|
||||||
|
UserProfile acceptProfile) {
|
||||||
|
String relationType = CpRelationshipType.normalize(cpApply.getRelationType());
|
||||||
|
String title = "User " + displayName(acceptProfile) + " accepted your "
|
||||||
|
+ relationType.toLowerCase() + " invitation.";
|
||||||
|
Map<String, Object> content = senderContent(senderProfile);
|
||||||
|
content.put("applyType", "APPLY");
|
||||||
|
content.put("relationType", relationType);
|
||||||
|
putAcceptProfile(content, acceptProfile);
|
||||||
|
|
||||||
|
Map<String, Object> payload = basePayload(cpApply.getId(), relationType, title,
|
||||||
|
ACTION_RELATION_ESTABLISHED, "ACCEPTED", content);
|
||||||
|
payload.put("agree", true);
|
||||||
|
putSenderProfile(payload, senderProfile);
|
||||||
|
putAcceptProfile(payload, acceptProfile);
|
||||||
|
return buildMessage(cpApply.getAcceptApplyUserId(), cpApply.getSendApplyUserId(), payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomC2cMsgBodyCmd buildRejected(CpApply cpApply, UserProfile senderProfile,
|
||||||
|
UserProfile acceptProfile) {
|
||||||
|
String relationType = CpRelationshipType.normalize(cpApply.getRelationType());
|
||||||
|
String title = "User " + displayName(acceptProfile) + " declined your "
|
||||||
|
+ relationType.toLowerCase() + " invitation.";
|
||||||
|
Map<String, Object> content = senderContent(senderProfile);
|
||||||
|
content.put("applyType", "APPLY");
|
||||||
|
content.put("relationType", relationType);
|
||||||
|
putAcceptProfile(content, acceptProfile);
|
||||||
|
|
||||||
|
Map<String, Object> payload = basePayload(cpApply.getId(), relationType, title,
|
||||||
|
ACTION_RELATION_REJECTED, "REJECTED", content);
|
||||||
|
payload.put("agree", false);
|
||||||
|
putSenderProfile(payload, senderProfile);
|
||||||
|
putAcceptProfile(payload, acceptProfile);
|
||||||
|
return buildMessage(cpApply.getAcceptApplyUserId(), cpApply.getSendApplyUserId(), payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomC2cMsgBodyCmd buildExpiredToAcceptUser(CpApply cpApply,
|
||||||
|
UserProfile senderProfile, UserProfile acceptProfile) {
|
||||||
|
return buildExpired(cpApply, senderProfile, acceptProfile, cpApply.getSendApplyUserId(),
|
||||||
|
cpApply.getAcceptApplyUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomC2cMsgBodyCmd buildExpiredToSendUser(CpApply cpApply,
|
||||||
|
UserProfile senderProfile, UserProfile acceptProfile) {
|
||||||
|
return buildExpired(cpApply, senderProfile, acceptProfile, cpApply.getAcceptApplyUserId(),
|
||||||
|
cpApply.getSendApplyUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CustomC2cMsgBodyCmd buildExpired(CpApply cpApply, UserProfile senderProfile,
|
||||||
|
UserProfile acceptProfile, Long fromUserId, Long toUserId) {
|
||||||
|
String relationType = CpRelationshipType.normalize(cpApply.getRelationType());
|
||||||
|
String title = "Your " + relationType.toLowerCase() + " invitation expired.";
|
||||||
|
Map<String, Object> content = senderContent(senderProfile);
|
||||||
|
content.put("applyType", "APPLY");
|
||||||
|
content.put("relationType", relationType);
|
||||||
|
putAcceptProfile(content, acceptProfile);
|
||||||
|
|
||||||
|
Map<String, Object> payload = basePayload(cpApply.getId(), relationType, title,
|
||||||
|
ACTION_RELATION_EXPIRED, "EXPIRED", content);
|
||||||
|
payload.put("expired", true);
|
||||||
|
putSenderProfile(payload, senderProfile);
|
||||||
|
putAcceptProfile(payload, acceptProfile);
|
||||||
|
return buildMessage(fromUserId, toUserId, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, Object> basePayload(Long applyId, String relationType, String title,
|
||||||
|
String action, String status, Map<String, Object> content) {
|
||||||
|
Map<String, Object> payload = new LinkedHashMap<>();
|
||||||
|
payload.put("noticeType", NOTICE_TYPE);
|
||||||
|
payload.put("type", NOTICE_TYPE);
|
||||||
|
payload.put("noticeAction", action);
|
||||||
|
payload.put("action", action);
|
||||||
|
payload.put("status", status);
|
||||||
|
payload.put("result", status);
|
||||||
|
payload.put("state", status);
|
||||||
|
payload.put("title", title);
|
||||||
|
payload.put("content", JacksonUtils.toJson(content));
|
||||||
|
payload.put("expand", applyId);
|
||||||
|
payload.put("applyId", applyId);
|
||||||
|
payload.put("relationType", relationType);
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CustomC2cMsgBodyCmd buildMessage(Long fromUserId, Long toUserId,
|
||||||
|
Map<String, Object> payload) {
|
||||||
|
return CustomC2cMsgBodyCmd.builder()
|
||||||
|
.fromAccount(fromUserId)
|
||||||
|
.toAccount(toUserId)
|
||||||
|
.desc(NOTICE_TYPE)
|
||||||
|
.data(payload)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, Object> senderContent(UserProfileDTO userProfile) {
|
||||||
|
Map<String, Object> content = new LinkedHashMap<>();
|
||||||
|
content.put("userNickname", userProfile.getUserNickname());
|
||||||
|
content.put("account", userProfile.getAccount());
|
||||||
|
content.put("actualAccount", userProfile.actualAccount());
|
||||||
|
content.put("userAvatar", userProfile.getUserAvatar());
|
||||||
|
content.put("countryCode", userProfile.getCountryCode());
|
||||||
|
content.put("countryName", userProfile.getCountryName());
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, Object> senderContent(UserProfile userProfile) {
|
||||||
|
Map<String, Object> content = new LinkedHashMap<>();
|
||||||
|
content.put("userNickname", Objects.nonNull(userProfile) ? userProfile.getUserNickname() : null);
|
||||||
|
content.put("account", Objects.nonNull(userProfile) ? userProfile.getAccount() : null);
|
||||||
|
content.put("actualAccount", Objects.nonNull(userProfile) ? userProfile.getActualAccount() : null);
|
||||||
|
content.put("userAvatar", Objects.nonNull(userProfile) ? userProfile.getUserAvatar() : null);
|
||||||
|
content.put("countryCode", Objects.nonNull(userProfile) ? userProfile.getCountryCode() : null);
|
||||||
|
content.put("countryName", Objects.nonNull(userProfile) ? userProfile.getCountryName() : null);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void putSenderProfile(Map<String, Object> payload, UserProfileDTO userProfile) {
|
||||||
|
payload.put("account", userProfile.getAccount());
|
||||||
|
payload.put("actualAccount", userProfile.actualAccount());
|
||||||
|
payload.put("userNickname", userProfile.getUserNickname());
|
||||||
|
payload.put("userAvatar", userProfile.getUserAvatar());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void putSenderProfile(Map<String, Object> payload, UserProfile userProfile) {
|
||||||
|
if (Objects.isNull(userProfile)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
payload.put("account", userProfile.getAccount());
|
||||||
|
payload.put("actualAccount", userProfile.getActualAccount());
|
||||||
|
payload.put("userNickname", userProfile.getUserNickname());
|
||||||
|
payload.put("userAvatar", userProfile.getUserAvatar());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void putAcceptProfile(Map<String, Object> payload, UserProfileDTO userProfile) {
|
||||||
|
payload.put("acceptUserId", userProfile.getId());
|
||||||
|
payload.put("acceptAccount", userProfile.getAccount());
|
||||||
|
payload.put("acceptActualAccount", userProfile.actualAccount());
|
||||||
|
payload.put("acceptNickname", userProfile.getUserNickname());
|
||||||
|
payload.put("acceptUserNickname", userProfile.getUserNickname());
|
||||||
|
payload.put("acceptUserAvatar", userProfile.getUserAvatar());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void putAcceptProfile(Map<String, Object> payload, UserProfile userProfile) {
|
||||||
|
if (Objects.isNull(userProfile)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
payload.put("acceptUserId", userProfile.getId());
|
||||||
|
payload.put("acceptAccount", userProfile.getAccount());
|
||||||
|
payload.put("acceptActualAccount", userProfile.getActualAccount());
|
||||||
|
payload.put("acceptNickname", userProfile.getUserNickname());
|
||||||
|
payload.put("acceptUserNickname", userProfile.getUserNickname());
|
||||||
|
payload.put("acceptUserAvatar", userProfile.getUserAvatar());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String displayName(UserProfile userProfile) {
|
||||||
|
if (Objects.isNull(userProfile)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(userProfile.getUserNickname())) {
|
||||||
|
return userProfile.getUserNickname();
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(userProfile.getAccount())) {
|
||||||
|
return userProfile.getAccount();
|
||||||
|
}
|
||||||
|
return Objects.toString(userProfile.getId(), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package com.red.circle.other.app.common.cp;
|
||||||
|
|
||||||
|
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
|
||||||
|
import com.red.circle.other.inner.enums.config.EnumConfigKey;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relation gold config helpers.
|
||||||
|
*/
|
||||||
|
public final class CpRelationGoldConfig {
|
||||||
|
|
||||||
|
private CpRelationGoldConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EnumConfigKey dismissConsumeGoldKey(String relationType) {
|
||||||
|
CpRelationshipType normalizedType = CpRelationshipType.of(relationType);
|
||||||
|
return switch (normalizedType) {
|
||||||
|
case BROTHER -> EnumConfigKey.BROTHER_DISMISS_CONSUME_GOLD;
|
||||||
|
case SISTERS -> EnumConfigKey.SISTERS_DISMISS_CONSUME_GOLD;
|
||||||
|
case CP -> EnumConfigKey.CP_DISMISS_CONSUME_GOLD;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigDecimal defaultGold(BigDecimal gold) {
|
||||||
|
return Objects.isNull(gold) ? BigDecimal.ZERO : gold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Long defaultGoldLong(BigDecimal gold) {
|
||||||
|
return defaultGold(gold).longValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -379,15 +379,15 @@ public class GiftCountStrategy implements GiftStrategy {
|
|||||||
if (CollectionUtils.isEmpty(runningWater.getAcceptUsers())) {
|
if (CollectionUtils.isEmpty(runningWater.getAcceptUsers())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String relationType = CpRelationshipType.normalize(
|
String relationType = resolveCpGiftRelationType(runningWater);
|
||||||
runningWater.getGiftValue().getCpRelationType());
|
BigDecimal applyConsumeGold = cpGiftApplyConsumeGold(runningWater.getGiftValue());
|
||||||
runningWater.getAcceptUsers().forEach(accept -> {
|
runningWater.getAcceptUsers().forEach(accept -> {
|
||||||
if (Objects.equals(runningWater.getUserId(), accept.getAcceptUserId())) {
|
if (Objects.equals(runningWater.getUserId(), accept.getAcceptUserId())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sendCpApplyCmdExe.autoCreateFromCpGift(
|
sendCpApplyCmdExe.autoCreateFromCpGift(
|
||||||
runningWater.getUserId(), accept.getAcceptUserId(), runningWater.getSysOrigin(),
|
runningWater.getUserId(), accept.getAcceptUserId(), runningWater.getSysOrigin(),
|
||||||
relationType);
|
relationType, applyConsumeGold);
|
||||||
});
|
});
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
log.warn("[CP] skip auto create cp apply from gift, runningWaterId={}, giftId={}, sendUserId={}, reason={}",
|
log.warn("[CP] skip auto create cp apply from gift, runningWaterId={}, giftId={}, sendUserId={}, reason={}",
|
||||||
@ -398,6 +398,44 @@ public class GiftCountStrategy implements GiftStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resolveCpGiftRelationType(GiftGiveRunningWater runningWater) {
|
||||||
|
String relationType = Objects.nonNull(runningWater.getGiftValue())
|
||||||
|
? runningWater.getGiftValue().getCpRelationType()
|
||||||
|
: null;
|
||||||
|
if (StringUtils.isNotBlank(relationType)) {
|
||||||
|
return CpRelationshipType.normalize(relationType);
|
||||||
|
}
|
||||||
|
String configuredRelationType = cpRelationTypeFromGiftConfig(runningWater);
|
||||||
|
return CpRelationshipType.normalize(configuredRelationType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String cpRelationTypeFromGiftConfig(GiftGiveRunningWater runningWater) {
|
||||||
|
if (Objects.isNull(runningWater) || Objects.isNull(runningWater.getGiftId())) {
|
||||||
|
log.warn("[CP] cp gift relation type missing and giftId missing, fallback CP. runningWaterId={}",
|
||||||
|
Objects.nonNull(runningWater) ? runningWater.getId() : null);
|
||||||
|
return CpRelationshipType.CP.name();
|
||||||
|
}
|
||||||
|
GiftConfigDTO giftConfig = cacheGiftConfigManagerService.getById(runningWater.getGiftId());
|
||||||
|
if (Objects.nonNull(giftConfig) && StringUtils.isNotBlank(giftConfig.getCpRelationType())) {
|
||||||
|
return giftConfig.getCpRelationType();
|
||||||
|
}
|
||||||
|
log.warn("[CP] cp gift relation type missing from running water and config, fallback CP. runningWaterId={}, giftId={}",
|
||||||
|
runningWater.getId(), runningWater.getGiftId());
|
||||||
|
return CpRelationshipType.CP.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal cpGiftApplyConsumeGold(GiftValue giftValue) {
|
||||||
|
if (Objects.isNull(giftValue) || !GiftCurrencyType.GOLD.eq(giftValue.getCurrencyType())
|
||||||
|
|| Objects.equals(giftValue.getBag(), Boolean.TRUE)) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
BigDecimal giftGold = giftValue.getGiftValue();
|
||||||
|
if (Objects.isNull(giftGold) || giftGold.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
return giftGold;
|
||||||
|
}
|
||||||
|
|
||||||
private void sendCpBlessNotice(GiftGiveRunningWater runningWater, CpRelationship cpRelationship,
|
private void sendCpBlessNotice(GiftGiveRunningWater runningWater, CpRelationship cpRelationship,
|
||||||
GiftConfigDTO giftConfig) {
|
GiftConfigDTO giftConfig) {
|
||||||
UserProfile userProfile = userProfileRepository.getByUserId(runningWater.getUserId());
|
UserProfile userProfile = userProfileRepository.getByUserId(runningWater.getUserId());
|
||||||
|
|||||||
@ -6,8 +6,12 @@ import com.red.circle.component.mq.config.RocketMqMessageListener;
|
|||||||
import com.red.circle.component.mq.service.Action;
|
import com.red.circle.component.mq.service.Action;
|
||||||
import com.red.circle.component.mq.service.ConsumerMessage;
|
import com.red.circle.component.mq.service.ConsumerMessage;
|
||||||
import com.red.circle.component.mq.service.MessageListener;
|
import com.red.circle.component.mq.service.MessageListener;
|
||||||
|
import com.red.circle.external.inner.endpoint.message.ImMessageClient;
|
||||||
import com.red.circle.mq.business.model.event.user.CpApplyEvent;
|
import com.red.circle.mq.business.model.event.user.CpApplyEvent;
|
||||||
import com.red.circle.mq.rocket.business.streams.CpApplySink;
|
import com.red.circle.mq.rocket.business.streams.CpApplySink;
|
||||||
|
import com.red.circle.other.app.common.cp.CpRelationC2cNoticeUtils;
|
||||||
|
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||||
|
import com.red.circle.other.domain.model.user.UserProfile;
|
||||||
import com.red.circle.tool.core.collection.CollectionUtils;
|
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||||
import com.red.circle.tool.core.json.JacksonUtils;
|
import com.red.circle.tool.core.json.JacksonUtils;
|
||||||
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
||||||
@ -16,7 +20,9 @@ import com.red.circle.other.infra.enums.user.user.CpApplyStatus;
|
|||||||
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
||||||
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
|
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
|
||||||
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -32,6 +38,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
public class CpApplyListener implements MessageListener {
|
public class CpApplyListener implements MessageListener {
|
||||||
|
|
||||||
private final CpApplyService cpApplyService;
|
private final CpApplyService cpApplyService;
|
||||||
|
private final ImMessageClient imMessageClient;
|
||||||
|
private final UserProfileGateway userProfileGateway;
|
||||||
private final WalletGoldClient walletGoldClient;
|
private final WalletGoldClient walletGoldClient;
|
||||||
private final MessageEventProcess messageEventProcess;
|
private final MessageEventProcess messageEventProcess;
|
||||||
|
|
||||||
@ -61,20 +69,36 @@ public class CpApplyListener implements MessageListener {
|
|||||||
|
|
||||||
// 等待超时
|
// 等待超时
|
||||||
if (Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name())) {
|
if (Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name())) {
|
||||||
reimburse(eventBody, cpApply);
|
reimburse(eventBody, cpApply, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkReimburse(CpApplyEvent param, CpApply cpApply) {
|
private void checkReimburse(CpApplyEvent param, CpApply cpApply) {
|
||||||
List<CpApply> cpApplies = cpApplyService.listRefuse(cpApply.getAcceptApplyUserId());
|
Map<Long, CpApply> applyMap = new LinkedHashMap<>();
|
||||||
|
addReimburseApplies(applyMap, cpApplyService.listRefuse(cpApply.getAcceptApplyUserId()));
|
||||||
|
addReimburseApplies(applyMap, cpApplyService.listRefuseBetweenUsers(cpApply.getSendApplyUserId(),
|
||||||
|
cpApply.getAcceptApplyUserId()));
|
||||||
|
if (applyMap.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applyMap.values().forEach(apply -> reimburse(param, apply, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addReimburseApplies(Map<Long, CpApply> applyMap, List<CpApply> cpApplies) {
|
||||||
if (CollectionUtils.isEmpty(cpApplies)) {
|
if (CollectionUtils.isEmpty(cpApplies)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cpApplies.forEach(apply -> reimburse(param, apply));
|
cpApplies.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(apply -> Objects.nonNull(apply.getId()))
|
||||||
|
.forEach(apply -> applyMap.putIfAbsent(apply.getId(), apply));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reimburse(CpApplyEvent param, CpApply cpApply) {
|
private void reimburse(CpApplyEvent param, CpApply cpApply, boolean expired) {
|
||||||
|
if (expired) {
|
||||||
|
sendExpiredNotice(cpApply);
|
||||||
|
}
|
||||||
if (Objects.isNull(cpApply.getApplyConsumeGold())
|
if (Objects.isNull(cpApply.getApplyConsumeGold())
|
||||||
|| cpApply.getApplyConsumeGold().signum() <= 0) {
|
|| cpApply.getApplyConsumeGold().signum() <= 0) {
|
||||||
cpApplyService.changeStatusById(cpApply.getId(), CpApplyStatus.REIMBURSE);
|
cpApplyService.changeStatusById(cpApply.getId(), CpApplyStatus.REIMBURSE);
|
||||||
@ -91,4 +115,23 @@ public class CpApplyListener implements MessageListener {
|
|||||||
cpApplyService.changeStatusById(cpApply.getId(), CpApplyStatus.REIMBURSE);
|
cpApplyService.changeStatusById(cpApply.getId(), CpApplyStatus.REIMBURSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendExpiredNotice(CpApply cpApply) {
|
||||||
|
try {
|
||||||
|
UserProfile senderProfile = userProfileGateway.getByUserId(cpApply.getSendApplyUserId());
|
||||||
|
UserProfile acceptProfile = userProfileGateway.getByUserId(cpApply.getAcceptApplyUserId());
|
||||||
|
if (Objects.isNull(senderProfile) || Objects.isNull(acceptProfile)) {
|
||||||
|
log.info("[CP] skip expired c2c notice, applyId={}, senderProfile={}, acceptProfile={}",
|
||||||
|
cpApply.getId(), Objects.nonNull(senderProfile), Objects.nonNull(acceptProfile));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
imMessageClient.sendCustomMessage(
|
||||||
|
CpRelationC2cNoticeUtils.buildExpiredToAcceptUser(cpApply, senderProfile, acceptProfile));
|
||||||
|
imMessageClient.sendCustomMessage(
|
||||||
|
CpRelationC2cNoticeUtils.buildExpiredToSendUser(cpApply, senderProfile, acceptProfile));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("[CP] send expired c2c notice failed, applyId={}, reason={}", cpApply.getId(),
|
||||||
|
ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,15 +3,19 @@ package com.red.circle.other.app.command.user;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
|
||||||
import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient;
|
import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient;
|
||||||
|
import com.red.circle.framework.dto.ResultResponse;
|
||||||
import com.red.circle.other.app.dto.clientobject.user.relation.cp.CpDismissApplyCO;
|
import com.red.circle.other.app.dto.clientobject.user.relation.cp.CpDismissApplyCO;
|
||||||
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyDismissCmd;
|
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyDismissCmd;
|
||||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||||
import com.red.circle.other.domain.model.user.UserProfile;
|
import com.red.circle.other.domain.model.user.UserProfile;
|
||||||
import com.red.circle.other.infra.common.user.UserGiftBackpackCommon;
|
import com.red.circle.other.infra.common.user.UserGiftBackpackCommon;
|
||||||
|
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
|
||||||
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
|
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
|
||||||
import com.red.circle.other.infra.database.cache.service.user.UserCpValueCacheService;
|
import com.red.circle.other.infra.database.cache.service.user.UserCpValueCacheService;
|
||||||
import com.red.circle.other.infra.database.mongo.service.user.count.WeekCpValueCountService;
|
import com.red.circle.other.infra.database.mongo.service.user.count.WeekCpValueCountService;
|
||||||
@ -22,6 +26,11 @@ import com.red.circle.other.infra.database.rds.service.user.user.CpCabinAchieveS
|
|||||||
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
|
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
|
||||||
import com.red.circle.other.infra.database.rds.service.user.user.CpValueService;
|
import com.red.circle.other.infra.database.rds.service.user.user.CpValueService;
|
||||||
import com.red.circle.other.infra.enums.user.user.CpRelationshipStatus;
|
import com.red.circle.other.infra.enums.user.user.CpRelationshipStatus;
|
||||||
|
import com.red.circle.other.inner.enums.config.EnumConfigKey;
|
||||||
|
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
||||||
|
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
|
||||||
|
import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@ -56,6 +65,7 @@ class DismissCpApplyCmdExeTest {
|
|||||||
verify(fixture.cpCabinAchieveService).deleteByCpValId(3001L);
|
verify(fixture.cpCabinAchieveService).deleteByCpValId(3001L);
|
||||||
verify(fixture.cpBlessRecordService).deleteByCpValId(3001L);
|
verify(fixture.cpBlessRecordService).deleteByCpValId(3001L);
|
||||||
verify(fixture.cpRelationshipCacheService).remove(Arrays.asList(1001L, 2001L));
|
verify(fixture.cpRelationshipCacheService).remove(Arrays.asList(1001L, 2001L));
|
||||||
|
verify(fixture.walletGoldClient).changeBalance(any(GoldReceiptCmd.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -75,13 +85,16 @@ class DismissCpApplyCmdExeTest {
|
|||||||
assertEquals("NONE", result.getStatus());
|
assertEquals("NONE", result.getStatus());
|
||||||
assertEquals(0L, result.getDismissRemainSeconds());
|
assertEquals(0L, result.getDismissRemainSeconds());
|
||||||
verify(fixture.cpRelationshipService).deleteByUserPair(1001L, 2001L, "CP");
|
verify(fixture.cpRelationshipService).deleteByUserPair(1001L, 2001L, "CP");
|
||||||
|
verify(fixture.walletGoldClient, never()).changeBalance(any(GoldReceiptCmd.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CpRelationship relationship() {
|
private static CpRelationship relationship() {
|
||||||
return new CpRelationship()
|
return new CpRelationship()
|
||||||
|
.setId(4001L)
|
||||||
.setUserId(1001L)
|
.setUserId(1001L)
|
||||||
.setCpUserId(2001L)
|
.setCpUserId(2001L)
|
||||||
.setCpValId(3001L)
|
.setCpValId(3001L)
|
||||||
|
.setSysOrigin("LIKEI")
|
||||||
.setRelationType("CP")
|
.setRelationType("CP")
|
||||||
.setStatus(CpRelationshipStatus.NORMAL.name());
|
.setStatus(CpRelationshipStatus.NORMAL.name());
|
||||||
}
|
}
|
||||||
@ -110,6 +123,8 @@ class DismissCpApplyCmdExeTest {
|
|||||||
private final CpCabinAchieveService cpCabinAchieveService = mock(CpCabinAchieveService.class);
|
private final CpCabinAchieveService cpCabinAchieveService = mock(CpCabinAchieveService.class);
|
||||||
private final CpRelationshipCacheService cpRelationshipCacheService = mock(
|
private final CpRelationshipCacheService cpRelationshipCacheService = mock(
|
||||||
CpRelationshipCacheService.class);
|
CpRelationshipCacheService.class);
|
||||||
|
private final WalletGoldClient walletGoldClient = mock(WalletGoldClient.class);
|
||||||
|
private final EnumConfigCacheService enumConfigCacheService = mock(EnumConfigCacheService.class);
|
||||||
private final DismissCpApplyCmdExe exe;
|
private final DismissCpApplyCmdExe exe;
|
||||||
|
|
||||||
private Fixture() {
|
private Fixture() {
|
||||||
@ -117,6 +132,11 @@ class DismissCpApplyCmdExeTest {
|
|||||||
UserGiftBackpackCommon userGiftBackpackCommon = mock(UserGiftBackpackCommon.class);
|
UserGiftBackpackCommon userGiftBackpackCommon = mock(UserGiftBackpackCommon.class);
|
||||||
UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
|
UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
|
||||||
when(userProfileGateway.getByUserId(1001L)).thenReturn(userProfile());
|
when(userProfileGateway.getByUserId(1001L)).thenReturn(userProfile());
|
||||||
|
when(enumConfigCacheService.getValueBigDecimal(
|
||||||
|
EnumConfigKey.CP_DISMISS_CONSUME_GOLD, "LIKEI"))
|
||||||
|
.thenReturn(BigDecimal.valueOf(100));
|
||||||
|
when(walletGoldClient.changeBalance(any(GoldReceiptCmd.class)))
|
||||||
|
.thenReturn(ResultResponse.success(new WalletReceiptResDTO()));
|
||||||
|
|
||||||
exe = new DismissCpApplyCmdExe(
|
exe = new DismissCpApplyCmdExe(
|
||||||
cpValueService,
|
cpValueService,
|
||||||
@ -129,7 +149,9 @@ class DismissCpApplyCmdExeTest {
|
|||||||
cpBlessRecordService,
|
cpBlessRecordService,
|
||||||
cpCabinAchieveService,
|
cpCabinAchieveService,
|
||||||
userProfileGateway,
|
userProfileGateway,
|
||||||
cpRelationshipCacheService);
|
cpRelationshipCacheService,
|
||||||
|
walletGoldClient,
|
||||||
|
enumConfigCacheService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,201 @@
|
|||||||
|
package com.red.circle.other.app.command.user;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.nullable;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import com.red.circle.external.inner.endpoint.message.ImMessageClient;
|
||||||
|
import com.red.circle.external.inner.model.cmd.message.CustomC2cMsgBodyCmd;
|
||||||
|
import com.red.circle.framework.core.dto.ReqSysOrigin;
|
||||||
|
import com.red.circle.framework.dto.ResultResponse;
|
||||||
|
import com.red.circle.mq.business.model.event.user.CpApplyEvent;
|
||||||
|
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
|
||||||
|
import com.red.circle.other.app.common.cp.CpRelationBroadcastMqClient;
|
||||||
|
import com.red.circle.other.app.dto.cmd.user.relation.cp.ProcessApplyCmd;
|
||||||
|
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||||
|
import com.red.circle.other.domain.model.user.UserProfile;
|
||||||
|
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.user.user.CpValueService;
|
||||||
|
import com.red.circle.other.infra.enums.user.user.CpApplyStatus;
|
||||||
|
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
class ProcessCpApplyCmdTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void agreeBrotherApplyShouldCreateBrotherRelationship() {
|
||||||
|
Fixture fixture = new Fixture("BROTHER");
|
||||||
|
|
||||||
|
fixture.exe.execute(processCmd(true));
|
||||||
|
|
||||||
|
verify(fixture.cpRelationshipService).addCp(eq(1001L), eq(2001L),
|
||||||
|
nullable(Long.class), eq("LIKEI"), eq("BROTHER"));
|
||||||
|
verify(fixture.cpRelationBroadcastMqClient).publish("LIKEI", 3001L, 1001L, 2001L,
|
||||||
|
"BROTHER");
|
||||||
|
assertProcessMessage(fixture.sentCustomMessage(), "RELATION_ESTABLISHED", "ACCEPTED",
|
||||||
|
true, "BROTHER");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void agreeSistersApplyShouldCreateSistersRelationship() {
|
||||||
|
Fixture fixture = new Fixture("SISTERS");
|
||||||
|
|
||||||
|
fixture.exe.execute(processCmd(true));
|
||||||
|
|
||||||
|
verify(fixture.cpRelationshipService).addCp(eq(1001L), eq(2001L),
|
||||||
|
nullable(Long.class), eq("LIKEI"), eq("SISTERS"));
|
||||||
|
verify(fixture.cpRelationBroadcastMqClient).publish("LIKEI", 3001L, 1001L, 2001L,
|
||||||
|
"SISTERS");
|
||||||
|
assertProcessMessage(fixture.sentCustomMessage(), "RELATION_ESTABLISHED", "ACCEPTED",
|
||||||
|
true, "SISTERS");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rejectApplyShouldSendRejectedC2cMessageToSender() {
|
||||||
|
Fixture fixture = new Fixture("CP");
|
||||||
|
|
||||||
|
fixture.exe.execute(processCmd(false));
|
||||||
|
|
||||||
|
assertProcessMessage(fixture.sentCustomMessage(), "RELATION_REJECTED", "REJECTED",
|
||||||
|
false, "CP");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void agreeApplyShouldFailWhenPairAlreadyHasAnyRelation() {
|
||||||
|
Fixture fixture = new Fixture("BROTHER");
|
||||||
|
when(fixture.cpRelationshipService.existsRelationship(1001L, 2001L)).thenReturn(true);
|
||||||
|
|
||||||
|
Assertions.assertThrows(RuntimeException.class, () -> fixture.exe.execute(processCmd(true)));
|
||||||
|
|
||||||
|
verify(fixture.cpApplyService, never()).changeStatusById(eq(3001L),
|
||||||
|
any(CpApplyStatus.class));
|
||||||
|
verify(fixture.cpRelationshipService, never()).addCp(any(Long.class), any(Long.class),
|
||||||
|
nullable(Long.class), any(String.class), any(String.class));
|
||||||
|
verify(fixture.cpRelationBroadcastMqClient, never()).publish(any(String.class),
|
||||||
|
any(Long.class), any(Long.class), any(Long.class), any(String.class));
|
||||||
|
verify(fixture.imMessageClient, never()).sendCustomMessage(any(CustomC2cMsgBodyCmd.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void agreeApplyShouldRejectOtherWaitAppliesBetweenSameUsers() {
|
||||||
|
Fixture fixture = new Fixture("CP");
|
||||||
|
when(fixture.cpApplyService.refuseOtherWaitBetweenUsers(3001L, 1001L, 2001L))
|
||||||
|
.thenReturn(List.of(3002L, 3003L));
|
||||||
|
|
||||||
|
fixture.exe.execute(processCmd(true));
|
||||||
|
|
||||||
|
verify(fixture.cpApplyService).refuseOtherWaitBetweenUsers(3001L, 1001L, 2001L);
|
||||||
|
ArgumentCaptor<CpApplyEvent> eventCaptor = ArgumentCaptor.forClass(CpApplyEvent.class);
|
||||||
|
verify(fixture.userMqMessageService).cpApplyDelayed(eventCaptor.capture(),
|
||||||
|
any(Timestamp.class));
|
||||||
|
Assertions.assertEquals(3001L, eventCaptor.getValue().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProcessApplyCmd processCmd(boolean agree) {
|
||||||
|
ProcessApplyCmd cmd = new ProcessApplyCmd()
|
||||||
|
.setApplyId(3001L)
|
||||||
|
.setAgree(agree);
|
||||||
|
cmd.setReqUserId(2001L);
|
||||||
|
cmd.setReqSysOrigin(ReqSysOrigin.of("LIKEI", "LIKEI"));
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CpApply apply(String relationType) {
|
||||||
|
return new CpApply()
|
||||||
|
.setId(3001L)
|
||||||
|
.setSendApplyUserId(1001L)
|
||||||
|
.setAcceptApplyUserId(2001L)
|
||||||
|
.setRelationType(relationType)
|
||||||
|
.setStatus(CpApplyStatus.WAIT.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static void assertProcessMessage(CustomC2cMsgBodyCmd message, String action,
|
||||||
|
String status, Boolean agree, String relationType) {
|
||||||
|
Assertions.assertEquals("2001", message.getFromAccount());
|
||||||
|
Assertions.assertEquals("1001", message.getToAccount());
|
||||||
|
Assertions.assertEquals("CP_BUILD", message.getDesc());
|
||||||
|
Map<String, Object> data = (Map<String, Object>) message.getData();
|
||||||
|
Assertions.assertEquals("CP_BUILD", data.get("noticeType"));
|
||||||
|
Assertions.assertEquals(action, data.get("noticeAction"));
|
||||||
|
Assertions.assertEquals(action, data.get("action"));
|
||||||
|
Assertions.assertEquals(status, data.get("status"));
|
||||||
|
Assertions.assertEquals(status, data.get("result"));
|
||||||
|
Assertions.assertEquals(status, data.get("state"));
|
||||||
|
Assertions.assertEquals(agree, data.get("agree"));
|
||||||
|
Assertions.assertEquals(3001L, data.get("applyId"));
|
||||||
|
Assertions.assertEquals(relationType, data.get("relationType"));
|
||||||
|
Assertions.assertTrue(data.get("content").toString()
|
||||||
|
.contains("\"relationType\":\"" + relationType + "\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Fixture {
|
||||||
|
|
||||||
|
private final CpApplyService cpApplyService = mock(CpApplyService.class);
|
||||||
|
private final CpRelationshipService cpRelationshipService = mock(CpRelationshipService.class);
|
||||||
|
private final CpRelationBroadcastMqClient cpRelationBroadcastMqClient = mock(
|
||||||
|
CpRelationBroadcastMqClient.class);
|
||||||
|
private final ImMessageClient imMessageClient = mock(ImMessageClient.class);
|
||||||
|
private final UserMqMessageService userMqMessageService = mock(UserMqMessageService.class);
|
||||||
|
private final ProcessCpApplyCmd exe;
|
||||||
|
|
||||||
|
private Fixture(String relationType) {
|
||||||
|
CpValueService cpValueService = mock(CpValueService.class);
|
||||||
|
WalletGoldClient walletGoldClient = mock(WalletGoldClient.class);
|
||||||
|
UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
|
||||||
|
CpRelationshipCacheService cpRelationshipCacheService = mock(
|
||||||
|
CpRelationshipCacheService.class);
|
||||||
|
|
||||||
|
when(cpApplyService.getById(3001L)).thenReturn(apply(relationType));
|
||||||
|
when(cpApplyService.changeStatusById(3001L, CpApplyStatus.AGREE)).thenReturn(true);
|
||||||
|
when(cpApplyService.changeStatusById(3001L, CpApplyStatus.REFUSE)).thenReturn(true);
|
||||||
|
when(cpApplyService.changeStatusById(3001L, CpApplyStatus.REIMBURSE)).thenReturn(true);
|
||||||
|
when(cpApplyService.refuseOtherWaitBetweenUsers(3001L, 1001L, 2001L))
|
||||||
|
.thenReturn(List.of());
|
||||||
|
when(userProfileGateway.getByUserId(1001L)).thenReturn(profile(1001L));
|
||||||
|
when(userProfileGateway.getByUserId(2001L)).thenReturn(profile(2001L));
|
||||||
|
when(imMessageClient.sendCustomMessage(any(CustomC2cMsgBodyCmd.class)))
|
||||||
|
.thenReturn(ResultResponse.success());
|
||||||
|
|
||||||
|
exe = new ProcessCpApplyCmd(
|
||||||
|
cpApplyService,
|
||||||
|
cpValueService,
|
||||||
|
imMessageClient,
|
||||||
|
walletGoldClient,
|
||||||
|
userMqMessageService,
|
||||||
|
cpRelationshipService,
|
||||||
|
userProfileGateway,
|
||||||
|
cpRelationshipCacheService,
|
||||||
|
cpRelationBroadcastMqClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CustomC2cMsgBodyCmd sentCustomMessage() {
|
||||||
|
ArgumentCaptor<CustomC2cMsgBodyCmd> captor = ArgumentCaptor.forClass(
|
||||||
|
CustomC2cMsgBodyCmd.class);
|
||||||
|
verify(imMessageClient).sendCustomMessage(captor.capture());
|
||||||
|
return captor.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UserProfile profile(Long userId) {
|
||||||
|
UserProfile userProfile = new UserProfile();
|
||||||
|
userProfile.setId(userId);
|
||||||
|
userProfile.setAccount(userId.toString());
|
||||||
|
userProfile.setUserNickname("user-" + userId);
|
||||||
|
userProfile.setCountryCode("SA");
|
||||||
|
userProfile.setCountryName("Saudi Arabia");
|
||||||
|
return userProfile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,14 +4,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient;
|
import com.red.circle.external.inner.endpoint.message.ImMessageClient;
|
||||||
import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExtTemplateTypeCmd;
|
import com.red.circle.external.inner.model.cmd.message.CustomC2cMsgBodyCmd;
|
||||||
import com.red.circle.framework.dto.ResultResponse;
|
import com.red.circle.framework.dto.ResultResponse;
|
||||||
|
import com.red.circle.mq.business.model.event.user.CpApplyEvent;
|
||||||
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
|
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
|
||||||
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
|
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
|
||||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||||
@ -23,6 +25,9 @@ import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
|||||||
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
|
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
|
||||||
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||||
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
@ -49,6 +54,61 @@ class SendCpApplyCmdExeTest {
|
|||||||
verify(fixture.cpApplyService, never()).save(any(CpApply.class));
|
verify(fixture.cpApplyService, never()).save(any(CpApply.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void autoCreateFromCpGiftShouldSkipWhenAnyRelationAlreadyExistsInEitherDirection() {
|
||||||
|
Fixture fixture = new Fixture(1, 0);
|
||||||
|
when(fixture.cpRelationshipService.existsRelationship(1001L, 2001L)).thenReturn(true);
|
||||||
|
|
||||||
|
assertFalse(fixture.exe.autoCreateFromCpGift(1001L, 2001L, "LIKEI", "BROTHER"));
|
||||||
|
verify(fixture.cpApplyService, never()).save(any(CpApply.class));
|
||||||
|
verify(fixture.imMessageClient, never()).sendCustomMessage(any(CustomC2cMsgBodyCmd.class));
|
||||||
|
verify(fixture.userMqMessageService, never()).cpApplyDelayed(any(CpApplyEvent.class),
|
||||||
|
any(Timestamp.class));
|
||||||
|
|
||||||
|
Fixture reverseFixture = new Fixture(1, 0);
|
||||||
|
when(reverseFixture.cpRelationshipService.existsRelationship(2001L, 1001L)).thenReturn(true);
|
||||||
|
|
||||||
|
assertFalse(reverseFixture.exe.autoCreateFromCpGift(2001L, 1001L, "LIKEI", "SISTERS"));
|
||||||
|
verify(reverseFixture.cpApplyService, never()).save(any(CpApply.class));
|
||||||
|
verify(reverseFixture.imMessageClient, never()).sendCustomMessage(any(CustomC2cMsgBodyCmd.class));
|
||||||
|
verify(reverseFixture.userMqMessageService, never()).cpApplyDelayed(any(CpApplyEvent.class),
|
||||||
|
any(Timestamp.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void autoCreateFromCpGiftShouldCreateIndependentAppliesForDifferentRelationTypes() {
|
||||||
|
Fixture fixture = new Fixture(1, 0);
|
||||||
|
|
||||||
|
assertTrue(fixture.exe.autoCreateFromCpGift(1001L, 2001L, "LIKEI", "CP"));
|
||||||
|
assertTrue(fixture.exe.autoCreateFromCpGift(1001L, 2001L, "LIKEI", "BROTHER"));
|
||||||
|
assertTrue(fixture.exe.autoCreateFromCpGift(1001L, 2001L, "LIKEI", "SISTERS"));
|
||||||
|
|
||||||
|
List<CpApply> applies = fixture.savedApplies(3);
|
||||||
|
assertEquals("CP", applies.get(0).getRelationType());
|
||||||
|
assertEquals("BROTHER", applies.get(1).getRelationType());
|
||||||
|
assertEquals("SISTERS", applies.get(2).getRelationType());
|
||||||
|
|
||||||
|
List<CustomC2cMsgBodyCmd> messages = fixture.sentCustomMessages(3);
|
||||||
|
assertEquals("1001", messages.get(0).getFromAccount());
|
||||||
|
assertEquals("2001", messages.get(0).getToAccount());
|
||||||
|
assertCpBuildMessage(messages.get(0), "CP", 3001L);
|
||||||
|
assertCpBuildMessage(messages.get(1), "BROTHER", 3002L);
|
||||||
|
assertCpBuildMessage(messages.get(2), "SISTERS", 3003L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static void assertCpBuildMessage(CustomC2cMsgBodyCmd message, String relationType,
|
||||||
|
Long applyId) {
|
||||||
|
assertEquals("CP_BUILD", message.getDesc());
|
||||||
|
Map<String, Object> data = (Map<String, Object>) message.getData();
|
||||||
|
assertEquals("CP_BUILD", data.get("noticeType"));
|
||||||
|
assertEquals("CP_BUILD", data.get("type"));
|
||||||
|
assertEquals(applyId, data.get("expand"));
|
||||||
|
assertEquals(applyId, data.get("applyId"));
|
||||||
|
assertEquals(relationType, data.get("relationType"));
|
||||||
|
assertTrue(data.get("content").toString().contains("\"relationType\":\"" + relationType + "\""));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void autoCreateFromCpGiftShouldSkipSelfGift() {
|
void autoCreateFromCpGiftShouldSkipSelfGift() {
|
||||||
Fixture fixture = new Fixture(1, 1);
|
Fixture fixture = new Fixture(1, 1);
|
||||||
@ -61,33 +121,42 @@ class SendCpApplyCmdExeTest {
|
|||||||
private static class Fixture {
|
private static class Fixture {
|
||||||
|
|
||||||
private final CpApplyService cpApplyService = mock(CpApplyService.class);
|
private final CpApplyService cpApplyService = mock(CpApplyService.class);
|
||||||
|
private final ImMessageClient imMessageClient = mock(ImMessageClient.class);
|
||||||
|
private final UserMqMessageService userMqMessageService = mock(UserMqMessageService.class);
|
||||||
|
private final CpRelationshipService cpRelationshipService = mock(CpRelationshipService.class);
|
||||||
private final UserRegionGateway userRegionGateway = mock(UserRegionGateway.class);
|
private final UserRegionGateway userRegionGateway = mock(UserRegionGateway.class);
|
||||||
private final SendCpApplyCmdExe exe;
|
private final SendCpApplyCmdExe exe;
|
||||||
|
private long nextApplyId = 3001L;
|
||||||
|
|
||||||
private Fixture(Integer sendSex, Integer acceptSex) {
|
private Fixture(Integer sendSex, Integer acceptSex) {
|
||||||
OfficialNoticeClient officialNoticeClient = mock(OfficialNoticeClient.class);
|
|
||||||
WalletGoldClient walletGoldClient = mock(WalletGoldClient.class);
|
WalletGoldClient walletGoldClient = mock(WalletGoldClient.class);
|
||||||
UserMqMessageService userMqMessageService = mock(UserMqMessageService.class);
|
|
||||||
CpRelationshipService cpRelationshipService = mock(CpRelationshipService.class);
|
|
||||||
EnumConfigCacheService enumConfigCacheService = mock(EnumConfigCacheService.class);
|
EnumConfigCacheService enumConfigCacheService = mock(EnumConfigCacheService.class);
|
||||||
UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
|
UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
|
||||||
UserProfileAppConvertor userProfileAppConvertor = mock(UserProfileAppConvertor.class);
|
UserProfileAppConvertor userProfileAppConvertor = mock(UserProfileAppConvertor.class);
|
||||||
UserProfile sendProfile = new UserProfile();
|
UserProfile sendProfile = new UserProfile();
|
||||||
|
sendProfile.setId(1001L);
|
||||||
UserProfile acceptProfile = new UserProfile();
|
UserProfile acceptProfile = new UserProfile();
|
||||||
|
acceptProfile.setId(2001L);
|
||||||
UserProfileDTO sendProfileDTO = profile(1001L, sendSex);
|
UserProfileDTO sendProfileDTO = profile(1001L, sendSex);
|
||||||
UserProfileDTO acceptProfileDTO = profile(2001L, acceptSex);
|
UserProfileDTO acceptProfileDTO = profile(2001L, acceptSex);
|
||||||
|
|
||||||
when(userRegionGateway.checkEqRegion(1001L, 2001L)).thenReturn(true);
|
when(userRegionGateway.checkEqRegion(1001L, 2001L)).thenReturn(true);
|
||||||
|
when(userRegionGateway.checkEqRegion(2001L, 1001L)).thenReturn(true);
|
||||||
when(userProfileGateway.getByUserId(1001L)).thenReturn(sendProfile);
|
when(userProfileGateway.getByUserId(1001L)).thenReturn(sendProfile);
|
||||||
when(userProfileGateway.getByUserId(2001L)).thenReturn(acceptProfile);
|
when(userProfileGateway.getByUserId(2001L)).thenReturn(acceptProfile);
|
||||||
when(userProfileAppConvertor.toUserProfileDTO(sendProfile)).thenReturn(sendProfileDTO);
|
when(userProfileAppConvertor.toUserProfileDTO(sendProfile)).thenReturn(sendProfileDTO);
|
||||||
when(userProfileAppConvertor.toUserProfileDTO(acceptProfile)).thenReturn(acceptProfileDTO);
|
when(userProfileAppConvertor.toUserProfileDTO(acceptProfile)).thenReturn(acceptProfileDTO);
|
||||||
when(officialNoticeClient.send(any(NoticeExtTemplateTypeCmd.class)))
|
when(imMessageClient.sendCustomMessage(any(CustomC2cMsgBodyCmd.class)))
|
||||||
.thenReturn(ResultResponse.success());
|
.thenReturn(ResultResponse.success());
|
||||||
|
when(cpApplyService.save(any(CpApply.class))).thenAnswer(invocation -> {
|
||||||
|
CpApply apply = invocation.getArgument(0);
|
||||||
|
apply.setId(nextApplyId++);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
exe = new SendCpApplyCmdExe(
|
exe = new SendCpApplyCmdExe(
|
||||||
cpApplyService,
|
cpApplyService,
|
||||||
officialNoticeClient,
|
imMessageClient,
|
||||||
walletGoldClient,
|
walletGoldClient,
|
||||||
userMqMessageService,
|
userMqMessageService,
|
||||||
cpRelationshipService,
|
cpRelationshipService,
|
||||||
@ -99,9 +168,19 @@ class SendCpApplyCmdExeTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CpApply savedApply() {
|
private CpApply savedApply() {
|
||||||
|
return savedApplies(1).get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CpApply> savedApplies(int count) {
|
||||||
ArgumentCaptor<CpApply> captor = ArgumentCaptor.forClass(CpApply.class);
|
ArgumentCaptor<CpApply> captor = ArgumentCaptor.forClass(CpApply.class);
|
||||||
verify(cpApplyService).save(captor.capture());
|
verify(cpApplyService, times(count)).save(captor.capture());
|
||||||
return captor.getValue();
|
return captor.getAllValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CustomC2cMsgBodyCmd> sentCustomMessages(int count) {
|
||||||
|
ArgumentCaptor<CustomC2cMsgBodyCmd> captor = ArgumentCaptor.forClass(CustomC2cMsgBodyCmd.class);
|
||||||
|
verify(imMessageClient, times(count)).sendCustomMessage(captor.capture());
|
||||||
|
return captor.getAllValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UserProfileDTO profile(Long userId, Integer sex) {
|
private static UserProfileDTO profile(Long userId, Integer sex) {
|
||||||
|
|||||||
@ -0,0 +1,103 @@
|
|||||||
|
package com.red.circle.other.app.listener.user;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||||
|
import com.red.circle.component.mq.MessageEventProcess;
|
||||||
|
import com.red.circle.component.mq.MessageEventProcessDescribe;
|
||||||
|
import com.red.circle.component.mq.service.Action;
|
||||||
|
import com.red.circle.component.mq.service.ConsumerMessage;
|
||||||
|
import com.red.circle.external.inner.endpoint.message.ImMessageClient;
|
||||||
|
import com.red.circle.external.inner.model.cmd.message.CustomC2cMsgBodyCmd;
|
||||||
|
import com.red.circle.framework.dto.ResultResponse;
|
||||||
|
import com.red.circle.mq.business.model.event.user.CpApplyEvent;
|
||||||
|
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||||
|
import com.red.circle.other.domain.model.user.UserProfile;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
||||||
|
import com.red.circle.other.infra.enums.user.user.CpApplyStatus;
|
||||||
|
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
class CpApplyListenerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void waitApplyExpiredShouldSendC2cMessageToBothUsers() {
|
||||||
|
CpApplyService cpApplyService = mock(CpApplyService.class);
|
||||||
|
ImMessageClient imMessageClient = mock(ImMessageClient.class);
|
||||||
|
UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
|
||||||
|
WalletGoldClient walletGoldClient = mock(WalletGoldClient.class);
|
||||||
|
MessageEventProcess messageEventProcess = mock(MessageEventProcess.class);
|
||||||
|
CpApply apply = new CpApply()
|
||||||
|
.setId(3001L)
|
||||||
|
.setSendApplyUserId(1001L)
|
||||||
|
.setAcceptApplyUserId(2001L)
|
||||||
|
.setRelationType("SISTERS")
|
||||||
|
.setStatus(CpApplyStatus.WAIT.name());
|
||||||
|
|
||||||
|
when(cpApplyService.getById(3001L)).thenReturn(apply);
|
||||||
|
when(cpApplyService.changeStatusById(3001L, CpApplyStatus.REIMBURSE)).thenReturn(true);
|
||||||
|
when(userProfileGateway.getByUserId(1001L)).thenReturn(profile(1001L));
|
||||||
|
when(userProfileGateway.getByUserId(2001L)).thenReturn(profile(2001L));
|
||||||
|
when(imMessageClient.sendCustomMessage(any(CustomC2cMsgBodyCmd.class)))
|
||||||
|
.thenReturn(ResultResponse.success());
|
||||||
|
when(messageEventProcess.consume(any(MessageEventProcessDescribe.class),
|
||||||
|
eq(CpApplyEvent.class), any())).thenAnswer(invocation -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Consumer<CpApplyEvent> consumer = invocation.getArgument(2, Consumer.class);
|
||||||
|
consumer.accept(new CpApplyEvent()
|
||||||
|
.setId(3001L)
|
||||||
|
.setSysOrigin(SysOriginPlatformEnum.LIKEI));
|
||||||
|
return Action.SUCCESS;
|
||||||
|
});
|
||||||
|
|
||||||
|
CpApplyListener listener = new CpApplyListener(cpApplyService, imMessageClient,
|
||||||
|
userProfileGateway, walletGoldClient, messageEventProcess);
|
||||||
|
|
||||||
|
assertEquals(Action.SUCCESS, listener.consume(new ConsumerMessage()));
|
||||||
|
|
||||||
|
ArgumentCaptor<CustomC2cMsgBodyCmd> captor = ArgumentCaptor.forClass(
|
||||||
|
CustomC2cMsgBodyCmd.class);
|
||||||
|
verify(imMessageClient, org.mockito.Mockito.times(2)).sendCustomMessage(captor.capture());
|
||||||
|
List<CustomC2cMsgBodyCmd> messages = captor.getAllValues();
|
||||||
|
assertExpiredMessage(messages.get(0), "1001", "2001");
|
||||||
|
assertExpiredMessage(messages.get(1), "2001", "1001");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static void assertExpiredMessage(CustomC2cMsgBodyCmd message, String fromAccount,
|
||||||
|
String toAccount) {
|
||||||
|
assertEquals(fromAccount, message.getFromAccount());
|
||||||
|
assertEquals(toAccount, message.getToAccount());
|
||||||
|
assertEquals("CP_BUILD", message.getDesc());
|
||||||
|
Map<String, Object> data = (Map<String, Object>) message.getData();
|
||||||
|
assertEquals("RELATION_EXPIRED", data.get("noticeAction"));
|
||||||
|
assertEquals("RELATION_EXPIRED", data.get("action"));
|
||||||
|
assertEquals("EXPIRED", data.get("status"));
|
||||||
|
assertEquals("EXPIRED", data.get("result"));
|
||||||
|
assertEquals("EXPIRED", data.get("state"));
|
||||||
|
assertEquals(Boolean.TRUE, data.get("expired"));
|
||||||
|
assertEquals("SISTERS", data.get("relationType"));
|
||||||
|
assertTrue(data.get("content").toString().contains("\"relationType\":\"SISTERS\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UserProfile profile(Long userId) {
|
||||||
|
UserProfile userProfile = new UserProfile();
|
||||||
|
userProfile.setId(userId);
|
||||||
|
userProfile.setAccount(userId.toString());
|
||||||
|
userProfile.setUserNickname("user-" + userId);
|
||||||
|
userProfile.setCountryCode("SA");
|
||||||
|
userProfile.setCountryName("Saudi Arabia");
|
||||||
|
return userProfile;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -45,6 +45,11 @@ public class CpRightsConfigCO extends ClientObject {
|
|||||||
*/
|
*/
|
||||||
private Long intimacyValue;
|
private Long intimacyValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gold required to dismiss this relationship type.
|
||||||
|
*/
|
||||||
|
private Long dismissConsumeGold;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Level rights config.
|
* Level rights config.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -107,6 +107,21 @@ public enum OtherConfigEnum implements SysConfigEnum {
|
|||||||
*/
|
*/
|
||||||
CP_PRICE("cp price"),
|
CP_PRICE("cp price"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CP 关系解绑金币.
|
||||||
|
*/
|
||||||
|
CP_DISMISS_CONSUME_GOLD("CP dismiss consume gold"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Brother 关系解绑金币.
|
||||||
|
*/
|
||||||
|
BROTHER_DISMISS_CONSUME_GOLD("Brother dismiss consume gold"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sisters 关系解绑金币.
|
||||||
|
*/
|
||||||
|
SISTERS_DISMISS_CONSUME_GOLD("Sisters dismiss consume gold"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aswat 超级管理员ID.
|
* Aswat 超级管理员ID.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -90,6 +90,16 @@ public interface CpApplyService extends BaseService<CpApply> {
|
|||||||
*/
|
*/
|
||||||
void refuseStatusWait(Long acceptApplyUserId, String relationType);
|
void refuseStatusWait(Long acceptApplyUserId, String relationType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拒绝两个用户之间除指定申请外的其他等待申请.
|
||||||
|
*/
|
||||||
|
List<Long> refuseOtherWaitBetweenUsers(Long excludeApplyId, Long userId, Long cpUserId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取两个用户之间已拒绝的申请.
|
||||||
|
*/
|
||||||
|
List<CpApply> listRefuseBetweenUsers(Long userId, Long cpUserId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取我拒绝都信息.
|
* 获取我拒绝都信息.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -36,6 +36,11 @@ public interface CpRelationshipService extends BaseService<CpRelationship> {
|
|||||||
*/
|
*/
|
||||||
boolean existsCp(Long userId, Long cpUserId, String relationType);
|
boolean existsCp(Long userId, Long cpUserId, String relationType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 两个用户之间是否存在任意正常关系.
|
||||||
|
*/
|
||||||
|
boolean existsRelationship(Long userId, Long cpUserId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取分手中的cp信息集合
|
* 获取分手中的cp信息集合
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -117,6 +117,34 @@ public class CpApplyServiceImpl extends BaseServiceImpl<CpApplyDAO, CpApply> imp
|
|||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Long> refuseOtherWaitBetweenUsers(Long excludeApplyId, Long userId, Long cpUserId) {
|
||||||
|
List<Long> applyIds = query()
|
||||||
|
.select(CpApply::getId)
|
||||||
|
.eq(CpApply::getStatus, CpApplyStatus.WAIT)
|
||||||
|
.ne(Objects.nonNull(excludeApplyId), CpApply::getId, excludeApplyId)
|
||||||
|
.and(where -> where
|
||||||
|
.nested(w -> w.eq(CpApply::getSendApplyUserId, userId)
|
||||||
|
.eq(CpApply::getAcceptApplyUserId, cpUserId))
|
||||||
|
.or()
|
||||||
|
.nested(w -> w.eq(CpApply::getSendApplyUserId, cpUserId)
|
||||||
|
.eq(CpApply::getAcceptApplyUserId, userId)))
|
||||||
|
.list()
|
||||||
|
.stream()
|
||||||
|
.map(CpApply::getId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.toList();
|
||||||
|
if (applyIds.isEmpty()) {
|
||||||
|
return applyIds;
|
||||||
|
}
|
||||||
|
update()
|
||||||
|
.set(CpApply::getStatus, CpApplyStatus.REFUSE)
|
||||||
|
.set(CpApply::getUpdateTime, LocalDateTime.now())
|
||||||
|
.in(CpApply::getId, applyIds)
|
||||||
|
.execute();
|
||||||
|
return applyIds;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CpApply> listRefuse(Long userId) {
|
public List<CpApply> listRefuse(Long userId) {
|
||||||
return query()
|
return query()
|
||||||
@ -126,6 +154,20 @@ public class CpApplyServiceImpl extends BaseServiceImpl<CpApplyDAO, CpApply> imp
|
|||||||
.list();
|
.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CpApply> listRefuseBetweenUsers(Long userId, Long cpUserId) {
|
||||||
|
return query()
|
||||||
|
.eq(CpApply::getStatus, CpApplyStatus.REFUSE)
|
||||||
|
.and(where -> where
|
||||||
|
.nested(w -> w.eq(CpApply::getSendApplyUserId, userId)
|
||||||
|
.eq(CpApply::getAcceptApplyUserId, cpUserId))
|
||||||
|
.or()
|
||||||
|
.nested(w -> w.eq(CpApply::getSendApplyUserId, cpUserId)
|
||||||
|
.eq(CpApply::getAcceptApplyUserId, userId)))
|
||||||
|
.last(PageConstant.MAX_LIMIT)
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<CpApply> pageCpApply(CpApplyQryCmd query) {
|
public PageResult<CpApply> pageCpApply(CpApplyQryCmd query) {
|
||||||
return query()
|
return query()
|
||||||
|
|||||||
@ -70,6 +70,21 @@ public class CpRelationshipServiceImpl extends
|
|||||||
).map(cpRelationship -> Objects.nonNull(cpRelationship.getId())).orElse(Boolean.FALSE);
|
).map(cpRelationship -> Objects.nonNull(cpRelationship.getId())).orElse(Boolean.FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean existsRelationship(Long userId, Long cpUserId) {
|
||||||
|
return Optional.ofNullable(
|
||||||
|
query().select(CpRelationship::getId)
|
||||||
|
.eq(CpRelationship::getStatus, CpRelationshipStatus.NORMAL.name())
|
||||||
|
.and(where -> where
|
||||||
|
.nested(w -> w.eq(CpRelationship::getUserId, userId).eq(CpRelationship::getCpUserId, cpUserId))
|
||||||
|
.or()
|
||||||
|
.nested(w -> w.eq(CpRelationship::getUserId, cpUserId).eq(CpRelationship::getCpUserId, userId))
|
||||||
|
)
|
||||||
|
.last(PageConstant.LIMIT_ONE)
|
||||||
|
.getOne()
|
||||||
|
).map(cpRelationship -> Objects.nonNull(cpRelationship.getId())).orElse(Boolean.FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CpRelationship> getDismissingByUserId(Long userId) {
|
public List<CpRelationship> getDismissingByUserId(Long userId) {
|
||||||
return getDismissingByUserId(userId, CpRelationshipType.CP.name());
|
return getDismissingByUserId(userId, CpRelationshipType.CP.name());
|
||||||
|
|||||||
@ -215,8 +215,9 @@ public class CpLocalFlowSmokeTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertGiftAutoApplyRelationType(UserPair pair, String relationType) {
|
private void assertGiftAutoApplyRelationType(UserPair pair, String relationType) {
|
||||||
|
BigDecimal giftConsumeGold = BigDecimal.valueOf(66);
|
||||||
boolean created = sendCpApplyCmdExe.autoCreateFromCpGift(pair.sendUserId,
|
boolean created = sendCpApplyCmdExe.autoCreateFromCpGift(pair.sendUserId,
|
||||||
pair.acceptUserId, SYS_ORIGIN, relationType);
|
pair.acceptUserId, SYS_ORIGIN, relationType, giftConsumeGold);
|
||||||
assertTrue(relationType + " gift should auto create apply", created);
|
assertTrue(relationType + " gift should auto create apply", created);
|
||||||
|
|
||||||
Long applyId = cpApplyService.getId(pair.acceptUserId, pair.sendUserId, relationType);
|
Long applyId = cpApplyService.getId(pair.acceptUserId, pair.sendUserId, relationType);
|
||||||
@ -225,12 +226,21 @@ public class CpLocalFlowSmokeTest {
|
|||||||
|
|
||||||
CpApply apply = cpApplyService.getById(applyId);
|
CpApply apply = cpApplyService.getById(applyId);
|
||||||
assertEquals(relationType, apply.getRelationType());
|
assertEquals(relationType, apply.getRelationType());
|
||||||
assertEquals(0, BigDecimal.ZERO.compareTo(apply.getApplyConsumeGold()));
|
assertEquals(0, giftConsumeGold.compareTo(apply.getApplyConsumeGold()));
|
||||||
|
|
||||||
|
agree(applyId, pair.acceptUserId);
|
||||||
|
CpRelationship relationship = cpRelationshipService.getByUserId(pair.sendUserId,
|
||||||
|
pair.acceptUserId, relationType);
|
||||||
|
assertNotNull(relationType + " relationship after gift auto apply agree", relationship);
|
||||||
|
assertEquals(relationType, relationship.getRelationType());
|
||||||
|
createdPairs.add(new RelationPair(pair.sendUserId, pair.acceptUserId, relationType));
|
||||||
|
createdCpValIds.add(relationship.getCpValId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runCpGiftApplyBlessDismissFlow(UserPair pair) throws Exception {
|
private void runCpGiftApplyBlessDismissFlow(UserPair pair) throws Exception {
|
||||||
|
BigDecimal giftConsumeGold = BigDecimal.valueOf(88);
|
||||||
boolean created = sendCpApplyCmdExe.autoCreateFromCpGift(pair.sendUserId, pair.acceptUserId,
|
boolean created = sendCpApplyCmdExe.autoCreateFromCpGift(pair.sendUserId, pair.acceptUserId,
|
||||||
SYS_ORIGIN);
|
SYS_ORIGIN, giftConsumeGold);
|
||||||
Long pendingApplyId = cpApplyService.getId(pair.acceptUserId, pair.sendUserId, "CP");
|
Long pendingApplyId = cpApplyService.getId(pair.acceptUserId, pair.sendUserId, "CP");
|
||||||
if (pendingApplyId != null && !createdApplyIds.contains(pendingApplyId)) {
|
if (pendingApplyId != null && !createdApplyIds.contains(pendingApplyId)) {
|
||||||
createdApplyIds.add(pendingApplyId);
|
createdApplyIds.add(pendingApplyId);
|
||||||
@ -243,7 +253,7 @@ public class CpLocalFlowSmokeTest {
|
|||||||
|
|
||||||
CpApply apply = cpApplyService.getById(applyId);
|
CpApply apply = cpApplyService.getById(applyId);
|
||||||
assertEquals("CP", apply.getRelationType());
|
assertEquals("CP", apply.getRelationType());
|
||||||
assertEquals(0, BigDecimal.ZERO.compareTo(apply.getApplyConsumeGold()));
|
assertEquals(0, giftConsumeGold.compareTo(apply.getApplyConsumeGold()));
|
||||||
|
|
||||||
agree(applyId, pair.acceptUserId);
|
agree(applyId, pair.acceptUserId);
|
||||||
CpRelationship relationship = cpRelationshipService.getByUserId(pair.sendUserId,
|
CpRelationship relationship = cpRelationshipService.getByUserId(pair.sendUserId,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user