From e6370f886c4660e8316695aecc548bef33711b27 Mon Sep 17 00:00:00 2001 From: Daniel K Date: Thu, 14 Dec 2023 09:41:38 -0800 Subject: [PATCH] (consolidate) allied_express integration with live tests --- .../karrio/mappers/allied_express/proxy.py | 20 +++++++-- .../karrio/providers/allied_express/error.py | 8 +++- .../karrio/providers/allied_express/rate.py | 12 +++-- .../allied_express/shipment/create.py | 12 +++-- .../providers/allied_express/tracking.py | 4 +- .../karrio/providers/allied_express/utils.py | 30 +++++++++---- .../tests/allied_express/test_rate.py | 44 +++++++++++++++++++ packages/ui/components/expanded-sidebar.tsx | 2 +- packages/ui/modals/connect-provider-modal.tsx | 8 ++++ 9 files changed, 110 insertions(+), 30 deletions(-) diff --git a/modules/connectors/allied_express/karrio/mappers/allied_express/proxy.py b/modules/connectors/allied_express/karrio/mappers/allied_express/proxy.py index c6d3ed9aea..65f9c3b47a 100644 --- a/modules/connectors/allied_express/karrio/mappers/allied_express/proxy.py +++ b/modules/connectors/allied_express/karrio/mappers/allied_express/proxy.py @@ -15,7 +15,10 @@ def get_rates(self, request: lib.Serializable) -> lib.Deserializable[str]: data=request.serialize(), trace=self.trace_as("json"), method="POST", - headers={"Authorization": f"Basic {self.settings.authorization}"}, + headers={ + "Authorization": f"Basic {self.settings.authorization}", + "Content-Type": "application/json", + }, ) return lib.Deserializable(response, provider_utils.parse_response) @@ -26,7 +29,10 @@ def create_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]: data=request.serialize(), trace=self.trace_as("json"), method="POST", - headers={"Authorization": f"Basic {self.settings.authorization}"}, + headers={ + "Authorization": f"Basic {self.settings.authorization}", + "Content-Type": "application/json", + }, ) return lib.Deserializable(response, provider_utils.parse_response, request.ctx) @@ -37,7 +43,10 @@ def cancel_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]: url=f"{self.settings.server_url}/cancelJob/{payload['shipmentno']}/{payload['postalcode']}", trace=self.trace_as("json"), method="POST", - headers={"Authorization": f"Basic {self.settings.authorization}"}, + headers={ + "Authorization": f"Basic {self.settings.authorization}", + "Content-Type": "application/json", + }, ) return lib.Deserializable(response, provider_utils.parse_response) @@ -50,7 +59,10 @@ def get_tracking(self, request: lib.Serializable) -> lib.Deserializable[str]: url=f"{self.settings.server_url}/getShipmentsStatus/{payload['shipmentno']}", trace=self.trace_as("json"), method="POST", - headers={"Authorization": f"Basic {self.settings.authorization}"}, + headers={ + "Authorization": f"Basic {self.settings.authorization}", + "Content-Type": "application/json", + }, ), ), request.serialize(), diff --git a/modules/connectors/allied_express/karrio/providers/allied_express/error.py b/modules/connectors/allied_express/karrio/providers/allied_express/error.py index a3e665ffd1..a74848edf8 100644 --- a/modules/connectors/allied_express/karrio/providers/allied_express/error.py +++ b/modules/connectors/allied_express/karrio/providers/allied_express/error.py @@ -14,7 +14,13 @@ def parse_error_response( errors.append(["500", response.error]) if response.is_error and response.data is not None: - errors.append(["400", response.data["result"]["statusError"]]) + errors.append( + [ + "400", + response.data["result"].get("statusError") + or response.data["result"].get("errors"), + ] + ) return [ models.Message( diff --git a/modules/connectors/allied_express/karrio/providers/allied_express/rate.py b/modules/connectors/allied_express/karrio/providers/allied_express/rate.py index 6f7f61979c..3177685912 100644 --- a/modules/connectors/allied_express/karrio/providers/allied_express/rate.py +++ b/modules/connectors/allied_express/karrio/providers/allied_express/rate.py @@ -78,11 +78,11 @@ def rate_request( request = allied.RateRequestType( bookedBy=shipper.contact, account=settings.account, - instructions=options.instructions.state, + instructions=options.instructions.state or "N/A", itemCount=len(packages), items=[ allied.ItemType( - dangerous=pkg.options.dangerous_good.state, + dangerous=(True if pkg.options.dangerous_good.state else False), height=pkg.height.CM, length=pkg.length.CM, width=pkg.width.CM, @@ -98,7 +98,7 @@ def rate_request( emailAddress=shipper.email, geographicAddress=allied.GeographicAddressType( address1=shipper.address_line1, - address2=shipper.address_line2, + address2=shipper.address_line2 or " ", country=shipper.country_code, postCode=shipper.postal_code, state=shipper.state_code, @@ -112,7 +112,7 @@ def rate_request( emailAddress=recipient.email, geographicAddress=allied.GeographicAddressType( address1=recipient.address_line1, - address2=recipient.address_line2, + address2=recipient.address_line2 or " ", country=recipient.country_code, postCode=recipient.postal_code, state=recipient.state_code, @@ -120,9 +120,7 @@ def rate_request( ), phoneNumber=recipient.phone_number, ), - referenceNumbers=( - [payload.reference] if any(payload.reference or "") else None - ), + referenceNumbers=([payload.reference] if any(payload.reference or "") else []), serviceLevel=(service.value if service else "R"), weight=packages.weight.KG, volume=packages.volume, diff --git a/modules/connectors/allied_express/karrio/providers/allied_express/shipment/create.py b/modules/connectors/allied_express/karrio/providers/allied_express/shipment/create.py index a971b27c7b..ba259a37e3 100644 --- a/modules/connectors/allied_express/karrio/providers/allied_express/shipment/create.py +++ b/modules/connectors/allied_express/karrio/providers/allied_express/shipment/create.py @@ -69,11 +69,11 @@ def shipment_request( request = allied.LabelRequestType( bookedBy=shipper.contact, account=settings.account, - instructions=options.instructions.state, + instructions=options.instructions.state or "N/A", itemCount=len(packages), items=[ allied.ItemType( - dangerous=pkg.options.dangerous_good.state, + dangerous=(True if pkg.options.dangerous_good.state else False), height=pkg.height.CM, length=pkg.length.CM, width=pkg.width.CM, @@ -89,7 +89,7 @@ def shipment_request( emailAddress=shipper.email, geographicAddress=allied.GeographicAddressType( address1=shipper.address_line1, - address2=shipper.address_line2, + address2=shipper.address_line2 or " ", country=shipper.country_code, postCode=shipper.postal_code, state=shipper.state_code, @@ -103,7 +103,7 @@ def shipment_request( emailAddress=recipient.email, geographicAddress=allied.GeographicAddressType( address1=recipient.address_line1, - address2=recipient.address_line2, + address2=recipient.address_line2 or " ", country=recipient.country_code, postCode=recipient.postal_code, state=recipient.state_code, @@ -111,9 +111,7 @@ def shipment_request( ), phoneNumber=recipient.phone_number, ), - referenceNumbers=( - [payload.reference] if any(payload.reference or "") else None - ), + referenceNumbers=([payload.reference] if any(payload.reference or "") else []), weight=packages.weight.KG, volume=packages.volume, serviceLevel=service, diff --git a/modules/connectors/allied_express/karrio/providers/allied_express/tracking.py b/modules/connectors/allied_express/karrio/providers/allied_express/tracking.py index da48102baa..34b7769136 100644 --- a/modules/connectors/allied_express/karrio/providers/allied_express/tracking.py +++ b/modules/connectors/allied_express/karrio/providers/allied_express/tracking.py @@ -57,11 +57,11 @@ def _extract_details( description=description, date=lib.fdate( result.statusBarcodesList.scannnedTimestamp, - "%Y-%m-%dT%H%M%S.%f%z", + "%Y-%m-%dT%H:%M:%S.%f%z", ), time=lib.ftime( result.statusBarcodesList.scannnedTimestamp, - "%Y-%m-%dT%H%M%S.%f%z", + "%Y-%m-%dT%H:%M:%S.%f%z", ), ) ], diff --git a/modules/connectors/allied_express/karrio/providers/allied_express/utils.py b/modules/connectors/allied_express/karrio/providers/allied_express/utils.py index 7851ff78e4..a2f8635194 100644 --- a/modules/connectors/allied_express/karrio/providers/allied_express/utils.py +++ b/modules/connectors/allied_express/karrio/providers/allied_express/utils.py @@ -43,10 +43,11 @@ class AlliedResponse: def parse_response(response: str) -> AlliedResponse: _response = lib.failsafe( lambda: lib.to_dict( - response.replace(": ", "$$ ") - .replace("@xmlns", "xmlns") - .replace(":", "") - .replace("$$ ", ": ") + ( + response.replace("soapenv:", "soapenv") + .replace("@xmlns:", "xmlns") + .replace("ns1:", "ns1") + ) ) ) @@ -67,7 +68,10 @@ def parse_response(response: str) -> AlliedResponse: body=_body, envelope=_envelope, response=_response, - is_error=("statusError" in (_data or {}).get("result", {})), + is_error=( + ("statusError" in (_data or {}).get("result", {})) + or ("errors" in (_data or {}).get("result", {})) + ), ) if "ns1calculatePriceResponse" in _body: @@ -77,7 +81,10 @@ def parse_response(response: str) -> AlliedResponse: body=_body, envelope=_envelope, response=_response, - is_error=("statusError" in (_data or {}).get("result", {})), + is_error=( + ("statusError" in (_data or {}).get("result", {})) + or ("errors" in (_data or {}).get("result", {})) + ), ) if "ns1cancelDispatchJobResponse" in _body: @@ -87,7 +94,11 @@ def parse_response(response: str) -> AlliedResponse: body=_body, envelope=_envelope, response=_response, - is_error=((_data or {}).get("result") != "0"), + is_error=( + ((_data or {}).get("result") != "0") + or ("statusError" in (_data or {}).get("result", {})) + or ("errors" in (_data or {}).get("result", {})) + ), ) if "ns1getLabelResponse" in _body: @@ -97,7 +108,10 @@ def parse_response(response: str) -> AlliedResponse: body=_body, envelope=_envelope, response=_response, - is_error=("statusError" in (_data or {}).get("result", {})), + is_error=( + ("statusError" in (_data or {}).get("result", {})) + or ("errors" in (_data or {}).get("result", {})) + ), ) return AlliedResponse( diff --git a/modules/connectors/allied_express/tests/allied_express/test_rate.py b/modules/connectors/allied_express/tests/allied_express/test_rate.py index be9cd4c54b..0876e80454 100644 --- a/modules/connectors/allied_express/tests/allied_express/test_rate.py +++ b/modules/connectors/allied_express/tests/allied_express/test_rate.py @@ -36,6 +36,15 @@ def test_parse_rate_response(self): self.assertListEqual(lib.to_dict(parsed_response), ParsedRateResponse) + def test_parse_error_response(self): + with patch("karrio.mappers.allied_express.proxy.lib.request") as mock: + mock.return_value = ErrorResponse + parsed_response = ( + karrio.Rating.fetch(self.RateRequest).from_(gateway).parse() + ) + + self.assertListEqual(lib.to_dict(parsed_response), ParsedErrorResponse) + if __name__ == "__main__": unittest.main() @@ -108,6 +117,21 @@ def test_parse_rate_response(self): [], ] +ParsedErrorResponse = [ + [], + [ + { + "carrier_id": "allied_express", + "carrier_name": "allied_express", + "code": "400", + "details": {}, + "message": "Validation failed: java.lang.Exception: Exception thrown in " + "SuburbDAO.getSuburb :java.lang.Exception: No valid JNDI name " + "found for state UM", + } + ], +] + RateRequest = { "account": "ACCOUNT", @@ -153,6 +177,7 @@ def test_parse_rate_response(self): "emailAddress": "test@gmail.com", "geographicAddress": { "address1": "17 VULCAN RD", + "address2": " ", "country": "AU", "postCode": "6155", "state": "WA", @@ -215,3 +240,22 @@ def test_parse_rate_response(self): } } """ + +ErrorResponse = """{ + "soapenv:Envelope": { + "@xmlns:soapenv": "http://schemas.xmlsoap.org/soap/envelope/", + "@xmlns:xsd": "http://www.w3.org/2001/XMLSchema", + "@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance", + "soapenv:Body": { + "ns1:calculatePriceResponse": { + "@xmlns:ns1": "http://neptune.alliedexpress.com.au/ttws-ejb", + "result": { + "errors": "Validation failed: java.lang.Exception: Exception thrown in SuburbDAO.getSuburb :java.lang.Exception: No valid JNDI name found for state UM", + "jobCharge": "0.0", + "totalCharge": "0.0" + } + } + } + } +} +""" diff --git a/packages/ui/components/expanded-sidebar.tsx b/packages/ui/components/expanded-sidebar.tsx index 99bc3f019f..1ac62c5fc1 100644 --- a/packages/ui/components/expanded-sidebar.tsx +++ b/packages/ui/components/expanded-sidebar.tsx @@ -128,7 +128,7 @@ export const ExpandedSidebar: React.FC = () => { - Logs + API Logs diff --git a/packages/ui/modals/connect-provider-modal.tsx b/packages/ui/modals/connect-provider-modal.tsx index 802cef74a2..3c4edd4503 100644 --- a/packages/ui/modals/connect-provider-modal.tsx +++ b/packages/ui/modals/connect-provider-modal.tsx @@ -400,6 +400,13 @@ export const ConnectProviderModal: React.FC = ({ required={field("account_number").required} />} + {field("account").exists && } + {field("billing_account").exists && = ({ function fieldState(carrier_name: CarrierNameType, property: string) { const field = ( ({ + [CarrierSettingsCarrierNameEnum.AlliedExpress]: [["carrier_id", true], ["username", true], ["password", true], ["account", false]], [CarrierSettingsCarrierNameEnum.AmazonShipping]: [["carrier_id", true], ["seller_id", true], ["developer_id", true], ["mws_auth_token", true], ["aws_region"]], [CarrierSettingsCarrierNameEnum.Aramex]: [["carrier_id", true], ["username", true], ["password", true], ["account_pin", true], ["account_entity", true], ["account_number", true], ["account_country_code"]], [CarrierSettingsCarrierNameEnum.Australiapost]: [["carrier_id", true], ["api_key", true], ["password", true], ["account_number", true]],