diff --git a/framework/src/main/java/cn/lili/modules/order/cart/entity/enums/DeliveryMethodEnum.java b/framework/src/main/java/cn/lili/modules/order/cart/entity/enums/DeliveryMethodEnum.java index c329cba98..87402989e 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/entity/enums/DeliveryMethodEnum.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/entity/enums/DeliveryMethodEnum.java @@ -19,7 +19,11 @@ public enum DeliveryMethodEnum { /** * "物流" */ - LOGISTICS("物流"); + LOGISTICS("物流"), + /** + * 虚拟发货 + */ + VIRTUAL("虚拟发货"); private final String description; diff --git a/framework/src/main/java/cn/lili/modules/statistics/entity/vo/BusinessCompositionDataVO.java b/framework/src/main/java/cn/lili/modules/statistics/entity/vo/BusinessCompositionDataVO.java new file mode 100644 index 000000000..fa356b188 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/statistics/entity/vo/BusinessCompositionDataVO.java @@ -0,0 +1,55 @@ +package cn.lili.modules.statistics.entity.vo; + + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 营业构成VO + * @author Bulbasaur + * @since 2025/08/25 7:07 下午 + */ +@Data +public class BusinessCompositionDataVO { + + //订单分类构成 + @ApiModelProperty(value = "到店自提") + private Double storeSelf; + @ApiModelProperty(value = "快递发货") + private Double express; + @ApiModelProperty(value = "线上无需配送") + private Double online; + + //营业收入 + @ApiModelProperty(value = "商品销售") + private Double income; + @ApiModelProperty(value = "运费") + private Double freight; + @ApiModelProperty(value = "商品返现(分销返佣)") + private Double incomeBack; + @ApiModelProperty(value = "商品销售+费用构成") + private Double incomeComposition; + + //退款统计 + @ApiModelProperty(value = "退款订单笔数") + private Long refundOrderNum; + @ApiModelProperty(value = "退款金额") + private Double refund; + @ApiModelProperty(value = "退款率") + private Double refundRate; + + //消费指标 + @ApiModelProperty(value = "支付金额") + private Double pay; + @ApiModelProperty(value = "折后笔单价") + private Double price; + @ApiModelProperty(value = "支付人数") + private Long payNum; + @ApiModelProperty(value = "折后客单价") + private Double priceNum; + + + + + +} diff --git a/framework/src/main/java/cn/lili/modules/statistics/entity/vo/OverViewDataVO.java b/framework/src/main/java/cn/lili/modules/statistics/entity/vo/OverViewDataVO.java new file mode 100644 index 000000000..134fe2eed --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/statistics/entity/vo/OverViewDataVO.java @@ -0,0 +1,31 @@ +package cn.lili.modules.statistics.entity.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 概览数据 + * @author Bulbasaur + * @since 2025/08/25 7:07 下午 + */ +@Data +public class OverViewDataVO { + + + @ApiModelProperty(value = "营业额") + private Double turnover; + @ApiModelProperty(value = "优惠金额") + private Double discount; + @ApiModelProperty(value = "营业收入不含数值储值金额") + private Double incomeNoStoreValue; + @ApiModelProperty(value = "支付订单数") + private Long payOrderNum; + @ApiModelProperty(value = "新增充值金额") + private Double recharge; + @ApiModelProperty(value = "使用充值金额") + private Long rechargeUse; + + + + +} diff --git a/framework/src/main/java/cn/lili/modules/statistics/entity/vo/SourceDataVO.java b/framework/src/main/java/cn/lili/modules/statistics/entity/vo/SourceDataVO.java new file mode 100644 index 000000000..48a532993 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/statistics/entity/vo/SourceDataVO.java @@ -0,0 +1,26 @@ +package cn.lili.modules.statistics.entity.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 收款构成 + * + * @author Bulbasaur + * @since 2025/08/25 7:07 下午 + */ +@Data +public class SourceDataVO { + + @ApiModelProperty(value = "支付方式") + private String payType; + @ApiModelProperty(value = "收款合计") + private Double total; + @ApiModelProperty(value = "营业收入") + private Double income; + @ApiModelProperty(value = "新增储值金额") + private Double recharge; + + + +} diff --git a/framework/src/main/java/cn/lili/modules/statistics/mapper/OrderStatisticsMapper.java b/framework/src/main/java/cn/lili/modules/statistics/mapper/OrderStatisticsMapper.java index f1fff3c14..f9c7e395d 100644 --- a/framework/src/main/java/cn/lili/modules/statistics/mapper/OrderStatisticsMapper.java +++ b/framework/src/main/java/cn/lili/modules/statistics/mapper/OrderStatisticsMapper.java @@ -1,6 +1,7 @@ package cn.lili.modules.statistics.mapper; import cn.lili.modules.order.order.entity.dos.Order; +import cn.lili.modules.order.order.entity.dos.OrderItem; import cn.lili.modules.order.order.entity.vo.OrderSimpleVO; import cn.lili.modules.statistics.entity.vo.OrderStatisticsDataVO; import com.baomidou.mybatisplus.core.conditions.Wrapper; @@ -60,4 +61,24 @@ public interface OrderStatisticsMapper extends BaseMapper { " FROM li_order o INNER JOIN li_order_item AS oi on o.sn = oi.order_sn ${ew.customSqlSegment} ") IPage queryByParams(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 查询已付款未全部退款的订单数量 + */ + @Select("SELECT COALESCE(COUNT(DISTINCT order_sn), 0) FROM li_order_item ${ew.customSqlSegment} ") + Long getPayOrderNum(@Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 查询已付款未全部退款的订单金额 + */ + @Select("SELECT COALESCE(SUM( oi.flow_price )- SUM( oi.refund_price ), 0) FROM li_order_item oi INNER JOIN li_order o ON o.sn=oi.order_sn ${ew.customSqlSegment} ") + Double getPayOrderPrice(@Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 查询商品价格 + */ + @Select("SELECT COALESCE(SUM(goods_price), 0) FROM li_order_item ${ew.customSqlSegment} ") + Double getGoodsPrice(@Param(Constants.WRAPPER) Wrapper queryWrapper); + + @Select("SELECT COALESCE(SUM( oi.refund_price ), 0) FROM li_order_item oi INNER JOIN li_order o ON o.sn=oi.order_sn ${ew.customSqlSegment} ") + Double getRefundPrice(@Param(Constants.WRAPPER) Wrapper queryWrapper); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/statistics/service/OrderStatisticsService.java b/framework/src/main/java/cn/lili/modules/statistics/service/OrderStatisticsService.java index 7fb074dd4..a0cdcb56d 100644 --- a/framework/src/main/java/cn/lili/modules/statistics/service/OrderStatisticsService.java +++ b/framework/src/main/java/cn/lili/modules/statistics/service/OrderStatisticsService.java @@ -1,14 +1,17 @@ package cn.lili.modules.statistics.service; import cn.lili.common.vo.PageVO; +import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.vo.OrderSimpleVO; +import cn.lili.modules.payment.entity.enums.PaymentMethodEnum; import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; import cn.lili.modules.statistics.entity.vo.OrderOverviewVO; import cn.lili.modules.statistics.entity.vo.OrderStatisticsDataVO; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; +import java.util.Date; import java.util.List; /** @@ -34,6 +37,22 @@ public interface OrderStatisticsService extends IService { * @return 订单总数量 */ long orderNum(String orderStatus); + /** + * 获取订单总数量 + * + * @param paymentMethod 支付方式 + * @param dates 时间 + * + * @return 订单总数量 + */ + long orderNum(String paymentMethod, Date[] dates); + + /** + * 获取所有优惠金额去除退款金额 + * @param dates + * @return + */ + Double getDiscountPrice(Date[] dates); /** * 图表统计 @@ -51,4 +70,64 @@ public interface OrderStatisticsService extends IService { * @return */ IPage getStatistics(StatisticsQueryParam statisticsQueryParam, PageVO pageVO); + + /** + * 获取付款订单数量 不含全部退款 + * + * @param dates 时间 + * @return 付款订单数量 + */ + long getPayOrderNum(Date[] dates); + + /** + * 获取付款订单金额去除退款金额 + * + * @param dates 时间 + * @param paymentMethodEnum 支付方式 + * @param deliveryMethodEnum 配送方式 + * @return 付款订单金额 + */ + Double getPayOrderPrice(Date[] dates, PaymentMethodEnum paymentMethodEnum, DeliveryMethodEnum deliveryMethodEnum); + + /** + * 获取商品价格 + * @param dates 时间 + * @return + */ + Double getGoodsPrice(Date[] dates); + + /** + * 获取运费 + * @param dates 时间 + * @return + */ + Double getFreight(Date[] dates); + + /** + * 获取分销返佣 + * @param dates + * @return + */ + Double getDistribution(Date[] dates); + + /** + * 获取退款订单数 + * @param dates + * @return + */ + Long getRefundNum(Date[] dates); + + /** + * 获取退款金额 + * @param dates + * @return + */ + Double getRefundPrice(Date[] dates); + + /** + * 获取退款率 + * @param dates + * @return + */ + Double getRefundRate(Date[] dates); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/statistics/service/OverViewStatisticsService.java b/framework/src/main/java/cn/lili/modules/statistics/service/OverViewStatisticsService.java new file mode 100644 index 000000000..e167bd986 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/statistics/service/OverViewStatisticsService.java @@ -0,0 +1,47 @@ +package cn.lili.modules.statistics.service; + +import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; +import cn.lili.modules.statistics.entity.vo.BusinessCompositionDataVO; +import cn.lili.modules.statistics.entity.vo.OrderOverviewVO; +import cn.lili.modules.statistics.entity.vo.OverViewDataVO; +import cn.lili.modules.statistics.entity.vo.SourceDataVO; + +import java.util.Date; +import java.util.List; + +/** + * 营业概览统计 + * + * @author Bulbasaur + * @since 2025/08/25 7:31 下午 + */ +public interface OverViewStatisticsService { + + + /** + * 获取营业概览统计 + * + * @param statisticsQueryParam 统计参数 + * @return 营业概览统计 + */ + OverViewDataVO getOverViewDataVO(StatisticsQueryParam statisticsQueryParam); + + + /** + * 获取收款构成列表 + * + * @param statisticsQueryParam 统计参数 + * @return 收款构成列表 + */ + List getSourceDataVOList(StatisticsQueryParam statisticsQueryParam); + + /** + * 获取营业构成列表 + * + * @param statisticsQueryParam 统计参数 + * @return 营业构成列表 + */ + BusinessCompositionDataVO businessCompositionDataVO(StatisticsQueryParam statisticsQueryParam); + + +} diff --git a/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/OrderStatisticsServiceImpl.java b/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/OrderStatisticsServiceImpl.java index b39266e94..6b0d44570 100644 --- a/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/OrderStatisticsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/OrderStatisticsServiceImpl.java @@ -6,10 +6,17 @@ import cn.lili.common.security.enums.UserEnums; import cn.lili.common.utils.CurrencyUtil; import cn.lili.common.utils.StringUtils; import cn.lili.common.vo.PageVO; +import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; import cn.lili.modules.order.order.entity.dos.Order; +import cn.lili.modules.order.order.entity.dos.OrderItem; +import cn.lili.modules.order.order.entity.dto.PriceDetailDTO; import cn.lili.modules.order.order.entity.enums.FlowTypeEnum; +import cn.lili.modules.order.order.entity.enums.OrderTypeEnum; import cn.lili.modules.order.order.entity.enums.PayStatusEnum; +import cn.lili.modules.order.order.entity.enums.RefundStatusEnum; import cn.lili.modules.order.order.entity.vo.OrderSimpleVO; +import cn.lili.modules.order.order.service.OrderItemService; +import cn.lili.modules.payment.entity.enums.PaymentMethodEnum; import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; import cn.lili.modules.statistics.entity.vo.OrderOverviewVO; import cn.lili.modules.statistics.entity.vo.OrderStatisticsDataVO; @@ -38,6 +45,8 @@ import java.util.*; @Service public class OrderStatisticsServiceImpl extends ServiceImpl implements OrderStatisticsService { + + /** * 平台PV统计 */ @@ -46,6 +55,8 @@ public class OrderStatisticsServiceImpl extends ServiceImpl queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(CharSequenceUtil.isNotEmpty(paymentMethod), Order::getPaymentMethod, paymentMethod); + queryWrapper.between(Order::getCreateTime, dates[0], dates[1]); + return this.count(queryWrapper); + } + + + @Override + public Double getDiscountPrice(Date[] dates) { + // 参数校验 + if (dates == null || dates.length < 2) { + return 0.0; + } + + // 构建查询条件:按时间范围过滤,排除全部退款的订单项 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .ne(OrderItem::getIsRefund, RefundStatusEnum.ALL_REFUND.name()) + .between(OrderItem::getCreateTime, dates[0], dates[1]); + + List orderItems = orderItemService.list(queryWrapper); + + if (orderItems.isEmpty()) { + return 0.0; + } + + Double totalDiscountPrice = 0.0; + + for (OrderItem orderItem : orderItems) { + PriceDetailDTO priceDetailDTO = orderItem.getPriceDetailDTO(); + if (priceDetailDTO == null) { + continue; + } + + Double itemDiscountPrice = calculateItemDiscountPrice(priceDetailDTO); + + if (RefundStatusEnum.NO_REFUND.name().equals(orderItem.getIsRefund())) { + // 未退款:计算全部优惠金额 + totalDiscountPrice = CurrencyUtil.add(totalDiscountPrice, itemDiscountPrice); + } else { + // 部分退款:按比例计算剩余优惠金额 + Double remainingDiscountPrice = calculateRemainingDiscountPrice( + itemDiscountPrice, orderItem.getNum(), orderItem.getReturnGoodsNumber()); + totalDiscountPrice = CurrencyUtil.add(totalDiscountPrice, remainingDiscountPrice); + } + } + + return totalDiscountPrice; + } + + @Override + public long getPayOrderNum(Date[] dates) { + + LambdaQueryWrapper orderItemLambdaQueryWrapper=new LambdaQueryWrapper<>(); + + orderItemLambdaQueryWrapper.between(OrderItem::getCreateTime,dates[0], dates[1]); + orderItemLambdaQueryWrapper.ne(OrderItem::getIsRefund,RefundStatusEnum.ALL_REFUND.name()); + + return this.baseMapper.getPayOrderNum(orderItemLambdaQueryWrapper); + } + + @Override + public Double getPayOrderPrice(Date[] dates, PaymentMethodEnum paymentMethodEnum, DeliveryMethodEnum deliveryMethodEnum) { + + //查看付款金额 + QueryWrapper queryWrapper = Wrappers.query(); + + queryWrapper.between("oi.create_time", dates[0], dates[1]); + queryWrapper.ne("oi.is_refund", RefundStatusEnum.ALL_REFUND.name()); + + if(paymentMethodEnum!=null){ + queryWrapper.eq("o.payment_method",paymentMethodEnum.name()); + } + if(deliveryMethodEnum!=null){ + if(DeliveryMethodEnum.VIRTUAL.equals(deliveryMethodEnum)){ + queryWrapper.eq("o.order_type", OrderTypeEnum.VIRTUAL.name()); + }else{ + queryWrapper.eq("o.delivery_method",deliveryMethodEnum.name()); + } + + } + return this.baseMapper.getPayOrderPrice(queryWrapper); + + } + + @Override + public Double getGoodsPrice(Date[] dates) { + LambdaQueryWrapper orderItemLambdaQueryWrapper=new LambdaQueryWrapper<>(); + + orderItemLambdaQueryWrapper.between(OrderItem::getCreateTime,dates[0], dates[1]); + orderItemLambdaQueryWrapper.ne(OrderItem::getIsRefund,RefundStatusEnum.ALL_REFUND.name()); + + return this.baseMapper.getGoodsPrice(orderItemLambdaQueryWrapper); + } + + @Override + public Double getFreight(Date[] dates) { + + LambdaQueryWrapper orderItemLambdaQueryWrapper=new LambdaQueryWrapper<>(); + + orderItemLambdaQueryWrapper.between(OrderItem::getCreateTime,dates[0], dates[1]); + orderItemLambdaQueryWrapper.ne(OrderItem::getIsRefund,RefundStatusEnum.ALL_REFUND.name()); + + List orderItems=orderItemService.list(orderItemLambdaQueryWrapper); + Double freight=0D; + for (OrderItem orderItem:orderItems){ + PriceDetailDTO priceDetailDTO=orderItem.getPriceDetailDTO(); + freight=CurrencyUtil.add(freight,priceDetailDTO.getFreightPrice()); + } + return freight; + } + + @Override + public Double getDistribution(Date[] dates) { + LambdaQueryWrapper orderItemLambdaQueryWrapper=new LambdaQueryWrapper<>(); + + orderItemLambdaQueryWrapper.between(OrderItem::getCreateTime,dates[0], dates[1]); + orderItemLambdaQueryWrapper.ne(OrderItem::getIsRefund,RefundStatusEnum.ALL_REFUND.name()); + + List orderItems=orderItemService.list(orderItemLambdaQueryWrapper); + Double distributionCommission=0D; + for (OrderItem orderItem:orderItems){ + PriceDetailDTO priceDetailDTO=orderItem.getPriceDetailDTO(); + distributionCommission=CurrencyUtil.add(distributionCommission,priceDetailDTO.getDistributionCommission()); + } + return distributionCommission; + } + + @Override + public Long getRefundNum(Date[] dates) { + LambdaQueryWrapper orderItemLambdaQueryWrapper=new LambdaQueryWrapper<>(); + + orderItemLambdaQueryWrapper.between(OrderItem::getCreateTime,dates[0], dates[1]); + orderItemLambdaQueryWrapper.eq(OrderItem::getIsRefund,RefundStatusEnum.ALL_REFUND.name()); + + return this.baseMapper.getPayOrderNum(orderItemLambdaQueryWrapper); + } + + @Override + public Double getRefundPrice(Date[] dates) { + + QueryWrapper queryWrapper = Wrappers.query(); + + queryWrapper.between("oi.create_time", dates[0], dates[1]); + queryWrapper.eq("oi.is_refund", RefundStatusEnum.ALL_REFUND.name()); + + + return this.baseMapper.getRefundPrice(queryWrapper); + } + + @Override + public Double getRefundRate(Date[] dates) { + + QueryWrapper queryWrapper = Wrappers.query(); + + queryWrapper.between("create_time", dates[0], dates[1]); + + + Long orderNum= this.baseMapper.getPayOrderNum(queryWrapper); + return CurrencyUtil.mul(CurrencyUtil.div(this.getRefundNum(dates),orderNum),100); + } + + /** + * 计算订单项的优惠金额 + */ + private Double calculateItemDiscountPrice(PriceDetailDTO priceDetailDTO) { + Double discountPrice = priceDetailDTO.getDiscountPrice() != null ? priceDetailDTO.getDiscountPrice() : 0.0; + Double couponPrice = priceDetailDTO.getCouponPrice() != null ? priceDetailDTO.getCouponPrice() : 0.0; + return CurrencyUtil.add(discountPrice, couponPrice); + } + + /** + * 计算部分退款后的剩余优惠金额 + */ + private Double calculateRemainingDiscountPrice(Double totalDiscountPrice, Integer totalNum, Integer returnNum) { + if (totalNum == null || totalNum <= 0 || returnNum == null || returnNum < 0) { + return totalDiscountPrice; + } + + Integer remainingNum = totalNum - returnNum; + if (remainingNum <= 0) { + return 0.0; + } + + // 按剩余数量比例计算优惠金额 + Double ratio = CurrencyUtil.div(remainingNum.doubleValue(), totalNum.doubleValue(), 4); + return CurrencyUtil.mul(totalDiscountPrice, ratio); + } + + @Override public List statisticsChart(StatisticsQueryParam statisticsQueryParam) { Date[] dates = StatisticsDateUtil.getDateArray(statisticsQueryParam); diff --git a/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/OverViewStatisticsServiceImpl.java b/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/OverViewStatisticsServiceImpl.java new file mode 100644 index 000000000..65bebd6b3 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/OverViewStatisticsServiceImpl.java @@ -0,0 +1,137 @@ +package cn.lili.modules.statistics.serviceimpl; + +import cn.lili.common.utils.CurrencyUtil; +import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; +import cn.lili.modules.payment.entity.enums.PaymentMethodEnum; +import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; +import cn.lili.modules.statistics.entity.vo.BusinessCompositionDataVO; +import cn.lili.modules.statistics.entity.vo.OrderOverviewVO; +import cn.lili.modules.statistics.entity.vo.OverViewDataVO; +import cn.lili.modules.statistics.entity.vo.SourceDataVO; +import cn.lili.modules.statistics.service.OrderStatisticsService; +import cn.lili.modules.statistics.service.OverViewStatisticsService; +import cn.lili.modules.statistics.util.StatisticsDateUtil; +import cn.lili.modules.wallet.service.RechargeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @author Bulbasaur + * @since 2025/08/25 7:07 下午 + * + */ +@Service +public class OverViewStatisticsServiceImpl implements OverViewStatisticsService { + + @Autowired + private RechargeService rechargeService; + @Autowired + private OrderStatisticsService orderStatisticsService; + @Override + public OverViewDataVO getOverViewDataVO(StatisticsQueryParam statisticsQueryParam) { + Date[] dates = StatisticsDateUtil.getDateArray(statisticsQueryParam); + + OverViewDataVO overViewDataVO = new OverViewDataVO(); + //营业收入不含数值储值金额.订单扣除退款折扣后金额(不含储值充值) + overViewDataVO.setIncomeNoStoreValue(orderStatisticsService.getPayOrderPrice(dates,null,null)); + //优惠金额.订单的优惠金额(扣除退款,不含储值充值) + overViewDataVO.setDiscount(orderStatisticsService.getDiscountPrice( dates)); + //营业额.营业额=营业收入+优惠金额,订单扣除退款折扣前金额(不含储值充值) + overViewDataVO.setTurnover(CurrencyUtil.add(overViewDataVO.getIncomeNoStoreValue(), overViewDataVO.getDiscount())); + //支付订单数.按客户支付完成时间统计的成功付款的订单数(不含退款、储值充值) + overViewDataVO.setPayOrderNum(orderStatisticsService.getPayOrderNum(dates)); + //新增充值金额.按客户支付完成时间统计的客户储值充值本金金额 + overViewDataVO.setRecharge(rechargeService.getRecharge(dates,null)); + //使用充值金额.使用储值支付本金金额:统计时间范围内,支付和退款成功的订单中,使用储值支付且扣除退款的金额 + overViewDataVO.setRechargeUse(orderStatisticsService.orderNum(PaymentMethodEnum.WALLET.name(), dates)); + + return overViewDataVO; + } + + @Override + public List getSourceDataVOList(StatisticsQueryParam statisticsQueryParam) { + Date[] dates = StatisticsDateUtil.getDateArray(statisticsQueryParam); + List sourceDataVOList=new ArrayList<>(); + //微信 + SourceDataVO sourceDataVO=new SourceDataVO(); + sourceDataVO.setPayType(PaymentMethodEnum.WECHAT.paymentName()); + + sourceDataVO.setIncome(orderStatisticsService.getPayOrderPrice(dates,PaymentMethodEnum.WECHAT,null)); + sourceDataVO.setRecharge(rechargeService.getRecharge(dates,PaymentMethodEnum.WECHAT)); + sourceDataVO.setTotal(CurrencyUtil.add(sourceDataVO.getIncome(),sourceDataVO.getRecharge())); + sourceDataVOList.add(sourceDataVO); + + //支付宝 + SourceDataVO zhifubao=new SourceDataVO(); + zhifubao.setPayType(PaymentMethodEnum.ALIPAY.paymentName()); + zhifubao.setIncome(orderStatisticsService.getPayOrderPrice(dates,PaymentMethodEnum.ALIPAY,null)); + zhifubao.setRecharge(rechargeService.getRecharge(dates,PaymentMethodEnum.ALIPAY)); + zhifubao.setTotal(CurrencyUtil.add(zhifubao.getIncome(),zhifubao.getRecharge())); + sourceDataVOList.add(zhifubao); + + //线下支付 + SourceDataVO bankTransfer=new SourceDataVO(); + bankTransfer.setPayType(PaymentMethodEnum.BANK_TRANSFER.paymentName()); + bankTransfer.setIncome(orderStatisticsService.getPayOrderPrice(dates,PaymentMethodEnum.BANK_TRANSFER,null)); + bankTransfer.setRecharge(rechargeService.getRecharge(dates,PaymentMethodEnum.BANK_TRANSFER)); + bankTransfer.setTotal(CurrencyUtil.add(bankTransfer.getIncome(),bankTransfer.getRecharge())); + sourceDataVOList.add(bankTransfer); + + //余额 + SourceDataVO wallet=new SourceDataVO(); + wallet.setPayType(PaymentMethodEnum.WALLET.paymentName()); + wallet.setIncome(orderStatisticsService.getPayOrderPrice(dates,PaymentMethodEnum.WALLET,null)); + wallet.setRecharge(rechargeService.getRecharge(dates,PaymentMethodEnum.WALLET)); + wallet.setTotal(CurrencyUtil.add(wallet.getIncome(),wallet.getRecharge())); + sourceDataVOList.add(wallet); + return sourceDataVOList; + } + + @Override + public BusinessCompositionDataVO businessCompositionDataVO(StatisticsQueryParam statisticsQueryParam) { + Date[] dates = StatisticsDateUtil.getDateArray(statisticsQueryParam); + BusinessCompositionDataVO businessCompositionDataVO=new BusinessCompositionDataVO(); + //-----订单分类构成----- + + businessCompositionDataVO.setStoreSelf(orderStatisticsService.getPayOrderPrice(dates,null, DeliveryMethodEnum.SELF_PICK_UP)); + businessCompositionDataVO.setExpress(orderStatisticsService.getPayOrderPrice(dates,null, DeliveryMethodEnum.LOGISTICS)); + businessCompositionDataVO.setOnline(orderStatisticsService.getPayOrderPrice(dates,null, DeliveryMethodEnum.VIRTUAL)); + + //-----营业收入----- + //商品销售 + businessCompositionDataVO.setIncome(orderStatisticsService.getGoodsPrice(dates)); + //运费 + businessCompositionDataVO.setFreight(orderStatisticsService.getFreight(dates)); + //商品返现(分销返佣) + businessCompositionDataVO.setIncomeBack(orderStatisticsService.getDistribution(dates)); + //商品销售+费用构成 + businessCompositionDataVO.setIncomeComposition( + CurrencyUtil.sub(CurrencyUtil.add(businessCompositionDataVO.getIncome(), businessCompositionDataVO.getFreight()), + businessCompositionDataVO.getIncomeBack())); + + //-----退款统计----- + //退款订单笔数 + businessCompositionDataVO.setRefundOrderNum(orderStatisticsService.getRefundNum(dates)); + //退款金额 + businessCompositionDataVO.setRefund(orderStatisticsService.getRefundPrice(dates)); + //退款率 + businessCompositionDataVO.setRefundRate(orderStatisticsService.getRefundRate(dates)); + + //-----消费指标----- + //支付金额 + OrderOverviewVO overview=orderStatisticsService.overview(statisticsQueryParam); + businessCompositionDataVO.setPay(overview.getPaymentAmount()); + //折后笔单价 + businessCompositionDataVO.setPrice(CurrencyUtil.div(overview.getPaymentAmount(),overview.getPaymentOrderNum())); + //支付人数 + businessCompositionDataVO.setPayNum(overview.getPaymentsNum()); + //折后客单价 + businessCompositionDataVO.setPriceNum(CurrencyUtil.div(overview.getPaymentAmount(),overview.getPaymentsNum())); + + return businessCompositionDataVO; + } +} diff --git a/framework/src/main/java/cn/lili/modules/wallet/mapper/RechargeMapper.java b/framework/src/main/java/cn/lili/modules/wallet/mapper/RechargeMapper.java index fba8eeedb..a8933f39f 100644 --- a/framework/src/main/java/cn/lili/modules/wallet/mapper/RechargeMapper.java +++ b/framework/src/main/java/cn/lili/modules/wallet/mapper/RechargeMapper.java @@ -1,7 +1,12 @@ package cn.lili.modules.wallet.mapper; +import cn.lili.modules.order.order.entity.vo.PaymentLog; import cn.lili.modules.wallet.entity.dos.Recharge; +import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; /** * 预存款充值记录数据处理层 @@ -11,4 +16,13 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface RechargeMapper extends BaseMapper { + + /** + * 获取会员预存款 + * + * @return 会员预存款 + */ + @Select("SELECT COALESCE(SUM(recharge_money), 0) FROM li_recharge ${ew.customSqlSegment}") + Double getRecharge(@Param(Constants.WRAPPER) Wrapper queryWrapper); + } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/wallet/service/RechargeService.java b/framework/src/main/java/cn/lili/modules/wallet/service/RechargeService.java index 818b7ef90..44572d1d6 100644 --- a/framework/src/main/java/cn/lili/modules/wallet/service/RechargeService.java +++ b/framework/src/main/java/cn/lili/modules/wallet/service/RechargeService.java @@ -2,10 +2,13 @@ package cn.lili.modules.wallet.service; import cn.lili.common.vo.PageVO; import cn.lili.modules.order.trade.entity.vo.RechargeQueryVO; +import cn.lili.modules.payment.entity.enums.PaymentMethodEnum; import cn.lili.modules.wallet.entity.dos.Recharge; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; +import java.util.Date; + /** * 预存款充值业务层 * @@ -56,4 +59,10 @@ public interface RechargeService extends IService { */ void rechargeOrderCancel(String sn); + /** + * 获取周期内的充值金额 + * + * @return + */ + Double getRecharge(Date[] dates, PaymentMethodEnum paymentMethodEnum); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/wallet/serviceimpl/RechargeServiceImpl.java b/framework/src/main/java/cn/lili/modules/wallet/serviceimpl/RechargeServiceImpl.java index 5f7220d76..3b5ec3088 100644 --- a/framework/src/main/java/cn/lili/modules/wallet/serviceimpl/RechargeServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/wallet/serviceimpl/RechargeServiceImpl.java @@ -10,6 +10,7 @@ import cn.lili.common.utils.SnowFlake; import cn.lili.common.vo.PageVO; import cn.lili.modules.order.order.entity.enums.PayStatusEnum; import cn.lili.modules.order.trade.entity.vo.RechargeQueryVO; +import cn.lili.modules.payment.entity.enums.PaymentMethodEnum; import cn.lili.modules.wallet.entity.dos.Recharge; import cn.lili.modules.wallet.entity.dto.MemberWalletUpdateDTO; import cn.lili.modules.wallet.entity.enums.DepositServiceTypeEnum; @@ -17,6 +18,7 @@ import cn.lili.modules.wallet.mapper.RechargeMapper; import cn.lili.modules.wallet.service.MemberWalletService; import cn.lili.modules.wallet.service.RechargeService; import cn.lili.mybatis.util.PageUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -116,4 +118,15 @@ public class RechargeServiceImpl extends ServiceImpl i this.updateById(recharge); } } + + @Override + public Double getRecharge(Date[] dates, PaymentMethodEnum paymentMethodEnum) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper(); + queryWrapper.eq(Recharge::getPayStatus, PayStatusEnum.PAID.name()); + queryWrapper.between(Recharge::getPayTime, dates[0], dates[1]); + if(paymentMethodEnum!=null){ + queryWrapper.eq(Recharge::getRechargeWay,paymentMethodEnum.name()); + } + return this.baseMapper.getRecharge(queryWrapper); + } } \ No newline at end of file diff --git a/manager-api/src/main/java/cn/lili/controller/statistics/OverViewStatisticsManagerController.java b/manager-api/src/main/java/cn/lili/controller/statistics/OverViewStatisticsManagerController.java new file mode 100644 index 000000000..bdf261dfd --- /dev/null +++ b/manager-api/src/main/java/cn/lili/controller/statistics/OverViewStatisticsManagerController.java @@ -0,0 +1,67 @@ +package cn.lili.controller.statistics; + +import cn.lili.common.enums.ResultUtil; +import cn.lili.common.vo.ResultMessage; +import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; +import cn.lili.modules.statistics.entity.vo.BusinessCompositionDataVO; +import cn.lili.modules.statistics.entity.vo.OverViewDataVO; +import cn.lili.modules.statistics.entity.vo.SourceDataVO; +import cn.lili.modules.statistics.service.OverViewStatisticsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +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; + +/** + * 管理端,营业概览接口 + * + * @author Bulbasaur + * @since 2025/08/25 7:31 下午 + */ +@Slf4j +@Api(tags = "管理端,营业概览接口") +@RestController +@RequestMapping("/manager/statistics/overview") +public class OverViewStatisticsManagerController { + + @Autowired + private OverViewStatisticsService overViewStatisticsService; + + @ApiOperation(value = "获取营业概览统计") + @GetMapping + public ResultMessage overViewDataVO(StatisticsQueryParam statisticsQueryParam) { + try { + return ResultUtil.data(overViewStatisticsService.getOverViewDataVO(statisticsQueryParam)); + } catch (Exception e) { + log.error("获取营业概览统计错误",e); + } + return null; + } + + @ApiOperation(value = "收款构成列表") + @GetMapping("/source") + public ResultMessage> sourceDataVOList(StatisticsQueryParam statisticsQueryParam) { + try { + return ResultUtil.data(overViewStatisticsService.getSourceDataVOList(statisticsQueryParam)); + } catch (Exception e) { + log.error("收款构成列表错误",e); + } + return null; + } + + @ApiOperation(value = "营业构成信息") + @GetMapping("/businessComposition") + public ResultMessage businessCompositionDataVO(StatisticsQueryParam statisticsQueryParam) { + try { + return ResultUtil.data(overViewStatisticsService.businessCompositionDataVO(statisticsQueryParam)); + } catch (Exception e) { + log.error("营业构成信息",e); + } + return null; + } +}