How do I conditionally merge hashes and add values? - ruby

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, e.g. 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}

Related

Using Featuretools to aggregate per time time of day

I'm wondering if there's any way to calculate all the same variables I already am using deep feature synthesis (ie counts, sums, mean, etc) for different time segments within a day?
I.e. count of morning events (hours 0-12) as a separate variable from evening events (13-24).
Also, within the same vein, what would be the easiest to get counts by day of week, day of month, day of year, etc. Custom aggregate primitives?
Yes, this is possible. First, let's generate some random data and then I'll walkthrough how
import featuretools as ft
import pandas as pd
import numpy as np
# make some random data
n = 100
events_df = pd.DataFrame({
"id" : range(n),
"customer_id": np.random.choice(["a", "b", "c"], n),
"timestamp": pd.date_range("Jan 1, 2019", freq="1h", periods=n),
"amount": np.random.rand(n) * 100
})
def to_part_of_day(x):
if x < 12:
return "morning"
elif x < 18:
return "afternoon"
else:
return "evening"
events_df["time_of_day"] = events_df["timestamp"].dt.hour.apply(to_part_of_day)
events_df
the first thing we want to do is add a new column for the segment we want to calculate features for
def to_part_of_day(x):
if x < 12:
return "morning"
elif x < 18:
return "afternoon"
else:
return "evening"
events_df["time_of_day"] = events_df["timestamp"].dt.hour.apply(to_part_of_day)
now we have a dataframe like this
id customer_id timestamp amount time_of_day
0 0 a 2019-01-01 00:00:00 44.713802 morning
1 1 c 2019-01-01 01:00:00 58.776476 morning
2 2 a 2019-01-01 02:00:00 94.671566 morning
3 3 a 2019-01-01 03:00:00 39.271852 morning
4 4 a 2019-01-01 04:00:00 40.773290 morning
5 5 c 2019-01-01 05:00:00 19.815855 morning
6 6 a 2019-01-01 06:00:00 62.457129 morning
7 7 b 2019-01-01 07:00:00 95.114636 morning
8 8 b 2019-01-01 08:00:00 37.824668 morning
9 9 a 2019-01-01 09:00:00 46.502904 morning
Next, let's load it into our entityset
es = ft.EntitySet()
es.entity_from_dataframe(entity_id="events",
time_index="timestamp",
dataframe=events_df)
es.normalize_entity(new_entity_id="customers", index="customer_id", base_entity_id="events")
es.plot()
Now, we are ready to set the segments we want to create aggregations for by using interesting_values
es["events"]["time_of_day"].interesting_values = ["morning", "afternoon", "evening"]
Then we can run DFS and place the aggregation primitives we want to do on a per segment basis in the where_primitives parameter
fm, fl = ft.dfs(target_entity="customers",
entityset=es,
agg_primitives=["count", "mean", "sum"],
trans_primitives=[],
where_primitives=["count", "mean", "sum"])
fm
In the resulting feature matrix, you can now see we have aggregations per morning, afternoon, and evening
COUNT(events) MEAN(events.amount) SUM(events.amount) COUNT(events WHERE time_of_day = afternoon) COUNT(events WHERE time_of_day = evening) COUNT(events WHERE time_of_day = morning) MEAN(events.amount WHERE time_of_day = afternoon) MEAN(events.amount WHERE time_of_day = evening) MEAN(events.amount WHERE time_of_day = morning) SUM(events.amount WHERE time_of_day = afternoon) SUM(events.amount WHERE time_of_day = evening) SUM(events.amount WHERE time_of_day = morning)
customer_id
a 37 49.753630 1840.884300 12 7 18 35.098923 45.861881 61.036892 421.187073 321.033164 1098.664063
b 30 51.241484 1537.244522 3 10 17 45.140800 46.170996 55.300715 135.422399 461.709963 940.112160
c 33 39.563222 1305.586314 9 7 17 50.129136 34.593936 36.015679 451.162220 242.157549 612.266545

Magento table rate shipping - exclude some regions from shipping

I have setup a table rate shipping in Magento 1.9. I need to exclude some region from shipping.
For eg., In CSV there are 2 rows, in this format:
Country code - Region - postal - thrashhold - shipping cost
1. FR - Corsica - * - 0 - 18
2. * - * - * - 0 - 50
Currently, If I select France - Corsica in shipping calculator, then it returns shipping cost as 18, which is correct. If I select France - any other region then it shows shipping cost 50, which is not as requirement. Is it possible to restrict other regions, if I select France - any other region?
As per your CSV format condition on 2nd line is applied for all the location except FR-Corsica.You need to remove the second line then It must work as expected.
I think, I got it. I need to remove the regions from tables: directory_country_region and directory_country_region_name, then it wont give option to select other regions of France. Then the shipping can be restricted for these regions.
Only change order of rows
Example:
Country code - Region - postal - thrashhold - shipping cost
1. * - * - * - 0 - 50
2. FR - Corsica - * - 0 - 18

Magento Tax Calculation Incorrect

Hi currently running into an issue with magento 1.9 tax calculations.
I have a product setup as £10.82 with VAT of 20% to be added. The price including VAT is £12.98.
When 1 product is added to the cart everything is ok but if I add 7 the total should be £90.86 but its showing as:
Subtotal - £75.74
VAT - £15.15
Total - £90.89
Therefore 3p of VAT extra is added. Please advise on how I can fix this.
This is not a bug. Total £90.89 is correct but if you want total sum without "extra" 3p of VAT, you can select a different method of calculating VAT.
£10,82 * 20% = £2,164 = £2,16
total: 7 * (£10,82+£2,16) = £90,86
vs
7 * £10,82 = £75,74
£75,74 * 20% = £15,148 = £15,15
total: £75,74 + £15,15 = £90,89
Check Tax Calculation Method in Settings.

Magento different product price starting the second product

I'm working on a software online store width magento CE 1.9
the license pricing is a bit tricky:
each software product has a price for the first license, each additional license of the same product is cheaper.
for example:
1 license (Product Quantity:1) 200$
2 licenses (Product Quantity:2) 200$ (main price of first license) + 20$ (price of additional license) = 220$
3 licenses (Product Quantity:3) 200$ + 2 x 20$ = 240$
4 licenses (Product Quantity:4) 200$ + 3 x 20$ = 260$
i already tried Tier Prices, but this would only allow reducing the price of all licenses.
Many thanks in advance!
Is there any limit on the number of items you can sell? Because if you limit for example the number of licenses to be purchased to max 6, by doing some simple maths you find out that you can apply the following prices and use Tier Prices:
Price single license: 200$
+-----+---------+
| Qty | Price |
+-----+---------+
| 2 | 110$ | = (200+20)/2 <--- The divider is #items
| 3 | 80$ | = (200+20*2)/3
| 4 | 65$ | = (200+20*3)/4
| 5 | 56$ | = (200+20*4)/5
| 6 | 50$ | = (200+20*5)/6
+-----+---------+
But after six numbers don't round that nicely, so this is just a partial solution. Hope it helps you anyway. :)

product are not being assigned to categories via magmi

I am using magmi to upload the product it is working fine product are being uploaded.
Only one problem they are not showing up at front end but they are showing up in admin
when i try to find the reason I find that products are not being assigned to any category when i did that manually they are showing up at fronted.
Any body can help ?
Here is a sample of my CSV
sku _store _attribute_set _type _category _root_category _product_websites ada_compliant backplate_dimension base_dimension brand bulb_included bulb_type bulb_wattage canopy_dimension carton_height carton_length carton_width collection1 cost country_of_manufacture country_orgin created_at custom_design custom_design_from custom_design_to custom_layout_update depth description designer diameter dimension enable_googlecheckout energy extension finish finish1 gallery gender gift_message_available harddrive_speed hardrive has_options height height_1 image image_label in_depth lamping length manufacturer1 max_resolution media_gallery megapixels memory meta_description meta_keyword meta_title minimal_price model msrp msrp_display_actual_price_type msrp_enabled name news_from_date news_to_date no_bulbs options_container page_layout price processor ram_size required_options response_time room screensize shade_color shade_dimension shade_material shape shirt_size shoe_size shoe_type short_description small_image small_image_label special_from_date special_price special_to_date status style switch tax_class_id thumbnail thumbnail_label updated_at url_key url_path visibility weight width qty min_qty use_config_min_qty is_qty_decimal backorders use_config_backorders min_sale_qty use_config_min_sale_qty max_sale_qty use_config_max_sale_qty is_in_stock notify_stock_qty use_config_notify_stock_qty manage_stock use_config_manage_stock stock_status_changed_auto use_config_qty_increments qty_increments use_config_enable_qty_inc enable_qty_increments is_decimal_divided _links_related_sku _links_related_position _links_crosssell_sku _links_crosssell_position _links_upsell_sku _links_upsell_position _associated_sku _associated_default_qty _associated_position _tier_price_website _tier_price_customer_group _tier_price_qty _tier_price_price _group_price_website _group_price_customer_group _group_price_price _media_attribute_id _media_image _media_lable _media_position _media_is_disabled
EP777777-81 admin Default simple Wall Lights/Wall Sconces base No Maxim Lighting No Medium base bulbs 100 29.72 33.66 10.43 Basix 170 Contemporary collection with sweeping arms and clean lines. Offered in Ice glass and Satin Nickel finish or Wilshire glass and Oil Rubbed Bronze finish. Maxim Lighting 31.5 H x 32 W x L Dry Locations Satin Nickel 1 31.5 /10001CLPC.jpg Basix 9-Light Chandelier Maxim Lighting 0 Basix 9-Light Chandelier7777 Ceiling Lights, Chandeliers, lighting, lights, Maxim Lighting Maxim Lighting Basix 9-Light Chandelier $510.00 Basix 9-Light Chandelier9999 9 255 Basix 9-Light Chandelier /10001CLPC.jpg Basix 9-Light Chandelier 1 Contemporary 2 /10001CLPC.jpg Basix 9-Light Chandelier 4 26 32 10 0 1 0 0 1 1 1 100 1 1 1 0 1 0 1 0 1 0 0
I had the same problem.
BUT i used the magmi classes into an personal project, not using the magmi interface.
I solved my problem by adding in the product data array the "category_ids"=> "2" . This is the id of the category.
It may not help you, but may help others.
Looking at your CSV, some of your column names are incorrect (including Category)
For example:
_store _attribute_set _type _category _product_websites
Should be:
store attribute_set type category websites
You can see the required column names at Magmi: Import New Products
Also ensure you have the On the fly category creator/importer plugin enabled in your Magmi configuration, and that your Category column values follow the format outlined in the documentation.
Try naming the field "categories" instead of "category"

Resources