def _create_pickup_request( payload: PickupRequest, settings: Settings ) -> Serializable[Envelope]: packages = Packages(payload.parcels, PackagePresets) has_overweight = any(package for package in packages if package.weight.KG > 32) request = create_envelope( header_content=settings.Security, body_content=PickupCreationRequest( Request=RequestType(), RatePickupIndicator="N", TaxInformationIndicator=None, UserLevelDiscountIndicator=None, Shipper=ShipperType( Account=AccountType( AccountNumber=settings.account_number, AccountCountryCode=payload.address.country_code or "", ), ChargeCard=None, TaxInformation=None, ), PickupDateInfo=PickupDateInfoType( CloseTime=DF.ftime(payload.closing_time, "%H:%M", "%H%M"), ReadyTime=DF.ftime(payload.ready_time, "%H:%M", "%H%M"), PickupDate=DF.date(payload.pickup_date).strftime("%Y%m%d"), ), PickupAddress=PickupAddressType( CompanyName=payload.address.company_name, ContactName=payload.address.person_name, AddressLine=SF.concat_str( payload.address.address_line1, payload.address.address_line2 ), Room=None, Floor=None, City=payload.address.city, StateProvince=payload.address.state_code, Urbanization=None, PostalCode=payload.address.postal_code, CountryCode=payload.address.country_code, ResidentialIndicator=("Y" if payload.address.residential else "N"), PickupPoint=payload.package_location, Phone=PhoneType(Number=payload.address.phone_number, Extension=None) if payload.address.phone_number is not None else None, ), AlternateAddressIndicator="Y", PickupPiece=None, TotalWeight=WeightType( Weight=packages.weight.LB, UnitOfMeasurement=WeightUnit.LB.value ), OverweightIndicator=("Y" if has_overweight else "N"), TrackingData=None, TrackingDataWithReferenceNumber=None, PaymentMethod="01", SpecialInstruction=payload.instruction, ReferenceNumber=None, FreightOptions=None, ServiceCategory=None, CashType=None, ShippingLabelsAvailable="Y", ), ) return Serializable( request, default_request_serializer( "v11", 'xmlns:v11="http://www.ups.com/XMLSchema/XOLTWS/Pickup/v1.1"' ), )
def 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 _pickup_request(payload: PickupRequest, settings: Settings) -> Serializable[CreatePickupRequest]: same_day = DF.date(payload.pickup_date).date() == datetime.today().date() packages = Packages(payload.parcels, PackagePresets, required=["weight"]) request = CreatePickupRequest( WebAuthenticationDetail=settings.webAuthenticationDetail, ClientDetail=settings.clientDetail, TransactionDetail=TransactionDetail(CustomerTransactionId="FTC"), Version=VersionId(ServiceId="disp", Major=22, Intermediate=0, Minor=0), AssociatedAccountNumber=AssociatedAccount( Type=AssociatedAccountNumberType.FEDEX_EXPRESS.value, AccountNumber=settings.account_number, ), TrackingNumber=None, OriginDetail=PickupOriginDetail( UseAccountAddress=None, PickupLocation=ContactAndAddress( Contact=Contact( ContactId=None, PersonName=payload.address.person_name, CompanyName=payload.address.company_name, PhoneNumber=payload.address.phone_number, EMailAddress=payload.address.email, ), Address=Address( StreetLines=SF.concat_str(payload.address.address_line1, payload.address.address_line2), City=payload.address.city, StateOrProvinceCode=payload.address.state_code, PostalCode=payload.address.postal_code, CountryCode=payload.address.country_code, Residential=payload.address.residential, ), ), PackageLocation=payload.package_location, ReadyTimestamp=f"{payload.pickup_date}T{payload.ready_time}:00", CompanyCloseTime=f"{payload.closing_time}:00", PickupDateType=(PickupRequestType.SAME_DAY if same_day else PickupRequestType.FUTURE_DAY).value, LastAccessTime=None, GeographicalPostalCode=None, Location=payload.package_location, DeleteLastUsed=None, SuppliesRequested=None, EarlyPickup=None, ), PickupServiceCategory=None, FreightPickupDetail=None, ExpressFreightDetail=None, PackageCount=len(packages) or 1, TotalWeight=Weight(Units=WeightUnits.LB.name, Value=packages.weight.LB) if len(packages) > 0 else None, CarrierCode=CarrierCodeType.FDXE.value, OversizePackageCount=None, Remarks=payload.instruction, CommodityDescription=None, CountryRelationship=None, ) return Serializable(request, _request_serializer)
def shipment_request( payload: ShipmentRequest, settings: Settings ) -> Serializable[ProcessShipmentRequest]: shipper = CompleteAddress.map(payload.shipper) recipient = CompleteAddress.map(payload.recipient) packages = Packages(payload.parcels, PackagePresets, required=["weight"]) # Only the master package is selected here because even for MPS only one package is accepted for a master tracking. master_package = packages[0] service = ServiceType.map(payload.service).value_or_key options = Options(payload.options, SpecialServiceType) special_services = [getattr(v, 'value', v) for k, v in options if k in SpecialServiceType] label_type, label_format = LabelType[payload.label_type or 'PDF_4x6'].value customs = payload.customs duty = customs.duty if customs is not None else None bill_to = CompleteAddress(getattr(duty, 'bill_to', None)) request = ProcessShipmentRequest( WebAuthenticationDetail=settings.webAuthenticationDetail, ClientDetail=settings.clientDetail, TransactionDetail=TransactionDetail(CustomerTransactionId="IE_v26_Ship"), Version=VersionId(ServiceId="ship", Major=26, Intermediate=0, Minor=0), RequestedShipment=RequestedShipment( ShipTimestamp=DF.date(options.shipment_date or datetime.now()), DropoffType="REGULAR_PICKUP", ServiceType=service, PackagingType=PackagingType[packages.package_type or 'your_packaging'].value, ManifestDetail=None, VariationOptions=None, TotalWeight=FedexWeight( Units=packages.weight.unit, Value=packages.weight.value ), TotalInsuredValue=options.insurance, PreferredCurrency=options.currency, ShipmentAuthorizationDetail=None, Shipper=Party( AccountNumber=settings.account_number, Tins=( [TaxpayerIdentification(Number=tax) for tax in shipper.taxes] if shipper.has_tax_info else None ), Contact=( Contact( ContactId=None, PersonName=shipper.person_name, Title=None, CompanyName=shipper.company_name, PhoneNumber=shipper.phone_number, PhoneExtension=None, TollFreePhoneNumber=None, PagerNumber=None, FaxNumber=None, EMailAddress=shipper.email, ) if shipper.has_contact_info else None ), Address=Address( StreetLines=shipper.address_lines, City=shipper.city, StateOrProvinceCode=shipper.state_code, PostalCode=shipper.postal_code, UrbanizationCode=None, CountryCode=shipper.country_code, CountryName=shipper.country_name, Residential=shipper.residential, GeographicCoordinates=None, ), ), Recipient=Party( AccountNumber=None, Tins=( [TaxpayerIdentification(Number=tax) for tax in recipient.taxes] if recipient.has_tax_info else None ), Contact=( Contact( ContactId=None, PersonName=recipient.person_name, Title=None, CompanyName=recipient.company_name, PhoneNumber=recipient.phone_number, PhoneExtension=None, TollFreePhoneNumber=None, PagerNumber=None, FaxNumber=None, EMailAddress=recipient.email, ) if recipient.has_contact_info else None ), Address=Address( StreetLines=recipient.address_lines, City=recipient.city, StateOrProvinceCode=recipient.state_code, PostalCode=recipient.postal_code, UrbanizationCode=None, CountryCode=recipient.country_code, CountryName=recipient.country_name, Residential=recipient.residential, GeographicCoordinates=None, ), ), RecipientLocationNumber=None, Origin=None, SoldTo=None, ShippingChargesPayment=Payment( PaymentType=PaymentType[payload.payment.paid_by or "sender"].value, Payor=Payor( ResponsibleParty=Party( AccountNumber=(payload.payment.account_number or settings.account_number), ) ), ), SpecialServicesRequested=( ShipmentSpecialServicesRequested( SpecialServiceTypes=special_services, CodDetail=( CodDetail( CodCollectionAmount=Money( Currency=options.currency or "USD", Amount=options.cash_on_delivery, ), AddTransportationChargesDetail=None, CollectionType=CodCollectionType.CASH, CodRecipient=None, FinancialInstitutionContactAndAddress=None, RemitToName=None, ReferenceIndicator=None, ReturnTrackingId=None, ) if options.cash_on_delivery else None ), DeliveryOnInvoiceAcceptanceDetail=None, HoldAtLocationDetail=None, EventNotificationDetail=( ShipmentEventNotificationDetail( AggregationType=None, PersonalMessage=None, EventNotifications=[ ShipmentEventNotificationSpecification( Role=None, Events=NOTIFICATION_EVENTS, NotificationDetail=NotificationDetail( NotificationType="EMAIL", EmailDetail=EMailDetail( EmailAddress=(options.email_notification_to or recipient.email), Name=recipient.person_name or recipient.company_name, ), Localization=Localization(LanguageCode="EN"), ), FormatSpecification=ShipmentNotificationFormatSpecification( Type="TEXT" ), ) ], ) if options.email_notification and any([options.email_notification_to, recipient.email]) else None ), ReturnShipmentDetail=None, PendingShipmentDetail=None, InternationalControlledExportDetail=None, InternationalTrafficInArmsRegulationsDetail=None, ShipmentDryIceDetail=None, HomeDeliveryPremiumDetail=None, EtdDetail=None, ) if options.has_content else None ), ExpressFreightDetail=None, FreightShipmentDetail=None, DeliveryInstructions=None, VariableHandlingChargeDetail=None, CustomsClearanceDetail=( CustomsClearanceDetail( Brokers=None, ClearanceBrokerage=None, CustomsOptions=None, ImporterOfRecord=None, RecipientCustomsId=None, DutiesPayment=( Payment( PaymentType=PaymentType[duty.paid_by or "sender"].value, Payor=( Payor( ResponsibleParty=Party( AccountNumber=duty.account_number, Tins=bill_to.taxes ) ) if any([duty.account_number, bill_to.taxes]) else None ) ) if duty is not None else None ), DocumentContent=None, CustomsValue=Money( Currency=(duty.currency or options.currency), Amount=(duty.declared_value or options.declared_value) ), FreightOnValue=None, InsuranceCharges=None, PartiesToTransactionAreRelated=None, CommercialInvoice=( CommercialInvoice( Comments=None, FreightCharge=None, TaxesOrMiscellaneousChargeType=None, PackingCosts=None, HandlingCosts=None, SpecialInstructions=None, DeclarationStatement=None, PaymentTerms=None, Purpose=PurposeType[customs.content_type or 'other'].value, PurposeOfShipmentDescription=None, CustomerReferences=None, OriginatorName=(shipper.company_name or shipper.person_name), TermsOfSale=Incoterm[customs.incoterm or "DDU"].value ) if customs.commercial_invoice else None ), Commodities=[ Commodity( Name=None, NumberOfPieces=item.quantity, Description=item.description or "N/A", Purpose=None, CountryOfManufacture=item.origin_country, HarmonizedCode=None, Weight=FedexWeight( Units=master_package.weight_unit.value, Value=Weight(item.weight, item.weight_unit)[master_package.weight_unit.value] ), Quantity=item.quantity, QuantityUnits='EA', AdditionalMeasures=None, UnitPrice=Money( Currency=(options.currency or duty.currency), Amount=item.value_amount, ), CustomsValue=None, ExciseConditions=None, ExportLicenseNumber=None, ExportLicenseExpirationDate=None, CIMarksAndNumbers=None, PartNumber=item.sku, NaftaDetail=None, ) for item in customs.commodities ], ExportDetail=None, RegulatoryControls=None, DeclarationStatementDetail=None ) if payload.customs is not None else None ), PickupDetail=None, SmartPostDetail=None, BlockInsightVisibility=None, LabelSpecification=LabelSpecification( Dispositions=None, LabelFormatType=LabelFormatType.COMMON_2_D.value, ImageType=label_type, LabelStockType=label_format, LabelPrintingOrientation=LabelPrintingOrientationType.TOP_EDGE_OF_TEXT_FIRST.value, LabelOrder=LabelOrderType.SHIPPING_LABEL_FIRST.value, PrintedLabelOrigin=None, CustomerSpecifiedDetail=None, ), ShippingDocumentSpecification=None, RateRequestTypes=None, EdtRequestType=None, MasterTrackingId=None, PackageCount=len(packages), ConfigurationData=None, RequestedPackageLineItems=[ RequestedPackageLineItem( SequenceNumber=1, GroupNumber=None, GroupPackageCount=None, VariableHandlingChargeDetail=None, InsuredValue=None, Weight=( FedexWeight( Units=master_package.weight.unit, Value=master_package.weight.value, ) if master_package.weight.value else None ), Dimensions=( FedexDimensions( Length=master_package.length.map(MeasurementOptions).value, Width=master_package.width.map(MeasurementOptions).value, Height=master_package.height.map(MeasurementOptions).value, Units=master_package.dimension_unit.value, ) if master_package.has_dimensions else None ), PhysicalPackaging=None, ItemDescription=master_package.parcel.description, ItemDescriptionForClearance=None, CustomerReferences=( [ CustomerReference( CustomerReferenceType=CustomerReferenceType.CUSTOMER_REFERENCE, Value=payload.reference ) ] if any(payload.reference or "") else None ), SpecialServicesRequested=None, ContentRecords=None, ) ], ), ) return Serializable(request, _request_serializer)