Skip to content

Commit

Permalink
Merge pull request #26 from PurplShip/HotFixrc6
Browse files Browse the repository at this point in the history
Hot fixrc6
  • Loading branch information
danh91 committed Nov 20, 2018
2 parents 0c7644c + dfd1b08 commit 7f8e135
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 39 deletions.
11 changes: 7 additions & 4 deletions purplship/mappers/dhl/dhl_mapper/partials/rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ def _extract_quote(self, quotes: List[T.QuoteDetails], qtdshpNode: 'XMLElement')

def create_dct_request(self, payload: T.shipment_request) -> Req.DCTRequest:
default_product_code = Product.EXPRESS_WORLDWIDE_DOC if payload.shipment.is_document else Product.EXPRESS_WORLDWIDE
product_code = Product[payload.shipment.services] if payload.shipment.services != None else default_product_code
products = (
[Product[svc] for svc in payload.shipment.services if svc in Product.__members__] +
[default_product_code]
)
is_dutiable = payload.shipment.declared_value != None
default_packaging_type = DCTPackageType.SM if payload.shipment.is_document else DCTPackageType.BOX
options = (
Expand Down Expand Up @@ -114,15 +117,15 @@ def create_dct_request(self, payload: T.shipment_request) -> Req.DCTRequest:
AcctPickupCloseTime=payload.shipment.extra.get('AcctPickupCloseTime'),
QtdShp=[
ReqType.QtdShpType(
GlobalProductCode=product_code.value,
LocalProductCode=product_code.value,
GlobalProductCode=product.value,
LocalProductCode=product.value,
QtdShpExChrg=[
ReqType.QtdShpExChrgType(
SpecialServiceType=svc.value,
LocalSpecialServiceType=None
) for svc in options
] if len(options) > 0 else None
)
) for product in products
]
),
Dutiable=ReqType.DCTDutiable(
Expand Down
9 changes: 6 additions & 3 deletions purplship/mappers/dhl/dhl_mapper/partials/shipment.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ def _extract_shipment(self, shipmentResponseNode) -> T.ShipmentDetails:
def create_dhlshipment_request(self, payload: T.shipment_request) -> ShipReq.ShipmentRequest:
is_dutiable = payload.shipment.declared_value != None
default_product_code = Product.EXPRESS_WORLDWIDE_DOC if payload.shipment.is_document else Product.EXPRESS_WORLDWIDE
product_code = Product[payload.shipment.services] if payload.shipment.services != None else default_product_code
product = (
[Product[svc] for svc in payload.shipment.services if svc in Product.__members__] +
[default_product_code]
)[0]
default_packaging_type = PackageType.Document if payload.shipment.is_document else PackageType.Your_packaging
options = (
[Service[svc] for svc in payload.shipment.options if svc in Service.__members__] +
Expand Down Expand Up @@ -167,8 +170,8 @@ def create_dhlshipment_request(self, payload: T.shipment_request) -> ShipReq.Shi
IsDutiable= "Y" if is_dutiable else "N",
InsuredAmount=payload.shipment.insured_amount,
DoorTo=payload.shipment.extra.get('DoorTo'),
GlobalProductCode=product_code.value,
LocalProductCode=product_code.value,
GlobalProductCode=product.value,
LocalProductCode=product.value,
Contents=payload.shipment.extra.get('Contents') or "..."
),
EProcShip=payload.shipment.extra.get('EProcShip'),
Expand Down
71 changes: 48 additions & 23 deletions purplship/mappers/ups/ups_mapper/partials/rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,48 @@ def _extract_freight_rate(self, rates: List[T.QuoteDetails], detailNode: 'XMLEle
]

def parse_package_rate_response(self, response: 'XMLElement') -> Tuple[List[T.QuoteDetails], List[T.Error]]:
rate_replys = response.xpath('.//*[local-name() = $name]', name="RateResponse")
rate_replys = response.xpath('.//*[local-name() = $name]', name="RatedShipment")
rates = reduce(self._extract_package_rate, rate_replys, [])
return (rates, self.parse_error_response(response))

def _extract_package_rate(self, rates: List[T.QuoteDetails], detailNode: 'XMLElement') -> List[T.QuoteDetails]:
detail = PRate.RateResponse()
detail.build(detailNode)
rate = PRate.RatedShipmentType()
rate.build(detailNode)

total_charge = [r for r in detail.Rate if r.Type.Code == 'AFTR_DSCNT'][0]
Discounts_ = [T.ChargeDetails(name=r.Type.Code, currency=r.Factor.UnitOfMeasurement.Code, amount=float(r.Factor.Value)) for r in detail.Rate if r.Type.Code == 'DSCNT']
Surcharges_ = [T.ChargeDetails(name=r.Type.Code, currency=r.Factor.UnitOfMeasurement.Code, amount=float(r.Factor.Value)) for r in detail.Rate if r.Type.Code not in ['DSCNT', 'AFTR_DSCNT', 'DSCNT_RATE', 'LND_GROSS']]
extra_charges = Discounts_ + Surcharges_
if rate.NegotiatedRateCharges != None:
total_charges = rate.NegotiatedRateCharges.TotalChargesWithTaxes or rate.NegotiatedRateCharges.TotalCharge
taxes = rate.NegotiatedRateCharges.TaxCharges
itemized_charges = rate.NegotiatedRateCharges.ItemizedCharges + taxes
else:
total_charges = rate.TotalChargesWithTaxes or rate.TotalCharges
taxes = rate.TaxCharges
itemized_charges = rate.ItemizedCharges + taxes

extra_charges = itemized_charges + [ rate.ServiceOptionsCharges ]

return rates + [
T.QuoteDetails(
carrier=self.client.carrier_name,
currency=detail.TotalShipmentCharge.CurrencyCode,
service_name=detail.Service.Description,
service_type=detail.Service.Code,
base_charge=float(detail.TotalShipmentCharge.MonetaryValue),
total_charge=float(total_charge.Factor.Value or 0),
duties_and_taxes=reduce(lambda r, c: r + c.amount, Surcharges_, 0),
discount=reduce(lambda r, c: r + c.amount, Discounts_, 0),
extra_charges=extra_charges
currency=rate.TransportationCharges.CurrencyCode,
service_name=rate.Service.Description,
service_type=rate.Service.Code,
base_charge=float(rate.TransportationCharges.MonetaryValue),
total_charge=float(total_charges.MonetaryValue),
duties_and_taxes=reduce(
lambda total, charge: total + float(charge.MonetaryValue),
taxes or [],
0
),
discount=None,
extra_charges=reduce(
lambda total, charge: total + [T.ChargeDetails(
name=charge.Code,
amount=float(charge.MonetaryValue),
currency=charge.CurrencyCode
)],
[charge for charge in extra_charges if charge != None],
[]
)
)
]

Expand Down Expand Up @@ -167,6 +186,12 @@ def create_package_rate_request(self, payload: T.shipment_request) -> PRate.Rate
[RatingServiceCode[svc] for svc in payload.shipment.services if svc in RatingServiceCode.__members__] +
[RatingServiceCode.UPS_Worldwide_Express]
)[0]
payment_details_provided = (
all((payload.shipment.paid_by, payload.shipment.payment_account_number)) or
(payload.shipment.paid_by == 'SENDER' and payload.shipper.account_number != None) or
(payload.shipment.paid_by == 'RECIPIENT' and payload.recipient.account_number != None)
)
is_negotiated_rate = any((payload.shipment.payment_account_number, payload.shipper.account_number))
return PRate.RateRequest(
Request=Common.RequestType(
RequestOption=payload.shipment.extra.get('RequestOption') or ["Rate"],
Expand Down Expand Up @@ -235,7 +260,7 @@ def create_package_rate_request(self, payload: T.shipment_request) -> PRate.Rate
AccountNumber=payload.shipment.payment_account_number or payload.shipper.account_number
) if payload.shipment.paid_by == 'SENDER' else None,
BillReceiver=PRate.BillReceiverChargeType(
AccountNumber=payload.recipient.account_number,
AccountNumber=payload.shipment.payment_account_number or payload.recipient.account_number,
Address=PRate.BillReceiverAddressType(
PostalCode=payload.recipient.postal_code
)
Expand All @@ -250,22 +275,22 @@ def create_package_rate_request(self, payload: T.shipment_request) -> PRate.Rate
)
],
SplitDutyVATIndicator=None
) if any((payload.shipment.paid_by, payload.shipment.payment_account_number)) else None,
) if payment_details_provided else None,
FRSPaymentInformation=None,
FreightShipmentInformation=None,
GoodsNotInFreeCirculationIndicator=None,
Service=PRate.CodeDescriptionType(Code=service.value, Description=None),
Service=PRate.UOMCodeDescriptionType(Code=service.value, Description=None),
NumOfPieces=payload.shipment.total_items,
ShipmentTotalWeight=payload.shipment.total_weight,
DocumentsOnlyIndicator="" if payload.shipment.is_document else None,
Package=[
PRate.PackageType(
PackagingType=PRate.CodeDescriptionType(
PackagingType=PRate.UOMCodeDescriptionType(
Code=RatingPackagingType[pkg.packaging_type or "BOX"].value,
Description=None
),
Dimensions=PRate.DimensionsType(
UnitOfMeasurement=PRate.CodeDescriptionType(
UnitOfMeasurement=PRate.UOMCodeDescriptionType(
Code=DimensionUnit[payload.shipment.dimension_unit].value,
Description=None
),
Expand All @@ -275,7 +300,7 @@ def create_package_rate_request(self, payload: T.shipment_request) -> PRate.Rate
),
DimWeight=pkg.extra.get('DimWeight'),
PackageWeight=PRate.PackageWeightType(
UnitOfMeasurement=PRate.CodeDescriptionType(
UnitOfMeasurement=PRate.UOMCodeDescriptionType(
Code=WeightUnit[payload.shipment.weight_unit].value,
Description=None
),
Expand All @@ -289,12 +314,12 @@ def create_package_rate_request(self, payload: T.shipment_request) -> PRate.Rate
ShipmentServiceOptions=None,
ShipmentRatingOptions=(lambda rating:
PRate.ShipmentRatingOptionsType(
NegotiatedRatesIndicator="" if 'NegotiatedRatesIndicator' in rating else None,
NegotiatedRatesIndicator="" if is_negotiated_rate else None,
FRSShipmentIndicator="" if 'FRSShipmentIndicator' in rating else None,
RateChartIndicator="" if 'RateChartIndicator' in rating else None,
UserLevelDiscountIndicator="" if 'UserLevelDiscountIndicator' in rating else None
)
)(payload.shipment.extra.get('ShipmentRatingOptions')) if 'ShipmentRatingOptions' in payload.shipment.extra else None,
)(payload.shipment.extra.get('ShipmentRatingOptions') or {}) if 'ShipmentRatingOptions' in payload.shipment.extra or is_negotiated_rate else None,
InvoiceLineTotal=None,
RatingMethodRequestedIndicator=None,
TaxInformationIndicator=None,
Expand Down
2 changes: 1 addition & 1 deletion purplship/mappers/ups/ups_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def get_quotes(self, RateRequest_: Union[RateRequest, FreightRateRequest]) -> "X
header_child_name='UPSSecurity',
body_child_name=body_child_name_,
body_child_prefix=body_child_prefix_
)
).replace('common:Code', 'rate:Code')
result = http(
url=url_,
data=bytearray(xmlStr, "utf-8"),
Expand Down
4 changes: 2 additions & 2 deletions tests/dhl/quote.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,8 @@ def test_parse_quote_vol_weight_higher_response(self):
</Pieces>
<IsDutiable>Y</IsDutiable>
<QtdShp>
<GlobalProductCode>D</GlobalProductCode>
<LocalProductCode>D</LocalProductCode>
<GlobalProductCode>P</GlobalProductCode>
<LocalProductCode>P</LocalProductCode>
<QtdShpExChrg>
<SpecialServiceType>II</SpecialServiceType>
</QtdShpExChrg>
Expand Down
2 changes: 1 addition & 1 deletion tests/dhl/shipment.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ def test_parse_shipment_response(self):
"duty_payment_account": "123456789",
"declared_value": 200.00,
"options": ["Paperless_Trade"],
"services": "EXPRESS_WORLDWIDE",
"services": ["EXPRESS_WORLDWIDE"],
"doc_images": [
{
"type": "CIN",
Expand Down
44 changes: 39 additions & 5 deletions tests/ups/quote.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ def setUp(self):
def test_create_quote_request(self):
payload = Quote.create(**rate_req_data)
RateRequest_ = proxy.mapper.create_quote_request(payload)
self.assertEqual(export(RateRequest_), export(self.RateRequest))
self.assertEqual(
export(RateRequest_),
export(self.RateRequest).replace('common:Code', 'rate:Code')
)

def test_create_freight_quote_request(self):
shipper = {
Expand Down Expand Up @@ -53,6 +56,12 @@ def test_parse_quote_response(self):
to_xml(FreightRateResponseXML))
self.assertEqual(jsonify(parsed_response),
jsonify(ParsedFreightRateResponse))

def test_parse_package_quote_response(self):
parsed_response = proxy.mapper.parse_quote_response(
to_xml(RateResponseXML))
self.assertEqual(jsonify(parsed_response),
jsonify(ParsedRateResponse))

def test_parse_quote_error(self):
parsed_response = proxy.mapper.parse_quote_response(
Expand Down Expand Up @@ -139,6 +148,28 @@ def test_parse_quote_missing_args_error(self):
[]
]

ParsedRateResponse = [
[
{
'base_charge': 9.86,
'carrier': 'UPS',
'currency': 'USD',
'delivery_date': None,
'discount': None,
'duties_and_taxes': 0,
'extra_charges': [
{'amount': 0.0, 'currency': 'USD', 'name': None}
],
'pickup_date': None,
'pickup_time': None,
'service_name': '',
'service_type': '03',
'total_charge': 9.86
}
],
[]
]


QuoteParsingError = """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
Expand Down Expand Up @@ -505,27 +536,30 @@ def test_parse_quote_missing_args_error(self):
</rate:Address>
</rate:ShipFrom>
<rate:Service>
<common:Code>03</common:Code>
<rate:Code>03</rate:Code>
</rate:Service>
<rate:Package>
<rate:PackagingType>
<common:Code>02</common:Code>
<rate:Code>02</rate:Code>
</rate:PackagingType>
<rate:Dimensions>
<rate:UnitOfMeasurement>
<common:Code>IN</common:Code>
<rate:Code>IN</rate:Code>
</rate:UnitOfMeasurement>
<rate:Length>10</rate:Length>
<rate:Width>3</rate:Width>
<rate:Height>3</rate:Height>
</rate:Dimensions>
<rate:PackageWeight>
<rate:UnitOfMeasurement>
<common:Code>LBS</common:Code>
<rate:Code>LBS</rate:Code>
</rate:UnitOfMeasurement>
<rate:Weight>4.0</rate:Weight>
</rate:PackageWeight>
</rate:Package>
<rate:ShipmentRatingOptions>
<rate:NegotiatedRatesIndicator></rate:NegotiatedRatesIndicator>
</rate:ShipmentRatingOptions>
</rate:Shipment>
</rate:RateRequest>
</tns:Body>
Expand Down

0 comments on commit 7f8e135

Please sign in to comment.