Spark实时项目第八天-DWS层订单明细实付金额分摊(双流合并)

本文介绍了Spark实时项目中如何处理订单明细的实付金额分摊,特别是在存在优惠和运费的情况下。通过双流合并解决不同批次数据丢失问题,并详细阐述了分摊算法和特殊情况下如何确保总金额精确匹配。
摘要由CSDN通过智能技术生成

需求

主订单的应付金额【origin_total_amount】一般是由所有订单明细的商品单价数量汇总【sku_pricesku_num】组成。

但是由于优惠、运费等都是以订单为单位进行计算的,所以减掉优惠、加上运费会得到一个最终实付金额【final_total_amount】。

但问题在于如果是以商品进行交易额分析,也要把优惠、运费的效果分摊到购买的每个商品中。

如何分摊

一般是由订单明细每种商品的消费占总订单的比重进行分摊,比如总价1000元的商品,
由分别由600元和400元的A、B两种商品组成, 但是经过打折和加运费后,实际付款金额变为810,那么A的分摊实付金额为486元和B的分摊实付金额为324元。

复杂情况

由于明细的分摊是由占比而得,那就会进行除法,除法就有可能出现除不尽的情况。

比如:原价90元 ,三种商品每件30元。没有优惠但有10元运费,总实付金额为100元。按占比分摊各三分之一,就会出现三个33.33元。加起来就会出现99.99元。就会出现差一分钱的情况。

而我们要求所有订单明细的实付分摊加总必须和订单的总实付相等。
所以我们要的是100=33.33+33.33+33.34

解决思路

分摊计算分成两种情况:

不是最后一笔: 按照占比,用除法求分摊金额
最后一笔: 用减法 用主表的总实付金额-之前所有明细以求得的分摊汇总值

如何判断是最后一笔

如果订单明细10条 分布在不同的批次中

双流合并

由于两个流的数据是独立保存,独立消费,很有可能同一业务的数据,分布在不同的批次。因为join算子只join同一批次的数据。如果只用简单的join流方式,会丢失掉不同批次的数据。

1.  利用滑动窗口进行join 然后再进行去重
  
2.  把数据存入缓存,关联时进行join后 再去查询缓存中的数据,来弥补不同批次的问题。

添加OrderDetailWide

在scala\com\atguigu\gmall\realtime\bean\OrderDetailWide.scala

case class OrderDetailWide(
                       var order_detail_id:Long =0L,
                       var order_id: Long=0L,
                       var order_status:String=null,
                       var create_time:String=null,
                       var user_id: Long=0L,
                       var sku_id: Long=0L,
                       var sku_price: Double=0D,
                       var sku_num: Long=0L,
                       var sku_name: String=null,
                       var benefit_reduce_amount:Double =0D ,
                       var original_total_amount:Double =0D ,// 订单主表中的 原始交易额 = 所有明细 单价*数量的汇总值
                       var feight_fee:Double=0D,
                       var final_total_amount: Double =0D,   //订单主表中的 实际付款总额
                       var final_detail_amount:Double=0D,    //从表中的  实际分摊总额



                       var if_first_order:String=null,

                       var province_name:String=null,
                       var province_area_code:String=null,

                       var user_age_group:String=null,
                       var user_gender:String=null,

                       var dt:String=null,

                       var spu_id: Long=0L,
                       var tm_id: Long=0L,
                       var category3_id: Long=0L,
                       var spu_name: String=null,
                       var tm_name: String=null,
                       var category3_name: String=null


                      )
{
   
  def this(orderInfo:OrderInfo,orderDetail: OrderDetail) {
   
    this
    mergeOrderInfo(orderInfo)
    mergeOrderDetail(orderDetail)

  }

  def mergeOrderInfo(orderInfo:OrderInfo): Unit ={
   
    if(orderInfo!=null){
   
      this.order_id=orderInfo.id
      this.order_status=orderInfo.order_status
      this.create_time=orderInfo.create_time
      this.dt=orderInfo.create_date

      this.benefit_reduce_amount  =orderInfo.benefit_reduce_amount
      this.original_total_amount  =orderInfo.original_total_amount
      this.feight_fee =orderInfo.feight_fee
      this.final_total_amount  =orderInfo.final_total_amount


      this.province_name=orderInfo.province_name
      this.province_area_code=orderInfo.province_area_code

      this
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值