Java计算账户余额核心类

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/**
* 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;
}
}
MiCai wechat
扫一扫,关注微信订阅号
坚持原创技术分享,您的支持将鼓励我继续创作!