|
|
@@ -57,24 +57,20 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
.le(Order::getPayTime, todayEnd);
|
|
|
|
|
|
List<Order> todayOrders = orderService.list(todayWrapper);
|
|
|
-
|
|
|
- // 今日销售额
|
|
|
- double todaySales = todayOrders.stream()
|
|
|
- .mapToDouble(o -> o.getTotalAmount() != null ? o.getTotalAmount() : 0)
|
|
|
- .sum();
|
|
|
- result.put("todaySales", String.format("%.2f", todaySales));
|
|
|
|
|
|
- // 今日订单量
|
|
|
+ BigDecimal todaySales = todayOrders.stream()
|
|
|
+ .map(o -> o.getTotalAmount() != null ? o.getTotalAmount() : BigDecimal.ZERO)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ result.put("todaySales", todaySales.setScale(2, RoundingMode.HALF_UP).toString());
|
|
|
+
|
|
|
int todayOrderCount = todayOrders.size();
|
|
|
result.put("todayOrders", todayOrderCount);
|
|
|
|
|
|
- // 今日客单价
|
|
|
String todayAvgPrice = todayOrderCount > 0
|
|
|
- ? String.format("%.2f", todaySales / todayOrderCount)
|
|
|
+ ? todaySales.divide(BigDecimal.valueOf(todayOrderCount), 2, RoundingMode.HALF_UP).toString()
|
|
|
: "0.00";
|
|
|
result.put("todayAvgPrice", todayAvgPrice);
|
|
|
|
|
|
- // 昨日同时段销售额和订单量
|
|
|
LambdaQueryWrapper<Order> yesterdayWrapper = new LambdaQueryWrapper<>();
|
|
|
yesterdayWrapper.eq(Order::getPayStatus, OrderConstants.PAY_STATUS_PAID)
|
|
|
.ge(Order::getPayTime, yesterdayStart)
|
|
|
@@ -82,17 +78,20 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
|
|
|
List<Order> yesterdayOrders = orderService.list(yesterdayWrapper);
|
|
|
|
|
|
- double yesterdaySales = yesterdayOrders.stream()
|
|
|
- .mapToDouble(o -> o.getTotalAmount() != null ? o.getTotalAmount() : 0)
|
|
|
- .sum();
|
|
|
+ BigDecimal yesterdaySales = yesterdayOrders.stream()
|
|
|
+ .map(o -> o.getTotalAmount() != null ? o.getTotalAmount() : BigDecimal.ZERO)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
int yesterdayOrderCount = yesterdayOrders.size();
|
|
|
- double yesterdayAvgPrice = yesterdayOrderCount > 0 ? yesterdaySales / yesterdayOrderCount : 0;
|
|
|
+ BigDecimal yesterdayAvgPrice = yesterdayOrderCount > 0
|
|
|
+ ? yesterdaySales.divide(BigDecimal.valueOf(yesterdayOrderCount), 2, RoundingMode.HALF_UP)
|
|
|
+ : BigDecimal.ZERO;
|
|
|
|
|
|
- // 与昨日同时段对比
|
|
|
- result.put("todaySalesCompare", formatCompare(todaySales - yesterdaySales));
|
|
|
+ result.put("todaySalesCompare", formatCompare(todaySales.subtract(yesterdaySales)));
|
|
|
result.put("todayOrdersCompare", formatCompare(todayOrderCount - yesterdayOrderCount));
|
|
|
- result.put("todayAvgPriceCompare", formatCompare(todayOrderCount > 0 ?
|
|
|
- (todaySales / todayOrderCount) - yesterdayAvgPrice : 0));
|
|
|
+ BigDecimal todayAvg = todayOrderCount > 0
|
|
|
+ ? todaySales.divide(BigDecimal.valueOf(todayOrderCount), 2, RoundingMode.HALF_UP)
|
|
|
+ : BigDecimal.ZERO;
|
|
|
+ result.put("todayAvgPriceCompare", formatCompare(todayAvg.subtract(yesterdayAvgPrice)));
|
|
|
|
|
|
// 设备状态统计
|
|
|
long totalDevices = deviceService.count();
|
|
|
@@ -168,21 +167,19 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
|
|
|
List<Order> orders = orderService.list(wrapper);
|
|
|
|
|
|
- // 销售额
|
|
|
- double totalSales = orders.stream()
|
|
|
- .mapToDouble(o -> o.getTotalAmount() != null ? o.getTotalAmount() : 0)
|
|
|
- .sum();
|
|
|
- result.put("totalSales", String.format("%.2f", totalSales));
|
|
|
+ BigDecimal totalSales = orders.stream()
|
|
|
+ .map(o -> o.getTotalAmount() != null ? o.getTotalAmount() : BigDecimal.ZERO)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ result.put("totalSales", totalSales.setScale(2, RoundingMode.HALF_UP).toString());
|
|
|
|
|
|
- // 订单量
|
|
|
int totalOrders = orders.size();
|
|
|
result.put("totalOrders", totalOrders);
|
|
|
|
|
|
- // 单均价
|
|
|
- double avgOrderPrice = totalOrders > 0 ? totalSales / totalOrders : 0;
|
|
|
- result.put("avgOrderPrice", String.format("%.2f", avgOrderPrice));
|
|
|
+ BigDecimal avgOrderPrice = totalOrders > 0
|
|
|
+ ? totalSales.divide(BigDecimal.valueOf(totalOrders), 2, RoundingMode.HALF_UP)
|
|
|
+ : BigDecimal.ZERO;
|
|
|
+ result.put("avgOrderPrice", avgOrderPrice.toString());
|
|
|
|
|
|
- // 查询对比期数据
|
|
|
LambdaQueryWrapper<Order> compareWrapper = new LambdaQueryWrapper<>();
|
|
|
compareWrapper.eq(Order::getPayStatus, OrderConstants.PAY_STATUS_PAID)
|
|
|
.ge(Order::getPayTime, compareStartTime)
|
|
|
@@ -190,26 +187,28 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
|
|
|
List<Order> compareOrders = orderService.list(compareWrapper);
|
|
|
|
|
|
- double compareSales = compareOrders.stream()
|
|
|
- .mapToDouble(o -> o.getTotalAmount() != null ? o.getTotalAmount() : 0)
|
|
|
- .sum();
|
|
|
+ BigDecimal compareSales = compareOrders.stream()
|
|
|
+ .map(o -> o.getTotalAmount() != null ? o.getTotalAmount() : BigDecimal.ZERO)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
int compareOrderCount = compareOrders.size();
|
|
|
- double compareAvgPrice = compareOrderCount > 0 ? compareSales / compareOrderCount : 0;
|
|
|
+ BigDecimal compareAvgPrice = compareOrderCount > 0
|
|
|
+ ? compareSales.divide(BigDecimal.valueOf(compareOrderCount), 2, RoundingMode.HALF_UP)
|
|
|
+ : BigDecimal.ZERO;
|
|
|
|
|
|
- // 环比增长率
|
|
|
result.put("salesGrowth", formatGrowth(totalSales, compareSales));
|
|
|
result.put("ordersGrowth", formatGrowth(totalOrders, compareOrderCount));
|
|
|
result.put("avgOrderGrowth", formatGrowth(avgOrderPrice, compareAvgPrice));
|
|
|
|
|
|
- // 毛利和毛利率(假设毛利为销售额的30%,实际应从成本数据计算)
|
|
|
- double grossProfit = totalSales * 0.3;
|
|
|
- double profitMargin = totalSales > 0 ? (grossProfit / totalSales) * 100 : 0;
|
|
|
- double compareGrossProfit = compareSales * 0.3;
|
|
|
+ BigDecimal grossProfit = totalSales.multiply(new BigDecimal("0.3"));
|
|
|
+ BigDecimal profitMargin = totalSales.compareTo(BigDecimal.ZERO) > 0
|
|
|
+ ? grossProfit.divide(totalSales, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100"))
|
|
|
+ : BigDecimal.ZERO;
|
|
|
+ BigDecimal compareGrossProfit = compareSales.multiply(new BigDecimal("0.3"));
|
|
|
|
|
|
- result.put("grossProfit", String.format("%.2f", grossProfit));
|
|
|
- result.put("profitMargin", String.format("%.0f", profitMargin) + "%");
|
|
|
+ result.put("grossProfit", grossProfit.setScale(2, RoundingMode.HALF_UP).toString());
|
|
|
+ result.put("profitMargin", profitMargin.setScale(1, RoundingMode.HALF_UP).toString() + "%");
|
|
|
result.put("profitGrowth", formatGrowth(grossProfit, compareGrossProfit));
|
|
|
- result.put("marginGrowth", "+0%"); // 毛利率变化
|
|
|
+ result.put("marginGrowth", "+0%");
|
|
|
|
|
|
// 用户统计
|
|
|
// 新增用户数
|
|
|
@@ -228,11 +227,11 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
}
|
|
|
result.put("transactUsers", transactUserIds.size());
|
|
|
|
|
|
- // 客单价(已付款用户的人均消费)
|
|
|
- double customerPrice = transactUserIds.size() > 0 ? totalSales / transactUserIds.size() : 0;
|
|
|
- result.put("customerPrice", String.format("%.2f", customerPrice));
|
|
|
+ BigDecimal customerPrice = transactUserIds.size() > 0
|
|
|
+ ? totalSales.divide(BigDecimal.valueOf(transactUserIds.size()), 2, RoundingMode.HALF_UP)
|
|
|
+ : BigDecimal.ZERO;
|
|
|
+ result.put("customerPrice", customerPrice.toString());
|
|
|
|
|
|
- // 对比期用户统计
|
|
|
long compareNewUsers = userService.lambdaQuery()
|
|
|
.ge(User::getCreateTime, compareStartTime)
|
|
|
.le(User::getCreateTime, compareEndTime)
|
|
|
@@ -244,16 +243,16 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
compareTransactUserIds.add(order.getUserId());
|
|
|
}
|
|
|
}
|
|
|
- double compareCustomerPrice = compareTransactUserIds.size() > 0
|
|
|
- ? compareSales / compareTransactUserIds.size() : 0;
|
|
|
+ BigDecimal compareCustomerPrice = compareTransactUserIds.size() > 0
|
|
|
+ ? compareSales.divide(BigDecimal.valueOf(compareTransactUserIds.size()), 2, RoundingMode.HALF_UP)
|
|
|
+ : BigDecimal.ZERO;
|
|
|
|
|
|
result.put("newUsersGrowth", formatGrowth(newUsers, compareNewUsers));
|
|
|
result.put("transactGrowth", formatGrowth(transactUserIds.size(), compareTransactUserIds.size()));
|
|
|
result.put("customerGrowth", formatGrowth(customerPrice, compareCustomerPrice));
|
|
|
|
|
|
- // 图表数据
|
|
|
List<String> dates = new ArrayList<>();
|
|
|
- List<Double> salesData = new ArrayList<>();
|
|
|
+ List<BigDecimal> salesData = new ArrayList<>();
|
|
|
List<Integer> ordersData = new ArrayList<>();
|
|
|
|
|
|
DateTimeFormatter formatter = type.equals("yesterday")
|
|
|
@@ -261,7 +260,6 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
: DateTimeFormatter.ofPattern("MM-dd");
|
|
|
|
|
|
if ("yesterday".equals(type)) {
|
|
|
- // 按小时统计
|
|
|
for (int i = 0; i < 24; i++) {
|
|
|
LocalDateTime hourStart = startTime.withHour(i);
|
|
|
LocalDateTime hourEnd = hourStart.withMinute(59).withSecond(59);
|
|
|
@@ -269,10 +267,10 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
dates.add(String.format("%d:00", i));
|
|
|
|
|
|
final int hour = i;
|
|
|
- double hourSales = orders.stream()
|
|
|
+ BigDecimal hourSales = orders.stream()
|
|
|
.filter(o -> o.getPayTime() != null && o.getPayTime().getHour() == hour)
|
|
|
- .mapToDouble(o -> o.getTotalAmount() != null ? o.getTotalAmount() : 0)
|
|
|
- .sum();
|
|
|
+ .map(o -> o.getTotalAmount() != null ? o.getTotalAmount() : BigDecimal.ZERO)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
long hourOrders = orders.stream()
|
|
|
.filter(o -> o.getPayTime() != null && o.getPayTime().getHour() == hour)
|
|
|
.count();
|
|
|
@@ -281,7 +279,6 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
ordersData.add((int) hourOrders);
|
|
|
}
|
|
|
} else {
|
|
|
- // 按天统计
|
|
|
for (int i = 0; i < days; i++) {
|
|
|
LocalDate date = startTime.toLocalDate().plusDays(i);
|
|
|
LocalDateTime dayStart = date.atStartOfDay();
|
|
|
@@ -289,12 +286,12 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
|
|
|
dates.add(date.format(DateTimeFormatter.ofPattern("MM-dd")));
|
|
|
|
|
|
- double daySales = orders.stream()
|
|
|
+ BigDecimal daySales = orders.stream()
|
|
|
.filter(o -> o.getPayTime() != null
|
|
|
&& !o.getPayTime().isBefore(dayStart)
|
|
|
&& !o.getPayTime().isAfter(dayEnd))
|
|
|
- .mapToDouble(o -> o.getTotalAmount() != null ? o.getTotalAmount() : 0)
|
|
|
- .sum();
|
|
|
+ .map(o -> o.getTotalAmount() != null ? o.getTotalAmount() : BigDecimal.ZERO)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
long dayOrders = orders.stream()
|
|
|
.filter(o -> o.getPayTime() != null
|
|
|
&& !o.getPayTime().isBefore(dayStart)
|
|
|
@@ -382,11 +379,11 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
/**
|
|
|
* 格式化对比数值(正负号)
|
|
|
*/
|
|
|
- private String formatCompare(double value) {
|
|
|
- if (value > 0) {
|
|
|
- return "+" + String.format("%.2f", value);
|
|
|
- } else if (value < 0) {
|
|
|
- return String.format("%.2f", value);
|
|
|
+ private String formatCompare(BigDecimal value) {
|
|
|
+ if (value.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ return "+" + value.setScale(2, RoundingMode.HALF_UP).toString();
|
|
|
+ } else if (value.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ return value.setScale(2, RoundingMode.HALF_UP).toString();
|
|
|
}
|
|
|
return "+0.00";
|
|
|
}
|
|
|
@@ -406,15 +403,17 @@ public class DashboardServiceImpl implements DashboardService {
|
|
|
/**
|
|
|
* 格式化增长率
|
|
|
*/
|
|
|
- private String formatGrowth(double current, double previous) {
|
|
|
- if (previous == 0) {
|
|
|
- return current > 0 ? "+100%" : "+0%";
|
|
|
+ private String formatGrowth(BigDecimal current, BigDecimal previous) {
|
|
|
+ if (previous.compareTo(BigDecimal.ZERO) == 0) {
|
|
|
+ return current.compareTo(BigDecimal.ZERO) > 0 ? "+100%" : "+0%";
|
|
|
}
|
|
|
- double growth = ((current - previous) / previous) * 100;
|
|
|
- if (growth > 0) {
|
|
|
- return "+" + String.format("%.0f", growth) + "%";
|
|
|
- } else if (growth < 0) {
|
|
|
- return String.format("%.0f", growth) + "%";
|
|
|
+ BigDecimal growth = current.subtract(previous)
|
|
|
+ .divide(previous, 4, RoundingMode.HALF_UP)
|
|
|
+ .multiply(new BigDecimal("100"));
|
|
|
+ if (growth.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ return "+" + growth.setScale(1, RoundingMode.HALF_UP) + "%";
|
|
|
+ } else if (growth.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ return growth.setScale(1, RoundingMode.HALF_UP) + "%";
|
|
|
}
|
|
|
return "+0%";
|
|
|
}
|