Esempio n. 1
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)
Esempio n. 2
0
def pickup_update_request(
    payload: PickupUpdateRequest, settings: Settings
) -> Serializable[ModifyPURequest]:
    weight_unit = DHLWeightUnit.LB
    weight = sum(
        [
            Weight(parcel.weight, WeightUnit[weight_unit.name]).LB
            for parcel in payload.parcels
        ]
    )
    request = ModifyPURequest(
        Request=settings.Request(
            MetaData=MetaData(SoftwareName="XMLPI", SoftwareVersion=1.0)
        ),
        schemaVersion=3.0,
        RegionCode=CountryRegion[payload.address.country_code].value
        if payload.address.country_code
        else "AM",
        ConfirmationNumber=payload.confirmation_number,
        Requestor=Requestor(
            AccountNumber=settings.account_number,
            AccountType="D",
            RequestorContact=RequestorContact(
                PersonName=payload.address.person_name,
                Phone=payload.address.phone_number,
                PhoneExtension=None,
            ),
            CompanyName=payload.address.company_name,
        ),
        Place=Place(
            City=payload.address.city,
            StateCode=payload.address.state_code,
            PostalCode=payload.address.postal_code,
            CompanyName=payload.address.company_name,
            CountryCode=payload.address.country_code,
            PackageLocation=payload.package_location,
            LocationType="R" if payload.address.residential else "B",
            Address1=payload.address.address_line1,
            Address2=payload.address.address_line2,
        ),
        PickupContact=RequestorContact(
            PersonName=payload.address.person_name, Phone=payload.address.phone_number
        ),
        Pickup=Pickup(
            Pieces=len(payload.parcels),
            PickupDate=payload.pickup_date,
            ReadyByTime=f"{payload.ready_time}:00",
            CloseTime=f"{payload.closing_time}:00",
            SpecialInstructions=[payload.instruction],
            RemotePickupFlag="Y",
            weight=WeightSeg(Weight=weight, WeightUnit=weight_unit.value),
        ),
        OriginSvcArea=None,
    )
    return Serializable(request, _request_serializer)
Esempio n. 3
0
def pickup_cancel_request(payload: PickupCancelRequest,
                          settings: Settings) -> Serializable[CancelPURequest]:

    request = CancelPURequest(
        Request=settings.Request(
            MetaData=MetaData(SoftwareName="XMLPI", SoftwareVersion=1.0)),
        schemaVersion=3.0,
        RegionCode=(CountryRegion[payload.address.country_code].value
                    if payload.address is not None
                    and payload.address.country_code is not None else "AM"),
        ConfirmationNumber=payload.confirmation_number,
        RequestorName=payload.address.person_name,
        CountryCode=payload.address.country_code,
        Reason="006",
        PickupDate=payload.pickup_date,
        CancelTime=time.strftime("%H:%M:%S"),
    )
    return Serializable(request, _request_serializer)
Esempio n. 4
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)
Esempio n. 5
0
def rate_request(payload: RateRequest,
                 settings: Settings) -> Serializable[DCTRequest]:
    packages = Packages(payload.parcels, PackagePresets, required=["weight"])
    products = [*Services(payload.services, ProductCode)]
    options = Options(payload.options, SpecialServiceCode)

    is_international = payload.shipper.country_code != payload.recipient.country_code
    is_document = all([parcel.is_document for parcel in payload.parcels])
    is_dutiable = not is_document

    if not is_international and payload.shipper.country_code in ["CA"]:
        raise DestinationNotServicedError(payload.shipper.country_code)

    paperless = (SpecialServiceCode.dhl_paperless_trade if
                 (is_international and is_dutiable) else None)
    special_services = [
        *options, *([(paperless.name, None)] if paperless is not None else [])
    ]
    insurance = options[
        'dhl_shipment_insurance'].value if 'dhl_shipment_insurance' in options else None

    if len(products) == 0:
        if is_international and is_document:
            product = 'dhl_express_worldwide_doc'
        elif is_international:
            product = 'dhl_express_worldwide_nondoc'
        elif is_document:
            product = 'dhl_express_worldwide_doc'
        else:
            product = 'dhl_express_easy_nondoc'

        products = [ProductCode[product]]

    request = DCTRequest(GetQuote=GetQuoteType(
        Request=settings.Request(
            MetaData=MetaData(SoftwareName="3PV", SoftwareVersion=1.0)),
        From=DCTFrom(
            CountryCode=payload.shipper.country_code,
            Postalcode=payload.shipper.postal_code,
            City=payload.shipper.city,
            Suburb=payload.shipper.state_code,
        ),
        To=DCTTo(
            CountryCode=payload.recipient.country_code,
            Postalcode=payload.recipient.postal_code,
            City=payload.recipient.city,
            Suburb=payload.recipient.state_code,
        ),
        BkgDetails=BkgDetailsType(
            PaymentCountryCode=payload.shipper.country_code,
            NetworkTypeCode=NetworkType.both_time_and_day_definite.value,
            WeightUnit=WeightUnit.LB.value,
            DimensionUnit=DimensionUnit.IN.value,
            ReadyTime=time.strftime("PT%HH%MM"),
            Date=time.strftime("%Y-%m-%d"),
            IsDutiable=("Y" if is_dutiable else "N"),
            Pieces=PiecesType(Piece=[
                PieceType(
                    PieceID=package.parcel.id or f"{index}",
                    PackageTypeCode=DCTPackageType[package.packaging_type
                                                   or "your_packaging"].value,
                    Depth=package.length.IN,
                    Width=package.width.IN,
                    Height=package.height.IN,
                    Weight=package.weight.LB,
                ) for index, package in enumerate(
                    cast(Iterable[Package], packages), 1)
            ]),
            NumberOfPieces=len(packages),
            ShipmentWeight=packages.weight.LB,
            Volume=None,
            PaymentAccountNumber=settings.account_number,
            InsuredCurrency=(options.currency
                             if insurance is not None else None),
            InsuredValue=insurance,
            PaymentType=None,
            AcctPickupCloseTime=None,
            QtdShp=[
                QtdShpType(
                    GlobalProductCode=product.value,
                    LocalProductCode=product.value,
                    QtdShpExChrg=[
                        QtdShpExChrgType(
                            SpecialServiceType=SpecialServiceCode[key].value.
                            key) for key, _ in special_services
                        if key in SpecialServiceCode
                    ],
                ) for product in products
            ],
        ),
        Dutiable=(DCTDutiable(
            DeclaredValue=insurance or 1.0,
            DeclaredCurrency=options.currency
            or CountryCurrency[payload.shipper.country_code].value)
                  if is_international and is_dutiable else None),
    ), )

    return Serializable(request, _request_serializer)
Esempio n. 6
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)