简体   繁体   中英

How do I conditionally merge hashes and add values?

I am stuck merging some hashes to get the results that I need.

The hashes contain a breakdown of the total price of an order, eg item price, taxes, & shipping, for all orders in a subscription. I'm trying to do this dynamically as not all orders charge tax, or even the same tax or shipping.

Here's what I would call the "worst case scenario" that I'm dealing with:

#First order - has charges for Canadian GST and HST
{:orderhdr_id=>17654122, :order_item_seq=>1, :order_item_amt_break_seq=>1, :order_item_break_type=>0, :local_amount=>8.16, :base_amount=>8.16, :orig_base_amount=>149, :tax_delivery=>0, :tax_active=>0}
{:orderhdr_id=>17654122, :order_item_seq=>1, :order_item_amt_break_seq=>2, :order_item_break_type=>1, :local_amount=>0.41, :base_amount=>0.41, :state=>"ON", :tax_type=>"GST", :tax_rate_category=>"STD", :orig_base_amount=>7.45, :tax_rate=>5, :tax_delivery=>0, :tax_active=>1, :tx_incl=>1}
{:orderhdr_id=>17654122, :order_item_seq=>1, :order_item_amt_break_seq=>3, :order_item_break_type=>1, :local_amount=>0.65, :base_amount=>0.65, :state=>"ON", :tax_type=>"HST", :tax_rate_category=>"STD", :orig_base_amount=>11.92, :tax_rate=>8, :tax_delivery=>0, :tax_active=>1, :tx_incl=>1}
#Second order - has only one charge for tax
{:orderhdr_id=>1815296, :order_item_seq=>1, :order_item_amt_break_seq=>1, :order_item_break_type=>0, :local_amount=>76.52, :base_amount=>76.52, :orig_base_amount=>99.95, :tax_delivery=>0, :tax_active=>0}
{:orderhdr_id=>1815296, :order_item_seq=>1, :order_item_amt_break_seq=>2, :order_item_break_type=>1, :local_amount=>4.59, :base_amount=>4.59, :orig_base_amount=>6, :tax_delivery=>0, :tax_active=>1}
#Third order - has charge for shipping
{:orderhdr_id=>6112412, :order_item_seq=>1, :order_item_amt_break_seq=>1, :order_item_break_type=>0, :local_amount=>21.34, :base_amount=>21.34, :orig_base_amount=>99.95, :tax_delivery=>0, :tax_active=>0}
{:orderhdr_id=>6112412, :order_item_seq=>1, :order_item_amt_break_seq=>2, :order_item_break_type=>2, :local_amount=>4.7, :base_amount=>4.7, :orig_base_amount=>22, :tax_delivery=>0, :tax_active=>0}

The :order_item_break_type determines what type of charge it is, item, tax, shipping.

If :order_item_break_type is 0 or 2, then subtract :base_amount from :orig_base_amount and add it to the overall total for that break type. For :order_item_break_type equals 1, I need to sum up the difference of :orig_base_amount and :base_amount , but I need to keep the different taxes separate.

So here's what I should end up with for the above orders:

:break_type = 0 | total = 242.88
:break_type = 1, :state = ON, :tax_type = GST, :tax_rate_category = STD | total = 7.04
:break_type = 1, :state = ON, :tax_type = HST, :tax_rate_category = STD | total = 11.27
:break_type = 1 | total = 1.41
:break_type = 2 | total = 17.30

I have these hashes in an array called @amounts .

I have methods like merge! , inject , shift and more going through my head, but can't put it together.

How about this? I really don't know what you are doing there, though.

@amounts = [
#First order - has charges for Canadian GST and HST
{:orderhdr_id=>17654122, :order_item_seq=>1, :order_item_amt_break_seq=>1, :order_item_break_type=>0, :local_amount=>8.16, :base_amount=>8.16, :orig_base_amount=>149, :tax_delivery=>0, :tax_active=>0},
{:orderhdr_id=>17654122, :order_item_seq=>1, :order_item_amt_break_seq=>2, :order_item_break_type=>1, :local_amount=>0.41, :base_amount=>0.41, :state=>"ON", :tax_type=>"GST", :tax_rate_category=>"STD", :orig_base_amount=>7.45, :tax_rate=>5, :tax_delivery=>0, :tax_active=>1, :tx_incl=>1},
{:orderhdr_id=>17654122, :order_item_seq=>1, :order_item_amt_break_seq=>3, :order_item_break_type=>1, :local_amount=>0.65, :base_amount=>0.65, :state=>"ON", :tax_type=>"HST", :tax_rate_category=>"STD", :orig_base_amount=>11.92, :tax_rate=>8, :tax_delivery=>0, :tax_active=>1, :tx_incl=>1},
#Second order - has only one charge for tax
{:orderhdr_id=>1815296, :order_item_seq=>1, :order_item_amt_break_seq=>1, :order_item_break_type=>0, :local_amount=>76.52, :base_amount=>76.52, :orig_base_amount=>99.95, :tax_delivery=>0, :tax_active=>0},
{:orderhdr_id=>1815296, :order_item_seq=>1, :order_item_amt_break_seq=>2, :order_item_break_type=>1, :local_amount=>4.59, :base_amount=>4.59, :orig_base_amount=>6, :tax_delivery=>0, :tax_active=>1},
#Third order - has charge for shipping
{:orderhdr_id=>6112412, :order_item_seq=>1, :order_item_amt_break_seq=>1, :order_item_break_type=>0, :local_amount=>21.34, :base_amount=>21.34, :orig_base_amount=>99.95, :tax_delivery=>0, :tax_active=>0},
{:orderhdr_id=>6112412, :order_item_seq=>1, :order_item_amt_break_seq=>2, :order_item_break_type=>2, :local_amount=>4.7, :base_amount=>4.7, :orig_base_amount=>22, :tax_delivery=>0, :tax_active=>0},
]

@totals = Hash.new(0)

@amounts.group_by{|row| row[:order_item_break_type]}.each do |break_type, rows|

  rows.each do |row|

    key = [break_type, row[:tax_type]]
    @totals[key] += row[:orig_base_amount] - row[:base_amount]

  end
end

@totals
# => {[0, nil]=>242.88,
#     [1, "GST"]=>7.04,
#     [1, "HST"]=>11.27,
#     [1, nil]=>1.4100000000000001,
#     [2, nil]=>17.3}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM