예제 #1
0
def create_shipping_request(payload: ShipmentRequest,
                            settings: Settings,
                            validate: bool = None) -> Serializable[Envelope]:
    RequestType: ShipmentRequestType = ValidateShipmentRequest if validate else CreateShipmentRequest

    packages = Packages(payload.parcels, PackagePresets, required=["weight"])
    is_document = all([parcel.is_document for parcel in payload.parcels])
    package_description = (packages[0].parcel.description
                           if len(packages) == 1 else None)
    service = Product[payload.service].value
    is_international = payload.shipper.country_code != payload.recipient.country_code
    options = Options(payload.options)
    shipper_phone_number = Phone(payload.shipper.phone_number)
    recipient_phone_number = Phone(payload.recipient.phone_number)
    printing = PrinterType[options.printing or "regular"].value
    special_services = {
        Service[name].value: value
        for name, value in payload.options.items()
        if name in Service.__members__
    }

    request = create_envelope(
        header_content=RequestContext(
            Version="2.1",
            Language=settings.language,
            GroupID="",
            RequestReference="",
            UserToken=settings.user_token,
        ),
        body_content=RequestType(
            Shipment=Shipment(
                SenderInformation=SenderInformation(
                    Address=Address(
                        Name=payload.shipper.person_name,
                        Company=payload.shipper.company_name,
                        Department=None,
                        StreetNumber="",
                        StreetSuffix=None,
                        StreetName=concat_str(payload.shipper.address_line1,
                                              join=True),
                        StreetType=None,
                        StreetDirection=None,
                        Suite=None,
                        Floor=None,
                        StreetAddress2=concat_str(
                            payload.shipper.address_line2, join=True),
                        StreetAddress3=None,
                        City=payload.shipper.city,
                        Province=payload.shipper.state_code,
                        Country=payload.shipper.country_code,
                        PostalCode=payload.shipper.postal_code,
                        PhoneNumber=PhoneNumber(
                            CountryCode=shipper_phone_number.country_code,
                            AreaCode=shipper_phone_number.area_code,
                            Phone=shipper_phone_number.phone,
                            Extension=None),
                        FaxNumber=None,
                    ),
                    TaxNumber=payload.shipper.federal_tax_id
                    or payload.shipper.state_tax_id,
                ),
                ReceiverInformation=ReceiverInformation(
                    Address=Address(
                        Name=payload.recipient.person_name,
                        Company=payload.recipient.company_name,
                        Department=None,
                        StreetNumber="",
                        StreetSuffix=None,
                        StreetName=concat_str(payload.recipient.address_line1,
                                              join=True),
                        StreetType=None,
                        StreetDirection=None,
                        Suite=None,
                        Floor=None,
                        StreetAddress2=concat_str(
                            payload.recipient.address_line2, join=True),
                        StreetAddress3=None,
                        City=payload.recipient.city,
                        Province=payload.recipient.state_code,
                        Country=payload.recipient.country_code,
                        PostalCode=payload.recipient.postal_code,
                        PhoneNumber=PhoneNumber(
                            CountryCode=recipient_phone_number.country_code,
                            AreaCode=recipient_phone_number.area_code,
                            Phone=recipient_phone_number.phone,
                            Extension=None),
                        FaxNumber=None,
                    ),
                    TaxNumber=payload.recipient.federal_tax_id
                    or payload.recipient.state_tax_id,
                ),
                FromOnLabelIndicator=None,
                FromOnLabelInformation=None,
                ShipmentDate=datetime.today().strftime("%Y-%m-%d"),
                PackageInformation=PackageInformation(
                    ServiceID=service,
                    Description=package_description,
                    TotalWeight=TotalWeight(
                        Value=packages.weight.value,
                        WeightUnit=PurolatorWeightUnit.LB.value,
                    ) if packages.weight.value else None,
                    TotalPieces=1,
                    PiecesInformation=ArrayOfPiece(Piece=[
                        Piece(
                            Weight=PurolatorWeight(
                                Value=package.weight.value,
                                WeightUnit=PurolatorWeightUnit[
                                    package.weight_unit.value].value,
                            ) if package.weight.value else None,
                            Length=PurolatorDimension(
                                Value=package.length.value,
                                DimensionUnit=PurolatorDimensionUnit[
                                    package.dimension_unit.value].value,
                            ) if package.length.value else None,
                            Width=PurolatorDimension(
                                Value=package.width.value,
                                DimensionUnit=PurolatorDimensionUnit[
                                    package.dimension_unit.value].value,
                            ) if package.width.value else None,
                            Height=PurolatorDimension(
                                Value=package.height.value,
                                DimensionUnit=PurolatorDimensionUnit[
                                    package.dimension_unit.value].value,
                            ) if package.height.value else None,
                            Options=None,
                        ) for package in packages
                    ]),
                    DangerousGoodsDeclarationDocumentIndicator=None,
                    OptionsInformation=ArrayOfOptionIDValuePair(
                        OptionIDValuePair=[
                            OptionIDValuePair(ID=key, Value=value)
                            for key, value in special_services.items()
                        ]) if len(special_services) > 0 else None,
                ),
                InternationalInformation=InternationalInformation(
                    DocumentsOnlyIndicator=is_document,
                    ContentDetails=ArrayOfContentDetail(ContentDetail=[
                        ContentDetail(Description=c.description,
                                      HarmonizedCode=None,
                                      CountryOfManufacture=c.origin_country,
                                      ProductCode=c.sku,
                                      UnitValue=c.value_amount,
                                      Quantity=c.quantity,
                                      NAFTADocumentIndicator=None,
                                      FDADocumentIndicator=None,
                                      FCCDocumentIndicator=None,
                                      SenderIsProducerIndicator=None,
                                      TextileIndicator=None,
                                      TextileManufacturer=None)
                        for c in payload.customs.commodities
                    ]) if not is_document else None,
                    BuyerInformation=None,
                    PreferredCustomsBroker=None,
                    DutyInformation=DutyInformation(
                        BillDutiesToParty=DutyPaymentType[
                            payload.customs.duty.paid_by].value,
                        BusinessRelationship=BusinessRelationship.NOT_RELATED.
                        value,
                        Currency=payload.customs.duty.currency,
                    ) if payload.customs is not None else None,
                    ImportExportType=None,
                    CustomsInvoiceDocumentIndicator=None,
                ) if is_international else None,
                ReturnShipmentInformation=None,
                PaymentInformation=PaymentInformation(
                    PaymentType=PaymentType[payload.payment.paid_by].value,
                    RegisteredAccountNumber=payload.payment.account_number
                    or settings.account_number,
                    BillingAccountNumber=payload.payment.account_number
                    or settings.account_number,
                    CreditCardInformation=CreditCardInformation(
                        Type=payload.payment.credit_card.type,
                        Number=payload.payment.credit_card.number,
                        Name=payload.payment.credit_card.name,
                        ExpiryMonth=payload.payment.credit_card.expiry_month,
                        ExpiryYear=payload.payment.credit_card.expiry_year,
                        CVV=payload.payment.credit_card.security_code,
                        BillingPostalCode=payload.payment.credit_card.
                        postal_code,
                    ) if payload.payment.credit_card is not None else None,
                ) if payload.payment is not None else None,
                PickupInformation=PickupInformation(
                    PickupType=PickupType.DROP_OFF.value),
                NotificationInformation=NotificationInformation(
                    ConfirmationEmailAddress=options.notification.email
                    or payload.shipper.email,
                    AdvancedShippingNotificationMessage=None,
                ) if options.notification else None,
                TrackingReferenceInformation=TrackingReferenceInformation(
                    Reference1=payload.reference),
                OtherInformation=None,
                ProactiveNotification=None,
            ),
            PrinterType=PurolatorPrinterType(printing).value,
        ),
    )
    return Serializable(request, standard_request_serializer)
예제 #2
0
def process_shipment_request(
        payload: ShipmentRequest,
        settings: Settings) -> Serializable[ProcessShipmentRequest]:
    packages = Packages(payload.parcels, PackagePresets, required=["weight"])
    # Only the master package is selected here because even for MPS only one package is accepted for a master tracking.
    master_package = packages[0]
    package_type = (PackagingType[master_package.packaging_type
                                  or "your_packaging"].value if len(packages)
                    == 1 else PackagingType.your_packaging.value)

    service = ServiceType[payload.service].value
    options = Options(payload.options)
    special_services = [
        SpecialServiceType[name].value
        for name, value in payload.options.items()
        if name in SpecialServiceType.__members__
    ]
    payment_type = PaymentType[payload.payment.paid_by or "sender"].value

    request = ProcessShipmentRequest(
        WebAuthenticationDetail=settings.webAuthenticationDetail,
        ClientDetail=settings.clientDetail,
        TransactionDetail=TransactionDetail(
            CustomerTransactionId="IE_v25_Ship"),
        Version=VersionId(ServiceId="ship", Major=25, Intermediate=0, Minor=0),
        RequestedShipment=RequestedShipment(
            ShipTimestamp=datetime.now(),
            DropoffType="REGULAR_PICKUP",
            ServiceType=service,
            PackagingType=package_type,
            ManifestDetail=None,
            TotalWeight=FedexWeight(Units=WeightUnits.LB.value,
                                    Value=packages.weight.LB),
            TotalInsuredValue=options.insurance.amount
            if options.insurance else None,
            PreferredCurrency=options.currency,
            ShipmentAuthorizationDetail=None,
            Shipper=Party(
                AccountNumber=settings.account_number,
                Tins=[
                    TaxpayerIdentification(TinType=None, Number=tax)
                    for tax in [
                        payload.shipper.federal_tax_id,
                        payload.shipper.state_tax_id,
                    ]
                ] if any([
                    payload.shipper.federal_tax_id,
                    payload.shipper.state_tax_id
                ]) else None,
                Contact=Contact(
                    ContactId=None,
                    PersonName=payload.shipper.person_name,
                    Title=None,
                    CompanyName=payload.shipper.company_name,
                    PhoneNumber=payload.shipper.phone_number,
                    PhoneExtension=None,
                    TollFreePhoneNumber=None,
                    PagerNumber=None,
                    FaxNumber=None,
                    EMailAddress=payload.shipper.email,
                ) if any((
                    payload.shipper.company_name,
                    payload.shipper.phone_number,
                    payload.shipper.person_name,
                    payload.shipper.email,
                )) else None,
                Address=Address(
                    StreetLines=concat_str(payload.shipper.address_line1,
                                           payload.shipper.address_line2),
                    City=payload.shipper.city,
                    StateOrProvinceCode=payload.shipper.state_code,
                    PostalCode=payload.shipper.postal_code,
                    UrbanizationCode=None,
                    CountryCode=payload.shipper.country_code,
                    CountryName=None,
                    Residential=None,
                    GeographicCoordinates=None,
                ),
            ),
            Recipient=Party(
                AccountNumber=None,
                Tins=[
                    TaxpayerIdentification(TinType=None, Number=tax)
                    for tax in [
                        payload.recipient.federal_tax_id,
                        payload.recipient.state_tax_id,
                    ]
                ] if any([
                    payload.recipient.federal_tax_id,
                    payload.recipient.state_tax_id
                ]) else None,
                Contact=Contact(
                    ContactId=None,
                    PersonName=payload.recipient.person_name,
                    Title=None,
                    CompanyName=payload.recipient.company_name,
                    PhoneNumber=payload.recipient.phone_number,
                    PhoneExtension=None,
                    TollFreePhoneNumber=None,
                    PagerNumber=None,
                    FaxNumber=None,
                    EMailAddress=payload.recipient.email,
                ) if any((
                    payload.recipient.company_name,
                    payload.recipient.phone_number,
                    payload.recipient.person_name,
                    payload.recipient.email,
                )) else None,
                Address=Address(
                    StreetLines=concat_str(
                        payload.recipient.address_line1,
                        payload.recipient.address_line2,
                    ),
                    City=payload.recipient.city,
                    StateOrProvinceCode=payload.recipient.state_code,
                    PostalCode=payload.recipient.postal_code,
                    UrbanizationCode=None,
                    CountryCode=payload.recipient.country_code,
                    CountryName=None,
                    Residential=None,
                    GeographicCoordinates=None,
                ),
            ),
            RecipientLocationNumber=None,
            Origin=None,
            SoldTo=None,
            ShippingChargesPayment=Payment(
                PaymentType=payment_type,
                Payor=Payor(ResponsibleParty=Party(
                    AccountNumber=payload.payment.account_number
                    or settings.account_number,
                    Tins=None,
                    Contact=None,
                    Address=None,
                )),
            ),
            SpecialServicesRequested=ShipmentSpecialServicesRequested(
                SpecialServiceTypes=special_services,
                CodDetail=CodDetail(
                    CodCollectionAmount=Money(
                        Currency=options.currency or "USD",
                        Amount=options.cash_on_delivery.amount,
                    ),
                    AddTransportationChargesDetail=None,
                    CollectionType=CodCollectionType.CASH,
                    CodRecipient=None,
                    FinancialInstitutionContactAndAddress=None,
                    RemitToName=None,
                    ReferenceIndicator=None,
                    ReturnTrackingId=None,
                ) if options.cash_on_delivery else None,
                DeliveryOnInvoiceAcceptanceDetail=None,
                HoldAtLocationDetail=None,
                EventNotificationDetail=ShipmentEventNotificationDetail(
                    AggregationType=None,
                    PersonalMessage=None,
                    EventNotifications=[
                        ShipmentEventNotificationSpecification(
                            Role=None,
                            Events=NOTIFICATION_EVENTS,
                            NotificationDetail=NotificationDetail(
                                NotificationType="EMAIL",
                                EmailDetail=EMailDetail(
                                    EmailAddress=options.notification.email
                                    or payload.shipper.email,
                                    Name=payload.shipper.person_name,
                                ),
                                Localization=Localization(LanguageCode="EN",
                                                          LocaleCode=None),
                            ),
                            FormatSpecification="TEXT",
                        )
                    ],
                ) if options.notification else None,
                ReturnShipmentDetail=None,
                PendingShipmentDetail=None,
                InternationalControlledExportDetail=None,
                InternationalTrafficInArmsRegulationsDetail=None,
                ShipmentDryIceDetail=None,
                HomeDeliveryPremiumDetail=None,
                EtdDetail=None,
                CustomDeliveryWindowDetail=None,
            ) if options.has_content else None,
            ExpressFreightDetail=None,
            FreightShipmentDetail=None,
            DeliveryInstructions=None,
            VariableHandlingChargeDetail=None,
            CustomsClearanceDetail=None,
            PickupDetail=None,
            SmartPostDetail=None,
            BlockInsightVisibility=None,
            LabelSpecification=LabelSpecification(
                Dispositions=None,
                LabelFormatType=LabelFormatType.COMMON_2_D.value,
                ImageType=ShippingDocumentImageType.PDF.value,
                LabelStockType=LabelStockType.PAPER__7_X_4_75.value,
                LabelPrintingOrientation=LabelPrintingOrientationType.
                TOP_EDGE_OF_TEXT_FIRST.value,
                LabelOrder=None,
                PrintedLabelOrigin=None,
                CustomerSpecifiedDetail=None,
            ),
            ShippingDocumentSpecification=None,
            RateRequestTypes=None,
            EdtRequestType=None,
            MasterTrackingId=None,
            PackageCount=len(packages),
            ConfigurationData=None,
            RequestedPackageLineItems=[
                RequestedPackageLineItem(
                    SequenceNumber=1,
                    GroupNumber=None,
                    GroupPackageCount=None,
                    VariableHandlingChargeDetail=None,
                    InsuredValue=None,
                    Weight=FedexWeight(
                        Units=master_package.weight_unit.value,
                        Value=master_package.weight.value,
                    ) if master_package.weight.value else None,
                    Dimensions=FedexDimensions(
                        Length=master_package.length.value,
                        Width=master_package.width.value,
                        Height=master_package.height.value,
                        Units=master_package.dimension_unit.value,
                    ) if any([
                        master_package.length, master_package.width,
                        master_package.height
                    ]) else None,
                    PhysicalPackaging=None,
                    ItemDescription=master_package.parcel.description,
                    ItemDescriptionForClearance=None,
                    CustomerReferences=None,
                    SpecialServicesRequested=None,
                    ContentRecords=None,
                )
            ]),
    )
    return Serializable(request, _request_serializer)
예제 #3
0
def shipment_request(
    payload: ShipmentRequest, settings: Settings
) -> Serializable[DHLShipmentRequest]:
    packages = Packages(payload.parcels, PackagePresets, required=["weight"])
    is_international = payload.shipper.country_code == payload.recipient.country_code
    options = Options(payload.options)
    product = ProductCode[payload.service].value
    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
    )
    special_services = [
        SpecialServiceCode[s].value
        for s in payload.options.keys()
        if s in SpecialServiceCode.__members__
    ]
    if is_international and payload.doc_images is not None:
        special_services.append(SpecialServiceCode.dhl_paperless_trade.value)
    has_payment_config = payload.payment is not None
    has_customs_config = payload.customs is not None

    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=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=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=time.strftime("%Y-%m-%d"),
            PackageType=package_type,
            IsDutiable="Y" if payload.customs is not None else "N",
            InsuredAmount=options.insurance.amount if options.insurance else None,
            ShipmentCharges=options.cash_on_delivery.amount
            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.terms_of_trade,
        )
        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=service) for service in special_services
        ],
        Notification=Notification(
            EmailAddress=options.notification.email or payload.shipper.email,
        )
        if options.notification
        else None,
        LabelImageFormat="PDF",
        DocImages=DocImages(
            DocImage=[
                DocImage(
                    Type=doc.type,
                    ImageFormat=doc.format,
                    Image=b64decode(doc.image + "=" * (-len(doc.image) % 4)),
                )
                for doc in payload.doc_images
            ]
        )
        if len(payload.doc_images) > 0
        else None,
        RequestArchiveDoc=None,
        NumberOfArchiveDoc=None,
        Label=None,
        ODDLinkReq=None,
        DGs=None,
    )
    return Serializable(request, _request_serializer)
예제 #4
0
def freight_ship_request(
    payload: ShipmentRequest, settings: Settings
) -> Serializable[FreightShipRequest]:
    dimension_unit = DimensionUnit[payload.parcel.dimension_unit or "IN"]
    weight_unit = WeightUnit[payload.parcel.weight_unit or "LB"]
    options = Options(payload.options)
    service = ShippingServiceCode[payload.service].value
    freight_class = FreightClass[
        payload.options.get("ups_freight_class", "ups_freight_class_50")
    ].value

    request = FreightShipRequest(
        Request=common.RequestType(
            RequestOption="1",
            SubVersion=None,
            TransactionReference=common.TransactionReferenceType(
                CustomerContext=payload.reference, TransactionIdentifier=None
            ),
        ),
        Shipment=ShipmentType(
            ShipFrom=ShipFromType(
                Name=payload.shipper.company_name,
                TaxIdentificationNumber=payload.shipper.federal_tax_id,
                TaxIDType=None,
                TariffPoint=None,
                Address=FreightShipAddressType(
                    AddressLine=concat_str(
                        payload.shipper.address_line1, payload.shipper.address_line2
                    ),
                    City=payload.shipper.city,
                    StateProvinceCode=payload.shipper.state_code,
                    Town=None,
                    PostalCode=payload.shipper.postal_code,
                    CountryCode=payload.shipper.country_code,
                ),
                AttentionName=payload.shipper.person_name,
                Phone=FreightShipPhoneType(
                    Number=payload.shipper.phone_number, Extension=None
                )
                if payload.shipper.phone_number is not None
                else None,
                FaxNumber=None,
                EMailAddress=payload.shipper.email,
            ),
            ShipperNumber=settings.account_number,
            ShipTo=ShipToType(
                Name=payload.recipient.company_name,
                TaxIdentificationNumber=payload.recipient.federal_tax_id,
                Address=FreightShipAddressType(
                    AddressLine=concat_str(
                        payload.recipient.address_line1,
                        payload.recipient.address_line2,
                    ),
                    City=payload.recipient.city,
                    StateProvinceCode=payload.recipient.state_code,
                    Town=None,
                    PostalCode=payload.recipient.postal_code,
                    CountryCode=payload.recipient.country_code,
                ),
                TariffPoint=None,
                AttentionName=payload.recipient.person_name,
                Phone=PhoneType(Number=payload.recipient.phone_number, Extension=None)
                if payload.recipient.phone_number is not None
                else None,
                FaxNumber=None,
                EMailAddress=payload.recipient.email,
            ),
            PaymentInformation=None,
            ManufactureInformation=None,
            Service=ShipCodeDescriptionType(Code=service)
            if service is not None
            else None,
            HandlingUnitOne=None,
            HandlingUnitTwo=None,
            ExistingShipmentID=None,
            HandlingInstructions=None,
            DeliveryInstructions=None,
            PickupInstructions=None,
            SpecialInstructions=None,
            ShipmentTotalWeight=None,
            Commodity=[
                CommodityType(
                    CommodityID=payload.parcel.id,
                    Description=payload.parcel.description,
                    Weight=WeightType(
                        UnitOfMeasurement=FreightShipUnitOfMeasurementType(
                            Code=UPSWeightUnit[weight_unit.name].value
                        ),
                        Value=Weight(payload.parcel.weight, weight_unit).value,
                    ),
                    Dimensions=DimensionsType(
                        UnitOfMeasurement=FreightShipUnitOfMeasurementType(
                            Code=dimension_unit.value
                        ),
                        Width=Dimension(payload.parcel.width, dimension_unit).value,
                        Height=Dimension(payload.parcel.height, dimension_unit).value,
                        Length=Dimension(payload.parcel.length, dimension_unit).value,
                    )
                    if any(
                        [
                            payload.parcel.width,
                            payload.parcel.height,
                            payload.parcel.length,
                        ]
                    )
                    else None,
                    NumberOfPieces=None,
                    PackagingType=None,
                    DangerousGoodsIndicator=None,
                    CommodityValue=None,
                    FreightClass=freight_class,
                    NMFCCommodityCode=None,
                    NMFCCommodity=None,
                )
            ],
            Reference=None,
            ShipmentServiceOptions=ShipmentServiceOptionsType(
                EMailInformation=[
                    EMailNotificationType(
                        EMailAddress=options.notification.email
                        or payload.shipper.email,
                        EventType=NOTIFICATION_EVENT_TYPES,
                    )
                ]
                if options.notification
                else None,
                PickupOptions=None,
                DeliveryOptions=None,
                OverSeasLeg=None,
                COD=CODType(
                    CODValue=CODValueType(
                        CurrencyCode=options.currency or "USD",
                        MonetaryValue=options.cash_on_delivery.amount,
                    ),
                    CODPaymentMethod=None,
                    CODBillingOption=None,
                    RemitTo=None,
                )
                if options.cash_on_delivery
                else 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,
            )
            if options.has_content
            else None,
            PickupRequest=None,
            Documents=None,
            ITNNumber=None,
            TaxID=None,
            MovementReferenceNumber=None,
            EICNumberAndStatement=None,
            TimeInTransitIndicator=None,
            HandlingUnits=None,
            DensityEligibleIndicator=None,
        ),
    )
    return Serializable(
        create_envelope(header_content=settings.Security, body_content=request),
        _request_serializer,
    )
예제 #5
0
def shipment_request(
    payload: ShipmentRequest, settings: Settings
) -> Serializable[UPSShipmentRequest]:
    packages = Packages(payload.parcels, PackagePresets)
    is_document = all([parcel.is_document for parcel in payload.parcels])
    package_description = (packages[0].parcel.description if len(packages) == 1 else None)
    options = Options(payload.options)
    service = ShippingServiceCode[payload.service].value

    if (("freight" in service) or ("ground" in service)) and (
        packages.weight.value is None
    ):
        raise FieldError({"parcel.weight": FieldErrorCode.required})

    charges: Dict[str, Payment] = {
        "01": payload.payment,
        "02": payload.customs.duty if payload.customs is not None else None,
    }
    mps_packaging = ShippingPackagingType.your_packaging.value if len(packages) > 1 else None

    request = UPSShipmentRequest(
        Request=common.RequestType(
            RequestOption=["validate"],
            SubVersion=None,
            TransactionReference=common.TransactionReferenceType(
                CustomerContext=payload.reference, TransactionIdentifier=None
            ),
        ),
        Shipment=ShipmentType(
            Description=package_description,
            DocumentsOnlyIndicator="" if is_document else None,
            Shipper=ShipperType(
                Name=payload.shipper.company_name,
                AttentionName=payload.shipper.person_name,
                CompanyDisplayableName=None,
                TaxIdentificationNumber=payload.shipper.federal_tax_id,
                TaxIDType=None,
                Phone=(
                    ShipPhoneType(Number=payload.shipper.phone_number, Extension=None)
                    if payload.shipper.phone_number is not None
                    else None
                ),
                ShipperNumber=settings.account_number,
                FaxNumber=None,
                EMailAddress=payload.shipper.email,
                Address=ShipAddressType(
                    AddressLine=concat_str(
                        payload.shipper.address_line1, payload.shipper.address_line2
                    ),
                    City=payload.shipper.city,
                    StateProvinceCode=payload.shipper.state_code,
                    PostalCode=payload.shipper.postal_code,
                    CountryCode=payload.shipper.country_code,
                ),
            ),
            ShipTo=ShipToType(
                Name=payload.recipient.company_name,
                AttentionName=payload.recipient.person_name,
                CompanyDisplayableName=None,
                TaxIdentificationNumber=payload.recipient.federal_tax_id,
                TaxIDType=None,
                Phone=(
                    ShipPhoneType(Number=payload.recipient.phone_number, Extension=None)
                    if payload.recipient.phone_number is not None
                    else None
                ),
                FaxNumber=None,
                EMailAddress=payload.recipient.email,
                Address=ShipAddressType(
                    AddressLine=concat_str(
                        payload.recipient.address_line1,
                        payload.recipient.address_line2,
                    ),
                    City=payload.recipient.city,
                    StateProvinceCode=payload.recipient.state_code,
                    PostalCode=payload.recipient.postal_code,
                    CountryCode=payload.recipient.country_code,
                ),
            ),
            PaymentInformation=PaymentInfoType(
                ShipmentCharge=[
                    ShipmentChargeType(
                        Type=charge_type,
                        BillShipper=BillShipperType(
                            AccountNumber=settings.account_number,
                            CreditCard=CreditCardType(
                                Type=payment.credit_card.type,
                                Number=payment.credit_card.number,
                                ExpirationDate=(
                                    f"{payment.credit_card.expiry_year}{payment.credit_card.expiry_month}"
                                ),
                                SecurityCode=payment.credit_card.security_code,
                                Address=CreditCardAddressType(
                                    AddressLine=concat_str(
                                        payload.shipper.address_line1,
                                        payload.shipper.address_line2,
                                    ),
                                    City=payload.shipper.city,
                                    StateProvinceCode=payload.shipper.state_code,
                                    PostalCode=payload.payment.credit_card.postal_code
                                    or payload.shipper.postal_code,
                                    CountryCode=payload.shipper.country_code,
                                ),
                            )
                            if payment.credit_card is not None
                            else None,
                            AlternatePaymentMethod=None,
                        )
                        if payment.paid_by == PaymentType.sender.name
                        else None,
                        BillReceiver=BillReceiverType(
                            AccountNumber=payment.account_number,
                            Address=BillReceiverAddressType(
                                PostalCode=payload.recipient.postal_code
                            ),
                        )
                        if payment.paid_by == PaymentType.recipient.name
                        else None,
                        BillThirdParty=BillThirdPartyChargeType(
                            AccountNumber=payment.account_number,
                        )
                        if payment.paid_by == PaymentType.third_party.name
                        else None,
                        ConsigneeBilledIndicator=None,
                    )
                    for charge_type, payment in charges.items()
                    if payment is not None
                ],
                SplitDutyVATIndicator=None,
            )
            if any(charges.values())
            else None,
            Service=(ServiceType(Code=service) if service is not None else None),
            ShipmentServiceOptions=ShipmentServiceOptionsType(
                COD=CODType(
                    CODFundsCode=None,
                    CODAmount=CurrencyMonetaryType(
                        CurrencyCode=options.currency or "USD",
                        MonetaryValue=options.cash_on_delivery.amount,
                    ),
                )
                if options.cash_on_delivery
                else None,
                Notification=[
                    NotificationType(
                        NotificationCode=event,
                        EMail=EmailDetailsType(
                            EMailAddress=[
                                options.notification.email or payload.shipper.email
                            ],
                        ),
                        VoiceMessage=None,
                        TextMessage=None,
                        Locale=None,
                    )
                    for event in [8]
                ]
                if options.notification
                else None,
            )
            if any([options.cash_on_delivery, options.notification])
            else None,
            Package=[
                PackageType(
                    Description=package.parcel.description,
                    Packaging=PackagingType(
                        Code=mps_packaging or ShippingPackagingType[package.packaging_type or "your_packaging"].value
                    ),
                    Dimensions=DimensionsType(
                        UnitOfMeasurement=ShipUnitOfMeasurementType(
                            Code=package.dimension_unit.value,
                        ),
                        Length=package.length.value,
                        Width=package.width.value,
                        Height=package.height.value,
                    ),
                    PackageWeight=PackageWeightType(
                        UnitOfMeasurement=ShipUnitOfMeasurementType(
                            Code=UPSWeightUnit[package.weight_unit.name].value,
                        ),
                        Weight=package.weight.value,
                    ),
                )
                for package in packages
            ],
        ),
        LabelSpecification=LabelSpecificationType(
            LabelImageFormat=LabelImageFormatType(
                Code='GIF',
                Description=None
            ),
            HTTPUserAgent=None,
            LabelStockSize=None,
            Instruction=None,
            CharacterSet=None
        ),
        ReceiptSpecification=None,
    )
    return Serializable(
        create_envelope(header_content=settings.Security, body_content=request),
        _request_serializer,
    )
예제 #6
0
def process_shipment_request(
    payload: ShipmentRequest, settings: Settings
) -> Serializable[ProcessShipmentRequest]:
    parcel_preset = (
        PackagePresets[payload.parcel.package_preset].value
        if payload.parcel.package_preset
        else None
    )
    package = Package(payload.parcel, parcel_preset)

    if package.weight.value is None:
        raise RequiredFieldError("parcel.weight")

    service = ServiceType[payload.service].value
    options = Options(payload.options)
    special_services = [
        SpecialServiceType[name].value
        for name, value in payload.options.items()
        if name in SpecialServiceType.__members__
    ]

    request = ProcessShipmentRequest(
        WebAuthenticationDetail=settings.webAuthenticationDetail,
        ClientDetail=settings.clientDetail,
        TransactionDetail=TransactionDetail(CustomerTransactionId="IE_v18_Ship"),
        Version=VersionId(ServiceId="ship", Major=25, Intermediate=0, Minor=0),
        RequestedShipment=RequestedShipment(
            ShipTimestamp=datetime.now(),
            DropoffType="REGULAR_PICKUP",
            ServiceType=service,
            PackagingType=PackagingType[
                payload.parcel.packaging_type or "small_box"
            ].value,
            ManifestDetail=None,
            TotalWeight=FedexWeight(
                Units=package.weight_unit.value, Value=package.weight.value,
            ),
            TotalInsuredValue=options.insurance.amount if options.insurance else None,
            PreferredCurrency=options.currency,
            ShipmentAuthorizationDetail=None,
            Shipper=Party(
                AccountNumber=settings.account_number,
                Tins=[
                    TaxpayerIdentification(TinType=None, Number=tax)
                    for tax in [
                        payload.shipper.federal_tax_id,
                        payload.shipper.state_tax_id,
                    ]
                ]
                if any([payload.shipper.federal_tax_id, payload.shipper.state_tax_id])
                else None,
                Contact=Contact(
                    ContactId=None,
                    PersonName=payload.shipper.person_name,
                    Title=None,
                    CompanyName=payload.shipper.company_name,
                    PhoneNumber=payload.shipper.phone_number,
                    PhoneExtension=None,
                    TollFreePhoneNumber=None,
                    PagerNumber=None,
                    FaxNumber=None,
                    EMailAddress=payload.shipper.email,
                )
                if any(
                    (
                        payload.shipper.company_name,
                        payload.shipper.phone_number,
                        payload.shipper.person_name,
                        payload.shipper.email,
                    )
                )
                else None,
                Address=Address(
                    StreetLines=concat_str(
                        payload.shipper.address_line1, payload.shipper.address_line2
                    ),
                    City=payload.shipper.city,
                    StateOrProvinceCode=payload.shipper.state_code,
                    PostalCode=payload.shipper.postal_code,
                    UrbanizationCode=None,
                    CountryCode=payload.shipper.country_code,
                    CountryName=None,
                    Residential=None,
                    GeographicCoordinates=None,
                ),
            ),
            Recipient=Party(
                AccountNumber=None,
                Tins=[
                    TaxpayerIdentification(TinType=None, Number=tax)
                    for tax in [
                        payload.recipient.federal_tax_id,
                        payload.recipient.state_tax_id,
                    ]
                ]
                if any(
                    [payload.recipient.federal_tax_id, payload.recipient.state_tax_id]
                )
                else None,
                Contact=Contact(
                    ContactId=None,
                    PersonName=payload.recipient.person_name,
                    Title=None,
                    CompanyName=payload.recipient.company_name,
                    PhoneNumber=payload.recipient.phone_number,
                    PhoneExtension=None,
                    TollFreePhoneNumber=None,
                    PagerNumber=None,
                    FaxNumber=None,
                    EMailAddress=payload.recipient.email,
                )
                if any(
                    (
                        payload.recipient.company_name,
                        payload.recipient.phone_number,
                        payload.recipient.person_name,
                        payload.recipient.email,
                    )
                )
                else None,
                Address=Address(
                    StreetLines=concat_str(
                        payload.recipient.address_line1,
                        payload.recipient.address_line2,
                    ),
                    City=payload.recipient.city,
                    StateOrProvinceCode=payload.recipient.state_code,
                    PostalCode=payload.recipient.postal_code,
                    UrbanizationCode=None,
                    CountryCode=payload.recipient.country_code,
                    CountryName=None,
                    Residential=None,
                    GeographicCoordinates=None,
                ),
            ),
            RecipientLocationNumber=None,
            Origin=None,
            SoldTo=None,
            ShippingChargesPayment=Payment(
                PaymentType=None,
                Payor=Payor(
                    ResponsibleParty=Party(
                        AccountNumber=payload.payment.account_number,
                        Tins=None,
                        Contact=None,
                        Address=None,
                    )
                ),
            ),
            SpecialServicesRequested=ShipmentSpecialServicesRequested(
                SpecialServiceTypes=special_services,
                CodDetail=CodDetail(
                    CodCollectionAmount=Money(
                        Currency=options.currency or "USD",
                        Amount=options.cash_on_delivery.amount,
                    ),
                    AddTransportationChargesDetail=None,
                    CollectionType=CodCollectionType.CASH,
                    CodRecipient=None,
                    FinancialInstitutionContactAndAddress=None,
                    RemitToName=None,
                    ReferenceIndicator=None,
                    ReturnTrackingId=None,
                )
                if options.cash_on_delivery
                else None,
                DeliveryOnInvoiceAcceptanceDetail=None,
                HoldAtLocationDetail=None,
                EventNotificationDetail=ShipmentEventNotificationDetail(
                    AggregationType=None,
                    PersonalMessage=None,
                    EventNotifications=[
                        ShipmentEventNotificationSpecification(
                            Role=None,
                            Events=NOTIFICATION_EVENTS,
                            NotificationDetail=NotificationDetail(
                                NotificationType="EMAIL",
                                EmailDetail=EMailDetail(
                                    EmailAddress=options.notification.email
                                    or payload.shipper.email,
                                    Name=payload.shipper.person_name,
                                ),
                                Localization=Localization(
                                    LanguageCode="EN", LocaleCode=None
                                ),
                            ),
                            FormatSpecification="TEXT",
                        )
                    ],
                )
                if options.notification
                else None,
                ReturnShipmentDetail=None,
                PendingShipmentDetail=None,
                InternationalControlledExportDetail=None,
                InternationalTrafficInArmsRegulationsDetail=None,
                ShipmentDryIceDetail=None,
                HomeDeliveryPremiumDetail=None,
                EtdDetail=None,
                CustomDeliveryWindowDetail=None,
            )
            if options.has_content
            else None,
            ExpressFreightDetail=None,
            FreightShipmentDetail=None,
            DeliveryInstructions=None,
            VariableHandlingChargeDetail=None,
            CustomsClearanceDetail=None,
            PickupDetail=None,
            SmartPostDetail=None,
            BlockInsightVisibility=None,
            LabelSpecification=None,
            ShippingDocumentSpecification=None,
            RateRequestTypes=(
                ["LIST"] + ([] if options.currency is None else ["PREFERRED"])
            ),
            EdtRequestType=None,
            MasterTrackingId=None,
            PackageCount=None,
            ConfigurationData=None,
            RequestedPackageLineItems=[
                RequestedPackageLineItem(
                    SequenceNumber=index,
                    GroupNumber=None,
                    GroupPackageCount=index,
                    VariableHandlingChargeDetail=None,
                    InsuredValue=None,
                    Weight=FedexWeight(
                        Units=package.weight_unit.value,
                        Value=Weight(pkg.weight, package.weight_unit).value,
                    )
                    if pkg.weight
                    else None,
                    Dimensions=FedexDimensions(
                        Length=Dimension(pkg.length, package.dimension_unit).value,
                        Width=Dimension(pkg.width, package.dimension_unit).value,
                        Height=Dimension(pkg.height, package.dimension_unit).value,
                        Units=package.dimension_unit.value,
                    )
                    if any([pkg.length, pkg.width, pkg.height])
                    else None,
                    PhysicalPackaging=None,
                    ItemDescription=pkg.description,
                    ItemDescriptionForClearance=None,
                    CustomerReferences=None,
                    SpecialServicesRequested=None,
                    ContentRecords=None,
                )
                for index, pkg in enumerate(payload.customs.commodities, 1)
            ]
            if payload.customs is not None
            else None,
        ),
    )
    return Serializable(request, _request_serializer)