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 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 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 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, RatingServiceCode).first if ((service is not None) and (("freight" in service.value) or ("ground" in service.value))): packages.validate(required=["weight"]) 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=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 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, )