def address_validation_request( payload: AddressValidationRequest, settings: Settings) -> Serializable[RouteRequest]: country = (Country[payload.address.country_code] if payload.address.country_code is not None else None) division = ( CountryState[country.name].value[payload.address.state_code].value if (country.name in CountryState.__members__ and payload.address.state_code in CountryState[country.name].value.__members__) else None) request = RouteRequest( schemaVersion="2.0", Request=settings.Request( MetaData=MetaData(SoftwareName="3PV", SoftwareVersion=1.0)), RegionCode=CountryRegion[payload.address.country_code].value, RequestType=RequestType.D.value, Address1=SF.concat_str(payload.address.address_line1, join=True), Address2=SF.concat_str(payload.address.address_line2, join=True), Address3=None, PostalCode=payload.address.postal_code, City=payload.address.city, Division=division, CountryCode=country.name, CountryName=country.value, OriginCountryCode=payload.address.country_code, ) return Serializable(request, _request_serializer)
def 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)
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)
def shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[DHLShipmentRequest]: packages = Packages(payload.parcels, PackagePresets, required=["weight"]) options = Options(payload.options, SpecialServiceCode) product = ProductCode[payload.service].value insurance = options[ 'dhl_shipment_insurance'].value if 'dhl_shipment_insurance' in options else None package_type = (PackageType[packages[0].packaging_type or "your_packaging"].value if len(packages) == 1 else None) delivery_type = next( (d for d in DeliveryType if d.name in payload.options.keys()), None) has_payment_config = payload.payment is not None has_customs_config = payload.customs is not None label_format, label_template = LabelType[payload.label_type or 'PDF_6x4'].value request = DHLShipmentRequest( schemaVersion=6.2, Request=settings.Request( MetaData=MetaData(SoftwareName="3PV", SoftwareVersion=6.2)), RegionCode=CountryRegion[payload.shipper.country_code].value, RequestedPickupTime="Y", LanguageCode="en", PiecesEnabled="Y", LatinResponseInd=None, Billing=Billing( ShipperAccountNumber=settings.account_number, BillingAccountNumber=payload.payment.account_number if has_payment_config else None, ShippingPaymentType=PaymentType[payload.payment.paid_by].value if has_payment_config else None, DutyAccountNumber=payload.customs.duty.account_number if has_customs_config else None, DutyPaymentType=PaymentType[payload.customs.duty.paid_by].value if has_customs_config else None, ), Consignee=Consignee( CompanyName=payload.recipient.company_name or " ", SuiteDepartmentName=None, AddressLine=SF.concat_str(payload.recipient.address_line1, payload.recipient.address_line2), City=payload.recipient.city, Division=None, DivisionCode=payload.recipient.state_code, PostalCode=payload.recipient.postal_code, CountryCode=payload.recipient.country_code, CountryName=Country[payload.recipient.country_code].value, FederalTaxId=payload.shipper.federal_tax_id, StateTaxId=payload.shipper.state_tax_id, Contact=(Contact( PersonName=payload.recipient.person_name, PhoneNumber=payload.recipient.phone_number or "0000", Email=payload.recipient.email, )), Suburb=None, ), Commodity=[ Commodity(CommodityCode=c.sku, CommodityName=c.description) for c in payload.customs.commodities ] if payload.customs is not None else None, NewShipper=None, Shipper=Shipper( ShipperID=settings.account_number or " ", RegisteredAccount=settings.account_number, AddressLine=SF.concat_str(payload.shipper.address_line1, payload.shipper.address_line2), CompanyName=payload.shipper.company_name or " ", PostalCode=payload.shipper.postal_code, CountryCode=payload.shipper.country_code, City=payload.shipper.city, CountryName=Country[payload.shipper.country_code].value, Division=None, DivisionCode=payload.shipper.state_code, Contact=(Contact( PersonName=payload.shipper.person_name, PhoneNumber=payload.shipper.phone_number or "0000", Email=payload.shipper.email, )), ), ShipmentDetails=DHLShipmentDetails( NumberOfPieces=len(packages), Pieces=Pieces(Piece=[ Piece( PieceID=payload.parcels[index].id, PackageType=(package_type or PackageType[ package.packaging_type or "your_packaging"].value), Depth=package.length.IN, Width=package.width.IN, Height=package.height.IN, Weight=package.weight.LB, DimWeight=None, PieceContents=payload.parcels[index].description, ) for index, package in enumerate(packages) ]), Weight=packages.weight.LB, CurrencyCode=options.currency or "USD", WeightUnit=WeightUnit.L.value, DimensionUnit=DimensionUnit.I.value, Date=(options.shipment_date or time.strftime("%Y-%m-%d")), PackageType=package_type, IsDutiable=("Y" if payload.customs is not None else "N"), InsuredAmount=insurance, ShipmentCharges=(options.cash_on_delivery if options.cash_on_delivery else None), DoorTo=delivery_type, GlobalProductCode=product, LocalProductCode=product, Contents=" ", ), EProcShip=None, Dutiable=Dutiable( DeclaredCurrency=payload.customs.duty.currency or "USD", DeclaredValue=payload.customs.duty.amount, TermsOfTrade=payload.customs.incoterm, ) if payload.customs is not None and payload.customs.duty is not None else None, ExportDeclaration=None, Reference=[Reference(ReferenceID=payload.reference)], SpecialService=[ SpecialService( SpecialServiceType=SpecialServiceCode[key].value.key) for key, svc in options if key in SpecialServiceCode ], Notification=(Notification( EmailAddress=options.notification_email or payload.recipient.email) if options.notification_email is None else None), DocImages=None, RequestArchiveDoc=None, NumberOfArchiveDoc=None, LabelImageFormat=label_format, Label=Label(LabelTemplate=label_template), ODDLinkReq=None, DGs=None, ) return Serializable(request, _request_serializer)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[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)
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)