Exemplo n.º 1
0
def shipment_request(
    payload: ShipmentRequest, settings: Settings
) -> Serializable[Envelope]:
    packages = Packages(payload.parcels, PackagePresets)
    packages.validate(required=["weight"])
    options = Options(payload.options, ServiceOption)
    service = ServiceCode.map(payload.service).value_or_key
    ship_from = CompleteAddress.map(payload.shipper)
    ship_to = CompleteAddress.map(payload.shipper)

    payment_account_number = getattr(
        payload.payment, "account_number", settings.account_number
    )
    payment_address = getattr(payload.payment, "address", None)
    mps_packaging = PackagingType.your_packaging.value if len(packages) > 1 else None
    payer = dict(
        sender=payment_address or ship_from,
        recipient=payment_address or ship_to,
        third_party=payment_address,
    )[getattr(payload.payment, "paid_by", "sender")]
    label_format, label_height, label_width = LabelType[
        payload.label_type or "PDF_6x4"
    ].value

    request = create_envelope(
        header_content=settings.Security,
        body_content=FreightShipRequest(
            Request=RequestType(
                RequestOption=1,
                SubVersion=1607,
                TransactionReference=TransactionReferenceType(
                    CustomerContext=payload.reference,
                    TransactionIdentifier=getattr(payload, "id", None),
                ),
            ),
            Shipment=ShipmentType(
                ShipFrom=ShipFromType(
                    Name=ship_from.company_name,
                    Address=AddressType(
                        AddressLine=ship_from.address_line,
                        City=ship_from.city,
                        StateProvinceCode=ship_from.state_code,
                        Town=None,
                        PostalCode=ship_from.postal_code,
                        CountryCode=ship_from.country_code,
                        ResidentialAddressIndicator=(
                            "" if ship_from.residential else None
                        ),
                    ),
                    TariffPoint=None,
                    AttentionName=ship_from.person_name,
                    Phone=PhoneType(Number=ship_from.phone_number),
                    FaxNumber=None,
                    EMailAddress=ship_from.email,
                ),
                ShipTo=ShipToType(
                    Name=ship_to.company_name,
                    TaxIdentificationNumber=None,
                    Address=AddressType(
                        AddressLine=ship_to.address_line,
                        City=ship_to.city,
                        StateProvinceCode=ship_to.state_code,
                        Town=None,
                        PostalCode=ship_to.postal_code,
                        CountryCode=ship_to.country_code,
                        ResidentialAddressIndicator=(
                            "" if ship_to.residential else None
                        ),
                    ),
                    TariffPoint=None,
                    AttentionName=ship_to.person_name,
                    Phone=PhoneType(Number=ship_to.phone_number),
                    FaxNumber=None,
                    EMailAddress=ship_to.email,
                ),
                PaymentInformation=PaymentInformationType(
                    Payer=PayerType(
                        Name=payer.company_name,
                        Address=AddressType(
                            AddressLine=payer.address_line,
                            City=payer.city,
                            StateProvinceCode=payer.state_code,
                            Town=None,
                            CountryCode=payer.country_code,
                            PostalCode=payer.postal_code,
                            ResidentialAddressIndicator=(
                                "" if payer.residential else None
                            ),
                        ),
                        ShipperNumber=payment_account_number,
                        AttentionName=payer.person_name,
                        Phone=PhoneType(Number=payer.phone_number),
                        FaxNumber=None,
                        EMailAddress=payer.email,
                    ),
                    ShipmentBillingOption=ShipCodeDescriptionType(
                        Code=40, Description="Freight Collect"
                    ),
                ),
                ManufactureInformation=None,
                Service=(
                    ShipCodeDescriptionType(Code=service, Description=None)
                    if service is not None
                    else None
                ),
                HandlingUnitOne=None,
                HandlingUnitTwo=None,
                ExistingShipmentID=None,
                HandlingInstructions=None,
                DeliveryInstructions=None,
                PickupInstructions=None,
                SpecialInstructions=None,
                ShipmentTotalWeight=ShipmentTotalWeightType(
                    Value=packages.weight.value,
                    UnitOfMeasurement=UPSWeightUnit[packages.weight.unit].value,
                ),
                Commodity=[
                    CommodityType(
                        CommodityID=getattr(commodity, "id", None),
                        Description=commodity.parcel.description,
                        Weight=WeightType(
                            Value=commodity.weight.value,
                            UnitOfMeasurement=UnitOfMeasurementType(
                                Code=UPSWeightUnit[commodity.weight_unit.name].value,
                            ),
                        ),
                        AdjustedWeight=None,
                        Dimensions=(
                            DimensionsType(
                                UnitOfMeasurement=UnitOfMeasurementType(
                                    Code=commodity.dimension_unit.value,
                                    Description=None,
                                ),
                                Length=commodity.length.value,
                                Width=commodity.width.value,
                                Height=commodity.height.value,
                            )
                            if commodity.has_dimensions
                            else None
                        ),
                        NumberOfPieces=1,
                        PackagingType=ShipCodeDescriptionType(
                            Code=(
                                mps_packaging
                                or PackagingType[
                                    commodity.packaging_type or "your_packaging"
                                ].value
                            ),
                        ),
                        DangerousGoodsIndicator=(
                            "" if options.dangerous_good else None
                        ),
                        CommodityValue=None,
                        FreightClass=FreightClass.map(
                            options.freight_class or 50
                        ).value,
                        NMFCCommodity=None,
                        NMFCCommodityCode=None,
                    )
                    for commodity in packages
                ],
                Reference=(
                    [
                        ReferenceType(
                            Number=ReferenceNumberType(
                                Code="OTHER", Value=payload.reference
                            )
                        )
                    ]
                    if any(payload.reference or "")
                    else None
                ),
                ShipmentServiceOptions=(
                    ShipmentServiceOptionsType(
                        EMailInformation=(
                            [
                                EMailInformationType(
                                    EMailType=f"000{email_type}",
                                    EMail=options.email_notification_to
                                    or payload.recipient.email,
                                )
                                for email_type in [1, 2, 3, 4]
                            ]
                            if any(
                                [options.email_notification_to, payload.recipient.email]
                            )
                            else None
                        ),
                        COD=(
                            CODType(
                                CODValue=CODValueType(
                                    CurrencyCode=options.currency or "USD",
                                    MonetaryValue=options.cash_on_delivery,
                                ),
                                CODPaymentMethod=ShipCodeDescriptionType(Code="M"),
                                CODBillingOption=ShipCodeDescriptionType(Code="02"),
                                RemitTo=RemitToType(
                                    Name=payer.company_name,
                                    Address=FreightShipAddressType(
                                        AddressLine=payer.address_line,
                                        City=payer.city,
                                        StateProvinceCode=payer.state_code,
                                        Town=payer.city,
                                        PostalCode=payer.postal_code,
                                        CountryCode=payer.country_code,
                                        ResidentialAddressIndicator=(
                                            "" if payer.residential else None
                                        ),
                                    ),
                                    AttentionName=payer.person_name,
                                    Phone=(
                                        FreightShipPhoneType(Number=payer.phone_number)
                                        if payer.phone_number
                                        else None
                                    ),
                                    FaxNumber=None,
                                    EMailAddress=payer.email,
                                ),
                            )
                            if options.cash_on_delivery
                            else None
                        ),
                        DangerousGoods=(
                            DangerousGoodsType(
                                Name=(ship_from.company_name or ship_from.person_name),
                                Phone=(
                                    FreightShipPhoneType(Number=payer.phone_number)
                                    if payer.phone_number
                                    else None
                                ),
                            )
                            if options.dangerous_good
                            else None
                        ),
                        DeclaredValue=(
                            DeclaredValueType(
                                CurrencyCode=options.currency or "USD",
                                MonetaryValue=options.declared_value,
                            )
                            if options.declared_value
                            else None
                        ),
                    )
                    if any(
                        [
                            options.cash_on_delivery,
                            options.email_notification,
                            options.dangerous_good,
                            options.declared_value,
                        ]
                    )
                    else None
                ),
                PickupRequest=None,
                Documents=DocumentsType(
                    Image=ImageType(
                        Type=ShipCodeDescriptionType(Code="30"),
                        LabelsPerPage=1,
                        Format=ShipCodeDescriptionType(Code="01"),
                        PrintFormat=ShipCodeDescriptionType(
                            Code="02" if "ZPL" in label_format else "01"
                        ),
                        PrintSize=PrintSizeType(Length=label_height, Width=label_width),
                    )
                ),
                ITNNumber=None,
                TaxID=None,
                MovementReferenceNumber=None,
                EICNumberAndStatement=None,
                TimeInTransitIndicator=None,
                HandlingUnits=None,
                DensityEligibleIndicator=None,
            ),
        ),
    )

    return Serializable(request, _request_serializer)
Exemplo n.º 2
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.º 3
0
def shipment_request(
    payload: ShipmentRequest, settings: Settings
) -> Serializable[ProcessShipmentRequest]:
    shipper = CompleteAddress.map(payload.shipper)
    recipient = CompleteAddress.map(payload.recipient)
    packages = Packages(payload.parcels, PackagePresets, required=["weight"])
    # Only the master package is selected here because even for MPS only one package is accepted for a master tracking.
    master_package = packages[0]

    service = ServiceType.map(payload.service).value_or_key
    options = Options(payload.options, SpecialServiceType)
    special_services = [getattr(v, 'value', v) for k, v in options if k in SpecialServiceType]
    label_type, label_format = LabelType[payload.label_type or 'PDF_4x6'].value
    customs = payload.customs
    duty = customs.duty if customs is not None else None
    bill_to = CompleteAddress(getattr(duty, 'bill_to', None))

    request = ProcessShipmentRequest(
        WebAuthenticationDetail=settings.webAuthenticationDetail,
        ClientDetail=settings.clientDetail,
        TransactionDetail=TransactionDetail(CustomerTransactionId="IE_v26_Ship"),
        Version=VersionId(ServiceId="ship", Major=26, Intermediate=0, Minor=0),
        RequestedShipment=RequestedShipment(
            ShipTimestamp=DF.date(options.shipment_date or datetime.now()),
            DropoffType="REGULAR_PICKUP",
            ServiceType=service,
            PackagingType=PackagingType[packages.package_type or 'your_packaging'].value,
            ManifestDetail=None,
            VariationOptions=None,
            TotalWeight=FedexWeight(
                Units=packages.weight.unit,
                Value=packages.weight.value
            ),
            TotalInsuredValue=options.insurance,
            PreferredCurrency=options.currency,
            ShipmentAuthorizationDetail=None,
            Shipper=Party(
                AccountNumber=settings.account_number,
                Tins=(
                    [TaxpayerIdentification(Number=tax) for tax in shipper.taxes]
                    if shipper.has_tax_info else None
                ),
                Contact=(
                    Contact(
                        ContactId=None,
                        PersonName=shipper.person_name,
                        Title=None,
                        CompanyName=shipper.company_name,
                        PhoneNumber=shipper.phone_number,
                        PhoneExtension=None,
                        TollFreePhoneNumber=None,
                        PagerNumber=None,
                        FaxNumber=None,
                        EMailAddress=shipper.email,
                    )
                    if shipper.has_contact_info else None
                ),
                Address=Address(
                    StreetLines=shipper.address_lines,
                    City=shipper.city,
                    StateOrProvinceCode=shipper.state_code,
                    PostalCode=shipper.postal_code,
                    UrbanizationCode=None,
                    CountryCode=shipper.country_code,
                    CountryName=shipper.country_name,
                    Residential=shipper.residential,
                    GeographicCoordinates=None,
                ),
            ),
            Recipient=Party(
                AccountNumber=None,
                Tins=(
                    [TaxpayerIdentification(Number=tax) for tax in recipient.taxes]
                    if recipient.has_tax_info else None
                ),
                Contact=(
                    Contact(
                        ContactId=None,
                        PersonName=recipient.person_name,
                        Title=None,
                        CompanyName=recipient.company_name,
                        PhoneNumber=recipient.phone_number,
                        PhoneExtension=None,
                        TollFreePhoneNumber=None,
                        PagerNumber=None,
                        FaxNumber=None,
                        EMailAddress=recipient.email,
                    )
                    if recipient.has_contact_info else None
                ),
                Address=Address(
                    StreetLines=recipient.address_lines,
                    City=recipient.city,
                    StateOrProvinceCode=recipient.state_code,
                    PostalCode=recipient.postal_code,
                    UrbanizationCode=None,
                    CountryCode=recipient.country_code,
                    CountryName=recipient.country_name,
                    Residential=recipient.residential,
                    GeographicCoordinates=None,
                ),
            ),
            RecipientLocationNumber=None,
            Origin=None,
            SoldTo=None,
            ShippingChargesPayment=Payment(
                PaymentType=PaymentType[payload.payment.paid_by or "sender"].value,
                Payor=Payor(
                    ResponsibleParty=Party(
                        AccountNumber=(payload.payment.account_number or settings.account_number),
                    )
                ),
            ),
            SpecialServicesRequested=(
                ShipmentSpecialServicesRequested(
                    SpecialServiceTypes=special_services,
                    CodDetail=(
                        CodDetail(
                            CodCollectionAmount=Money(
                                Currency=options.currency or "USD",
                                Amount=options.cash_on_delivery,
                            ),
                            AddTransportationChargesDetail=None,
                            CollectionType=CodCollectionType.CASH,
                            CodRecipient=None,
                            FinancialInstitutionContactAndAddress=None,
                            RemitToName=None,
                            ReferenceIndicator=None,
                            ReturnTrackingId=None,
                        )
                        if options.cash_on_delivery else None
                    ),
                    DeliveryOnInvoiceAcceptanceDetail=None,
                    HoldAtLocationDetail=None,
                    EventNotificationDetail=(
                        ShipmentEventNotificationDetail(
                            AggregationType=None,
                            PersonalMessage=None,
                            EventNotifications=[
                                ShipmentEventNotificationSpecification(
                                    Role=None,
                                    Events=NOTIFICATION_EVENTS,
                                    NotificationDetail=NotificationDetail(
                                        NotificationType="EMAIL",
                                        EmailDetail=EMailDetail(
                                            EmailAddress=(options.email_notification_to or recipient.email),
                                            Name=recipient.person_name or recipient.company_name,
                                        ),
                                        Localization=Localization(LanguageCode="EN"),
                                    ),
                                    FormatSpecification=ShipmentNotificationFormatSpecification(
                                        Type="TEXT"
                                    ),
                                )
                            ],
                        )
                        if options.email_notification and any([options.email_notification_to, recipient.email])
                        else None
                    ),
                    ReturnShipmentDetail=None,
                    PendingShipmentDetail=None,
                    InternationalControlledExportDetail=None,
                    InternationalTrafficInArmsRegulationsDetail=None,
                    ShipmentDryIceDetail=None,
                    HomeDeliveryPremiumDetail=None,
                    EtdDetail=None,
                )
                if options.has_content else None
            ),
            ExpressFreightDetail=None,
            FreightShipmentDetail=None,
            DeliveryInstructions=None,
            VariableHandlingChargeDetail=None,
            CustomsClearanceDetail=(
                CustomsClearanceDetail(
                    Brokers=None,
                    ClearanceBrokerage=None,
                    CustomsOptions=None,
                    ImporterOfRecord=None,
                    RecipientCustomsId=None,
                    DutiesPayment=(
                        Payment(
                            PaymentType=PaymentType[duty.paid_by or "sender"].value,
                            Payor=(
                                Payor(
                                    ResponsibleParty=Party(
                                        AccountNumber=duty.account_number,
                                        Tins=bill_to.taxes
                                    )
                                ) if any([duty.account_number, bill_to.taxes]) else None
                            )
                        ) if duty is not None else None
                    ),
                    DocumentContent=None,
                    CustomsValue=Money(
                        Currency=(duty.currency or options.currency),
                        Amount=(duty.declared_value or options.declared_value)
                    ),
                    FreightOnValue=None,
                    InsuranceCharges=None,
                    PartiesToTransactionAreRelated=None,
                    CommercialInvoice=(
                        CommercialInvoice(
                            Comments=None,
                            FreightCharge=None,
                            TaxesOrMiscellaneousChargeType=None,
                            PackingCosts=None,
                            HandlingCosts=None,
                            SpecialInstructions=None,
                            DeclarationStatement=None,
                            PaymentTerms=None,
                            Purpose=PurposeType[customs.content_type or 'other'].value,
                            PurposeOfShipmentDescription=None,
                            CustomerReferences=None,
                            OriginatorName=(shipper.company_name or shipper.person_name),
                            TermsOfSale=Incoterm[customs.incoterm or "DDU"].value
                        )
                        if customs.commercial_invoice else None
                    ),
                    Commodities=[
                        Commodity(
                            Name=None,
                            NumberOfPieces=item.quantity,
                            Description=item.description or "N/A",
                            Purpose=None,
                            CountryOfManufacture=item.origin_country,
                            HarmonizedCode=None,
                            Weight=FedexWeight(
                                Units=master_package.weight_unit.value,
                                Value=Weight(item.weight, item.weight_unit)[master_package.weight_unit.value]
                            ),
                            Quantity=item.quantity,
                            QuantityUnits='EA',
                            AdditionalMeasures=None,
                            UnitPrice=Money(
                                Currency=(options.currency or duty.currency),
                                Amount=item.value_amount,
                            ),
                            CustomsValue=None,
                            ExciseConditions=None,
                            ExportLicenseNumber=None,
                            ExportLicenseExpirationDate=None,
                            CIMarksAndNumbers=None,
                            PartNumber=item.sku,
                            NaftaDetail=None,
                        ) for item in customs.commodities
                    ],
                    ExportDetail=None,
                    RegulatoryControls=None,
                    DeclarationStatementDetail=None
                ) if payload.customs is not None else None
            ),
            PickupDetail=None,
            SmartPostDetail=None,
            BlockInsightVisibility=None,
            LabelSpecification=LabelSpecification(
                Dispositions=None,
                LabelFormatType=LabelFormatType.COMMON_2_D.value,
                ImageType=label_type,
                LabelStockType=label_format,
                LabelPrintingOrientation=LabelPrintingOrientationType.TOP_EDGE_OF_TEXT_FIRST.value,
                LabelOrder=LabelOrderType.SHIPPING_LABEL_FIRST.value,
                PrintedLabelOrigin=None,
                CustomerSpecifiedDetail=None,
            ),
            ShippingDocumentSpecification=None,
            RateRequestTypes=None,
            EdtRequestType=None,
            MasterTrackingId=None,
            PackageCount=len(packages),
            ConfigurationData=None,
            RequestedPackageLineItems=[
                RequestedPackageLineItem(
                    SequenceNumber=1,
                    GroupNumber=None,
                    GroupPackageCount=None,
                    VariableHandlingChargeDetail=None,
                    InsuredValue=None,
                    Weight=(
                        FedexWeight(
                            Units=master_package.weight.unit,
                            Value=master_package.weight.value,
                        )
                        if master_package.weight.value else None
                    ),
                    Dimensions=(
                        FedexDimensions(
                            Length=master_package.length.map(MeasurementOptions).value,
                            Width=master_package.width.map(MeasurementOptions).value,
                            Height=master_package.height.map(MeasurementOptions).value,
                            Units=master_package.dimension_unit.value,
                        )
                        if master_package.has_dimensions else None
                    ),
                    PhysicalPackaging=None,
                    ItemDescription=master_package.parcel.description,
                    ItemDescriptionForClearance=None,
                    CustomerReferences=(
                        [
                            CustomerReference(
                                CustomerReferenceType=CustomerReferenceType.CUSTOMER_REFERENCE,
                                Value=payload.reference
                            )
                        ]
                        if any(payload.reference or "") else None
                    ),
                    SpecialServicesRequested=None,
                    ContentRecords=None,
                )
            ],
        ),
    )
    return Serializable(request, _request_serializer)
Exemplo n.º 4
0
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[IntlRateV2Request]:
    """Create the appropriate USPS International rate request depending on the destination

    :param payload: Purplship unified API rate request data
    :param settings: USPS International connection and auth settings
    :return: a domestic or international USPS International compatible request
    :raises:
        - OriginNotServicedError when origin country is not serviced by the carrier
        - DestinationNotServicedError when destination country is US
    """

    if payload.shipper.country_code is not None and payload.shipper.country_code != Country.US.name:
        raise OriginNotServicedError(payload.shipper.country_code)

    if payload.recipient.country_code == Country.US.name:
        raise DestinationNotServicedError(payload.recipient.country_code)

    package = Packages(payload.parcels, max_weight=Weight(70, WeightUnit.LB)).single
    recipient = CompleteAddress(payload.recipient)
    options = Options(payload.options, ShipmentOption)
    services = Services(payload.services, ShipmentService)

    extra_services = [getattr(option, 'value', option) for key, option in options if 'usps_option' not in key]
    commercial = next(("Y" for svc in services if "commercial" in svc.name), "N")
    commercial_plus = next(("Y" for svc in services if "plus" in svc.name), "N")

    request = IntlRateV2Request(
        USERID=settings.username,
        Revision="2",
        Package=[
            PackageType(
                ID=0,
                Pounds=package.weight.LB,
                Ounces=package.weight.OZ,
                Machinable=options.usps_option_machinable_item or False,
                MailType=PackagingType[package.packaging_type or "package"].value,
                GXG=(
                    GXGType(POBoxFlag='N', GiftFlag='N')
                    if any('global_express_guaranteed' in s.name for s in payload.services) else None
                ),
                ValueOfContents=(options.declared_value or ""),
                Country=recipient.country_name,
                Width=package.width.IN,
                Length=package.length.IN,
                Height=package.height.IN,
                Girth=(package.girth.value if package.packaging_type == "tube" else None),
                OriginZip=payload.shipper.postal_code,
                CommercialFlag=commercial,
                CommercialPlusFlag=commercial_plus,
                AcceptanceDateTime=DF.fdatetime(
                    (options.shipment_date or datetime.today()),
                    output_format="%Y-%m-%dT%H:%M:%S"
                ),
                DestinationPostalCode=recipient.postal_code,
                ExtraServices=(
                    ExtraServicesType(ExtraService=[s for s in extra_services])
                    if any(extra_services) else None
                ),
                Content=None,
            )
        ],
    )

    return Serializable(request, XP.export)
Exemplo n.º 5
0
def rate_request(
    payload: RateRequest, settings: Settings
) -> Serializable[FedexRateRequest]:
    shipper = CompleteAddress.map(payload.shipper)
    recipient = CompleteAddress.map(payload.recipient)
    packages = Packages(payload.parcels, PackagePresets, required=["weight"])
    service = Services(payload.services, ServiceType).first
    options = Options(payload.options)

    request_types = ["LIST"] + ([] if "currency" not in options else ["PREFERRED"])

    request = FedexRateRequest(
        WebAuthenticationDetail=settings.webAuthenticationDetail,
        ClientDetail=settings.clientDetail,
        TransactionDetail=TransactionDetail(CustomerTransactionId="FTC"),
        Version=VersionId(ServiceId="crs", Major=28, Intermediate=0, Minor=0),
        ReturnTransitAndCommit=True,
        CarrierCodes=None,
        VariableOptions=None,
        ConsolidationKey=None,
        RequestedShipment=RequestedShipment(
            ShipTimestamp=DF.date(options.shipment_date or datetime.now()),
            DropoffType="REGULAR_PICKUP",
            ServiceType=(service.value if service is not None else None),
            PackagingType=PackagingType[packages.package_type or 'your_packaging'].value,
            VariationOptions=None,
            TotalWeight=FedexWeight(
                Units=packages.weight.unit,
                Value=packages.weight.LB,
            ),
            TotalInsuredValue=None,
            PreferredCurrency=options.currency,
            ShipmentAuthorizationDetail=None,
            Shipper=Party(
                AccountNumber=settings.account_number,
                Tins=(
                    [TaxpayerIdentification(Number=tax) for tax in shipper.taxes]
                    if shipper.has_tax_info else None
                ),
                Contact=(
                    Contact(
                        ContactId=None,
                        PersonName=shipper.person_name,
                        Title=None,
                        CompanyName=shipper.company_name,
                        PhoneNumber=shipper.phone_number,
                        PhoneExtension=None,
                        TollFreePhoneNumber=None,
                        PagerNumber=None,
                        FaxNumber=None,
                        EMailAddress=shipper.email,
                    )
                    if shipper.has_contact_info else None
                ),
                Address=Address(
                    StreetLines=shipper.address_lines,
                    City=shipper.city,
                    StateOrProvinceCode=shipper.state_code,
                    PostalCode=shipper.postal_code,
                    UrbanizationCode=None,
                    CountryCode=shipper.country_code,
                    CountryName=shipper.country_name,
                    Residential=shipper.residential,
                    GeographicCoordinates=None,
                ),
            ),
            Recipient=Party(
                AccountNumber=None,
                Tins=(
                    [TaxpayerIdentification(Number=tax) for tax in recipient.taxes]
                    if recipient.has_tax_info else None
                ),
                Contact=(
                    Contact(
                        ContactId=None,
                        PersonName=recipient.person_name,
                        Title=None,
                        CompanyName=recipient.company_name,
                        PhoneNumber=recipient.phone_number,
                        PhoneExtension=None,
                        TollFreePhoneNumber=None,
                        PagerNumber=None,
                        FaxNumber=None,
                        EMailAddress=recipient.email,
                    )
                    if recipient.has_contact_info else None
                ),
                Address=Address(
                    StreetLines=recipient.address_lines,
                    City=recipient.city,
                    StateOrProvinceCode=recipient.state_code,
                    PostalCode=recipient.postal_code,
                    UrbanizationCode=None,
                    CountryCode=recipient.country_code,
                    CountryName=recipient.country_name,
                    Residential=recipient.residential,
                    GeographicCoordinates=None,
                ),
            ),
            RecipientLocationNumber=None,
            Origin=None,
            SoldTo=None,
            ShippingChargesPayment=None,
            SpecialServicesRequested=None,
            ExpressFreightDetail=None,
            FreightShipmentDetail=None,
            DeliveryInstructions=None,
            VariableHandlingChargeDetail=None,
            CustomsClearanceDetail=None,
            PickupDetail=None,
            SmartPostDetail=None,
            BlockInsightVisibility=None,
            LabelSpecification=None,
            ShippingDocumentSpecification=None,
            RateRequestTypes=request_types,
            EdtRequestType=None,
            PackageCount=len(packages),
            ShipmentOnlyFields=None,
            ConfigurationData=None,
            RequestedPackageLineItems=[
                RequestedPackageLineItem(
                    SequenceNumber=index,
                    GroupNumber=None,
                    GroupPackageCount=1,
                    VariableHandlingChargeDetail=None,
                    InsuredValue=None,
                    Weight=(
                        FedexWeight(
                            Units=package.weight.unit,
                            Value=package.weight.value,
                        )
                        if package.weight.value else None
                    ),
                    Dimensions=(
                        Dimensions(
                            Length=package.length.map(MeasurementOptions).value,
                            Width=package.width.map(MeasurementOptions).value,
                            Height=package.height.map(MeasurementOptions).value,
                            Units=package.dimension_unit.value,
                        )
                        if package.has_dimensions else None
                    ),
                    PhysicalPackaging=None,
                    ItemDescription=package.parcel.description,
                    ItemDescriptionForClearance=None,
                    CustomerReferences=(
                        [
                            CustomerReference(
                                CustomerReferenceType=CustomerReferenceType.CUSTOMER_REFERENCE,
                                Value=payload.reference
                            )
                        ]
                        if any(payload.reference or "") else None
                    ),
                    SpecialServicesRequested=None,
                    ContentRecords=None,
                )
                for index, package in enumerate(packages, 1)
            ],
        ),
    )
    return Serializable(request, _request_serializer)
Exemplo n.º 6
0
def rate_request(payload: RateRequest,
                 settings: Settings) -> Serializable[Envelope]:
    packages = Packages(payload.parcels, PackagePresets)
    packages.validate(required=["weight"])
    options = Options(payload.options, ServiceOption)
    service = Services(payload.services, ServiceCode).first
    ship_from = CompleteAddress.map(payload.shipper)
    ship_to = CompleteAddress.map(payload.shipper)

    mps_packaging = PackagingType.ups_freight_other.value if len(
        packages) > 1 else None

    request = create_envelope(
        header_content=settings.Security,
        body_content=FreightRateRequest(
            Request=RequestType(
                RequestOption=[1],
                SubVersion=1707,
                TransactionReference=TransactionReferenceType(
                    CustomerContext=payload.reference,
                    TransactionIdentifier=getattr(payload, "id", None),
                ),
            ),
            ShipFrom=ShipFromType(
                Name=ship_from.company_name,
                Address=AddressType(
                    AddressLine=[ship_from.address_line],
                    City=ship_from.city,
                    StateProvinceCode=ship_from.state_code,
                    Town=None,
                    CountryCode=ship_from.country_code,
                    ResidentialAddressIndicator=("" if ship_from.residential
                                                 else None),
                ),
                AttentionName=ship_from.person_name,
                TariffPoint=None,
            ),
            ShipTo=ShipToType(
                Name=ship_to.company_name,
                Address=AddressType(
                    AddressLine=[ship_to.address_line],
                    City=ship_to.city,
                    StateProvinceCode=ship_to.state_code,
                    Town=None,
                    CountryCode=ship_to.country_code,
                    ResidentialAddressIndicator=("" if ship_to.residential else
                                                 None),
                ),
                AttentionName=ship_to.person_name,
                TariffPoint=None,
            ),
            PaymentInformation=PaymentInformationType(
                Payer=PayerType(
                    Name=ship_from.company_name,
                    Address=AddressType(
                        AddressLine=[ship_from.address_line],
                        City=ship_from.city,
                        StateProvinceCode=ship_from.state_code,
                        Town=None,
                        CountryCode=ship_from.country_code,
                        ResidentialAddressIndicator=(
                            "" if ship_from.residential else None),
                    ),
                    AttentionName=ship_from.person_name,
                    ShipperNumber=settings.account_number,
                ),
                ShipmentBillingOption=RateCodeDescriptionType(
                    Code=40, Description="Freight Collect"),
            ),
            Service=(RateCodeDescriptionType(Code=service, Description=None)
                     if service is not None else None),
            HandlingUnitOne=None,
            HandlingUnitTwo=None,
            Commodity=[
                CommodityType(
                    CommodityID=getattr(commodity, "id", None),
                    Description=commodity.parcel.description,
                    Weight=WeightType(
                        Value=commodity.weight.value,
                        UnitOfMeasurement=UnitOfMeasurementType(
                            Code=UPSWeightUnit[
                                commodity.weight_unit.name].value, ),
                    ),
                    AdjustedWeight=None,
                    Dimensions=(DimensionsType(
                        UnitOfMeasurement=UnitOfMeasurementType(
                            Code=commodity.dimension_unit.value,
                            Description=None),
                        Length=commodity.length.value,
                        Width=commodity.width.value,
                        Height=commodity.height.value,
                    ) if commodity.has_dimensions else None),
                    NumberOfPieces=1,
                    PackagingType=RateCodeDescriptionType(
                        Code=(mps_packaging or PackagingType[
                            commodity.packaging_type or "small_box"].value, )),
                    DangerousGoodsIndicator=None,
                    CommodityValue=None,
                    FreightClass=None,
                    NMFCCommodity=None,
                    NMFCCommodityCode=None,
                ) for commodity in packages
            ],
            ShipmentServiceOptions=(ShipmentServiceOptionsType(
                PickupOptions=None,
                DeliveryOptions=None,
                OverSeasLeg=None,
                COD=None,
                DangerousGoods=None,
                SortingAndSegregating=None,
                DeclaredValue=None,
                ExcessDeclaredValue=None,
                CustomsValue=None,
                DeliveryDutiesPaidIndicator=None,
                DeliveryDutiesUnpaidIndicator=None,
                HandlingCharge=None,
                CustomsClearanceIndicator=None,
                FreezableProtectionIndicator=None,
                ExtremeLengthIndicator=None,
                LinearFeet=None,
                AdjustedHeight=None,
            ) if any([
                options.cash_on_delivery,
                options.email_notification,
                options.dangerous_good,
                options.declared_value,
            ]) else None),
            PickupRequest=None,
            AlternateRateOptions=RateCodeDescriptionType(Code=3),
            GFPOptions=None,
            AccountType=None,
            ShipmentTotalWeight=ShipmentTotalWeightType(
                Value=packages.weight.value,
                UnitOfMeasurement=UnitOfMeasurementType(
                    Code=UPSWeightUnit[packages.weight.unit].value, ),
            ),
            HandlingUnitWeight=None,
            AdjustedWeightIndicator=None,
            TimeInTransitIndicator="",
            HandlingUnits=None,
            AdjustedHeightIndicator=None,
            DensityEligibleIndicator=None,
            QuoteNumberIndicator="",
        ),
    )

    return Serializable(request, _request_serializer)
def shipment_request(
        payload: ShipmentRequest,
        settings: Settings) -> Serializable[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 key in ShipmentOption and '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 = CompleteAddress.map(
        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_line2,
        FromAddress2=payload.shipper.address_line1,
        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 or "",
        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_line2,
        ToAddress2=payload.recipient.address_line1,
        ToAddress3=None,
        ToCity=payload.recipient.city,
        ToProvince=Location(
            payload.recipient.state_code,
            country=payload.recipient.country_code).as_state_name,
        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=redirect_address.address_line,
        RedirectCity=redirect_address.city,
        RedirectState=redirect_address.state_code,
        RedirectZipCode=redirect_address.postal_code,
        RedirectZip4=Location(redirect_address.postal_code).as_zip4 or "",
        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 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 or time.strftime('%Y-%m-%d')),
            current_format="%Y-%m-%d",
            output_format="%m/%d/%Y"),
        EMCAAccount=None,
        HoldForManifest=None,
        EELPFC=customs.eel_pfc,
        PriceOptions=None,
        Length=package.length.IN,
        Width=package.width.IN,
        Height=package.height.IN,
        Girth=(package.girth.value
               if package.packaging_type == "tube" else None),
        ExtraServices=(ExtraServicesType(
            ExtraService=[s for s 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 or False),
        DestinationRateIndicator="I",
        MID=settings.mailer_id,
        LogisticsManagerMID=settings.logistics_manager_mailer_id,
        CRID=settings.customer_registration_id,
        VendorCode=None,
        VendorProductVersionNumber=None,
        ChargebackCode=None,
    )

    return Serializable(request, XP.export)