Пример #1
0
def _extract_details(service_node: Element, settings: Settings) -> RateDetails:
    service: ServiceType = ServiceType()
    service.build(service_node)
    currency = "USD"
    special_services: List[ExtraServiceType] = [
        XP.build(ExtraServiceType, svc)
        for svc in service_node.xpath(".//*[local-name() = $name]",
                                      name="ExtraService")
    ]
    delivery_date = DF.date(service.GuaranteeAvailability, "%m/%d/%Y")
    transit = ((delivery_date -
                datetime.now()).days if delivery_date is not None else None)
    rate_service: Service = Service.find(service.SvcDescription)

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        service=rate_service.value,
        base_charge=NF.decimal(service.Postage),
        total_charge=NF.decimal(service.Postage),
        currency=currency,
        transit_days=transit,
        extra_charges=[
            ChargeDetails(
                name=ExtraService(special.ServiceID).name,
                amount=NF.decimal(special.Price),
                currency=currency,
            ) for special in special_services
        ],
    )
Пример #2
0
def _extract_rate_details(node: Element, settings: Settings) -> RateDetails:
    shipment = XP.build(Shipment, node)
    surcharges = [
        ChargeDetails(name=charge.value,
                      amount=NF.decimal(getattr(shipment, charge.name)),
                      currency='CAD') for charge in list(Charges)
        if NF.decimal(getattr(shipment, charge.name)) > 0.0
    ]
    taxes = [
        ChargeDetails(name=f'{getattr(shipment, code)} Tax Charge',
                      amount=NF.decimal(charge),
                      currency='CAD')
        for code, charge in [(
            'tax_code_1',
            shipment.tax_charge_1), ('tax_code_2', shipment.tax_charge_2)]
        if NF.decimal(charge) > 0.0
    ]

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        currency="CAD",
        transit_days=shipment.transit_time,
        service=Service(shipment.service_type).name,
        base_charge=NF.decimal(shipment.freight_charge),
        total_charge=sum([c.amount for c in (surcharges + taxes)], 0.0),
        duties_and_taxes=sum([t.amount for t in taxes], 0.0),
        extra_charges=(surcharges + taxes),
    )
Пример #3
0
def _extract_details(response: Element, settings: Settings) -> ShipmentDetails:
    shipment = XP.build(eVSResponse, response)
    charges: List[ExtraServiceType] = shipment.ExtraServices.ExtraService
    total_charge = sum([
        NF.decimal(shipment.Postage), *[NF.decimal(c.Price) for c in charges]
    ], 0.0)

    return ShipmentDetails(carrier_name=settings.carrier_name,
                           carrier_id=settings.carrier_id,
                           label=shipment.LabelImage,
                           tracking_number=shipment.BarcodeNumber,
                           shipment_identifier=shipment.BarcodeNumber,
                           selected_rate=RateDetails(
                               carrier_name=settings.carrier_name,
                               carrier_id=settings.carrier_id,
                               service=ServiceClassID(shipment).name,
                               currency=Currency.USD.value,
                               base_charge=NF.decimal(shipment.Postage),
                               total_charge=total_charge,
                               extra_charges=[
                                   ChargeDetails(name=charge.ServiceName,
                                                 amount=NF.decimal(
                                                     charge.Price),
                                                 currency=Currency.USD.value)
                                   for charge in charges
                               ]))
Пример #4
0
def _extract_rate_details(response: Tuple[Element, ResponseGetCharges],
                          settings: Settings) -> RateDetails:
    product, rate = response
    charges = [
        *[(charge.SurChargeName, charge.SurChargeAmount)
          for charge in cast(List[SurCharge], rate.SurCharges)],
        *[(name, value)
          for name, value in [("Fuel Charges", rate.FuelCharges),
                              ("Insurance Charges", rate.InsuranceCharges)]
          if (value or 0) > 0]
    ]

    return RateDetails(carrier_name=settings.carrier_name,
                       carrier_id=settings.carrier_id,
                       service=Service(product.text),
                       currency=Currency.CAD.name,
                       base_charge=NF.decimal(rate.BaseCharges),
                       total_charge=NF.decimal(rate.BaseCharges),
                       extra_charges=[
                           ChargeDetails(
                               name=name,
                               amount=amount,
                               currency=Currency.CAD.name,
                           ) for name, amount in charges
                       ])
Пример #5
0
def _extract_details(service_node: Element, settings: Settings) -> RateDetails:
    service: ServiceType = XP.build(ServiceType, service_node)
    charges: List[ExtraServiceType] = service.ExtraServices.ExtraService
    delivery_date = DF.date(service.GuaranteeAvailability, "%m/%d/%Y")
    transit = (
        (delivery_date - datetime.now()).days
        if delivery_date is not None else None
    )

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,

        service=ServiceClassID(str(service.ID)),
        base_charge=NF.decimal(service.Postage),
        total_charge=NF.decimal(service.Postage),
        currency=Currency.USD.name,
        transit_days=transit,
        extra_charges=[
            ChargeDetails(
                name=charge.ServiceID,
                amount=NF.decimal(charge.Price),
                currency=Currency.USD.name,
            )
            for charge in charges
        ],
    )
Пример #6
0
def _extract_pickup_details(response: Element,
                            settings: Settings) -> PickupDetails:
    header = next((XP.build(PickupRequestHeaderType, elt)
                   for elt in response.xpath(".//*[local-name() = $name]",
                                             name="pickup-request-header")))
    price = next((XP.build(PickupRequestPriceType, elt)
                  for elt in response.xpath(".//*[local-name() = $name]",
                                            name="pickup-request-price")),
                 None)

    price_amount = sum(
        [
            NF.decimal(price.hst_amount or 0.0),
            NF.decimal(price.gst_amount or 0.0),
            NF.decimal(price.due_amount or 0.0),
        ],
        0.0,
    ) if price is not None else None

    return PickupDetails(
        carrier_id=settings.carrier_id,
        carrier_name=settings.carrier_name,
        confirmation_number=header.request_id,
        pickup_date=DF.fdate(header.next_pickup_date),
        pickup_charge=ChargeDetails(name="Pickup fees",
                                    amount=NF.decimal(price_amount),
                                    currency="CAD")
        if price is not None else None,
    )
Пример #7
0
def _extract_details(postage_node: Element, settings: Settings) -> RateDetails:
    postage: PostageType = XP.to_object(PostageType, postage_node)

    service = ServiceClassID.map(str(postage.CLASSID))
    charges: List[SpecialServiceType] = getattr(postage.SpecialServices,
                                                'SpecialService', [])
    rate = NF.decimal(XP.find('Rate', postage_node, first=True).text)
    estimated_date = DF.date(
        getattr(XP.find('CommitmentDate', postage_node, first=True), 'text',
                None))
    transit = ((estimated_date.date() - datetime.now().date()).days
               if estimated_date is not None else None)

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        service=service.name_or_key,
        base_charge=rate,
        total_charge=rate,
        currency=Currency.USD.name,
        transit_days=transit,
        extra_charges=[
            ChargeDetails(
                name=charge.ServiceName,
                amount=NF.decimal(charge.Price),
                currency=Currency.USD.name,
            ) for charge in charges
        ],
        meta=dict(service_name=(service.name or postage.MailService)))
Пример #8
0
def _extract_rate(node: Element, settings: Settings) -> RateDetails:
    quote = XP.build(QuoteType, node)
    rate_provider, service, service_name = Service.info(
        quote.serviceId, quote.carrierId, quote.serviceName, quote.carrierName
    )
    surcharges = [
        ChargeDetails(
            name=charge.name, amount=NF.decimal(charge.amount), currency=quote.currency
        )
        for charge in cast(List[SurchargeType], quote.Surcharge)
    ]
    fuel_surcharge = (
        ChargeDetails(
            name="Fuel surcharge",
            amount=NF.decimal(quote.fuelSurcharge),
            currency=quote.currency,
        )
        if quote.fuelSurcharge is not None else None
    )

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        currency=quote.currency,
        service=service,
        base_charge=NF.decimal(quote.baseCharge),
        total_charge=NF.decimal(quote.totalCharge),
        transit_days=quote.transitDays,
        extra_charges=([fuel_surcharge] + surcharges),
        meta=dict(
            rate_provider=rate_provider,
            service_name=service_name
        )
    )
Пример #9
0
def _extract_details(postage_node: Element, settings: Settings) -> RateDetails:
    postage: PostageType = PostageType()
    postage.build(postage_node)
    currency = Currency.USD.name
    services: List[SpecialServiceType] = [
        XP.build(SpecialServiceType, svc)
        for svc in postage_node.xpath(".//*[local-name() = $name]",
                                      name="SpecialService")
    ]
    estimated_date = DF.date(postage.CommitmentDate)
    transit = ((estimated_date -
                datetime.now()).days if estimated_date is not None else None)
    postage_rate = postage_node.find("Rate").text

    def get(key: str) -> Any:
        return reduce(lambda r, v: v.text, postage_node.findall(key), None)

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        service=Service.find(get("MailService")).name,
        total_charge=NF.decimal(postage_rate),
        currency=currency,
        transit_days=transit,
        extra_charges=[
            ChargeDetails(
                name=SpecialService(str(svc.ServiceID)).name,
                amount=NF.decimal(svc.Price),
                currency=currency,
            ) for svc in services
        ],
    )
Пример #10
0
def _extract_details(postage_node: Element, settings: Settings) -> RateDetails:
    postage: ServiceType = XP.to_object(ServiceType, postage_node)

    service = ServiceClassID.map(str(postage.ID))
    charges: List[ExtraServiceType] = postage.ExtraServices.ExtraService
    delivery_date = DF.date(postage.GuaranteeAvailability, "%m/%d/%Y")
    transit = ((delivery_date.date() - datetime.now().date()).days if delivery_date is not None else None)

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,

        service=service.name_or_key,
        base_charge=NF.decimal(postage.Postage),
        total_charge=NF.decimal(postage.Postage),
        currency=Currency.USD.name,
        transit_days=transit,
        extra_charges=[
            ChargeDetails(
                name=charge.ServiceName,
                amount=NF.decimal(charge.Price),
                currency=Currency.USD.name,
            )
            for charge in charges
        ],
        meta=dict(service_name=service.name or postage.SvcDescription)
    )
Пример #11
0
def _extract_details(postage_node: Element, settings: Settings) -> RateDetails:
    postage: PostageType = XP.build(PostageType, postage_node)
    charges: List[SpecialServiceType] = postage.SpecialServices.SpecialService
    estimated_date = DF.date(postage.CommitmentDate)
    transit = (
        (estimated_date - datetime.now()).days
        if estimated_date is not None else None
    )

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        service=ServiceClassID(str(postage.CLASSID)),
        total_charge=NF.decimal(postage.Rate),
        currency=Currency.USD.name,
        transit_days=transit,
        extra_charges=[
            ChargeDetails(
                name=charge.ServiceName,
                amount=NF.decimal(charge.Price),
                currency=Currency.USD.name,
            )
            for charge in charges
        ]
    )
Пример #12
0
    def extract(rates: List[RateDetails],
                detail_node: Element) -> List[RateDetails]:
        rate = XP.build(RatedShipmentType, detail_node)

        if rate.NegotiatedRateCharges is not None:
            total_charges = (rate.NegotiatedRateCharges.TotalChargesWithTaxes
                             or rate.NegotiatedRateCharges.TotalCharge)
            taxes = rate.NegotiatedRateCharges.TaxCharges
            itemized_charges = rate.NegotiatedRateCharges.ItemizedCharges + taxes
        else:
            total_charges = rate.TotalChargesWithTaxes or rate.TotalCharges
            taxes = rate.TaxCharges
            itemized_charges = rate.ItemizedCharges + taxes

        extra_charges = itemized_charges + [rate.ServiceOptionsCharges]
        estimated_arrival = next(
            (XP.build(EstimatedArrivalType, n)
             for n in detail_node.xpath(".//*[local-name() = $name]",
                                        name="EstimatedArrival")),
            EstimatedArrivalType(),
        )
        transit_days = (rate.GuaranteedDelivery.BusinessDaysInTransit
                        if rate.GuaranteedDelivery is not None else
                        estimated_arrival.BusinessDaysInTransit)
        currency_ = next(
            str(c.text)
            for c in detail_node.xpath(".//*[local-name() = $name]",
                                       name="CurrencyCode"))
        service = ShippingServiceCode(rate.Service.Code).name
        return rates + [
            RateDetails(
                carrier_name=settings.carrier_name,
                carrier_id=settings.carrier_id,
                currency=currency_,
                service=service,
                base_charge=NF.decimal(
                    rate.TransportationCharges.MonetaryValue),
                total_charge=NF.decimal(total_charges.MonetaryValue),
                duties_and_taxes=reduce(
                    lambda total, charge: total + NF.decimal(charge.
                                                             MonetaryValue),
                    taxes or [],
                    0.0,
                ),
                extra_charges=reduce(
                    lambda total, charge: (total + [
                        ChargeDetails(
                            name=charge.Code,
                            amount=NF.decimal(charge.MonetaryValue),
                            currency=charge.CurrencyCode,
                        )
                    ]),
                    [charge for charge in extra_charges if charge is not None],
                    [],
                ),
                transit_days=NF.integer(transit_days),
            )
        ]
Пример #13
0
    def extract(rates: List[RateDetails],
                detail_node: Element) -> List[RateDetails]:
        rate = XP.to_object(RatedShipmentType, detail_node)

        if rate.NegotiatedRateCharges is not None:
            total_charges = (rate.NegotiatedRateCharges.TotalChargesWithTaxes
                             or rate.NegotiatedRateCharges.TotalCharge)
            taxes = rate.NegotiatedRateCharges.TaxCharges
            itemized_charges = rate.NegotiatedRateCharges.ItemizedCharges + taxes
        else:
            total_charges = rate.TotalChargesWithTaxes or rate.TotalCharges
            taxes = rate.TaxCharges
            itemized_charges = rate.ItemizedCharges + taxes

        extra_charges = itemized_charges + [rate.ServiceOptionsCharges]
        estimated_arrival = (XP.find(
            "EstimatedArrival", detail_node, EstimatedArrivalType, first=True)
                             or EstimatedArrivalType())
        transit_days = (rate.GuaranteedDelivery.BusinessDaysInTransit
                        if rate.GuaranteedDelivery is not None else
                        estimated_arrival.BusinessDaysInTransit)
        currency = XP.find("CurrencyCode", detail_node, first=True).text
        service = ServiceCode.map(rate.Service.Code)

        return rates + [
            RateDetails(
                carrier_name=settings.carrier_name,
                carrier_id=settings.carrier_id,
                currency=currency,
                service=service.name_or_key,
                base_charge=NF.decimal(
                    rate.TransportationCharges.MonetaryValue),
                total_charge=NF.decimal(total_charges.MonetaryValue),
                duties_and_taxes=reduce(
                    lambda total, charge: total + NF.decimal(charge.
                                                             MonetaryValue),
                    taxes or [],
                    0.0,
                ),
                extra_charges=reduce(
                    lambda total, charge: (total + [
                        ChargeDetails(
                            name=charge.Code,
                            amount=NF.decimal(charge.MonetaryValue),
                            currency=charge.CurrencyCode,
                        )
                    ]),
                    [
                        charge for charge in extra_charges
                        if charge is not None and charge.Code is not None
                    ],
                    [],
                ),
                transit_days=NF.integer(transit_days),
                meta=dict(service_name=service.name_or_key))
        ]
Пример #14
0
def _extract_shipment(node: Element, settings: Settings) -> ShipmentDetails:
    shipping = XP.build(ShippingReplyType, node)
    quote: QuoteType = shipping.Quote

    tracking_number = getattr(next(iter(shipping.Package), None), 'trackingNumber', None)
    rate_provider, service, service_name = Service.info(
        quote.serviceId, quote.carrierId, quote.serviceName, quote.carrierName
    )
    surcharges = [
        ChargeDetails(
            name=charge.name,
            currency=quote.currency,
            amount=NF.decimal(charge.amount),
        )
        for charge in cast(List[SurchargeType], quote.Surcharge)
    ]
    fuel_surcharge = (
        ChargeDetails(
            name="Fuel surcharge",
            currency=quote.currency,
            amount=NF.decimal(quote.fuelSurcharge),
        )
        if quote.fuelSurcharge is not None else None
    )

    return ShipmentDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        tracking_number=tracking_number,
        shipment_identifier=shipping.Order.id,
        label=shipping.Labels,
        selected_rate=(
            RateDetails(
                carrier_name=settings.carrier_name,
                carrier_id=settings.carrier_id,
                service=service,
                currency=quote.currency,
                base_charge=NF.decimal(quote.baseCharge),
                total_charge=NF.decimal(quote.totalCharge),
                transit_days=quote.transitDays,
                extra_charges=([fuel_surcharge] + surcharges),
                meta=dict(
                    rate_provider=rate_provider,
                    service_name=service_name
                )
            ) if quote is not None else None
        ),
        meta=dict(
            rate_provider=rate_provider,
            service_name=service_name,
            tracking_url=shipping.TrackingURL
        )
    )
Пример #15
0
def _extract_rate(detail_node: Element, settings: Settings) -> Optional[RateDetails]:
    rate: RateReplyDetail = XP.to_object(RateReplyDetail, detail_node)
    service = ServiceType.map(rate.ServiceType)
    rate_type = rate.ActualRateType
    shipment_rate, shipment_discount = cast(
        Tuple[ShipmentRateDetail, Money],
        next(
            (
                (r.ShipmentRateDetail, r.EffectiveNetDiscount)
                for r in rate.RatedShipmentDetails
                if cast(ShipmentRateDetail, r.ShipmentRateDetail).RateType == rate_type
            ),
            (None, None),
        ),
    )
    discount = (
        NF.decimal(shipment_discount.Amount) if shipment_discount is not None else None
    )
    currency = cast(Money, shipment_rate.TotalBaseCharge).Currency
    duties_and_taxes = (
        shipment_rate.TotalTaxes.Amount + shipment_rate.TotalDutiesAndTaxes.Amount
    )
    surcharges = [
        ChargeDetails(
            name=cast(Surcharge, s).Description,
            amount=NF.decimal(cast(Surcharge, s).Amount.Amount),
            currency=currency,
        )
        for s in shipment_rate.Surcharges + shipment_rate.Taxes
    ]
    estimated_delivery = DF.date(rate.DeliveryTimestamp)
    transit = (
        ((estimated_delivery.date() - datetime.today().date()).days or None)
        if estimated_delivery is not None else None
    )

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        service=service.name_or_key,
        currency=currency,
        base_charge=NF.decimal(shipment_rate.TotalBaseCharge.Amount),
        total_charge=NF.decimal(shipment_rate.TotalNetChargeWithDutiesAndTaxes.Amount),
        duties_and_taxes=NF.decimal(duties_and_taxes),
        discount=discount,
        transit_days=transit,
        extra_charges=surcharges,
        meta=dict(service_name=service.name_or_key)
    )
Пример #16
0
def _extract_pickup(response: Element, settings: Settings) -> PickupDetails:
    pickup = ModifyPUResponse()
    pickup.build(response)
    pickup_charge = (
        ChargeDetails(
            name="Pickup Charge",
            amount=NF.decimal(pickup.PickupCharge),
            currency=pickup.CurrencyCode,
        )
        if pickup.PickupCharge is not None
        else None
    )
    pickup_date = (
        DF.fdate(pickup.NextPickupDate)
        if pickup.NextPickupDate is not None
        else None
    )

    return PickupDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        confirmation_number=str(pickup.ConfirmationNumber[0]),
        pickup_date=pickup_date,
        pickup_charge=pickup_charge,
        ready_time=DF.ftime(pickup.ReadyByTime),
        closing_time=DF.ftime(pickup.CallInTime),
    )
Пример #17
0
def _extract_pickup_details(
    response: PickupCreationResponse, settings: Settings
) -> PickupDetails:
    pickup = XP.build(
        PickupCreationResponse,
        next(
            iter(
                response.xpath(
                    ".//*[local-name() = $name]", name="PickupCreationResponse"
                )
            ),
            None,
        ),
    )
    rate = XP.build(
        RateResultType,
        next(
            iter(response.xpath(".//*[local-name() = $name]", name="RateResult")), None
        ),
    )

    return PickupDetails(
        carrier_id=settings.carrier_id,
        carrier_name=settings.carrier_name,
        confirmation_number=pickup.PRN,
        pickup_charge=ChargeDetails(
            name=rate.RateType,
            currency=rate.CurrencyCode,
            amount=NF.decimal(rate.GrandTotalOfAllCharge),
        ),
    )
Пример #18
0
        def apply(rate: Rate) -> Rate:
            applicable = []

            if any(self.carriers or []):
                applicable.append(rate.carrier_name in self.carriers)

            if any(self.services or []):
                applicable.append(rate.service in self.services)

            if self.discount_range is not None:
                applicable.append(
                    rate.discount in cast(NumericRange, self.discount_range))

            if self.freight_range is not None:
                applicable.append(rate.total_charge in cast(
                    NumericRange, self.freight_range))

            if any(applicable) and all(applicable):
                logger.debug('applying broker surcharge to rates')
                return Rate(
                    **{
                        **DP.to_dict(rate), 'total_charge':
                        NF.decimal(rate.total_charge +
                                   cast(float, self.amount)),
                        'extra_charges': (rate.extra_charges + [
                            ChargeDetails(name=cast(str, self.name),
                                          amount=cast(float, self.amount),
                                          currency=rate.currency)
                        ])
                    })

            return rate
Пример #19
0
    def value(self):
        sides = [self._side1.CM, self._side2.CM, self._side3.CM]
        if not any(sides):
            return None

        sides.sort()
        small_side1, small_side2, _ = sides
        return NF.decimal((small_side1 + small_side2) * 2)
Пример #20
0
        def apply(rate: Rate) -> Rate:
            applicable = []
            carrier_ids = [c.carrier_id for c in self.carrier_accounts.all()]

            if any(self.carriers or []):
                applicable.append(rate.carrier_name in self.carriers)

            if any(carrier_ids):
                applicable.append(rate.carrier_id in carrier_ids)

            if any(self.services or []):
                applicable.append(rate.service in self.services)

            if self.discount_range is not None:
                applicable.append(rate.discount in cast(NumericRange, self.discount_range))

            if self.freight_range is not None:
                applicable.append(rate.total_charge in cast(NumericRange, self.freight_range))

            if any(applicable) and all(applicable):
                logger.debug('applying broker surcharge to rate')

                amount = NF.decimal(
                    self.amount
                    if self.surcharge_type == 'AMOUNT' else
                    (rate.total_charge * (cast(float, self.amount) / 100))
                )
                base_charge = NF.decimal(rate.base_charge + amount)
                total_charge = NF.decimal(rate.total_charge + amount)
                extra_charges = (rate.extra_charges + [
                    ChargeDetails(
                        name=cast(str, self.name),
                        amount=amount,
                        currency=rate.currency
                    )
                ])

                return Rate(**{
                    **DP.to_dict(rate),
                    'base_charge': base_charge,
                    'total_charge': total_charge,
                    'extra_charges': extra_charges
                })

            return rate
Пример #21
0
def _extract_detail(details: Tuple[ratedServices, ratedService],
                    settings: Settings) -> RateDetails:
    rate, service = details
    charges: List[chargeElement] = service.chargeElements.chargeElement

    return RateDetails(carrier_name=settings.carrier_name,
                       carrier_id=settings.carrier_id,
                       currency=rate.currency,
                       service=str(service.product.id),
                       base_charge=NF.decimal(service.totalPriceExclVat),
                       total_charge=NF.decimal(service.totalPrice),
                       duties_and_taxes=NF.decimal(service.vatAmount),
                       extra_charges=[
                           ChargeDetails(name=charge.description,
                                         amount=NF.decimal(charge.chargeValue),
                                         currency=rate.currency)
                           for charge in charges
                       ],
                       meta=dict(service_name=service.product.productDesc))
Пример #22
0
def _extract_details(rate: Rate, response: RateResponse,
                     settings: Settings) -> RateDetails:

    return RateDetails(carrier_id=settings.carrier_id,
                       carrier_name=settings.carrier_name,
                       currency="CAD",
                       transit_days=response.delay,
                       service=Service(rate.rateType),
                       discount=NF.decimal(rate.discountAmount),
                       base_charge=NF.decimal(rate.basicCharge),
                       total_charge=NF.decimal(rate.total),
                       duties_and_taxes=NF.decimal(rate.taxes),
                       extra_charges=[
                           ChargeDetails(
                               name=charge.name,
                               amount=NF.decimal(charge.amount),
                               currency="CAD",
                           ) for charge in rate.surcharges
                       ],
                       meta=dict(accountType=rate.accountType))
Пример #23
0
def _extract_quote(node: Element, settings: Settings) -> RateDetails:
    quote = XP.to_object(price_quoteType, node)
    service = ServiceType.map(quote.service_code)
    adjustments = getattr(quote.price_details.adjustments, 'adjustment', [])
    discount = sum(NF.decimal(d.adjustment_cost or 0) for d in adjustments)
    transit_days = quote.service_standard.expected_transit_time

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        currency=Currency.CAD.name,
        transit_days=transit_days,
        service=service.name_or_key,
        base_charge=NF.decimal(quote.price_details.base or 0),
        total_charge=NF.decimal(quote.price_details.due or 0),
        discount=NF.decimal(discount),
        duties_and_taxes=NF.decimal(
            float(quote.price_details.taxes.gst.valueOf_ or 0)
            + float(quote.price_details.taxes.pst.valueOf_ or 0)
            + float(quote.price_details.taxes.hst.valueOf_ or 0)
        ),
        extra_charges=[
            ChargeDetails(
                name=a.adjustment_name,
                currency=Currency.CAD.name,
                amount=NF.decimal(a.adjustment_cost or 0),
            )
            for a in adjustments
        ],
        meta=dict(
            service_name=(service.name or quote.service_name)
        )
    )
Пример #24
0
def _extract_pickup_details(response: Element, settings: Settings) -> PickupDetails:
    pickup = XP.find(
        "PickupCreationResponse", response, PickupCreationResponse, first=True
    )
    rate = XP.find("RateResult", response, RateResultType, first=True)

    return PickupDetails(
        carrier_id=settings.carrier_id,
        carrier_name=settings.carrier_name,
        confirmation_number=pickup.PRN,
        pickup_charge=ChargeDetails(
            name=rate.RateType,
            currency=rate.CurrencyCode,
            amount=NF.decimal(rate.GrandTotalOfAllCharge),
        ),
    )
Пример #25
0
def _extract_quote(qtdshp_node: Element, settings: Settings) -> RateDetails:
    qtdshp = ResponseQtdShpType()
    qtdshp.build(qtdshp_node)
    if qtdshp.ShippingCharge is None or qtdshp.ShippingCharge == 0:
        return None

    ExtraCharges = list(
        map(
            lambda s: ChargeDetails(name=s.LocalServiceTypeName,
                                    amount=NF.decimal(s.ChargeValue or 0)),
            qtdshp.QtdShpExChrg,
        ))
    Discount_ = reduce(
        lambda d, ec: d + ec.amount
        if "Discount" in ec.name else d, ExtraCharges, 0.0)
    DutiesAndTaxes_ = reduce(
        lambda d, ec: d + ec.amount
        if "TAXES PAID" in ec.name else d, ExtraCharges, 0.0)
    delivery_date = DF.date(qtdshp.DeliveryDate[0].DlvyDateTime,
                            "%Y-%m-%d %H:%M:%S")
    pricing_date = DF.date(qtdshp.PricingDate)
    transit = ((delivery_date - pricing_date).days
               if all([delivery_date, pricing_date]) else None)
    service_name = next(
        (p.name for p in ProductCode if p.value == qtdshp.GlobalProductCode),
        None,
    )
    return RateDetails(carrier_name=settings.carrier_name,
                       carrier_id=settings.carrier_id,
                       currency=qtdshp.CurrencyCode,
                       transit_days=transit,
                       service=(service_name or qtdshp.GlobalProductCode),
                       base_charge=NF.decimal(qtdshp.WeightCharge),
                       total_charge=NF.decimal(qtdshp.ShippingCharge),
                       duties_and_taxes=NF.decimal(DutiesAndTaxes_),
                       discount=NF.decimal(Discount_),
                       extra_charges=list(
                           map(
                               lambda s: ChargeDetails(
                                   name=s.LocalServiceTypeName,
                                   amount=NF.decimal(s.ChargeValue),
                                   currency=qtdshp.CurrencyCode,
                               ),
                               qtdshp.QtdShpExChrg,
                           )),
                       meta=(dict(service=qtdshp.GlobalProductCode,
                                  service_name=qtdshp.ProductShortName)
                             if service_name is None else None))
Пример #26
0
def _extract_quote(price_quote_node: Element, settings: Settings) -> RateDetails:
    price_quote = price_quoteType()
    price_quote.build(price_quote_node)
    currency = Currency.CAD.name
    discounts = [
        ChargeDetails(
            name=d.adjustment_name,
            currency=currency,
            amount=NF.decimal(d.adjustment_cost or 0),
        )
        for d in price_quote.price_details.adjustments.adjustment
    ]
    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        currency=currency,
        transit_days=cast(
            service_standardType, price_quote.service_standard
        ).expected_transit_time,
        service=ServiceType(price_quote.service_code).name,
        base_charge=NF.decimal(price_quote.price_details.base or 0),
        total_charge=NF.decimal(price_quote.price_details.due or 0),
        discount=NF.decimal(reduce(lambda total, d: total + d.amount, discounts, 0.0)),
        duties_and_taxes=NF.decimal(
            float(price_quote.price_details.taxes.gst.valueOf_ or 0)
            + float(price_quote.price_details.taxes.pst.valueOf_ or 0)
            + float(price_quote.price_details.taxes.hst.valueOf_ or 0)
        ),
        extra_charges=list(
            map(
                lambda a: ChargeDetails(
                    name=a.adjustment_name,
                    currency=currency,
                    amount=NF.decimal(a.adjustment_cost or 0),
                ),
                price_quote.price_details.adjustments.adjustment,
            )
        ),
    )
Пример #27
0
def _extract_quote(quote: ResponseQtdShpType,
                   settings: Settings) -> RateDetails:
    service = ProductCode.map(quote.GlobalProductCode)
    ExtraCharges = [
        ChargeDetails(name=s.LocalServiceTypeName,
                      amount=NF.decimal(s.ChargeValue or 0))
        for s in quote.QtdShpExChrg
    ]
    discount = reduce(
        lambda d, ec: d + ec.amount
        if "Discount" in ec.name else d, ExtraCharges, 0.0)
    duties_and_taxes = reduce(
        lambda d, ec: d + ec.amount
        if "TAXES PAID" in ec.name else d, ExtraCharges, 0.0)
    delivery_date = DF.date(quote.DeliveryDate[0].DlvyDateTime,
                            "%Y-%m-%d %H:%M:%S")
    pricing_date = DF.date(quote.PricingDate)
    transit = ((delivery_date.date() - pricing_date.date()).days
               if all([delivery_date, pricing_date]) else None)

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        currency=quote.CurrencyCode,
        transit_days=transit,
        service=service.name_or_key,
        base_charge=NF.decimal(quote.WeightCharge),
        total_charge=NF.decimal(quote.ShippingCharge),
        duties_and_taxes=NF.decimal(duties_and_taxes),
        discount=NF.decimal(discount),
        extra_charges=[
            ChargeDetails(
                name=s.LocalServiceTypeName,
                amount=NF.decimal(s.ChargeValue),
                currency=quote.CurrencyCode,
            ) for s in quote.QtdShpExChrg
        ],
        meta=dict(service_name=(service.name or quote.ProductShortName)))
Пример #28
0
def _extract_rate(estimate_node: Element, settings: Settings) -> RateDetails:
    estimate = ShipmentEstimate()
    estimate.build(estimate_node)
    currency = Currency.CAD.name
    duties_and_taxes = [
        ChargeDetails(
            name=cast(Tax, tax).Description,
            amount=NF.decimal(cast(Tax, tax).Amount),
            currency=currency,
        ) for tax in estimate.Taxes.Tax
    ]
    surcharges = [
        ChargeDetails(
            name=cast(Surcharge, charge).Description,
            amount=NF.decimal(cast(Surcharge, charge).Amount),
            currency=currency,
        ) for charge in estimate.Surcharges.Surcharge
    ]
    option_charges = [
        ChargeDetails(
            name=cast(OptionPrice, charge).Description,
            amount=NF.decimal(cast(OptionPrice, charge).Amount),
            currency=currency,
        ) for charge in estimate.OptionPrices.OptionPrice
    ]
    service = next((p.name for p in Product if p.value in estimate.ServiceID),
                   estimate.ServiceID)
    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        service=service,
        currency=currency,
        base_charge=NF.decimal(estimate.BasePrice),
        transit_days=estimate.EstimatedTransitDays,
        total_charge=NF.decimal(estimate.TotalPrice),
        duties_and_taxes=NF.decimal(sum(c.amount for c in duties_and_taxes)),
        extra_charges=(duties_and_taxes + surcharges + option_charges),
    )
Пример #29
0
def _extract_rate(estimate_node: Element, settings: Settings) -> RateDetails:
    estimate = XP.to_object(ShipmentEstimate, estimate_node)
    currency = Currency.CAD.name
    service = Product.map(estimate.ServiceID)
    duties_and_taxes = [
        ChargeDetails(
            name=cast(Tax, tax).Description,
            amount=NF.decimal(cast(Tax, tax).Amount),
            currency=currency,
        ) for tax in estimate.Taxes.Tax
    ]
    surcharges = [
        ChargeDetails(
            name=cast(Surcharge, charge).Description,
            amount=NF.decimal(cast(Surcharge, charge).Amount),
            currency=currency,
        ) for charge in estimate.Surcharges.Surcharge
    ]
    option_charges = [
        ChargeDetails(
            name=cast(OptionPrice, charge).Description,
            amount=NF.decimal(cast(OptionPrice, charge).Amount),
            currency=currency,
        ) for charge in estimate.OptionPrices.OptionPrice
    ]

    return RateDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        service=service.name_or_key,
        currency=currency,
        base_charge=NF.decimal(estimate.BasePrice),
        transit_days=estimate.EstimatedTransitDays,
        total_charge=NF.decimal(estimate.TotalPrice),
        duties_and_taxes=NF.decimal(sum(c.amount for c in duties_and_taxes)),
        extra_charges=(duties_and_taxes + surcharges + option_charges),
        meta=dict(service_name=service.name_or_key))
Пример #30
0
def shipment_request(payload: ShipmentRequest,
                     _) -> Serializable[NonContractShipmentType]:
    package = Packages(payload.parcels, PackagePresets,
                       required=["weight"]).single
    service = ServiceType[payload.service].value
    options = Options(payload.options, OptionCode)

    is_intl = (payload.recipient.country_code is not None
               and payload.recipient.country_code != 'CA')
    all_options = ([*options] +
                   [(OptionCode.canadapost_return_to_sender.name,
                     OptionCode.canadapost_return_to_sender.value.apply(True))]
                   if is_intl
                   and not any(key in options
                               for key in INTERNATIONAL_NON_DELIVERY_OPTION)
                   else [*options])

    request = NonContractShipmentType(
        requested_shipping_point=None,
        delivery_spec=DeliverySpecType(
            service_code=service,
            sender=SenderType(
                name=payload.shipper.person_name,
                company=payload.shipper.company_name,
                contact_phone=payload.shipper.phone_number,
                address_details=DomesticAddressDetailsType(
                    address_line_1=SF.concat_str(payload.shipper.address_line1,
                                                 join=True),
                    address_line_2=SF.concat_str(payload.shipper.address_line2,
                                                 join=True),
                    city=payload.shipper.city,
                    prov_state=payload.shipper.state_code,
                    postal_zip_code=payload.shipper.postal_code,
                ),
            ),
            destination=DestinationType(
                name=payload.recipient.person_name,
                company=payload.recipient.company_name,
                additional_address_info=None,
                client_voice_number=payload.recipient.phone_number,
                address_details=DestinationAddressDetailsType(
                    address_line_1=SF.concat_str(
                        payload.recipient.address_line1, join=True),
                    address_line_2=SF.concat_str(
                        payload.recipient.address_line2, join=True),
                    city=payload.recipient.city,
                    prov_state=payload.recipient.state_code,
                    country_code=payload.recipient.country_code,
                    postal_zip_code=payload.recipient.postal_code,
                ),
            ),
            options=(optionsType(option=[
                OptionType(
                    option_code=getattr(option, 'key', option),
                    option_amount=getattr(option, 'value', None),
                    option_qualifier_1=None,
                    option_qualifier_2=None,
                ) for code, option in all_options if code in OptionCode
            ]) if any(options) else None),
            parcel_characteristics=ParcelCharacteristicsType(
                weight=NF.decimal(package.weight.KG, .1),
                dimensions=dimensionsType(
                    length=NF.decimal(package.length.CM, .1),
                    width=NF.decimal(package.width.CM, .1),
                    height=NF.decimal(package.height.CM, .1),
                ),
                unpackaged=None,
                mailing_tube=None,
            ),
            notification=(NotificationType(
                email=options.notification_email or payload.recipient.email,
                on_shipment=True,
                on_exception=True,
                on_delivery=True,
            ) if options.notification_email is not None else None),
            preferences=PreferencesType(
                show_packing_instructions=False,
                show_postage_rate=True,
                show_insured_value=("insurance" in payload.options),
            ),
            references=ReferencesType(
                cost_centre=None,
                customer_ref_1=payload.reference,
                customer_ref_2=None,
            ),
            customs=(CustomsType(
                currency=Currency.AUD.value,
                conversion_from_cad=None,
                reason_for_export=payload.customs.incoterm,
                other_reason=payload.customs.content_description,
                duties_and_taxes_prepaid=payload.customs.duty.account_number,
                certificate_number=None,
                licence_number=None,
                invoice_number=None,
                sku_list=sku_listType(item=[
                    SkuType(
                        customs_number_of_units=item.quantity,
                        customs_description=item.description,
                        sku=item.sku,
                        hs_tariff_code=None,
                        unit_weight=WeightUnit.KG.value,
                        customs_value_per_unit=item.value_amount,
                        customs_unit_of_measure=None,
                        country_of_origin=payload.shipper.country_code,
                        province_of_origin=None,
                    ) for item in payload.customs.commodities
                ]),
            ) if payload.customs is not None else None),
            settlement_info=None,
        ),
    )
    return Serializable(request, _request_serializer)