|
@@ -1,19 +1,37 @@
|
|
|
package com.abi.qms.platform.service.impl;
|
|
|
|
|
|
+import com.abi.qms.platform.dao.enums.QrTypeEnum;
|
|
|
import com.abi.qms.platform.dao.mapper.ReportServiceMapper;
|
|
|
import com.abi.qms.platform.dao.vo.result.ListBrandCodeReportVO;
|
|
|
+import com.abi.qms.platform.dao.vo.result.ListFactoryCodeReportVO;
|
|
|
import com.abi.qms.platform.dao.vo.result.ListSkuCodeReportVO;
|
|
|
+import com.abi.qms.platform.dao.vo.result.ListPackageCodeVo;
|
|
|
import com.abi.qms.platform.dto.req.ReportReq;
|
|
|
import com.abi.qms.platform.dto.res.ListBrandCodeReportRes;
|
|
|
+import com.abi.qms.platform.dto.res.ListFactoryCodeReportRes;
|
|
|
import com.abi.qms.platform.dto.res.ListSkuCodeRankingReportRes;
|
|
|
+import com.abi.qms.platform.dto.res.PackageCodeTypeRes;
|
|
|
import com.abi.qms.platform.service.ReportService;
|
|
|
import com.abi.task.common.utils.PojoConverterUtils;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
+import org.springframework.util.ObjectUtils;
|
|
|
|
|
|
import java.text.DecimalFormat;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.time.DayOfWeek;
|
|
|
+import java.time.Instant;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.time.temporal.TemporalAdjusters;
|
|
|
+import java.util.Calendar;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
@@ -26,23 +44,26 @@ public class ReportServiceImpl implements ReportService {
|
|
|
@Autowired
|
|
|
private ReportServiceMapper reportServiceMapper;
|
|
|
|
|
|
- /**
|
|
|
- * 品牌使用码量占比
|
|
|
- * @author ludashi
|
|
|
- * @date 2021/6/2 17:50
|
|
|
- * @param reportReq
|
|
|
- * @return com.abi.qms.platform.dto.res.ListBrandCodeReportRes
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * 品牌使用码量占比
|
|
|
+ *
|
|
|
+ * @param reportReq
|
|
|
+ * @return com.abi.qms.platform.dto.res.ListBrandCodeReportRes
|
|
|
+ * @author ludashi
|
|
|
+ * @date 2021/6/2 17:50
|
|
|
+ */
|
|
|
@Override
|
|
|
public ListBrandCodeReportRes queryBrandCodeProportion(ReportReq reportReq) {
|
|
|
+ //参数设置初始化
|
|
|
+ setQueryTime(reportReq);
|
|
|
//查询 品牌数量
|
|
|
List<ListBrandCodeReportVO> listReportVOS = reportServiceMapper.queryBrandCodeProportion(reportReq);
|
|
|
- //求总和
|
|
|
- Long collect = listReportVOS.stream().collect(Collectors.summingLong(ListBrandCodeReportVO::getQrNumber));
|
|
|
if(!CollectionUtils.isEmpty(listReportVOS)){
|
|
|
+ //求总和
|
|
|
+ Long collect = listReportVOS.stream().collect(Collectors.summingLong(ListBrandCodeReportVO::getQrNumber));
|
|
|
listReportVOS.forEach(listReportVO->{
|
|
|
- long l = listReportVO.getQrNumber() / collect * 100;
|
|
|
- listReportVO.setPercent(new DecimalFormat("#0.00").format(l + 0.000001d)+"%");
|
|
|
+ Double val = new Double(listReportVO.getQrNumber() / collect * 100);
|
|
|
+ listReportVO.setPercent(new DecimalFormat("#0.00").format(val + 0.000001d)+"%");
|
|
|
});
|
|
|
}
|
|
|
// 封装出参
|
|
@@ -66,4 +87,329 @@ public class ReportServiceImpl implements ReportService {
|
|
|
res.setReportSkuCodeRankingResList(skuCodeReportResBeans);
|
|
|
return res;
|
|
|
}
|
|
|
-}
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 包材厂使用码量,下载率
|
|
|
+ * @param reportReq
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public ListFactoryCodeReportRes queryFactoryCodeTotalReport(ReportReq reportReq) {
|
|
|
+ //参数设置初始化
|
|
|
+ setQueryTime(reportReq);
|
|
|
+ //包材厂生成包数量
|
|
|
+ List<ListFactoryCodeReportVO> listFactoryCodeTotalReportVOS = reportServiceMapper.queryFactoryCodeTotal(reportReq,0);
|
|
|
+ //包材厂包下载量
|
|
|
+ List<ListFactoryCodeReportVO> listFactoryCodeDownloadTotalReportVOS = reportServiceMapper.queryFactoryCodeTotal(reportReq,1);
|
|
|
+ Map<String, Long> FactoryCodeDownloadTotalMaps = listFactoryCodeTotalReportVOS.stream().collect(Collectors.toMap(ListFactoryCodeReportVO::getFactoryName, ListFactoryCodeReportVO::getQrNumber));
|
|
|
+ listFactoryCodeTotalReportVOS.forEach(listReportVO->{
|
|
|
+ Double val = 0d;
|
|
|
+ if (null != FactoryCodeDownloadTotalMaps.get(listReportVO.getFactoryName())){
|
|
|
+ val = new Double(FactoryCodeDownloadTotalMaps.get(listReportVO.getFactoryName()) / listReportVO.getQrNumber() * 100);
|
|
|
+ }
|
|
|
+ listReportVO.setDownloadNumber(new DecimalFormat("#0.00").format(val + 0.000001d)+"%");
|
|
|
+ });
|
|
|
+ // 封装出参
|
|
|
+ ListFactoryCodeReportRes res = new ListFactoryCodeReportRes();
|
|
|
+ List<ListFactoryCodeReportRes.FactoryCodeReportResBean> reportFactoryRes = PojoConverterUtils.copyList(listFactoryCodeTotalReportVOS, ListFactoryCodeReportRes.FactoryCodeReportResBean.class);
|
|
|
+ res.setFactoryCodeResReportList(reportFactoryRes);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置时间区间值
|
|
|
+ * @param reportReq
|
|
|
+ */
|
|
|
+ private void setQueryTime(ReportReq reportReq){
|
|
|
+ if(!ObjectUtils.isEmpty(reportReq) &&
|
|
|
+ null == reportReq.getEndTime() &&
|
|
|
+ null == reportReq.getBeginTime() &&
|
|
|
+ !ObjectUtils.isEmpty(reportReq.getValue())){
|
|
|
+ HashMap<String, LocalDateTime> timestamp = getTimestamp(reportReq.getValue());
|
|
|
+ reportReq.setBeginTime( timestamp.get("startTime"));
|
|
|
+ reportReq.setEndTime( timestamp.get("endTime"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据类型获取时间范围
|
|
|
+ * @param timeType (0-当天,1-本周,2-本月)
|
|
|
+ * @return key 开始时间:startTime 结束时间:endTime
|
|
|
+ */
|
|
|
+ private HashMap<String, LocalDateTime> getTimestamp(Integer timeType) {
|
|
|
+ HashMap<String, LocalDateTime> hashMap = new HashMap<String, LocalDateTime>();
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
+
|
|
|
+ //当天
|
|
|
+ if (timeType == 0){
|
|
|
+ hashMap.put("startTime", longTurnData(getTimestampByOffsetDay(0)));
|
|
|
+ hashMap.put("endTime", longTurnData(getTimestampByOffsetDay(1)));
|
|
|
+ }
|
|
|
+ //本周
|
|
|
+ if (timeType == 1){
|
|
|
+ hashMap.put(
|
|
|
+ "startTime",
|
|
|
+ longTurnData(getTimestampByOffsetDay(0 - calendar.get(Calendar.DAY_OF_WEEK) + 2)) );
|
|
|
+ hashMap.put(
|
|
|
+ "endTime",
|
|
|
+ longTurnData( getTimestampByOffsetDay(calendar
|
|
|
+ .getMaximum(Calendar.DAY_OF_WEEK)
|
|
|
+ - calendar.get(Calendar.DAY_OF_WEEK) + 2)));
|
|
|
+ }
|
|
|
+
|
|
|
+ //本月
|
|
|
+ if (timeType == 2){
|
|
|
+ hashMap.put(
|
|
|
+ "startTime",
|
|
|
+ longTurnData(getTimestampByOffsetDay(0 - calendar.get(Calendar.DAY_OF_MONTH) + 1)));
|
|
|
+ hashMap.put(
|
|
|
+ "endTime",
|
|
|
+ longTurnData( getTimestampByOffsetDay(calendar
|
|
|
+ .getMaximum(Calendar.DAY_OF_MONTH)
|
|
|
+ - calendar.get(Calendar.DAY_OF_MONTH))));
|
|
|
+ }
|
|
|
+ return hashMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 时间格式转化
|
|
|
+ * @author ludashi
|
|
|
+ * @date 2021/6/3 13:37
|
|
|
+ * @param l 时间毫秒值
|
|
|
+ * @return java.time.LocalDateTime
|
|
|
+ */
|
|
|
+ private LocalDateTime longTurnData(Long l) {
|
|
|
+ Instant instant = Instant.ofEpochMilli(l);
|
|
|
+ ZoneId zone = ZoneId.systemDefault();
|
|
|
+ LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
|
|
|
+ return localDateTime;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 时间定义
|
|
|
+ * @author ludashi
|
|
|
+ * @date 2021/6/3 13:12
|
|
|
+ * @param day
|
|
|
+ * @return long
|
|
|
+ */
|
|
|
+ public long getTimestampByOffsetDay(int day){
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
+ calendar.add(Calendar.DAY_OF_MONTH, day);
|
|
|
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
+ calendar.set(Calendar.SECOND, 0);
|
|
|
+ calendar.set(Calendar.MINUTE, 0);
|
|
|
+ calendar.set(Calendar.MILLISECOND, 0);
|
|
|
+ return calendar.getTimeInMillis();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public PackageCodeTypeRes queryPackageCodeGeneral(ReportReq reportReq) {
|
|
|
+ PackageCodeTypeRes res = new PackageCodeTypeRes();
|
|
|
+ int before=0;//往期
|
|
|
+ int present=0;//同期
|
|
|
+ //封装入参
|
|
|
+ Map<String,LocalDateTime> map=null;
|
|
|
+ if(!ObjectUtils.isEmpty(reportReq) && null == reportReq.getEndTime() && null == reportReq.getBeginTime()){
|
|
|
+ HashMap<String, LocalDateTime> timestamp = getTimestamp(reportReq.getValue());
|
|
|
+ reportReq.setBeginTime( timestamp.get("startTime"));
|
|
|
+ reportReq.setEndTime( timestamp.get("endTime"));
|
|
|
+ if(1==reportReq.getValue()){//周
|
|
|
+ map=getBeforeWeekTimes();
|
|
|
+ }
|
|
|
+ if(2==reportReq.getValue()){//月
|
|
|
+ map=getBeforeMonthTime();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //1.生成码数量
|
|
|
+ getGenerateCodeNum(reportReq, res,present,before,map);
|
|
|
+ //2.下载码数量
|
|
|
+ getLoadCodeNum(reportReq, res,present,before,map);
|
|
|
+ //3.激活码数量
|
|
|
+ getActivateCodeNum(reportReq, res,present,before,map);
|
|
|
+ //返回参数
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void getGenerateCodeNum(ReportReq reportReq, PackageCodeTypeRes res, int present, int before,Map<String,LocalDateTime> map) {
|
|
|
+ List<ListPackageCodeVo> createList = reportServiceMapper.queryPackageCodeNum(reportReq,map.get("beginDate"), map.get("endDate"));
|
|
|
+ /**
|
|
|
+ * 处理逻辑
|
|
|
+ * 1.取出本周的数据集
|
|
|
+ * 2.取出不是本周的数据集
|
|
|
+ * 3.本周的数据集-不是本周的数据集/不是本周的数据集*100%
|
|
|
+ */
|
|
|
+ for (int i = 0; i < createList.size(); i++) {
|
|
|
+ if("0".equals(createList.get(i).getPercent())){
|
|
|
+ if (QrTypeEnum.CARTON.getCode().equals(createList.get(i).getQrType())) {//判断是否箱码
|
|
|
+ res.setCreateBoxNumber(createList.get(i).getQrNumber());//箱码
|
|
|
+ } else if (QrTypeEnum.CAP.getCode().equals(createList.get(i).getQrType())) {//判断是否盖码
|
|
|
+ res.setCreateCapNumber(createList.get(i).getQrNumber());//盖码
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(reportReq.getValue() + "")) {
|
|
|
+ //计算同期和往期的箱码和盖码
|
|
|
+ String vaiue=reportReq.getValue() + "";
|
|
|
+ before = createList.stream().filter(x -> x.getPercent().equals(vaiue)).mapToInt(x -> Math.toIntExact(x.getQrNumber())).sum();
|
|
|
+ present = createList.stream().filter(x -> x.getPercent().equals("0")).mapToInt(x -> Math.toIntExact(x.getQrNumber())).sum();
|
|
|
+ BigDecimal number = new BigDecimal(0);
|
|
|
+ BigDecimal preNum = BigDecimal.valueOf((int) present);
|
|
|
+ BigDecimal sufNum = BigDecimal.valueOf((int) before);
|
|
|
+ String result = percentBigDecimal(preNum, sufNum);
|
|
|
+ res.setCreatePercent(result);//获取同比增长率
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private void getLoadCodeNum(ReportReq reportReq, PackageCodeTypeRes res, int present, int before,Map<String,LocalDateTime> map) {
|
|
|
+ List<ListPackageCodeVo> loadList = reportServiceMapper.queryLoadPackageCodeNum(reportReq,map.get("beginDate"), map.get("endDate"));
|
|
|
+ for (int i = 0; i < loadList.size(); i++) {
|
|
|
+ if("0".equals(loadList.get(i).getPercent())) {
|
|
|
+ if (QrTypeEnum.CARTON.getCode().equals(loadList.get(i).getQrType())) {
|
|
|
+ res.setLoadBoxNumber(loadList.get(i).getQrNumber());
|
|
|
+ } else if (QrTypeEnum.CAP.getCode().equals(loadList.get(i).getQrType())) {
|
|
|
+ res.setLoadCapNumber(loadList.get(i).getQrNumber());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(reportReq.getValue() + "")) {
|
|
|
+ //计算同期和往期的箱码和盖码
|
|
|
+ before = loadList.stream().filter(x -> x.getPercent().equals(reportReq.getValue())).mapToInt(x -> Math.toIntExact(x.getQrNumber())).sum();
|
|
|
+ //获取为0的
|
|
|
+ present = loadList.stream().filter(x -> x.getPercent().equals("0")).mapToInt(x -> Math.toIntExact(x.getQrNumber())).sum();
|
|
|
+ BigDecimal number = new BigDecimal(0);
|
|
|
+ BigDecimal preNum = BigDecimal.valueOf((int) present);
|
|
|
+ BigDecimal sufNum = BigDecimal.valueOf((int) before);
|
|
|
+ String result = percentBigDecimal(preNum, sufNum);
|
|
|
+ res.setLoadPercent(result);//获取同比增长率
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private void getActivateCodeNum(ReportReq reportReq, PackageCodeTypeRes res, int present, int before,Map<String,LocalDateTime> map) {
|
|
|
+ List<ListPackageCodeVo> activateList = reportServiceMapper.queryActivateCodeNum(reportReq,map.get("beginDate"), map.get("endDate"));
|
|
|
+ for (int i = 0; i < activateList.size(); i++) {
|
|
|
+ if("0".equals(activateList.get(i).getPercent())) {
|
|
|
+ if (QrTypeEnum.CARTON.getCode().equals(activateList.get(i).getQrType())) {
|
|
|
+ res.setActivateBoxNumber(activateList.get(i).getQrNumber());
|
|
|
+ } else if (QrTypeEnum.CAP.getCode().equals(activateList.get(i).getQrType())) {
|
|
|
+ res.setActivateCapNumber(activateList.get(i).getQrNumber());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(reportReq.getValue() + "")) {
|
|
|
+ //计算同期和往期的箱码和盖码
|
|
|
+ before = activateList.stream().filter(x -> x.getPercent().equals(reportReq.getValue())).mapToInt(x -> Math.toIntExact(x.getQrNumber())).sum();
|
|
|
+ present = activateList.stream().filter(x -> x.getPercent().equals("0")).mapToInt(x -> Math.toIntExact(x.getQrNumber())).sum();
|
|
|
+ BigDecimal number = new BigDecimal(0);
|
|
|
+ BigDecimal preNum = BigDecimal.valueOf((int) present);
|
|
|
+ BigDecimal sufNum = BigDecimal.valueOf((int) before);
|
|
|
+ String result = percentBigDecimal(preNum, sufNum);
|
|
|
+ res.setActivatePercent(result);//获取同比增长率
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * @param preNum 同期数
|
|
|
+ * @param sufNum 往期数
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String percentBigDecimal(BigDecimal preNum, BigDecimal sufNum) {
|
|
|
+ double result = countDecimal(preNum, sufNum);
|
|
|
+ if (result > 0) {
|
|
|
+ System.out.println("上升" + result + "%");
|
|
|
+ return "+" + result + "%";
|
|
|
+ }
|
|
|
+ if (result < 0) {
|
|
|
+ return "-" + Math.abs(result) + "%";
|
|
|
+ }
|
|
|
+ if (result == 0) {
|
|
|
+ return "0%";
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static double countDecimal(BigDecimal preNum, BigDecimal sufNum) {
|
|
|
+ boolean preBoolean = verifyNum(preNum);
|
|
|
+ boolean sufBoolean = verifyNum(sufNum);
|
|
|
+ //同时为true计算
|
|
|
+ if (preBoolean && sufBoolean) {
|
|
|
+ boolean b = verifyEqual(preNum, sufNum);
|
|
|
+ if (b == false) {
|
|
|
+ return realCountDecimal(preNum, sufNum);
|
|
|
+ }
|
|
|
+ if (b) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (preBoolean == false && sufBoolean == false) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (sufBoolean == false) {
|
|
|
+ return 100;
|
|
|
+ }
|
|
|
+ if (preBoolean == false) {
|
|
|
+ return -100;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ //验证数字是否为零和null
|
|
|
+ public static boolean verifyNum(BigDecimal num) {
|
|
|
+ if (null != num && num.compareTo(BigDecimal.ZERO) != 0) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ //验证两个数字是否相等
|
|
|
+ public static boolean verifyEqual(BigDecimal preNum, BigDecimal sufNum) {
|
|
|
+ int n = preNum.compareTo(sufNum);
|
|
|
+ if (n == 0) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ //真正计算
|
|
|
+ public static double realCountDecimal(BigDecimal preNum, BigDecimal sufNum) {
|
|
|
+ //(前面的数字-后面的数字)/后面的数字*100
|
|
|
+ BigDecimal bigDecimal = (preNum.subtract(sufNum)).divide(sufNum, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
+ if (bigDecimal.compareTo(BigDecimal.ZERO) != 0) {
|
|
|
+ return bigDecimal.doubleValue();
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取上月月初和月末日期
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public Map<String,LocalDateTime> getBeforeMonthTime(){
|
|
|
+ Map<String,LocalDateTime> map=new HashMap<String,LocalDateTime>();
|
|
|
+ DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
+ String localTime = fmt.format(LocalDateTime.now());
|
|
|
+ LocalDateTime date2 = LocalDateTime.parse(localTime, fmt);
|
|
|
+ LocalDateTime localDateTime = date2.minusMonths(1);
|
|
|
+ LocalDateTime with = localDateTime.with(TemporalAdjusters.lastDayOfMonth());
|
|
|
+ LocalDateTime with2 = localDateTime.with(TemporalAdjusters.firstDayOfMonth());
|
|
|
+ map.put("beginDate",localDateTime.with(TemporalAdjusters.lastDayOfMonth()));
|
|
|
+ map.put("endDate",localDateTime.with(TemporalAdjusters.firstDayOfMonth()));
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取上周周一和周末的数据
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public Map<String,LocalDateTime> getBeforeWeekTimes(){
|
|
|
+ Map<String,LocalDateTime> map=new HashMap<String,LocalDateTime>();
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
+ LocalDateTime todayOfLastWeek = now.minusDays(7);
|
|
|
+ LocalDateTime monday = todayOfLastWeek.with(TemporalAdjusters.previous(DayOfWeek.SUNDAY)).plusDays(1);
|
|
|
+ LocalDateTime sunday = todayOfLastWeek.with(TemporalAdjusters.next(DayOfWeek.MONDAY)).minusDays(1);
|
|
|
+ map.put("beginDate",monday);
|
|
|
+ map.put("endDate",sunday);
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|