Java计算账户余额的核心方法

摘要:在项目开发中,有这样一个业务场景,就是我们有个虚拟服务,服务是按一定的YD(这里的YD相当于一般的积分即可)去抵扣的,同时YD又是通过用户下单购买产生的,规则如下图:
在这里插入图片描述
那么在用户使用服务的时候,会消费一定的YD,那么久需要计算账户的剩余YD,详细见如下代码:

/**
 * Copyright 2019. yaodouwang.com Studio All Right Reserved
 *
 * Create on Nov 8, 2019 1:56:16 PM
 * created by yolo
 * Version 1.0.0
 */
package com.yaodou.baseproduct;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.yaodou.utils.OtherException;

/**
 * 计算账户余额
 * @author yolo
 * @date 2019-11-08
 */
public class caculatePriceUtil {
	
	
	public static void main(String[] args) {
		
		generateTotal("A1001",new BigDecimal(1000));
		
		generateTotal("A1001",new BigDecimal(1000));
		
		generateTotal("A1001",new BigDecimal(1000));
		
	}
	
	private static final String DEAULT_ORDER_ID = "NA";
	private static final BigDecimal DEFAULT_UNIT_PRICE = new BigDecimal(0.05);
	
	/**
	 * 根据用户编码获取当前用户账户余额
	 * @param userId 用户唯一标示
	 * @return
	 * @author yolo
	 * @date 2019-11-08
	 */
	@SuppressWarnings("unchecked")
	private static Map<String,Object> generateTotal(String userId,BigDecimal todayQuantity) {
		//如果今日消费数量为0 则不用走以下统计流程
		if(todayQuantity.compareTo(BigDecimal.ZERO) == 0) {
			return null;
		}
		
		//返回数据形式定义
		 Map<String,Object> returnMap = new HashMap<>();
		//--》消费记录map
		List<YdyConsumePO> consumeList = new ArrayList<>();
		//剩余总额
		BigDecimal remainTotalMoney = BigDecimal.ZERO;
		
		//TODO 根据userId去账户表ydy_account查询该用户对应的 账户account_id 余额remain_balance,剩余条数remain_quantity
		String accountId = "A1001";
		//剩余条数,这个条数是统计后的条数
		BigDecimal remainQuantity = new BigDecimal(100000);
		
		//TODO 去ydy_recharge表查询 status="N"的充值记录,时间正序排序。取出以下对应字段
		List<YdyRechargePO>  rechargeList = new LinkedList<YdyRechargePO>();
		//如果没有可用充值记录,则直接把今日消费的条数记录成 欠费条数
		if(rechargeList.size() ==0) {
			YdyConsumePO consumer = new YdyConsumePO();
			consumer.setAcountId(accountId);
			consumer.setConsumeQuantity(remainQuantity);
			consumer.setOrderId("初始化orderId"); //为空代表超前消费//欠费
			consumeList.add(consumer);
			remainTotalMoney = remainQuantity.multiply(DEFAULT_UNIT_PRICE).negate();//取负数
		}else {
			BigDecimal totalQuantity = rechargeList.get(0).getTotalQuanity();
			//校准数据,如果剩余量和库存不一样则跑出异常
			if(totalQuantity.compareTo(remainQuantity) != 0){
				throw new OtherException("数据有异常,请联系开发人员核对数据!");
			}
			//如果今日消费条数大于或者等于剩余总的条数
			if(todayQuantity.compareTo(totalQuantity) !=-1) {
				//TODO 所有的rechage表中的状态都变成 N
				for(YdyRechargePO recharge:rechargeList) {
					generateConsumList(consumeList, recharge.getOrderId(), recharge.getRemainQuantity(), accountId);
					remainTotalMoney = BigDecimal.ZERO;
				}
				//大于
				if(todayQuantity.compareTo(totalQuantity) ==1) {
					//欠费数量
					BigDecimal oweQuantity = todayQuantity.divide(totalQuantity);
					generateConsumList(consumeList, oweQuantity, accountId);
					remainTotalMoney = oweQuantity.multiply(DEFAULT_UNIT_PRICE).negate();
				}
			}else {
				Map<String,Object> rechargeMap = getIndex(rechargeList, todayQuantity);
				List<YdyRechargePO> rechargeUpdateList= (List<YdyRechargePO>) rechargeMap.get("rechargeUpdateList");
				BigDecimal newRemainQuantity = (BigDecimal) rechargeMap.get("newRemainQuantity");
				int index = (int) rechargeMap.get("index");
				YdyRechargePO updateRemaining = rechargeList.get(index);
				if(newRemainQuantity.compareTo(BigDecimal.ZERO)!=0) {
					//TODO 修改updateRemaining记录 把remianQuantity设置成newRemainQuantity
					generateConsumList(consumeList, updateRemaining.getOrderId(), 
							updateRemaining.getRemainQuantity().divide(newRemainQuantity), accountId);
				}
				//TODO 把rechargeIdList 集合中的YdyRechargePO 记录状态都修改成N
				generateConsumList(consumeList, rechargeUpdateList);
				remainTotalMoney = (BigDecimal) rechargeMap.get("remianTotalMoney");
			}
		}
		//返回的数据
		returnMap.put("remainTotalMoney", remainTotalMoney);
		returnMap.put("consumerList", consumeList);
		
		return returnMap;
		
	}

	/**
	 * 生成消费记录
	 * @param consumeList
	 * @param rechargeList
	 * @author yolo
	 * @date 2019-11-08
	 */
	private static void generateConsumList(List<YdyConsumePO> consumeList,List<YdyRechargePO>  rechargeList) {
		for(YdyRechargePO recharge:rechargeList) {
			generateConsumList(consumeList, recharge.getOrderId(), recharge.getRemainQuantity(), recharge.getAcountId());
		}
	}

	/**
	 * 生成消费记录
	 * @param consumeList 消费记录insert数据的list
	 * @param orderId 充值编码
	 * @param consumeQuantity 消费数量
	 * @param accuntId 账户编码
	 * @author yolo
	 * @date 2019-11-08
	 */
	private static void generateConsumList(List<YdyConsumePO> consumeList,String orderId,BigDecimal consumeQuantity,String accountId) {
		YdyConsumePO consumer = new YdyConsumePO();
		consumer.setOrderId(orderId); 
		consumer.setConsumeQuantity(consumeQuantity);
		consumer.setAcountId(accountId);
		consumeList.add(consumer);
	}

	/**
	 * 生成消费记录
	 * @param consumeList 消费记录insert数据的list
	 * @param consumeQuantity 消费数量
	 * @param accountId 账户编码
	 * @author yolo
	 * @date 2019-11-08
	 */
	private static void generateConsumList(List<YdyConsumePO> consumeList, BigDecimal consumeQuantity,String accountId) {
		generateConsumList(consumeList, DEAULT_ORDER_ID, consumeQuantity, accountId);
	}

	/**
	 * 计算剩余第几条记录的总条数满足扣除
	 * @param rechargeList 没有消费的充值记录的list
	 * @param todayQuantity 今日消费条数
	 * @return
	 * @author yolo
	 * @date 2019-11-08
	 */
	private static Map<String,Object> getIndex(List<YdyRechargePO> rechargeList,BigDecimal todayQuantity) {
		BigDecimal total = BigDecimal.ZERO;
		int size = rechargeList.size();
		List<YdyRechargePO> rechargeUpdateList = new ArrayList<>(size);
		//充值记录剩余未使用的条数
		BigDecimal newRemainQuantity = BigDecimal.ZERO;
		//账余额
		BigDecimal remianTotalMoney = BigDecimal.ZERO;
		//判断是否需要停止叠加价格
		boolean isCaculateMoney = Boolean.FALSE;
		Map<String,Object> returnMap = new HashMap<>();
		for(int i=0;i< size;i++) {
			YdyRechargePO recharge = rechargeList.get(i);
			total = recharge.getRemainQuantity();//剩余未使用的的数量
			if(isCaculateMoney) {
				remianTotalMoney = remianTotalMoney.add(recharge.getRechargeAmount());//充值金额
			}else {
				if(total.compareTo(todayQuantity) !=-1) {
					newRemainQuantity = total.divide(todayQuantity);
					remianTotalMoney = recharge.getRechargeUnitPrice().multiply(newRemainQuantity).setScale(2);//充值金额
					if(newRemainQuantity.compareTo(BigDecimal.ZERO)==0) {
						rechargeUpdateList.add(recharge);
					}
					returnMap.put("index", i);
					isCaculateMoney = Boolean.TRUE;
				}else {
					rechargeUpdateList.add(recharge);
					total = total.add(recharge.getRemainQuantity());
				}
			}
		}
		returnMap.put("newRemainQuantity", newRemainQuantity);
		returnMap.put("rechargeUpdateList", rechargeUpdateList);
		returnMap.put("remianTotalMoney", remianTotalMoney);
		return returnMap;
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章