TASK: 1.affiliate 新增referral新增、查询、修改以及其他相关的自动结算佣金的功能;2.删除affiliate_income表及相关mapper
This commit is contained in:
@@ -102,6 +102,12 @@ public class PaymentTask {
|
|||||||
affiliateService.updateAffiliateInfoWithPayment();
|
affiliateService.updateAffiliateInfoWithPayment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 定时同步(每分钟一次)
|
||||||
|
@Scheduled(fixedRate = 60000)
|
||||||
|
public void syncLinkViewCountToDB(){
|
||||||
|
affiliateService.syncLinkViewCountToDB();
|
||||||
|
}
|
||||||
|
|
||||||
// @Scheduled(cron = "0 0 8 28-31 * ?")
|
// @Scheduled(cron = "0 0 8 28-31 * ?")
|
||||||
public void commissionSummaryReminder(){
|
public void commissionSummaryReminder(){
|
||||||
// 每个月末的最后一天的早上八点执行
|
// 每个月末的最后一天的早上八点执行
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import io.netty.util.internal.StringUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
@@ -379,6 +380,15 @@ public class RedisUtil {
|
|||||||
return redisTemplate.opsForValue().increment(key, 0);
|
return redisTemplate.opsForValue().increment(key, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getAndSetKey(String key, Long count) {
|
||||||
|
try {
|
||||||
|
String val = redisTemplate.opsForValue().getAndSet(key, count.toString());
|
||||||
|
return StringUtil.isNullOrEmpty(val) ? 0L : Long.parseLong(val);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return 0L; // 或 throw new BusinessException("非法的数值格式");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录任务的耗时到Redis
|
* 记录任务的耗时到Redis
|
||||||
* @param taskKey 任务标识,如 "taskA"
|
* @param taskKey 任务标识,如 "taskA"
|
||||||
|
|||||||
@@ -762,7 +762,7 @@ public class SendEmailUtil {
|
|||||||
try {
|
try {
|
||||||
String merchantEmail = "kimwong@code-create.com.hk";
|
String merchantEmail = "kimwong@code-create.com.hk";
|
||||||
String developer = "xupei3360@163.com";
|
String developer = "xupei3360@163.com";
|
||||||
String[] receiverEmail = {merchantEmail, developer};
|
String[] receiverEmail = {/*merchantEmail,*/ developer};
|
||||||
Credential cred = new Credential(SECRET_ID, SECRET_KEy);
|
Credential cred = new Credential(SECRET_ID, SECRET_KEy);
|
||||||
// 实例化一个http选项,可选的,没有特殊需求可以跳过
|
// 实例化一个http选项,可选的,没有特殊需求可以跳过
|
||||||
HttpProfile httpProfile = new HttpProfile();
|
HttpProfile httpProfile = new HttpProfile();
|
||||||
@@ -932,7 +932,7 @@ public class SendEmailUtil {
|
|||||||
req.setFromEmailAddress(SEND_ADDRESS);
|
req.setFromEmailAddress(SEND_ADDRESS);
|
||||||
String merchantEmail = "kimwong@code-create.com.hk";
|
String merchantEmail = "kimwong@code-create.com.hk";
|
||||||
String developerEmail = "xupei@code-create.com.hk";
|
String developerEmail = "xupei@code-create.com.hk";
|
||||||
req.setDestination(new String[]{merchantEmail, developerEmail});
|
req.setDestination(new String[]{/*merchantEmail,*/ developerEmail});
|
||||||
Template template = new Template();
|
Template template = new Template();
|
||||||
req.setSubject("New Credit Purchase Order");
|
req.setSubject("New Credit Purchase Order");
|
||||||
template.setTemplateID(CREDITS_PURCHASE_MERCHANT);
|
template.setTemplateID(CREDITS_PURCHASE_MERCHANT);
|
||||||
|
|||||||
@@ -4,17 +4,24 @@ package com.ai.da.controller;
|
|||||||
import com.ai.da.common.response.PageBaseResponse;
|
import com.ai.da.common.response.PageBaseResponse;
|
||||||
import com.ai.da.common.response.Response;
|
import com.ai.da.common.response.Response;
|
||||||
import com.ai.da.model.dto.AffiliateQueryDTO;
|
import com.ai.da.model.dto.AffiliateQueryDTO;
|
||||||
|
import com.ai.da.model.dto.EditReferralDTO;
|
||||||
|
import com.ai.da.model.dto.ReferralPageQueryDTO;
|
||||||
import com.ai.da.model.vo.AffiliateInvitationDetailsVO;
|
import com.ai.da.model.vo.AffiliateInvitationDetailsVO;
|
||||||
import com.ai.da.model.vo.AffiliateVO;
|
import com.ai.da.model.vo.AffiliateVO;
|
||||||
|
import com.ai.da.model.vo.ReferralPageQueryVO;
|
||||||
import com.ai.da.service.AffiliateService;
|
import com.ai.da.service.AffiliateService;
|
||||||
|
import com.ai.da.service.ReferralService;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@@ -25,6 +32,9 @@ public class AffiliateController {
|
|||||||
@Resource
|
@Resource
|
||||||
private AffiliateService affiliateService;
|
private AffiliateService affiliateService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ReferralService referralService;
|
||||||
|
|
||||||
@ApiOperation(value = "注册成为affiliate")
|
@ApiOperation(value = "注册成为affiliate")
|
||||||
@GetMapping("/registration")
|
@GetMapping("/registration")
|
||||||
public Response<Boolean> completeGuidance(@RequestParam(value = "promotionMethod", required = false) String promotionMethod) {
|
public Response<Boolean> completeGuidance(@RequestParam(value = "promotionMethod", required = false) String promotionMethod) {
|
||||||
@@ -45,7 +55,7 @@ public class AffiliateController {
|
|||||||
|
|
||||||
@ApiOperation(value = "获取个人佣金图表数据")
|
@ApiOperation(value = "获取个人佣金图表数据")
|
||||||
@GetMapping("/getPersonalMonthlyIncome")
|
@GetMapping("/getPersonalMonthlyIncome")
|
||||||
public Response<double[]> getPersonalMonthlyIncome(@RequestParam("year")int year) {
|
public Response<BigDecimal[]> getPersonalMonthlyIncome(@RequestParam("year")int year) {
|
||||||
return Response.success(affiliateService.getPersonalMonthlyIncome(year));
|
return Response.success(affiliateService.getPersonalMonthlyIncome(year));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,9 +96,29 @@ public class AffiliateController {
|
|||||||
|
|
||||||
@ApiOperation(value = "获取每个affiliate产生的收入")
|
@ApiOperation(value = "获取每个affiliate产生的收入")
|
||||||
@PostMapping("/getEachAffiliateGeneratedRevenue")
|
@PostMapping("/getEachAffiliateGeneratedRevenue")
|
||||||
public Response<IPage<AffiliateInvitationDetailsVO>> getEachAffiliateGeneratedRevenue(@RequestBody AffiliateQueryDTO affiliateQueryDTO) {
|
public Response<IPage<AffiliateInvitationDetailsVO>> getEachAffiliateGeneratedRevenue(@Validated @RequestBody AffiliateQueryDTO affiliateQueryDTO) {
|
||||||
return Response.success(affiliateService.getEachAffiliateGeneratedRevenue(affiliateQueryDTO));
|
return Response.success(affiliateService.getEachAffiliateGeneratedRevenue(affiliateQueryDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "获取所有的referral")
|
||||||
|
@PostMapping("/getReferrals")
|
||||||
|
public Response<IPage<ReferralPageQueryVO>> getReferrals(@RequestBody ReferralPageQueryDTO referralPageQueryDTO) {
|
||||||
|
return Response.success(referralService.queryByPage(referralPageQueryDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "编辑单个referral")
|
||||||
|
@PostMapping("/editReferral")
|
||||||
|
public Response<String> editReferral(@Validated @RequestBody EditReferralDTO editReferralDTO) {
|
||||||
|
referralService.editReferral(editReferralDTO);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "(批量)删除referral")
|
||||||
|
@PostMapping("/batchDeleteReferral")
|
||||||
|
public Response<String> batchDeleteReferral(@RequestBody List<Long> idList) {
|
||||||
|
referralService.deleteReferral(idList);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
package com.ai.da.mapper.primary;
|
|
||||||
|
|
||||||
import com.ai.da.mapper.primary.entity.AffiliateIncome;
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface AffiliateIncomeMapper extends BaseMapper<AffiliateIncome> {
|
|
||||||
|
|
||||||
List<Map<String, Object>> getPersonalMonthlyIncome(Long affiliateAccountId, int year);
|
|
||||||
|
|
||||||
List<Map<String, Object>> getMonthlyAffiliateIncome(int year, int month);
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@ public interface AffiliateMapper extends BaseMapper<Affiliate> {
|
|||||||
Map<String, Long> getMonthlyApprovedAffiliate(int year, int month);
|
Map<String, Long> getMonthlyApprovedAffiliate(int year, int month);
|
||||||
|
|
||||||
List<AffiliateVO> getAffiliateList(String status, String startTime, String endTime,
|
List<AffiliateVO> getAffiliateList(String status, String startTime, String endTime,
|
||||||
String order, Long affiliateId, int size, int offset);
|
String order, Long affiliateId, String sortField, int size, int offset);
|
||||||
|
|
||||||
int queryAffiliateTotalCount(String status, String startTime, String endTime, Long affiliateId);
|
int queryAffiliateTotalCount(String status, String startTime, String endTime, Long affiliateId);
|
||||||
|
|
||||||
|
|||||||
32
src/main/java/com/ai/da/mapper/primary/ReferralMapper.java
Normal file
32
src/main/java/com/ai/da/mapper/primary/ReferralMapper.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package com.ai.da.mapper.primary;
|
||||||
|
|
||||||
|
import com.ai.da.mapper.primary.entity.Referral;
|
||||||
|
import com.ai.da.model.vo.ReferralPageQueryVO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface ReferralMapper extends BaseMapper<Referral> {
|
||||||
|
// 使用自定义SQL进行分页查询
|
||||||
|
IPage<ReferralPageQueryVO> selectReferralWithAffiliate(Page<ReferralPageQueryVO> page, @Param("ew") Wrapper<ReferralPageQueryVO> wrapper);
|
||||||
|
|
||||||
|
void batchDeleteByIds(List<Long> ids);
|
||||||
|
|
||||||
|
BigDecimal sumAmount(
|
||||||
|
Long affiliateId,
|
||||||
|
List<String> statusList, // 改为 List 类型
|
||||||
|
LocalDateTime startTime, // 开始时间(可选)
|
||||||
|
LocalDateTime endTime // 结束时间(可选)
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Map<String, Object>> getPersonalMonthlyIncome(Long affiliateAccountId, int year);
|
||||||
|
|
||||||
|
List<Map<String, Object>> getMonthlyAffiliateIncome(int year, int month);
|
||||||
|
}
|
||||||
@@ -22,7 +22,8 @@ public class Affiliate extends BaseEntity{
|
|||||||
|
|
||||||
private Float unpaidEarnings = 0.00F;
|
private Float unpaidEarnings = 0.00F;
|
||||||
|
|
||||||
private Integer visits = 0;
|
// 邀请链接的访问人数,每分钟从redis同步到数据库
|
||||||
|
private Long visits = 0L;
|
||||||
|
|
||||||
private Boolean approved = false;
|
private Boolean approved = false;
|
||||||
|
|
||||||
|
|||||||
39
src/main/java/com/ai/da/mapper/primary/entity/Referral.java
Normal file
39
src/main/java/com/ai/da/mapper/primary/entity/Referral.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("t_referral")
|
||||||
|
public class Referral extends BaseEntity{
|
||||||
|
|
||||||
|
// 佣金
|
||||||
|
private BigDecimal commission;
|
||||||
|
|
||||||
|
private Long affiliateId;
|
||||||
|
|
||||||
|
// affiliate的accountId
|
||||||
|
private Long affiliateAccountId;
|
||||||
|
|
||||||
|
// 产生当前订单的受邀者accountId
|
||||||
|
private Long inviteeAccountId;
|
||||||
|
|
||||||
|
// 当前订单的总金额(订阅金额)
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
// 产生该笔佣金时的佣金百分比
|
||||||
|
private Float commissionPercent;
|
||||||
|
|
||||||
|
// 产生该笔佣金的订单(payment_info id)
|
||||||
|
private Long paymentInfoId;
|
||||||
|
|
||||||
|
// 状态 Pending || Accept || Rejected || Paid || Unpaid
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
private Integer isDeleted = 0;
|
||||||
|
|
||||||
|
private LocalDateTime paymentTime;
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("查询affiliate列表")
|
@ApiModel("查询affiliate列表")
|
||||||
@@ -15,6 +17,10 @@ public class AffiliateQueryDTO extends TimeQueryBaseDTO{
|
|||||||
@ApiModelProperty("推广者id")
|
@ApiModelProperty("推广者id")
|
||||||
private Long affiliateId;
|
private Long affiliateId;
|
||||||
|
|
||||||
|
@NotBlank(message = "orderBy cannot be empty")
|
||||||
|
@ApiModelProperty("目前允许按id, createTime, totalIncome进行排序")
|
||||||
|
private String orderBy;
|
||||||
|
|
||||||
@ApiModelProperty("按时间 DESC 降序 || ASC 升序")
|
@ApiModelProperty("按时间 DESC 降序 || ASC 升序")
|
||||||
private String order = "ASC";
|
private String order = "ASC";
|
||||||
|
|
||||||
|
|||||||
18
src/main/java/com/ai/da/model/dto/EditReferralDTO.java
Normal file
18
src/main/java/com/ai/da/model/dto/EditReferralDTO.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class EditReferralDTO {
|
||||||
|
@NotNull(message = "referral id cannot be empty")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
@Pattern(regexp = "Paid|Unpaid|Accept|Rejected", message = "状态必须是Paid/Unpaid/Accept/Rejected")
|
||||||
|
private String status;
|
||||||
|
}
|
||||||
13
src/main/java/com/ai/da/model/dto/ReferralPageQueryDTO.java
Normal file
13
src/main/java/com/ai/da/model/dto/ReferralPageQueryDTO.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class ReferralPageQueryDTO extends TimeQueryBaseDTO {
|
||||||
|
|
||||||
|
private Long affiliateId;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ public enum StyleEnum {
|
|||||||
LOLITA("洛丽塔", "Lolita"),
|
LOLITA("洛丽塔", "Lolita"),
|
||||||
Y2K("Y2K", "Y2K"),
|
Y2K("Y2K", "Y2K"),
|
||||||
BUSINESS("商务风", "Business"),
|
BUSINESS("商务风", "Business"),
|
||||||
MERLAD("美拉德", "Merlad"),
|
MERLAD("梅拉德", "Merlad"),
|
||||||
OUTDOOR_FUNCTIONAL("户外机能", "Outdoor Functional"),
|
OUTDOOR_FUNCTIONAL("户外机能", "Outdoor Functional"),
|
||||||
ROCK("摇滚", "Rock"),
|
ROCK("摇滚", "Rock"),
|
||||||
DOPAMINE("多巴胺", "Dopamine"),
|
DOPAMINE("多巴胺", "Dopamine"),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -16,9 +17,9 @@ public class AffiliateInvitationDetailsVO {
|
|||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
private Float firstSubscriptionPaymentAmount;
|
private BigDecimal firstSubscriptionPaymentAmount;
|
||||||
|
|
||||||
private Float commission;
|
private BigDecimal commission;
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
|
||||||
private LocalDateTime time;
|
private LocalDateTime time;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class AffiliateVO extends Affiliate {
|
public class AffiliateVO extends Affiliate {
|
||||||
|
|
||||||
private Long linkViewCount;
|
// private Long linkViewCount;
|
||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
|
|||||||
11
src/main/java/com/ai/da/model/vo/ReferralPageQueryVO.java
Normal file
11
src/main/java/com/ai/da/model/vo/ReferralPageQueryVO.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package com.ai.da.model.vo;
|
||||||
|
|
||||||
|
import com.ai.da.mapper.primary.entity.Referral;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class ReferralPageQueryVO extends Referral {
|
||||||
|
private String affiliateName;
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ import com.ai.da.model.vo.AffiliateVO;
|
|||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
public interface AffiliateService extends IService<Affiliate> {
|
public interface AffiliateService extends IService<Affiliate> {
|
||||||
|
|
||||||
Boolean registerAsAnAffiliate(String promotionMethod);
|
Boolean registerAsAnAffiliate(String promotionMethod);
|
||||||
@@ -16,7 +18,7 @@ public interface AffiliateService extends IService<Affiliate> {
|
|||||||
|
|
||||||
AffiliateVO personalAffiliateCenter();
|
AffiliateVO personalAffiliateCenter();
|
||||||
|
|
||||||
double[] getPersonalMonthlyIncome(int year);
|
BigDecimal[] getPersonalMonthlyIncome(int year);
|
||||||
|
|
||||||
Boolean applicationApproval(Long id, Boolean isApproved, Float commission);
|
Boolean applicationApproval(Long id, Boolean isApproved, Float commission);
|
||||||
|
|
||||||
@@ -26,6 +28,8 @@ public interface AffiliateService extends IService<Affiliate> {
|
|||||||
|
|
||||||
Boolean affiliateLinkViewsIncrease(Long id);
|
Boolean affiliateLinkViewsIncrease(Long id);
|
||||||
|
|
||||||
|
void syncLinkViewCountToDB();
|
||||||
|
|
||||||
IPage<AffiliateInvitationDetailsVO> getEachAffiliateGeneratedRevenue(AffiliateQueryDTO affiliateQueryDTO);
|
IPage<AffiliateInvitationDetailsVO> getEachAffiliateGeneratedRevenue(AffiliateQueryDTO affiliateQueryDTO);
|
||||||
|
|
||||||
Affiliate getByAccountId(Long accountId);
|
Affiliate getByAccountId(Long accountId);
|
||||||
|
|||||||
19
src/main/java/com/ai/da/service/ReferralService.java
Normal file
19
src/main/java/com/ai/da/service/ReferralService.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package com.ai.da.service;
|
||||||
|
|
||||||
|
import com.ai.da.mapper.primary.entity.Referral;
|
||||||
|
import com.ai.da.model.dto.EditReferralDTO;
|
||||||
|
import com.ai.da.model.dto.ReferralPageQueryDTO;
|
||||||
|
import com.ai.da.model.vo.ReferralPageQueryVO;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ReferralService extends IService<Referral> {
|
||||||
|
|
||||||
|
IPage<ReferralPageQueryVO> queryByPage(ReferralPageQueryDTO referralPageQueryDTO);
|
||||||
|
|
||||||
|
void editReferral(EditReferralDTO editReferralDTO);
|
||||||
|
|
||||||
|
void deleteReferral(List<Long> idList);
|
||||||
|
}
|
||||||
@@ -8,10 +8,7 @@ import com.ai.da.common.response.ResultEnum;
|
|||||||
import com.ai.da.common.utils.CopyUtil;
|
import com.ai.da.common.utils.CopyUtil;
|
||||||
import com.ai.da.common.utils.RedisUtil;
|
import com.ai.da.common.utils.RedisUtil;
|
||||||
import com.ai.da.common.utils.SendEmailUtil;
|
import com.ai.da.common.utils.SendEmailUtil;
|
||||||
import com.ai.da.mapper.primary.AffiliateIncomeMapper;
|
import com.ai.da.mapper.primary.*;
|
||||||
import com.ai.da.mapper.primary.AffiliateMapper;
|
|
||||||
import com.ai.da.mapper.primary.ProductCouponsMapper;
|
|
||||||
import com.ai.da.mapper.primary.SubscriptionInfoMapper;
|
|
||||||
import com.ai.da.mapper.primary.entity.*;
|
import com.ai.da.mapper.primary.entity.*;
|
||||||
import com.ai.da.model.dto.AffiliateEmailParamsDTO;
|
import com.ai.da.model.dto.AffiliateEmailParamsDTO;
|
||||||
import com.ai.da.model.dto.AffiliateQueryDTO;
|
import com.ai.da.model.dto.AffiliateQueryDTO;
|
||||||
@@ -20,6 +17,7 @@ import com.ai.da.model.vo.AffiliateVO;
|
|||||||
import com.ai.da.model.vo.AuthPrincipalVo;
|
import com.ai.da.model.vo.AuthPrincipalVo;
|
||||||
import com.ai.da.service.*;
|
import com.ai.da.service.*;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
@@ -35,6 +33,8 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static com.ai.da.common.utils.RedisUtil.AFFILIATE_LINK_VIEW_KEY;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate> implements AffiliateService {
|
public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate> implements AffiliateService {
|
||||||
@@ -48,7 +48,9 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
|||||||
@Resource
|
@Resource
|
||||||
private SubscriptionInfoMapper subscriptionInfoMapper;
|
private SubscriptionInfoMapper subscriptionInfoMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private AffiliateIncomeMapper affiliateIncomeMapper;
|
private ReferralService referralService;
|
||||||
|
@Resource
|
||||||
|
private ReferralMapper referralMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private StripeService stripeService;
|
private StripeService stripeService;
|
||||||
@Resource
|
@Resource
|
||||||
@@ -75,7 +77,7 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
|||||||
// 邮件通知审批者
|
// 邮件通知审批者
|
||||||
String merchantEmail = "kimwong@code-create.com.hk";
|
String merchantEmail = "kimwong@code-create.com.hk";
|
||||||
String developer = "xupei3360@163.com";
|
String developer = "xupei3360@163.com";
|
||||||
String[] receiverEmail = {merchantEmail, developer};
|
String[] receiverEmail = {/*merchantEmail, */developer};
|
||||||
SendEmailUtil.affiliateEmailReminder(receiverEmail, new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
|
SendEmailUtil.affiliateEmailReminder(receiverEmail, new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
|
||||||
// emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
|
// emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
|
||||||
}else {
|
}else {
|
||||||
@@ -88,11 +90,16 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
|||||||
log.info("parameter => {}", affiliateQueryDTO.toString());
|
log.info("parameter => {}", affiliateQueryDTO.toString());
|
||||||
|
|
||||||
int offset = (affiliateQueryDTO.getPage() - 1) * affiliateQueryDTO.getSize();
|
int offset = (affiliateQueryDTO.getPage() - 1) * affiliateQueryDTO.getSize();
|
||||||
|
String orderBy = affiliateQueryDTO.getOrderBy() == null ? "create_time" :
|
||||||
|
affiliateQueryDTO.getOrderBy().equals("id") ? "id" :
|
||||||
|
affiliateQueryDTO.getOrderBy().equals("totalIncome") ? "total_earnings" :
|
||||||
|
"create_time";
|
||||||
List<AffiliateVO> affiliateList = baseMapper.getAffiliateList(affiliateQueryDTO.getStatus(),
|
List<AffiliateVO> affiliateList = baseMapper.getAffiliateList(affiliateQueryDTO.getStatus(),
|
||||||
affiliateQueryDTO.getStartTime(),
|
affiliateQueryDTO.getStartTime(),
|
||||||
affiliateQueryDTO.getEndTime(),
|
affiliateQueryDTO.getEndTime(),
|
||||||
affiliateQueryDTO.getOrder(),
|
affiliateQueryDTO.getOrder(),
|
||||||
affiliateQueryDTO.getAffiliateId(),
|
affiliateQueryDTO.getAffiliateId(),
|
||||||
|
orderBy,
|
||||||
affiliateQueryDTO.getSize(),
|
affiliateQueryDTO.getSize(),
|
||||||
offset
|
offset
|
||||||
);
|
);
|
||||||
@@ -133,17 +140,17 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
|||||||
qw.eq("account_id", accountId);
|
qw.eq("account_id", accountId);
|
||||||
Affiliate affiliate = baseMapper.selectOne(qw);
|
Affiliate affiliate = baseMapper.selectOne(qw);
|
||||||
AffiliateVO affiliateVO = CopyUtil.copyObject(affiliate, AffiliateVO.class);
|
AffiliateVO affiliateVO = CopyUtil.copyObject(affiliate, AffiliateVO.class);
|
||||||
affiliateVO.setLinkViewCount(getAffiliateLinkViewCount(affiliate.getId()));
|
|
||||||
return affiliateVO;
|
return affiliateVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double[] getPersonalMonthlyIncome(int year){
|
public BigDecimal[] getPersonalMonthlyIncome(int year){
|
||||||
Long accountId = UserContext.getUserHolder().getId();
|
Long accountId = UserContext.getUserHolder().getId();
|
||||||
List<Map<String, Object>> personalMonthlyIncome = affiliateIncomeMapper.getPersonalMonthlyIncome(accountId, year);
|
List<Map<String, Object>> personalMonthlyIncome = referralMapper.getPersonalMonthlyIncome(accountId, year);
|
||||||
double[] commissions = new double[12];
|
BigDecimal[] commissions = new BigDecimal[12];
|
||||||
|
Arrays.fill(commissions, BigDecimal.ZERO);
|
||||||
personalMonthlyIncome.forEach(income -> {
|
personalMonthlyIncome.forEach(income -> {
|
||||||
int month = Integer.parseInt(income.get("yearMonth").toString());
|
int month = Integer.parseInt(income.get("yearMonth").toString());
|
||||||
commissions[month-1] = (double)income.get("totalCommission");
|
commissions[month-1] = (BigDecimal) income.get("totalCommission");
|
||||||
});
|
});
|
||||||
|
|
||||||
return commissions;
|
return commissions;
|
||||||
@@ -206,10 +213,14 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
|||||||
String currentTime = LocalDateTime.now().toString();
|
String currentTime = LocalDateTime.now().toString();
|
||||||
// 1、查上次更新之后有无新订单
|
// 1、查上次更新之后有无新订单
|
||||||
QueryWrapper<PaymentInfo> queryWrapper = new QueryWrapper<>();
|
QueryWrapper<PaymentInfo> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.lambda().eq(PaymentInfo::getTradeState, "paid")
|
||||||
|
.and(wrapper -> wrapper
|
||||||
|
.eq(PaymentInfo::getType,"new")
|
||||||
|
.or()
|
||||||
|
.eq(PaymentInfo::getType, "manual"));
|
||||||
if (!StringUtil.isNullOrEmpty(lastTime)){
|
if (!StringUtil.isNullOrEmpty(lastTime)){
|
||||||
queryWrapper.gt("create_time", lastTime);
|
queryWrapper.lambda().gt(PaymentInfo::getCreateTime, lastTime);
|
||||||
}
|
}
|
||||||
queryWrapper.eq("type","new").eq("trade_state", "paid");
|
|
||||||
|
|
||||||
List<PaymentInfo> paymentInfos = paymentInfoService.getBaseMapper().selectList(queryWrapper);
|
List<PaymentInfo> paymentInfos = paymentInfoService.getBaseMapper().selectList(queryWrapper);
|
||||||
if (!paymentInfos.isEmpty()){
|
if (!paymentInfos.isEmpty()){
|
||||||
@@ -232,33 +243,41 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
|||||||
log.info("结算订单id为{}的佣金", orderInfo.getId());
|
log.info("结算订单id为{}的佣金", orderInfo.getId());
|
||||||
// 3、若有, 直接更新affiliate的所得
|
// 3、若有, 直接更新affiliate的所得
|
||||||
Affiliate affiliate = baseMapper.selectById(account.getInvitationCode());
|
Affiliate affiliate = baseMapper.selectById(account.getInvitationCode());
|
||||||
|
if (Objects.isNull(affiliate)){
|
||||||
|
log.error("未知affiliate Id:{}, 关联订单:{}", account.getInvitationCode(), orderInfo.getOrderNo());
|
||||||
|
return;
|
||||||
|
}
|
||||||
Float payerTotal = paymentInfo.getPayerTotal();
|
Float payerTotal = paymentInfo.getPayerTotal();
|
||||||
|
|
||||||
if (payerTotal > 0){
|
if (payerTotal > 0){
|
||||||
// 分配新用户首次订阅所付费用 预设的佣金比例 作为佣金
|
// 分配新用户首次订阅所付费用 预设的佣金比例 作为佣金
|
||||||
|
// 逻辑修改。只有当该笔referral被审批通过后才被计算为推广者的佣金
|
||||||
BigDecimal commission = BigDecimal.valueOf(payerTotal).multiply(BigDecimal.valueOf(affiliate.getCommissionPercent() / 100));
|
BigDecimal commission = BigDecimal.valueOf(payerTotal).multiply(BigDecimal.valueOf(affiliate.getCommissionPercent() / 100));
|
||||||
BigDecimal monthlyEarning = BigDecimal.valueOf(affiliate.getMonthlyEarnings()).add(commission);
|
/*BigDecimal monthlyEarning = BigDecimal.valueOf(affiliate.getMonthlyEarnings()).add(commission);
|
||||||
BigDecimal unpaidEarnings = BigDecimal.valueOf(affiliate.getUnpaidEarnings()).add(commission);
|
BigDecimal unpaidEarnings = BigDecimal.valueOf(affiliate.getUnpaidEarnings()).add(commission);
|
||||||
int visits = affiliate.getVisits() + 1;
|
int visits = affiliate.getVisits() + 1;
|
||||||
affiliate.setMonthlyEarnings(monthlyEarning.floatValue());
|
affiliate.setMonthlyEarnings(monthlyEarning.floatValue());
|
||||||
affiliate.setUnpaidEarnings(unpaidEarnings.floatValue());
|
affiliate.setUnpaidEarnings(unpaidEarnings.floatValue());
|
||||||
affiliate.setVisits(visits);
|
affiliate.setVisits(visits);
|
||||||
affiliate.setUpdateTime(LocalDateTime.now());
|
affiliate.setUpdateTime(LocalDateTime.now());
|
||||||
baseMapper.updateById(affiliate);
|
baseMapper.updateById(affiliate);*/
|
||||||
|
|
||||||
orderInfo.setIsCommissionCalculated((byte)1);
|
orderInfo.setIsCommissionCalculated((byte)1);
|
||||||
|
|
||||||
// 4、添加到t_affiliate_income
|
// 4、添加到referral
|
||||||
AffiliateIncome affiliateIncome = new AffiliateIncome();
|
Referral referral = new Referral();
|
||||||
affiliateIncome.setAffiliateId(affiliate.getId());
|
referral.setAffiliateId(affiliate.getId());
|
||||||
affiliateIncome.setAffiliateAccountId(affiliate.getAccountId());
|
referral.setAffiliateAccountId(affiliate.getAccountId());
|
||||||
affiliateIncome.setInviteeAccountId(accountId);
|
referral.setInviteeAccountId(accountId);
|
||||||
affiliateIncome.setAmount(payerTotal);
|
referral.setAmount(BigDecimal.valueOf(payerTotal));
|
||||||
affiliateIncome.setPaymentInfoId(paymentInfo.getId());
|
referral.setPaymentInfoId(paymentInfo.getId());
|
||||||
affiliateIncome.setPaymentTime(paymentInfo.getCreateTime());
|
referral.setPaymentTime(paymentInfo.getCreateTime());
|
||||||
affiliateIncome.setCommission(commission.floatValue());
|
referral.setCommission(BigDecimal.valueOf(commission.floatValue()));
|
||||||
affiliateIncome.setCreateTime(LocalDateTime.now());
|
referral.setCommissionPercent(affiliate.getCommissionPercent());
|
||||||
affiliateIncomeMapper.insert(affiliateIncome);
|
referral.setStatus("Pending");
|
||||||
|
referral.setCreateTime(LocalDateTime.now());
|
||||||
|
int insert = referralService.getBaseMapper().insert(referral);
|
||||||
|
log.info("向Referral中插入 {} 条数据", insert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
orderInfo.setIsFirstSubscription((byte)1);
|
orderInfo.setIsFirstSubscription((byte)1);
|
||||||
@@ -279,6 +298,30 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
|||||||
return redisUtil.getAffiliateLinkViewCount(affiliateId);
|
return redisUtil.getAffiliateLinkViewCount(affiliateId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void syncLinkViewCountToDB() {
|
||||||
|
// 1、获取当前所有激活状态的affiliate
|
||||||
|
List<Affiliate> affiliateList = baseMapper.selectList(new QueryWrapper<Affiliate>().lambda().eq(Affiliate::getStatus, "Active"));
|
||||||
|
|
||||||
|
// 2、获取redis中各自的viewCount
|
||||||
|
for (Affiliate affiliate : affiliateList){
|
||||||
|
String redisKey = AFFILIATE_LINK_VIEW_KEY + affiliate.getId();
|
||||||
|
|
||||||
|
// 原子性获取并重置为0
|
||||||
|
Long redisCount = redisUtil.getAndSetKey(redisKey, 0L);
|
||||||
|
|
||||||
|
if (redisCount != null && redisCount > 0) {
|
||||||
|
// 累加到数据库
|
||||||
|
baseMapper.update(
|
||||||
|
null,
|
||||||
|
new UpdateWrapper<Affiliate>()
|
||||||
|
.setSql("visits = visits + " + redisCount)
|
||||||
|
.set("update_time", LocalDateTime.now())
|
||||||
|
.eq("id", affiliate.getId())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 查看每个affiliate带来收入的详情
|
// 查看每个affiliate带来收入的详情
|
||||||
@Override
|
@Override
|
||||||
public IPage<AffiliateInvitationDetailsVO> getEachAffiliateGeneratedRevenue(AffiliateQueryDTO affiliateQueryDTO) {
|
public IPage<AffiliateInvitationDetailsVO> getEachAffiliateGeneratedRevenue(AffiliateQueryDTO affiliateQueryDTO) {
|
||||||
@@ -286,14 +329,14 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
|||||||
throw new BusinessException("Please specify the affiliate ID.", ResultEnum.PROMPT.getCode());
|
throw new BusinessException("Please specify the affiliate ID.", ResultEnum.PROMPT.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryWrapper<AffiliateIncome> affiliateIncomeQueryWrapper = new QueryWrapper<>();
|
QueryWrapper<Referral> referralQueryWrapper = new QueryWrapper<>();
|
||||||
affiliateIncomeQueryWrapper
|
referralQueryWrapper
|
||||||
.gt(!StringUtils.isNullOrEmpty(affiliateQueryDTO.getStartTime()), "create_time", affiliateQueryDTO.getStartTime())
|
.gt(!StringUtils.isNullOrEmpty(affiliateQueryDTO.getStartTime()), "create_time", affiliateQueryDTO.getStartTime())
|
||||||
.lt(!StringUtils.isNullOrEmpty(affiliateQueryDTO.getEndTime()), "create_time", affiliateQueryDTO.getEndTime())
|
.lt(!StringUtils.isNullOrEmpty(affiliateQueryDTO.getEndTime()), "create_time", affiliateQueryDTO.getEndTime())
|
||||||
.eq(!Objects.isNull(affiliateQueryDTO.getAffiliateId()), "affiliate_id", affiliateQueryDTO.getAffiliateId())
|
.eq(!Objects.isNull(affiliateQueryDTO.getAffiliateId()), "affiliate_id", affiliateQueryDTO.getAffiliateId())
|
||||||
.orderByDesc(affiliateQueryDTO.getOrder().equals("DESC"), "create_time");
|
.orderByDesc(affiliateQueryDTO.getOrder().equals("DESC"), "create_time");
|
||||||
IPage<AffiliateIncome> affiliateIncomePage = affiliateIncomeMapper.selectPage(new Page<>(affiliateQueryDTO.getPage(), affiliateQueryDTO.getSize()), affiliateIncomeQueryWrapper);
|
IPage<Referral> affiliateIncomePage = referralMapper.selectPage(new Page<>(affiliateQueryDTO.getPage(), affiliateQueryDTO.getSize()), referralQueryWrapper);
|
||||||
return affiliateIncomePage.convert((Function<AffiliateIncome, AffiliateInvitationDetailsVO>) affiliateIncome -> {
|
return affiliateIncomePage.convert((Function<Referral, AffiliateInvitationDetailsVO>) affiliateIncome -> {
|
||||||
AffiliateInvitationDetailsVO affiliateInvitationDetailsVO = CopyUtil.copyObject(affiliateIncome, AffiliateInvitationDetailsVO.class);
|
AffiliateInvitationDetailsVO affiliateInvitationDetailsVO = CopyUtil.copyObject(affiliateIncome, AffiliateInvitationDetailsVO.class);
|
||||||
affiliateInvitationDetailsVO.setAccountId(affiliateIncome.getInviteeAccountId());
|
affiliateInvitationDetailsVO.setAccountId(affiliateIncome.getInviteeAccountId());
|
||||||
affiliateInvitationDetailsVO.setUsername(accountService.getBaseMapper().selectById(affiliateIncome.getInviteeAccountId()).getUserName());
|
affiliateInvitationDetailsVO.setUsername(accountService.getBaseMapper().selectById(affiliateIncome.getInviteeAccountId()).getUserName());
|
||||||
@@ -312,14 +355,16 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
|||||||
month = LocalDateTime.now().getMonthValue();
|
month = LocalDateTime.now().getMonthValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Map<String, Object>> monthlyAffiliateIncome = affiliateIncomeMapper.getMonthlyAffiliateIncome(year, month);
|
List<Map<String, Object>> monthlyAffiliateIncome = referralMapper.getMonthlyAffiliateIncome(year, month);
|
||||||
// 1、总收入(近一个月通过affiliate产生的收入),未支付的金额 affiliate表中unpaid的总和
|
// 1、总收入(近一个月通过affiliate产生的收入),未支付的金额 affiliate表中unpaid的总和
|
||||||
Double totalAmount = 0.0;
|
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||||
Double totalCommission = 0.0;
|
BigDecimal paidCommission = BigDecimal.ZERO;
|
||||||
|
BigDecimal unpaidCommission = BigDecimal.ZERO;
|
||||||
if (!monthlyAffiliateIncome.isEmpty()){
|
if (!monthlyAffiliateIncome.isEmpty()){
|
||||||
Map<String, Object> monthlyIncome = monthlyAffiliateIncome.get(0);
|
Map<String, Object> monthlyIncome = monthlyAffiliateIncome.get(0);
|
||||||
totalAmount = (Double) monthlyIncome.get("totalAmount");
|
totalAmount = (BigDecimal) monthlyIncome.get("totalAmount");
|
||||||
totalCommission = (Double) monthlyIncome.get("totalCommission");
|
paidCommission = (BigDecimal) monthlyIncome.get("paidCommission");
|
||||||
|
unpaidCommission = (BigDecimal) monthlyIncome.get("unpaidCommission");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2、本月新注册的Affiliate
|
// 2、本月新注册的Affiliate
|
||||||
@@ -329,12 +374,12 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
|||||||
AffiliateEmailParamsDTO affiliateEmailParamsDTO = new AffiliateEmailParamsDTO();
|
AffiliateEmailParamsDTO affiliateEmailParamsDTO = new AffiliateEmailParamsDTO();
|
||||||
affiliateEmailParamsDTO.setTotalProgramRevenue(totalAmount.toString());
|
affiliateEmailParamsDTO.setTotalProgramRevenue(totalAmount.toString());
|
||||||
affiliateEmailParamsDTO.setNewApprovedAffiliates(count.toString());
|
affiliateEmailParamsDTO.setNewApprovedAffiliates(count.toString());
|
||||||
affiliateEmailParamsDTO.setUnpaidEarnings(totalCommission.toString());
|
affiliateEmailParamsDTO.setUnpaidEarnings(String.valueOf(unpaidCommission));
|
||||||
affiliateEmailParamsDTO.setPaidEarnings("0");
|
affiliateEmailParamsDTO.setPaidEarnings(String.valueOf(paidCommission));
|
||||||
|
|
||||||
String merchantEmail = "kimwong@code-create.com.hk";
|
String merchantEmail = "kimwong@code-create.com.hk";
|
||||||
String developer = "xupei3360@163.com";
|
String developer = "xupei3360@163.com";
|
||||||
String[] receiverEmail = {merchantEmail, developer};
|
String[] receiverEmail = {/*merchantEmail,*/ developer};
|
||||||
// 邮件通知
|
// 邮件通知
|
||||||
SendEmailUtil.affiliateEmailReminder(receiverEmail, affiliateEmailParamsDTO, "summary");
|
SendEmailUtil.affiliateEmailReminder(receiverEmail, affiliateEmailParamsDTO, "summary");
|
||||||
// emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), affiliateEmailParamsDTO, "summary");
|
// emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), affiliateEmailParamsDTO, "summary");
|
||||||
|
|||||||
116
src/main/java/com/ai/da/service/impl/ReferralServiceImpl.java
Normal file
116
src/main/java/com/ai/da/service/impl/ReferralServiceImpl.java
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
package com.ai.da.service.impl;
|
||||||
|
|
||||||
|
import com.ai.da.mapper.primary.ReferralMapper;
|
||||||
|
import com.ai.da.mapper.primary.entity.Affiliate;
|
||||||
|
import com.ai.da.mapper.primary.entity.Referral;
|
||||||
|
import com.ai.da.model.dto.EditReferralDTO;
|
||||||
|
import com.ai.da.model.dto.ReferralPageQueryDTO;
|
||||||
|
import com.ai.da.model.vo.ReferralPageQueryVO;
|
||||||
|
import com.ai.da.service.AffiliateService;
|
||||||
|
import com.ai.da.service.ReferralService;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import io.netty.util.internal.StringUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.YearMonth;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ReferralServiceImpl extends ServiceImpl<ReferralMapper, Referral> implements ReferralService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AffiliateService affiliateService;
|
||||||
|
|
||||||
|
// Referral Recap
|
||||||
|
// 当有用户通过链接成功订阅AiDA后。这里应该要出现一笔待支付给affiliate的记录
|
||||||
|
// 每一笔交易需要管理员Accept才能被算为佣金(有审批这个过程)
|
||||||
|
|
||||||
|
// 查询所有referral (分页查)
|
||||||
|
// 允许按推广人用户名、记录产生时间、记录状态分页查询
|
||||||
|
public IPage<ReferralPageQueryVO> queryByPage(ReferralPageQueryDTO referralPageQueryDTO) {
|
||||||
|
// 1. 构建查询条件
|
||||||
|
QueryWrapper<ReferralPageQueryVO> queryWrapper = new QueryWrapper<>();
|
||||||
|
|
||||||
|
if (referralPageQueryDTO.getAffiliateId() != null && referralPageQueryDTO.getAffiliateId() != 0L) {
|
||||||
|
queryWrapper.eq("r.affiliate_id", referralPageQueryDTO.getAffiliateId());
|
||||||
|
}
|
||||||
|
if (!StringUtil.isNullOrEmpty(referralPageQueryDTO.getStartTime())) {
|
||||||
|
queryWrapper.gt("r.create_time", referralPageQueryDTO.getStartTime());
|
||||||
|
}
|
||||||
|
if (!StringUtil.isNullOrEmpty(referralPageQueryDTO.getEndTime())) {
|
||||||
|
queryWrapper.lt("r.create_time", referralPageQueryDTO.getEndTime());
|
||||||
|
}
|
||||||
|
if (!StringUtil.isNullOrEmpty(referralPageQueryDTO.getStatus()) && !"All Types".equals(referralPageQueryDTO.getStatus())) {
|
||||||
|
queryWrapper.eq("r.status", referralPageQueryDTO.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
queryWrapper.eq("r.is_deleted", 0);
|
||||||
|
|
||||||
|
// 2. 执行分页查询(返回的是 ReferralVO)
|
||||||
|
Page<ReferralPageQueryVO> page = new Page<>(referralPageQueryDTO.getPage(), referralPageQueryDTO.getSize());
|
||||||
|
return baseMapper.selectReferralWithAffiliate(page, queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑referral
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void editReferral(EditReferralDTO editReferralDTO){
|
||||||
|
Referral referral = baseMapper.selectById(editReferralDTO.getId());
|
||||||
|
if (Objects.nonNull(editReferralDTO.getAmount()) && editReferralDTO.getAmount().compareTo(referral.getCommission()) != 0){
|
||||||
|
log.info("设置referral id为{} 原佣金 {} 设置为 {}", referral.getId(), referral.getAffiliateId(), editReferralDTO.getAmount());
|
||||||
|
referral.setCommission(editReferralDTO.getAmount());
|
||||||
|
referral.setUpdateTime(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
if (!StringUtil.isNullOrEmpty(editReferralDTO.getStatus()) && !editReferralDTO.getStatus().equals(referral.getStatus())){
|
||||||
|
// 如果该笔佣金审批通过,则自动转为未支付状态
|
||||||
|
if (editReferralDTO.getStatus().equals("Accept")){
|
||||||
|
editReferralDTO.setStatus("Unpaid");
|
||||||
|
}
|
||||||
|
log.info("设置referral id为{} 原状态 {} 设置为 {}", referral.getId(), referral.getStatus(), editReferralDTO.getStatus());
|
||||||
|
referral.setStatus(editReferralDTO.getStatus());
|
||||||
|
referral.setUpdateTime(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
boolean b = updateById(referral);
|
||||||
|
|
||||||
|
if (b){
|
||||||
|
Affiliate affiliate = affiliateService.getBaseMapper().selectById(referral.getAffiliateId());
|
||||||
|
|
||||||
|
// 如果修改了referral的状态,则需要同步修改affiliate已支付或未支付的金额总数
|
||||||
|
// 在平台的总未支付
|
||||||
|
BigDecimal unpaid = baseMapper.sumAmount(referral.getAffiliateId(), Collections.singletonList("Unpaid"), null, null);
|
||||||
|
|
||||||
|
// 已支付和未支付的值肯定是同时发生变化
|
||||||
|
if (BigDecimal.valueOf(affiliate.getUnpaidEarnings()).compareTo(unpaid) != 0){
|
||||||
|
LocalDateTime start = YearMonth.now().atDay(1).atStartOfDay(); // 本月第一天 00:00:00
|
||||||
|
LocalDateTime end = YearMonth.now().atEndOfMonth().atTime(23, 59, 59);
|
||||||
|
// 本月的总收入(包括已支付和未支付)
|
||||||
|
BigDecimal monthlyEarning = baseMapper.sumAmount(referral.getAffiliateId(), Arrays.asList("Unpaid", "Paid"), start, end);
|
||||||
|
// 在平台的总收入
|
||||||
|
BigDecimal totalEarning = baseMapper.sumAmount(referral.getAffiliateId(), Arrays.asList("Unpaid", "Paid"), null, null);
|
||||||
|
affiliate.setUnpaidEarnings(Objects.nonNull(unpaid) ? unpaid.floatValue() : 0);
|
||||||
|
affiliate.setMonthlyEarnings(Objects.nonNull(monthlyEarning) ? monthlyEarning.floatValue() : 0);
|
||||||
|
affiliate.setTotalEarnings(Objects.nonNull(totalEarning) ? totalEarning.floatValue() : 0);
|
||||||
|
affiliate.setUpdateTime(LocalDateTime.now());
|
||||||
|
affiliateService.getBaseMapper().updateById(affiliate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
public void deleteReferral(List<Long> idList){
|
||||||
|
if (!idList.isEmpty()){
|
||||||
|
baseMapper.batchDeleteByIds(idList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
<mapper namespace="com.ai.da.mapper.primary.AffiliateIncomeMapper">
|
|
||||||
|
|
||||||
<select id="getPersonalMonthlyIncome" resultType="java.util.Map">
|
|
||||||
SELECT
|
|
||||||
DATE_FORMAT(payment_time, '%m') as yearMonth,
|
|
||||||
SUM(commission) AS totalCommission
|
|
||||||
FROM
|
|
||||||
t_affiliate_income
|
|
||||||
WHERE
|
|
||||||
YEAR(payment_time) = #{year}
|
|
||||||
and affiliate_account_id = #{affiliateAccountId}
|
|
||||||
GROUP BY
|
|
||||||
yearMonth
|
|
||||||
ORDER BY
|
|
||||||
yearMonth
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="getMonthlyAffiliateIncome" resultType="java.util.Map">
|
|
||||||
SELECT
|
|
||||||
DATE_FORMAT(payment_time, '%m') as yearMonth,
|
|
||||||
SUM(amount) AS totalAmount,
|
|
||||||
SUM(commission) AS totalCommission
|
|
||||||
FROM
|
|
||||||
t_affiliate_income
|
|
||||||
WHERE
|
|
||||||
YEAR(payment_time) = #{year}
|
|
||||||
and MONTH(payment_time) = #{month}
|
|
||||||
GROUP BY
|
|
||||||
yearMonth
|
|
||||||
ORDER BY
|
|
||||||
yearMonth
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</mapper>
|
|
||||||
@@ -38,12 +38,24 @@
|
|||||||
AND f.id = #{affiliateId}
|
AND f.id = #{affiliateId}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
<if test="order != null and order.toUpperCase() == 'DESC'">
|
<choose>
|
||||||
ORDER BY f.create_time DESC
|
<when test="sortField != null and sortField != ''">
|
||||||
</if>
|
ORDER BY
|
||||||
<if test="order == null or order.toUpperCase() != 'DESC'">
|
<choose>
|
||||||
|
<when test="sortField == 'id'">f.id</when>
|
||||||
|
<when test="sortField == 'totalEarnings'">f.total_earnings</when>
|
||||||
|
<when test="sortField == 'createTime'">f.create_time</when>
|
||||||
|
<otherwise>f.create_time</otherwise>
|
||||||
|
</choose>
|
||||||
|
<choose>
|
||||||
|
<when test="order != null and order.toUpperCase() == 'DESC'">DESC</when>
|
||||||
|
<otherwise>ASC</otherwise>
|
||||||
|
</choose>
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
ORDER BY f.create_time ASC
|
ORDER BY f.create_time ASC
|
||||||
</if>
|
</otherwise>
|
||||||
|
</choose>
|
||||||
LIMIT ${size} OFFSET ${offset}
|
LIMIT ${size} OFFSET ${offset}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|||||||
81
src/main/resources/mapper/primary/ReferralMapper.xml
Normal file
81
src/main/resources/mapper/primary/ReferralMapper.xml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ai.da.mapper.primary.ReferralMapper">
|
||||||
|
|
||||||
|
<!-- resources/mapper/ReferralMapper.xml -->
|
||||||
|
<select id="selectReferralWithAffiliate" resultType="com.ai.da.model.vo.ReferralPageQueryVO">
|
||||||
|
SELECT
|
||||||
|
r.*,
|
||||||
|
ac.user_name AS affiliateName
|
||||||
|
FROM
|
||||||
|
t_referral r
|
||||||
|
LEFT JOIN
|
||||||
|
t_account ac ON r.affiliate_account_id = ac.id
|
||||||
|
${ew.customSqlSegment} <!-- 动态条件 -->
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- Mapper.xml -->
|
||||||
|
<update id="batchDeleteByIds">
|
||||||
|
UPDATE t_referral
|
||||||
|
SET is_deleted = 1
|
||||||
|
WHERE id IN
|
||||||
|
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- Mapper.xml -->
|
||||||
|
<select id="sumAmount" resultType="java.math.BigDecimal">
|
||||||
|
SELECT SUM(commission)
|
||||||
|
FROM t_referral
|
||||||
|
WHERE affiliate_id = #{affiliateId}
|
||||||
|
<if test="statusList != null and statusList.size() > 0">
|
||||||
|
AND status IN
|
||||||
|
<foreach collection="statusList" item="status" open="(" separator="," close=")">
|
||||||
|
#{status}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<if test="startTime != null">
|
||||||
|
AND create_time >= #{startTime}
|
||||||
|
</if>
|
||||||
|
<if test="endTime != null">
|
||||||
|
AND create_time <![CDATA[<=]]> #{endTime}
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="getPersonalMonthlyIncome" resultType="java.util.Map">
|
||||||
|
SELECT
|
||||||
|
DATE_FORMAT(create_time, '%m') as yearMonth,
|
||||||
|
SUM(commission) AS totalCommission
|
||||||
|
FROM
|
||||||
|
t_referral
|
||||||
|
WHERE
|
||||||
|
YEAR(create_time) = #{year}
|
||||||
|
and affiliate_account_id = #{affiliateAccountId}
|
||||||
|
and is_deleted = 0
|
||||||
|
and status in ("Paid", "Unpaid")
|
||||||
|
GROUP BY
|
||||||
|
yearMonth
|
||||||
|
ORDER BY
|
||||||
|
yearMonth
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="getMonthlyAffiliateIncome" resultType="java.util.Map">
|
||||||
|
SELECT
|
||||||
|
DATE_FORMAT(create_time, '%m') as yearMonth,
|
||||||
|
SUM(amount) AS totalAmount,
|
||||||
|
SUM(CASE WHEN status = 'Paid' THEN commission ELSE 0 END) AS paidCommission,
|
||||||
|
SUM(CASE WHEN status = 'Unpaid' THEN commission ELSE 0 END) AS unpaidCommission
|
||||||
|
FROM
|
||||||
|
t_referral
|
||||||
|
WHERE
|
||||||
|
YEAR(create_time) = #{year}
|
||||||
|
AND MONTH(create_time) = #{month}
|
||||||
|
AND is_deleted = 0
|
||||||
|
AND status IN ('Paid', 'Unpaid')
|
||||||
|
GROUP BY
|
||||||
|
yearMonth
|
||||||
|
ORDER BY
|
||||||
|
yearMonth
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user