def rate_request(payload: RateRequest, settings: Settings) -> Serializable[Envelope]: packages = Packages(payload.parcels) product = Services(payload.services, Service).first request = create_envelope(body_content=GetEstimatedCharges( AuthenicateAccount=Authenticate( AccountID=settings.account_id, Password=settings.password, ), PkgInfo=PackgeInfoToGetCharges( Product=(product or Service.ics_courier_ground.value), Pieces=ArrayOfPieceInfo(PieceInfo=[ PieceInfo( Weight=piece.weight.value, WeightUnit=piece.weight.unit, Length=piece.length.value, Width=piece.width.value, Height=piece.height.value, DeclaredValue=None, ) for piece in packages ]), FromPost=payload.shipper.postal_code, ToPost=payload.recipient.postal_code, ))) return Serializable(request, lambda _: (product, Settings.serialize(_)))
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) request = mailing_scenario( customer_number=settings.customer_number, contract_id=None, 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=payload.shipper.postal_code, destination=destinationType( domestic=( domesticType(postal_code=payload.recipient.postal_code) if (payload.recipient.country_code == Country.CA.name) else None), united_states=( united_statesType(zip_code=payload.recipient.postal_code) if (payload.recipient.country_code == Country.US.name) else None), international=(internationalType( country_code=payload.recipient.postal_code) if (payload.recipient.country_code not in [ Country.US.name, Country.CA.name ]) else None), ), ) return Serializable(request, _request_serializer)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[IntlRateV2Request]: package = Packages(payload.parcels, max_weight=Weight(70, WeightUnit.LB)).single services = Services(payload.options.keys(), RateService) extra_services = Services(payload.services, ExtraService) commercial = "Y" if "commercial" in services else "N" commercial_plus = "Y" if "plus" in services else "N" country = (Country[payload.recipient.country_code].value if payload.recipient.country_code else None) request = IntlRateV2Request( USERID=settings.username, Revision="2", Package=[ PackageType( ID=0, Pounds=package.weight.LB, Ounces=package.weight.OZ, Machinable=("usps_machinable" in payload.options), MailType=IntlPackageType[package.packaging_type or "package"].value, GXG=None, ValueOfContents=None, Country=country, 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=datetime.today().strftime( "%Y-%m-%dT%H:%M:%S"), DestinationPostalCode=payload.recipient.postal_code, ExtraServices=ExtraServicesType( ExtraService=[s.value for s in extra_services]), Content=None, ) ], ) return Serializable(request, XP.export)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[RateV4Request]: package = Packages(payload.parcels).single options = Options(payload.options) service = Services(payload.services, RateService).first or RateService.usps_all special_services = Services(payload.options.keys(), SpecialService) request = RateV4Request( USERID=settings.username, Revision="2", Package=[ PackageType( ID=0, Service=service.value, FirstClassMailType=FirstClassMailType[ package.packaging_type or "your_packaging"].value, ZipOrigination=payload.shipper.postal_code, ZipDestination=payload.recipient.postal_code, Pounds=package.weight.LB, Ounces=package.weight.OZ, Container=Container[package.packaging_type or "your_packaging"].value, Width=package.width.IN, Length=package.length.IN, Height=package.height.IN, Girth=package.girth.value, Value=None, AmountToCollect=options.cash_on_delivery, SpecialServices=SpecialServicesType( SpecialService=[s.value for s in special_services]), Content=None, GroundOnly=None, SortBy=None, Machinable=("usps_machinable" in options), ReturnLocations=None, ReturnServiceInfo=None, DropOffTime=None, ShipDate=ShipDateType( valueOf_=str(datetime.today().strftime("%Y-%m-%d"))), ) ], ) return Serializable(request, XP.export)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[DicomRateRequest]: packages = Packages(payload.parcels) service = (Services(payload.services, Service).first or Service.dicom_ground_delivery).value options = Options(payload.options, Option) request = DicomRateRequest( category="Parcel", paymentType=PaymentType.prepaid.value, deliveryType=service, unitOfMeasurement=UnitOfMeasurement.KC.value, sender=Address(postalCode=payload.shipper.postal_code, provinceCode=payload.shipper.state_code, countryCode=payload.shipper.country_code, name=(payload.shipper.company_name or payload.shipper.person_name)), consignee=Address(postalCode=payload.recipient.postal_code, provinceCode=payload.recipient.state_code, countryCode=payload.recipient.country_code, name=(payload.recipient.company_name or payload.recipient.person_name)), parcels=[ Parcel( quantity=1, parcelType=ParcelType[package.packaging_type or "dicom_box"].value, id=None, weight=package.weight.KG, length=package.height.CM, depth=package.length.CM, width=package.width.CM, note=None, status=None, FCA_Class=None, hazmat=None, requestReturnLabel=None, returnWaybill=None, ) for package in packages ], billing=settings.billing_account, promoCodes=None, surcharges=[ Surcharge(type=getattr(option, 'key', option), value=getattr(option, 'value', None)) for _, option in options ], appointment=None, ) return Serializable(request, DP.to_dict)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[priceRequest]: options = Options(payload.options, ShipmentOption) package = Packages(payload.parcels).single service = Services(payload.services, ShipmentService).first option_codes = [code for label, code in options if 'division' not in label] request = priceRequest( appId=settings.username, appVersion="3.0", priceCheck=priceCheck( rateId=None, sender=address(country=payload.shipper.country_code, town=payload.shipper.city, postcode=payload.shipper.postal_code), delivery=address(country=payload.recipient.country_code, town=payload.recipient.city, postcode=payload.recipient.postal_code), collectionDateTime=DF.fdatetime(options.shipment_date, output_format='%Y-%m-%dT%H:%M:%S'), product=product( id=getattr(service, 'value', None), division=next( (code for label, code in options if 'division' in label), None), productDesc=None, type_=('D' if package.parcel.is_document else 'N'), options=(optionsType( option=[option(optionCode=code) for code in option_codes]) if any(option_codes) else None)), account=(account( accountNumber=settings.account_number, accountCountry=settings.account_country_code, ) if any([settings.account_number, settings.account_country_code]) else None), insurance=(insurance(insuranceValue=options.insurance, goodsValue=options.insurance) if options.insurance is not None else None), termsOfPayment=PaymentType.sender.value, currency=options.currency, priceBreakDown=True, consignmentDetails=consignmentDetails( totalWeight=package.weight.KG, totalVolume=package.volume.value, totalNumberOfPieces=1, ), pieceLine=None), ) return Serializable(request, XP.to_xml)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[UPSRateRequest]: packages = Packages(payload.parcels, PackagePresets) is_document = all([parcel.is_document for parcel in payload.parcels]) service = Services(payload.services, ServiceCode).first mps_packaging = PackagingType.ups_unknown.value if len( packages) > 1 else None request = UPSRateRequest( Request=RequestType( RequestOption=["Shop", "Rate"], SubVersion=None, TransactionReference=TransactionReferenceType( CustomerContext=payload.reference, TransactionIdentifier=getattr(payload, 'id', None)), ), PickupType=None, CustomerClassification=None, Shipment=ShipmentType( OriginRecordTransactionTimestamp=None, Shipper=ShipperType( Name=payload.shipper.company_name, ShipperNumber=settings.account_number, Address=ShipAddressType( AddressLine=SF.concat_str( payload.recipient.address_line1, payload.recipient.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, Address=ShipToAddressType( 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, ResidentialAddressIndicator=None, ), ), ShipFrom=None, AlternateDeliveryAddress=None, ShipmentIndicationType=None, PaymentDetails=None, FRSPaymentInformation=None, FreightShipmentInformation=None, GoodsNotInFreeCirculationIndicator=None, Service=(UOMCodeDescriptionType(Code=service.value, Description=None) if service is not None else None), NumOfPieces=None, # Only required for Freight ShipmentTotalWeight= None, # Only required for "timeintransit" requests DocumentsOnlyIndicator=("" if is_document else None), Package=[ PackageType( PackagingType=UOMCodeDescriptionType( Code=(mps_packaging or PackagingType[package.packaging_type or "your_packaging"].value), Description=None, ), Dimensions=(DimensionsType( UnitOfMeasurement=UOMCodeDescriptionType( Code=package.dimension_unit.value, Description=None), Length=package.length.value, Width=package.width.value, Height=package.height.value, ) if any([ package.length.value, package.height.value, package.width.value, ]) else None), DimWeight=None, PackageWeight=PackageWeightType( UnitOfMeasurement=UOMCodeDescriptionType( Code=UPSWeightUnit[package.weight_unit.name].value, Description=None, ), Weight=package.weight.value, ) if package.weight.value else None, Commodity=None, PackageServiceOptions=None, AdditionalHandlingIndicator=None, ) for package in packages ], ShipmentServiceOptions=None, ShipmentRatingOptions=ShipmentRatingOptionsType( NegotiatedRatesIndicator=""), InvoiceLineTotal=None, RatingMethodRequestedIndicator=None, TaxInformationIndicator=None, PromotionalDiscountInformation=None, DeliveryTimeInformation=TimeInTransitRequestType( PackageBillType="02" if is_document else "03"), ), ) return Serializable( create_envelope(header_content=settings.Security, body_content=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) 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].value if service.value in ["All", "Online"] else None) mail_type = (FirstClassMailType[container.name].value if 'first_class' in service.value else None) request = RateV4Request( USERID=settings.username, Revision="2", Package=[ PackageType( ID=0, Service=service.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 for s in special_services]) if any(special_services) else None), Content=None, GroundOnly=options.usps_option_ground_only, SortBy=sort_level, Machinable=(options.usps_option_machinable_item or False), 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)) if options.shipment_date is not None else None), ) ], ) return Serializable(request, XP.export)
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 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") country = ( Country[payload.recipient.country_code].value if payload.recipient.country_code else None ) 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"], MailType=PackagingType[package.packaging_type or "package"].value, GXG=None, ValueOfContents=None, Country=country, 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=datetime.today().strftime("%Y-%m-%dT%H:%M:%S"), DestinationPostalCode=payload.recipient.postal_code, ExtraServices=( ExtraServicesType( ExtraService=[ getattr(option, 'value', option) for option in extra_services ] ) if any(extra_services) else None ), Content=None, ) ], ) return Serializable(request, XP.export)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[DCTRequest]: packages = Packages(payload.parcels, PackagePresets, required=["weight"]) products = [*Services(payload.services, ProductCode)] options = Options(payload.options, SpecialServiceCode) 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 if not is_international and payload.shipper.country_code in ["CA"]: raise DestinationNotServicedError(payload.shipper.country_code) paperless = (SpecialServiceCode.dhl_paperless_trade if (is_international and is_dutiable) else None) special_services = [ *options, *([(paperless.name, None)] if paperless is not None else []) ] insurance = options[ 'dhl_shipment_insurance'].value if 'dhl_shipment_insurance' in options else None if len(products) == 0: if is_international and is_document: product = 'dhl_express_worldwide_doc' elif is_international: product = 'dhl_express_worldwide_nondoc' elif is_document: product = 'dhl_express_worldwide_doc' else: product = 'dhl_express_easy_nondoc' products = [ProductCode[product]] 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 insurance is not None else None), InsuredValue=insurance, PaymentType=None, AcctPickupCloseTime=None, QtdShp=[ QtdShpType( GlobalProductCode=product.value, LocalProductCode=product.value, QtdShpExChrg=[ QtdShpExChrgType( SpecialServiceType=SpecialServiceCode[key].value. key) for key, _ in special_services if key in SpecialServiceCode ], ) for product in products ], ), Dutiable=(DCTDutiable( DeclaredValue=insurance or 1.0, DeclaredCurrency=options.currency or CountryCurrency[payload.shipper.country_code].value) if is_international and is_dutiable else None), ), ) return Serializable(request, _request_serializer)
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, partial( settings.serialize, extra_namespace='xmlns:xsd1="http://dto.canshipws.canpar.com/xsd"', special_prefixes=dict(shipment_children='xsd1')))
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 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 rate_request(payload: RateRequest, settings: Settings) -> Serializable[Envelope]: packages = Packages(payload.parcels, PackagePresets) packages.validate(required=["weight"]) options = Options(payload.options, ServiceOption) service = Services(payload.services, ServiceCode).first ship_from = CompleteAddress.map(payload.shipper) ship_to = CompleteAddress.map(payload.shipper) mps_packaging = PackagingType.ups_freight_other.value if len( packages) > 1 else None request = create_envelope( header_content=settings.Security, body_content=FreightRateRequest( Request=RequestType( RequestOption=[1], SubVersion=1707, TransactionReference=TransactionReferenceType( CustomerContext=payload.reference, TransactionIdentifier=getattr(payload, "id", None), ), ), 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, CountryCode=ship_from.country_code, ResidentialAddressIndicator=("" if ship_from.residential else None), ), AttentionName=ship_from.person_name, TariffPoint=None, ), ShipTo=ShipToType( Name=ship_to.company_name, Address=AddressType( AddressLine=[ship_to.address_line], City=ship_to.city, StateProvinceCode=ship_to.state_code, Town=None, CountryCode=ship_to.country_code, ResidentialAddressIndicator=("" if ship_to.residential else None), ), AttentionName=ship_to.person_name, TariffPoint=None, ), PaymentInformation=PaymentInformationType( Payer=PayerType( Name=ship_from.company_name, Address=AddressType( AddressLine=[ship_from.address_line], City=ship_from.city, StateProvinceCode=ship_from.state_code, Town=None, CountryCode=ship_from.country_code, ResidentialAddressIndicator=( "" if ship_from.residential else None), ), AttentionName=ship_from.person_name, ShipperNumber=settings.account_number, ), ShipmentBillingOption=RateCodeDescriptionType( Code=40, Description="Freight Collect"), ), Service=(RateCodeDescriptionType(Code=service, Description=None) if service is not None else None), HandlingUnitOne=None, HandlingUnitTwo=None, 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=RateCodeDescriptionType( Code=(mps_packaging or PackagingType[ commodity.packaging_type or "small_box"].value, )), DangerousGoodsIndicator=None, CommodityValue=None, FreightClass=None, NMFCCommodity=None, NMFCCommodityCode=None, ) for commodity in packages ], ShipmentServiceOptions=(ShipmentServiceOptionsType( PickupOptions=None, DeliveryOptions=None, OverSeasLeg=None, COD=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, AdjustedHeight=None, ) if any([ options.cash_on_delivery, options.email_notification, options.dangerous_good, options.declared_value, ]) else None), PickupRequest=None, AlternateRateOptions=RateCodeDescriptionType(Code=3), GFPOptions=None, AccountType=None, ShipmentTotalWeight=ShipmentTotalWeightType( Value=packages.weight.value, UnitOfMeasurement=UnitOfMeasurementType( Code=UPSWeightUnit[packages.weight.unit].value, ), ), HandlingUnitWeight=None, AdjustedWeightIndicator=None, TimeInTransitIndicator="", HandlingUnits=None, AdjustedHeightIndicator=None, DensityEligibleIndicator=None, QuoteNumberIndicator="", ), ) return Serializable(request, _request_serializer)
def quote_request(payload: RateRequest, settings: Settings) -> Serializable[EShipper]: options = Options(payload.options, Option) packages = Packages(payload.parcels, required=["weight", "height", "width", "length"]) packaging_type = PackagingType[packages.package_type or "eshipper_boxes"].value packaging = ("Pallet" if packaging_type in [PackagingType.pallet.value] else "Package") service = (Services(payload.services, Service).first or Service.eshipper_all) freight_class = next( (FreightClass[c].value for c in payload.options.keys() if c in FreightClass), None, ) request = EShipper( username=settings.username, password=settings.password, version="3.0.0", QuoteRequest=QuoteRequestType( 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.value, stackable=options.eshipper_stackable, From=FromType( id=payload.shipper.id, company=payload.shipper.company_name or " ", 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 or " ", 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=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, ), ), ) return Serializable(request, standard_request_serializer)