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;
	}
}

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