总览:
在api模块service包,创建IncomeService类:(收益计划 和 收益返还)
package com.bjpowernode.api.service;
public interface IncomeService {
/*收益计划*/
void generateIncomePlan();
/*收益返还*/
void generateIncomeBack();
}
在dataservice模块service包,实现该接口方法(收益计划generateIncomePlan()),创建IncomeServiceImpl类:
1、查询符合条件的满标的理财产品(productInfoMapper.selectFullTimeProducts(beginTime,endTime))
2、查询投资表,找到某个产品的所有的投资记录
3、计算每笔投资的 利息 和 到期时间
4、更新产品的状态(productInfoMapper.updateStatus(product.getId(),YLBConstant.PRODUCT_STATUS_PLAN))
package com.bjpowernode.dataservice.service;
import com.bjpowernode.api.model.BidInfo;
import com.bjpowernode.api.model.IncomeRecord;
import com.bjpowernode.api.model.ProductInfo;
import com.bjpowernode.api.service.IncomeService;
import com.bjpowernode.common.constants.YLBConstant;
import com.bjpowernode.dataservice.mapper.BidInfoMapper;
import com.bjpowernode.dataservice.mapper.FinanceAccountMapper;
import com.bjpowernode.dataservice.mapper.IncomeRecordMapper;
import com.bjpowernode.dataservice.mapper.ProductInfoMapper;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@DubboService(interfaceClass = IncomeService.class,version = "1.0")
public class IncomeServiceImpl implements IncomeService {
@Resource
private ProductInfoMapper productInfoMapper;
@Resource
private BidInfoMapper bidInfoMapper;
@Resource
private IncomeRecordMapper incomeMapper;
@Resource
private FinanceAccountMapper accountMapper;
/*收益计划*/
@Transactional(rollbackFor = Exception.class)
@Override
public synchronized void generateIncomePlan() {
//1.获取要处理的理财产品记录
Date currentDate = new Date();
Date beginTime = DateUtils.truncate(DateUtils.addDays(currentDate, -1), Calendar.DATE);;
Date endTime = DateUtils.truncate(currentDate, Calendar.DATE);;
List<ProductInfo> productInfoList = productInfoMapper.selectFullTimeProducts(beginTime,endTime);
//2.查询每个理财产品的多个投资记录
int rows = 0 ;
BigDecimal income = null;
BigDecimal dayRate = null;
BigDecimal cycle = null; //周期
Date incomeDate = null;//到期时间
for(ProductInfo product:productInfoList){
//日利率
dayRate = product.getRate().divide(new BigDecimal("360"),10, RoundingMode.HALF_UP)
.divide(new BigDecimal("100"),10,RoundingMode.HALF_UP);
//产品类型不同,周期不同 天 ,月
if( product.getProductType() == YLBConstant.PRODUCT_TYPE_XINSHOUBAO){ //天为单位
cycle = new BigDecimal(product.getCycle());
incomeDate = DateUtils.addDays(product.getProductFullTime(),(1+product.getCycle()));
} else {
cycle = new BigDecimal(product.getCycle() * 30);
incomeDate = DateUtils.addDays(product.getProductFullTime(),(1+ product.getCycle() * 30 ));
}
List<BidInfo> bidList = bidInfoMapper.selectByProdId(product.getId());
//3.计算每笔投资的 利息 和 到期时间
for(BidInfo bid : bidList){
//利息 = 本金 * 周期 * 利率
income = bid.getBidMoney().multiply(cycle).multiply(dayRate);
// 创建收益记录
IncomeRecord incomeRecord = new IncomeRecord();
incomeRecord.setBidId(bid.getId());
incomeRecord.setBidMoney(bid.getBidMoney());
incomeRecord.setIncomeDate(incomeDate);
incomeRecord.setIncomeStatus(YLBConstant.INCOME_STATUS_PLAN);
incomeRecord.setProdId(product.getId());
incomeRecord.setIncomeMoney(income);
incomeRecord.setUid(bid.getUid());
incomeMapper.insertSelective(incomeRecord);
}
//更新产品的状态
rows = productInfoMapper.updateStatus(product.getId(),YLBConstant.PRODUCT_STATUS_PLAN);
if(rows < 1 ){
throw new RuntimeException("生成收益计划,更新产品状态为2失败");
}
}
}
/*收益返还*/
@Transactional(rollbackFor = Exception.class)
@Override
public synchronized void generateIncomeBack() {
//1.获取要处理的到期的收益记录
Date curDate = new Date();
Date expiredDate = DateUtils.truncate(DateUtils.addDays(curDate, -1),Calendar.DATE);
System.out.println("expiredDate="+expiredDate);
List<IncomeRecord> incomeRecordList = incomeMapper.selectExpiredIncome(expiredDate);
int rows = 0;
//2.把每个收益,进行返还, 本金 + 利息
for(IncomeRecord ir : incomeRecordList){
rows = accountMapper.updateAvailableMoneyByIncomeBack(ir.getUid(),ir.getBidMoney(),ir.getIncomeMoney());
if( rows < 1 ){
throw new RuntimeException("收益返还,更新账号资金失败");
}
//3.更新收益记录的状态为 1
ir.setIncomeStatus(YLBConstant.INCOME_STATUS_BACK);
rows = incomeMapper.updateByPrimaryKey(ir);
if( rows <1) {
throw new RuntimeException("收益返还,更新收益记录的状态失败");
}
}
}
}
其中:
1、查询满标的理财列表(需要在dataservice模块mapper包下的ProductInfoMapper接口添加方法,并在resources/mappers/ProductInfoMapper.xml编写SQL语句):
/*满标的理财列表*/
List<ProductInfo> selectFullTimeProducts(@Param("beginTime") Date beginTime, @Param("endTime") Date endTime);
<!--满标的理财列表-->
<select id="selectFullTimeProducts" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List" />
FROM
b_product_info
WHERE
product_status = 1
AND product_full_time >= #{beginTime} AND product_full_time < #{endTime}
order by id
</select>
2、更新产品的状态(需要在dataservice模块mapper包下的ProductInfoMapper接口添加方法,并在resources/mappers/ProductInfoMapper.xml编写SQL语句):
/*更新状态*/
int updateStatus(@Param("id") Integer id, @Param("newStatus") int newStatus);
<!--更新状态-->
<update id="updateStatus">
update b_product_info set product_status = #{newStatus} where id = #{id}
</update>
在dataservice模块service包,实现该接口方法(收益返还),IncomeServiceImpl类添加generateIncomeBack():
1、获取要处理的到期的收益记录(incomeMapper.selectExpiredIncome(expiredDate))
2、把每个收益,进行返还, 本金 + 利息(accountMapper.updateAvailableMoneyByIncomeBack(ir.getUid(),ir.getBidMoney(),ir.getIncomeMoney()))
3、更新收益记录的状态为 1(incomeMapper.updateByPrimaryKey(ir))
package com.bjpowernode.dataservice.service;
import com.bjpowernode.api.model.BidInfo;
import com.bjpowernode.api.model.IncomeRecord;
import com.bjpowernode.api.model.ProductInfo;
import com.bjpowernode.api.service.IncomeService;
import com.bjpowernode.common.constants.YLBConstant;
import com.bjpowernode.dataservice.mapper.BidInfoMapper;
import com.bjpowernode.dataservice.mapper.FinanceAccountMapper;
import com.bjpowernode.dataservice.mapper.IncomeRecordMapper;
import com.bjpowernode.dataservice.mapper.ProductInfoMapper;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@DubboService(interfaceClass = IncomeService.class,version = "1.0")
public class IncomeServiceImpl implements IncomeService {
@Resource
private ProductInfoMapper productInfoMapper;
@Resource
private BidInfoMapper bidInfoMapper;
@Resource
private IncomeRecordMapper incomeMapper;
@Resource
private FinanceAccountMapper accountMapper;
/*收益计划*/
@Transactional(rollbackFor = Exception.class)
@Override
public synchronized void generateIncomePlan() {
//1.获取要处理的理财产品记录
Date currentDate = new Date();
Date beginTime = DateUtils.truncate(DateUtils.addDays(currentDate, -1), Calendar.DATE);;
Date endTime = DateUtils.truncate(currentDate, Calendar.DATE);;
List<ProductInfo> productInfoList = productInfoMapper.selectFullTimeProducts(beginTime,endTime);
//2.查询每个理财产品的多个投资记录
int rows = 0 ;
BigDecimal income = null;
BigDecimal dayRate = null;
BigDecimal cycle = null; //周期
Date incomeDate = null;//到期时间
for(ProductInfo product:productInfoList){
//日利率
dayRate = product.getRate().divide(new BigDecimal("360"),10, RoundingMode.HALF_UP)
.divide(new BigDecimal("100"),10,RoundingMode.HALF_UP);
//产品类型不同,周期不同 天 ,月
if( product.getProductType() == YLBConstant.PRODUCT_TYPE_XINSHOUBAO){ //天为单位
cycle = new BigDecimal(product.getCycle());
incomeDate = DateUtils.addDays(product.getProductFullTime(),(1+product.getCycle()));
} else {
cycle = new BigDecimal(product.getCycle() * 30);
incomeDate = DateUtils.addDays(product.getProductFullTime(),(1+ product.getCycle() * 30 ));
}
List<BidInfo> bidList = bidInfoMapper.selectByProdId(product.getId());
//3.计算每笔投资的 利息 和 到期时间
for(BidInfo bid : bidList){
//利息 = 本金 * 周期 * 利率
income = bid.getBidMoney().multiply(cycle).multiply(dayRate);
// 创建收益记录
IncomeRecord incomeRecord = new IncomeRecord();
incomeRecord.setBidId(bid.getId());
incomeRecord.setBidMoney(bid.getBidMoney());
incomeRecord.setIncomeDate(incomeDate);
incomeRecord.setIncomeStatus(YLBConstant.INCOME_STATUS_PLAN);
incomeRecord.setProdId(product.getId());
incomeRecord.setIncomeMoney(income);
incomeRecord.setUid(bid.getUid());
incomeMapper.insertSelective(incomeRecord);
}
//更新产品的状态
rows = productInfoMapper.updateStatus(product.getId(),YLBConstant.PRODUCT_STATUS_PLAN);
if(rows < 1 ){
throw new RuntimeException("生成收益计划,更新产品状态为2失败");
}
}
}
/*收益返还*/
@Transactional(rollbackFor = Exception.class)
@Override
public synchronized void generateIncomeBack() {
//1.获取要处理的到期的收益记录
Date curDate = new Date();
Date expiredDate = DateUtils.truncate(DateUtils.addDays(curDate, -1),Calendar.DATE);
System.out.println("expiredDate="+expiredDate);
List<IncomeRecord> incomeRecordList = incomeMapper.selectExpiredIncome(expiredDate);
int rows = 0;
//2.把每个收益,进行返还, 本金 + 利息
for(IncomeRecord ir : incomeRecordList){
rows = accountMapper.updateAvailableMoneyByIncomeBack(ir.getUid(),ir.getBidMoney(),ir.getIncomeMoney());
if( rows < 1 ){
throw new RuntimeException("收益返还,更新账号资金失败");
}
//3.更新收益记录的状态为 1
ir.setIncomeStatus(YLBConstant.INCOME_STATUS_BACK);
rows = incomeMapper.updateByPrimaryKey(ir);
if( rows <1) {
throw new RuntimeException("收益返还,更新收益记录的状态失败");
}
}
}
}
其中:
1、查询到期的收益记录(需要在dataservice模块mapper包下的IncomeRecordMapper接口添加方法,并在resources/mappers/IncomeRecordMapper.xml编写SQL语句):
/*到期的收益记录*/
List<IncomeRecord> selectExpiredIncome(@Param("expiredDate") Date expiredDate);
<!--到期的收益记录-->
<select id="selectExpiredIncome" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List" />
FROM
b_income_record
WHERE
income_status = 0
AND income_date = #{expiredDate}
</select>
2、收益返还,更新资金(需要在dataservice模块mapper包下的FinanceAccountMapper接口添加方法,并在resources/mappers/FinanceAccountMapper.xml编写SQL语句):
/*收益返还,更新资金*/
int updateAvailableMoneyByIncomeBack(@Param("uid") Integer uid,
@Param("bidMoney") BigDecimal bidMoney,
@Param("incomeMoney") BigDecimal incomeMoney);
<!--收益返还,更新资金-->
<update id="updateAvailableMoneyByIncomeBack">
update u_finance_account set available_money = available_money + #{bidMoney} + #{incomeMoney}
where uid = #{uid}
</update>
在task模块下的resources/application.yml,添加配置信息(spring和dubbo):
spring:
application:
name: micr-task
dubbo:
scan:
base-packages: com.bjpowernode.task
registry:
address: zookeeper://localhost:2181
consumer:
timeout: 50000
check: false
retries: 0
在task模块下的启动类上添加注解(@EnableScheduling),启动定时任务:
package com.bjpowernode;
import com.bjpowernode.task.TaskManager;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableDubbo
//启用定时任务
@EnableScheduling
@SpringBootApplication
public class MicrTaskApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(MicrTaskApplication.class, args);
TaskManager tm = (TaskManager) ctx.getBean("taskManager");
//tm.invokeGenerateIncomePlan();
//tm.invokeGenerateIncomeBack();
tm.invokeKuaiQianQuery();
}
}
在task模块task包,创建TaskManager类:
package com.bjpowernode.task;
import com.bjpowernode.api.service.IncomeService;
import com.bjpowernode.common.util.HttpClientUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component("taskManager")
public class TaskManager {
/**
* 定义方法,表示要执行的定时任务功能
* 方法定义的要求:
* 1.public 公共方法
* 2.方法没有参数
* 3.方法没有返回值
* 4.方法的上面加入@Scheduled,设置cron属性,指定时间
*/
/* @Scheduled(cron = "30 37 10 * * ?")
public void testCron(){
System.out.println("执行了定时任务的方法:"+ new Date());
}*/
// @Scheduled(cron = "*/5 * * * * ?")
/* public void testCron(){
System.out.println("执行了定时任务的方法:"+ new Date());
}
*/
@DubboReference(interfaceClass = IncomeService.class, version = "1.0")
private IncomeService incomeService;
/*生成收益计划*/
@Scheduled(cron = "0 0 1 * * ?")
public void invokeGenerateIncomePlan() {
incomeService.generateIncomePlan();
}
/*生成收益返还*/
@Scheduled(cron = "0 0 2 * * ?")
public void invokeGenerateIncomeBack() {
incomeService.generateIncomeBack();
}
/**补单接口*/
// @Scheduled(cron = "0 0/20 * * * ?")
public void invokeKuaiQianQuery(){
try{
String url = "http://localhost:9000/pay/kq/rece/query";
HttpClientUtils.doGet(url);
}catch (Exception e){
e.printStackTrace();
}
}
}