# AGPLv3 sysmocom s.f.m.c. GmbH module Spree class Calculator::SysmocomValueCalculator < Calculator def self.description I18n.t(:sysmocom_value_based) end ZONE1 = { "AT" => 1, "BE" => 1, "BG" => 1, "HR" => 1, "CZ" => 1, "DK" => 1, "EE" => 1, "FI" => 1, "FR" => 1, "GR" => 1, "HU" => 1, "IE" => 1, "IT" => 1, "LV" => 1, "LT" => 1, "LU" => 1, "MT" => 1, "MC" => 1, "NL" => 1, "PL" => 1, "PT" => 1, "RO" => 1, "SK" => 1, "SI" => 1, "ES" => 1, "SE" => 1 }.freeze() ZONE2 = { "CH" => 1, "GB" => 1 }.freeze() ZONE3 = { "AL" => 1, "AD" => 1, "BY" => 1, "BA" => 1, "CY" => 1, "FO" => 1, "GE" => 1, "GI" => 1, "GL" => 1, "GG" => 1, "VA" => 1, "IS" => 1, "JE" => 1, "KZ" => 1, "LI" => 1, "MK" => 1, "MD" => 1, "ME" => 1, "NO" => 1, "SM" => 1, "RS" => 1, "TR" => 1, "UA" => 1, "AX" => 1 }.freeze ZONE4 = { "RU" => 1 }.freeze() ZONE5 = { "US" => 1 }.freeze() ZONE6 = { "DZ" => 1, "AM" => 1, "AZ" => 1, "CA" => 1, "EG" => 1, "IL" => 1, "JO" => 1, "KZ" => 1, "LB" => 1, "LY" => 1, "MA" => 1, "PS" => 1, "PM" => 1, "SY" => 1, "TN" => 1 }.freeze() ZONE7 = { "CN" => 1 }.freeze() def total_weight(o) weight = 0 o.line_items.each do |li| weight += li.quantity + li.variant.weight end return weight end def insurance_cost_intl(value) # Service Hoeherversicherung International stand 1.1.2019 if value <= 500 return 0 elsif value <= 1000 return 14 elsif value <= 2000 return 28 elsif value <= 3000 return 42 elsif value <= 4000 return 56 elsif value <= 5000 return 70 else return 99999 end # maximum insured value 5000 EUR end def insurance_cost_DE(value) if value <= 500 return 0 elsif value <= 2500 return 6 elsif value <= 25000 return 18 else return 99999 end end # we choose pricing between 2kg and 5kg def price_germany(value, weight) if weight < 2000 price = 4.99 elsif weight < 5000 price = 5.99 elsif weight < 10000 price = 8.49 elsif weight < 31500 price = 16.49 else price = 99999 end return price + insurance_cost_DE(value) end # We assume a 5kg package in all zones below def price_package_zone1(value, weight) if weight < 2000 price = 13.99 elsif weight < 5000 price = 15.99 elsif weight < 10000 price = 20.99 elsif weight < 20000 price = 21.99 elsif weight < 31500 price = 44.99 else price = 99999 end return price + insurance_cost_intl(value) end def price_package_zone2(value, weight) if weight < 5000 price = 26.90 elsif weight < 10000 price = 34.99 elsif weight < 20000 price = 48.99 elsif weight < 31500 price = 55.99 else price = 99999 end return price + insurance_cost_intl(value) end def price_package_zone3(value, weight) if weight < 5000 price = 29.99 elsif weight < 10000 price = 37.99 elsif weight < 20000 price = 52.99 elsif weight < 31500 price = 60.99 else price = 99999 end return price + insurance_cost_intl(value) end def price_package_zone4(value, weight) if weight < 5000 price = 30.99 elsif weight < 10000 price = 37.99 elsif weight < 20000 price = 54.99 else price = 99999 end return price + insurance_cost_intl(value) end def price_package_zone5(value, weight) if weight < 5000 price = 36.99 elsif weight < 10000 price = 53.99 elsif weight < 20000 price = 75.99 elsif weight < 31500 price = 105.99 else price = 99999 end return price + insurance_cost_intl(value) end def price_package_zone6(value, weight) if weight < 5000 price = 37.99 elsif weight < 10000 price = 51.99 elsif weight < 20000 price = 71.99 elsif weight < 31500 price = 98.99 else price = 99999 end return price + insurance_cost_intl(value) end def price_package_zone7(value, weight) if weight < 5000 price = 42.99 elsif weight < 10000 price = 58.99 elsif weight < 20000 price = 94.99 elsif weight < 31500 price = 125.99 else price = 99999 end return price + insurance_cost_intl(value) end def price_package_zone8(value, weight) if weight < 5000 price = 45.99 elsif weight < 10000 price = 61.99 elsif weight < 20000 price = 100.99 elsif weight < 31500 price = 131.99 else price = 99999 end return price + insurance_cost_intl(value) end def total_value_no_tax(o) item_total = o.line_items.map(&:amount).sum item_total end def extract_iso_code(o) if o.kind_of?(Spree::Shipment) return o.address.country.iso end return o.ship_address.country.iso end def compute(object) # This could be more than an order but not right now shipping_value = total_value_no_tax(object) weight = total_weight(object) iso_code = extract_iso_code(object) # Go through the zones by name... if iso_code == 'DE' return price_germany(shipping_value, weight) elsif ZONE1.has_key?(iso_code) return price_package_zone1(shipping_value, weight) elsif ZONE2.has_key?(iso_code) return price_package_zone2(shipping_value, weight) elsif ZONE3.has_key?(iso_code) return price_package_zone3(shipping_value, weight) elsif ZONE4.has_key?(iso_code) return price_package_zone4(shipping_value, weight) elsif ZONE5.has_key?(iso_code) return price_package_zone5(shipping_value, weight) elsif ZONE6.has_key?(iso_code) return price_package_zone6(shipping_value, weight) elsif ZONE7.has_key?(iso_code) return price_package_zone7(shipping_value, weight) else return price_package_zone8(shipping_value, weight) end end end end