Skip to content

Commit

Permalink
revert: deprecated eshipper_xml and usps* extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
danh91 committed Jul 30, 2024
1 parent 627be3d commit 641370a
Show file tree
Hide file tree
Showing 463 changed files with 264,240 additions and 3,333 deletions.
30 changes: 30 additions & 0 deletions modules/connectors/eshipper_xml/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# karrio.eshipper_xml

This package is a eShipper XML extension of the [karrio](https://pypi.org/project/karrio) multi carrier shipping SDK.

## Requirements

`Python 3.7+`

## Installation

```bash
pip install karrio.eshipper_xml
```

## Usage

```python
import karrio
from karrio.mappers.eshipper_xml.settings import Settings


# Initialize a carrier gateway
eshipper_xml = karrio.gateway["eshipper_xml"].create(
Settings(
...
)
)
```

Check the [karrio Mutli-carrier SDK docs](https://docs.karrio.io) for Shipping API requests
12 changes: 12 additions & 0 deletions modules/connectors/eshipper_xml/generate
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
SCHEMAS=./vendor/schemas
LIB_MODULES=./karrio/schemas/eshipper_xml
find "${LIB_MODULES}" -name "*.py" -exec rm -r {} \;
touch "${LIB_MODULES}/__init__.py"

generateDS --no-namespace-defs -o "${LIB_MODULES}/quote_request.py" $SCHEMAS/quote_request.xsd
generateDS --no-namespace-defs -o "${LIB_MODULES}/quote_reply.py" $SCHEMAS/quote_reply.xsd
generateDS --no-namespace-defs -o "${LIB_MODULES}/shipping_request.py" $SCHEMAS/shipping_request.xsd
generateDS --no-namespace-defs -o "${LIB_MODULES}/shipping_reply.py" $SCHEMAS/shipping_reply.xsd
generateDS --no-namespace-defs -o "${LIB_MODULES}/error.py" $SCHEMAS/error.xsd
generateDS --no-namespace-defs -o "${LIB_MODULES}/shipment_cancel_request.py" $SCHEMAS/shipment_cancel_request.xsd
generateDS --no-namespace-defs -o "${LIB_MODULES}/shipment_cancel_reply.py" $SCHEMAS/shipment_cancel_reply.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from karrio.core.metadata import Metadata

from karrio.mappers.eshipper_xml.mapper import Mapper
from karrio.mappers.eshipper_xml.proxy import Proxy
from karrio.mappers.eshipper_xml.settings import Settings
import karrio.providers.eshipper_xml.units as units


METADATA = Metadata(
id="eshipper_xml",
label="eShipper XML",
is_hub=True,
# Integrations
Mapper=Mapper,
Proxy=Proxy,
Settings=Settings,
# Data Units
options=units.ShippingOption,
services=units.ShippingService,
hub_carriers=units.CARRIER_IDS,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from typing import List, Tuple
from karrio.api.mapper import Mapper as BaseMapper
from karrio.mappers.eshipper_xml.settings import Settings
from karrio.core.utils.serializable import Deserializable, Serializable
from karrio.core.models import (
RateRequest,
ShipmentRequest,
ShipmentDetails,
ShipmentCancelRequest,
RateDetails,
Message,
ConfirmationDetails,
)
from karrio.providers.eshipper_xml import (
parse_quote_reply,
quote_request,
parse_shipping_reply,
shipping_request,
shipment_cancel_request,
parse_shipment_cancel_reply,
)


class Mapper(BaseMapper):
settings: Settings

# Request Mappers

def create_rate_request(self, payload: RateRequest) -> Serializable:
return quote_request(payload, self.settings)

def create_shipment_request(self, payload: ShipmentRequest) -> Serializable:
return shipping_request(payload, self.settings)

def create_cancel_shipment_request(
self, payload: ShipmentCancelRequest
) -> Serializable:
return shipment_cancel_request(payload, self.settings)

# Response Parsers

def parse_rate_response(
self, response: Deserializable
) -> Tuple[List[RateDetails], List[Message]]:
return parse_quote_reply(response, self.settings)

def parse_shipment_response(
self, response: Deserializable
) -> Tuple[ShipmentDetails, List[Message]]:
return parse_shipping_reply(response, self.settings)

def parse_cancel_shipment_response(
self, response: Deserializable
) -> Tuple[ConfirmationDetails, List[Message]]:
return parse_shipment_cancel_reply(response, self.settings)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from karrio.core.utils import XP, request as http
from karrio.api.proxy import Proxy as BaseProxy
from karrio.mappers.eshipper_xml.settings import Settings
from karrio.core.utils.serializable import Serializable, Deserializable


class Proxy(BaseProxy):
settings: Settings

def get_rates(self, request: Serializable) -> Deserializable:
response = http(
url=self.settings.server_url,
data=request.serialize(),
trace=self.trace_as("xml"),
method="POST",
headers={"Content-Type": "application/xml"},
)
return Deserializable(response, XP.to_xml)

def create_shipment(self, request: Serializable) -> Deserializable:
response = http(
url=self.settings.server_url,
data=request.serialize(),
trace=self.trace_as("xml"),
method="POST",
headers={"Content-Type": "application/xml"},
)
return Deserializable(response, XP.to_xml)

def cancel_shipment(self, request: Serializable) -> Deserializable:
response = http(
url=self.settings.server_url,
data=request.serialize(),
trace=self.trace_as("xml"),
method="POST",
headers={"Content-Type": "application/xml"},
)
return Deserializable(response, XP.to_xml)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Karrio eshipper_xml connection settings."""

import attr
from karrio.providers.eshipper_xml.utils import Settings as BaseSettings


@attr.s(auto_attribs=True)
class Settings(BaseSettings):
"""eshipper_xml connection settings."""

username: str
password: str

id: str = None
test_mode: bool = False
carrier_id: str = "eshipper_xml"
account_country_code: str = None
metadata: dict = {}
config: dict = {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from karrio.providers.eshipper_xml.quote import parse_quote_reply, quote_request
from karrio.providers.eshipper_xml.shipping import (
parse_shipping_reply,
shipping_request,
)
from karrio.providers.eshipper_xml.void_shipment import (
shipment_cancel_request,
parse_shipment_cancel_reply,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from typing import List
from karrio.schemas.eshipper_xml.error import ErrorType
from karrio.core.models import Message
from karrio.core.utils import Element, XP
from karrio.providers.eshipper_xml.utils import Settings


def parse_error_response(response: Element, settings: Settings) -> List[Message]:
errors = XP.find("Error", response, ErrorType)
return [_extract_error(node, settings) for node in errors]


def _extract_error(error: ErrorType, settings: Settings) -> Message:
return Message(
code="Error",
carrier_name=settings.carrier_name,
carrier_id=settings.carrier_id,
message=error.Message,
)
175 changes: 175 additions & 0 deletions modules/connectors/eshipper_xml/karrio/providers/eshipper_xml/quote.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
from karrio.schemas.eshipper_xml.quote_reply import QuoteType
from karrio.schemas.eshipper_xml.quote_request import (
EShipper,
QuoteRequestType,
FromType,
ToType,
PackagesType,
PackageType,
)

import typing
import karrio.lib as lib
import karrio.core.models as models
import karrio.providers.eshipper_xml.error as provider_error
import karrio.providers.eshipper_xml.units as provider_units
import karrio.providers.eshipper_xml.utils as provider_utils


def parse_quote_reply(
_response: lib.Deserializable[lib.Element],
settings: provider_utils.Settings,
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
response = _response.deserialize()
estimates = lib.find_element("Quote", response)
return (
[_extract_rate(node, settings) for node in estimates],
provider_error.parse_error_response(response, settings),
)


def _extract_rate(
node: lib.Element, settings: provider_utils.Settings
) -> models.RateDetails:
quote = lib.to_object(QuoteType, node)
rate_provider, service, service_name = provider_units.ShippingService.info(
quote.serviceId, quote.carrierId, quote.serviceName, quote.carrierName
)
charges = [
("Base charge", quote.baseCharge),
("Fuel surcharge", quote.fuelSurcharge),
*((surcharge.name, surcharge.amount) for surcharge in quote.Surcharge),
]

return models.RateDetails(
carrier_name=settings.carrier_name,
carrier_id=settings.carrier_id,
currency=quote.currency,
service=service,
total_charge=lib.to_decimal(quote.totalCharge),
transit_days=quote.transitDays,
extra_charges=[
models.ChargeDetails(
name=name,
currency="CAD",
amount=lib.to_decimal(amount),
)
for name, amount in charges
if amount
],
meta=dict(rate_provider=rate_provider, service_name=service_name),
)


def quote_request(
payload: models.RateRequest,
settings: provider_utils.Settings,
) -> lib.Serializable:
shipper = lib.to_address(payload.shipper)
recipient = lib.to_address(payload.recipient)
packages = lib.to_packages(
payload.parcels,
package_option_type=provider_units.ShippingOption,
required=["weight", "height", "width", "length"],
)
options = lib.to_shipping_options(
payload.options,
package_options=packages.options,
initializer=provider_units.shipping_options_initializer,
)
packaging_type = provider_units.PackagingType[
packages.package_type or "eshipper_boxes"
].value
packaging = (
"Pallet"
if packaging_type in [provider_units.PackagingType.pallet.value]
else "Package"
)
service = (
lib.to_services(payload.services, provider_units.ShippingService).first
or provider_units.ShippingService.eshipper_all
)

request = EShipper(
username=settings.username,
password=settings.password,
version="3.0.0",
QuoteRequest=QuoteRequestType(
saturdayPickupRequired=options.eshipper_saturday_pickup_required.state,
homelandSecurity=options.eshipper_homeland_security.state,
pierCharge=None,
exhibitionConventionSite=options.eshipper_exhibition_convention_site.state,
militaryBaseDelivery=options.eshipper_military_base_delivery.state,
customsIn_bondFreight=options.eshipper_customs_in_bond_freight.state,
limitedAccess=options.eshipper_limited_access.state,
excessLength=options.eshipper_excess_length.state,
tailgatePickup=options.eshipper_tailgate_pickup.state,
residentialPickup=options.eshipper_residential_pickup.state,
crossBorderFee=None,
notifyRecipient=options.eshipper_notify_recipient.state,
singleShipment=options.eshipper_single_shipment.state,
tailgateDelivery=options.eshipper_tailgate_delivery.state,
residentialDelivery=options.eshipper_residential_delivery.state,
insuranceType=options.insurance.state is not None,
scheduledShipDate=None,
insideDelivery=options.eshipper_inside_delivery.state,
isSaturdayService=options.eshipper_is_saturday_service.state,
dangerousGoodsType=options.eshipper_dangerous_goods_type.state,
serviceId=service.value,
stackable=options.eshipper_stackable.state,
From=FromType(
id=None,
company=shipper.company_name or " ",
instructions=None,
email=shipper.email,
attention=shipper.person_name,
phone=shipper.phone_number,
tailgateRequired=None,
residential=shipper.residential,
address1=shipper.street,
address2=lib.text(shipper.address_line2),
city=shipper.city,
state=shipper.state_code,
zip=shipper.postal_code,
country=shipper.country_code,
),
To=ToType(
id=None,
company=recipient.company_name or " ",
notifyRecipient=None,
instructions=None,
email=recipient.email,
attention=recipient.person_name,
phone=recipient.phone_number,
tailgateRequired=None,
residential=recipient.residential,
address1=recipient.street,
address2=lib.text(recipient.address_line2),
city=recipient.city,
state=recipient.state_code,
zip=recipient.postal_code,
country=recipient.country_code,
),
COD=None,
Packages=PackagesType(
Package=[
PackageType(
length=provider_utils.ceil(package.length.IN),
width=provider_utils.ceil(package.width.IN),
height=provider_utils.ceil(package.height.IN),
weight=provider_utils.ceil(package.weight.LB),
type_=packaging_type,
freightClass=package.parcel.freight_class,
nmfcCode=None,
insuranceAmount=package.options.insurance.state,
codAmount=package.options.cash_on_delivery.state,
description=package.parcel.description,
)
for package in packages
],
type_=packaging,
),
),
)

return lib.Serializable(request, provider_utils.standard_request_serializer)
Loading

0 comments on commit 641370a

Please sign in to comment.