def rate_request(payload: RateRequest, settings: Settings) -> Serializable[IntlRateV2Request]: """Create the appropriate USPS International rate request depending on the destination :param payload: Purplship unified API rate request data :param settings: USPS International connection and auth settings :return: a domestic or international USPS International compatible request :raises: - OriginNotServicedError when origin country is not serviced by the carrier - DestinationNotServicedError when destination country is US """ if payload.shipper.country_code is not None and payload.shipper.country_code != Country.US.name: raise OriginNotServicedError(payload.shipper.country_code) if payload.recipient.country_code == Country.US.name: raise DestinationNotServicedError(payload.recipient.country_code) package = Packages(payload.parcels, max_weight=Weight(70, WeightUnit.LB)).single recipient = CompleteAddress(payload.recipient) options = Options(payload.options, ShipmentOption) services = Services(payload.services, ShipmentService) extra_services = [getattr(option, 'value', option) for key, option in options if 'usps_option' not in key] commercial = next(("Y" for svc in services if "commercial" in svc.name), "N") commercial_plus = next(("Y" for svc in services if "plus" in svc.name), "N") request = IntlRateV2Request( USERID=settings.username, Revision="2", Package=[ PackageType( ID=0, Pounds=package.weight.LB, Ounces=package.weight.OZ, Machinable=options.usps_option_machinable_item or False, MailType=PackagingType[package.packaging_type or "package"].value, GXG=( GXGType(POBoxFlag='N', GiftFlag='N') if any('global_express_guaranteed' in s.name for s in payload.services) else None ), ValueOfContents=(options.declared_value or ""), Country=recipient.country_name, Width=package.width.IN, Length=package.length.IN, Height=package.height.IN, Girth=(package.girth.value if package.packaging_type == "tube" else None), OriginZip=payload.shipper.postal_code, CommercialFlag=commercial, CommercialPlusFlag=commercial_plus, AcceptanceDateTime=DF.fdatetime( (options.shipment_date or datetime.today()), output_format="%Y-%m-%dT%H:%M:%S" ), DestinationPostalCode=recipient.postal_code, ExtraServices=( ExtraServicesType(ExtraService=[s for s in extra_services]) if any(extra_services) else None ), Content=None, ) ], ) return Serializable(request, XP.export)
def shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[ESHIPPER]: ref = f"ref_{uuid4()}" options = Options(payload.options, ShipmentOption) package = Packages(payload.parcels).single service = ShipmentService.map(payload.service).value_or_key payment = payload.payment or Payment(paid_by='sender') insurance = getattr(options.tnt_insurance, 'value', None) request = ESHIPPER( LOGIN=LOGIN( COMPANY=settings.username, PASSWORD=settings.password, APPID='EC', APPVERSION=3.1, ), CONSIGNMENTBATCH=CONSIGNMENTBATCH( GROUPCODE=None, SENDER=SENDER( COMPANYNAME=payload.shipper.company_name, STREETADDRESS1=payload.shipper.address_line1, STREETADDRESS2=payload.shipper.address_line2, STREETADDRESS3=None, CITY=payload.shipper.city, PROVINCE=payload.shipper.state_code, POSTCODE=payload.shipper.postal_code, COUNTRY=payload.shipper.country_code, ACCOUNT=settings.account_number, VAT=(payload.shipper.state_tax_id or payload.shipper.federal_tax_id), CONTACTNAME=payload.shipper.person_name, CONTACTDIALCODE=None, CONTACTTELEPHONE=payload.shipper.phone_number, CONTACTEMAIL=payload.shipper.email, COLLECTION=None, ), CONSIGNMENT=CONSIGNMENT( CONREF=ref, DETAILS=DETAILS( RECEIVER=RECEIVER( COMPANYNAME=payload.recipient.company_name, STREETADDRESS1=payload.recipient.address_line1, STREETADDRESS2=payload.recipient.address_line2, STREETADDRESS3=None, CITY=payload.recipient.city, PROVINCE=payload.recipient.state_code, POSTCODE=payload.recipient.postal_code, COUNTRY=payload.recipient.country_code, VAT=(payload.recipient.state_tax_id or payload.recipient.federal_tax_id), CONTACTNAME=payload.recipient.person_name, CONTACTDIALCODE=None, CONTACTTELEPHONE=payload.recipient.phone_number, CONTACTEMAIL=payload.recipient.email, ACCOUNT=None, ACCOUNTCOUNTRY=None, ), DELIVERY=None, CONNUMBER=None, CUSTOMERREF=payload.reference, CONTYPE=('D' if package.parcel.is_document else 'N'), PAYMENTIND=PaymentType[payment.paid_by or 'sender'].value, ITEMS=1, TOTALWEIGHT=package.weight.KG, TOTALVOLUME=package.volume, CURRENCY=options.currency, GOODSVALUE=insurance, INSURANCEVALUE=insurance, INSURANCECURRENCY=options.currency, DIVISION=None, SERVICE=service, OPTION=[ getattr(option, 'key', option) for _, option in options ], DESCRIPTION=package.parcel.content, DELIVERYINST=None, CUSTOMCONTROLIN=None, HAZARDOUS=None, UNNUMBER=None, PACKINGGROUP=None, PACKAGE=PACKAGE( ITEMS=1, DESCRIPTION=package.parcel.description, LENGTH=package.length.M, HEIGHT=package.height.M, WIDTH=package.width.M, WEIGHT=package.weight.KG, ARTICLE=([ ARTICLE(ITEMS=article.quantity, DESCRIPTION=article.description, WEIGHT=Weight( article.weight, WeightUnit[article.weight_unit]).KG, INVOICEVALUE=article.value_amount, INVOICEDESC=None, HTS=article.sku, COUNTRY=article.origin_country) for article in payload.customs.commodities ] if payload.customs is not None and any(payload.customs.commodities) else None)), ), CONNUMBER=None, )), ACTIVITY=ACTIVITY(CREATE=CREATE(CONREF=ref), RATE=RATE(CONREF=ref), BOOK=BOOK(CONREF=ref), SHIP=SHIP(CONREF=ref), PRINT=PRINT( REQUIRED=REQUIRED(CONREF=ref), CONNOTE=CONNOTE(CONREF=ref), LABEL=LABEL(CONREF=ref), MANIFEST=MANIFEST(CONREF=ref), INVOICE=INVOICE(CONREF=ref), EMAILTO=payload.recipient.email, EMAILFROM=payload.shipper.email, ), SHOW_GROUPCODE=None)) return Serializable(request, XP.to_xml)
def freight_rate_request( payload: RateRequest, settings: Settings) -> Serializable[FreightRateRequest]: packages = Packages(payload.parcels, PackagePresets) service = ([ RatingServiceCode[svc] for svc in payload.services if svc in RatingServiceCode.__members__ ] + [RatingServiceCode.ups_freight_ltl_guaranteed])[0] request = FreightRateRequest( Request=common.RequestType( TransactionReference=common.TransactionReferenceType( TransactionIdentifier="TransactionIdentifier"), RequestOption=[1], ), ShipFrom=ShipFromType( Name=payload.shipper.company_name, Address=AddressType( AddressLine=concat_str(payload.shipper.address_line1, payload.shipper.address_line2), City=payload.shipper.city, PostalCode=payload.shipper.postal_code, CountryCode=payload.shipper.country_code, StateProvinceCode=payload.shipper.state_code, ), AttentionName=payload.shipper.person_name, ), ShipTo=ShipToType( Name=payload.recipient.company_name, Address=AddressType( AddressLine=concat_str(payload.recipient.address_line1, payload.recipient.address_line2), City=payload.recipient.city, PostalCode=payload.recipient.postal_code, CountryCode=payload.recipient.country_code, StateProvinceCode=payload.recipient.state_code, ), AttentionName=payload.recipient.person_name, ), PaymentInformation=None, Service=RateCodeDescriptionType(Code=service.value, Description=None), HandlingUnitOne=HandlingUnitType( Quantity=1, Type=RateCodeDescriptionType(Code="SKD")), ShipmentServiceOptions=ShipmentServiceOptionsType( PickupOptions=PickupOptionsType(WeekendPickupIndicator="")), DensityEligibleIndicator="", AdjustedWeightIndicator="", HandlingUnitWeight=None, PickupRequest=None, GFPOptions=None, TimeInTransitIndicator="", Commodity=[ CommodityType( Description=package.parcel.description or "...", Weight=WeightType( UnitOfMeasurement=UnitOfMeasurementType( Code=UPSWeightUnit[package.weight_unit].value), Value=package.weight.value, ), Dimensions=DimensionsType( UnitOfMeasurement=UnitOfMeasurementType( Code=package.dimension_unit), Width=package.width.value, Height=package.height.value, Length=package.length.value, ), NumberOfPieces=None, PackagingType=RateCodeDescriptionType( Code=FreightPackagingType[package.packaging_type or "small_box"].value, Description=None, ), FreightClass=50, ) for package in packages ], ) return Serializable( create_envelope(header_content=settings.Security, body_content=request), _request_serializer, )
def shipment_request( payload: ShipmentRequest, settings: Settings) -> Serializable[eVSPriorityMailIntlRequest]: package = Packages(payload.parcels, max_weight=Weight(70, WeightUnit.LB)).single options = Options(payload.options, ShipmentOption) label_format = LabelFormat[payload.label_type or 'usps_6_x_4_label'].value extra_services = [ getattr(option, 'value', option) for key, option in options if 'usps_option' not in key ] customs = payload.customs or Customs(commodities=[]) insurance = getattr( (options['usps_insurance_priority_mail_international']), 'value', options.insurance) # Gets the first provided non delivery option or default to "RETURN" non_delivery = next( (option.value for name, option in options if 'non_delivery' in name), "RETURN") redirect_address = Address( **(options['usps_option_redirect_non_delivery'] or {})) request = eVSPriorityMailIntlRequest( USERID=settings.username, Option=None, Revision=2, ImageParameters=ImageParametersType(ImageParameter=label_format), FromFirstName=customs.signer or payload.shipper.person_name or "N/A", FromMiddleInitial=None, FromLastName=payload.shipper.person_name, FromFirm=payload.shipper.company_name or "N/A", FromAddress1=payload.shipper.address_line1, FromAddress2=payload.shipper.address_line2, FromUrbanization=None, FromCity=payload.shipper.city, FromState=Location(payload.shipper.state_code, country='US').as_state_name, FromZip5=Location(payload.shipper.postal_code).as_zip5, FromZip4=Location(payload.shipper.postal_code).as_zip4, FromPhone=payload.shipper.phone_number, FromCustomsReference=None, ToName=None, ToFirstName=payload.recipient.person_name, ToLastName=None, ToFirm=payload.recipient.company_name or "N/A", ToAddress1=payload.recipient.address_line1, ToAddress2=payload.recipient.address_line2, ToAddress3=None, ToCity=payload.recipient.city, ToProvince=payload.recipient.state_code, ToCountry=Location(payload.recipient.country_code).as_country_name, ToPostalCode=payload.recipient.postal_code, ToPOBoxFlag=None, ToPhone=payload.recipient.phone_number, ToFax=None, ToEmail=payload.recipient.email, ImportersReferenceNumber=None, NonDeliveryOption=non_delivery, RedirectName=redirect_address.person_name, RedirectEmail=redirect_address.email, RedirectSMS=redirect_address.phone_number, RedirectAddress=SF.concat_str(redirect_address.address_line1, redirect_address.address_line2, join=True), RedirectCity=redirect_address.city, RedirectState=redirect_address.state_code, RedirectZipCode=redirect_address.postal_code, RedirectZip4=Location(redirect_address.postal_code).as_zip4, Container=None, ShippingContents=ShippingContentsType(ItemDetail=[ ItemDetailType( Description=item.description, Quantity=item.quantity, Value=item.value_amount, NetPounds=Weight(item.weight, WeightUnit[item.weight_unit or 'LB']).LB, NetOunces=Weight(item.weight, WeightUnit[item.weight_unit or 'LB']).OZ, HSTariffNumber=item.sku, CountryOfOrigin=Location(item.origin_country).as_country_name) for item in payload.customs.commodities ]), Insured=('N' if insurance is None else 'Y'), InsuredAmount=insurance, GrossPounds=package.weight.LB, GrossOunces=package.weight.OZ, ContentType=ContentType[customs.content_type or "other"].value, ContentTypeOther=customs.content_description or "N/A", Agreement=('N' if customs.certify else 'Y'), Comments=customs.content_description, LicenseNumber=customs.license_number, CertificateNumber=customs.certificate_number, InvoiceNumber=customs.invoice, ImageType="PDF", ImageLayout="ALLINONEFILE", CustomerRefNo=None, CustomerRefNo2=None, POZipCode=None, LabelDate=DF.fdatetime(options.shipment_date, output_format="%m/%d/%Y"), EMCAAccount=None, HoldForManifest=None, EELPFC=customs.eel_pfc, PriceOptions=None, Length=package.length.IN, Width=package.weight.IN, Height=package.height.IN, Girth=(package.girth.value if package.packaging_type == "tube" else None), ExtraServices=(ExtraServicesType(ExtraService=[ getattr(option, 'value', option) for option in extra_services ]) if any(extra_services) else None), ActionCode=None, OptOutOfSPE=None, PermitNumber=None, AccountZipCode=None, ImportersReferenceType=None, ImportersTelephoneNumber=None, ImportersFaxNumber=None, ImportersEmail=None, Machinable=options["usps_option_machinable_item"], DestinationRateIndicator="I", MID=None, LogisticsManagerMID=None, CRID=None, VendorCode=None, VendorProductVersionNumber=None, ChargebackCode=None, ) return Serializable(request, XP.export)
def shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[UPSShipmentRequest]: packages = Packages(payload.parcels, PackagePresets) is_document = all([parcel.is_document for parcel in payload.parcels]) package_description = packages[0].parcel.description if len( packages) == 1 else None options = Options(payload.options) service = ShippingServiceCode[payload.service].value if any(key in service for key in ["freight", "ground"]): packages.validate(required=["weight"]) charges: Dict[str, Payment] = { "01": payload.payment, "02": payload.customs.duty if payload.customs is not None else None, } mps_packaging = (ShippingPackagingType.your_packaging.value if len(packages) > 1 else None) label_format, label_height, label_width = LabelType[payload.label_type or 'PDF_6x4'].value request = UPSShipmentRequest( Request=common.RequestType( RequestOption=["validate"], SubVersion=None, TransactionReference=common.TransactionReferenceType( CustomerContext=payload.reference, TransactionIdentifier=None), ), Shipment=ShipmentType( Description=package_description, DocumentsOnlyIndicator="" if is_document else None, Shipper=ShipperType( Name=payload.shipper.company_name, AttentionName=payload.shipper.person_name, CompanyDisplayableName=None, TaxIdentificationNumber=payload.shipper.federal_tax_id, TaxIDType=None, Phone=(ShipPhoneType(Number=payload.shipper.phone_number, Extension=None) if payload.shipper.phone_number is not None else None), ShipperNumber=settings.account_number, FaxNumber=None, EMailAddress=payload.shipper.email, Address=ShipAddressType( AddressLine=SF.concat_str(payload.shipper.address_line1, payload.shipper.address_line2), City=payload.shipper.city, StateProvinceCode=payload.shipper.state_code, PostalCode=payload.shipper.postal_code, CountryCode=payload.shipper.country_code, ), ), ShipTo=ShipToType( Name=payload.recipient.company_name, AttentionName=payload.recipient.person_name, CompanyDisplayableName=None, TaxIdentificationNumber=payload.recipient.federal_tax_id, TaxIDType=None, Phone=(ShipPhoneType(Number=payload.recipient.phone_number, Extension=None) if payload.recipient.phone_number is not None else None), FaxNumber=None, EMailAddress=payload.recipient.email, Address=ShipAddressType( AddressLine=SF.concat_str( payload.recipient.address_line1, payload.recipient.address_line2, ), City=payload.recipient.city, StateProvinceCode=payload.recipient.state_code, PostalCode=payload.recipient.postal_code, CountryCode=payload.recipient.country_code, ), ), PaymentInformation=PaymentInfoType( ShipmentCharge=[ ShipmentChargeType( Type=charge_type, BillShipper=BillShipperType( AccountNumber=settings.account_number, CreditCard=None, AlternatePaymentMethod=None, ) if payment.paid_by == PaymentType.sender.name else None, BillReceiver=BillReceiverType( AccountNumber=payment.account_number, Address=BillReceiverAddressType( PostalCode=payload.recipient.postal_code), ) if payment.paid_by == PaymentType.recipient.name else None, BillThirdParty=BillThirdPartyChargeType( AccountNumber=payment.account_number, ) if payment. paid_by == PaymentType.third_party.name else None, ConsigneeBilledIndicator=None, ) for charge_type, payment in charges.items() if payment is not None ], SplitDutyVATIndicator=None, ) if any(charges.values()) else None, Service=(ServiceType( Code=service) if service is not None else None), ShipmentServiceOptions=(ShipmentServiceOptionsType( COD=(CODType( CODFundsCode=None, CODAmount=CurrencyMonetaryType( CurrencyCode=options.currency or "USD", MonetaryValue=options.cash_on_delivery, ), ) if options.cash_on_delivery else None), Notification=([ NotificationType( NotificationCode=event, EMail=EmailDetailsType(EMailAddress=[ options.notification_email or payload.recipient.email ]), VoiceMessage=None, TextMessage=None, Locale=None, ) for event in [8] ] if options.notification_email is not None else None), ) if any([options.cash_on_delivery, options.notification_email]) else None), Package=[ PackageType( Description=package.parcel.description, Packaging=PackagingType( Code=mps_packaging or ShippingPackagingType[ package.packaging_type or "your_packaging"].value), Dimensions=DimensionsType( UnitOfMeasurement=ShipUnitOfMeasurementType( Code=package.dimension_unit.value, ), Length=package.length.value, Width=package.width.value, Height=package.height.value, ), PackageWeight=PackageWeightType( UnitOfMeasurement=ShipUnitOfMeasurementType( Code=UPSWeightUnit[ package.weight_unit.name].value, ), Weight=package.weight.value, ), ) for package in packages ], ), LabelSpecification=LabelSpecificationType( LabelImageFormat=LabelImageFormatType(Code=label_format, Description=None), HTTPUserAgent=None, LabelStockSize=LabelStockSizeType(Height=label_height, Width=label_width), Instruction=None, CharacterSet=None, ), ReceiptSpecification=None, ) return Serializable( create_envelope(header_content=settings.Security, body_content=request), _request_serializer, )
def _pickup_request(payload: PickupRequest, settings: Settings) -> Serializable[CreatePickupRequest]: same_day = DF.date(payload.pickup_date).date() == datetime.today().date() packages = Packages(payload.parcels, PackagePresets, required=["weight"]) request = CreatePickupRequest( WebAuthenticationDetail=settings.webAuthenticationDetail, ClientDetail=settings.clientDetail, TransactionDetail=TransactionDetail(CustomerTransactionId="FTC"), Version=VersionId(ServiceId="disp", Major=22, Intermediate=0, Minor=0), AssociatedAccountNumber=AssociatedAccount( Type=AssociatedAccountNumberType.FEDEX_EXPRESS.value, AccountNumber=settings.account_number, ), TrackingNumber=None, OriginDetail=PickupOriginDetail( UseAccountAddress=None, PickupLocation=ContactAndAddress( Contact=Contact( ContactId=None, PersonName=payload.address.person_name, CompanyName=payload.address.company_name, PhoneNumber=payload.address.phone_number, EMailAddress=payload.address.email, ), Address=Address( StreetLines=SF.concat_str(payload.address.address_line1, payload.address.address_line2), City=payload.address.city, StateOrProvinceCode=payload.address.state_code, PostalCode=payload.address.postal_code, CountryCode=payload.address.country_code, Residential=payload.address.residential, ), ), PackageLocation=payload.package_location, ReadyTimestamp=f"{payload.pickup_date}T{payload.ready_time}:00", CompanyCloseTime=f"{payload.closing_time}:00", PickupDateType=(PickupRequestType.SAME_DAY if same_day else PickupRequestType.FUTURE_DAY).value, LastAccessTime=None, GeographicalPostalCode=None, Location=payload.package_location, DeleteLastUsed=None, SuppliesRequested=None, EarlyPickup=None, ), PickupServiceCategory=None, FreightPickupDetail=None, ExpressFreightDetail=None, PackageCount=len(packages) or 1, TotalWeight=Weight(Units=WeightUnits.LB.name, Value=packages.weight.LB) if len(packages) > 0 else None, CarrierCode=CarrierCodeType.FDXE.value, OversizePackageCount=None, Remarks=payload.instruction, CommodityDescription=None, CountryRelationship=None, ) return Serializable(request, _request_serializer)
def shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[DicomShipmentRequest]: packages = Packages(payload.parcels) is_international = payload.shipper.country_code != payload.recipient.country_code broker_info = payload.options.get('dicom_broker_info', {}) importer_info = ( Address(**payload.options.get('importer_info')) if 'importer_info' in payload.options else None ) delivery_type = Service[payload.service].value options = { key: (value if Option[key].value in ['DCV', 'COD'] else None) for key, value in payload.options if key in Option.__members__ } request = DicomShipmentRequest( paymentType=PaymentType[payload.payment.paid_by or "prepaid"].value, billingAccount=settings.billing_account, sender=DicomAddress( city=payload.shipper.city, provinceCode=payload.shipper.state_code, postalCode=payload.shipper.postal_code, countryCode=payload.shipper.country_code, customerName=payload.shipper.company_name, addressLine1=payload.shipper.address_line1, addressLine2=payload.shipper.address_line2, contact=Contact( fullName=payload.shipper.person_name, email=payload.shipper.email, telephone=payload.shipper.phone_number ) ), consignee=DicomAddress( city=payload.recipient.city, provinceCode=payload.recipient.state_code, postalCode=payload.recipient.postal_code, countryCode=payload.recipient.country_code, customerName=payload.recipient.company_name, addressLine1=payload.recipient.address_line1, addressLine2=payload.recipient.address_line2, contact=Contact( fullName=payload.recipient.person_name, email=payload.recipient.email, telephone=payload.recipient.phone_number ) ), parcels=[ Parcel( quantity=1, parcelType=ParcelType[package.packaging_type or "dicom_box"].value, weight=package.weight.KG, length=package.height.CM, depth=package.length.CM, width=package.width.CM, note=None, status=None, FCAClass=None, hazmat=None, requestReturnLabel=None, returnWaybill=None, ) for package in packages ], note=None, category="Parcel", pickupDate=None, deliveryType=delivery_type, trackingNumber=None, unitOfMeasurement=UnitOfMeasurement.KC.value, surcharges=[ Surcharge(type=key, value=value) for key, value in options.items() ], promoCodes=None, references=None, returnAddress=None, appointment=None, internationalDetails=(InternationalDetails( isDicomBroker=(broker_info is not None), descriptionOfGoods=payload.customs.content_description, dutyBilling=payload.customs.duty.paid_by, importerOfRecord=(DicomAddress( city=importer_info.city, provinceCode=importer_info.state_code, postalCode=importer_info.postal_code, countryCode=importer_info.country_code, customerName=importer_info.company_name, addressLine1=importer_info.address_line1, addressLine2=importer_info.address_line2, contact=Contact( fullName=importer_info.person_name, email=importer_info.email, telephone=importer_info.phone_number ) ) if importer_info is not None else None), broker=(Broker( id=broker_info.get("id"), CSA_BusinessNumber=broker_info.get("CSA_BusinessNumber"), otherBroker=broker_info.get("otherBroker") ) if broker_info is not None else None), purpose=( Purpose[payload.customs.content_type].value if payload.customs.content_type is not None else None ), products=[ Product(id=index, Quantity=product.quantity) for index, product in enumerate(payload.customs.commodities, 1) ] ) if is_international and payload.customs is not None else None), ) return Serializable(request)
def shipment_request( payload: ShipmentRequest, settings: Settings ) -> Serializable[DHLShipmentRequest]: packages = Packages(payload.parcels, PackagePresets, required=["weight"]) options = Options(payload.options, SpecialServiceCode) product = next( (p.value for p in ProductCode if payload.service == p.name), payload.service ) insurance = options['dhl_shipment_insurance'].value if 'dhl_shipment_insurance' in options else None package_type = ( PackageType[packages[0].packaging_type or "your_packaging"].value if len(packages) == 1 else None ) delivery_type = next( (d for d in DeliveryType if d.name in payload.options.keys()), None ) label_format, label_template = LabelType[payload.label_type or 'PDF_6x4'].value payment = (payload.payment or Payment(paid_by="sender", account_number=settings.account_number)) customs = (payload.customs or Customs()) content = (packages[0].parcel.content or "N/A") request = DHLShipmentRequest( schemaVersion=6.2, Request=settings.Request( MetaData=MetaData(SoftwareName="3PV", SoftwareVersion=6.2) ), RegionCode=CountryRegion[payload.shipper.country_code].value, RequestedPickupTime="Y", LanguageCode="en", PiecesEnabled="Y", LatinResponseInd=None, Billing=Billing( ShipperAccountNumber=settings.account_number, BillingAccountNumber=payment.account_number, ShippingPaymentType=PaymentType[payment.paid_by].value, DutyAccountNumber=(customs.duty.account_number if customs.duty is not None else None), DutyPaymentType=(PaymentType[customs.duty.paid_by].value if customs.duty is not None else None), ), Consignee=Consignee( CompanyName=payload.recipient.company_name or "N/A", SuiteDepartmentName=None, AddressLine=SF.concat_str( payload.recipient.address_line1, payload.recipient.address_line2 ), City=payload.recipient.city, Division=None, DivisionCode=payload.recipient.state_code, PostalCode=payload.recipient.postal_code, CountryCode=payload.recipient.country_code, CountryName=Country[payload.recipient.country_code].value, FederalTaxId=payload.shipper.federal_tax_id, StateTaxId=payload.shipper.state_tax_id, Contact=( Contact( PersonName=payload.recipient.person_name, PhoneNumber=payload.recipient.phone_number or "0000", Email=payload.recipient.email, ) ), Suburb=None, ), Commodity=( [ Commodity(CommodityCode=c.sku, CommodityName=c.description) for c in payload.customs.commodities ] if any(customs.commodities) else None ), NewShipper=None, Shipper=Shipper( ShipperID=settings.account_number or "N/A", RegisteredAccount=settings.account_number, AddressLine=SF.concat_str( payload.shipper.address_line1, payload.shipper.address_line2 ), CompanyName=payload.shipper.company_name or "N/A", PostalCode=payload.shipper.postal_code, CountryCode=payload.shipper.country_code, City=payload.shipper.city, CountryName=Country[payload.shipper.country_code].value, Division=None, DivisionCode=payload.shipper.state_code, Contact=( Contact( PersonName=payload.shipper.person_name, PhoneNumber=payload.shipper.phone_number or "0000", Email=payload.shipper.email, ) ), ), ShipmentDetails=DHLShipmentDetails( NumberOfPieces=len(packages), Pieces=Pieces( Piece=[ Piece( PieceID=package.parcel.id, PackageType=( package_type or PackageType[ package.packaging_type or "your_packaging" ].value ), Depth=package.length.IN, Width=package.width.IN, Height=package.height.IN, Weight=package.weight.LB, DimWeight=None, PieceContents=( package.parcel.content or package.parcel.description ), ) for package in packages ] ), Weight=packages.weight.LB, CurrencyCode=options.currency or "USD", WeightUnit=WeightUnit.L.value, DimensionUnit=DimensionUnit.I.value, Date=(options.shipment_date or time.strftime("%Y-%m-%d")), PackageType=package_type, IsDutiable=("Y" if payload.customs is not None else "N"), InsuredAmount=insurance, ShipmentCharges=(options.cash_on_delivery if options.cash_on_delivery else None), DoorTo=delivery_type, GlobalProductCode=product, LocalProductCode=product, Contents=content, ), EProcShip=None, Dutiable=( Dutiable( DeclaredCurrency=customs.duty.currency or "USD", DeclaredValue=insurance or 1.0, TermsOfTrade=customs.incoterm, ) if customs.duty is not None else None ), ExportDeclaration=None, Reference=[Reference(ReferenceID=payload.reference)], SpecialService=[ SpecialService(SpecialServiceType=SpecialServiceCode[key].value.key) for key, svc in options if key in SpecialServiceCode ], Notification=( Notification( EmailAddress=options.notification_email or payload.recipient.email ) if options.notification_email is None else None ), DocImages=None, RequestArchiveDoc=None, NumberOfArchiveDoc=None, LabelImageFormat=label_format, Label=Label(LabelTemplate=label_template), ODDLinkReq=None, DGs=None, ) return Serializable(request, _request_serializer)
def shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[ShipmentType]: package = Packages(payload.parcels, PackagePresets, required=['weight']).single service = ServiceType[payload.service].value options = Options(payload.options, OptionCode) is_intl = (payload.recipient.country_code is not None and payload.recipient.country_code != 'CA') payment_type = (PaymentType[payload.payment.paid_by].value if payload.payment is not None else None) all_options = ([ *options, (OptionCode.canadapost_return_to_sender.name, OptionCode.canadapost_return_to_sender.value.apply(True)) ] if is_intl and not any(key in options for key in INTERNATIONAL_NON_DELIVERY_OPTION) else [*options]) label_encoding, label_format = LabelType[payload.label_type or 'PDF_4x6'].value request = ShipmentType( customer_request_id=None, groupIdOrTransmitShipment=groupIdOrTransmitShipment(), quickship_label_requested=None, cpc_pickup_indicator=None, requested_shipping_point=payload.shipper.postal_code, shipping_point_id=None, expected_mailing_date=options.shipment_date, provide_pricing_info=True, provide_receipt_info=None, delivery_spec=DeliverySpecType( service_code=service, sender=SenderType( name=payload.shipper.person_name, company=payload.shipper.company_name or "Not Applicable", contact_phone=payload.shipper.phone_number, address_details=AddressDetailsType( city=payload.shipper.city, prov_state=payload.shipper.state_code, country_code=payload.shipper.country_code, postal_zip_code=payload.shipper.postal_code, address_line_1=SF.concat_str(payload.shipper.address_line1, join=True), address_line_2=SF.concat_str(payload.shipper.address_line2, join=True), ), ), destination=DestinationType( name=payload.recipient.person_name, company=payload.recipient.company_name, additional_address_info=None, client_voice_number=payload.recipient.phone_number, address_details=DestinationAddressDetailsType( city=payload.recipient.city, prov_state=payload.recipient.state_code, country_code=payload.recipient.country_code, postal_zip_code=payload.recipient.postal_code, address_line_1=SF.concat_str( payload.recipient.address_line1, join=True), address_line_2=SF.concat_str( payload.recipient.address_line2, join=True), ), ), parcel_characteristics=ParcelCharacteristicsType( weight=package.weight.map(MeasurementOptions).KG, dimensions=dimensionsType( length=package.length.map(MeasurementOptions).CM, width=package.width.map(MeasurementOptions).CM, height=package.height.map(MeasurementOptions).CM, ), unpackaged=None, mailing_tube=None, ), options=(optionsType(option=[ OptionType( option_code=getattr(option, 'key', option), option_amount=getattr(option, 'value', None), option_qualifier_1=None, option_qualifier_2=None, ) for code, option in all_options if code in OptionCode ]) if any(all_options) else None), notification=(NotificationType( email=options.notification_email or payload.recipient.email, on_shipment=True, on_exception=True, on_delivery=True, ) if options.notification_email else None), print_preferences=PrintPreferencesType( output_format=label_format, encoding=label_encoding, ), preferences=PreferencesType( service_code=None, show_packing_instructions=False, show_postage_rate=True, show_insured_value=True, ), customs=(CustomsType( currency=options.currency or Currency.CAD.value, conversion_from_cad=None, reason_for_export=payload.customs.content_type, other_reason=payload.customs.content_description, duties_and_taxes_prepaid=payload.customs.duty.account_number, certificate_number=payload.customs.certificate_number, licence_number=None, invoice_number=payload.customs.invoice, sku_list=(sku_listType(item=[ SkuType( customs_number_of_units=item.quantity, customs_description=item.description, sku=item.sku, hs_tariff_code=None, unit_weight=WeightUnit.KG.value, customs_value_per_unit=item.value_amount, customs_unit_of_measure=None, country_of_origin=payload.shipper.country_code, province_of_origin=None, ) for item in payload.customs.commodities ]), )) if payload.customs is not None else None), references=ReferencesType( cost_centre=None, customer_ref_1=payload.reference, customer_ref_2=None, ), settlement_info=SettlementInfoType( paid_by_customer=(payload.payment.account_number if payload.payment is not None else settings.customer_number), contract_id=settings.contract_id, cif_shipment=None, intended_method_of_payment=payment_type, promo_code=None, ), ), return_spec=None, pre_authorized_payment=None, ) request.groupIdOrTransmitShipment.original_tagname_ = "transmit-shipment" return Serializable(request, _request_serializer)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[RateV4Request]: """Create the appropriate USPS rate request depending on the destination :param payload: Purplship unified API rate request data :param settings: USPS connection and auth settings :return: a domestic or international USPS compatible request :raises: an OriginNotServicedError when origin country is not serviced by the carrier """ if payload.shipper.country_code is not None and payload.shipper.country_code != Country.US.name: raise OriginNotServicedError(payload.shipper.country_code) if payload.recipient.country_code is not None and payload.recipient.country_code == Country.US.name: raise DestinationNotServicedError(payload.recipient.country_code) package = Packages(payload.parcels).single options = Options(payload.options, ShipmentOption) service = (Services(payload.services, ShipmentService).first or ShipmentService.usps_all).value special_services = [getattr(option, 'value', option) for key, option in options if 'usps_option' not in key] insurance = next( (option.value for key, option in options if 'usps_insurance' in key), options.insurance ) container = PackagingType[package.packaging_type or "your_packaging"] sort_level = SortLevelType[container.name] mail_type = (FirstClassMailType[container.name].value if 'first_class' in service else None) request = RateV4Request( USERID=settings.username, Revision="2", Package=[ PackageType( ID=0, Service=(service or ShipmentService.usps_all).value, FirstClassMailType=mail_type, ZipOrigination=payload.shipper.postal_code, ZipDestination=payload.recipient.postal_code, Pounds=package.weight.LB, Ounces=package.weight.OZ, Container=container.value, Width=package.width.IN, Length=package.length.IN, Height=package.height.IN, Girth=package.girth.value, Value=insurance, AmountToCollect=options.cash_on_delivery, SpecialServices=( SpecialServicesType(SpecialService=[s.value for s in special_services]) if any(special_services) else None ), Content=None, GroundOnly=options["usps_option_ground_only"], SortBy=sort_level.value, Machinable=options["usps_option_machinable_item"], ReturnLocations=options["usps_option_return_service_info"], ReturnServiceInfo=options["usps_option_return_service_info"], DropOffTime=('13:30' if options.shipment_date is not None else None), ShipDate=ShipDateType(valueOf_=DF.fdate(options.shipment_date)), ) ], ) return Serializable(request, XP.export)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[Envelope]: packages = Packages(payload.parcels) service_type = Services(payload.services, Service).first options = Options(payload.options, Option) shipment_date = DF.fdatetime(options.shipment_date or time.strftime('%Y-%m-%d'), current_format='%Y-%m-%d', output_format='%Y-%m-%dT%H:%M:%S') premium: Optional[bool] = next((True for option, _ in options if option in [ Option.canpar_ten_am.name, Option.canpar_noon.name, Option.canpar_saturday.name, ]), None) nsr = next( (Option[o].value for o in ['canpar_no_signature_required', 'canpar_not_no_signature_required'] if o in options), None) request = create_envelope(body_content=rateShipment(request=RateShipmentRq( apply_association_discount=False, apply_individual_discount=False, apply_invoice_discount=False, password=settings.password, shipment=Shipment( cod_type=options['canpar_cash_on_delivery'], delivery_address=Address( address_line_1=payload.recipient.address_line1, address_line_2=payload.recipient.address_line2, address_line_3=None, attention=payload.recipient.person_name, city=payload.recipient.city, country=payload.recipient.country_code, email=payload.recipient.email, extension=None, name=payload.recipient.company_name, phone=payload.recipient.phone_number, postal_code=payload.recipient.postal_code, province=payload.recipient.state_code, residential=payload.recipient.residential, ), description=None, dg=options['canpar_dangerous_goods'], dimention_unit=DimensionUnit.IN.value, handling=None, handling_type=None, instruction=None, nsr=nsr, packages=[ Package(alternative_reference=None, cod=None, cost_centre=None, declared_value=None, height=pkg.height.CM, length=pkg.length.CM, lg=None, reference=None, reported_weight=pkg.weight.LB, store_num=None, width=pkg.width.CM, xc=options['canpar_extra_care']) for pkg in packages ], pickup_address=Address( address_line_1=payload.shipper.address_line1, address_line_2=payload.shipper.address_line2, address_line_3=None, attention=payload.shipper.person_name, city=payload.shipper.city, country=payload.shipper.country_code, email=payload.shipper.email, extension=None, name=payload.shipper.company_name, phone=payload.shipper.phone_number, postal_code=payload.shipper.postal_code, province=payload.shipper.state_code, residential=payload.shipper.residential, ), premium=premium, proforma=None, reported_weight_unit=WeightUnit.LB.value, send_email_to_delivery=payload.recipient.email, send_email_to_pickup=payload.shipper.email, service_type=service_type.value, shipper_num=None, shipping_date=shipment_date, subtotal=None, subtotal_with_handling=None, total=None, total_with_handling=None, user_id=None, ), user_id=settings.username))) return Serializable(request, default_request_serializer)
def dct_request(payload: RateRequest, settings: Settings) -> Serializable[DCTRequest]: packages = Packages(payload.parcels, PackagePresets, required=["weight"]) options = Options(payload.options) is_international = payload.shipper.country_code != payload.recipient.country_code is_document = all([parcel.is_document for parcel in payload.parcels]) is_dutiable = not is_document products = [ ProductCode[svc].value for svc in payload.services if svc in ProductCode.__members__ ] special_services = [ SpecialServiceCode[s].value for s in payload.options.keys() if s in SpecialServiceCode.__members__ ] if is_international and is_dutiable: special_services.append(SpecialServiceCode.dhl_paperless_trade.value) if len(products) == 0: if is_international: products = [(ProductCode.dhl_express_worldwide_doc if is_document else ProductCode.dhl_express_worldwide_nondoc).value] else: products = [(ProductCode.dhl_express_easy_doc if is_document else ProductCode.dhl_express_easy_nondoc).value] request = DCTRequest(GetQuote=GetQuoteType( Request=settings.Request( MetaData=MetaData(SoftwareName="3PV", SoftwareVersion=1.0)), From=DCTFrom( CountryCode=payload.shipper.country_code, Postalcode=payload.shipper.postal_code, City=payload.shipper.city, Suburb=payload.shipper.state_code, ), To=DCTTo( CountryCode=payload.recipient.country_code, Postalcode=payload.recipient.postal_code, City=payload.recipient.city, Suburb=payload.recipient.state_code, ), BkgDetails=BkgDetailsType( PaymentCountryCode=payload.shipper.country_code, NetworkTypeCode=NetworkType.both_time_and_day_definite.value, WeightUnit=WeightUnit.LB.value, DimensionUnit=DimensionUnit.IN.value, ReadyTime=time.strftime("PT%HH%MM"), Date=time.strftime("%Y-%m-%d"), IsDutiable=("Y" if is_dutiable else "N"), Pieces=PiecesType(Piece=[ PieceType( PieceID=package.parcel.id or f"{index}", PackageTypeCode=DCTPackageType[package.packaging_type or "your_packaging"].value, Depth=package.length.IN, Width=package.width.IN, Height=package.height.IN, Weight=package.weight.LB, ) for index, package in enumerate( cast(Iterable[Package], packages), 1) ]), NumberOfPieces=len(packages), ShipmentWeight=packages.weight.LB, Volume=None, PaymentAccountNumber=settings.account_number, InsuredCurrency=options.currency if options.insurance is not None else None, InsuredValue=options.insurance.amount if options.insurance is not None else None, PaymentType=None, AcctPickupCloseTime=None, QtdShp=[ QtdShpType( GlobalProductCode=product, LocalProductCode=product, QtdShpExChrg=[ QtdShpExChrgType(SpecialServiceType=service) for service in special_services ], ) for product in products ], ), Dutiable=DCTDutiable( DeclaredValue=payload.options.get('value', 1.0), DeclaredCurrency=options.currency, ) if is_international and is_dutiable else None, ), ) return Serializable(request, _request_serializer)
def shipment_request( payload: ShipmentRequest, settings: Settings ) -> Serializable[ProcessShipmentRequest]: shipper = CompleteAddress.map(payload.shipper) recipient = CompleteAddress.map(payload.recipient) packages = Packages(payload.parcels, PackagePresets, required=["weight"]) # Only the master package is selected here because even for MPS only one package is accepted for a master tracking. master_package = packages[0] service = ServiceType.map(payload.service).value_or_key options = Options(payload.options, SpecialServiceType) special_services = [getattr(v, 'value', v) for k, v in options if k in SpecialServiceType] label_type, label_format = LabelType[payload.label_type or 'PDF_4x6'].value customs = payload.customs duty = customs.duty if customs is not None else None bill_to = CompleteAddress(getattr(duty, 'bill_to', None)) request = ProcessShipmentRequest( WebAuthenticationDetail=settings.webAuthenticationDetail, ClientDetail=settings.clientDetail, TransactionDetail=TransactionDetail(CustomerTransactionId="IE_v26_Ship"), Version=VersionId(ServiceId="ship", Major=26, Intermediate=0, Minor=0), RequestedShipment=RequestedShipment( ShipTimestamp=DF.date(options.shipment_date or datetime.now()), DropoffType="REGULAR_PICKUP", ServiceType=service, PackagingType=PackagingType[packages.package_type or 'your_packaging'].value, ManifestDetail=None, VariationOptions=None, TotalWeight=FedexWeight( Units=packages.weight.unit, Value=packages.weight.value ), TotalInsuredValue=options.insurance, PreferredCurrency=options.currency, ShipmentAuthorizationDetail=None, Shipper=Party( AccountNumber=settings.account_number, Tins=( [TaxpayerIdentification(Number=tax) for tax in shipper.taxes] if shipper.has_tax_info else None ), Contact=( Contact( ContactId=None, PersonName=shipper.person_name, Title=None, CompanyName=shipper.company_name, PhoneNumber=shipper.phone_number, PhoneExtension=None, TollFreePhoneNumber=None, PagerNumber=None, FaxNumber=None, EMailAddress=shipper.email, ) if shipper.has_contact_info else None ), Address=Address( StreetLines=shipper.address_lines, City=shipper.city, StateOrProvinceCode=shipper.state_code, PostalCode=shipper.postal_code, UrbanizationCode=None, CountryCode=shipper.country_code, CountryName=shipper.country_name, Residential=shipper.residential, GeographicCoordinates=None, ), ), Recipient=Party( AccountNumber=None, Tins=( [TaxpayerIdentification(Number=tax) for tax in recipient.taxes] if recipient.has_tax_info else None ), Contact=( Contact( ContactId=None, PersonName=recipient.person_name, Title=None, CompanyName=recipient.company_name, PhoneNumber=recipient.phone_number, PhoneExtension=None, TollFreePhoneNumber=None, PagerNumber=None, FaxNumber=None, EMailAddress=recipient.email, ) if recipient.has_contact_info else None ), Address=Address( StreetLines=recipient.address_lines, City=recipient.city, StateOrProvinceCode=recipient.state_code, PostalCode=recipient.postal_code, UrbanizationCode=None, CountryCode=recipient.country_code, CountryName=recipient.country_name, Residential=recipient.residential, GeographicCoordinates=None, ), ), RecipientLocationNumber=None, Origin=None, SoldTo=None, ShippingChargesPayment=Payment( PaymentType=PaymentType[payload.payment.paid_by or "sender"].value, Payor=Payor( ResponsibleParty=Party( AccountNumber=(payload.payment.account_number or settings.account_number), ) ), ), SpecialServicesRequested=( ShipmentSpecialServicesRequested( SpecialServiceTypes=special_services, CodDetail=( CodDetail( CodCollectionAmount=Money( Currency=options.currency or "USD", Amount=options.cash_on_delivery, ), AddTransportationChargesDetail=None, CollectionType=CodCollectionType.CASH, CodRecipient=None, FinancialInstitutionContactAndAddress=None, RemitToName=None, ReferenceIndicator=None, ReturnTrackingId=None, ) if options.cash_on_delivery else None ), DeliveryOnInvoiceAcceptanceDetail=None, HoldAtLocationDetail=None, EventNotificationDetail=( ShipmentEventNotificationDetail( AggregationType=None, PersonalMessage=None, EventNotifications=[ ShipmentEventNotificationSpecification( Role=None, Events=NOTIFICATION_EVENTS, NotificationDetail=NotificationDetail( NotificationType="EMAIL", EmailDetail=EMailDetail( EmailAddress=(options.email_notification_to or recipient.email), Name=recipient.person_name or recipient.company_name, ), Localization=Localization(LanguageCode="EN"), ), FormatSpecification=ShipmentNotificationFormatSpecification( Type="TEXT" ), ) ], ) if options.email_notification and any([options.email_notification_to, recipient.email]) else None ), ReturnShipmentDetail=None, PendingShipmentDetail=None, InternationalControlledExportDetail=None, InternationalTrafficInArmsRegulationsDetail=None, ShipmentDryIceDetail=None, HomeDeliveryPremiumDetail=None, EtdDetail=None, ) if options.has_content else None ), ExpressFreightDetail=None, FreightShipmentDetail=None, DeliveryInstructions=None, VariableHandlingChargeDetail=None, CustomsClearanceDetail=( CustomsClearanceDetail( Brokers=None, ClearanceBrokerage=None, CustomsOptions=None, ImporterOfRecord=None, RecipientCustomsId=None, DutiesPayment=( Payment( PaymentType=PaymentType[duty.paid_by or "sender"].value, Payor=( Payor( ResponsibleParty=Party( AccountNumber=duty.account_number, Tins=bill_to.taxes ) ) if any([duty.account_number, bill_to.taxes]) else None ) ) if duty is not None else None ), DocumentContent=None, CustomsValue=Money( Currency=(duty.currency or options.currency), Amount=(duty.declared_value or options.declared_value) ), FreightOnValue=None, InsuranceCharges=None, PartiesToTransactionAreRelated=None, CommercialInvoice=( CommercialInvoice( Comments=None, FreightCharge=None, TaxesOrMiscellaneousChargeType=None, PackingCosts=None, HandlingCosts=None, SpecialInstructions=None, DeclarationStatement=None, PaymentTerms=None, Purpose=PurposeType[customs.content_type or 'other'].value, PurposeOfShipmentDescription=None, CustomerReferences=None, OriginatorName=(shipper.company_name or shipper.person_name), TermsOfSale=Incoterm[customs.incoterm or "DDU"].value ) if customs.commercial_invoice else None ), Commodities=[ Commodity( Name=None, NumberOfPieces=item.quantity, Description=item.description or "N/A", Purpose=None, CountryOfManufacture=item.origin_country, HarmonizedCode=None, Weight=FedexWeight( Units=master_package.weight_unit.value, Value=Weight(item.weight, item.weight_unit)[master_package.weight_unit.value] ), Quantity=item.quantity, QuantityUnits='EA', AdditionalMeasures=None, UnitPrice=Money( Currency=(options.currency or duty.currency), Amount=item.value_amount, ), CustomsValue=None, ExciseConditions=None, ExportLicenseNumber=None, ExportLicenseExpirationDate=None, CIMarksAndNumbers=None, PartNumber=item.sku, NaftaDetail=None, ) for item in customs.commodities ], ExportDetail=None, RegulatoryControls=None, DeclarationStatementDetail=None ) if payload.customs is not None else None ), PickupDetail=None, SmartPostDetail=None, BlockInsightVisibility=None, LabelSpecification=LabelSpecification( Dispositions=None, LabelFormatType=LabelFormatType.COMMON_2_D.value, ImageType=label_type, LabelStockType=label_format, LabelPrintingOrientation=LabelPrintingOrientationType.TOP_EDGE_OF_TEXT_FIRST.value, LabelOrder=LabelOrderType.SHIPPING_LABEL_FIRST.value, PrintedLabelOrigin=None, CustomerSpecifiedDetail=None, ), ShippingDocumentSpecification=None, RateRequestTypes=None, EdtRequestType=None, MasterTrackingId=None, PackageCount=len(packages), ConfigurationData=None, RequestedPackageLineItems=[ RequestedPackageLineItem( SequenceNumber=1, GroupNumber=None, GroupPackageCount=None, VariableHandlingChargeDetail=None, InsuredValue=None, Weight=( FedexWeight( Units=master_package.weight.unit, Value=master_package.weight.value, ) if master_package.weight.value else None ), Dimensions=( FedexDimensions( Length=master_package.length.map(MeasurementOptions).value, Width=master_package.width.map(MeasurementOptions).value, Height=master_package.height.map(MeasurementOptions).value, Units=master_package.dimension_unit.value, ) if master_package.has_dimensions else None ), PhysicalPackaging=None, ItemDescription=master_package.parcel.description, ItemDescriptionForClearance=None, CustomerReferences=( [ CustomerReference( CustomerReferenceType=CustomerReferenceType.CUSTOMER_REFERENCE, Value=payload.reference ) ] if any(payload.reference or "") else None ), SpecialServicesRequested=None, ContentRecords=None, ) ], ), ) return Serializable(request, _request_serializer)
def shipping_request( payload: ShipmentRequest, settings: Settings ) -> Serializable[EShipper]: packages = Packages(payload.parcels, required=["weight", "height", "width", "length"]) options = Options(payload.options, Option) service = Service.map(payload.service).value_or_key packaging_type = PackagingType[packages.package_type or "eshipper_boxes"].value packaging = ("Pallet" if packaging_type in [PackagingType.pallet.value] else "Package") freight_class = ( FreightClass[payload.options["freight_class"]].value if payload.options.get("freight_class") in FreightClass else None ) payment_type = ( PaymentType[payload.payment.paid_by].value if payload.payment else None ) item = next( iter(payload.customs.commodities if payload.customs is not None else []), None ) payer: Address = { PaymentType.sender: payload.shipper, PaymentType.recipient: payload.recipient, PaymentType.third_party: payload.recipient, }.get(PaymentType[payload.payment.paid_by]) if payload.payment else None request = EShipper( username=settings.username, password=settings.password, version="3.0.0", ShippingRequest=ShippingRequestType( saturdayPickupRequired=options.eshipper_saturday_pickup_required, homelandSecurity=options.eshipper_homeland_security, pierCharge=None, exhibitionConventionSite=options.eshipper_exhibition_convention_site, militaryBaseDelivery=options.eshipper_military_base_delivery, customsIn_bondFreight=options.eshipper_customs_in_bond_freight, limitedAccess=options.eshipper_limited_access, excessLength=options.eshipper_excess_length, tailgatePickup=options.eshipper_tailgate_pickup, residentialPickup=options.eshipper_residential_pickup, crossBorderFee=None, notifyRecipient=options.eshipper_notify_recipient, singleShipment=options.eshipper_single_shipment, tailgateDelivery=options.eshipper_tailgate_delivery, residentialDelivery=options.eshipper_residential_delivery, insuranceType=options.insurance is not None, scheduledShipDate=None, insideDelivery=options.eshipper_inside_delivery, isSaturdayService=options.eshipper_is_saturday_service, dangerousGoodsType=options.eshipper_dangerous_goods_type, serviceId=service, stackable=options.eshipper_stackable, From=FromType( id=payload.shipper.id, company=payload.shipper.company_name, instructions=None, email=payload.shipper.email, attention=payload.shipper.person_name, phone=payload.shipper.phone_number, tailgateRequired=None, residential=payload.shipper.residential, address1=SF.concat_str(payload.shipper.address_line1, join=True), address2=SF.concat_str(payload.shipper.address_line2, join=True), city=payload.shipper.city, state=payload.shipper.state_code, zip=payload.shipper.postal_code, country=payload.shipper.country_code, ), To=ToType( id=payload.recipient.id, company=payload.recipient.company_name, notifyRecipient=None, instructions=None, email=payload.recipient.email, attention=payload.recipient.person_name, phone=payload.recipient.phone_number, tailgateRequired=None, residential=payload.recipient.residential, address1=SF.concat_str(payload.recipient.address_line1, join=True), address2=SF.concat_str(payload.recipient.address_line2, join=True), city=payload.recipient.city, state=payload.recipient.state_code, zip=payload.recipient.postal_code, country=payload.recipient.country_code, ), COD=( CODType( paymentType=PaymentType.recipient.value, CODReturnAddress=CODReturnAddressType( codCompany=payload.recipient.company_name, codName=payload.recipient.person_name, codAddress1=SF.concat_str(payload.recipient.address_line1, join=True), codCity=payload.recipient.city, codStateCode=payload.recipient.state_code, codZip=payload.recipient.postal_code, codCountry=payload.recipient.country_code, ), ) if options.cash_on_delivery is not None else None ), Packages=PackagesType( Package=[ PackageType( length=ceil(package.length.IN), width=ceil(package.width.IN), height=ceil(package.height.IN), weight=ceil(package.weight.LB), type_=packaging_type, freightClass=freight_class, nmfcCode=None, insuranceAmount=None, codAmount=None, description=package.parcel.description, ) for package in packages ], type_=packaging, ), Payment=( RequestPaymentType(type_=payment_type) if payload.payment is not None else None ), Reference=( [ReferenceType(name="REF", code=payload.reference)] if payload.reference != "" else None ), CustomsInvoice=( CustomsInvoiceType( BillTo=BillToType( company=payer.company_name, name=payer.person_name, address1=SF.concat_str(payer.address_line1, join=True), city=payer.city, state=payer.state_code, zip=payer.postal_code, country=payer.country_code, ), Contact=ContactType(name=payer.person_name, phone=payer.phone_number), Item=ItemType( code=item.sku, description=item.description, originCountry=item.origin_country, quantity=item.quantity, unitPrice=item.value_amount, ), ) if all([payload.customs, payer]) else None ), ), ) return Serializable(request, standard_request_serializer)
def shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[eVSRequest]: if payload.shipper.country_code is not None and payload.shipper.country_code != Country.US.name: raise OriginNotServicedError(payload.shipper.country_code) if payload.recipient.country_code is not None and payload.recipient.country_code != Country.US.name: raise DestinationNotServicedError(payload.recipient.country_code) service = ServiceType[payload.service].value package = Packages(payload.parcels).single options = Options(payload.options, ShipmentOption) customs = payload.customs or Customs(commodities=[]) extra_services = [ getattr(option, 'value', option) for key, option in options if 'usps_option' not in key ] label_format = LabelFormat[payload.label_type or 'usps_6_x_4_label'].value insurance = next( (option.value for key, option in options if 'usps_insurance' in key), options.insurance) # Gets the first provided non delivery option or default to "RETURN" non_delivery = next( (option.value for name, option in options if 'non_delivery' in name), "RETURN") redirect_address = Address( **(options['usps_option_redirect_non_delivery'] or {})) request = eVSRequest( USERID=settings.username, Option=None, Revision="1", ImageParameters=ImageParametersType(ImageParameter=label_format, LabelSequence=LabelSequenceType( PackageNumber=1, TotalPackages=1)), FromName=payload.shipper.person_name, FromFirm=payload.shipper.company_name or "N/A", FromAddress1=payload.shipper.address_line1, FromAddress2=payload.shipper.address_line2, FromCity=payload.shipper.city, FromState=payload.shipper.state_code, FromZip5=Location(payload.shipper.postal_code).as_zip5, FromZip4=Location(payload.shipper.postal_code).as_zip4, FromPhone=payload.shipper.phone_number, POZipCode=None, AllowNonCleansedOriginAddr=False, ToName=payload.recipient.person_name, ToFirm=payload.recipient.company_name or "N/A", ToAddress1=payload.recipient.address_line1, ToAddress2=payload.recipient.address_line2, ToCity=payload.recipient.city, ToState=payload.recipient.state_code, ToZip5=Location(payload.recipient.postal_code).as_zip5, ToZip4=Location(payload.recipient.postal_code).as_zip4, ToPhone=payload.recipient.phone_number, POBox=None, ToContactPreference=None, ToContactMessaging=payload.recipient.email, ToContactEmail=payload.recipient.email, AllowNonCleansedDestAddr=False, WeightInOunces=package.weight.OZ, ServiceType=service, Container=PackagingType[package.packaging_type or 'variable'].value, Width=package.width.IN, Length=package.length.IN, Height=package.height.IN, Girth=(package.girth.value if package.packaging_type == "tube" else None), Machinable=options["usps_option_machinable_item"], ProcessingCategory=None, PriceOptions=None, InsuredAmount=insurance, AddressServiceRequested=None, ExpressMailOptions=None, ShipDate=options.shipment_date, CustomerRefNo=None, ExtraServices=(ExtraServicesType(ExtraService=[ getattr(option, 'value', option) for option in extra_services ]) if any(extra_services) else None), CRID=None, MID=None, LogisticsManagerMID=None, VendorCode=None, VendorProductVersionNumber=None, SenderName=(payload.shipper.person_name or payload.shipper.company_name), SenderEMail=payload.shipper.email, RecipientName=(payload.recipient.person_name or payload.recipient.company_name), RecipientEMail=payload.recipient.email, ReceiptOption="SEPARATE PAGE", ImageType="PDF", HoldForManifest=None, NineDigitRoutingZip=None, ShipInfo=options["usps_option_ship_info"], CarrierRelease=None, DropOffTime=None, ReturnCommitments=None, PrintCustomerRefNo=None, Content=None, ShippingContents=(ShippingContentsType(ItemDetail=[ ItemDetailType( Description=item.description, Quantity=item.quantity, Value=item.value_amount, NetPounds=Weight(item.weight, WeightUnit[item.weight_unit or 'LB']).LB, NetOunces=Weight(item.weight, WeightUnit[item.weight_unit or 'LB']).OZ, HSTariffNumber=item.sku, CountryOfOrigin=Location(item.origin_country).as_country_name) for item in customs.commodities ]) if payload.customs is not None else None), CustomsContentType=ContentType[customs.content_type or "other"].value, ContentComments=None, RestrictionType=None, RestrictionComments=None, AESITN=customs.aes, ImportersReference=None, ImportersContact=None, ExportersReference=None, ExportersContact=None, InvoiceNumber=customs.invoice, LicenseNumber=customs.license_number, CertificateNumber=customs.certificate_number, NonDeliveryOption=non_delivery, AltReturnAddress1=redirect_address.address_line1, AltReturnAddress2=redirect_address.address_line2, AltReturnAddress3=None, AltReturnAddress4=None, AltReturnAddress5=None, AltReturnAddress6=None, AltReturnCountry=None, LabelImportType=None, ChargebackCode=None, TrackingRetentionPeriod=None, ) return Serializable(request)
def shipment_request( payload: ShipmentRequest, settings: Settings) -> Serializable[eVSGXGGetLabelRequest]: package = Packages(payload.parcels, max_weight=Weight(70, WeightUnit.LB)).single options = Options(payload.options, ShipmentOption) customs = payload.customs or Customs(commodities=[]) incoterm = Incoterm[customs.incoterm or 'OTHER'].value insurance = getattr((options.usps_insurance_global_express_guaranteed), 'value', options.insurance) request = eVSGXGGetLabelRequest( USERID=settings.username, PASSWORD=settings.password, Option=None, Revision=2, ImageParameters=None, FromFirstName=(customs.signer or payload.shipper.person_name or "N/A"), FromMiddleInitial=None, FromLastName=payload.shipper.person_name, FromFirm=payload.shipper.company_name or "N/A", FromAddress1=payload.shipper.address_line1, FromAddress2=payload.shipper.address_line2, FromUrbanization=None, FromCity=payload.shipper.city, FromState=Location(payload.shipper.state_code, country='US').as_state_name, FromZIP5=Location(payload.shipper.postal_code).as_zip5, FromZIP4=Location(payload.shipper.postal_code).as_zip4, FromPhone=payload.shipper.phone_number, ShipFromZIP=None, ToFirstName=None, ToLastName=payload.recipient.person_name, ToFirm=payload.recipient.company_name or "N/A", ToAddress1=payload.recipient.address_line1, ToAddress2=payload.recipient.address_line2, ToAddress3=None, ToPostalCode=payload.recipient.postal_code, ToPhone=payload.recipient.phone_number, RecipientEMail=payload.recipient.email, ToDPID="000", # supposedly required test and find a solution ToProvince=payload.recipient.state_code, ToTaxID=(payload.recipient.federal_tax_id or payload.recipient.state_tax_id), Container=PackagingType[package.packaging_type or 'package'].value, ContentType=('DOCUMENTS' if package.parcel.is_document else 'NON-DOC'), ShippingContents=ShippingContentsType(ItemDetail=[ ItemDetailType( Description=item.description, Commodity=item.description or "N/A", Quantity=item.quantity, UnitValue=item.value_amount, NetPounds=Weight(item.weight, WeightUnit[item.weight_unit or 'LB']).LB, NetOunces=Weight(item.weight, WeightUnit[item.weight_unit or 'LB']).OZ, UnitOfMeasure=None, HSTariffNumber=item.sku, CountryofManufacture=Location( item.origin_country).as_country_name) for item in customs.commodities ]), PurposeOfShipment=ContentType[customs.content_type or 'other'].value, PartiesToTransaction=None, Agreement=('N' if customs.certify else 'Y'), Postage=None, InsuredValue=insurance, GrossPounds=package.weight.LB, GrossOunces=package.weight.OZ, Length=package.length.IN, Width=package.width.IN, Height=package.height.IN, Girth=(package.girth.value if package.packaging_type == "tube" else None), Shape=None, CIRequired=customs.commercial_invoice, InvoiceDate=DF.fdatetime(customs.invoice_date, output_format="%m/%d/%Y"), InvoiceNumber=customs.invoice, CustomerOrderNumber=None, CustOrderNumber=None, TermsDelivery=incoterm, TermsDeliveryOther=((customs.incoterm or incoterm) if incoterm == 'OTHER' else None), PackingCost=None, CountryUltDest=Location( payload.recipient.country_code).as_country_name, CIAgreement=customs.commercial_invoice, ImageType="PDF", ImageLayout=None, CustomerRefNo=None, CustomerRefNo2=None, ShipDate=DF.fdatetime( (options.shipment_date or time.strftime('%Y-%m-%d')), current_format="%Y-%m-%d", output_format="%m/%d/%Y"), HoldForManifest=None, PriceOptions=None, CommercialShipment=customs.commercial_invoice, BuyerRecipient=( customs.commercial_invoice or None), # Consider recipient as buyer for commercial shipment TermsPayment=("Net 50" if customs.commercial_invoice else None), ActionCode=None, OptOutOfSPE=None, PermitNumber=None, AccountZipCode=None, Machinable=(options.usps_option_machinable_item or False), DestinationRateIndicator="I", MID=settings.mailer_id, LogisticsManagerMID=settings.logistics_manager_mailer_id, CRID=settings.customer_registration_id, VendorCode=None, VendorProductVersionNumber=None, OverrideMID=None, ChargebackCode=None, ) return Serializable(request, XP.export)
def shipment_request( payload: ShipmentRequest, settings: Settings ) -> Serializable[DHLShipmentRequest]: packages = Packages(payload.parcels, PackagePresets, required=["weight"]) is_international = payload.shipper.country_code == payload.recipient.country_code options = Options(payload.options) product = ProductCode[payload.service].value package_type = ( PackageType[packages[0].packaging_type or "your_packaging"].value if len(packages) == 1 else None ) delivery_type = next( (d for d in DeliveryType if d.name in payload.options.keys()), None ) special_services = [ SpecialServiceCode[s].value for s in payload.options.keys() if s in SpecialServiceCode.__members__ ] if is_international and payload.doc_images is not None: special_services.append(SpecialServiceCode.dhl_paperless_trade.value) has_payment_config = payload.payment is not None has_customs_config = payload.customs is not None request = DHLShipmentRequest( schemaVersion=6.2, Request=settings.Request( MetaData=MetaData(SoftwareName="3PV", SoftwareVersion=6.2) ), RegionCode=CountryRegion[payload.shipper.country_code].value, RequestedPickupTime="Y", LanguageCode="en", PiecesEnabled="Y", LatinResponseInd=None, Billing=Billing( ShipperAccountNumber=settings.account_number, BillingAccountNumber=payload.payment.account_number if has_payment_config else None, ShippingPaymentType=PaymentType[payload.payment.paid_by].value if has_payment_config else None, DutyAccountNumber=payload.customs.duty.account_number if has_customs_config else None, DutyPaymentType=PaymentType[payload.customs.duty.paid_by].value if has_customs_config else None, ), Consignee=Consignee( CompanyName=payload.recipient.company_name or " ", SuiteDepartmentName=None, AddressLine=concat_str( payload.recipient.address_line1, payload.recipient.address_line2 ), City=payload.recipient.city, Division=None, DivisionCode=payload.recipient.state_code, PostalCode=payload.recipient.postal_code, CountryCode=payload.recipient.country_code, CountryName=Country[payload.recipient.country_code].value, FederalTaxId=payload.shipper.federal_tax_id, StateTaxId=payload.shipper.state_tax_id, Contact=( Contact( PersonName=payload.recipient.person_name, PhoneNumber=payload.recipient.phone_number or "0000", Email=payload.recipient.email, ) ), Suburb=None, ), Commodity=[ Commodity(CommodityCode=c.sku, CommodityName=c.description) for c in payload.customs.commodities ] if payload.customs is not None else None, NewShipper=None, Shipper=Shipper( ShipperID=settings.account_number or " ", RegisteredAccount=settings.account_number, AddressLine=concat_str( payload.shipper.address_line1, payload.shipper.address_line2 ), CompanyName=payload.shipper.company_name or " ", PostalCode=payload.shipper.postal_code, CountryCode=payload.shipper.country_code, City=payload.shipper.city, CountryName=Country[payload.shipper.country_code].value, Division=None, DivisionCode=payload.shipper.state_code, Contact=( Contact( PersonName=payload.shipper.person_name, PhoneNumber=payload.shipper.phone_number or "0000", Email=payload.shipper.email, ) ), ), ShipmentDetails=DHLShipmentDetails( NumberOfPieces=len(packages), Pieces=Pieces( Piece=[ Piece( PieceID=payload.parcels[index].id, PackageType=( package_type or PackageType[package.packaging_type or "your_packaging"].value ), Depth=package.length.IN, Width=package.width.IN, Height=package.height.IN, Weight=package.weight.LB, DimWeight=None, PieceContents=payload.parcels[index].description, ) for index, package in enumerate(packages) ] ), Weight=packages.weight.LB, CurrencyCode=options.currency or "USD", WeightUnit=WeightUnit.L.value, DimensionUnit=DimensionUnit.I.value, Date=time.strftime("%Y-%m-%d"), PackageType=package_type, IsDutiable="Y" if payload.customs is not None else "N", InsuredAmount=options.insurance.amount if options.insurance else None, ShipmentCharges=options.cash_on_delivery.amount if options.cash_on_delivery else None, DoorTo=delivery_type, GlobalProductCode=product, LocalProductCode=product, Contents=" ", ), EProcShip=None, Dutiable=Dutiable( DeclaredCurrency=payload.customs.duty.currency or "USD", DeclaredValue=payload.customs.duty.amount, TermsOfTrade=payload.customs.terms_of_trade, ) if payload.customs is not None and payload.customs.duty is not None else None, ExportDeclaration=None, Reference=[Reference(ReferenceID=payload.reference)], SpecialService=[ SpecialService(SpecialServiceType=service) for service in special_services ], Notification=Notification( EmailAddress=options.notification.email or payload.shipper.email, ) if options.notification else None, LabelImageFormat="PDF", DocImages=DocImages( DocImage=[ DocImage( Type=doc.type, ImageFormat=doc.format, Image=b64decode(doc.image + "=" * (-len(doc.image) % 4)), ) for doc in payload.doc_images ] ) if len(payload.doc_images) > 0 else None, RequestArchiveDoc=None, NumberOfArchiveDoc=None, Label=None, ODDLinkReq=None, DGs=None, ) return Serializable(request, _request_serializer)
def shipment_request(payload: ShipmentRequest, _) -> Serializable[NonContractShipmentType]: package = Packages(payload.parcels, PackagePresets, required=["weight"]).single service = ServiceType[payload.service].value options = Options(payload.options, OptionCode) is_intl = (payload.recipient.country_code is not None and payload.recipient.country_code != 'CA') all_options = ([*options] + [(OptionCode.canadapost_return_to_sender.name, OptionCode.canadapost_return_to_sender.value.apply(True))] if is_intl and not any(key in options for key in INTERNATIONAL_NON_DELIVERY_OPTION) else [*options]) request = NonContractShipmentType( requested_shipping_point=None, delivery_spec=DeliverySpecType( service_code=service, sender=SenderType( name=payload.shipper.person_name, company=payload.shipper.company_name, contact_phone=payload.shipper.phone_number, address_details=DomesticAddressDetailsType( address_line_1=SF.concat_str(payload.shipper.address_line1, join=True), address_line_2=SF.concat_str(payload.shipper.address_line2, join=True), city=payload.shipper.city, prov_state=payload.shipper.state_code, postal_zip_code=payload.shipper.postal_code, ), ), destination=DestinationType( name=payload.recipient.person_name, company=payload.recipient.company_name, additional_address_info=None, client_voice_number=payload.recipient.phone_number, address_details=DestinationAddressDetailsType( address_line_1=SF.concat_str( payload.recipient.address_line1, join=True), address_line_2=SF.concat_str( payload.recipient.address_line2, join=True), city=payload.recipient.city, prov_state=payload.recipient.state_code, country_code=payload.recipient.country_code, postal_zip_code=payload.recipient.postal_code, ), ), options=(optionsType(option=[ OptionType( option_code=getattr(option, 'key', option), option_amount=getattr(option, 'value', None), option_qualifier_1=None, option_qualifier_2=None, ) for code, option in all_options if code in OptionCode ]) if any(options) else None), parcel_characteristics=ParcelCharacteristicsType( weight=NF.decimal(package.weight.KG, .1), dimensions=dimensionsType( length=NF.decimal(package.length.CM, .1), width=NF.decimal(package.width.CM, .1), height=NF.decimal(package.height.CM, .1), ), unpackaged=None, mailing_tube=None, ), notification=(NotificationType( email=options.notification_email or payload.recipient.email, on_shipment=True, on_exception=True, on_delivery=True, ) if options.notification_email is not None else None), preferences=PreferencesType( show_packing_instructions=False, show_postage_rate=True, show_insured_value=("insurance" in payload.options), ), references=ReferencesType( cost_centre=None, customer_ref_1=payload.reference, customer_ref_2=None, ), customs=(CustomsType( currency=Currency.AUD.value, conversion_from_cad=None, reason_for_export=payload.customs.incoterm, other_reason=payload.customs.content_description, duties_and_taxes_prepaid=payload.customs.duty.account_number, certificate_number=None, licence_number=None, invoice_number=None, sku_list=sku_listType(item=[ SkuType( customs_number_of_units=item.quantity, customs_description=item.description, sku=item.sku, hs_tariff_code=None, unit_weight=WeightUnit.KG.value, customs_value_per_unit=item.value_amount, customs_unit_of_measure=None, country_of_origin=payload.shipper.country_code, province_of_origin=None, ) for item in payload.customs.commodities ]), ) if payload.customs is not None else None), settlement_info=None, ), ) return Serializable(request, _request_serializer)
def shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[ShippingRequest]: package = Packages(payload.parcels).single options = Options(payload.options, Option) product_code = Service.map(payload.service).value_or_key unique_id = getattr(payload, 'id', uuid4().hex) customs = payload.customs or Customs(commodities=[]) request = ShippingRequest( accountNumber=settings.account_number, subAccountNumber=options.asendia_sub_account_number, processingLocation=ProcessingLocation.map( options.asendia_processing_location or "SFO").name, includeRate=True, labelType=LabelType.map(payload.label_type or "PDF").name_or_key, orderNumber=unique_id, dispatchNumber=unique_id, packageID=unique_id, recipientTaxID=payload.recipient.state_tax_id, returnFirstName=payload.shipper.person_name, returnLastName=payload.shipper.person_name, returnCompanyName=payload.shipper.company_name, returnAddressLine1=payload.shipper.address_line1, returnAddressLine2=payload.shipper.address_line2, returnAddressLine3=None, returnProvince=payload.shipper.state_code, returnPostalCode=payload.shipper.postal_code, returnCountryCode=payload.shipper.country_code, returnPhone=payload.shipper.phone_number, returnEmail=payload.shipper.email, recipientFirstName=payload.recipient.person_name, recipientLastName=payload.recipient.person_name, recipientBusinessName=payload.recipient.company_name, recipientAddressLine1=payload.recipient.address_line1, recipientAddressLine2=payload.recipient.address_line2, recipientAddressLine3=None, recipientCity=payload.recipient.city, recipientProvince=payload.recipient.state_code, recipientPostalCode=payload.recipient.postal_code, recipientPhone=payload.recipient.phone_number, recipientEmail=payload.recipient.email, totalPackageWeight=package.weight.value, weightUnit=package.weight_unit.value.lower(), dimLength=package.length.value, dimWidth=package.width.value, dimHeight=package.height.value, dimUnit=package.dimension_unit.value, totalPackageValue=options.declared_value, currencyType=options.currency, productCode=product_code, customerReferenceNumber1=payload.reference, customerReferenceNumber2=None, customerReferenceNumber3=None, contentType=("D" if package.parcel.is_document else "M"), packageContentDescription=package.parcel.description, vatNumber=None, sellerName=payload.shipper.person_name, sellerAddressLine1=payload.shipper.address_line1, sellerAddressLine2=payload.shipper.address_line2, sellerAddressLine3=None, sellerProvince=payload.shipper.state_code, sellerPostalCode=payload.shipper.postal_code, sellerPhone=payload.shipper.phone_number, sellerEmail=payload.shipper.email, items=[ Item(sku=item.sku, itemDescription=item.description, unitPrice=item.value_amount, quantity=item.quantity, unitWeight=Weight(item.weight, package.weight_unit).value, countryOfOrigin=item.origin_country, htsNumber=None) for item in customs.commodities ]) return Serializable(request)
def freight_ship_request( payload: ShipmentRequest, settings: Settings) -> Serializable[FreightShipRequest]: packages = Packages(payload.parcels, PackagePresets) options = Options(payload.options) service = ShippingServiceCode[payload.service].value freight_class = FreightClass[payload.options.get( "ups_freight_class", "ups_freight_class_50")].value request = FreightShipRequest( Request=common.RequestType( RequestOption="1", SubVersion=None, TransactionReference=common.TransactionReferenceType( CustomerContext=payload.reference, TransactionIdentifier=None), ), Shipment=ShipmentType( ShipFrom=ShipFromType( Name=payload.shipper.company_name, TaxIdentificationNumber=payload.shipper.federal_tax_id, TaxIDType=None, TariffPoint=None, Address=FreightShipAddressType( AddressLine=concat_str(payload.shipper.address_line1, payload.shipper.address_line2), City=payload.shipper.city, StateProvinceCode=payload.shipper.state_code, Town=None, PostalCode=payload.shipper.postal_code, CountryCode=payload.shipper.country_code, ), AttentionName=payload.shipper.person_name, Phone=FreightShipPhoneType(Number=payload.shipper.phone_number, Extension=None) if payload.shipper.phone_number is not None else None, FaxNumber=None, EMailAddress=payload.shipper.email, ), ShipperNumber=settings.account_number, ShipTo=ShipToType( Name=payload.recipient.company_name, TaxIdentificationNumber=payload.recipient.federal_tax_id, Address=FreightShipAddressType( AddressLine=concat_str( payload.recipient.address_line1, payload.recipient.address_line2, ), City=payload.recipient.city, StateProvinceCode=payload.recipient.state_code, Town=None, PostalCode=payload.recipient.postal_code, CountryCode=payload.recipient.country_code, ), TariffPoint=None, AttentionName=payload.recipient.person_name, Phone=PhoneType(Number=payload.recipient.phone_number, Extension=None) if payload.recipient.phone_number is not None else None, FaxNumber=None, EMailAddress=payload.recipient.email, ), PaymentInformation=None, ManufactureInformation=None, Service=ShipCodeDescriptionType( Code=service) if service is not None else None, HandlingUnitOne=None, HandlingUnitTwo=None, ExistingShipmentID=None, HandlingInstructions=None, DeliveryInstructions=None, PickupInstructions=None, SpecialInstructions=None, ShipmentTotalWeight=None, Commodity=[ CommodityType( CommodityID=package.parcel.id, Description=package.parcel.description, Weight=WeightType( UnitOfMeasurement=FreightShipUnitOfMeasurementType( Code=WeightUnit[package.weight_unit].value), Value=package.weight.value, ), Dimensions=DimensionsType( UnitOfMeasurement=FreightShipUnitOfMeasurementType( Code=package.dimension_unit), Width=package.width.value, Height=package.height.value, Length=package.length.value, ) if any([ package.width.value, package.height.value, package.length.value, ]) else None, NumberOfPieces=None, PackagingType=None, DangerousGoodsIndicator=None, CommodityValue=None, FreightClass=freight_class, NMFCCommodityCode=None, NMFCCommodity=None, ) for package in packages ], Reference=None, ShipmentServiceOptions=ShipmentServiceOptionsType( EMailInformation=[ EMailNotificationType( EMailAddress=options.notification.email or payload.shipper.email, EventType=NOTIFICATION_EVENT_TYPES, ) ] if options.notification else None, PickupOptions=None, DeliveryOptions=None, OverSeasLeg=None, COD=CODType( CODValue=CODValueType( CurrencyCode=options.currency or "USD", MonetaryValue=options.cash_on_delivery.amount, ), CODPaymentMethod=None, CODBillingOption=None, RemitTo=None, ) if options.cash_on_delivery else None, DangerousGoods=None, SortingAndSegregating=None, DeclaredValue=None, ExcessDeclaredValue=None, CustomsValue=None, DeliveryDutiesPaidIndicator=None, DeliveryDutiesUnpaidIndicator=None, HandlingCharge=None, CustomsClearanceIndicator=None, FreezableProtectionIndicator=None, ExtremeLengthIndicator=None, LinearFeet=None, ) if options.has_content else None, PickupRequest=None, Documents=None, ITNNumber=None, TaxID=None, MovementReferenceNumber=None, EICNumberAndStatement=None, TimeInTransitIndicator=None, HandlingUnits=None, DensityEligibleIndicator=None, ), ) return Serializable( create_envelope(header_content=settings.Security, body_content=request), _request_serializer, )
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[Envelope]: packages = Packages(payload.parcels, PackagePresets, required=["weight"]) service = Services(payload.services, Product).first options = Options(payload.options, Service) package_description = packages[0].parcel.description if len( packages) == 1 else None is_document = all([parcel.is_document for parcel in payload.parcels]) shipper_phone = Phone(payload.shipper.phone_number, payload.shipper.country_code or 'CA') recipient_phone = Phone(payload.recipient.phone_number, payload.recipient.country_code) is_international = payload.shipper.country_code != payload.recipient.country_code option_ids = [(key, value) for key, value in options if key in Service and key not in NON_OFFICIAL_SERVICES] # When no specific service is requested, set a default one. if service is None: show_alternate_services = options[ 'purolator_show_alternative_services'] is not False service = Product['purolator_express_international' if is_international else 'purolator_express'] else: show_alternate_services = options[ 'purolator_show_alternative_services'] is True request = create_envelope( header_content=RequestContext( Version="2.1", Language=settings.language, GroupID="", RequestReference=getattr(payload, 'id', ""), UserToken=settings.user_token, ), body_content=GetFullEstimateRequest( Shipment=Shipment( SenderInformation=SenderInformation( Address=Address( Name=payload.shipper.person_name or "", Company=payload.shipper.company_name, Department=None, StreetNumber="", StreetSuffix=None, StreetName=SF.concat_str(payload.shipper.address_line1, join=True), StreetType=None, StreetDirection=None, Suite=None, Floor=None, StreetAddress2=SF.concat_str( payload.shipper.address_line2, join=True), StreetAddress3=None, City=payload.shipper.city or "", Province=payload.shipper.state_code or "", Country=payload.shipper.country_code or "", PostalCode=payload.shipper.postal_code or "", PhoneNumber=PhoneNumber( CountryCode=shipper_phone.country_code or "0", AreaCode=shipper_phone.area_code or "0", Phone=shipper_phone.phone or "0", Extension=None, ), FaxNumber=None, ), TaxNumber=(payload.shipper.federal_tax_id or payload.shipper.state_tax_id), ), ReceiverInformation=ReceiverInformation( Address=Address( Name=payload.recipient.person_name or "", Company=payload.recipient.company_name, Department=None, StreetNumber="", StreetSuffix=None, StreetName=SF.concat_str( payload.recipient.address_line1, join=True), StreetType=None, StreetDirection=None, Suite=None, Floor=None, StreetAddress2=SF.concat_str( payload.recipient.address_line2, join=True), StreetAddress3=None, City=payload.recipient.city or "", Province=payload.recipient.state_code or "", Country=payload.recipient.country_code or "", PostalCode=payload.recipient.postal_code or "", PhoneNumber=PhoneNumber( CountryCode=recipient_phone.country_code or "0", AreaCode=recipient_phone.area_code or "0", Phone=recipient_phone.phone or "0", Extension=None, ), FaxNumber=None, ), TaxNumber=(payload.recipient.federal_tax_id or payload.recipient.state_tax_id), ), FromOnLabelIndicator=None, FromOnLabelInformation=None, ShipmentDate=options.shipment_date, PackageInformation=PackageInformation( ServiceID=service.value, Description=package_description, TotalWeight=(TotalWeight( Value=packages.weight.map(MeasurementOptions).LB, WeightUnit=PurolatorWeightUnit.LB.value, ) if packages.weight.value is not None else None), TotalPieces=1, PiecesInformation=ArrayOfPiece(Piece=[ Piece( Weight=(PurolatorWeight( Value=package.weight.map(MeasurementOptions). value, WeightUnit=PurolatorWeightUnit[ package.weight_unit.value].value, ) if package.weight.value else None), Length=(PurolatorDimension( Value=package.length.value, DimensionUnit=PurolatorDimensionUnit[ package.dimension_unit.value].value, ) if package.length.value else None), Width=(PurolatorDimension( Value=package.width.value, DimensionUnit=PurolatorDimensionUnit[ package.dimension_unit.value].value, ) if package.width.value else None), Height=(PurolatorDimension( Value=package.height.value, DimensionUnit=PurolatorDimensionUnit[ package.dimension_unit.value].value, ) if package.height.value else None), Options=ArrayOfOptionIDValuePair( OptionIDValuePair=[ OptionIDValuePair(ID=key, Value=value) for key, value in option_ids ]) if any(option_ids) else None, ) for package in packages ]), DangerousGoodsDeclarationDocumentIndicator=None, OptionsInformation=None, ), InternationalInformation=(InternationalInformation( DocumentsOnlyIndicator=is_document, ContentDetails=None, BuyerInformation=None, PreferredCustomsBroker=None, DutyInformation=DutyInformation( BillDutiesToParty=DutyPaymentType.recipient.value, BusinessRelationship=BusinessRelationship.NOT_RELATED. value, Currency=options.currency, ), ImportExportType=None, CustomsInvoiceDocumentIndicator=None, ) if is_international else None), ReturnShipmentInformation=None, PaymentInformation=PaymentInformation( PaymentType=PaymentType.SENDER.value, RegisteredAccountNumber=settings.account_number, ), PickupInformation=PickupInformation( PickupType=PickupType.DROP_OFF.value), NotificationInformation=None, TrackingReferenceInformation=(TrackingReferenceInformation( Reference1=payload.reference) if payload.reference != "" else None), OtherInformation=None, ProactiveNotification=None, ), ShowAlternativeServicesIndicator=show_alternate_services, ), ) return Serializable(request, standard_request_serializer)
def _schedule_pickup_request(payload: Union[PickupRequest, PickupUpdateRequest], settings: Settings) -> Serializable[Envelope]: """ Create a serializable typed Envelope containing a SchedulePickUpRequest Options: - LoadingDockAvailable - TrailerAccessible :param payload: PickupRequest :param settings: Settings :return: Serializable[PickupRequest] """ packages = Packages(payload.parcels, PackagePresets, required=["weight"]) phone = Phone(payload.address.phone_number, payload.address.country_code or 'CA') request = create_envelope( header_content=RequestContext( Version="1.2", Language=settings.language, GroupID="", RequestReference="", UserToken=settings.user_token, ), body_content=SchedulePickUpRequest( BillingAccountNumber=settings.account_number, PartnerID=None, PickupInstruction=PickupInstruction( Date=payload.pickup_date, AnyTimeAfter="".join(payload.ready_time.split(":")), UntilTime="".join(payload.closing_time.split(":")), TotalWeight=Weight(Value=packages.weight.LB, WeightUnit=WeightUnit.LB.value), TotalPieces=len(packages) or 1, BoxesIndicator=None, PickUpLocation=payload.package_location, AdditionalInstructions=payload.instruction, SupplyRequestCodes=None, TrailerAccessible=payload.options.get("TrailerAccessible"), LoadingDockAvailable=payload.options.get( "LoadingDockAvailable"), ShipmentOnSkids=None, NumberOfSkids=None, ), Address=Address( Name=payload.address.person_name or "", Company=payload.address.company_name, Department=None, StreetNumber="", StreetSuffix=None, StreetName=SF.concat_str(payload.address.address_line1, join=True), StreetType=None, StreetDirection=None, Suite=None, Floor=None, StreetAddress2=SF.concat_str(payload.address.address_line2, join=True), StreetAddress3=None, City=payload.address.city, Province=payload.address.state_code, Country=payload.address.country_code, PostalCode=payload.address.postal_code, PhoneNumber=PhoneNumber( CountryCode=phone.country_code or "0", AreaCode=phone.area_code or "0", Phone=phone.phone or "0", Extension=None, ), FaxNumber=None, ), ShipmentSummary=None, NotificationEmails=NotificationEmails( NotificationEmail=[payload.address.email]), ), ) return Serializable(request, partial(standard_request_serializer, version="v1"))
def shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[DHLShipmentRequest]: if any(settings.account_country_code or "") and ( payload.shipper.country_code != settings.account_country_code): raise OriginNotServicedError(payload.shipper.country_code) packages = Packages.map(payload.parcels, PackagePresets, required=["weight"]) options = Options(payload.options, SpecialServiceCode) product = ProductCode.map(payload.service).value_or_key shipper = CompleteAddress.map(payload.shipper) recipient = CompleteAddress.map(payload.recipient) weight_unit, dim_unit = (COUNTRY_PREFERED_UNITS.get( payload.shipper.country_code) or packages.compatible_units) is_document = all(p.parcel.is_document for p in packages) package_type = PackageType[packages.package_type].value label_format, label_template = LabelType[payload.label_type or 'PDF_6x4'].value payment = (payload.payment or Payment(paid_by="sender", account_number=settings.account_number)) customs = (payload.customs or Customs(commodities=[])) is_dutiable = (is_document is False and customs.duty is not None) paperless_supported = (is_dutiable and payload.shipper.country_code not in UNSUPPORTED_PAPERLESS_COUNTRIES) duty = (customs.duty or Duty(paid_by="sender")) bill_to = CompleteAddress.map(duty.bill_to) content = (packages[0].parcel.content or customs.content_description or "N/A") reference = (payload.reference or getattr(payload, 'id', None)) request = DHLShipmentRequest( schemaVersion='10.0', Request=settings.Request( MetaData=MetaData(SoftwareName="3PV", SoftwareVersion='10.0')), RegionCode=CountryRegion[shipper.country_code].value, LanguageCode="en", LatinResponseInd=None, Billing=Billing( ShipperAccountNumber=settings.account_number, ShippingPaymentType=PaymentType[payment.paid_by].value, BillingAccountNumber=payment.account_number, DutyAccountNumber=duty.account_number, ), Consignee=Consignee( CompanyName=recipient.company_name or "N/A", SuiteDepartmentName=recipient.suite, AddressLine1=recipient.address_line1 or recipient.address_line, AddressLine2=SF.concat_str(recipient.address_line2, join=True), AddressLine3=None, City=recipient.city, Division=None, DivisionCode=recipient.state_code, PostalCode=recipient.postal_code, CountryCode=recipient.country_code, CountryName=recipient.country_name, Contact=Contact( PersonName=recipient.person_name, PhoneNumber=recipient.phone_number or "0000", Email=recipient.email, ), Suburb=recipient.suburb, StreetName=recipient.street_name, BuildingName=None, StreetNumber=recipient.street_number, RegistrationNumbers=None, BusinessPartyTypeCode=None, ), Commodity=([ Commodity(CommodityCode=c.sku, CommodityName=c.description) for c in payload.customs.commodities ] if any(customs.commodities) else None), Dutiable=(Dutiable( DeclaredValue=duty.declared_value or options.declared_value or 1.0, DeclaredCurrency=duty.currency or options.currency or "USD", ScheduleB=None, ExportLicense=customs.license_number, ShipperEIN=None, ShipperIDType=None, TermsOfTrade=customs.incoterm, CommerceLicensed=None, Filing=None) if is_dutiable else None), UseDHLInvoice=("Y" if is_dutiable else None), DHLInvoiceLanguageCode=("en" if is_dutiable else None), DHLInvoiceType=(("CMI" if customs.commercial_invoice else "PFI") if is_dutiable else None), ExportDeclaration=(ExportDeclaration( InterConsignee=None, IsPartiesRelation=None, ECCN=None, SignatureName=customs.signer, SignatureTitle=None, ExportReason=customs.content_type, ExportReasonCode=ExportReasonCode[customs.content_type or 'other'].value, SedNumber=None, SedNumberType=None, MxStateCode=None, InvoiceNumber=(customs.invoice or "N/A"), InvoiceDate=(customs.invoice_date or time.strftime("%Y-%m-%d")), BillToCompanyName=bill_to.company_name, BillToContactName=bill_to.person_name, BillToAddressLine=bill_to.address_line, BillToCity=bill_to.city, BillToPostcode=bill_to.postal_code, BillToSuburb=bill_to.extra, BillToCountryName=bill_to.country_name, BillToPhoneNumber=bill_to.phone_number, BillToPhoneNumberExtn=None, BillToFaxNumber=None, BillToFederalTaxID=bill_to.federal_tax_id, Remarks=customs.content_description, DestinationPort=None, TermsOfPayment=None, PayerGSTVAT=bill_to.state_tax_id, SignatureImage=None, ReceiverReference=None, ExporterId=None, ExporterCode=None, ExportLineItem=[ ExportLineItem( LineNumber=index, Quantity=item.quantity, QuantityUnit='PCS', Description=item.description or 'N/A', Value=((item.quantity or 1) * (item.value_amount or 0.0)), IsDomestic=None, CommodityCode=item.sku, ScheduleB=None, ECCN=None, Weight=WeightType( Weight=Weight(item.weight, WeightUnit[item.weight_unit or 'KG'])[weight_unit.name], WeightUnit=DHLWeightUnit[weight_unit.name].value), GrossWeight=WeightType( Weight=Weight(item.weight, WeightUnit[item.weight_unit or 'KG'])[weight_unit.name], WeightUnit=DHLWeightUnit[weight_unit.name].value), License=None, LicenseSymbol=None, ManufactureCountryCode=item.origin_country, ManufactureCountryName=Location( item.origin_country).as_country_name, ImportTaxManagedOutsideDhlExpress=None, AdditionalInformation=None, ImportCommodityCode=None, ItemReferences=None, CustomsPaperworks=None, ) for (index, item) in enumerate(customs.commodities, start=1) ], ShipmentDocument=None, InvoiceInstructions=None, CustomerDataTextEntries=None, PlaceOfIncoterm="N/A", ShipmentPurpose=( "COMMERCIAL" if customs.commercial_invoice else "PERSONAL"), DocumentFunction=None, CustomsDocuments=None, InvoiceTotalNetWeight=None, InvoiceTotalGrossWeight=None, InvoiceReferences=None, ) if is_dutiable else None), Reference=([Reference( ReferenceID=reference)] if any([reference]) else None), ShipmentDetails=DHLShipmentDetails( Pieces=Pieces(Piece=[ Piece( PieceID=index, PackageType=(package_type or PackageType[package.packaging_type or "your_packaging"].value), Depth=package.length.map(MeasurementOptions)[ dim_unit.name], Width=package.width.map(MeasurementOptions)[dim_unit.name], Height=package.height.map(MeasurementOptions)[ dim_unit.name], Weight=package.weight[weight_unit.name], PieceContents=( package.parcel.content or package.parcel.description), PieceReference=([Reference( ReferenceID=package.parcel.id)] if package.parcel. id is not None else None), AdditionalInformation=(AdditionalInformation( CustomerDescription=package.parcel.description ) if package.parcel.description is not None else None)) for (index, package) in enumerate(packages, start=1) ]), WeightUnit=DHLWeightUnit[weight_unit.name].value, GlobalProductCode=product, LocalProductCode=product, Date=(options.shipment_date or time.strftime("%Y-%m-%d")), Contents=content, DimensionUnit=DimensionUnit[dim_unit.name].value, PackageType=package_type, IsDutiable=("Y" if is_dutiable else "N"), CurrencyCode=options.currency or "USD", CustData=getattr(payload, 'id', None), ShipmentCharges=(options.cash_on_delivery if options.cash_on_delivery else None), ParentShipmentIdentificationNumber=None, ParentShipmentGlobalProductCode=None, ParentShipmentPackagesCount=None, ), Shipper=Shipper( ShipperID=settings.account_number or "N/A", CompanyName=shipper.company_name or "N/A", SuiteDepartmentName=shipper.suite, RegisteredAccount=settings.account_number, AddressLine1=shipper.address_line1 or shipper.address_line, AddressLine2=SF.concat_str(shipper.address_line2, join=True), AddressLine3=None, City=shipper.city, Division=None, DivisionCode=shipper.state_code, PostalCode=shipper.postal_code, OriginServiceAreaCode=None, OriginFacilityCode=None, CountryCode=shipper.country_code, CountryName=shipper.country_name, Contact=Contact( PersonName=shipper.person_name, PhoneNumber=shipper.phone_number or "0000", Email=shipper.email, ), Suburb=shipper.suburb, StreetName=shipper.street_name, BuildingName=None, StreetNumber=shipper.street_number, RegistrationNumbers=None, BusinessPartyTypeCode=None, ), SpecialService=([ SpecialService( SpecialServiceType=SpecialServiceCode[key].value.key, ChargeValue=getattr(svc, 'value', None), CurrencyCode=(options.currency or "USD" if hasattr( svc, 'value') else None)) for key, svc in options if key in SpecialServiceCode ] + ( # Add paperless trade if dutiable [SpecialService(SpecialServiceType="WY")] if paperless_supported and 'dhl_paperless_trade' not in options else [])), Notification=(Notification( EmailAddress=options.email_notification_to or recipient.email) if options.email_notification and any([options.email_notification_to, recipient.email]) else None), Place=None, EProcShip=None, Airwaybill=None, DocImages=None, LabelImageFormat=label_format, RequestArchiveDoc=None, NumberOfArchiveDoc=None, RequestQRCode='N', RequestTransportLabel=None, Label=Label(LabelTemplate=label_template), ODDLinkReq=None, DGs=None, GetPriceEstimate='Y', SinglePieceImage='N', ShipmentIdentificationNumber=None, UseOwnShipmentIdentificationNumber='N', Importer=None, ) return Serializable(request, _request_serializer)
def _shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[Envelope]: packages = Packages(payload.parcels, PackagePresets, required=["weight"]) service = Product.map(payload.service).value_or_key options = Options(payload.options, Service) is_document = all([parcel.is_document for parcel in payload.parcels]) package_description = packages[0].parcel.description if len( packages) == 1 else None is_international = (payload.shipper.country_code != payload.recipient.country_code) shipper_phone_number = Phone(payload.shipper.phone_number, payload.shipper.country_code) recipient_phone_number = Phone(payload.recipient.phone_number, payload.recipient.country_code) printing = PrintType.map(payload.label_type or "PDF").value option_ids = [(key, value) for key, value in options if key in Service and key not in NON_OFFICIAL_SERVICES] request = create_envelope( header_content=RequestContext( Version="2.1", Language=settings.language, GroupID="", RequestReference=(getattr(payload, 'id', None) or ""), UserToken=settings.user_token, ), body_content=CreateShipmentRequest( Shipment=Shipment( SenderInformation=SenderInformation( Address=Address( Name=payload.shipper.person_name, Company=payload.shipper.company_name, Department=None, StreetNumber="", StreetSuffix=None, StreetName=SF.concat_str(payload.shipper.address_line1, join=True), StreetType=None, StreetDirection=None, Suite=None, Floor=None, StreetAddress2=SF.concat_str( payload.shipper.address_line2, join=True), StreetAddress3=None, City=payload.shipper.city or "", Province=payload.shipper.state_code or "", Country=payload.shipper.country_code or "", PostalCode=payload.shipper.postal_code or "", PhoneNumber=PhoneNumber( CountryCode=shipper_phone_number.country_code or "0", AreaCode=shipper_phone_number.area_code or "0", Phone=shipper_phone_number.phone or "0", Extension=None, ), FaxNumber=None, ), TaxNumber=(payload.shipper.federal_tax_id or payload.shipper.state_tax_id), ), ReceiverInformation=ReceiverInformation( Address=Address( Name=payload.recipient.person_name, Company=payload.recipient.company_name, Department=None, StreetNumber="", StreetSuffix=None, StreetName=SF.concat_str( payload.recipient.address_line1, join=True), StreetType=None, StreetDirection=None, Suite=None, Floor=None, StreetAddress2=SF.concat_str( payload.recipient.address_line2, join=True), StreetAddress3=None, City=payload.recipient.city or "", Province=payload.recipient.state_code or "", Country=payload.recipient.country_code or "", PostalCode=payload.recipient.postal_code or "", PhoneNumber=PhoneNumber( CountryCode=recipient_phone_number.country_code or "0", AreaCode=recipient_phone_number.area_code or "0", Phone=recipient_phone_number.phone or "0", Extension=None, ), FaxNumber=None, ), TaxNumber=(payload.recipient.federal_tax_id or payload.recipient.state_tax_id), ), FromOnLabelIndicator=None, FromOnLabelInformation=None, ShipmentDate=options.shipment_date, PackageInformation=PackageInformation( ServiceID=service, Description=package_description, TotalWeight=(TotalWeight( Value=packages.weight.map(MeasurementOptions).LB, WeightUnit=PurolatorWeightUnit.LB.value, ) if packages.weight.value else None), TotalPieces=1, PiecesInformation=ArrayOfPiece(Piece=[ Piece( Weight=(PurolatorWeight( Value=package.weight.map(MeasurementOptions). value, WeightUnit=PurolatorWeightUnit[ package.weight_unit.value].value, ) if package.weight.value else None), Length=(PurolatorDimension( Value=package.length.map(MeasurementOptions). value, DimensionUnit=PurolatorDimensionUnit[ package.dimension_unit.value].value, ) if package.length.value else None), Width=(PurolatorDimension( Value=package.width.map(MeasurementOptions). value, DimensionUnit=PurolatorDimensionUnit[ package.dimension_unit.value].value, ) if package.width.value else None), Height=(PurolatorDimension( Value=package.height.map(MeasurementOptions). value, DimensionUnit=PurolatorDimensionUnit[ package.dimension_unit.value].value, ) if package.height.value else None), Options=None, ) for package in packages ]), DangerousGoodsDeclarationDocumentIndicator=None, OptionsInformation=(ArrayOfOptionIDValuePair( OptionIDValuePair=[ OptionIDValuePair(ID=key, Value=value) for key, value in option_ids ]) if any(option_ids) else None), ), InternationalInformation=(InternationalInformation( DocumentsOnlyIndicator=is_document, ContentDetails=(ArrayOfContentDetail(ContentDetail=[ ContentDetail( Description=c.description, HarmonizedCode=None, CountryOfManufacture=c.origin_country, ProductCode=c.sku, UnitValue=c.value_amount, Quantity=c.quantity, NAFTADocumentIndicator=None, FDADocumentIndicator=None, FCCDocumentIndicator=None, SenderIsProducerIndicator=None, TextileIndicator=None, TextileManufacturer=None, ) for c in payload.customs.commodities ]) if not is_document else None), BuyerInformation=None, PreferredCustomsBroker=None, DutyInformation=(DutyInformation( BillDutiesToParty=DutyPaymentType[ payload.customs.duty.paid_by].value, BusinessRelationship=BusinessRelationship.NOT_RELATED. value, Currency=payload.customs.duty.currency, ) if payload.customs is not None else None), ImportExportType=None, CustomsInvoiceDocumentIndicator=None, ) if is_international else None), ReturnShipmentInformation=None, PaymentInformation=(PaymentInformation( PaymentType=PaymentType[payload.payment.paid_by].value, RegisteredAccountNumber=(payload.payment.account_number or settings.account_number), BillingAccountNumber=(payload.payment.account_number or settings.account_number), CreditCardInformation=None, ) if payload.payment is not None else None), PickupInformation=PickupInformation( PickupType=PickupType.DROP_OFF.value), NotificationInformation=( NotificationInformation( ConfirmationEmailAddress=(options.email_notification_to or payload.recipient.email)) if options.email_notification and any([ options.email_notification_to, payload.recipient.email ]) else None), TrackingReferenceInformation=(TrackingReferenceInformation( Reference1=payload.reference) if any(payload.reference or "") else None), OtherInformation=None, ProactiveNotification=None, ), PrinterType=PrinterType(printing).value, ), ) return Serializable(request, standard_request_serializer)
def non_contract_shipment_request( payload: ShipmentRequest, settings: Settings) -> Serializable[NonContractShipmentType]: package = Packages(payload.parcels, PackagePresets).single if package.weight.value is None: raise FieldError({"parcel.weight": FieldErrorCode.required}) service = ServiceType[payload.service].value options = Options(payload.options) def compute_amount(code: str, _: Any): if code == OptionCode.insurance.value: return options.insurance.amount if code == OptionCode.cash_on_delivery.value: return options.cash_on_delivery.amount return None special_services = { OptionCode[name].value: compute_amount(OptionCode[name].value, value) for name, value in payload.options.items() if name in OptionCode.__members__ } request = NonContractShipmentType( requested_shipping_point=None, delivery_spec=DeliverySpecType( service_code=service, sender=SenderType( name=payload.shipper.person_name, company=payload.shipper.company_name, contact_phone=payload.shipper.phone_number, address_details=DomesticAddressDetailsType( address_line_1=concat_str(payload.shipper.address_line1, join=True), address_line_2=concat_str(payload.shipper.address_line2, join=True), city=payload.shipper.city, prov_state=payload.shipper.state_code, postal_zip_code=payload.shipper.postal_code, ), ), destination=DestinationType( name=payload.recipient.person_name, company=payload.recipient.company_name, additional_address_info=None, client_voice_number=None, address_details=DestinationAddressDetailsType( address_line_1=concat_str(payload.recipient.address_line1, join=True), address_line_2=concat_str(payload.recipient.address_line2, join=True), city=payload.recipient.city, prov_state=payload.recipient.state_code, country_code=payload.recipient.country_code, postal_zip_code=payload.recipient.postal_code, ), ), options=optionsType(option=[ OptionType( option_code=code, option_amount=amount, option_qualifier_1=None, option_qualifier_2=None, ) for code, amount in special_services.items() ]) if len(special_services) > 0 else None, parcel_characteristics=ParcelCharacteristicsType( weight=package.weight.KG, dimensions=dimensionsType( length=package.length.CM, width=package.width.CM, height=package.height.CM, ), unpackaged=None, mailing_tube=None, ), notification=NotificationType( email=options.notification.email or payload.shipper.email, on_shipment=True, on_exception=True, on_delivery=True, ) if options.notification else None, preferences=PreferencesType( show_packing_instructions=True, show_postage_rate=True, show_insured_value=("insurance" in payload.options)), references=ReferencesType( cost_centre=None, customer_ref_1=payload.reference, customer_ref_2=None, ), customs=CustomsType( currency=Currency.AUD.value, conversion_from_cad=None, reason_for_export=payload.customs.terms_of_trade, other_reason=payload.customs.description, duties_and_taxes_prepaid=payload.customs.duty.account_number, certificate_number=None, licence_number=None, invoice_number=None, sku_list=sku_listType(item=[ SkuType( customs_number_of_units=item.quantity, customs_description=item.description, sku=item.sku, hs_tariff_code=None, unit_weight=WeightUnit.KG.value, customs_value_per_unit=item.value_amount, customs_unit_of_measure=None, country_of_origin=payload.shipper.country_code, province_of_origin=None, ) for item in payload.customs.commodities ]), ) if payload.customs is not None else None, settlement_info=None, ), ) return Serializable(request, _request_serializer)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[FedexRateRequest]: packages = Packages(payload.parcels, PackagePresets, required=["weight"]) service = Services(payload.services, ServiceType).first options = Options(payload.options) package_type = (PackagingType[packages[0].packaging_type or "your_packaging"].value if len(packages) == 1 else None) request_types = ["LIST" ] + ([] if "currency" not in options else ["PREFERRED"]) request = FedexRateRequest( WebAuthenticationDetail=settings.webAuthenticationDetail, ClientDetail=settings.clientDetail, TransactionDetail=TransactionDetail(CustomerTransactionId="FTC"), Version=VersionId(ServiceId="crs", Major=26, Intermediate=0, Minor=0), ReturnTransitAndCommit=True, CarrierCodes=None, VariableOptions=None, ConsolidationKey=None, RequestedShipment=RequestedShipment( ShipTimestamp=DF.date(options.shipment_date or datetime.now()), DropoffType="REGULAR_PICKUP", ServiceType=(service.value if service is not None else None), PackagingType=package_type, VariationOptions=None, TotalWeight=FedexWeight( Units=WeightUnit.LB.value, Value=packages.weight.LB, ), TotalInsuredValue=None, PreferredCurrency=options.currency, ShipmentAuthorizationDetail=None, Shipper=Party( AccountNumber=settings.account_number, Tins=([ TaxpayerIdentification(TinType=None, Number=tax) for tax in [ payload.shipper.federal_tax_id, payload.shipper.state_tax_id, ] ] if any([ payload.shipper.federal_tax_id, payload.shipper.state_tax_id ]) else None), Contact=Contact( ContactId=None, PersonName=payload.shipper.person_name, Title=None, CompanyName=payload.shipper.company_name, PhoneNumber=payload.shipper.phone_number, PhoneExtension=None, TollFreePhoneNumber=None, PagerNumber=None, FaxNumber=None, EMailAddress=payload.shipper.email, ) if any(( payload.shipper.company_name, payload.shipper.person_name, payload.shipper.phone_number, payload.shipper.email, )) else None, Address=Address( StreetLines=SF.concat_str(payload.shipper.address_line1, payload.shipper.address_line2), City=payload.shipper.city, StateOrProvinceCode=payload.shipper.state_code, PostalCode=payload.shipper.postal_code, UrbanizationCode=None, CountryCode=payload.shipper.country_code, CountryName=None, Residential=None, GeographicCoordinates=None, ), ), Recipient=Party( AccountNumber=None, Tins=[ TaxpayerIdentification(TinType=None, Number=tax) for tax in [ payload.recipient.federal_tax_id, payload.recipient.state_tax_id, ] ] if any([ payload.recipient.federal_tax_id, payload.recipient.state_tax_id ]) else None, Contact=Contact( ContactId=None, PersonName=payload.recipient.person_name, Title=None, CompanyName=payload.recipient.company_name, PhoneNumber=payload.recipient.phone_number, PhoneExtension=None, TollFreePhoneNumber=None, PagerNumber=None, FaxNumber=None, EMailAddress=payload.recipient.email, ) if any(( payload.recipient.company_name, payload.recipient.person_name, payload.recipient.phone_number, payload.recipient.email, )) else None, Address=Address( StreetLines=SF.concat_str( payload.recipient.address_line1, payload.recipient.address_line2, ), City=payload.recipient.city, StateOrProvinceCode=payload.recipient.state_code, PostalCode=payload.recipient.postal_code, UrbanizationCode=None, CountryCode=payload.recipient.country_code, CountryName=None, Residential=None, GeographicCoordinates=None, ), ), RecipientLocationNumber=None, Origin=None, SoldTo=None, ShippingChargesPayment=None, SpecialServicesRequested=None, ExpressFreightDetail=None, FreightShipmentDetail=None, DeliveryInstructions=None, VariableHandlingChargeDetail=None, CustomsClearanceDetail=None, PickupDetail=None, SmartPostDetail=None, BlockInsightVisibility=None, LabelSpecification=None, ShippingDocumentSpecification=None, RateRequestTypes=request_types, EdtRequestType=None, PackageCount=len(packages), ShipmentOnlyFields=None, ConfigurationData=None, RequestedPackageLineItems=[ RequestedPackageLineItem( SequenceNumber=index, GroupNumber=None, GroupPackageCount=1, VariableHandlingChargeDetail=None, InsuredValue=None, Weight=FedexWeight( Units=package.weight_unit.value, Value=package.weight.value, ) if package.weight.value is not None else None, Dimensions=Dimensions( Length=package.length.value, Width=package.width.value, Height=package.height.value, Units=package.dimension_unit.value, ) if any([ package.length.value, package.width.value, package.height.value, ]) else None, PhysicalPackaging=None, ItemDescription=package.parcel.description, ItemDescriptionForClearance=None, CustomerReferences=None, SpecialServicesRequested=None, ContentRecords=None, ) for index, package in enumerate(packages, 1) ], ), ) return Serializable(request, _request_serializer)
def _create_pickup_request( payload: PickupRequest, settings: Settings ) -> Serializable[Envelope]: packages = Packages(payload.parcels, PackagePresets) has_overweight = any(package for package in packages if package.weight.KG > 32) request = create_envelope( header_content=settings.Security, body_content=PickupCreationRequest( Request=RequestType(), RatePickupIndicator="N", TaxInformationIndicator=None, UserLevelDiscountIndicator=None, Shipper=ShipperType( Account=AccountType( AccountNumber=settings.account_number, AccountCountryCode=payload.address.country_code or "", ), ChargeCard=None, TaxInformation=None, ), PickupDateInfo=PickupDateInfoType( CloseTime=DF.ftime(payload.closing_time, "%H:%M", "%H%M"), ReadyTime=DF.ftime(payload.ready_time, "%H:%M", "%H%M"), PickupDate=DF.date(payload.pickup_date).strftime("%Y%m%d"), ), PickupAddress=PickupAddressType( CompanyName=payload.address.company_name, ContactName=payload.address.person_name, AddressLine=SF.concat_str( payload.address.address_line1, payload.address.address_line2 ), Room=None, Floor=None, City=payload.address.city, StateProvince=payload.address.state_code, Urbanization=None, PostalCode=payload.address.postal_code, CountryCode=payload.address.country_code, ResidentialIndicator=("Y" if payload.address.residential else "N"), PickupPoint=payload.package_location, Phone=PhoneType(Number=payload.address.phone_number, Extension=None) if payload.address.phone_number is not None else None, ), AlternateAddressIndicator="Y", PickupPiece=None, TotalWeight=WeightType( Weight=packages.weight.LB, UnitOfMeasurement=WeightUnit.LB.value ), OverweightIndicator=("Y" if has_overweight else "N"), TrackingData=None, TrackingDataWithReferenceNumber=None, PaymentMethod="01", SpecialInstruction=payload.instruction, ReferenceNumber=None, FreightOptions=None, ServiceCategory=None, CashType=None, ShippingLabelsAvailable="Y", ), ) return Serializable( request, default_request_serializer( "v11", 'xmlns:v11="http://www.ups.com/XMLSchema/XOLTWS/Pickup/v1.1"' ), )
def shipment_request( payload: ShipmentRequest, settings: Settings ) -> Serializable[Envelope]: packages = Packages(payload.parcels, PackagePresets) packages.validate(required=["weight"]) options = Options(payload.options, ServiceOption) service = ServiceCode.map(payload.service).value_or_key ship_from = CompleteAddress.map(payload.shipper) ship_to = CompleteAddress.map(payload.shipper) payment_account_number = getattr( payload.payment, "account_number", settings.account_number ) payment_address = getattr(payload.payment, "address", None) mps_packaging = PackagingType.your_packaging.value if len(packages) > 1 else None payer = dict( sender=payment_address or ship_from, recipient=payment_address or ship_to, third_party=payment_address, )[getattr(payload.payment, "paid_by", "sender")] label_format, label_height, label_width = LabelType[ payload.label_type or "PDF_6x4" ].value request = create_envelope( header_content=settings.Security, body_content=FreightShipRequest( Request=RequestType( RequestOption=1, SubVersion=1607, TransactionReference=TransactionReferenceType( CustomerContext=payload.reference, TransactionIdentifier=getattr(payload, "id", None), ), ), Shipment=ShipmentType( ShipFrom=ShipFromType( Name=ship_from.company_name, Address=AddressType( AddressLine=ship_from.address_line, City=ship_from.city, StateProvinceCode=ship_from.state_code, Town=None, PostalCode=ship_from.postal_code, CountryCode=ship_from.country_code, ResidentialAddressIndicator=( "" if ship_from.residential else None ), ), TariffPoint=None, AttentionName=ship_from.person_name, Phone=PhoneType(Number=ship_from.phone_number), FaxNumber=None, EMailAddress=ship_from.email, ), ShipTo=ShipToType( Name=ship_to.company_name, TaxIdentificationNumber=None, Address=AddressType( AddressLine=ship_to.address_line, City=ship_to.city, StateProvinceCode=ship_to.state_code, Town=None, PostalCode=ship_to.postal_code, CountryCode=ship_to.country_code, ResidentialAddressIndicator=( "" if ship_to.residential else None ), ), TariffPoint=None, AttentionName=ship_to.person_name, Phone=PhoneType(Number=ship_to.phone_number), FaxNumber=None, EMailAddress=ship_to.email, ), PaymentInformation=PaymentInformationType( Payer=PayerType( Name=payer.company_name, Address=AddressType( AddressLine=payer.address_line, City=payer.city, StateProvinceCode=payer.state_code, Town=None, CountryCode=payer.country_code, PostalCode=payer.postal_code, ResidentialAddressIndicator=( "" if payer.residential else None ), ), ShipperNumber=payment_account_number, AttentionName=payer.person_name, Phone=PhoneType(Number=payer.phone_number), FaxNumber=None, EMailAddress=payer.email, ), ShipmentBillingOption=ShipCodeDescriptionType( Code=40, Description="Freight Collect" ), ), ManufactureInformation=None, Service=( ShipCodeDescriptionType(Code=service, Description=None) if service is not None else None ), HandlingUnitOne=None, HandlingUnitTwo=None, ExistingShipmentID=None, HandlingInstructions=None, DeliveryInstructions=None, PickupInstructions=None, SpecialInstructions=None, ShipmentTotalWeight=ShipmentTotalWeightType( Value=packages.weight.value, UnitOfMeasurement=UPSWeightUnit[packages.weight.unit].value, ), Commodity=[ CommodityType( CommodityID=getattr(commodity, "id", None), Description=commodity.parcel.description, Weight=WeightType( Value=commodity.weight.value, UnitOfMeasurement=UnitOfMeasurementType( Code=UPSWeightUnit[commodity.weight_unit.name].value, ), ), AdjustedWeight=None, Dimensions=( DimensionsType( UnitOfMeasurement=UnitOfMeasurementType( Code=commodity.dimension_unit.value, Description=None, ), Length=commodity.length.value, Width=commodity.width.value, Height=commodity.height.value, ) if commodity.has_dimensions else None ), NumberOfPieces=1, PackagingType=ShipCodeDescriptionType( Code=( mps_packaging or PackagingType[ commodity.packaging_type or "your_packaging" ].value ), ), DangerousGoodsIndicator=( "" if options.dangerous_good else None ), CommodityValue=None, FreightClass=FreightClass.map( options.freight_class or 50 ).value, NMFCCommodity=None, NMFCCommodityCode=None, ) for commodity in packages ], Reference=( [ ReferenceType( Number=ReferenceNumberType( Code="OTHER", Value=payload.reference ) ) ] if any(payload.reference or "") else None ), ShipmentServiceOptions=( ShipmentServiceOptionsType( EMailInformation=( [ EMailInformationType( EMailType=f"000{email_type}", EMail=options.email_notification_to or payload.recipient.email, ) for email_type in [1, 2, 3, 4] ] if any( [options.email_notification_to, payload.recipient.email] ) else None ), COD=( CODType( CODValue=CODValueType( CurrencyCode=options.currency or "USD", MonetaryValue=options.cash_on_delivery, ), CODPaymentMethod=ShipCodeDescriptionType(Code="M"), CODBillingOption=ShipCodeDescriptionType(Code="02"), RemitTo=RemitToType( Name=payer.company_name, Address=FreightShipAddressType( AddressLine=payer.address_line, City=payer.city, StateProvinceCode=payer.state_code, Town=payer.city, PostalCode=payer.postal_code, CountryCode=payer.country_code, ResidentialAddressIndicator=( "" if payer.residential else None ), ), AttentionName=payer.person_name, Phone=( FreightShipPhoneType(Number=payer.phone_number) if payer.phone_number else None ), FaxNumber=None, EMailAddress=payer.email, ), ) if options.cash_on_delivery else None ), DangerousGoods=( DangerousGoodsType( Name=(ship_from.company_name or ship_from.person_name), Phone=( FreightShipPhoneType(Number=payer.phone_number) if payer.phone_number else None ), ) if options.dangerous_good else None ), DeclaredValue=( DeclaredValueType( CurrencyCode=options.currency or "USD", MonetaryValue=options.declared_value, ) if options.declared_value else None ), ) if any( [ options.cash_on_delivery, options.email_notification, options.dangerous_good, options.declared_value, ] ) else None ), PickupRequest=None, Documents=DocumentsType( Image=ImageType( Type=ShipCodeDescriptionType(Code="30"), LabelsPerPage=1, Format=ShipCodeDescriptionType(Code="01"), PrintFormat=ShipCodeDescriptionType( Code="02" if "ZPL" in label_format else "01" ), PrintSize=PrintSizeType(Length=label_height, Width=label_width), ) ), ITNNumber=None, TaxID=None, MovementReferenceNumber=None, EICNumberAndStatement=None, TimeInTransitIndicator=None, HandlingUnits=None, DensityEligibleIndicator=None, ), ), ) return Serializable(request, _request_serializer)
def _process_shipment(payload: ShipmentRequest, settings: Settings) -> Job: packages = Packages(payload.parcels) options = Options(payload.options, Option) service_type = Service.map(payload.service).value_or_key premium: Optional[bool] = next((True for option, _ in options if option in [ Option.canpar_ten_am.value, Option.canpar_noon.value, Option.canpar_saturday.value, ]), None) shipping_date = DF.fdatetime( options.shipment_date or time.strftime('%Y-%m-%d'), current_format='%Y-%m-%d', output_format='%Y-%m-%dT%H:%M:%S' ) request = create_envelope( body_content=processShipment( request=ProcessShipmentRq( password=settings.password, shipment=Shipment( cod_type=options.canpar_cash_on_delivery, delivery_address=Address( address_line_1=payload.recipient.address_line1, address_line_2=payload.recipient.address_line2, address_line_3=None, attention=payload.recipient.person_name, city=payload.recipient.city, country=payload.recipient.country_code, email=payload.recipient.email, extension=None, name=payload.recipient.company_name, phone=payload.recipient.phone_number, postal_code=payload.recipient.postal_code, province=payload.recipient.state_code, residential=payload.recipient.residential, ), description=None, dg=options.canpar_dangerous_goods, dimention_unit=DimensionUnit.IN.value, handling=None, handling_type=None, instruction=None, nsr=(options.canpar_no_signature_required or options.canpar_not_no_signature_required), packages=[ Package( alternative_reference=None, cod=None, cost_centre=None, declared_value=None, height=pkg.height.CM, length=pkg.length.CM, lg=None, reference=None, reported_weight=pkg.weight.LB, store_num=None, width=pkg.width.CM, xc=('canpar_extra_care' in options) or None ) for pkg in packages ], pickup_address=Address( address_line_1=payload.shipper.address_line1, address_line_2=payload.shipper.address_line2, address_line_3=None, attention=payload.shipper.person_name, city=payload.shipper.city, country=payload.shipper.country_code, email=payload.shipper.email, extension=None, name=payload.shipper.company_name, phone=payload.shipper.phone_number, postal_code=payload.shipper.postal_code, province=payload.shipper.state_code, residential=payload.shipper.residential, ), premium=premium, proforma=None, reported_weight_unit=WeightUnit.LB.value, send_email_to_delivery=payload.recipient.email, send_email_to_pickup=payload.shipper.email, service_type=service_type, shipper_num=None, shipping_date=shipping_date, subtotal=None, subtotal_with_handling=None, total=None, total_with_handling=None, user_id=None, ), user_id=settings.username ) ) ) data = Serializable( request, partial( settings.serialize, extra_namespace='xmlns:xsd1="http://dto.canshipws.canpar.com/xsd"', special_prefixes=dict(shipment_children='xsd1') ) ) return Job(id="process", data=data)
def rate_request( payload: RateRequest, settings: Settings ) -> Serializable[mailing_scenario]: """Create the appropriate Canada Post rate request depending on the destination :param settings: Purplship carrier connection settings :param payload: Purplship unified API rate request data :return: a domestic or international Canada post compatible request :raises: an OriginNotServicedError when origin country is not serviced by the carrier """ if payload.shipper.country_code and payload.shipper.country_code != Country.CA.name: raise OriginNotServicedError(payload.shipper.country_code) package = Packages(payload.parcels, PackagePresets, required=["weight"]).single services = Services(payload.services, ServiceType) options = Options(payload.options, OptionCode) recipient_postal_code = (payload.recipient.postal_code or "").replace(" ", "").upper() shipper_postal_code = (payload.shipper.postal_code or "").replace(" ", "").upper() request = mailing_scenario( customer_number=settings.customer_number, contract_id=settings.contract_id, promo_code=None, quote_type=None, expected_mailing_date=options.shipment_date, options=( optionsType( option=[ optionType( option_code=getattr(option, 'key', option), option_amount=getattr(option, 'value', None) ) for code, option in options if code in OptionCode ] ) if any([c in OptionCode for c, _ in options]) else None ), parcel_characteristics=parcel_characteristicsType( weight=package.weight.map(MeasurementOptions).KG, dimensions=dimensionsType( length=package.length.map(MeasurementOptions).CM, width=package.width.map(MeasurementOptions).CM, height=package.height.map(MeasurementOptions).CM, ), unpackaged=None, mailing_tube=None, oversized=None, ), services=( servicesType( service_code=[svc.value for svc in services] ) if any(services) else None ), origin_postal_code=shipper_postal_code, destination=destinationType( domestic=( domesticType(postal_code=recipient_postal_code) if (payload.recipient.country_code == Country.CA.name) else None ), united_states=( united_statesType(zip_code=recipient_postal_code) if (payload.recipient.country_code == Country.US.name) else None ), international=( internationalType(country_code=recipient_postal_code) if ( payload.recipient.country_code not in [Country.US.name, Country.CA.name] ) else None ), ), ) return Serializable(request, _request_serializer)