Browse Source

修改定时任务时间

release_toaliyun_real
Burce 6 years ago
parent
commit
1f8cad51e7
8 changed files with 436 additions and 388 deletions
  1. +338
    -339
      mallinkSchedule/src/main/java/com/iformall/schedule/CouponSendSchedule.java
  2. +3
    -0
      mallinkService/src/main/java/com/iformall/domain/vo/WxCouponSendVo.java
  3. +14
    -0
      mallinkService/src/main/java/com/iformall/service/impl/MarkingDataReportServiceImpl.java
  4. +1
    -0
      mallinkService/src/main/java/com/iformall/service/impl/WxCreditHistoryServiceImpl.java
  5. +6
    -5
      mallinkService/src/main/java/com/iformall/service/impl/WxScoreRulesServiceImpl.java
  6. +67
    -37
      mallinkService/src/main/java/com/iformall/utils/CreditUtil.java
  7. +3
    -3
      mallinkService/src/main/resources/mapper/WxCouponActionLogMapper.xml
  8. +4
    -4
      mallinkService/src/main/resources/mapper/WxCouponSendMapper.xml

+ 338
- 339
mallinkSchedule/src/main/java/com/iformall/schedule/CouponSendSchedule.java View File

@@ -9,6 +9,7 @@ import com.iformall.enums.*;
import com.iformall.mapper.*;
import com.iformall.mq.MqBaseProducer;
import com.iformall.service.*;
import com.iformall.utils.CreditUtil;
import com.iformall.utils.DateUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
@@ -28,344 +29,342 @@ import java.util.stream.Collectors;
@Component
public class CouponSendSchedule {

private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private WxMallMapper wxMallMapper;

@Autowired
private WxLevelConfigMapper WxLevelConfigMapper;

@Autowired
private WxLevelConfigService wxLevelConfigService;

@Autowired
private WxCUserBasicInfoMapper wxCUserBasicInfoMapper;

@Autowired
private WxCouponSendMapper wxCouponSendMapper;

@Autowired
private WxCouponActionLogMapper wxCouponActionLogMapper;

@Autowired
private WxOrderService wxOrderService;

@Autowired
private WxCouponActionLogService wxCouponActionLogService;

@Autowired
private WxCouponSendConfigMapper couponSendConfigMapper ;

@Autowired
private WxCouponSendService wxCouponSendService ;
@Autowired
private WxScoreRulesService wxScoreRulesService ;

@Autowired
private MqBaseProducer mqBaseProducer;



//@Scheduled(cron = "0 0 6 1 * ?") // 每月1号发放会员的权益券
@Scheduled(cron = "0 0 6 * * ?") // 测试每天6点发券
//@Scheduled(cron = "*/30 * * * * ?") // 测试30秒中一次
public void couponSendSchedule() {

List<WxMall> mallList = wxMallMapper.findList(new WxMall());

if (mallList.size()==0) {
logger.info("定时发券: No Mall info found");
return;
}

Date startTime = Date.from(LocalDateTime.now()
.with(TemporalAdjusters.firstDayOfMonth())
.with(LocalTime.MIN)
.atZone(ZoneId.systemDefault())
.toInstant());
Date endTime = Date.from(LocalDateTime.now()
.with(TemporalAdjusters.lastDayOfMonth())
.with(LocalTime.MAX)
.atZone(ZoneId.systemDefault())
.toInstant());
//查找所有couponSendConfig
Map<String, Integer> mallConfigMap = getAllCouponSendConfig(EnumCouponSendSendType.TIMED.getCode());
mallList.stream().forEach(mall-> {
//判断启用状态,状态为关闭时跳过不执行
if (isCouponSendDisable(mallConfigMap, mall)) {
logger.info("定时发券: {}发券状态关闭, 任务跳过不执行", mall.getName());
return;
}
WxLevelConfig wxLevelConfig = new WxLevelConfig();
wxLevelConfig.setTenantId(mall.getTenantId());
List<WxLevelConfig> levelConfigList = WxLevelConfigMapper.findList(wxLevelConfig);
levelConfigList = levelConfigList.stream()
.sorted(Comparator.comparing(WxLevelConfig::getPoints))
.collect(Collectors.toList());

for (int levelIndex = 0; levelIndex < levelConfigList.size(); levelIndex++) {
WxLevelConfig l = levelConfigList.get(levelIndex);
if (l.getCapability() == null)
continue;
Integer levelStartScore = l.getPoints();
Integer levelEndScore = levelIndex+1 < levelConfigList.size() ? levelConfigList.get(levelIndex+1).getPoints() : null;

JSONObject jo = null;
Long result = null;
try {
jo = JSONObject.parseObject(l.getCapability());
result = wxLevelConfigService.getCapabilitiesOfSendCarConpon(jo);
} catch (Exception e) {
logger.error("定时发券: 不能解析发券规则 levelId=" + l.getId() + e.getMessage());
continue;
}
Long sendCount = result;
if (sendCount > 0) {

WxCUserBasicInfoDto wxCUserBasicInfoDto = new WxCUserBasicInfoDto();
wxCUserBasicInfoDto.setTenantId(l.getTenantId());
wxCUserBasicInfoDto.setLevelStartScore(levelStartScore);
wxCUserBasicInfoDto.setLevelEndScore(levelEndScore);
List<WxCUserBasicInfo> wxCUserBasicInfoList = wxCUserBasicInfoMapper.findListByScore(wxCUserBasicInfoDto);

logger.info("定时发券:给LEVEL["+ l.getLevel() +
"]积分["+levelStartScore+"-"+levelEndScore+"]发券"+sendCount+"张");

wxCUserBasicInfoList.stream().forEach(cu->{

WxCouponSend wxCouponSend = new WxCouponSend();
wxCouponSend.setTenantId(l.getTenantId());
wxCouponSend.setSendType(EnumCouponSendSendType.TIMED.getCode());
wxCouponSend.setStatus(EnumCouponSendStatus.VALID.getCode());
List<WxCouponSendVo> couponSendList = wxCouponSendMapper.findListVo(wxCouponSend);
int remain = couponSendList.stream().map(cs->{
int count = cs.getRemainInventory();
logger.info("定时发券:给["+ cu.getNickName() +
"]券[" + cs.getTitle() + "]还剩" +
count +"张");
return count;
}).reduce(Integer::sum).get();

if (remain < sendCount){
logger.error("定时发券:库存不足["+ cu.getNickName() +"]应发"+sendCount+"张,总共剩"+ remain + "张");
return;
}

int sentCount = couponSendList.stream().map(cs->{
Map params = new HashMap<String, Object>();
params.put("tenantId", cs.getTenantId());
params.put("cUserId", cu.getId());
params.put("couponId", cs.getCouponId());
params.put("startTime", startTime);
params.put("endTime", endTime);
params.put("channelType", EnumCouponSendSendType.TIMED.getCode());
int count = wxCouponActionLogMapper.getCountByUserAndCouponAndDate(params);
logger.info("定时发券:已经给["+ cu.getNickName() +
"]券[" + cs.getTitle() + "] " +
count +"张");
return count;
}).reduce(Integer::sum).get();


logger.info("定时发券:给["+ cu.getNickName() +
"]总共已发送券" + sentCount + "张,还需发"+ (sendCount-sentCount) +"张");

for (int count = 0; count < sendCount - sentCount; count++) {
boolean sent = false;
for(int couponIndex = 0; couponIndex< couponSendList.size(); couponIndex++) {
WxCouponSendVo cs = couponSendList.get(couponIndex);
if (cs.getRemainInventory() <= 0)
continue;

// 发放免费券
try {
WxCouponOrder couponOrder = wxOrderService.sendFreeCouponToUser(cu.getId(), cs.getCouponId(),null);
wxCouponActionLogService.addOne(l.getTenantId(), cs.getCouponId(), couponOrder.getId(), cs.getSendType(), cs.getId());
} catch (Exception e) {
logger.error("定时发券:发券失败 levelId=" + l.getId() + " couponId=" + cs.getCouponId() + " userId=" + cu.getId() + e.getMessage());
continue;
}

logger.info("定时发券:商场[" + mall.getName() +
"]会员等级[" + l.getLevel() +
"]发送券[" + cs.getTitle() +
"]给:" + cu.getNickName() +
" 电话-" + cu.getPhone() +
" id-" + cu.getId());
sent = true;
break;
}
if (!sent)
break;
}
});
}
}
});
}

/**
* 生日券发放
*/
@Scheduled(cron = "0 0 18 0 * ?") // 测试每天6点发券
public void birthdayCouponSendSchedule() {
logger.info("生日发券: 任务开始");
List<WxMall> mallList = wxMallMapper.findList(new WxMall());
if (mallList.size() == 0) {
logger.info("生日发券: No Mall info found");
return;
}

Date startTime = Date.from(LocalDateTime.now()
.with(TemporalAdjusters.firstDayOfYear())
.with(LocalTime.MIN)
.atZone(ZoneId.systemDefault())
.toInstant());
Date endTime = Date.from(LocalDateTime.now()
.with(TemporalAdjusters.lastDayOfYear())
.with(LocalTime.MAX)
.atZone(ZoneId.systemDefault())
.toInstant());

//查找所有couponSendConfig
Map<String, Integer> mallConfigMap = getAllCouponSendConfig(EnumCouponSendSendType.BIRTHDAY.getCode());
mallList.forEach(mall -> {
//判断启用状态,状态为关闭时跳过不执行
if (isCouponSendDisable(mallConfigMap, mall)) {
logger.info("生日发券: {} 发券状态关闭, 任务跳过不执行", mall.getName());
return;
}

WxCUserBasicInfoDto wxCUserBasicInfoDto = new WxCUserBasicInfoDto();
wxCUserBasicInfoDto.setTenantId(mall.getTenantId());
List<WxCUserBasicInfo> wxCUserBasicInfoList = wxCUserBasicInfoMapper.findBirthdayList(wxCUserBasicInfoDto);
if (CollectionUtils.isEmpty(wxCUserBasicInfoList)) {
logger.info("生日发券: {} 用户列表为空 wxCUserBasicInfoList = {}, 任务跳过不执行", mall.getName(), wxCUserBasicInfoList);
return;
}
//每人可以发送几张生日券
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private WxMallMapper wxMallMapper;

@Autowired
private WxLevelConfigMapper WxLevelConfigMapper;

@Autowired
private WxLevelConfigService wxLevelConfigService;

@Autowired
private WxCUserBasicInfoMapper wxCUserBasicInfoMapper;

@Autowired
private WxCouponSendMapper wxCouponSendMapper;

@Autowired
private WxCouponActionLogMapper wxCouponActionLogMapper;

@Autowired
private WxOrderService wxOrderService;

@Autowired
private WxCouponActionLogService wxCouponActionLogService;

@Autowired
private WxCouponSendConfigMapper couponSendConfigMapper;

@Autowired
private WxCouponSendService wxCouponSendService;
@Autowired
private WxScoreRulesService wxScoreRulesService;

@Autowired
private MqBaseProducer mqBaseProducer;


//@Scheduled(cron = "0 0 6 1 * ?") // 每月1号发放会员的权益券
@Scheduled(cron = "0 0 6 * * ?") // 测试每天6点发券
//@Scheduled(cron = "*/30 * * * * ?") // 测试30秒中一次
public void couponSendSchedule() {

List<WxMall> mallList = wxMallMapper.findList(new WxMall());

if (mallList.size() == 0) {
logger.info("定时发券: No Mall info found");
return;
}

Date startTime = Date.from(LocalDateTime.now()
.with(TemporalAdjusters.firstDayOfMonth())
.with(LocalTime.MIN)
.atZone(ZoneId.systemDefault())
.toInstant());
Date endTime = Date.from(LocalDateTime.now()
.with(TemporalAdjusters.lastDayOfMonth())
.with(LocalTime.MAX)
.atZone(ZoneId.systemDefault())
.toInstant());
//查找所有couponSendConfig
Map<String, Integer> mallConfigMap = getAllCouponSendConfig(EnumCouponSendSendType.TIMED.getCode());
mallList.stream().forEach(mall -> {
//判断启用状态,状态为关闭时跳过不执行
if (isCouponSendDisable(mallConfigMap, mall)) {
logger.info("定时发券: {}发券状态关闭, 任务跳过不执行", mall.getName());
return;
}
WxLevelConfig wxLevelConfig = new WxLevelConfig();
wxLevelConfig.setTenantId(mall.getTenantId());
List<WxLevelConfig> levelConfigList = WxLevelConfigMapper.findList(wxLevelConfig);
levelConfigList = levelConfigList.stream()
.sorted(Comparator.comparing(WxLevelConfig::getPoints))
.collect(Collectors.toList());

for (int levelIndex = 0; levelIndex < levelConfigList.size(); levelIndex++) {
WxLevelConfig l = levelConfigList.get(levelIndex);
if (l.getCapability() == null)
continue;
Integer levelStartScore = l.getPoints();
Integer levelEndScore = levelIndex + 1 < levelConfigList.size() ? levelConfigList.get(levelIndex + 1).getPoints() : null;

JSONObject jo = null;
Long result = null;
try {
jo = JSONObject.parseObject(l.getCapability());
result = wxLevelConfigService.getCapabilitiesOfSendCarConpon(jo);
} catch (Exception e) {
logger.error("定时发券: 不能解析发券规则 levelId=" + l.getId() + e.getMessage());
continue;
}
Long sendCount = result;
if (sendCount > 0) {

WxCUserBasicInfoDto wxCUserBasicInfoDto = new WxCUserBasicInfoDto();
wxCUserBasicInfoDto.setTenantId(l.getTenantId());
wxCUserBasicInfoDto.setLevelStartScore(levelStartScore);
wxCUserBasicInfoDto.setLevelEndScore(levelEndScore);
List<WxCUserBasicInfo> wxCUserBasicInfoList = wxCUserBasicInfoMapper.findListByScore(wxCUserBasicInfoDto);

logger.info("定时发券:给LEVEL[" + l.getLevel() +
"]积分[" + levelStartScore + "-" + levelEndScore + "]发券" + sendCount + "张");

wxCUserBasicInfoList.stream().forEach(cu -> {

WxCouponSend wxCouponSend = new WxCouponSend();
wxCouponSend.setTenantId(l.getTenantId());
wxCouponSend.setSendType(EnumCouponSendSendType.TIMED.getCode());
wxCouponSend.setStatus(EnumCouponSendStatus.VALID.getCode());
List<WxCouponSendVo> couponSendList = wxCouponSendMapper.findListVo(wxCouponSend);
int remain = couponSendList.stream().map(cs -> {
int count = cs.getRemainInventory();
logger.info("定时发券:给[" + cu.getNickName() +
"]券[" + cs.getTitle() + "]还剩" +
count + "张");
return count;
}).reduce(Integer::sum).get();

if (remain < sendCount) {
logger.error("定时发券:库存不足[" + cu.getNickName() + "]应发" + sendCount + "张,总共剩" + remain + "张");
return;
}

int sentCount = couponSendList.stream().map(cs -> {
Map params = new HashMap<String, Object>();
params.put("tenantId", cs.getTenantId());
params.put("cUserId", cu.getId());
params.put("couponId", cs.getCouponId());
params.put("startTime", startTime);
params.put("endTime", endTime);
params.put("channelType", EnumCouponSendSendType.TIMED.getCode());
int count = wxCouponActionLogMapper.getCountByUserAndCouponAndDate(params);
logger.info("定时发券:已经给[" + cu.getNickName() +
"]券[" + cs.getTitle() + "] " +
count + "张");
return count;
}).reduce(Integer::sum).get();


logger.info("定时发券:给[" + cu.getNickName() +
"]总共已发送券" + sentCount + "张,还需发" + (sendCount - sentCount) + "张");

for (int count = 0; count < sendCount - sentCount; count++) {
boolean sent = false;
for (int couponIndex = 0; couponIndex < couponSendList.size(); couponIndex++) {
WxCouponSendVo cs = couponSendList.get(couponIndex);
if (cs.getRemainInventory() <= 0)
continue;

// 发放免费券
try {
WxCouponOrder couponOrder = wxOrderService.sendFreeCouponToUser(cu.getId(), cs.getCouponId(), null);
wxCouponActionLogService.addOne(l.getTenantId(), cs.getCouponId(), couponOrder.getId(), cs.getSendType(), cs.getId());
} catch (Exception e) {
logger.error("定时发券:发券失败 levelId=" + l.getId() + " couponId=" + cs.getCouponId() + " userId=" + cu.getId() + e.getMessage());
continue;
}

logger.info("定时发券:商场[" + mall.getName() +
"]会员等级[" + l.getLevel() +
"]发送券[" + cs.getTitle() +
"]给:" + cu.getNickName() +
" 电话-" + cu.getPhone() +
" id-" + cu.getId());
sent = true;
break;
}
if (!sent)
break;
}
});
}
}
});
}

/**
* 生日券发放
*/
@Scheduled(cron = "0 0 18 0 * ?") // 测试每天6点发券
public void birthdayCouponSendSchedule() {
logger.info("生日发券: 任务开始");
List<WxMall> mallList = wxMallMapper.findList(new WxMall());
if (mallList.size() == 0) {
logger.info("生日发券: No Mall info found");
return;
}

Date startTime = Date.from(LocalDateTime.now()
.with(TemporalAdjusters.firstDayOfYear())
.with(LocalTime.MIN)
.atZone(ZoneId.systemDefault())
.toInstant());
Date endTime = Date.from(LocalDateTime.now()
.with(TemporalAdjusters.lastDayOfYear())
.with(LocalTime.MAX)
.atZone(ZoneId.systemDefault())
.toInstant());

//查找所有couponSendConfig
Map<String, Integer> mallConfigMap = getAllCouponSendConfig(EnumCouponSendSendType.BIRTHDAY.getCode());
mallList.forEach(mall -> {
//判断启用状态,状态为关闭时跳过不执行
if (isCouponSendDisable(mallConfigMap, mall)) {
logger.info("生日发券: {} 发券状态关闭, 任务跳过不执行", mall.getName());
return;
}

WxCUserBasicInfoDto wxCUserBasicInfoDto = new WxCUserBasicInfoDto();
wxCUserBasicInfoDto.setTenantId(mall.getTenantId());
List<WxCUserBasicInfo> wxCUserBasicInfoList = wxCUserBasicInfoMapper.findBirthdayList(wxCUserBasicInfoDto);
if (CollectionUtils.isEmpty(wxCUserBasicInfoList)) {
logger.info("生日发券: {} 用户列表为空 wxCUserBasicInfoList = {}, 任务跳过不执行", mall.getName(), wxCUserBasicInfoList);
return;
}
//每人可以发送几张生日券
// final int sendCount = 1;
wxCUserBasicInfoList.forEach(cu -> {
WxCouponSend wxCouponSend = new WxCouponSend();
wxCouponSend.setTenantId(cu.getTenantId());
wxCouponSend.setSendType(EnumCouponSendSendType.BIRTHDAY.getCode());
wxCouponSend.setStatus(EnumCouponSendStatus.VALID.getCode());
List<WxCouponSendVo> couponSendList = wxCouponSendMapper.findListVo(wxCouponSend);
if (CollectionUtils.isEmpty(couponSendList)) {
logger.info("生日发券: 会员生日券投放列表为空 couponSendList = {}, 任务跳过不执行", couponSendList);
return;
}
boolean sent = false;
for (WxCouponSendVo cs : couponSendList) {
String conditions = cs.getConditions();
JSONObject configJo = null;
try {
configJo = JSONObject.parseObject(conditions);
} catch (Exception e) {
logger.error("生日发券: 解析conditions异常: {}",e.getMessage());
}
if (Objects.isNull(conditions)||Objects.isNull(configJo)) {
logger.info("生日发券: 会员生日券配置不存在 conditions = {}, 任务跳过不执行", conditions);
return;
}
//默认生日当天发送
int beforeDays = 0;
if (configJo.containsKey(WxCouponSend.KEY_BEFOREDAYS)) {
beforeDays = configJo.getIntValue(WxCouponSend.KEY_BEFOREDAYS);
}
Map<String, Object> params = new HashMap<>();
params.put("tenantId", cs.getTenantId());
params.put("cUserId", cu.getId());
params.put("couponId", cs.getCouponId());
params.put("startTime", startTime);
params.put("endTime", endTime);
params.put("channelType", EnumCouponSendSendType.BIRTHDAY.getCode());
int count = wxCouponActionLogMapper.getCountByUserAndCouponAndDate(params);
logger.info("生日发券:已经给[" + cu.getNickName() +
"]券[" + cs.getTitle() + "] " +
count + "张");
if (count > 0) {
logger.info("生日发券: 会员{}已经发送过生日券, 本次不再发送", cu.getNickName());
continue;
}
//提前n天发送生日券,不满足跳过不执行,没有发送的进行补发
if (DateUtils.birthdaysBetween(cu.getBirthdate()) <= beforeDays) {
logger.info("生日发券: [会员={},生日={}不满足提前{}天发券]", cu.getNickName(), cu.getBirthdate(),beforeDays);
continue;
}
if (cs.getRemainInventory() <= 0) {
logger.info("生日发券: [title={},id={}]卡券库存不足!", cs.getTitle(), cs.getCouponId());
continue;
}
// 发放免费券
try {
WxCouponOrder couponOrder = wxOrderService.sendFreeCouponToUser(cu.getId(), cs.getCouponId(),null);
wxCouponActionLogService.addOne(cu.getTenantId(), cs.getCouponId(), couponOrder.getId(), cs.getSendType(), cs.getId());
} catch (Exception e) {
logger.error("定时发券:发券失败 levelId=" + cu.getId() + " couponId=" + cs.getCouponId() + " userId=" + cu.getId() + e.getMessage());
continue;
}
sent = true ;
logger.info("定时发券:商场[" + mall.getName() +
"]会员生日[" + cu.getBirthdate().toInstant() +
"]发送券[" + cs.getTitle() +
"]给:" + cu.getNickName() +
" 电话-" + cu.getPhone() +
" id-" + cu.getId());
}
if (sent) {
sendSMS(cu, mall);
// 记录积分倍率日期
try {
cu.setScoreDate(cu.getBirthdate());
wxCUserBasicInfoMapper.updateByPrimaryKeySelective(cu);
} catch (Exception e) {
logger.error("定时发券:记录积分倍率日期失败 {}", e.getMessage());
}
}
});
});
logger.info("生日发券: 任务结束");
}

private Map<String, Integer> getAllCouponSendConfig(Integer sendType) {
WxCouponSendConfig queryConfig = new WxCouponSendConfig();
queryConfig.setSendType(sendType);
List<WxCouponSendConfig> couponSendConfigList = couponSendConfigMapper.findList(queryConfig);
return CollectionUtils.isNotEmpty(couponSendConfigList) ?
couponSendConfigList.stream().collect(Collectors.toMap(WxCouponSendConfig::getTenantId, WxCouponSendConfig::getValue)) : null;
}

private boolean isCouponSendDisable(Map<String, Integer> mallConfigMap, WxMall mall) {
if (mallConfigMap != null && Objects.nonNull(mallConfigMap.get(mall.getTenantId()))) {
Integer disable = mallConfigMap.get(mall.getTenantId());
return Objects.equals(disable, EnumEnableType.Disable.getCode());
}
return false;
}

private void sendSMS(WxCUserBasicInfo cUserBasicInfo, WxMall mall) {
WxMsgRecord wxMsgRecord = new WxMsgRecord();
wxMsgRecord.setMsgType(EnumMsgRecordType.SMS.getCode());
wxMsgRecord.setReceiver(cUserBasicInfo.getPhone());
wxMsgRecord.setTenantId(cUserBasicInfo.getTenantId());
Map<String, String> dynamicContentMap = new HashMap<>();
WxScoreRules rules = wxScoreRulesService.getScoreRules(cUserBasicInfo.getTenantId());
if (Objects.nonNull(rules) && Objects.nonNull(rules.getScale())) {
int birthdayScale = rules.getScale();
if (birthdayScale > WxScoreRules.DEFAULT_SCALE) {
float creditScale = new BigDecimal(birthdayScale).divide(new BigDecimal(WxScoreRules.DEFAULT_SCALE)).floatValue();
dynamicContentMap.put("creditScale", String.valueOf(creditScale));
wxMsgRecord.setModelType(EnumMsgModel.COUPON_BIRTHDAY_OPENED.getCode());
}
} else {
//没有配置积分规则
wxMsgRecord.setModelType(EnumMsgModel.COUPON_BIRTHDAY_OPENED_NO.getCode());
}
dynamicContentMap.put("userName", Objects.isNull(cUserBasicInfo.getNickName()) ? "" : cUserBasicInfo.getNickName());
dynamicContentMap.put("mallName", mall.getName());
wxMsgRecord.setDynamicContentMap(dynamicContentMap);
mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode());
}
wxCUserBasicInfoList.forEach(cu -> {
WxCouponSend wxCouponSend = new WxCouponSend();
wxCouponSend.setTenantId(cu.getTenantId());
wxCouponSend.setSendType(EnumCouponSendSendType.BIRTHDAY.getCode());
wxCouponSend.setStatus(EnumCouponSendStatus.VALID.getCode());
List<WxCouponSendVo> couponSendList = wxCouponSendMapper.findListVo(wxCouponSend);
if (CollectionUtils.isEmpty(couponSendList)) {
logger.info("生日发券: 会员生日券投放列表为空 couponSendList = {}, 任务跳过不执行", couponSendList);
return;
}
boolean sent = false;
for (WxCouponSendVo cs : couponSendList) {
String conditions = cs.getConditions();
JSONObject configJo = null;
try {
configJo = JSONObject.parseObject(conditions);
} catch (Exception e) {
logger.error("生日发券: 解析conditions异常: {}", e.getMessage());
}
if (Objects.isNull(conditions) || Objects.isNull(configJo)) {
logger.info("生日发券: 会员生日券配置不存在 conditions = {}, 任务跳过不执行", conditions);
return;
}
//默认生日当天发送
int beforeDays = 0;
if (configJo.containsKey(WxCouponSend.KEY_BEFOREDAYS)) {
beforeDays = configJo.getIntValue(WxCouponSend.KEY_BEFOREDAYS);
}
Map<String, Object> params = new HashMap<>();
params.put("tenantId", cs.getTenantId());
params.put("cUserId", cu.getId());
params.put("couponId", cs.getCouponId());
params.put("startTime", startTime);
params.put("endTime", endTime);
params.put("channelType", EnumCouponSendSendType.BIRTHDAY.getCode());
int count = wxCouponActionLogMapper.getCountByUserAndCouponAndDate(params);
logger.info("生日发券:已经给[" + cu.getNickName() +
"]券[" + cs.getTitle() + "] " +
count + "张");
if (count > 0) {
logger.info("生日发券: 会员{}已经发送过生日券, 本次不再发送", cu.getNickName());
continue;
}
//提前n天发送生日券,不满足跳过不执行,没有发送的进行补发
int diffBithday = DateUtils.birthdaysBetween(cu.getBirthdate());
if (diffBithday < 0 || diffBithday > beforeDays) {
logger.info("生日发券: [会员={},生日={}不满足提前{}天发券]", cu.getNickName(), cu.getBirthdate(), beforeDays);
continue;
}
if (cs.getRemainInventory() <= 0) {
logger.info("生日发券: [title={},id={}]卡券库存不足!", cs.getTitle(), cs.getCouponId());
continue;
}
// 发放免费券
try {
WxCouponOrder couponOrder = wxOrderService.sendFreeCouponToUser(cu.getId(), cs.getCouponId(), null);
wxCouponActionLogService.addOne(cu.getTenantId(), cs.getCouponId(), couponOrder.getId(), cs.getSendType(), cs.getId());
} catch (Exception e) {
logger.error("定时发券:发券失败 levelId=" + cu.getId() + " couponId=" + cs.getCouponId() + " userId=" + cu.getId() + e.getMessage());
continue;
}
sent = true;
logger.info("定时发券:商场[" + mall.getName() +
"]会员生日[" + cu.getBirthdate().toInstant() +
"]发送券[" + cs.getTitle() +
"]给:" + cu.getNickName() +
" 电话-" + cu.getPhone() +
" id-" + cu.getId());
}
if (sent) {
sendSMS(cu, mall);
// 记录积分倍率日期
try {
cu.setScoreDate(cu.getBirthdate());
wxCUserBasicInfoMapper.updateByPrimaryKeySelective(cu);
} catch (Exception e) {
logger.error("定时发券:记录积分倍率日期失败 {}", e.getMessage());
}
}
});
});
logger.info("生日发券: 任务结束");
}

private Map<String, Integer> getAllCouponSendConfig(Integer sendType) {
WxCouponSendConfig queryConfig = new WxCouponSendConfig();
queryConfig.setSendType(sendType);
List<WxCouponSendConfig> couponSendConfigList = couponSendConfigMapper.findList(queryConfig);
return CollectionUtils.isNotEmpty(couponSendConfigList) ?
couponSendConfigList.stream().collect(Collectors.toMap(WxCouponSendConfig::getTenantId, WxCouponSendConfig::getValue)) : null;
}

private boolean isCouponSendDisable(Map<String, Integer> mallConfigMap, WxMall mall) {
if (mallConfigMap != null && Objects.nonNull(mallConfigMap.get(mall.getTenantId()))) {
Integer disable = mallConfigMap.get(mall.getTenantId());
return Objects.equals(disable, EnumEnableType.Disable.getCode());
}
return false;
}

private void sendSMS(WxCUserBasicInfo cUserBasicInfo, WxMall mall) {
WxMsgRecord wxMsgRecord = new WxMsgRecord();
wxMsgRecord.setMsgType(EnumMsgRecordType.SMS.getCode());
wxMsgRecord.setReceiver(cUserBasicInfo.getPhone());
wxMsgRecord.setTenantId(cUserBasicInfo.getTenantId());
Map<String, String> dynamicContentMap = new HashMap<>();

int birthdayScale = CreditUtil.getScoreScale(cUserBasicInfo.getTenantId(), wxScoreRulesService);
if (birthdayScale > WxScoreRules.DEFAULT_SCALE) {
float creditScale = new BigDecimal(birthdayScale).divide(new BigDecimal(WxScoreRules.DEFAULT_SCALE)).floatValue();
dynamicContentMap.put("creditScale", String.valueOf(creditScale));
wxMsgRecord.setModelType(EnumMsgModel.COUPON_BIRTHDAY_OPENED.getCode());
} else {
//没有配置积分规则
wxMsgRecord.setModelType(EnumMsgModel.COUPON_BIRTHDAY_OPENED_NO.getCode());
}
dynamicContentMap.put("userName", Objects.isNull(cUserBasicInfo.getNickName()) ? "" : cUserBasicInfo.getNickName());
dynamicContentMap.put("mallName", mall.getName());
wxMsgRecord.setDynamicContentMap(dynamicContentMap);
mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode());
}
}

+ 3
- 0
mallinkService/src/main/java/com/iformall/domain/vo/WxCouponSendVo.java View File

@@ -35,4 +35,7 @@ public class WxCouponSendVo extends WxCouponSend implements Serializable{
private String merchantName;

private Date sendDate ;

@io.swagger.annotations.ApiModelProperty(value="自领取之日几日有效",name="validDays")
private Integer validDays ;
}

+ 14
- 0
mallinkService/src/main/java/com/iformall/service/impl/MarkingDataReportServiceImpl.java View File

@@ -514,6 +514,20 @@ public class MarkingDataReportServiceImpl implements MarkingDataReportService {
}
result.put("micropayHistory",historyMap);

//商户发券
markingCouponDataReportDto.setChannelType(EnumCouponSendSendType.MERCHANT.getCode());
List<MarkingSceneDataVo> merchantList = wxCouponActionLogMapper.sceneDataList(markingCouponDataReportDto);
countMap = merchantList.stream().collect(Collectors.toMap(MarkingSceneDataVo::getXtime, p -> p.getSendCount()));
historyMap = new TreeMap<>();
for (String date:days) {
historyMap.put(date.substring(5).replace("-","/"),"0");
}
for (String key : countMap.keySet()) {
String keySub = key.substring(5).replace("-","/");
historyMap.put(keySub,countMap.get(key));
}
result.put("merchantHistory",historyMap);

return result;
}



+ 1
- 0
mallinkService/src/main/java/com/iformall/service/impl/WxCreditHistoryServiceImpl.java View File

@@ -217,6 +217,7 @@ public class WxCreditHistoryServiceImpl implements WxCreditHistoryService {
int creditChangeNumOrigin = creditIncrement(record);
int creditChangeNum = creditChangeNumOrigin ;
if (record.getCreditType().equals(EnumScoreType.CONSUMPTION.getCode()) || record.getCreditType().equals(EnumScoreType.SPEND_CREDIT.getCode())) {
//等级积分配置
int birthdayScale = wxLevelConfigMapper.getScale(wxCUser.getTenantId(), wxCUser.getScore()) ;
creditChangeNum = CreditUtil.calUserCredit(creditChangeNumOrigin, wxCUser, birthdayScale, wxCUserBasicInfo, wxScoreRulesService);
}


+ 6
- 5
mallinkService/src/main/java/com/iformall/service/impl/WxScoreRulesServiceImpl.java View File

@@ -67,11 +67,12 @@ public class WxScoreRulesServiceImpl implements WxScoreRulesService {

} else {
// 如果成长值规则不存在,启用默认值
final IdWorker idWorker = IdWorker.get();
scoreRules.setId(idWorker.nextId());
scoreRules.setRules(WxScoreRules.getScoreDefaultRules());

wxScoreRulesMapper.insertSelective(scoreRules);
this.saveOrUpdate(scoreRules);
//final IdWorker idWorker = IdWorker.get();
//scoreRules.setId(idWorker.nextId());
//scoreRules.setRules(WxScoreRules.getScoreDefaultRules());
//
//wxScoreRulesMapper.insertSelective(scoreRules);
}
// 插入缓存
scoreRulesRedisTemplate.opsForValue().set(key, scoreRules);


+ 67
- 37
mallinkService/src/main/java/com/iformall/utils/CreditUtil.java View File

@@ -14,44 +14,74 @@ import java.util.Objects;
@Slf4j
public class CreditUtil {

/**
* 计算用户积分
*
* @return
*/
public static int calUserCredit(int creditOrigin, WxCUser wxCUser, Integer scaleFromDb, WxCUserBasicInfo wxCUserBasicInfo, WxScoreRulesService wxScoreRulesService) {
if (Objects.isNull(wxCUser) || Objects.isNull(wxCUserBasicInfo)) {
return 0;
}
// 获取等级积分倍率:默认为1.0,
int levelScale = WxLevelConfig.DEFAULT_SCALE;
Integer score = wxCUser.getScore();
if (Objects.nonNull(score)) {
if (Objects.nonNull(scaleFromDb)) {
levelScale = scaleFromDb;
}
}
/**
* 计算用户积分
*
* @param creditOrigin 原始积分
* @param wxCUser C端用户信息
* @param scaleFromDb 等级倍率
* @param wxCUserBasicInfo C端用户信息
* @param wxScoreRulesService
* @return
*/
public static int calUserCredit(int creditOrigin, WxCUser wxCUser, Integer scaleFromDb, WxCUserBasicInfo wxCUserBasicInfo, WxScoreRulesService wxScoreRulesService) {
if (Objects.isNull(wxCUser) || Objects.isNull(wxCUserBasicInfo)) {
return 0;
}
// 获取等级积分倍率:默认为1.0,
int levelScale = calLevelScale(wxCUser, scaleFromDb);

// 获取生日积分倍率:
int birthdayScale = calBirthdayScale(wxCUserBasicInfo, wxScoreRulesService);

int creditNew = new BigDecimal(creditOrigin)
.multiply(new BigDecimal(levelScale))
.multiply(new BigDecimal(birthdayScale))
.divide(new BigDecimal(WxScoreRules.DEFAULT_SCALE))
.divide(new BigDecimal(WxLevelConfig.DEFAULT_SCALE)
, BigDecimal.ROUND_HALF_UP).intValue();
log.info("积分倍率计算, 用户:{},成长值:{},等级积分倍率:{},生日积分倍率:{},原积分:{},新积分:{}", wxCUser.getId(), wxCUser.getScore(), levelScale, birthdayScale, creditOrigin, creditNew);
return creditNew;
}

// 获取生日积分倍率:
public static int calLevelScale(WxCUser wxCUser, Integer scaleFromDb) {
int levelScale = WxLevelConfig.DEFAULT_SCALE;
Integer score = wxCUser.getScore();
//积分不为空时进行计算
if (Objects.nonNull(score)) {
//等级积分配置存在时进行计算
if (Objects.nonNull(scaleFromDb)) {
levelScale = scaleFromDb;
} else {
log.info("积分倍率计算:等级积分倍率配置=null");
}
}
log.info("积分倍率计算:会员等级积分倍率配置={}", levelScale);
return levelScale;
}

public static int calBirthdayScale(WxCUserBasicInfo wxCUserBasicInfo, WxScoreRulesService wxScoreRulesService) {
int birthdayScale = WxScoreRules.DEFAULT_SCALE;
//判断是否生日当天,一年一天有效
if (Objects.nonNull(wxCUserBasicInfo.getScoreDate()) && DateUtils.birthdaysBetween(wxCUserBasicInfo.getScoreDate()) == 0) {
birthdayScale = getScoreScale(wxCUserBasicInfo.getTenantId(), wxScoreRulesService);
} else {
log.info("积分倍率计算:未设置生日或生日条件未匹配={}", wxCUserBasicInfo.getScoreDate());
}
return birthdayScale;
}

public static int getScoreScale(String tenantId, WxScoreRulesService wxScoreRulesService) {
int birthdayScale = WxScoreRules.DEFAULT_SCALE;
//判断是否生日当天,一年一天有效
if (Objects.nonNull(wxCUserBasicInfo.getScoreDate()) && DateUtils.birthdaysBetween(wxCUserBasicInfo.getScoreDate()) == 0) {
WxScoreRules rules = wxScoreRulesService.getCreditRules(wxCUser.getTenantId());
if (Objects.nonNull(rules) && Objects.nonNull(rules.getScale())) {
birthdayScale = rules.getScale();
} else {
log.info("会员生日券倍率配置:null");
//没有配置积分规则
}
WxScoreRules rules = wxScoreRulesService.getCreditRules(tenantId);
if (Objects.nonNull(rules) && Objects.nonNull(rules.getScale())) {
//规则存使用积分倍率
birthdayScale = rules.getScale();
} else {
//没有配置积分规则
log.info("积分倍率计算:会员生日积分倍率配置=null");
}

int creditNew = new BigDecimal(creditOrigin)
.multiply(new BigDecimal(levelScale))
.multiply(new BigDecimal(birthdayScale))
.divide(new BigDecimal(WxScoreRules.DEFAULT_SCALE))
.divide(new BigDecimal(WxLevelConfig.DEFAULT_SCALE)
, BigDecimal.ROUND_HALF_UP).intValue();
log.info("积分倍率, 用户:{},成长值:{},等级积分倍率:{},生日积分倍率:{},原积分:{},新积分:{}", wxCUser.getId(), wxCUser.getScore(), levelScale, birthdayScale, creditOrigin, creditNew);
return creditNew;
}
log.info("会员生日积分倍率配置:{}", birthdayScale);
return birthdayScale ;
}
}

+ 3
- 3
mallinkService/src/main/resources/mapper/WxCouponActionLogMapper.xml View File

@@ -226,14 +226,14 @@
LEFT JOIN wx_coupon_order co ON cal.coupon_order_id = co.id
LEFT JOIN wx_coupon c ON cal.coupon_id = c.id
LEFT JOIN wx_c_user cu ON cu.id = co.c_user_id
LEFT JOIN wx_merchant_b_user mbu ON co.b_user_id = mbu.id
LEFT JOIN wx_merchant_b_user mbu ON concat(mbu.merchant_id,'') = JSON_EXTRACT(cs.conditions , '$.id')
WHERE cal.channel_type = #{channelType}
AND cs.conditions -> '$.id' = concat(#{merchantId},'')
<if test=" null != beginDate ">
and cal.create_time &gt;= #{beginDate}
AND cal.create_time &gt;= #{beginDate}
</if>
<if test=" null != endDate ">
and cal.create_time &lt; #{endDate}
AND cal.create_time &lt; #{endDate}
</if>
</select>



+ 4
- 4
mallinkService/src/main/resources/mapper/WxCouponSendMapper.xml View File

@@ -18,13 +18,13 @@
<result column="use_limit_quantity" jdbcType="INTEGER" property="useLimitQuantity"/>
<result column="valid_start_date" jdbcType="TIMESTAMP" property="validStartDate"/>
<result column="valid_end_date" jdbcType="TIMESTAMP" property="validEndDate"/>
<result column="send_sms" jdbcType="INTEGER" property="sendSms"/>
<result column="valid_days" jdbcType="INTEGER" property="validDays"/>

</resultMap>

<sql id="allColumns">
cs.id,cs.tenant_id,cs.coupon_id,cs.title,cs.send_type,cs.conditions,cs.status,cs.create_date,cs.update_date,JSON_EXTRACT(cs.conditions,'$.merchantLnventory') as merchantLnventory,
cs.id,cs.tenant_id,cs.coupon_id,cs.title,cs.send_type,cs.conditions,cs.status,cs.create_date,cs.update_date,
(case when
(select count(*) from wx_coupon_merchant xcm where xcm.product_id = cs.coupon_id and xcm.status = 0)=1
then
@@ -32,7 +32,7 @@
else
'[多商户通用]'
end) as merchant_name,
c.remain_inventory, c.use_limit_quantity, c.inventory, c.valid_start_date, c.valid_end_date,c.valid_type,cs.send_sms
c.remain_inventory, c.use_limit_quantity, c.inventory, c.valid_start_date, c.valid_end_date,c.valid_type,cs.send_sms,c.valid_days
</sql>

<sql id="dynamicWhereConditions">


Loading…
Cancel
Save