答题奖励规则

This commit is contained in:
ronger 2021-02-20 16:55:12 +08:00
parent b4f9074338
commit b7437b01a1
13 changed files with 197 additions and 12 deletions

View File

@ -3,6 +3,9 @@ package com.rymcu.forest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author ronger
*/
@SpringBootApplication
public class ForestApplication {

View File

@ -3,8 +3,10 @@ package com.rymcu.forest.answer;
import com.alibaba.fastjson.JSONObject;
import com.rymcu.forest.core.result.GlobalResult;
import com.rymcu.forest.core.result.GlobalResultGenerator;
import com.rymcu.forest.core.service.log.annotation.TransactionLogger;
import com.rymcu.forest.dto.AnswerDTO;
import com.rymcu.forest.entity.User;
import com.rymcu.forest.enumerate.TransactionEnum;
import com.rymcu.forest.util.HttpUtils;
import com.rymcu.forest.util.UserUtils;
import com.rymcu.forest.web.api.exception.BaseApiException;
@ -30,6 +32,7 @@ public class AnswerController {
}
@PostMapping("/answer")
@TransactionLogger(transactionType = TransactionEnum.Answer)
public GlobalResult answer(@RequestBody AnswerDTO answerDTO) throws BaseApiException {
User user = UserUtils.getCurrentUserByToken();
Map params = new HashMap<>(3);

View File

@ -7,7 +7,6 @@ import org.apache.ibatis.exceptions.TooManyResultsException;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.entity.Condition;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;

View File

@ -0,0 +1,94 @@
package com.rymcu.forest.core.service.log;
import com.rymcu.forest.core.result.GlobalResult;
import com.rymcu.forest.core.service.log.annotation.TransactionLogger;
import com.rymcu.forest.entity.TransactionRecord;
import com.rymcu.forest.entity.User;
import com.rymcu.forest.enumerate.TransactionEnum;
import com.rymcu.forest.service.TransactionRecordService;
import com.rymcu.forest.util.UserUtils;
import com.rymcu.forest.web.api.exception.BaseApiException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;
/**
* @author ronger
*
*/
@Aspect
@Component
public class TransactionAspect {
Logger logger = LoggerFactory.getLogger(TransactionAspect.class);
@Resource
private TransactionRecordService transactionRecordService;
@Pointcut("@annotation(com.rymcu.forest.core.service.log.annotation.TransactionLogger)")
public void pointCut() {}
/**
* 保存交易操作日志
*
* @param joinPoint 连接点
* @return 方法执行结果
* @throws Throwable 调用出错
*/
@AfterReturning(value = "pointCut()", returning="obj")
public void save(JoinPoint joinPoint, Object obj) throws Exception {
logger.info("保存交易记录 start ...");
/**
* 解析Log注解
*/
String methodName = joinPoint.getSignature().getName();
Method method = currentMethod(joinPoint, methodName);
TransactionLogger log = method.getAnnotation(TransactionLogger.class);
if (Objects.nonNull(log)) {
User user = UserUtils.getCurrentUserByToken();
GlobalResult globalResult = (GlobalResult) obj;
if (globalResult.isSuccess()) {
if (TransactionEnum.Answer.equals(log.transactionType())) {
if (globalResult.getData().equals(true)) {
transactionRecordService.bankTransfer(user.getIdUser(), TransactionEnum.CorrectAnswer);
} else {
transactionRecordService.bankTransfer(user.getIdUser(), TransactionEnum.Answer);
}
}
}
}
logger.info("保存交易记录 end ...");
}
/**
* 获取当前执行的方法
*
* @param joinPoint 连接点
* @param methodName 方法名称
* @return 方法
*/
private Method currentMethod(JoinPoint joinPoint, String methodName) {
/**
* 获取目标类的所有方法找到当前要执行的方法
*/
Method[] methods = joinPoint.getTarget().getClass().getMethods();
Method resultMethod = null;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
resultMethod = method;
break;
}
}
return resultMethod;
}
}

View File

@ -0,0 +1,16 @@
package com.rymcu.forest.core.service.log.annotation;
import com.rymcu.forest.enumerate.TransactionEnum;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* @author ronger
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface TransactionLogger {
TransactionEnum transactionType();
}

View File

@ -7,17 +7,20 @@ import java.util.Arrays;
*/
public enum TransactionEnum {
ArticleSponsor("0", 20),
Answer("1", 30),
CorrectAnswer("2", 50);
ArticleSponsor("0", 20, "文章赞赏"),
Answer("1", 30, "答题奖励"),
CorrectAnswer("2", 50, "答题奖励");
private String dataType;
private Integer money;
TransactionEnum(String dataType, Integer money) {
private String description;
TransactionEnum(String dataType, Integer money, String description) {
this.dataType = dataType;
this.money = money;
this.description = description;
}
public static TransactionEnum findTransactionEnum(String dataType) {
@ -32,6 +35,10 @@ public enum TransactionEnum {
return this.money;
}
public String getDescription() {
return this.description;
}
public boolean isArticleSponsor() {
return ArticleSponsor.equals(this);
}

View File

@ -27,4 +27,12 @@ public interface TransactionRecordMapper extends Mapper<TransactionRecord> {
* @return
*/
List<TransactionRecordDTO> selectTransactionRecords(@Param("bankAccount") String bankAccount);
/**
* 校验今日是否已发放答题奖励
* @param bankAccount
* @param funds
* @return
*/
Boolean existsWithBankAccountAndFunds(@Param("bankAccount") String bankAccount, @Param("funds") String funds);
}

View File

@ -32,4 +32,10 @@ public interface BankAccountService extends Service<BankAccount> {
* @return
*/
BankAccount findByBankAccount(String bankAccount);
/**
* 查询系统社区银行
* @return
*/
BankAccount findSystemBankAccount();
}

View File

@ -3,6 +3,7 @@ package com.rymcu.forest.service;
import com.rymcu.forest.core.service.Service;
import com.rymcu.forest.dto.TransactionRecordDTO;
import com.rymcu.forest.entity.TransactionRecord;
import com.rymcu.forest.enumerate.TransactionEnum;
import java.math.BigDecimal;
import java.util.List;
@ -30,9 +31,18 @@ public interface TransactionRecordService extends Service<TransactionRecord> {
* 根据用户主键进行交易
* @param toUserId
* @param formUserId
* @param money
* @param transactionType
* @return
* @throws Exception
*/
TransactionRecord transferByUserId(Integer toUserId, Integer formUserId, BigDecimal money) throws Exception;
TransactionRecord userTransfer(Integer toUserId, Integer formUserId, TransactionEnum transactionType) throws Exception;
/**
* 社区银行转账/奖励发放
* @param idUser
* @param transactionType
* @return
* @throws Exception
*/
TransactionRecord bankTransfer(Integer idUser, TransactionEnum transactionType) throws Exception;
}

View File

@ -67,6 +67,15 @@ public class BankAccountServiceImpl extends AbstractService<BankAccount> impleme
return bankAccountMapper.selectOne(searchBankAccount);
}
@Override
public BankAccount findSystemBankAccount() {
BankAccount bankAccount = new BankAccount();
bankAccount.setIdBank(1);
bankAccount.setAccountType("1");
bankAccount.setAccountOwner(2);
return bankAccountMapper.selectOne(bankAccount);
}
private String nextBankAccount() {
String bankAccount = "600000001";
String maxBankAccount = bankAccountMapper.selectMaxBankAccount();

View File

@ -1,5 +1,6 @@
package com.rymcu.forest.service.impl;
import com.rymcu.forest.core.exception.TransactionException;
import com.rymcu.forest.core.service.AbstractService;
import com.rymcu.forest.dto.ArticleDTO;
@ -51,7 +52,7 @@ public class SponsorServiceImpl extends AbstractService<Sponsor> implements Spon
// 赞赏金额划转
if (result.isArticleSponsor()) {
ArticleDTO articleDTO = articleService.findArticleDTOById(sponsor.getDataId(), 1);
TransactionRecord transactionRecord = transactionRecordService.transferByUserId(articleDTO.getArticleAuthorId(), user.getIdUser(), money);
TransactionRecord transactionRecord = transactionRecordService.userTransfer(articleDTO.getArticleAuthorId(), user.getIdUser(), result);
if (Objects.isNull(transactionRecord.getIdTransactionRecord())) {
throw new TransactionException(TransactionCode.InsufficientBalance);
}

View File

@ -1,6 +1,5 @@
package com.rymcu.forest.service.impl;
import com.rymcu.forest.core.exception.ServiceException;
import com.rymcu.forest.core.exception.TransactionException;
import com.rymcu.forest.core.service.AbstractService;
import com.rymcu.forest.core.service.redis.RedisService;
@ -9,6 +8,7 @@ import com.rymcu.forest.dto.TransactionRecordDTO;
import com.rymcu.forest.entity.BankAccount;
import com.rymcu.forest.entity.TransactionRecord;
import com.rymcu.forest.enumerate.TransactionCode;
import com.rymcu.forest.enumerate.TransactionEnum;
import com.rymcu.forest.mapper.TransactionRecordMapper;
import com.rymcu.forest.service.BankAccountService;
import com.rymcu.forest.service.TransactionRecordService;
@ -60,17 +60,42 @@ public class TransactionRecordServiceImpl extends AbstractService<TransactionRec
}
@Override
public TransactionRecord transferByUserId(Integer toUserId, Integer formUserId, BigDecimal money) throws Exception {
public TransactionRecord userTransfer(Integer toUserId, Integer formUserId, TransactionEnum transactionType) throws Exception {
BankAccountDTO toBankAccount = bankAccountService.findBankAccountByIdUser(toUserId);
BankAccountDTO formBankAccount = bankAccountService.findBankAccountByIdUser(formUserId);
TransactionRecord transactionRecord = new TransactionRecord();
transactionRecord.setToBankAccount(toBankAccount.getBankAccount());
transactionRecord.setFormBankAccount(formBankAccount.getBankAccount());
transactionRecord.setMoney(money);
transactionRecord.setFunds("赞赏");
transactionRecord.setMoney(new BigDecimal(transactionType.getMoney()));
transactionRecord.setFunds(transactionType.getDescription());
return transfer(transactionRecord);
}
@Override
public TransactionRecord bankTransfer(Integer idUser, TransactionEnum transactionType) throws Exception {
BankAccountDTO toBankAccount = bankAccountService.findBankAccountByIdUser(idUser);
Boolean isTrue;
// 校验货币规则
switch (transactionType) {
case Answer:
case CorrectAnswer:
isTrue = transactionRecordMapper.existsWithBankAccountAndFunds(toBankAccount.getBankAccount(), transactionType.getDescription());
break;
default:
isTrue = true;
}
if (isTrue) {
BankAccount formBankAccount = bankAccountService.findSystemBankAccount();
TransactionRecord transactionRecord = new TransactionRecord();
transactionRecord.setToBankAccount(toBankAccount.getBankAccount());
transactionRecord.setFormBankAccount(formBankAccount.getBankAccount());
transactionRecord.setMoney(new BigDecimal(transactionType.getMoney()));
transactionRecord.setFunds(transactionType.getDescription());
return transfer(transactionRecord);
}
return null;
}
private String nextTransactionNo() {
String orderNo = "E";
String key = "orderId";

View File

@ -18,4 +18,8 @@
<select id="selectTransactionRecords" resultMap="DTOResultMap">
select * from forest_transaction_record where form_bank_account = #{bankAccount} or to_bank_account = #{bankAccount}
</select>
<select id="existsWithBankAccountAndFunds" resultType="java.lang.Boolean">
select ifnull((select false from forest_transaction_record where to_bank_account = #{bankAccount}
and funds = #{funds} and transaction_time > str_to_date(date_format(sysdate(),'%Y-%m-%d'),'%Y-%m-%d') limit 1), true)
</select>
</mapper>