提交 dfc345a1 authored 作者: hzh's avatar hzh

商城模块集成

上级 7122073b
package org.dromara.mall.controller.statistics.admin.common.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Schema(description = "管理后台 - 数据对照 Response VO")
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class DataComparisonRespVO<T> {
@Schema(description = "当前数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private T value;
@Schema(description = "参照数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private T reference;
}
package org.dromara.mall.controller.statistics.admin.member;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.mall.controller.statistics.admin.common.vo.DataComparisonRespVO;
import org.dromara.mall.controller.statistics.admin.member.vo.*;
import org.dromara.mall.convert.statistics.member.MemberStatisticsConvert;
import org.dromara.mall.service.statistics.member.MemberStatisticsService;
import org.dromara.mall.service.statistics.trade.TradeOrderStatisticsService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.List;
@Tag(name = "管理后台 - 会员统计")
@RestController
@RequestMapping("/admin/statistics/member")
@Validated
@Slf4j
public class MemberStatisticsController {
@Resource
private MemberStatisticsService memberStatisticsService;
@Resource
private TradeOrderStatisticsService tradeOrderStatisticsService;
// @Resource
// private ApiAccessLogStatisticsService apiAccessLogStatisticsService;
@GetMapping("/summary")
@Operation(summary = "获得会员统计(实时统计)")
@SaCheckPermission("statistics:member:query")
public R<MemberSummaryRespVO> getMemberSummary() {
return R.ok(memberStatisticsService.getMemberSummary());
}
@GetMapping("/analyse")
@Operation(summary = "获得会员分析数据")
@SaCheckPermission("statistics:member:query")
public R<MemberAnalyseRespVO> getMemberAnalyse(MemberAnalyseReqVO reqVO) {
// 1. 查询数据
LocalDateTime beginTime = ArrayUtil.get(reqVO.getTimes(), 0);
LocalDateTime endTime = ArrayUtil.get(reqVO.getTimes(), 1);
// 1.1 查询分析对照数据
DataComparisonRespVO<MemberAnalyseDataRespVO> comparisonData = memberStatisticsService.getMemberAnalyseComparisonData(beginTime, endTime);
// TODO @疯狂:这个可能有点特殊,要按照 create_time 来查询;不然它的漏斗就不统一;因为是访问数量 > 今日下单人 > 今日支付人;是一个统一的维度;
// 1.2 查询成交用户数量
Integer payUserCount = tradeOrderStatisticsService.getPayUserCount(beginTime, endTime);
// 1.3 计算客单价
int atv = 0;
if (payUserCount != null && payUserCount > 0) {
// TODO @疯狂:类似上面的 payUserCount
Integer payPrice = tradeOrderStatisticsService.getOrderPayPrice(beginTime, endTime);
atv = NumberUtil.div(payPrice, payUserCount).intValue();
}
// 1.4 查询访客数量
//TODO WHO
// Integer visitUserCount = apiAccessLogStatisticsService.getIpCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime);
// 1.5 下单用户数量
Integer orderUserCount = tradeOrderStatisticsService.getOrderUserCount(beginTime, endTime);
// 2. 拼接返回
return R.ok(MemberStatisticsConvert.INSTANCE.convert(0, orderUserCount, payUserCount, atv, comparisonData));
// return R.ok(MemberStatisticsConvert.INSTANCE.convert(visitUserCount, orderUserCount, payUserCount, atv, comparisonData));
}
@GetMapping("/area-statistics-list")
@Operation(summary = "按照省份,获得会员统计列表")
@SaCheckPermission("statistics:member:query")
public R<List<MemberAreaStatisticsRespVO>> getMemberAreaStatisticsList() {
return R.ok(memberStatisticsService.getMemberAreaStatisticsList());
}
@GetMapping("/sex-statistics-list")
@Operation(summary = "按照性别,获得会员统计列表")
@SaCheckPermission("statistics:member:query")
public R<List<MemberSexStatisticsRespVO>> getMemberSexStatisticsList() {
return R.ok(memberStatisticsService.getMemberSexStatisticsList());
}
@GetMapping("/terminal-statistics-list")
@Operation(summary = "按照终端,获得会员统计列表")
@SaCheckPermission("statistics:member:query")
public R<List<MemberTerminalStatisticsRespVO>> getMemberTerminalStatisticsList() {
return R.ok(memberStatisticsService.getMemberTerminalStatisticsList());
}
// TODO @疯狂:要注意 date 的排序;
@GetMapping("/user-count-comparison")
@Operation(summary = "获得用户数量对照")
@SaCheckPermission("statistics:member:query")
public R<DataComparisonRespVO<MemberCountRespVO>> getUserCountComparison() {
return R.ok(memberStatisticsService.getUserCountComparison());
}
@GetMapping("/register-count-list")
@Operation(summary = "获得会员注册数量列表")
@SaCheckPermission("statistics:member:query")
public R<List<MemberRegisterCountRespVO>> getMemberRegisterCountList(MemberAnalyseReqVO reqVO) {
return R.ok(memberStatisticsService.getMemberRegisterCountList(
ArrayUtil.get(reqVO.getTimes(), 0), ArrayUtil.get(reqVO.getTimes(), 1)));
}
}
package org.dromara.mall.controller.statistics.admin.member.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "管理后台 - 会员分析数据 Response VO")
@Data
@Accessors(chain = true)
public class MemberAnalyseDataRespVO {
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer registerUserCount;
@Schema(description = "活跃用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer visitUserCount;
@Schema(description = "充值会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "221")
private Integer rechargeUserCount;
}
package org.dromara.mall.controller.statistics.admin.member.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 会员分析 Request VO")
@Data
public class MemberAnalyseReqVO {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Schema(description = "时间范围")
private LocalDateTime[] times;
}
package org.dromara.mall.controller.statistics.admin.member.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.mall.controller.statistics.admin.common.vo.DataComparisonRespVO;
@Schema(description = "管理后台 - 会员分析 Response VO")
@Data
public class MemberAnalyseRespVO {
@Schema(description = "访客数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer visitUserCount;
@Schema(description = "下单用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer orderUserCount;
@Schema(description = "成交用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer payUserCount;
@Schema(description = "客单价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer atv;
@Schema(description = "对照数据", requiredMode = Schema.RequiredMode.REQUIRED)
private DataComparisonRespVO<MemberAnalyseDataRespVO> comparison;
}
package org.dromara.mall.controller.statistics.admin.member.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "管理后台 - 会员地区统计 Response VO")
@Data
@Accessors(chain = true)
public class MemberAreaStatisticsRespVO {
@Schema(description = "省份编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer areaId;
@Schema(description = "省份名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "浙江省")
private String areaName;
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer userCount;
@Schema(description = "下单的会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer orderCreateUserCount;
@Schema(description = "支付订单的会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "512")
private Integer orderPayUserCount;
@Schema(description = "订单支付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "622")
private Integer orderPayPrice;
}
package org.dromara.mall.controller.statistics.admin.member.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "管理后台 - 会员数量统计 Response VO")
@Data
@Accessors(chain = true)
public class MemberCountRespVO {
@Schema(description = "用户访问量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer visitUserCount;
@Schema(description = "注册用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer registerUserCount;
}
package org.dromara.mall.controller.statistics.admin.member.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDate;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
import static org.dromara.common.mall.util.date.DateUtils.TIME_ZONE_DEFAULT;
@Schema(description = "管理后台 - 会员注册数量 Response VO")
@Data
public class MemberRegisterCountRespVO {
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY, timezone = TIME_ZONE_DEFAULT)
@Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private LocalDate date;
@Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer count;
}
package org.dromara.mall.controller.statistics.admin.member.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 会员性别统计 Response VO")
@Data
public class MemberSexStatisticsRespVO {
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer sex;
// TODO @疯狂:要不还是其它字段,我们也补全,这样方便使用的用户,做定制化;就保持和 MemberAreaStatisticsRespVO 一致;
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer userCount;
}
package org.dromara.mall.controller.statistics.admin.member.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 会员统计 Response VO")
@Data
public class MemberSummaryRespVO {
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer userCount;
@Schema(description = "充值会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "221")
private Integer rechargeUserCount;
@Schema(description = "充值金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer rechargePrice;
// TODO @疯狂:要不干脆这个字段改成:orderPayPrice??
@Schema(description = "支出金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer expensePrice; // 只计算 mall 交易订单的支付金额,不考虑退款
}
package org.dromara.mall.controller.statistics.admin.member.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 会员终端统计 Response VO")
@Data
public class MemberTerminalStatisticsRespVO {
@Schema(description = "终端", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer terminal;
// TODO @疯狂:要不 orderCreateUserCount 和 orderPayUserCount 貌似更统一一些;
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer userCount;
}
package org.dromara.mall.controller.statistics.admin.pay;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.mall.controller.statistics.admin.pay.vo.PaySummaryRespVO;
import org.dromara.mall.convert.statistics.pay.PayStatisticsConvert;
import org.dromara.mall.service.statistics.pay.PayWalletStatisticsService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "管理后台 - 支付统计")
@RestController
@RequestMapping("/admin/statistics/pay")
@Validated
@Slf4j
public class PayStatisticsController {
@Resource
private PayWalletStatisticsService payWalletStatisticsService;
@GetMapping("/summary")
@Operation(summary = "获取充值金额")
public R<PaySummaryRespVO> getWalletRechargePrice() {
Integer rechargePrice = payWalletStatisticsService.getRechargePriceSummary();
return R.ok(PayStatisticsConvert.INSTANCE.convert(rechargePrice));
}
}
package org.dromara.mall.controller.statistics.admin.pay.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 支付统计 Response VO")
@Data
public class PaySummaryRespVO {
@Schema(description = "充值金额,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer rechargePrice;
}
package org.dromara.mall.controller.statistics.admin.product;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.common.mybatis.core.page.SortablePageParam;
import org.dromara.common.mybatis.util.BeanUtils;
import org.dromara.mall.api.dto.product.ProductSpuRespDTO;
import org.dromara.mall.api.service.product.ProductSpuApi;
import org.dromara.mall.controller.statistics.admin.common.vo.DataComparisonRespVO;
import org.dromara.mall.controller.statistics.admin.product.vo.ProductStatisticsReqVO;
import org.dromara.mall.controller.statistics.admin.product.vo.ProductStatisticsRespVO;
import org.dromara.mall.domain.statistics.ProductStatisticsDO;
import org.dromara.mall.service.statistics.product.ProductStatisticsService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertMap;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 商品统计")
@RestController
@RequestMapping("/admin/statistics/product")
@Validated
public class ProductStatisticsController {
@Resource
private ProductStatisticsService productStatisticsService;
@Resource
private ProductSpuApi productSpuApi;
@GetMapping("/analyse")
@Operation(summary = "获得商品统计分析")
@SaCheckPermission("statistics:product:query")
public R<DataComparisonRespVO<ProductStatisticsRespVO>> getProductStatisticsAnalyse(ProductStatisticsReqVO reqVO) {
return R.ok(productStatisticsService.getProductStatisticsAnalyse(reqVO));
}
@GetMapping("/list")
@Operation(summary = "获得商品统计明细(日期维度)")
@SaCheckPermission("statistics:product:query")
public R<List<ProductStatisticsRespVO>> getProductStatisticsList(ProductStatisticsReqVO reqVO) {
List<ProductStatisticsDO> list = productStatisticsService.getProductStatisticsList(reqVO);
return R.ok(BeanUtils.toBean(list, ProductStatisticsRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出获得商品统计明细 Excel(日期维度)")
@SaCheckPermission("statistics:product:export")
public void exportProductStatisticsExcel(ProductStatisticsReqVO reqVO, HttpServletResponse response) throws IOException {
List<ProductStatisticsDO> list = productStatisticsService.getProductStatisticsList(reqVO);
// 导出 Excel
List<ProductStatisticsRespVO> voList = BeanUtils.toBean(list, ProductStatisticsRespVO.class);
ExcelUtil.exportExcel(voList, "商品状况", ProductStatisticsRespVO.class, response);
}
@GetMapping("/rank-page")
@Operation(summary = "获得商品统计排行榜分页(商品维度)")
@SaCheckPermission("statistics:product:query")
public R<PageResult<ProductStatisticsRespVO>> getProductStatisticsRankPage(@Valid ProductStatisticsReqVO reqVO,
@Valid SortablePageParam pageParam) {
PageResult<ProductStatisticsDO> pageResult = productStatisticsService.getProductStatisticsRankPage(reqVO, pageParam);
// 处理商品信息
Set<Long> spuIds = convertSet(pageResult.getList(), ProductStatisticsDO::getSpuId);
Map<Long, ProductSpuRespDTO> spuMap = convertMap(productSpuApi.getSpuList(spuIds), ProductSpuRespDTO::getId);
return R.ok(BeanUtils.toBean(pageResult, ProductStatisticsRespVO.class,
item -> Optional.ofNullable(spuMap.get(item.getSpuId()))
.ifPresent(spu -> item.setName(spu.getName()).setPicUrl(spu.getPicUrl()))));
}
}
package org.dromara.mall.controller.statistics.admin.product.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 商品统计分析 Request VO")
@Data
@ToString(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
public class ProductStatisticsReqVO {
@Schema(description = "统计时间范围", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] times;
}
package org.dromara.mall.controller.statistics.admin.product.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDate;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
@Schema(description = "管理后台 - 商品统计 Response VO")
@Data
@Accessors(chain = true)
@ExcelIgnoreUnannotated
public class ProductStatisticsRespVO {
@Schema(description = "编号,主键自增", requiredMode = Schema.RequiredMode.REQUIRED, example = "12393")
private Long id;
@Schema(description = "统计日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-12-16")
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
@ExcelProperty("统计日期")
private LocalDate time;
@Schema(description = "商品SPU编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15114")
@ExcelProperty("商品SPU编号")
private Long spuId;
// region 商品信息
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "商品名称")
@ExcelProperty("商品名称")
private String name;
@Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "15114")
@ExcelProperty("商品封面图")
private String picUrl;
// endregion
@Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "17505")
@ExcelProperty("浏览量")
private Integer browseCount;
@Schema(description = "访客量", requiredMode = Schema.RequiredMode.REQUIRED, example = "11814")
@ExcelProperty("访客量")
private Integer browseUserCount;
@Schema(description = "收藏数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20950")
@ExcelProperty("收藏数量")
private Integer favoriteCount;
@Schema(description = "加购数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "28493")
@ExcelProperty("加购数量")
private Integer cartCount;
@Schema(description = "下单件数", requiredMode = Schema.RequiredMode.REQUIRED, example = "18966")
@ExcelProperty("下单件数")
private Integer orderCount;
@Schema(description = "支付件数", requiredMode = Schema.RequiredMode.REQUIRED, example = "15142")
@ExcelProperty("支付件数")
private Integer orderPayCount;
@Schema(description = "支付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "11595")
@ExcelProperty("支付金额,单位:分")
private Integer orderPayPrice;
@Schema(description = "退款件数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2591")
@ExcelProperty("退款件数")
private Integer afterSaleCount;
@Schema(description = "退款金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "21709")
@ExcelProperty("退款金额,单位:分")
private Integer afterSaleRefundPrice;
@Schema(description = "访客支付转化率(百分比)", requiredMode = Schema.RequiredMode.REQUIRED, example = "15")
private Integer browseConvertPercent;
}
package org.dromara.mall.controller.statistics.admin.trade;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.ArrayUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.mall.controller.statistics.admin.common.vo.DataComparisonRespVO;
import org.dromara.mall.controller.statistics.admin.trade.vo.*;
import org.dromara.mall.convert.statistics.trade.TradeStatisticsConvert;
import org.dromara.mall.domain.statistics.TradeStatisticsDO;
import org.dromara.mall.enums.trade.aftersale.AfterSaleStatusEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageWithdrawStatusEnum;
import org.dromara.mall.enums.trade.delivery.DeliveryTypeEnum;
import org.dromara.mall.enums.trade.order.TradeOrderStatusEnum;
import org.dromara.mall.service.statistics.trade.AfterSaleStatisticsService;
import org.dromara.mall.service.statistics.trade.BrokerageStatisticsService;
import org.dromara.mall.service.statistics.trade.TradeOrderStatisticsService;
import org.dromara.mall.service.statistics.trade.TradeStatisticsService;
import org.dromara.mall.service.statistics.trade.bo.TradeSummaryRespBO;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
@Tag(name = "管理后台 - 交易统计")
@RestController
@RequestMapping("/admin/statistics/trade")
@Validated
@Slf4j
public class TradeStatisticsController {
@Resource
private TradeStatisticsService tradeStatisticsService;
@Resource
private TradeOrderStatisticsService tradeOrderStatisticsService;
@Resource
private AfterSaleStatisticsService afterSaleStatisticsService;
@Resource
private BrokerageStatisticsService brokerageStatisticsService;
@GetMapping("/summary")
@Operation(summary = "获得交易统计")
@SaCheckPermission("statistics:trade:query")
public R<DataComparisonRespVO<TradeSummaryRespVO>> getTradeSummaryComparison() {
// 1.1 昨天的数据
TradeSummaryRespBO yesterdayData = tradeStatisticsService.getTradeSummaryByDays(-1);
// 1.2 前天的数据(用于对照昨天的数据)
TradeSummaryRespBO beforeYesterdayData = tradeStatisticsService.getTradeSummaryByDays(-2);
// 2.1 本月数据
TradeSummaryRespBO monthData = tradeStatisticsService.getTradeSummaryByMonths(0);
// 2.2 上月数据(用于对照本月的数据)
TradeSummaryRespBO lastMonthData = tradeStatisticsService.getTradeSummaryByMonths(-1);
// 拼接数据
return R.ok(TradeStatisticsConvert.INSTANCE.convert(yesterdayData, beforeYesterdayData, monthData, lastMonthData));
}
@GetMapping("/analyse")
@Operation(summary = "获得交易状况统计")
@SaCheckPermission("statistics:trade:query")
public R<DataComparisonRespVO<TradeTrendSummaryRespVO>> getTradeStatisticsAnalyse(TradeTrendReqVO reqVO) {
return R.ok(tradeStatisticsService.getTradeStatisticsAnalyse(ArrayUtil.get(reqVO.getTimes(), 0),
ArrayUtil.get(reqVO.getTimes(), 1)));
}
@GetMapping("/list")
@Operation(summary = "获得交易状况明细")
@SaCheckPermission("statistics:trade:query")
public R<List<TradeTrendSummaryRespVO>> getTradeStatisticsList(TradeTrendReqVO reqVO) {
List<TradeStatisticsDO> list = tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0),
ArrayUtil.get(reqVO.getTimes(), 1));
return R.ok(TradeStatisticsConvert.INSTANCE.convertList(list));
}
@GetMapping("/export-excel")
@Operation(summary = "导出获得交易状况明细 Excel")
@SaCheckPermission("statistics:trade:export")
public void exportTradeStatisticsExcel(TradeTrendReqVO reqVO, HttpServletResponse response) throws IOException {
List<TradeStatisticsDO> list = tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0),
ArrayUtil.get(reqVO.getTimes(), 1));
// 导出 Excel
List<TradeTrendSummaryRespVO> voList = TradeStatisticsConvert.INSTANCE.convertList(list);
List<TradeTrendSummaryExcelVO> data = TradeStatisticsConvert.INSTANCE.convertList02(voList);
ExcelUtil.exportExcel(data, "交易状况", TradeTrendSummaryExcelVO.class, response);
}
@GetMapping("/order-count")
@Operation(summary = "获得交易订单数量")
@SaCheckPermission("statistics:trade:query")
public R<TradeOrderCountRespVO> getOrderCount() {
// 订单统计
Long undeliveredCount = tradeOrderStatisticsService.getCountByStatusAndDeliveryType(
TradeOrderStatusEnum.UNDELIVERED.getStatus(), DeliveryTypeEnum.EXPRESS.getType());
// TODO @疯狂:订单支付后,如果是门店自提的,需要 update 成 DELIVERED;;目前还没搞~~突然反应过来
Long pickUpCount = tradeOrderStatisticsService.getCountByStatusAndDeliveryType(
TradeOrderStatusEnum.DELIVERED.getStatus(), DeliveryTypeEnum.PICK_UP.getType());
// 售后统计
Long afterSaleApplyCount = afterSaleStatisticsService.getCountByStatus(AfterSaleStatusEnum.APPLY);
Long auditingWithdrawCount = brokerageStatisticsService.getWithdrawCountByStatus(BrokerageWithdrawStatusEnum.AUDITING);
// 拼接返回
return R.ok(TradeStatisticsConvert.INSTANCE.convert(undeliveredCount, pickUpCount, afterSaleApplyCount, auditingWithdrawCount));
}
@GetMapping("/order-comparison")
@Operation(summary = "获得交易订单数量")
@SaCheckPermission("statistics:trade:query")
public R<DataComparisonRespVO<TradeOrderSummaryRespVO>> getOrderComparison() {
return R.ok(tradeOrderStatisticsService.getOrderComparison());
}
@GetMapping("/order-count-trend")
@Operation(summary = "获得订单量趋势统计")
@SaCheckPermission("statistics:trade:query")
public R<List<DataComparisonRespVO<TradeOrderTrendRespVO>>> getOrderCountTrendComparison(@Valid TradeOrderTrendReqVO reqVO) {
// TODO @疯狂:要注意 date 的排序;
return R.ok(tradeOrderStatisticsService.getOrderCountTrendComparison(reqVO));
}
}
package org.dromara.mall.controller.statistics.admin.trade.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 交易订单数量 Response VO")
@Data
public class TradeOrderCountRespVO {
@Schema(description = "待发货", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long undelivered;
@Schema(description = "待核销", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long pickUp;
@Schema(description = "退款中", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long afterSaleApply;
@Schema(description = "提现待审核", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long auditingWithdraw;
}
package org.dromara.mall.controller.statistics.admin.trade.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 交易订单统计 Response VO")
@Data
public class TradeOrderSummaryRespVO {
@Schema(description = "支付订单商品数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer orderPayCount;
@Schema(description = "总支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer orderPayPrice;
}
package org.dromara.mall.controller.statistics.admin.trade.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.mall.enums.statistics.TimeRangeTypeEnum;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 交易订单量趋势统计 Request VO")
@Data
public class TradeOrderTrendReqVO {
@Schema(description = "日期范围类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "日期范围类型不能为空")
@InEnum(value = TimeRangeTypeEnum.class, message = "日期范围类型,必须是 {value}")
private Integer type;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Schema(description = "起始时间")
private LocalDateTime beginTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Schema(description = "截止时间")
private LocalDateTime endTime;
}
package org.dromara.mall.controller.statistics.admin.trade.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 订单量趋势统计 Response VO")
@Data
public class TradeOrderTrendRespVO {
@Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private String date;
@Schema(description = "订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer orderPayCount;
@Schema(description = "订单支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer orderPayPrice;
}
package org.dromara.mall.controller.statistics.admin.trade.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "管理后台 - 交易统计 Response VO")
@Data
@Accessors(chain = true)
public class TradeSummaryRespVO {
@Schema(description = "昨日订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer yesterdayOrderCount;
@Schema(description = "昨日支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer yesterdayPayPrice;
@Schema(description = "本月订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer monthOrderCount;
@Schema(description = "本月支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer monthPayPrice;
}
package org.dromara.mall.controller.statistics.admin.trade.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 交易状况 Request VO")
@Data
public class TradeTrendReqVO {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Schema(description = "时间范围")
private LocalDateTime[] times;
}
package org.dromara.mall.controller.statistics.admin.trade.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.Data;
import org.dromara.common.excel.convert.MoneyConvert;
import java.time.LocalDate;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
/**
* 交易状况统计 Excel VO
*
* @author owen
*/
@Data
public class TradeTrendSummaryExcelVO {
@ExcelProperty(value = "日期")
@DateTimeFormat(FORMAT_YEAR_MONTH_DAY)
private LocalDate date;
@ExcelProperty(value = "营业额", converter = MoneyConvert.class)
private Integer turnoverPrice;
@ExcelProperty(value = "商品支付金额", converter = MoneyConvert.class)
private Integer orderPayPrice;
@ExcelProperty(value = "充值金额", converter = MoneyConvert.class)
private Integer rechargePrice;
@ExcelProperty(value = "支出金额", converter = MoneyConvert.class)
private Integer expensePrice;
@ExcelProperty(value = "余额支付金额", converter = MoneyConvert.class)
private Integer walletPayPrice;
@ExcelProperty(value = "支付佣金金额", converter = MoneyConvert.class)
private Integer brokerageSettlementPrice;
@ExcelProperty(value = "商品退款金额", converter = MoneyConvert.class)
private Integer afterSaleRefundPrice;
}
package org.dromara.mall.controller.statistics.admin.trade.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDate;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
@Schema(description = "管理后台 - 交易状况统计 Response VO")
@Data
@Accessors(chain = true)
public class TradeTrendSummaryRespVO {
@Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-12-16")
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate date;
@Schema(description = "营业额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer turnoverPrice; // 营业额 = 商品支付金额 + 充值金额
@Schema(description = "订单支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer orderPayPrice;
@Schema(description = "余额支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer walletPayPrice;
@Schema(description = "订单退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer afterSaleRefundPrice;
@Schema(description = "支付佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer brokerageSettlementPrice;
@Schema(description = "充值金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer rechargePrice;
@Schema(description = "支出金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer expensePrice; // 余额支付金额 + 支付佣金金额 + 商品退款金额
}
/**
* TODO 芋艿:占位
*/
package org.dromara.mall.controller.statistics.app;
package org.dromara.mall.controller.system.admin.ip;
import cn.hutool.core.lang.Assert;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.dromara.common.core.domain.R;
import org.dromara.common.mall.domain.Area;
import org.dromara.common.mall.util.ip.AreaUtils;
import org.dromara.common.mall.util.ip.IPUtils;
import org.dromara.common.mybatis.util.BeanUtils;
import org.dromara.mall.controller.system.admin.ip.vo.AreaNodeRespVO;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "管理后台 - 地区")
@RestController
@RequestMapping("/admin/system/area")
@Validated
public class AreaController {
@GetMapping("/tree")
@Operation(summary = "获得地区树")
public R<List<AreaNodeRespVO>> getAreaTree() {
Area area = AreaUtils.getArea(Area.ID_CHINA);
Assert.notNull(area, "获取不到中国");
return R.ok(BeanUtils.toBean(area.getChildren(), AreaNodeRespVO.class));
}
@GetMapping("/get-by-ip")
@Operation(summary = "获得 IP 对应的地区名")
@Parameter(name = "ip", description = "IP", required = true)
public R<String> getAreaByIp(@RequestParam("ip") String ip) {
// 获得城市
Area area = IPUtils.getArea(ip);
if (area == null) {
return R.ok("未知");
}
// 格式化返回
return R.ok(AreaUtils.format(area.getId()));
}
}
package org.dromara.mall.controller.system.admin.ip.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - 地区节点 Response VO")
@Data
public class AreaNodeRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110000")
private Integer id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "北京")
private String name;
/**
* 子节点
*/
private List<AreaNodeRespVO> children;
}
package org.dromara.mall.controller.system.app.ip;
import cn.hutool.core.lang.Assert;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.security.PermitAll;
import org.dromara.common.core.domain.R;
import org.dromara.common.mall.domain.Area;
import org.dromara.common.mall.util.ip.AreaUtils;
import org.dromara.common.mybatis.util.BeanUtils;
import org.dromara.mall.controller.system.app.ip.vo.AppAreaNodeRespVO;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "用户 App - 地区")
@RestController
@RequestMapping("/app/system/area")
@Validated
public class AppAreaController {
@GetMapping("/tree")
@Operation(summary = "获得地区树")
@PermitAll
public R<List<AppAreaNodeRespVO>> getAreaTree() {
Area area = AreaUtils.getArea(Area.ID_CHINA);
Assert.notNull(area, "获取不到中国");
return R.ok(BeanUtils.toBean(area.getChildren(), AppAreaNodeRespVO.class));
}
}
package org.dromara.mall.controller.system.app.ip.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "用户 App - 地区节点 Response VO")
@Data
public class AppAreaNodeRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110000")
private Integer id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "北京")
private String name;
/**
* 子节点
*/
private List<AppAreaNodeRespVO> children;
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论