def shipment_request(payload: ShipmentRequest, _) -> Serializable: request = OrderRequest( packageCount=len(payload.parcels), signatureRequired=payload.options.get('signature_required', False), recipient=Recipient(name=payload.recipient.person_name, phone=payload.recipient.phone_number, notes=None, email=payload.recipient.email), recipientAddress=Address(street=SF.concat_str( payload.recipient.address_line1, payload.recipient.address_line2, join=True), city=payload.recipient.city, province=payload.recipient.state_code, country=payload.recipient.country_code, postalCode=payload.recipient.postal_code, unit=None), originAddress=Address(street=SF.concat_str( payload.shipper.address_line1, payload.shipper.address_line2, join=True), city=payload.shipper.city, province=payload.shipper.state_code, country=payload.shipper.country_code, postalCode=payload.shipper.postal_code, unit=None), service=Service[payload.service].value, notes=None, refNumber=payload.reference, completeAfter=None, completeBefore=None, merchantDisplayName=payload.shipper.company_name) return Serializable(request)
def address_validation_request( payload: AddressValidationRequest, settings: Settings) -> Serializable[RouteRequest]: country = (Country[payload.address.country_code] if payload.address.country_code is not None else None) division = ( CountryState[country.name].value[payload.address.state_code].value if (country.name in CountryState.__members__ and payload.address.state_code in CountryState[country.name].value.__members__) else None) request = RouteRequest( schemaVersion="2.0", Request=settings.Request( MetaData=MetaData(SoftwareName="3PV", SoftwareVersion=1.0)), RegionCode=CountryRegion[payload.address.country_code].value, RequestType=RequestType.D.value, Address1=SF.concat_str(payload.address.address_line1, join=True), Address2=SF.concat_str(payload.address.address_line2, join=True), Address3=None, PostalCode=payload.address.postal_code, City=payload.address.city, Division=division, CountryCode=country.name, CountryName=country.value, OriginCountryCode=payload.address.country_code, ) return Serializable(request, _request_serializer)
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 pickup_request(payload: PickupRequest, _) -> Serializable: shipments: List[ShipmentDetails] = payload.options.get('shipments', []) after = DF.date(f"{payload.pickup_date} {payload.ready_time}", current_format="%Y-%m-%d %H:%M") before = DF.date(f"{payload.pickup_date} {payload.ready_time}", current_format="%Y-%m-%d %H:%M") request = BoxKnightPickupRequest( packageCount=len(payload.parcels), recipient=Recipient( name=payload.address.person_name, phone=payload.address.phone_number, notes=None, email=payload.address.email, ), recipientAddress=PickupRequestRecipientAddress( street=SF.concat_str(payload.address.address_line1, payload.address.address_line2, join=True), city=payload.address.city, province=payload.address.state_code, country=payload.address.country_code, postalCode=payload.address.postal_code, unit=None ), notes=payload.instruction, completeAfter=int(after.timestamp() * 1000.0), completeBefore=int(before.timestamp() * 1000.0), orderIds=[shipment.shipment_identifier for shipment in shipments], ) return Serializable(request)
def parse_address_validation_response( response: Element, settings: Settings) -> Tuple[AddressValidationDetails, List[Message]]: errors = parse_error_response(response, settings) address_node = next( iter(response.xpath(".//*[local-name() = $name]", name="address")), None) address = XP.to_object(CanparAddress, address_node) success = len(errors) == 0 validation_details = AddressValidationDetails( carrier_id=settings.carrier_id, carrier_name=settings.carrier_name, success=success, complete_address=Address(postal_code=address.postal_code, city=address.city, company_name=address.name, country_code=address.country, email=address.email, state_code=address.province, residential=address.residential, address_line1=address.address_line_1, address_line2=SF.concat_str( address.address_line_2, address.address_line_3, join=True))) if success else None return validation_details, errors
def _extract_tracking_details(node: Element, settings: Settings) -> TrackingDetails: result = XP.build(TrackingResult, node) is_en = settings.language == "en" events = [ TrackingEvent( date=DF.fdate(event.local_date_time, '%Y%m%d %H%M%S'), description=(event.code_description_en if is_en else event.code_description_fr), location=SF.concat_str(event.address.address_line_1, event.address.address_line_2, event.address.city, event.address.province, event.address.country, join=True, separator=", "), code=event.code, time=DF.ftime(event.local_date_time, '%Y%m%d %H%M%S'), ) for event in cast(List[CanparTrackingEvent], result.events) ] return TrackingDetails(carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=result.barcode, events=events, delivered=any(event.code == 'DEL' for event in events))
def _compute_address_line(self, join: bool = True) -> Optional[str]: if any([self._address.address_line1, self._address.address_line2]): return SF.concat_str(self._address.address_line1, self._address.address_line2, join=join) if self._address.extra is not None: return SF.concat_str( self._address.extra.suite, self._address.extra.street_number, self._address.extra.street_name, self._address.extra.street_type, join=True, ) return None
def pickup_request(payload: PickupRequest, settings: Settings) -> Serializable: shipments: List[ShipmentRequest] = payload.options.get('shipments', []) packages = Packages(payload.parcels) request = CarrierPickupScheduleRequest( USERID=settings.username, FirstName=payload.address.person_name, LastName=None, FirmName=payload.address.company_name, SuiteOrApt=payload.address.address_line1, Address2=SF.concat_str(payload.address.address_line1, payload.address.address_line2, join=True), Urbanization=None, City=payload.address.city, State=payload.address.state_code, ZIP5=payload.address.postal_code, ZIP4=None, Phone=payload.address.phone_number, Extension=None, Package=[ PackageType(ServiceType=shipment.service, Count=len(shipment.parcels)) for shipment in shipments ], EstimatedWeight=packages.weight.LB, PackageLocation=payload.package_location, SpecialInstructions=payload.instruction, EmailAddress=payload.address.email) return Serializable(request)
def parse_address_validation_response( response: Element, settings: Settings) -> Tuple[AddressValidationDetails, List[Message]]: reply = XP.build( AddressValidationReply, next( iter( response.xpath(".//*[local-name() = $name]", name="AddressValidationReply")), None)) address: FedexAddress = next( (result.EffectiveAddress for result in reply.AddressResults), None) success = reply.HighestSeverity == NotificationSeverityType.SUCCESS.value _, lines = (address.StreetLines if address is not None and len(address.StreetLines) > 1 else ["", ""]) validation_details = AddressValidationDetails( carrier_id=settings.carrier_id, carrier_name=settings.carrier_name, success=success, complete_address=Address(city=address.City, state_code=address.StateOrProvinceCode, country_code=address.CountryCode, residential=address.Residential, address_line1=next(iter(address.StreetLines), None), address_line2=SF.concat_str(lines, join=True)) if address is not None else None) if success else None return validation_details, parse_error_response(response, settings)
def pickup_cancel_request(payload: PickupCancelRequest, settings: Settings) -> Serializable: request = CarrierPickupCancelRequest( UserID=settings.username, FirmName=payload.address.company_name, SuiteOrApt=payload.address.address_line1, Address2=SF.concat_str(payload.address.address_line1, payload.address.address_line2, join=True), Urbanization=None, City=payload.address.city, State=payload.address.state_code, ZIP5=payload.address.postal_code, ZIP4=None, ConfirmationNumber=payload.confirmation_number ) return Serializable(request)
def address_validation_request(payload: AddressValidationRequest, settings: Settings) -> Serializable[Envelope]: contact = dict(PersonName=payload.address.person_name, CompanyName=payload.address.company_name, PhoneNumber=payload.address.phone_number, EMailAddress=payload.address.email) request = create_envelope(body_content=FedexAddressValidationRequest( WebAuthenticationDetail=settings.webAuthenticationDetail, ClientDetail=settings.clientDetail, TransactionDetail=TransactionDetail( CustomerTransactionId="AddressValidationRequest_v4"), Version=VersionId(ServiceId="aval", Major=4, Intermediate=0, Minor=0), InEffectAsOfTimestamp=None, AddressesToValidate=[ AddressToValidate( ClientReferenceId=None, Contact=Contact(ContactId=None, PersonName=contact['person_name'], Title=None, CompanyName=contact['company_name'], PhoneNumber=contact['phone_number'], PhoneExtension=None, TollFreePhoneNumber=None, PagerNumber=None, FaxNumber=None, EMailAddress=contact['email'] ) if any(contact.values()) else None, Address=FedexAddress( StreetLines=SF.concat_str(payload.address.address_line1, payload.address.address_line2), City=payload.address.city, StateOrProvinceCode=payload.address.city, PostalCode=payload.address.postal_code, UrbanizationCode=None, CountryCode=payload.address.country_code, CountryName=None, Residential="" if payload.address.residential else None, ), ) ], )) return Serializable( request, default_request_serializer( 'v4', 'xmlns:v4="http://fedex.com/ws/addressvalidation/v4"'))
def pickup_rate_request(payload: PickupRequest, settings: Settings) -> Serializable[Envelope]: pickup_date = DF.date(payload.pickup_date) same_day = pickup_date.date() == datetime.today().date() request = create_envelope( header_content=settings.Security, body_content=PickupRateRequest( Request=RequestType(), ShipperAccount=None, 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", ServiceDateOption=("01" if same_day else "02"), PickupDateInfo=PickupDateInfoType( CloseTime=DF.ftime(payload.closing_time, "%H:%M", "%H%M"), ReadyTime=DF.ftime(payload.ready_time, "%H:%M", "%H%M"), PickupDate=pickup_date.strftime("%Y%m%d"), ), TaxInformationIndicator=None, UserLevelDiscountIndicator=None, ), ) return Serializable( request, default_request_serializer( "v11", 'xmlns:v11="http://www.ups.com/XMLSchema/XOLTWS/Pickup/v1.1"'), )
def _retrieve_pickup(creation_response: str, payload: PickupRequest, settings: Settings) -> Job: errors = parse_error_response(DP.to_dict(creation_response), settings) data = (Serializable( dict( category=payload.options.get("category", "Parcel"), pickupDate=payload.pickup_date, streetNumber=SF.concat_str(payload.address.address_line1, payload.address.address_line2, join=True), postalCode=payload.address.postal_code, offset=10, ), urllib.parse.urlencode) if not any(errors) else None) return Job(id="retrieve_pickup", data=data, fallback=('{}' if data is None else None))
def address_validation_request(payload: AddressValidationRequest, settings: Settings) -> Serializable[Envelope]: request = create_envelope(body_content=searchCanadaPost( request=SearchCanadaPostRq( city=payload.address.city or "", password=settings.password, postal_code=payload.address.postal_code or "", province=payload.address.state_code or "", street_direction="", street_name=SF.concat_str(payload.address.address_line1, payload.address.address_line2, join=True) or "", street_num="", street_type="", user_id=settings.username, validate_only=True))) return Serializable(request, Settings.serialize)
def address_validation_request(payload: AddressValidationRequest, settings: Settings) -> Serializable[AddressValidateRequest]: request = AddressValidateRequest( USERID=settings.username, Revision="1", Address=AddressType( ID=None, FirmName=(payload.address.company_name or payload.address.person_name), Address1=payload.address.address_line1, Address2=SF.concat_str(payload.address.address_line1, payload.address.address_line2, join=True), City=payload.address.city, State=payload.address.state_code, Urbanization=None, Zip5=payload.address.postal_code, Zip4=None, ) ) return Serializable(request, XP.export)
def _extract_tracking(detail_node: Element, settings: Settings) -> TrackingDetails: pin = XP.find("pin", detail_node, first=True) events: List[occurrenceType] = XP.find("occurrence", detail_node, occurrenceType) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=pin.text, events=[ TrackingEvent( date=DF.fdate(event.event_date, "%Y-%m-%d"), time=DF.ftime(event.event_time, "%H:%M:%S"), code=event.event_identifier, location=SF.concat_str(event.event_site, event.event_province, join=True, separator=', '), description=event.event_description ) for event in events ], delivered=any(e.event_identifier in TRACKING_DELIVERED_EVENT_CODES for e in events) )
def _extract_detail(node: Element, settings: Settings) -> TrackingDetails: detail = XP.build(ConsignmentType, node) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=detail.ConsignmentNumber, events=[ TrackingEvent( date=DF.fdate(status.LocalEventDate.valueOf_, '%Y%m%d'), description=status.StatusDescription, location=SF.concat_str(status.Depot, status.DepotName, join=True, separator='-'), code=status.StatusCode, time=DF.ftime(status.LocalEventTime.valueOf_, '%H%M') ) for status in cast(List[StatusStructure], detail.StatusData) ], delivered=(detail.SummaryCode == "DEL") )
def pickup_availability_request( payload: PickupRequest, settings: Settings) -> Serializable[PickupAvailabilityRequest]: same_day = DF.date(payload.pickup_date).date() == datetime.today().date() request = PickupAvailabilityRequest( WebAuthenticationDetail=settings.webAuthenticationDetail, ClientDetail=settings.clientDetail, TransactionDetail=TransactionDetail(CustomerTransactionId="FTC"), Version=VersionId(ServiceId="disp", Major=22, Intermediate=0, Minor=0), PickupType=None, AccountNumber=AssociatedAccount( Type=AssociatedAccountNumberType.FEDEX_EXPRESS.value, AccountNumber=settings.account_number, ), PickupAddress=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, ), PickupRequestType=[(PickupRequestType.SAME_DAY if same_day else PickupRequestType.FUTURE_DAY).value], DispatchDate=payload.pickup_date, NumberOfBusinessDays=None, PackageReadyTime=f"{payload.ready_time}:00", CustomerCloseTime=f"{payload.closing_time}:00", Carriers=[CarrierCodeType.FDXE.value], ShipmentAttributes=None, PackageDetails=None, ) return Serializable(request, _request_serializer)
def _create_pickup(payload: PickupRequest) -> Job: request = DicomPickupRequest( date=payload.pickup_date, ready=payload.ready_time, category=payload.options.get("category", "Parcel"), officeClose=payload.closing_time, sender=Sender(city=payload.address.city, provinceCode=payload.address.state_code, postalCode=payload.address.postal_code, countryCode=payload.address.country_code, customerName=payload.address.company_name, streetNumber=SF.concat_str(payload.address.address_line1, payload.address.address_line2, join=True), contact=Contact( fullName=payload.address.person_name, email=payload.address.email, telephone=payload.address.phone_number, )), location=payload.options.get("dicom_location", "OT"), otherLocation=payload.package_location) return Job(id="create_pickup", data=Serializable(request, DP.to_dict))
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 _create_pickup_request( payload: PickupRequest, settings: Settings, update: bool = False) -> Serializable[PickupRequestDetails]: """ pickup_request create a serializable typed PickupRequestDetailsType Options: - five_ton_flag - loading_dock_flag :param update: bool :param payload: PickupRequest :param settings: Settings :return: Serializable[PickupRequest] """ RequestType = PickupRequestUpdateDetailsType if update else PickupRequestDetailsType packages = Packages(payload.parcels, PackagePresets, required=["weight"]) heavy = any([p for p in packages if p.weight.KG > 23]) location_details = dict( instruction=payload.instruction, five_ton_flag=payload.options.get("five_ton_flag"), loading_dock_flag=payload.options.get("loading_dock_flag"), ) address = dict( company=payload.address.company_name or "", address_line_1=SF.concat_str(payload.address.address_line1, payload.address.address_line2, join=True), city=payload.address.city, province=payload.address.state_code, postal_code=payload.address.postal_code, ) request = RequestType( customer_request_id=settings.customer_number, pickup_type=PickupType.ON_DEMAND.value, pickup_location=PickupLocationType( business_address_flag=(not payload.address.residential), alternate_address=AlternateAddressType( company=address["company"], address_line_1=address["address_line_1"], city=address["city"], province=address["province"], postal_code=address["postal_code"], ) if any(address.values()) else None, ), contact_info=ContactInfoType( contact_name=payload.address.person_name, email=payload.address.email or "", contact_phone=payload.address.phone_number, telephone_ext=None, receive_email_updates_flag=(payload.address.email is not None), ), location_details=LocationDetailsType( five_ton_flag=location_details["five_ton_flag"], loading_dock_flag=location_details["loading_dock_flag"], pickup_instructions=location_details["instruction"], ) if any(location_details.values()) else None, items_characteristics=ItemsCharacteristicsType(pww_flag=None, priority_flag=None, returns_flag=None, heavy_item_flag=heavy) if heavy else None, pickup_volume=f"{len(packages) or 1}", pickup_times=PickupTimesType( on_demand_pickup_time=OnDemandPickupTimeType( date=payload.pickup_date, preferred_time=payload.ready_time, closing_time=payload.closing_time, ), scheduled_pickup_times=None, ), payment_info=None, ) return Serializable(request, partial(_request_serializer, update=update))
def shipment_request( payload: ShipmentRequest, settings: Settings) -> Serializable[ProcessShipmentRequest]: 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] package_type = (PackagingType[master_package.packaging_type or "your_packaging"].value if len(packages) == 1 else PackagingType.your_packaging.value) service = ServiceType[payload.service].value options = Options(payload.options) special_services = [ SpecialServiceType[name].value for name, value in payload.options.items() if name in SpecialServiceType.__members__ ] payment_type = PaymentType[payload.payment.paid_by or "sender"].value shipment_date = (DF.date(options.shipment_date) if 'shipment_date' in options else datetime.now()) label_type, label_format = LabelType[payload.label_type or 'PDF_4x6'].value request = ProcessShipmentRequest( WebAuthenticationDetail=settings.webAuthenticationDetail, ClientDetail=settings.clientDetail, TransactionDetail=TransactionDetail( CustomerTransactionId="IE_v25_Ship"), Version=VersionId(ServiceId="ship", Major=25, Intermediate=0, Minor=0), RequestedShipment=RequestedShipment( ShipTimestamp=shipment_date, DropoffType="REGULAR_PICKUP", ServiceType=service, PackagingType=package_type, ManifestDetail=None, TotalWeight=FedexWeight(Units=WeightUnit.LB.value, Value=packages.weight.LB), TotalInsuredValue=options.insurance, 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.phone_number, payload.shipper.person_name, 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.phone_number, payload.recipient.person_name, 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=Payment( PaymentType=payment_type, Payor=Payor(ResponsibleParty=Party( AccountNumber=(payload.payment.account_number or settings.account_number), Tins=None, Contact=None, Address=None, )), ), 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.notification_email or payload.recipient.email, Name=payload.recipient.person_name or payload.recipient.company_name, ), Localization=Localization(LanguageCode="EN", LocaleCode=None), ), FormatSpecification= ShipmentNotificationFormatSpecification( Type="TEXT"), ) ], ) if options.notification_email is None else None), ReturnShipmentDetail=None, PendingShipmentDetail=None, InternationalControlledExportDetail=None, InternationalTrafficInArmsRegulationsDetail=None, ShipmentDryIceDetail=None, HomeDeliveryPremiumDetail=None, EtdDetail=None, CustomDeliveryWindowDetail=None, ) if options.has_content else None, ExpressFreightDetail=None, FreightShipmentDetail=None, DeliveryInstructions=None, VariableHandlingChargeDetail=None, CustomsClearanceDetail=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, Value=master_package.weight.value, ) if master_package.weight.value else None, Dimensions=FedexDimensions( Length=master_package.length.value, Width=master_package.width.value, Height=master_package.height.value, Units=master_package.dimension_unit.value, ) if any([ master_package.length, master_package.width, master_package.height, ]) else None, PhysicalPackaging=None, ItemDescription=master_package.parcel.description, ItemDescriptionForClearance=None, CustomerReferences=None, SpecialServicesRequested=None, ContentRecords=None, ) ], ), ) 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=17, 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 _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 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 shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[DHLShipmentRequest]: if any(settings.account_country_code or "") and ( payload.shipper.country_code != settings.account_country_code): raise OriginNotServicedError(payload.shipper.country_code) packages = Packages.map(payload.parcels, PackagePresets, required=["weight"]) options = Options(payload.options, SpecialServiceCode) product = ProductCode.map(payload.service).value_or_key shipper = CompleteAddress.map(payload.shipper) recipient = CompleteAddress.map(payload.recipient) weight_unit, dim_unit = (COUNTRY_PREFERED_UNITS.get( payload.shipper.country_code) or packages.compatible_units) is_document = all(p.parcel.is_document for p in packages) package_type = PackageType[packages.package_type].value label_format, label_template = LabelType[payload.label_type or 'PDF_6x4'].value payment = (payload.payment or Payment(paid_by="sender", account_number=settings.account_number)) customs = (payload.customs or Customs(commodities=[])) is_dutiable = (is_document is False and customs.duty is not None) paperless_supported = (is_dutiable and payload.shipper.country_code not in UNSUPPORTED_PAPERLESS_COUNTRIES) duty = (customs.duty or Duty(paid_by="sender")) bill_to = CompleteAddress.map(duty.bill_to) content = (packages[0].parcel.content or customs.content_description or "N/A") reference = (payload.reference or getattr(payload, 'id', None)) request = DHLShipmentRequest( schemaVersion='10.0', Request=settings.Request( MetaData=MetaData(SoftwareName="3PV", SoftwareVersion='10.0')), RegionCode=CountryRegion[shipper.country_code].value, LanguageCode="en", LatinResponseInd=None, Billing=Billing( ShipperAccountNumber=settings.account_number, ShippingPaymentType=PaymentType[payment.paid_by].value, BillingAccountNumber=payment.account_number, DutyAccountNumber=duty.account_number, ), Consignee=Consignee( CompanyName=recipient.company_name or "N/A", SuiteDepartmentName=recipient.suite, AddressLine1=recipient.address_line1 or recipient.address_line, AddressLine2=SF.concat_str(recipient.address_line2, join=True), AddressLine3=None, City=recipient.city, Division=None, DivisionCode=recipient.state_code, PostalCode=recipient.postal_code, CountryCode=recipient.country_code, CountryName=recipient.country_name, Contact=Contact( PersonName=recipient.person_name, PhoneNumber=recipient.phone_number or "0000", Email=recipient.email, ), Suburb=recipient.suburb, StreetName=recipient.street_name, BuildingName=None, StreetNumber=recipient.street_number, RegistrationNumbers=None, BusinessPartyTypeCode=None, ), Commodity=([ Commodity(CommodityCode=c.sku, CommodityName=c.description) for c in payload.customs.commodities ] if any(customs.commodities) else None), Dutiable=(Dutiable( DeclaredValue=duty.declared_value or options.declared_value or 1.0, DeclaredCurrency=duty.currency or options.currency or "USD", ScheduleB=None, ExportLicense=customs.license_number, ShipperEIN=None, ShipperIDType=None, TermsOfTrade=customs.incoterm, CommerceLicensed=None, Filing=None) if is_dutiable else None), UseDHLInvoice=("Y" if is_dutiable else None), DHLInvoiceLanguageCode=("en" if is_dutiable else None), DHLInvoiceType=(("CMI" if customs.commercial_invoice else "PFI") if is_dutiable else None), ExportDeclaration=(ExportDeclaration( InterConsignee=None, IsPartiesRelation=None, ECCN=None, SignatureName=customs.signer, SignatureTitle=None, ExportReason=customs.content_type, ExportReasonCode=ExportReasonCode[customs.content_type or 'other'].value, SedNumber=None, SedNumberType=None, MxStateCode=None, InvoiceNumber=(customs.invoice or "N/A"), InvoiceDate=(customs.invoice_date or time.strftime("%Y-%m-%d")), BillToCompanyName=bill_to.company_name, BillToContactName=bill_to.person_name, BillToAddressLine=bill_to.address_line, BillToCity=bill_to.city, BillToPostcode=bill_to.postal_code, BillToSuburb=bill_to.extra, BillToCountryName=bill_to.country_name, BillToPhoneNumber=bill_to.phone_number, BillToPhoneNumberExtn=None, BillToFaxNumber=None, BillToFederalTaxID=bill_to.federal_tax_id, Remarks=customs.content_description, DestinationPort=None, TermsOfPayment=None, PayerGSTVAT=bill_to.state_tax_id, SignatureImage=None, ReceiverReference=None, ExporterId=None, ExporterCode=None, ExportLineItem=[ ExportLineItem( LineNumber=index, Quantity=item.quantity, QuantityUnit='PCS', Description=item.description or 'N/A', Value=((item.quantity or 1) * (item.value_amount or 0.0)), IsDomestic=None, CommodityCode=item.sku, ScheduleB=None, ECCN=None, Weight=WeightType( Weight=Weight(item.weight, WeightUnit[item.weight_unit or 'KG'])[weight_unit.name], WeightUnit=DHLWeightUnit[weight_unit.name].value), GrossWeight=WeightType( Weight=Weight(item.weight, WeightUnit[item.weight_unit or 'KG'])[weight_unit.name], WeightUnit=DHLWeightUnit[weight_unit.name].value), License=None, LicenseSymbol=None, ManufactureCountryCode=item.origin_country, ManufactureCountryName=Location( item.origin_country).as_country_name, ImportTaxManagedOutsideDhlExpress=None, AdditionalInformation=None, ImportCommodityCode=None, ItemReferences=None, CustomsPaperworks=None, ) for (index, item) in enumerate(customs.commodities, start=1) ], ShipmentDocument=None, InvoiceInstructions=None, CustomerDataTextEntries=None, PlaceOfIncoterm="N/A", ShipmentPurpose=( "COMMERCIAL" if customs.commercial_invoice else "PERSONAL"), DocumentFunction=None, CustomsDocuments=None, InvoiceTotalNetWeight=None, InvoiceTotalGrossWeight=None, InvoiceReferences=None, ) if is_dutiable else None), Reference=([Reference( ReferenceID=reference)] if any([reference]) else None), ShipmentDetails=DHLShipmentDetails( Pieces=Pieces(Piece=[ Piece( PieceID=index, PackageType=(package_type or PackageType[package.packaging_type or "your_packaging"].value), Depth=package.length.map(MeasurementOptions)[ dim_unit.name], Width=package.width.map(MeasurementOptions)[dim_unit.name], Height=package.height.map(MeasurementOptions)[ dim_unit.name], Weight=package.weight[weight_unit.name], PieceContents=( package.parcel.content or package.parcel.description), PieceReference=([Reference( ReferenceID=package.parcel.id)] if package.parcel. id is not None else None), AdditionalInformation=(AdditionalInformation( CustomerDescription=package.parcel.description ) if package.parcel.description is not None else None)) for (index, package) in enumerate(packages, start=1) ]), WeightUnit=DHLWeightUnit[weight_unit.name].value, GlobalProductCode=product, LocalProductCode=product, Date=(options.shipment_date or time.strftime("%Y-%m-%d")), Contents=content, DimensionUnit=DimensionUnit[dim_unit.name].value, PackageType=package_type, IsDutiable=("Y" if is_dutiable else "N"), CurrencyCode=options.currency or "USD", CustData=getattr(payload, 'id', None), ShipmentCharges=(options.cash_on_delivery if options.cash_on_delivery else None), ParentShipmentIdentificationNumber=None, ParentShipmentGlobalProductCode=None, ParentShipmentPackagesCount=None, ), Shipper=Shipper( ShipperID=settings.account_number or "N/A", CompanyName=shipper.company_name or "N/A", SuiteDepartmentName=shipper.suite, RegisteredAccount=settings.account_number, AddressLine1=shipper.address_line1 or shipper.address_line, AddressLine2=SF.concat_str(shipper.address_line2, join=True), AddressLine3=None, City=shipper.city, Division=None, DivisionCode=shipper.state_code, PostalCode=shipper.postal_code, OriginServiceAreaCode=None, OriginFacilityCode=None, CountryCode=shipper.country_code, CountryName=shipper.country_name, Contact=Contact( PersonName=shipper.person_name, PhoneNumber=shipper.phone_number or "0000", Email=shipper.email, ), Suburb=shipper.suburb, StreetName=shipper.street_name, BuildingName=None, StreetNumber=shipper.street_number, RegistrationNumbers=None, BusinessPartyTypeCode=None, ), SpecialService=([ SpecialService( SpecialServiceType=SpecialServiceCode[key].value.key, ChargeValue=getattr(svc, 'value', None), CurrencyCode=(options.currency or "USD" if hasattr( svc, 'value') else None)) for key, svc in options if key in SpecialServiceCode ] + ( # Add paperless trade if dutiable [SpecialService(SpecialServiceType="WY")] if paperless_supported and 'dhl_paperless_trade' not in options else [])), Notification=(Notification( EmailAddress=options.email_notification_to or recipient.email) if options.email_notification and any([options.email_notification_to, recipient.email]) else None), Place=None, EProcShip=None, Airwaybill=None, DocImages=None, LabelImageFormat=label_format, RequestArchiveDoc=None, NumberOfArchiveDoc=None, RequestQRCode='N', RequestTransportLabel=None, Label=Label(LabelTemplate=label_template), ODDLinkReq=None, DGs=None, GetPriceEstimate='Y', SinglePieceImage='N', ShipmentIdentificationNumber=None, UseOwnShipmentIdentificationNumber='N', Importer=None, ) return Serializable(request, _request_serializer)
def shipment_request( payload: ShipmentRequest, settings: Settings) -> Serializable[eVSPriorityMailIntlRequest]: package = Packages(payload.parcels, max_weight=Weight(70, WeightUnit.LB)).single options = Options(payload.options, ShipmentOption) label_format = LabelFormat[payload.label_type or 'usps_6_x_4_label'].value extra_services = [ getattr(option, 'value', option) for key, option in options if 'usps_option' not in key ] customs = payload.customs or Customs(commodities=[]) insurance = getattr( (options['usps_insurance_priority_mail_international']), 'value', options.insurance) # Gets the first provided non delivery option or default to "RETURN" non_delivery = next( (option.value for name, option in options if 'non_delivery' in name), "RETURN") redirect_address = Address( **(options['usps_option_redirect_non_delivery'] or {})) request = eVSPriorityMailIntlRequest( USERID=settings.username, Option=None, Revision=2, ImageParameters=ImageParametersType(ImageParameter=label_format), FromFirstName=customs.signer or payload.shipper.person_name or "N/A", FromMiddleInitial=None, FromLastName=payload.shipper.person_name, FromFirm=payload.shipper.company_name or "N/A", FromAddress1=payload.shipper.address_line1, FromAddress2=payload.shipper.address_line2, FromUrbanization=None, FromCity=payload.shipper.city, FromState=Location(payload.shipper.state_code, country='US').as_state_name, FromZip5=Location(payload.shipper.postal_code).as_zip5, FromZip4=Location(payload.shipper.postal_code).as_zip4, FromPhone=payload.shipper.phone_number, FromCustomsReference=None, ToName=None, ToFirstName=payload.recipient.person_name, ToLastName=None, ToFirm=payload.recipient.company_name or "N/A", ToAddress1=payload.recipient.address_line1, ToAddress2=payload.recipient.address_line2, ToAddress3=None, ToCity=payload.recipient.city, ToProvince=payload.recipient.state_code, ToCountry=Location(payload.recipient.country_code).as_country_name, ToPostalCode=payload.recipient.postal_code, ToPOBoxFlag=None, ToPhone=payload.recipient.phone_number, ToFax=None, ToEmail=payload.recipient.email, ImportersReferenceNumber=None, NonDeliveryOption=non_delivery, RedirectName=redirect_address.person_name, RedirectEmail=redirect_address.email, RedirectSMS=redirect_address.phone_number, RedirectAddress=SF.concat_str(redirect_address.address_line1, redirect_address.address_line2, join=True), RedirectCity=redirect_address.city, RedirectState=redirect_address.state_code, RedirectZipCode=redirect_address.postal_code, RedirectZip4=Location(redirect_address.postal_code).as_zip4, Container=None, ShippingContents=ShippingContentsType(ItemDetail=[ ItemDetailType( Description=item.description, Quantity=item.quantity, Value=item.value_amount, NetPounds=Weight(item.weight, WeightUnit[item.weight_unit or 'LB']).LB, NetOunces=Weight(item.weight, WeightUnit[item.weight_unit or 'LB']).OZ, HSTariffNumber=item.sku, CountryOfOrigin=Location(item.origin_country).as_country_name) for item in payload.customs.commodities ]), Insured=('N' if insurance is None else 'Y'), InsuredAmount=insurance, GrossPounds=package.weight.LB, GrossOunces=package.weight.OZ, ContentType=ContentType[customs.content_type or "other"].value, ContentTypeOther=customs.content_description or "N/A", Agreement=('N' if customs.certify else 'Y'), Comments=customs.content_description, LicenseNumber=customs.license_number, CertificateNumber=customs.certificate_number, InvoiceNumber=customs.invoice, ImageType="PDF", ImageLayout="ALLINONEFILE", CustomerRefNo=None, CustomerRefNo2=None, POZipCode=None, LabelDate=DF.fdatetime(options.shipment_date, output_format="%m/%d/%Y"), EMCAAccount=None, HoldForManifest=None, EELPFC=customs.eel_pfc, PriceOptions=None, Length=package.length.IN, Width=package.weight.IN, Height=package.height.IN, Girth=(package.girth.value if package.packaging_type == "tube" else None), ExtraServices=(ExtraServicesType(ExtraService=[ getattr(option, 'value', option) for option in extra_services ]) if any(extra_services) else None), ActionCode=None, OptOutOfSPE=None, PermitNumber=None, AccountZipCode=None, ImportersReferenceType=None, ImportersTelephoneNumber=None, ImportersFaxNumber=None, ImportersEmail=None, Machinable=options["usps_option_machinable_item"], DestinationRateIndicator="I", MID=None, LogisticsManagerMID=None, CRID=None, VendorCode=None, VendorProductVersionNumber=None, ChargebackCode=None, ) return Serializable(request, XP.export)
def validate_pickup_request(payload: Union[PickupRequest, PickupUpdateRequest], settings: Settings) -> Serializable[Envelope]: """ Create a serializable typed Envelope containing a ValidatePickUpRequest Options: - LoadingDockAvailable - TrailerAccessible :param payload: PickupRequest :param settings: Settings :return: Serializable[PickupRequest] """ packages = Packages(payload.parcels, PackagePresets, required=["weight"]) phone = Phone(payload.address.phone_number, payload.address.country_code or 'CA') request = create_envelope( header_content=RequestContext( Version="1.2", Language=settings.language, GroupID="", RequestReference="", UserToken=settings.user_token, ), body_content=ValidatePickUpRequest( BillingAccountNumber=settings.account_number, PartnerID=None, PickupInstruction=PickupInstruction( Date=payload.pickup_date, AnyTimeAfter="".join(payload.ready_time.split(":")), UntilTime="".join(payload.closing_time.split(":")), TotalWeight=Weight(Value=packages.weight.LB, WeightUnit=WeightUnit.LB.value), TotalPieces=len(packages) or 1, BoxesIndicator=None, PickUpLocation=payload.package_location, AdditionalInstructions=payload.instruction, SupplyRequestCodes=None, TrailerAccessible=payload.options.get("TrailerAccessible"), LoadingDockAvailable=payload.options.get( "LoadingDockAvailable"), ShipmentOnSkids=None, NumberOfSkids=None, ), Address=Address( Name=payload.address.person_name or "", Company=payload.address.company_name, Department=None, StreetNumber="", StreetSuffix=None, StreetName=SF.concat_str(payload.address.address_line1, join=True), StreetType=None, StreetDirection=None, Suite=None, Floor=None, StreetAddress2=SF.concat_str(payload.address.address_line2, join=True), StreetAddress3=None, City=payload.address.city, Province=payload.address.state_code, Country=payload.address.country_code, PostalCode=payload.address.postal_code, PhoneNumber=PhoneNumber( CountryCode=phone.country_code or "0", AreaCode=phone.area_code or "0", Phone=phone.phone or "0", Extension=None, ), FaxNumber=None, ), ShipmentSummary=None, NotificationEmails=NotificationEmails( NotificationEmail=[payload.address.email]), ), ) return Serializable(request, partial(standard_request_serializer, version="v1"))
def shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[DHLShipmentRequest]: packages = Packages(payload.parcels, PackagePresets, required=["weight"]) options = Options(payload.options, SpecialServiceCode) product = ProductCode[payload.service].value insurance = options[ 'dhl_shipment_insurance'].value if 'dhl_shipment_insurance' in options else None package_type = (PackageType[packages[0].packaging_type or "your_packaging"].value if len(packages) == 1 else None) delivery_type = next( (d for d in DeliveryType if d.name in payload.options.keys()), None) has_payment_config = payload.payment is not None has_customs_config = payload.customs is not None label_format, label_template = LabelType[payload.label_type or 'PDF_6x4'].value request = DHLShipmentRequest( schemaVersion=6.2, Request=settings.Request( MetaData=MetaData(SoftwareName="3PV", SoftwareVersion=6.2)), RegionCode=CountryRegion[payload.shipper.country_code].value, RequestedPickupTime="Y", LanguageCode="en", PiecesEnabled="Y", LatinResponseInd=None, Billing=Billing( ShipperAccountNumber=settings.account_number, BillingAccountNumber=payload.payment.account_number if has_payment_config else None, ShippingPaymentType=PaymentType[payload.payment.paid_by].value if has_payment_config else None, DutyAccountNumber=payload.customs.duty.account_number if has_customs_config else None, DutyPaymentType=PaymentType[payload.customs.duty.paid_by].value if has_customs_config else None, ), Consignee=Consignee( CompanyName=payload.recipient.company_name or " ", SuiteDepartmentName=None, AddressLine=SF.concat_str(payload.recipient.address_line1, payload.recipient.address_line2), City=payload.recipient.city, Division=None, DivisionCode=payload.recipient.state_code, PostalCode=payload.recipient.postal_code, CountryCode=payload.recipient.country_code, CountryName=Country[payload.recipient.country_code].value, FederalTaxId=payload.shipper.federal_tax_id, StateTaxId=payload.shipper.state_tax_id, Contact=(Contact( PersonName=payload.recipient.person_name, PhoneNumber=payload.recipient.phone_number or "0000", Email=payload.recipient.email, )), Suburb=None, ), Commodity=[ Commodity(CommodityCode=c.sku, CommodityName=c.description) for c in payload.customs.commodities ] if payload.customs is not None else None, NewShipper=None, Shipper=Shipper( ShipperID=settings.account_number or " ", RegisteredAccount=settings.account_number, AddressLine=SF.concat_str(payload.shipper.address_line1, payload.shipper.address_line2), CompanyName=payload.shipper.company_name or " ", PostalCode=payload.shipper.postal_code, CountryCode=payload.shipper.country_code, City=payload.shipper.city, CountryName=Country[payload.shipper.country_code].value, Division=None, DivisionCode=payload.shipper.state_code, Contact=(Contact( PersonName=payload.shipper.person_name, PhoneNumber=payload.shipper.phone_number or "0000", Email=payload.shipper.email, )), ), ShipmentDetails=DHLShipmentDetails( NumberOfPieces=len(packages), Pieces=Pieces(Piece=[ Piece( PieceID=payload.parcels[index].id, PackageType=(package_type or PackageType[ package.packaging_type or "your_packaging"].value), Depth=package.length.IN, Width=package.width.IN, Height=package.height.IN, Weight=package.weight.LB, DimWeight=None, PieceContents=payload.parcels[index].description, ) for index, package in enumerate(packages) ]), Weight=packages.weight.LB, CurrencyCode=options.currency or "USD", WeightUnit=WeightUnit.L.value, DimensionUnit=DimensionUnit.I.value, Date=(options.shipment_date or time.strftime("%Y-%m-%d")), PackageType=package_type, IsDutiable=("Y" if payload.customs is not None else "N"), InsuredAmount=insurance, ShipmentCharges=(options.cash_on_delivery if options.cash_on_delivery else None), DoorTo=delivery_type, GlobalProductCode=product, LocalProductCode=product, Contents=" ", ), EProcShip=None, Dutiable=Dutiable( DeclaredCurrency=payload.customs.duty.currency or "USD", DeclaredValue=payload.customs.duty.amount, TermsOfTrade=payload.customs.incoterm, ) if payload.customs is not None and payload.customs.duty is not None else None, ExportDeclaration=None, Reference=[Reference(ReferenceID=payload.reference)], SpecialService=[ SpecialService( SpecialServiceType=SpecialServiceCode[key].value.key) for key, svc in options if key in SpecialServiceCode ], Notification=(Notification( EmailAddress=options.notification_email or payload.recipient.email) if options.notification_email is None else None), DocImages=None, RequestArchiveDoc=None, NumberOfArchiveDoc=None, LabelImageFormat=label_format, Label=Label(LabelTemplate=label_template), ODDLinkReq=None, DGs=None, ) return Serializable(request, _request_serializer)
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)