Skip to content

Commit

Permalink
Merge branch 'hotfix'
Browse files Browse the repository at this point in the history
  • Loading branch information
DeveloperMetal committed Aug 9, 2019
2 parents a806a27 + 9f4877c commit 1421850
Show file tree
Hide file tree
Showing 11 changed files with 450 additions and 87 deletions.
2 changes: 1 addition & 1 deletion shipment_management/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

__version__ = '2.0.13'
__version__ = '2.0.14'

99 changes: 59 additions & 40 deletions shipment_management/api.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
from __future__ import unicode_literals

import json
from math import ceil

import frappe
from provider_fedex import get_fedex_packages_rate
from awesome_cart.compat.customer import get_current_customer
from utils import get_country_code
from math import ceil
import json

from dti_devtools.debug import pretty_json

VALID_PACKAGING_TYPES = (
"FEDEX_10KG_BOX",
"FEDEX_25KG_BOX",
"FEDEX_BOX",
"FEDEX_ENVELOPE",
"FEDEX_PAK",
"FEDEX_TUBE",
"YOUR_PACKAGING"
)

@frappe.whitelist()
def get_rates_for_doc(doc, address=None, address_obj=None):
Expand Down Expand Up @@ -84,15 +73,14 @@ def get_rates(from_address, to_address, items=None, doc=None, packaging_type="YO
package["insured_amount"] = insured_amount
packages.append(package)

# to try and keep some form of standardization we'll minimally require
# to try and keep some form of standardization we'll minimally require
# a weight_value. Any other values will be passed as is to the rates service.
surcharge = 0
for package in packages:
if package.get("weight_value", None) is None or \
package.get("weight_units", None) is None:
if package.get("weight_value") is None or package.get("weight_units") is None:
raise frappe.exceptions.ValidationError("Missing weight_value data")

#if not package.get("group_package_count"):
# if not package.get("group_package_count"):
# keep count on 1 as we don't care about package groups
package["group_package_count"] = 1

Expand All @@ -104,11 +92,33 @@ def get_rates(from_address, to_address, items=None, doc=None, packaging_type="YO

surcharge = surcharge + package.get("surcharge", 0)

# check item conditions for applying Fedex One Rate pricing
rate_settings = frappe.get_single("Shipment Rate Settings")
RecipientCountryCode = get_country_code(to_address.get("country"))

flat_rate = False
signature_option = "DIRECT"
packaging = packaging_type

if RecipientCountryCode.lower() == "us": # One Rate only applies for intra-US deliveries
flat_rate_items = {item.item: item.max_qty for item in rate_settings.items}
for item in items:
if item.get("qty", 0) < flat_rate_items.get(item.get("item_code"), 0):
flat_rate = True
signature_option = None
packaging = frappe.db.get_value("Shipment Rate Item Settings", {"item": item.get("item_code")}, "packaging")
packaging = frappe.db.get_value("Shipping Package", packaging, "box_code")
else:
flat_rate = False
signature_option = "DIRECT"
packaging = packaging_type
break

# form rate request arguments
rate_exceptions = []
args = dict(
DropoffType='REGULAR_PICKUP',
PackagingType=packaging_type,
PackagingType=packaging,
EdtRequestType='NONE',
PaymentType='SENDER',
# Shipper
Expand All @@ -121,42 +131,51 @@ def get_rates(from_address, to_address, items=None, doc=None, packaging_type="YO
# Delivery options
package_list=packages,
ignoreErrors=True,
signature_option="DIRECT",
signature_option=signature_option,
exceptions=rate_exceptions,
delivery_date=doc.get("delivery_date") if doc else "",
saturday_delivery=doc.get("saturday_delivery") if doc else ""
saturday_delivery=doc.get("saturday_delivery") if doc else "",
flat_rate=flat_rate
)

upcharge_doc = frappe.get_doc("Shipment Rate Settings", "Shipment Rate Settings")

if to_address:
rates = get_fedex_packages_rate(**args)
rates = get_fedex_packages_rate(**args) or []

# since we're working on v18 of Fedex's rate service, which is incompatible with
# getting One Rate and non-One Rate prices in the same query, we do another query
# to get the non-One Rate prices and update the existing rates
if flat_rate:
non_flat_rate_args = args.copy()
non_flat_rate_args.update({"flat_rate": False, "signature_option": "DIRECT", "PackagingType": packaging_type})
flat_rates = get_fedex_packages_rate(**non_flat_rate_args) or []
rates.extend(flat_rates)
else:
rates = []

sorted_rates = []
if rates:
sorted_rates = []
unique_labels = []
for rate in sorted(rates, key=lambda rate: rate["fee"]):
rate["fee"] = rate["fee"] + surcharge

if upcharge_doc.upcharge_type == "Percentage":
rate["fee"] = rate["fee"] + (rate["fee"] * (upcharge_doc.upcharge/100))
elif upcharge_doc.upcharge_type == "Actual":
rate["fee"] = rate["fee"] + upcharge_doc.upcharge
# remove duplicate shipping methods
if rate["label"] in unique_labels:
continue

rate['fee'] = round(rate['fee'], 2)
# disallow FEDEX GROUND for Canada
if RecipientCountryCode.lower() == "ca" and rate['label'] == "FEDEX GROUND":
continue

sorted_rates.append(rate)
unique_labels.append(rate["label"])
rate["fee"] += surcharge

final_sorted_rates = sorted_rates
if rate_settings.upcharge_type == "Percentage":
rate["fee"] += (rate["fee"] * (rate_settings.upcharge / 100))
elif rate_settings.upcharge_type == "Actual":
rate["fee"] += rate_settings.upcharge

# Disallow FEDEX GROUND for Canada
if RecipientCountryCode.lower() == "ca":
for rate in sorted_rates:
if rate['label'] == "FEDEX GROUND":
final_sorted_rates.remove(rate)
rate['fee'] = round(rate['fee'], 2)
sorted_rates.append(rate)

return final_sorted_rates
return sorted_rates
else:
msg = "Could not get rates, please check your Shipping Address"
if len(rate_exceptions) > 0:
Expand Down
97 changes: 57 additions & 40 deletions shipment_management/provider_fedex.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,8 @@ def get_fedex_packages_rate(international=False,
signature_option=None,
exceptions=None,
delivery_date=None,
saturday_delivery=False):
saturday_delivery=False,
flat_rate=False):

"""
:param international:
Expand Down Expand Up @@ -661,75 +662,92 @@ def get_fedex_packages_rate(international=False,
"""

# Initiate Fedex request
if international:
rate = FedexInternationalRateServiceRequest(CONFIG_OBJ)
else:
rate = FedexRateServiceRequest(CONFIG_OBJ)

# Set Fedex shipping details
rate.RequestedShipment.DropoffType = DropoffType
rate.RequestedShipment.ServiceType = ServiceType
rate.RequestedShipment.PackagingType = PackagingType

# Set shipper address details
rate.RequestedShipment.Shipper.Address.StateOrProvinceCode = ShipperStateOrProvinceCode
rate.RequestedShipment.Shipper.Address.PostalCode = ShipperPostalCode
rate.RequestedShipment.Shipper.Address.CountryCode = ShipperCountryCode

# Set reciever address details
if RecipientStateOrProvinceCode:
rate.RequestedShipment.Recipient.Address.StateOrProvinceCode = RecipientStateOrProvinceCode
rate.RequestedShipment.Recipient.Address.PostalCode = RecipientPostalCode
rate.RequestedShipment.Recipient.Address.CountryCode = RecipientCountryCode
rate.RequestedShipment.Recipient.Address.Residential = IsResidential

# Set payer details
rate.RequestedShipment.EdtRequestType = EdtRequestType
rate.RequestedShipment.ShippingChargesPayment.PaymentType = PaymentType

if saturday_delivery:
# Set special services, if applicable

# Fedex One Rate
if flat_rate:
rate.RequestedShipment.SpecialServicesRequested.SpecialServiceTypes = "FEDEX_ONE_RATE"

# Fedex Saturday Delivery
elif saturday_delivery:
if not delivery_date:
frappe.throw(_("Please specify Ship Date for Saturday Delivery"))

delivery_datetime = frappe.utils.get_datetime(delivery_date)
rate.RequestedShipment.SpecialServicesRequested.SpecialServiceTypes = "SATURDAY_DELIVERY"
rate.RequestedShipment.ShipTimestamp = delivery_datetime.isoformat()

# Create Fedex shipments for each package
for package in package_list:
package1_weight = rate.create_wsdl_object_of_type('Weight')

package1_weight.Value = package["weight_value"]
package1_weight.Units = package["weight_units"]

package1 = rate.create_wsdl_object_of_type('RequestedPackageLineItem')
package1.Weight = package1_weight

package1.GroupPackageCount = package["group_package_count"]

if package.get("packaging_type"):
# Set package weights
pkg_weight = rate.create_wsdl_object_of_type('Weight')
pkg_weight.Value = package["weight_value"]
pkg_weight.Units = package["weight_units"]

# Set package content details
pkg_obj = rate.create_wsdl_object_of_type('RequestedPackageLineItem')
pkg_obj.Weight = pkg_weight
pkg_obj.GroupPackageCount = package["group_package_count"]

# Set packaging details
if flat_rate:
rate.RequestedShipment.PackagingType = PackagingType
pkg_obj.PhysicalPackaging = frappe.db.get_value("Shipping Package", {"box_code": PackagingType}, "physical_packaging")
elif package.get("packaging_type"):
box_doc = frappe.get_doc("Shipping Package", package.get("packaging_type"))
rate.RequestedShipment.PackagingType = box_doc.box_code

package1.PhysicalPackaging = box_doc.physical_packaging
pkg_obj.PhysicalPackaging = box_doc.physical_packaging

if box_doc.box_code == "YOUR_PACKAGING":
package_dim = rate.create_wsdl_object_of_type("Dimensions")
package_dim.Length = cint(box_doc.length)
package_dim.Width = cint(box_doc.width)
package_dim.Height = cint(box_doc.height)
package_dim.Units = "IN"
package1.Dimensions = package_dim

package_insure = rate.create_wsdl_object_of_type('Money')
package_insure.Currency = "USD"
package_insure.Amount = package["insured_amount"]

package1.InsuredValue = package_insure

pkg_dim = rate.create_wsdl_object_of_type("Dimensions")
pkg_dim.Length = cint(box_doc.length)
pkg_dim.Width = cint(box_doc.width)
pkg_dim.Height = cint(box_doc.height)
pkg_dim.Units = "IN"
pkg_obj.Dimensions = pkg_dim

# Set insurance amounts
pkg_insurance = rate.create_wsdl_object_of_type('Money')
pkg_insurance.Currency = "USD"
pkg_insurance.Amount = package["insured_amount"]
pkg_obj.InsuredValue = pkg_insurance

# Set additional surcharges
if signature_option:
# Additional Surcharges
package1.SpecialServicesRequested.SpecialServiceTypes = 'SIGNATURE_OPTION'
package1.SpecialServicesRequested.SignatureOptionDetail.OptionType = signature_option
pkg_obj.SpecialServicesRequested.SpecialServiceTypes = 'SIGNATURE_OPTION'
pkg_obj.SpecialServicesRequested.SignatureOptionDetail.OptionType = signature_option

rate.add_package(package1)
rate.add_package(pkg_obj)

try:
# Get rates for all the packages
rate.send_request()
except Exception as e:
print(e)
Expand Down Expand Up @@ -759,19 +777,18 @@ def get_fedex_packages_rate(international=False,

try:
for service in data["RateReplyDetails"]:
rates.append({'fee' :
service['RatedShipmentDetails'][0]["ShipmentRateDetail"]['TotalNetChargeWithDutiesAndTaxes']['Amount'],
'label' : service['ServiceType'].replace("_", " "),
'name' : service['ServiceType']})
rates.append({
'fee': service['RatedShipmentDetails'][0]['ShipmentRateDetail']['TotalNetChargeWithDutiesAndTaxes']['Amount'],
'label' : service['ServiceType'].replace("_", " "),
'name' : service['ServiceType'],
'special_rates_applied': service['RatedShipmentDetails'][0]['ShipmentRateDetail'].get('SpecialRatingApplied', [])
})
except KeyError as e:

if exceptions is not None:
exceptions.append({"type": "keyerror", "exception": e})


if not ignoreErrors:
frappe.throw(data)
return None
return

if single_rate:
return rates[0]
Expand Down
Empty file.
Loading

0 comments on commit 1421850

Please sign in to comment.