统计 成本价 部分
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<ShopOrderStatistic> {
|
||||
|
||||
|
||||
@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<ShopOrderStatistic>
|
||||
/**
|
||||
* 商品成本 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<Long, BigDecimal> 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<Long, BigDecimal> 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<ProductCostAmountVO> getOrderDetailProduct(Long shopId, LocalDate tradeDay);
|
||||
|
||||
}
|
||||
|
||||
@@ -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<ShopOrderStatisti
|
||||
ShopOrderStatistic statDateRange = getStatDateRange(shopId, start, end);
|
||||
ShopOrderStatistic shopOrderStatistic = ShopOrderStatistic.mergeStatistics(realTimeDataByDay, statDateRange);
|
||||
shopOrderStatistic.setShopId(shopId);
|
||||
calculateShopOrderStatistic(shopOrderStatistic);
|
||||
return shopOrderStatistic;
|
||||
}
|
||||
}
|
||||
@@ -106,16 +111,17 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl<ShopOrderStatisti
|
||||
ShopOrderStatistic result = new ShopOrderStatistic();
|
||||
|
||||
ShopOrderStatistic onlineStat = mapper.getOnlineStatSingleDate(shopId, day);
|
||||
log.info("onlineStat:{}", JSONObject.toJSONString(onlineStat));
|
||||
// log.info("onlineStat:{}", JSONObject.toJSONString(onlineStat));
|
||||
ShopOrderStatistic orderStat = mapper.getOrderStatSingleDate(shopId, day);
|
||||
log.info("orderStat:{}", JSONObject.toJSONString(orderStat));
|
||||
// log.info("orderStat:{}", JSONObject.toJSONString(orderStat));
|
||||
ShopOrderStatistic userFlowStat = mapper.getShopUserFlowStatSingleDate(shopId, day);
|
||||
log.info("userFlowStat:{}", JSONObject.toJSONString(userFlowStat));
|
||||
// log.info("userFlowStat:{}", JSONObject.toJSONString(userFlowStat));
|
||||
Long discountCount = mapper.countDiscountOrder(shopId, day);
|
||||
BigDecimal discountAmount = mapper.countDiscountAmount(shopId, day);
|
||||
Long tableCount = mapper.countShopTable(shopId);
|
||||
Long newMemberCount = mapper.countNewMember(shopId, day);
|
||||
BigDecimal productCostAmount = mapper.countProductCostAmount(shopId, day);
|
||||
//获取商品成本金额
|
||||
BigDecimal productCostAmount = getProductCostAmount(shopId, day);
|
||||
// 合并结果
|
||||
CopyOptions copyOptions = CopyOptions.create().setIgnoreNullValue(true);
|
||||
if (onlineStat != null) {
|
||||
@@ -134,11 +140,11 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl<ShopOrderStatisti
|
||||
result.setShopId(shopId);
|
||||
result.setStatisticDate(day);
|
||||
|
||||
result.setDiscountCount(discountCount);
|
||||
result.setDiscountAmount(discountAmount);
|
||||
result.setTableCount(tableCount);
|
||||
result.setNewMemberCount(newMemberCount);
|
||||
result.setProductCostAmount(productCostAmount);
|
||||
result.setDiscountCount(Optional.ofNullable(discountCount).orElse(0L));
|
||||
result.setDiscountAmount(Optional.ofNullable(discountAmount).orElse(BigDecimal.ZERO));
|
||||
result.setNewMemberCount(Optional.ofNullable(newMemberCount).orElse(0L));
|
||||
result.setTableCount(Optional.ofNullable(tableCount).orElse(0L));
|
||||
result.setProductCostAmount(Optional.ofNullable(productCostAmount).orElse(BigDecimal.ZERO));
|
||||
|
||||
//会员充值退款 充值退款金额(线上退款+现金退款)
|
||||
BigDecimal cashRechargeAmount = Objects.requireNonNullElse(result.getCashRechargeAmount(), BigDecimal.ZERO);
|
||||
@@ -177,11 +183,49 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl<ShopOrderStatisti
|
||||
.add(memberPayAmount)
|
||||
.add(creditPayAmount);
|
||||
result.setPayAmount(totalPayAmount);
|
||||
//毛利润(订单实付金额-商品成本)
|
||||
if (productCostAmount == null) {
|
||||
productCostAmount = BigDecimal.ZERO;
|
||||
calculateShopOrderStatistic(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品成本价
|
||||
*/
|
||||
private BigDecimal getProductCostAmount(Long shopId, LocalDate day) {
|
||||
//获取商品sku成本价 productId skuId price
|
||||
Map<Long, BigDecimal> skuCostAmountList = mapper.getSkuCostAmount(shopId);
|
||||
// //获取商品耗材成本价 productId price
|
||||
Map<Long, BigDecimal> 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<ProductCostAmountVO> 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<ShopOrderStatisti
|
||||
result.setAvgPayAmount(result.getPayAmount());
|
||||
}
|
||||
//翻台率 (订单数-桌台数)/桌台数*100%
|
||||
if (tableCount > 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user