def get_full_estimate_request( payload: RateRequest, settings: Settings ) -> Serializable[Envelope]: packages = Packages(payload.parcels, PackagePresets, required=["weight"]) package_description = (packages[0].parcel.description if len(packages) == 1 else None) is_document = all([parcel.is_document for parcel in payload.parcels]) options = Options(payload.options) shipper_phone_number = Phone(payload.shipper.phone_number) recipient_phone_number = Phone(payload.recipient.phone_number) is_international = payload.shipper.country_code != payload.recipient.country_code service = next((Product[s].value for s in payload.services if s in Product.__members__), None) default_service = ( Product.purolator_express_international if is_international else Product.purolator_express ).value request = create_envelope( header_content=RequestContext( Version="2.1", Language=settings.language, GroupID="", RequestReference="", 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=concat_str(payload.shipper.address_line1, join=True), StreetType=None, StreetDirection=None, Suite=None, Floor=None, StreetAddress2=concat_str( payload.shipper.address_line2, join=True ), StreetAddress3=None, City=payload.shipper.city, Province=payload.shipper.state_code, Country=payload.shipper.country_code, PostalCode=payload.shipper.postal_code, 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 or "", Company=payload.recipient.company_name, Department=None, StreetNumber="", StreetSuffix=None, StreetName=concat_str( payload.recipient.address_line1, join=True ), StreetType=None, StreetDirection=None, Suite=None, Floor=None, StreetAddress2=concat_str( payload.recipient.address_line2, join=True ), StreetAddress3=None, City=payload.recipient.city, Province=payload.recipient.state_code, Country=payload.recipient.country_code, PostalCode=payload.recipient.postal_code, 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=datetime.today().strftime("%Y-%m-%d"), PackageInformation=PackageInformation( ServiceID=(service or default_service), Description=package_description, TotalWeight=TotalWeight( Value=packages.weight.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.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=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=service is None, ), ) return Serializable(request, standard_request_serializer)
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: str = next( (RatingServiceCode[s].value for s in payload.services if s in RatingServiceCode.__members__), None ) if (service is not None) and (("freight" in service) or ("ground" in service)) and ( packages.weight.value is None ): raise FieldError({"parcel.weight": FieldErrorCode.required}) mps_packaging = RatingPackagingType.ups_unknown.value if len(packages) > 1 else None request = UPSRateRequest( Request=RequestType( RequestOption=["Shop", "Rate"], SubVersion=None, TransactionReference=TransactionReferenceType( CustomerContext=payload.reference, TransactionIdentifier=None ), ), PickupType=None, CustomerClassification=None, Shipment=ShipmentType( OriginRecordTransactionTimestamp=None, Shipper=ShipperType( Name=payload.shipper.company_name, ShipperNumber=settings.account_number, Address=ShipAddressType( AddressLine=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=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, 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 RatingPackagingType[package.packaging_type or "small_box"].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 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 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"]) package_type = (PackagingType[packages[0].packaging_type or "your_packaging"].value if len(packages) == 1 else None) service = next((ServiceType[s].value for s in payload.services if s in ServiceType.__members__), None) options = Options(payload.options) 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=datetime.now(), DropoffType="REGULAR_PICKUP", ServiceType=service, PackagingType=package_type, VariationOptions=None, TotalWeight=FedexWeight( Units=WeightUnits.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=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=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=( ["LIST"] + ([] if "currency" not in payload.options else ["PREFERRED"])), 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 contract_shipment_request( payload: ShipmentRequest, settings: Settings ) -> Serializable[ShipmentType]: parcel_preset = ( PackagePresets[payload.parcel.package_preset].value if payload.parcel.package_preset else None ) package = Package(payload.parcel, parcel_preset) if package.weight.value is None: raise RequiredFieldError("parcel.weight") 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__ } payment_type = ( PaymentType[payload.payment.paid_by].value if payload.payment is not None else None ) 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=None, 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, 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=concat_str(payload.shipper.address_line1, join=True), address_line_2=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=None, 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=concat_str( payload.recipient.address_line1, join=True ), address_line_2=concat_str( payload.recipient.address_line2, join=True ), ), ), 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, ), 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, notification=NotificationType( email=options.notification.email or payload.shipper.email, on_shipment=True, on_exception=True, on_delivery=True, ) if options.notification else None, print_preferences=PrintPreferencesType( output_format=PrinterType[options.printing or "regular"].value, encoding=None, ), preferences=PreferencesType( service_code=None, show_packing_instructions=True, show_postage_rate=True, show_insured_value=True, ), 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=DimensionUnit.CM.value, 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, ) return Serializable(request, _request_serializer)