Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
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)
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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))
Exemplo n.º 7
0
    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
Exemplo n.º 8
0
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)
Exemplo n.º 9
0
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)
Exemplo n.º 10
0
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)
Exemplo n.º 11
0
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"'))
Exemplo n.º 12
0
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"'),
    )
Exemplo n.º 13
0
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))
Exemplo n.º 14
0
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)
Exemplo n.º 15
0
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)
Exemplo n.º 16
0
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)
    )
Exemplo n.º 17
0
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")
    )
Exemplo n.º 18
0
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)
Exemplo n.º 19
0
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))
Exemplo n.º 20
0
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,
    )
Exemplo n.º 21
0
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))
Exemplo n.º 22
0
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)
Exemplo n.º 23
0
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)
Exemplo n.º 24
0
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"'
        ),
    )
Exemplo n.º 25
0
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,
    )
Exemplo n.º 26
0
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)
Exemplo n.º 27
0
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)
Exemplo n.º 28
0
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"))
Exemplo n.º 29
0
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)
Exemplo n.º 30
0
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)