商城报表统计

  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 }

 

posted on 2018-09-03 17:55  动物管理猿  阅读(595)  评论(0编辑  收藏  举报

导航