From ec46d876b187b1c9be14509c591996e78c9bc2d9 Mon Sep 17 00:00:00 2001 From: wangw <1594593906@qq.com> Date: Tue, 25 Nov 2025 11:49:40 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E8=AE=A1=20=E6=88=90=E6=9C=AC?= =?UTF-8?q?=E4=BB=B7=20=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/czg/order/vo/ProductCostAmountVO.java | 4 - .../mapper/ShopOrderStatisticMapper.java | 128 +++++++++++------- .../impl/ShopOrderStatisticServiceImpl.java | 77 ++++++++--- 3 files changed, 140 insertions(+), 69 deletions(-) diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/vo/ProductCostAmountVO.java b/cash-common/cash-common-service/src/main/java/com/czg/order/vo/ProductCostAmountVO.java index e718bc631..aa0dadcf3 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/order/vo/ProductCostAmountVO.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/order/vo/ProductCostAmountVO.java @@ -14,9 +14,5 @@ import java.math.BigDecimal; public class ProductCostAmountVO { private Long productId; private Long skuId; - //向上取整 保留两位小数 - private BigDecimal costAmount; - private Long count; - private BigDecimal totalCostAmount; } diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/mapper/ShopOrderStatisticMapper.java b/cash-service/order-service/src/main/java/com/czg/service/order/mapper/ShopOrderStatisticMapper.java index 8b684a033..2f9683a1a 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/mapper/ShopOrderStatisticMapper.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/mapper/ShopOrderStatisticMapper.java @@ -1,8 +1,10 @@ package com.czg.service.order.mapper; +import com.czg.order.vo.ProductCostAmountVO; import com.czg.order.vo.TotalVo; import com.mybatisflex.core.BaseMapper; import com.czg.order.entity.ShopOrderStatistic; +import org.apache.ibatis.annotations.MapKey; import org.apache.ibatis.annotations.Select; import java.math.BigDecimal; @@ -19,55 +21,56 @@ import java.util.Map; public interface ShopOrderStatisticMapper extends BaseMapper { - @Select("SELECT"+ - " SUM(pay_amount) AS payAmount,"+ - " SUM(online_pay_amount) AS onlinePayAmount,"+ - " SUM(member_pay_amount) AS memberPayAmount,"+ - " SUM(member_pay_count) AS memberPayCount,"+ - " SUM(refund_amount) AS refundAmount,"+ - " SUM(online_refund_amount) AS onlineRefundAmount,"+ - " SUM(recharge_amount) AS rechargeAmount,"+ - " SUM(online_recharge_amount) AS onlineRechargeAmount,"+ - " SUM(give_amount) AS giveAmount,"+ - " SUM(recharge_refund_amount) AS rechargeRefundAmount,"+ - " SUM(online_recharge_refund_amount) AS onlineRechargeRefundAmount,"+ - " SUM(cash_recharge_refund_amount) AS cashRechargeRefundAmount,"+ - " SUM(cash_recharge_amount) AS cashRechargeAmount,"+ - " SUM(member_refund_amount) AS memberRefundAmount,"+ - " SUM(cash_refund_amount) AS cashRefundAmount,"+ - " SUM(new_member_count) AS newMemberCount,"+ - " SUM(customer_count) AS customerCount,"+ - " SUM(order_count) AS orderCount,"+ - " SUM(table_count) AS tableCount,"+ - " SUM(avg_pay_amount) AS avgPayAmount,"+ - " SUM(turnover_rate) AS turnoverRate,"+ - " SUM(profit_amount) AS profitAmount,"+ - " SUM(product_cost_amount) AS productCostAmount,"+ - " SUM(profit_rate) AS profitRate,"+ - " SUM(net_profit_amount) AS netProfitAmount,"+ - " SUM(net_profit_rate) AS netProfitRate,"+ - " SUM(discount_amount) AS discountAmount,"+ - " SUM(discount_count) AS discountCount,"+ - " SUM(new_customer_discount_amount) AS newCustomerDiscountAmount,"+ - " SUM(full_discount_amount) AS fullDiscountAmount,"+ - " SUM(coupon_discount_amount) AS couponDiscountAmount,"+ - " SUM(point_discount_amount) AS pointDiscountAmount,"+ - " SUM(back_discount_amount) AS backDiscountAmount,"+ - " SUM(member_discount_amount) AS memberDiscountAmount,"+ - " SUM(order_price_discount_amount) AS orderPriceDiscountAmount,"+ - " SUM(cash_pay_amount) AS cashPayAmount,"+ - " SUM(wechat_pay_amount) AS wechatPayAmount,"+ - " SUM(alipay_pay_amount) AS alipayPayAmount,"+ - " SUM(back_scan_pay_amount) AS backScanPayAmount,"+ - " SUM(main_scan_pay_amount) AS mainScanPayAmount,"+ - " SUM(credit_pay_amount) AS creditPayAmount "+ - "FROM"+ + @Select("SELECT" + + " SUM(pay_amount) AS payAmount," + + " SUM(online_pay_amount) AS onlinePayAmount," + + " SUM(member_pay_amount) AS memberPayAmount," + + " SUM(member_pay_count) AS memberPayCount," + + " SUM(refund_amount) AS refundAmount," + + " SUM(online_refund_amount) AS onlineRefundAmount," + + " SUM(recharge_amount) AS rechargeAmount," + + " SUM(online_recharge_amount) AS onlineRechargeAmount," + + " SUM(give_amount) AS giveAmount," + + " SUM(recharge_refund_amount) AS rechargeRefundAmount," + + " SUM(online_recharge_refund_amount) AS onlineRechargeRefundAmount," + + " SUM(cash_recharge_refund_amount) AS cashRechargeRefundAmount," + + " SUM(cash_recharge_amount) AS cashRechargeAmount," + + " SUM(member_refund_amount) AS memberRefundAmount," + + " SUM(cash_refund_amount) AS cashRefundAmount," + + " SUM(new_member_count) AS newMemberCount," + + " SUM(customer_count) AS customerCount," + + " SUM(order_count) AS orderCount," + + " SUM(table_count) AS tableCount," + + " SUM(avg_pay_amount) AS avgPayAmount," + + " SUM(turnover_rate) AS turnoverRate," + + " SUM(profit_amount) AS profitAmount," + + " SUM(product_cost_amount) AS productCostAmount," + + " SUM(profit_rate) AS profitRate," + + " SUM(net_profit_amount) AS netProfitAmount," + + " SUM(net_profit_rate) AS netProfitRate," + + " SUM(discount_amount) AS discountAmount," + + " SUM(discount_count) AS discountCount," + + " SUM(new_customer_discount_amount) AS newCustomerDiscountAmount," + + " SUM(full_discount_amount) AS fullDiscountAmount," + + " SUM(coupon_discount_amount) AS couponDiscountAmount," + + " SUM(point_discount_amount) AS pointDiscountAmount," + + " SUM(back_discount_amount) AS backDiscountAmount," + + " SUM(member_discount_amount) AS memberDiscountAmount," + + " SUM(order_price_discount_amount) AS orderPriceDiscountAmount," + + " SUM(cash_pay_amount) AS cashPayAmount," + + " SUM(wechat_pay_amount) AS wechatPayAmount," + + " SUM(alipay_pay_amount) AS alipayPayAmount," + + " SUM(back_scan_pay_amount) AS backScanPayAmount," + + " SUM(main_scan_pay_amount) AS mainScanPayAmount," + + " SUM(credit_pay_amount) AS creditPayAmount " + + "FROM" + " tb_shop_order_statistic " + "WHERE " + " shop_id = #{shopId} " + " AND statistic_date BETWEEN #{start} AND #{end} ") ShopOrderStatistic countStatistic(Long shopId, LocalDate start, LocalDate end); //---------------------------------------------金额统计--------------------------------------------------- + /** * 订单金额统计 当日实时数据 */ @@ -254,17 +257,44 @@ public interface ShopOrderStatisticMapper extends BaseMapper /** * 商品成本 productCostAmount */ + @Select("SELECT" + + " sku.id AS skuId," + + " sku.cost_price AS costAmount " + + "FROM" + + " tb_product product" + + " LEFT JOIN tb_prod_sku sku ON product.id = sku.product_id " + + " AND product.shop_id = sku.shop_id " + + "WHERE" + + " product.shop_id = #{shopId} " + + " AND sku.cost_price > 0") + @MapKey("skuId") + Map getSkuCostAmount(Long shopId); + + @Select("SELECT" + + " relation.product_id as productId," + + " ROUND(relation.surplus_stock * cons.price, 2) AS costAmount" + + " FROM" + + " tb_prod_cons_relation relation " + + " INNER JOIN tb_cons_info cons on relation.cons_info_id = cons.id and relation.shop_id = cons.shop_id and price > 0" + + " WHERE" + + " relation.shop_id = #{shopId} " + + " order by relation.product_id") + @MapKey("productId") + Map getConsCostAmount(Long shopId); + + @Select("SELECT " + - " SUM(CASE WHEN sku.cost_price IS NULL OR sku.cost_price <= 0 THEN 0 ELSE sku.cost_price END) AS productCostAmount " + + " detail.product_id as productId," + + " detail.sku_id as skuId," + + " sum(detail.num - detail.return_num) as count " + "FROM " + " tb_order_info `order` " + - " INNER JOIN tb_order_detail detail ON `order`.id = detail.order_id " + - " AND is_temporary = 0 " + - " LEFT JOIN tb_prod_sku sku ON detail.sku_id = sku.id " + + " INNER JOIN tb_order_detail detail ON `order`.id = detail.order_id AND is_temporary = 0 " + "WHERE " + " `order`.shop_id = #{shopId} " + " and trade_day = #{tradeDay} " + - " and paid_time is not null") - BigDecimal countProductCostAmount(Long shopId, LocalDate tradeDay); + " and paid_time is not null" + + " order by detail.product_id, detail.sku_id") + List getOrderDetailProduct(Long shopId, LocalDate tradeDay); } diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/ShopOrderStatisticServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/ShopOrderStatisticServiceImpl.java index 0ce33dd95..a9ecdf764 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/ShopOrderStatisticServiceImpl.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/ShopOrderStatisticServiceImpl.java @@ -2,11 +2,13 @@ package com.czg.service.order.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; +import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson2.JSONObject; import com.czg.exception.CzgException; import com.czg.order.entity.ShopOrderStatistic; import com.czg.order.service.ShopOrderStatisticService; import com.czg.order.vo.CountPayTypeVo; +import com.czg.order.vo.ProductCostAmountVO; import com.czg.order.vo.TotalVo; import com.czg.service.order.mapper.ShopOrderStatisticMapper; import com.mybatisflex.core.query.QueryWrapper; @@ -18,7 +20,9 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Optional; /** @@ -53,6 +57,7 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl skuCostAmountList = mapper.getSkuCostAmount(shopId); +// //获取商品耗材成本价 productId price + Map consCostAmountList = mapper.getConsCostAmount(shopId); + //获取orderDetail信息 productId skuId 数量 + BigDecimal productCostAmount = BigDecimal.ZERO; + if (CollUtil.isEmpty(skuCostAmountList) && CollUtil.isEmpty(consCostAmountList)) { + return productCostAmount; } - result.setProfitAmount(result.getPayAmount().subtract(productCostAmount)); + List orderDetailProduct = mapper.getOrderDetailProduct(shopId, day); + if (CollUtil.isEmpty(orderDetailProduct)) { + return productCostAmount; + } + for (ProductCostAmountVO productCostAmountVO : orderDetailProduct) { + if (skuCostAmountList.containsKey(productCostAmountVO.getSkuId())) { + BigDecimal costAmount = skuCostAmountList.get(productCostAmountVO.getSkuId()); + productCostAmount = productCostAmount.add(costAmount.multiply(new BigDecimal(productCostAmountVO.getCount())).setScale(2, RoundingMode.HALF_UP)); + } else if (consCostAmountList.containsKey(productCostAmountVO.getProductId())) { + BigDecimal costAmount = consCostAmountList.get(productCostAmountVO.getProductId()); + productCostAmount = productCostAmount.add(costAmount.multiply(new BigDecimal(productCostAmountVO.getCount())).setScale(2, RoundingMode.HALF_UP)); + } + } + return productCostAmount; + } + + + /** + * 计算 客单价 翻台率 净利润 净利率 毛利润 毛利率 + */ + private void calculateShopOrderStatistic(ShopOrderStatistic result) { + //毛利润(订单实付金额-商品成本) + if (result.getProductCostAmount() == null) { + result.setProductCostAmount(BigDecimal.ZERO); + } + result.setProfitAmount(result.getPayAmount().subtract(result.getProductCostAmount())); //毛利率(订单实付金额-商品成本)/订单实付金额*100% if (result.getPayAmount().compareTo(BigDecimal.ZERO) > 0) { BigDecimal profitRate = result.getProfitAmount().divide(result.getPayAmount(), 4, RoundingMode.HALF_DOWN).multiply(BigDecimal.valueOf(100)); @@ -199,13 +243,14 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl 0) { - BigDecimal turnoverRate = new BigDecimal(result.getOrderCount()).subtract(new BigDecimal(tableCount)).divide(new BigDecimal(tableCount), 4, RoundingMode.HALF_DOWN).multiply(BigDecimal.valueOf(100)); + if (result.getTableCount() != null && result.getTableCount() > 0) { + BigDecimal turnoverRate = new BigDecimal( + result.getOrderCount()).subtract(new BigDecimal(result.getTableCount())) + .divide(new BigDecimal(result.getTableCount()), 4, RoundingMode.HALF_DOWN).multiply(BigDecimal.valueOf(100)); result.setTurnoverRate(turnoverRate); } else { result.setTurnoverRate(BigDecimal.ZERO); } - return result; }