1 package net.baiqu.shop.data.core.service.impl;
2
3 import com.baiqu.api.model.ApiResultResponse;
4 import lombok.extern.slf4j.Slf4j;
5 import net.baiqu.shop.data.api.AppResponseUtils;
6 import net.baiqu.shop.data.api.enums.report.ReportTypeEnum;
7 import net.baiqu.shop.data.api.models.request.report.ReportQueryRequest;
8 import net.baiqu.shop.data.api.models.response.report.ReportQueryResponse;
9 import net.baiqu.shop.data.core.service.AmountStatisticService;
10 import net.baiqu.shop.data.core.service.ReportQueryService;
11 import net.baiqu.shop.data.core.service.RepurchaseService;
12 import net.baiqu.shop.data.core.service.VipStatisticService;
13 import net.baiqu.shop.data.dal.entity.document.*;
14 import org.springframework.beans.factory.annotation.Autowired;
15 import org.springframework.stereotype.Service;
16
17 import java.util.Arrays;
18 import java.util.List;
19 import java.util.concurrent.*;
20 import java.util.stream.Collectors;
21
22 @Service
23 @Slf4j
24 public class ReportQueryServiceImpl implements ReportQueryService {
25
26 @Autowired
27 private AmountStatisticService amountStatisticService;
28
29 @Autowired
30 private VipStatisticService vipStatisticService;
31
32 @Autowired
33 private RepurchaseService repurchaseService;
34
35 @Override
36 public ApiResultResponse<List<ReportQueryResponse>> getStatistic(ReportQueryRequest request) {
37 ExecutorService executor = new ThreadPoolExecutor(
38 10,
39 10,
40 60,
41 TimeUnit.SECONDS,
42 new LinkedBlockingQueue<>(),
43 new ThreadPoolExecutor.AbortPolicy());
44 List<Integer> indexs = Arrays.asList(0, 1, 2, 3, 4, 5);
45
46 List<CompletableFuture<ReportQueryResponse>> listTasks = indexs.stream()
47 .map(index -> CompletableFuture.supplyAsync(() -> syncFunc(index, request), executor))
48 .collect(Collectors.toList());
49
50 List<ReportQueryResponse> list = listTasks.stream().map(CompletableFuture::join).collect(Collectors.toList());
51 executor.shutdown();
52
53 return AppResponseUtils.buildSuccessResponse(list);
54 }
55
56 /**
57 * 异步调用统计查询
58 */
59 private ReportQueryResponse syncFunc(Integer index, ReportQueryRequest request) {
60 ReportQueryResponse result = null;
61 switch (index) {
62 case 0: result = queryBalance(request);break;
63 case 1: result = queryVipConsume(request);break;
64 case 2: result = queryCustomerSave(request);break;
65 case 3: result = queryFormalVip(request);break;
66 case 4: result = queryExpVip(request);break;
67 case 5: result = queryRepurchaseVip(request);break;
68 default:
69 }
70 return result;
71 }
72
73 /**
74 * 余额增长
75 */
76 private ReportQueryResponse queryBalance(ReportQueryRequest request) {
77 log.info("开始查询余额增长");
78 ReportQueryResponse balanceResp = new ReportQueryResponse();
79 balanceResp.setStatisticType(ReportTypeEnum.BALANCE);
80 balanceResp.setStatisticResult(amountStatisticService.getAmountStatistic(request, MBalance.class));
81 //log.info("getStatistic->balanceResp",JSON.toJSONString(balanceResp));
82 log.info("完成余额增长查询");
83 return balanceResp;
84 }
85
86 /**
87 * 会员消费
88 */
89 private ReportQueryResponse queryVipConsume(ReportQueryRequest request) {
90 log.info("开始查询会员消费");
91 ReportQueryResponse vipConsumeResp = new ReportQueryResponse();
92 vipConsumeResp.setStatisticType(ReportTypeEnum.VIP_CONSUME);
93 vipConsumeResp.setStatisticResult(amountStatisticService.getAmountStatistic(request, MVipConsume.class));
94 //log.info("getStatistic->vipConsumeResp",JSON.toJSONString(vipConsumeResp));
95 log.info("完成查询会员消费");
96 return vipConsumeResp;
97 }
98
99 /**
100 * 客户节约
101 */
102 private ReportQueryResponse queryCustomerSave(ReportQueryRequest request) {
103 log.info("开始查询客户节约");
104 ReportQueryResponse customerResp = new ReportQueryResponse();
105 customerResp.setStatisticType(ReportTypeEnum.CUSTOMER_SAVE);
106 customerResp.setStatisticResult(amountStatisticService.getAmountStatistic(request, MCustomerSave.class));
107 //log.info("getStatistic->customerResp",JSON.toJSONString(customerResp));
108 log.info("完成查询客户节约");
109 return customerResp;
110 }
111
112 /**
113 * 食堂会员增长
114 */
115 private ReportQueryResponse queryFormalVip(ReportQueryRequest request) {
116 log.info("开始查询会员增长");
117 ReportQueryResponse formalVipResp = new ReportQueryResponse();
118 formalVipResp.setStatisticType(ReportTypeEnum.VIP);
119 formalVipResp.setStatisticResult(vipStatisticService.getVipStatistic(request, MFormalVip.class));
120 //log.info("getStatistic->formalVipResp",JSON.toJSONString(formalVipResp));
121 log.info("完成查询会员增长");
122 return formalVipResp;
123 }
124
125 /**
126 * 体验会员增长
127 */
128 private ReportQueryResponse queryExpVip(ReportQueryRequest request) {
129 log.info("开始查询体验会员增长");
130 ReportQueryResponse expVipResp = new ReportQueryResponse();
131 expVipResp.setStatisticType(ReportTypeEnum.EXP_VIP);
132 expVipResp.setStatisticResult(vipStatisticService.getVipStatistic(request, MExpVip.class));
133 //log.info("getStatistic->expVipResp",JSON.toJSONString(expVipResp));
134 log.info("完成查询体验会员增长");
135 return expVipResp;
136 }
137
138 /**
139 * 复购会员
140 */
141 private ReportQueryResponse queryRepurchaseVip(ReportQueryRequest request) {
142 log.info("开始查询复购会员增长");
143 ReportQueryResponse repurchaseVipResp = new ReportQueryResponse();
144 repurchaseVipResp.setStatisticType(ReportTypeEnum.REPURCHASE_VIP);
145 repurchaseVipResp.setStatisticResult(repurchaseService.getRepurchaseStatistic(request, MCustomerSave.class));
146 //log.info("getStatistic->repurchaseVipResp",JSON.toJSONString(repurchaseVipResp));
147 log.info("完成查询复购会员增长");
148 return repurchaseVipResp;
149 }
150
151 }
1 package net.baiqu.shop.data.core.service.impl;
2
3 import com.alibaba.fastjson.JSONObject;
4 import com.mongodb.BasicDBObject;
5 import com.mongodb.DBObject;
6 import lombok.extern.slf4j.Slf4j;
7 import net.baiqu.shop.data.api.enums.ApiResponseCodeEnum;
8 import net.baiqu.shop.data.api.enums.report.AreaTypeEnum;
9 import net.baiqu.shop.data.api.models.request.report.ReportQueryRequest;
10 import net.baiqu.shop.data.api.models.response.vip.VipChartResponse;
11 import net.baiqu.shop.data.api.models.response.vip.VipStatisticResponse;
12 import net.baiqu.shop.data.core.exception.AppException;
13 import net.baiqu.shop.data.core.service.VipStatisticService;
14 import net.baiqu.shop.data.core.util.DateUtils;
15 import org.springframework.beans.factory.annotation.Autowired;
16 import org.springframework.data.domain.Sort;
17 import org.springframework.data.mongodb.core.MongoTemplate;
18 import org.springframework.data.mongodb.core.aggregation.Aggregation;
19 import org.springframework.data.mongodb.core.aggregation.AggregationResults;
20 import org.springframework.data.mongodb.core.query.Criteria;
21 import org.springframework.stereotype.Service;
22 import org.springframework.util.CollectionUtils;
23
24 import java.util.*;
25 import java.util.concurrent.*;
26 import java.util.stream.Collectors;
27
28 import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
29
30 @Service
31 @Slf4j
32 public class VipStatisticServiceImpl implements VipStatisticService {
33
34 private ExecutorService executor;
35
36 public VipStatisticServiceImpl() {
37 executor = new ThreadPoolExecutor(
38 5,
39 10,
40 60,
41 TimeUnit.SECONDS, new LinkedBlockingQueue<>(),
42 new ThreadPoolExecutor.AbortPolicy());
43 }
44
45 @Autowired
46 private MongoTemplate mongoTemplate;
47
48 private Class<?> clazz;
49
50 /**
51 * 查询食堂会员增长 | 查询体验会员增长
52 *
53 * @param request 查询条件 省、市、县、支行封装对象
54 * @param clazz 查询类 例: MVip.class, MExpVip.class
55 * @return 查询结果
56 */
57 @Override
58 public VipStatisticResponse getVipStatistic(ReportQueryRequest request, Class<?> clazz) {
59 log.info("getVipStatistic->request:{}", JSONObject.toJSONString(request));
60 this.clazz = clazz;
61 String province = request.getProvince();
62 String city = request.getCity();
63 String area = request.getArea();
64 String bank = request.getBank();
65
66 VipStatisticResponse vipStatistic;
67 List<VipStatisticResponse> child = new ArrayList<>();
68 if (city == null) {
69 // 查询全省统计数据
70 vipStatistic = this.findVipStatistic("province", province, clazz);
71 log.info("getVipStatistic->vipStatistic 省统计数据:{}", JSONObject.toJSONString(vipStatistic));
72 vipStatistic.setChild(child);
73 Map<String, Integer> childMap = this.getChildAndChildCount("province", "city", province, clazz);
74 // 异步查询省下所有城市统计数据
75 List<CompletableFuture<Integer>> listTasks = childMap.keySet().stream()
76 .map(c -> CompletableFuture.supplyAsync(() ->
77 this.findProvinceVipStatisticChild(child, c, childMap.get(c)), executor))
78 .collect(Collectors.toList());
79 listTasks.stream().map(CompletableFuture::join).collect(Collectors.toList());
80 } else if (area == null) {
81 // 查询某市统计数据
82 vipStatistic = this.findVipStatistic("city", city, clazz);
83 log.info("getVipStatistic->vipStatistic 地市统计数据:{}", JSONObject.toJSONString(vipStatistic));
84 vipStatistic.setChild(child);
85 Map<String, Integer> childMap = this.getChildAndChildCount("city", "area", city, clazz);
86 // 查询child
87 List<CompletableFuture<Integer>> listTasks = childMap.keySet().stream()
88 .map(a -> CompletableFuture.supplyAsync(() ->
89 this.findCityVipStatisticChild(child, a, childMap.get(a)), executor))
90 .collect(Collectors.toList());
91 listTasks.stream().map(CompletableFuture::join).collect(Collectors.toList());
92 } else if (bank == null) {
93 // 查询某县统计数据
94 vipStatistic = this.findVipStatistic("area", area, clazz);
95 log.info("getVipStatistic->vipStatistic 县市统计数据:{}", JSONObject.toJSONString(vipStatistic));
96 vipStatistic.setChild(child);
97 Map<String, Integer> childMap = this.getChildAndChildCount("area", "bank", area, clazz);
98 // 查询child
99 List<CompletableFuture<Integer>> listTasks = childMap.keySet().stream()
100 .map(b -> CompletableFuture.supplyAsync(() ->
101 this.findAreaVipStatisticChild(child, b, childMap.get(b)), executor))
102 .collect(Collectors.toList());
103 listTasks.stream().map(CompletableFuture::join).collect(Collectors.toList());
104 } else {
105 // 查询某支行统计数据
106 vipStatistic = this.findVipStatistic("bank", bank, clazz);
107 log.info("getVipStatistic->vipStatistic 支行统计数据:{}", JSONObject.toJSONString(vipStatistic));
108 }
109
110 //log.info("getVipStatistic->vipStatistic:{}", JSONObject.toJSONString(vipStatistic));
111 return vipStatistic;
112 }
113
114 /**
115 * 获取parent区划的下线和下线各自的会员总数的map
116 * @param parentRefer 查询父标识
117 * @param childRefer 查询子标识
118 * @param query 查询条件
119 * @param clazz 类型
120 * @return map -> child, childCount
121 */
122 private Map<String, Integer> getChildAndChildCount(String parentRefer, String childRefer, String query, Class<?> clazz) {
123 Map<String, Integer> map = new HashMap<>();
124 Aggregation aggregation = Aggregation.newAggregation(
125 match(
126 Criteria.where(parentRefer).is(query)),
127 group(childRefer).count().as("total"));
128 AggregationResults<BasicDBObject> result = mongoTemplate.aggregate(aggregation, clazz, BasicDBObject.class);
129 if (CollectionUtils.isEmpty(result.getMappedResults())) {
130 throw new AppException(ApiResponseCodeEnum.USER_NOT_EXIST);
131 }
132 for (Iterator<BasicDBObject> iterator = result.iterator(); iterator.hasNext(); ) {
133 DBObject obj = iterator.next();
134 map.put(obj.get("_id").toString(), Integer.valueOf(obj.get("total").toString()));
135 }
136 return map;
137 }
138
139 /**
140 * 查询县市下线会员统计数据
141 * @param child 下线
142 * @param bank 支行
143 * @param count 支行会员数
144 * @return
145 */
146 private int findAreaVipStatisticChild(List<VipStatisticResponse> child, String bank, Integer count) {
147 VipStatisticResponse bankVipStatistic = this.findVipStatistic("bank", bank, count, clazz);
148 child.add(bankVipStatistic);
149 return 1;
150 }
151
152 /**
153 * 查询地市下线会员统计数据
154 * @param child 下线
155 * @param area 县市
156 * @param count 县市会员数
157 * @return
158 */
159 private int findCityVipStatisticChild(List<VipStatisticResponse> child, String area, Integer count) {
160 VipStatisticResponse areaVipStatistic = this.findVipStatistic("area", area, count, clazz);
161 child.add(areaVipStatistic);
162 List<VipStatisticResponse> areaChild = new ArrayList<>();
163 areaVipStatistic.setChild(areaChild);
164 Map<String, Integer> bankMap = this.getChildAndChildCount("area", "bank", area, clazz);
165 for (String b : bankMap.keySet()) {
166 this.findAreaVipStatisticChild(areaChild, b, bankMap.get(b));
167 }
168 return 1;
169 }
170
171 /**
172 * 查询省下线会员统计数据
173 * @param child 下线
174 * @param city 地市
175 * @param count 地市会员数
176 * @return
177 */
178 private int findProvinceVipStatisticChild(List<VipStatisticResponse> child, String city, Integer count) {
179 VipStatisticResponse cityVipStatistic = this.findVipStatistic("city", city, count, clazz);
180 child.add(cityVipStatistic);
181 List<VipStatisticResponse> cityChild = new ArrayList<>();
182 cityVipStatistic.setChild(cityChild);
183 Map<String, Integer> areaMap = this.getChildAndChildCount("city", "area", city, clazz);
184 // 查询地市下所有县市统计数据
185 for (String a : areaMap.keySet()) {
186 this.findCityVipStatisticChild(cityChild, a, areaMap.get(a));
187 }
188 return 1;
189 }
190
191 /**
192 * 通用封装统计数据
193 * @param refer 查询标识
194 * @param query 查询条件
195 * @param count 会员数量
196 * @param clazz 类型
197 * @return vipStatistic
198 */
199 private VipStatisticResponse generateVipStatistic(String refer, String query, Integer count, Class<?> clazz) {
200 VipStatisticResponse vipStatistic = new VipStatisticResponse();
201 // 查询近7日
202 List<String> past7Date = DateUtils.getSevenDays();
203 Aggregation aggregation = Aggregation.newAggregation(
204 match(
205 Criteria.where(refer).is(query).and("day").in(past7Date)),
206 group("day")
207 .count().as("total")
208 .first("day").as("day"),
209 project("total", "day"),
210 sort(Sort.Direction.DESC, "day"));
211 AggregationResults<BasicDBObject> result =
212 mongoTemplate.aggregate(aggregation, clazz, BasicDBObject.class);
213
214 if (CollectionUtils.isEmpty(result.getMappedResults())) {
215 throw new AppException(ApiResponseCodeEnum.USER_NOT_EXIST);
216 }
217
218 List<VipChartResponse> sevenDays = new ArrayList<>();
219 Map<String, Integer> map = new HashMap<>();
220 for (Iterator<BasicDBObject> iterator = result.iterator(); iterator.hasNext(); ) {
221 DBObject obj = iterator.next();
222 map.put(obj.get("day").toString(), Integer.valueOf(obj.get("total").toString()));
223 }
224 for (String day : past7Date) {
225 if (map.containsKey(day)) {
226 sevenDays.add(new VipChartResponse(day, map.get(day)));
227 } else {
228 sevenDays.add(new VipChartResponse(day, 0));
229 }
230 }
231 // 当日
232 int todayCount = sevenDays.get(0).getVip();
233
234 // 查询近6月
235 List<String> past6Months = DateUtils.getSixMonths();
236 aggregation = Aggregation.newAggregation(
237 match(
238 Criteria.where(refer).is(query).and("month").in(past6Months)),
239 group("month")
240 .count().as("total")
241 .first("month").as("month"),
242 project("total", "month"),
243 sort(Sort.Direction.DESC, "month"));
244 result = mongoTemplate.aggregate(aggregation, clazz, BasicDBObject.class);
245 if (CollectionUtils.isEmpty(result.getMappedResults())) {
246 throw new AppException(ApiResponseCodeEnum.USER_NOT_EXIST);
247 }
248 List<VipChartResponse> sixMonths = new ArrayList<>();
249 map = new HashMap<>();
250 for (Iterator<BasicDBObject> iterator = result.iterator(); iterator.hasNext(); ) {
251 DBObject obj = iterator.next();
252 map.put(obj.get("month").toString(), Integer.valueOf(obj.get("total").toString()));
253 }
254
255 for (String month : past6Months) {
256 if (map.containsKey(month)) {
257 sixMonths.add(new VipChartResponse(month, map.get(month)));
258 } else {
259 sixMonths.add(new VipChartResponse(month, 0));
260 }
261 }
262 // 当月
263 int monthCount = sixMonths.get(0).getVip();
264
265 // 查询累计
266 int total;
267 if (count == null) {
268 aggregation = Aggregation.newAggregation(
269 match(
270 Criteria.where(refer).is(query)),
271 group(refer).count().as("total"));
272 result = mongoTemplate.aggregate(aggregation, clazz, BasicDBObject.class);
273 if (CollectionUtils.isEmpty(result.getMappedResults())) {
274 throw new AppException(ApiResponseCodeEnum.USER_NOT_EXIST);
275 }
276 total = Integer.valueOf(result.getMappedResults().get(0).get("total").toString());
277 } else {
278 total = count;
279 }
280 vipStatistic.setName(query);
281 vipStatistic.setType(AreaTypeEnum.getByCode(refer.toUpperCase()));
282 vipStatistic.setToday(todayCount);
283 vipStatistic.setThisMonth(monthCount);
284 vipStatistic.setTotal(total);
285 vipStatistic.setSevenDays(sevenDays);
286 vipStatistic.setSixMonths(sixMonths);
287
288 return vipStatistic;
289 }
290
291 /**
292 * 通用会员查询统计方法:可用于邮储食堂正式会员, 体验会员和复购会员
293 * 仅用于父级查询
294 * @param refer 查询标识
295 * @param query 查询条件
296 * @param clazz 类型
297 * @return vipStatistic
298 */
299 private VipStatisticResponse findVipStatistic(String refer, String query, Class<?> clazz) {
300 return this.generateVipStatistic(refer, query, null, clazz);
301 }
302
303 /**
304 * 通用会员查询统计方法:可用于邮储食堂正式会员, 体验会员和复购会员
305 * 仅用于子级查询
306 * @param refer 查询标识
307 * @param query 查询条件
308 * @param clazz 类型
309 * @return vipStatistic
310 */
311 private VipStatisticResponse findVipStatistic(String refer, String query, Integer count, Class<?> clazz) {
312 return this.generateVipStatistic(refer, query, count, clazz);
313 }
314
315 }
1 package net.baiqu.shop.data.core.service.impl;
2
3 import com.alibaba.fastjson.JSONObject;
4 import com.mongodb.BasicDBObject;
5 import lombok.extern.slf4j.Slf4j;
6 import net.baiqu.shop.data.api.enums.ApiResponseCodeEnum;
7 import net.baiqu.shop.data.api.enums.report.AreaTypeEnum;
8 import net.baiqu.shop.data.api.models.request.report.ReportQueryRequest;
9 import net.baiqu.shop.data.api.models.response.amount.AmountChartResponse;
10 import net.baiqu.shop.data.api.models.response.amount.AmountStatisticResponse;
11 import net.baiqu.shop.data.core.exception.AppException;
12 import net.baiqu.shop.data.core.service.AmountStatisticService;
13 import net.baiqu.shop.data.core.util.DateUtils;
14 import org.springframework.beans.factory.annotation.Autowired;
15 import org.springframework.data.domain.Sort;
16 import org.springframework.data.mongodb.core.MongoTemplate;
17 import org.springframework.data.mongodb.core.aggregation.Aggregation;
18 import org.springframework.data.mongodb.core.aggregation.AggregationResults;
19 import org.springframework.data.mongodb.core.query.Criteria;
20 import org.springframework.stereotype.Service;
21 import org.springframework.util.CollectionUtils;
22
23 import java.math.BigDecimal;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.concurrent.*;
29 import java.util.stream.Collectors;
30
31 import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
32
33 @Service
34 @Slf4j
35 public class AmountStatisticServiceImpl implements AmountStatisticService {
36
37 private ExecutorService executor;
38
39 @Autowired
40 private MongoTemplate mongoTemplate;
41
42 private Class<?> clazz;
43
44 public AmountStatisticServiceImpl() {
45 executor = new ThreadPoolExecutor(
46 5,
47 10,
48 60,
49 TimeUnit.SECONDS, new LinkedBlockingQueue<>(),
50 new ThreadPoolExecutor.AbortPolicy());
51 }
52
53 /**
54 * 查询消费统计
55 *
56 * @return
57 */
58 @Override
59 public AmountStatisticResponse getAmountStatistic(ReportQueryRequest request, Class<?> clazz) {
60 this.clazz = clazz;
61 String province = request.getProvince();
62 String city = request.getCity();
63 String area = request.getArea();
64 String bank = request.getBank();
65 //下线集合
66 List<AmountStatisticResponse> child = new ArrayList<>();
67 AmountStatisticResponse reportStatistic;
68 if (city == null) {
69 reportStatistic = getAmountChart("province", province);
70 reportStatistic.setTotal(getTotal("province", province));
71 log.info("getAmountStatistic->reportStatistic 省统计数据:{}", JSONObject.toJSONString(reportStatistic));
72 //查询省份下线城市
73 Map<String, BigDecimal> proChild = getChildMap("province", province, "city");
74 List<CompletableFuture<Integer>> tasks = proChild.keySet().stream()
75 .map(c -> CompletableFuture.supplyAsync(() -> {
76 return getProChild(proChild, child, c);
77 }, executor)).collect(Collectors.toList());
78 tasks.stream().map(CompletableFuture::join).collect(Collectors.toList());
79 reportStatistic.setChild(child);
80 } else if (area == null) {
81 reportStatistic = getAmountChart("city", city);
82 reportStatistic.setTotal(getTotal("city", city));
83 log.info("getAmountStatistic->reportStatistic 地市统计数据:{}", JSONObject.toJSONString(reportStatistic));
84 //查询城市下线地区
85 Map<String, BigDecimal> cityChild = getChildMap("city", city, "area");
86 List<CompletableFuture<Integer>> tasks = cityChild.keySet().stream()
87 .map(c -> CompletableFuture.supplyAsync(() -> {
88 return getCityChild(cityChild, child, c);
89 }, executor)).collect(Collectors.toList());
90 tasks.stream().map(CompletableFuture::join).collect(Collectors.toList());
91 reportStatistic.setChild(child);
92 } else if (bank == null) {
93 reportStatistic = getAmountChart("area", area);
94 reportStatistic.setTotal(getTotal("area", area));
95 log.info("getAmountStatistic->reportStatistic 县市统计数据:{}", JSONObject.toJSONString(reportStatistic));
96 //查询地区下线支行
97 Map<String, BigDecimal> areaChild = getChildMap("area", area, "bank");
98 List<CompletableFuture<Integer>> tasks = areaChild.keySet().stream()
99 .map(c -> CompletableFuture.supplyAsync(() -> {
100 return getAreaChild(areaChild, child, c);
101 }, executor)).collect(Collectors.toList());
102 tasks.stream().map(CompletableFuture::join).collect(Collectors.toList());
103 reportStatistic.setChild(child);
104 } else {
105 reportStatistic = getAmountChart("bank", bank);
106 reportStatistic.setTotal(getTotal("bank", bank));
107 log.info("getAmountStatistic->reportStatistic 支行统计数据:{}", JSONObject.toJSONString(reportStatistic));
108 }
109 //log.info("getReportStastic-->response:{}", JSONObject.toJSONString(reportStatistic));
110 return reportStatistic;
111 }
112
113 /**
114 * 查询顶级组织的总金额
115 *
116 * @param areaType 区域类型
117 * @param area 区域
118 * @return
119 */
120 private BigDecimal getTotal(String areaType, String area) {
121 Aggregation agg = Aggregation.newAggregation(
122 match(Criteria.where(areaType).is(area)),
123 group(areaType).sum("amount").as("total"));
124 AggregationResults<BasicDBObject> results = mongoTemplate.aggregate(agg, clazz, BasicDBObject.class);
125 if (results.getMappedResults() == null || results.getMappedResults().size() < 1) {
126 return new BigDecimal(0);
127 }
128 return new BigDecimal(results.getMappedResults().get(0).get("total").toString());
129 }
130
131 /**
132 * 获取折现图和当日、当月金额
133 *
134 * @param areaType 区域类型
135 * @param area 区域
136 * @return
137 */
138 private AmountStatisticResponse getAmountChart(String areaType, String area) {
139 AmountStatisticResponse reportStatistic = new AmountStatisticResponse();
140 reportStatistic.setName(area);
141 reportStatistic.setType(AreaTypeEnum.getByCode(areaType.toUpperCase()));
142 //7日数据
143 List<AmountChartResponse> sevenDays = getAmountChartResults(areaType, area, "day", DateUtils.getSevenDays());
144 reportStatistic.setToday(sevenDays.get(0).getAmount());
145 reportStatistic.setSevenDays(sevenDays);
146 //6个月数据
147 List<AmountChartResponse> sixMonths = getAmountChartResults(areaType, area, "month", DateUtils.getSixMonths());
148 reportStatistic.setThisMonth(sixMonths.get(0).getAmount());
149 reportStatistic.setSixMonths(sixMonths);
150 return reportStatistic;
151 }
152
153 /**
154 * 获取折线图数据
155 *
156 * @param areaType 区域类型
157 * @param area 区域
158 * @param dateType 时间类型
159 * @param dates 时间集合
160 * @return
161 */
162 private List<AmountChartResponse> getAmountChartResults(String areaType, String area, String dateType, List<String> dates) {
163 Aggregation agg = Aggregation.newAggregation(
164 match(Criteria.where(areaType).is(area).and(dateType).in(dates)),
165 group(dateType).sum("amount").as("amount"),
166 project("amount").and("_id").as("date"),
167 sort(Sort.Direction.DESC, "date"));
168 AggregationResults<BasicDBObject> results = mongoTemplate.aggregate(agg, clazz, BasicDBObject.class);
169 if (CollectionUtils.isEmpty(results.getMappedResults())) {
170 throw new AppException(ApiResponseCodeEnum.ORDER_NOT_EXIST);
171 }
172 Map<String, BigDecimal> map = new HashMap<>();
173 for (BasicDBObject result : results) {
174 String date = result.getString("date");
175 BigDecimal amount = new BigDecimal(result.get("amount").toString());
176 map.put(date, amount);
177 }
178 List<AmountChartResponse> list = new ArrayList<>();
179 for (int i = 0; i < dates.size(); i++) {
180 AmountChartResponse amountChart = new AmountChartResponse();
181 if (map.containsKey(dates.get(i))) {
182 amountChart.setAmount(map.get(dates.get(i)));
183 } else {
184 amountChart.setAmount(new BigDecimal(0));
185 }
186 amountChart.setDate(dates.get(i));
187 list.add(amountChart);
188 }
189 // log.info("AmountStatisticServiceImpl->getAmountChartResults: {}", JSONObject.toJSONString(list));
190 return list;
191 }
192
193
194 /**
195 * 查询下线以及下线的总金额
196 *
197 * @param parentType 上级类型
198 * @param area 要查询的地区
199 * @param childType 下级类型
200 * @return
201 */
202 private Map<String, BigDecimal> getChildMap(String parentType, String area, String childType) {
203 Map<String, BigDecimal> map = new HashMap<>();
204 Aggregation agg = Aggregation.newAggregation(
205 match(Criteria.where(parentType).is(area)),
206 group(childType).sum("amount").as("amount"));
207 AggregationResults<BasicDBObject> results = mongoTemplate.aggregate(agg, clazz, BasicDBObject.class);
208 if (CollectionUtils.isEmpty(results.getMappedResults())) {
209 throw new AppException(ApiResponseCodeEnum.ORDER_NOT_EXIST);
210 }
211 for (BasicDBObject result : results) {
212 String newArea = result.getString("_id");
213 BigDecimal amount = new BigDecimal(result.get("amount").toString());
214 map.put(newArea, amount);
215 }
216 // log.info("AmountStatisticServiceImpl->getChildMap: {}", JSONObject.toJSONString(map));
217 return map;
218 }
219
220
221 /**
222 * 获取省份子集
223 *
224 * @param childMap 子集map
225 * @param child 下线子集
226 * @param city 城市
227 * @return
228 */
229 private int getProChild(Map<String, BigDecimal> childMap, List<AmountStatisticResponse> child, String city) {
230 AmountStatisticResponse cityStatistic = getAmountChart("city", city);
231 cityStatistic.setTotal(childMap.get(city));
232 Map<String, BigDecimal> cityChild = getChildMap("city", city, "area");
233 //查询下线区域孩子
234 List<AmountStatisticResponse> cityChildStatistic = new ArrayList<>();
235 for (String area : cityChild.keySet()) {
236 getCityChild(cityChild, cityChildStatistic, area);
237 }
238 // log.info("AmountStatisticServiceImpl->getProChild: {}", JSONObject.toJSONString(cityChildStatistic));
239 cityStatistic.setChild(cityChildStatistic);
240 child.add(cityStatistic);
241 return 1;
242 }
243
244
245 /**
246 * 获取城市子集
247 *
248 * @param childMap 子集map
249 * @param child 下线子集
250 * @param area 区域
251 * @return
252 */
253 private int getCityChild(Map<String, BigDecimal> childMap, List<AmountStatisticResponse> child, String area) {
254 AmountStatisticResponse areaStatistic = getAmountChart("area", area);
255 areaStatistic.setTotal(childMap.get(area));
256 Map<String, BigDecimal> areaChild = getChildMap("area", area, "bank");
257 //查询下线区域孩子
258 List<AmountStatisticResponse> areaChildStatistic = new ArrayList<>();
259 for (String bank : areaChild.keySet()) {
260 getAreaChild(areaChild, areaChildStatistic, bank);
261 }
262 // log.info("AmountStatisticServiceImpl->getCityChild: {}", JSONObject.toJSONString(areaChildStatistic));
263 areaStatistic.setChild(areaChildStatistic);
264 child.add(areaStatistic);
265 return 1;
266 }
267
268
269 /**
270 * 获取区域子集
271 *
272 * @param childMap 子集map
273 * @param child 下线子集
274 * @param bank 支行
275 * @return
276 */
277 private int getAreaChild(Map<String, BigDecimal> childMap, List<AmountStatisticResponse> child, String bank) {
278 AmountStatisticResponse bankStatistic = getbankStatistic(childMap, bank);
279 // log.info("AmountStatisticServiceImpl->getAreaChild: {}", JSONObject.toJSONString(bankStatistic));
280 child.add(bankStatistic);
281 return 1;
282 }
283
284 /**
285 * 获取支行统计
286 *
287 * @param childMap 子集map
288 * @param bank 支行
289 * @return
290 */
291 private AmountStatisticResponse getbankStatistic(Map<String, BigDecimal> childMap, String bank) {
292 AmountStatisticResponse bankStatistic = getAmountChart("bank", bank);
293 // log.info("AmountStatisticServiceImpl->getbankStatistic: {}", JSONObject.toJSONString(bankStatistic));
294 bankStatistic.setTotal(childMap.get(bank));
295 return bankStatistic;
296 }
297
298 }