def get_shipping_documents_request( pin: str, payload: ShipmentRequest, settings: Settings) -> Serializable[Envelope]: is_international = payload.shipper.country_code != payload.recipient.country_code label_type = PrintType.map(payload.label_type or 'PDF').name document_type = SF.concat_str( ("International" if is_international else "Domestic"), "BillOfLading", ("Thermal" if label_type == "ZPL" else ""), separator="", join=True) request = create_envelope( header_content=RequestContext( Version="1.3", Language=settings.language, GroupID="", RequestReference=(getattr(payload, 'id', None) or ""), UserToken=settings.user_token, ), body_content=GetDocumentsRequest( OutputType=label_type, Synchronous=True, DocumentCriterium=ArrayOfDocumentCriteria(DocumentCriteria=[ DocumentCriteria(PIN=PIN(Value=pin), DocumentTypes=DocumentTypes( DocumentType=[document_type])) ]), ), ) return Serializable(request, _request_serializer)
def _request_serializer(request: ProcessShipmentRequest) -> str: namespacedef_ = 'xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v25="http://fedex.com/ws/ship/v25"' envelope = create_envelope(body_content=request) envelope.Body.ns_prefix_ = envelope.ns_prefix_ apply_namespaceprefix(envelope.Body.anytypeobjs_[0], "v25") return export(envelope, namespacedef_=namespacedef_)
def _request_serializer(request: TrackRequest) -> str: namespacedef_ = 'xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v18="http://fedex.com/ws/track/v18"' envelope = create_envelope(body_content=request) envelope.Body.ns_prefix_ = envelope.ns_prefix_ apply_namespaceprefix(envelope.Body.anytypeobjs_[0], "v18") return XP.export(envelope, namespacedef_=namespacedef_)
def _request_serializer(request: FedexRateRequest) -> str: namespacedef_ = 'xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:v26="http://fedex.com/ws/rate/v26"' envelope = create_envelope(body_content=request) envelope.Body.ns_prefix_ = envelope.ns_prefix_ apply_namespaceprefix(envelope.Body.anytypeobjs_[0], "v26") return export(envelope, namespacedef_=namespacedef_)
def _request_serializer(request: ProcessShipmentRequest) -> str: return clean_namespaces( export( create_envelope(body_content=request), namespacedef_='tns:Envelope xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://fedex.com/ws/ship/v25"', ), envelope_prefix="tns:", body_child_prefix="ns:", body_child_name="ProcessShipmentRequest", )
def _request_serializer(request: TrackRequest) -> str: return clean_namespaces( export( create_envelope(body_content=request), namespacedef_= 'tns:Envelope xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v18="http://fedex.com/ws/track/v18"', ), envelope_prefix="tns:", body_child_prefix="ns:", body_child_name="TrackRequest", )
def track_package_by_pin_request(payload: TrackingRequest, settings: Settings) -> Serializable[Envelope]: request = create_envelope( header_content=RequestContext( Version="1.2", Language=settings.language, GroupID="", RequestReference="", UserToken=settings.user_token, ), body_content=TrackPackagesByPinRequest(PINs=ArrayOfPIN( PIN=[PIN(Value=pin) for pin in payload.tracking_numbers])), ) return Serializable(request, _request_serializer)
def track_request(payload: TrackingRequest, settings: Settings) -> Serializable[List[Envelope]]: requests = [ create_envelope( header_content=settings.Security, body_content=TrackRequest( Request=RequestType( RequestOption=[1], TransactionReference=TransactionReferenceType( TransactionIdentifier="TransactionIdentifier"), ), InquiryNumber=number, ), ) for number in payload.tracking_numbers ] return Serializable(requests, _request_serializer)
def get_shipping_documents_request( pin: str, payload: ShipmentRequest, settings: Settings) -> Serializable[Envelope]: request = create_envelope( header_content=RequestContext( Version="1.3", Language=settings.language, GroupID="", RequestReference="", UserToken=settings.user_token, ), body_content=GetDocumentsRequest( OutputType="PDF", Synchronous=True, DocumentCriterium=ArrayOfDocumentCriteria(DocumentCriteria=[ DocumentCriteria(PIN=PIN(Value=pin), DocumentTypes=None) ]), ), ) return Serializable(request, _request_serializer)
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 create_shipping_request(payload: ShipmentRequest, settings: Settings, validate: bool = None) -> Serializable[Envelope]: RequestType: ShipmentRequestType = ValidateShipmentRequest if validate else CreateShipmentRequest packages = Packages(payload.parcels, PackagePresets, required=["weight"]) is_document = all([parcel.is_document for parcel in payload.parcels]) package_description = (packages[0].parcel.description if len(packages) == 1 else None) service = Product[payload.service].value is_international = payload.shipper.country_code != payload.recipient.country_code options = Options(payload.options) shipper_phone_number = Phone(payload.shipper.phone_number) recipient_phone_number = Phone(payload.recipient.phone_number) printing = PrinterType[options.printing or "regular"].value special_services = { Service[name].value: value for name, value in payload.options.items() if name in Service.__members__ } request = create_envelope( header_content=RequestContext( Version="2.1", Language=settings.language, GroupID="", RequestReference="", UserToken=settings.user_token, ), body_content=RequestType( Shipment=Shipment( SenderInformation=SenderInformation( Address=Address( Name=payload.shipper.person_name, 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, AreaCode=shipper_phone_number.area_code, Phone=shipper_phone_number.phone, 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=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, AreaCode=recipient_phone_number.area_code, Phone=recipient_phone_number.phone, 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, Description=package_description, TotalWeight=TotalWeight( Value=packages.weight.value, WeightUnit=PurolatorWeightUnit.LB.value, ) if packages.weight.value 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=ArrayOfOptionIDValuePair( OptionIDValuePair=[ OptionIDValuePair(ID=key, Value=value) for key, value in special_services.items() ]) if len(special_services) > 0 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=CreditCardInformation( Type=payload.payment.credit_card.type, Number=payload.payment.credit_card.number, Name=payload.payment.credit_card.name, ExpiryMonth=payload.payment.credit_card.expiry_month, ExpiryYear=payload.payment.credit_card.expiry_year, CVV=payload.payment.credit_card.security_code, BillingPostalCode=payload.payment.credit_card. postal_code, ) if payload.payment.credit_card is not None else None, ) if payload.payment is not None else None, PickupInformation=PickupInformation( PickupType=PickupType.DROP_OFF.value), NotificationInformation=NotificationInformation( ConfirmationEmailAddress=options.notification.email or payload.shipper.email, AdvancedShippingNotificationMessage=None, ) if options.notification else None, TrackingReferenceInformation=TrackingReferenceInformation( Reference1=payload.reference), OtherInformation=None, ProactiveNotification=None, ), PrinterType=PurolatorPrinterType(printing).value, ), ) 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 freight_ship_request( payload: ShipmentRequest, settings: Settings ) -> Serializable[FreightShipRequest]: dimension_unit = DimensionUnit[payload.parcel.dimension_unit or "IN"] weight_unit = WeightUnit[payload.parcel.weight_unit or "LB"] 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=payload.parcel.id, Description=payload.parcel.description, Weight=WeightType( UnitOfMeasurement=FreightShipUnitOfMeasurementType( Code=UPSWeightUnit[weight_unit.name].value ), Value=Weight(payload.parcel.weight, weight_unit).value, ), Dimensions=DimensionsType( UnitOfMeasurement=FreightShipUnitOfMeasurementType( Code=dimension_unit.value ), Width=Dimension(payload.parcel.width, dimension_unit).value, Height=Dimension(payload.parcel.height, dimension_unit).value, Length=Dimension(payload.parcel.length, dimension_unit).value, ) if any( [ payload.parcel.width, payload.parcel.height, payload.parcel.length, ] ) else None, NumberOfPieces=None, PackagingType=None, DangerousGoodsIndicator=None, CommodityValue=None, FreightClass=freight_class, NMFCCommodityCode=None, NMFCCommodity=None, ) ], 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 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 (("freight" in service) or ("ground" in service)) and ( packages.weight.value is None ): raise FieldError({"parcel.weight": FieldErrorCode.required}) 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 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=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=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=CreditCardType( Type=payment.credit_card.type, Number=payment.credit_card.number, ExpirationDate=( f"{payment.credit_card.expiry_year}{payment.credit_card.expiry_month}" ), SecurityCode=payment.credit_card.security_code, Address=CreditCardAddressType( AddressLine=concat_str( payload.shipper.address_line1, payload.shipper.address_line2, ), City=payload.shipper.city, StateProvinceCode=payload.shipper.state_code, PostalCode=payload.payment.credit_card.postal_code or payload.shipper.postal_code, CountryCode=payload.shipper.country_code, ), ) if payment.credit_card is not None else 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.amount, ), ) if options.cash_on_delivery else None, Notification=[ NotificationType( NotificationCode=event, EMail=EmailDetailsType( EMailAddress=[ options.notification.email or payload.shipper.email ], ), VoiceMessage=None, TextMessage=None, Locale=None, ) for event in [8] ] if options.notification else None, ) if any([options.cash_on_delivery, options.notification]) 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='GIF', Description=None ), HTTPUserAgent=None, LabelStockSize=None, Instruction=None, CharacterSet=None ), ReceiptSpecification=None, ) return Serializable( create_envelope(header_content=settings.Security, body_content=request), _request_serializer, )
def _request_serializer(request: FedexRateRequest) -> str: return export( create_envelope(body_content=request), namespacedef_= 'xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://fedex.com/ws/rate/v26"', ).replace('tns:RateRequest', 'RateRequest')