Exemplo n.º 1
0
def _extract_error(node: Element, settings: Settings) -> Message:
    error = XP.build(ERROR, node)

    return Message(
        # context info
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,

        # carrier error info
        code=error.CODE,
        message=error.DESCRIPTION,
    )
Exemplo n.º 2
0
def parse_shipment_response(
        response: Element,
        settings: Settings) -> Tuple[ShipmentDetails, List[Message]]:
    shipment = XP.build(
        Shipment,
        next(
            iter(response.xpath(".//*[local-name() = $name]",
                                name="shipment")), None))
    success = (shipment is not None and shipment.id is not None)
    shipment_details = _extract_details(response,
                                        settings) if success else None

    return shipment_details, parse_error_response(response, settings)
Exemplo n.º 3
0
def parse_tracking_response(
        response,
        settings: Settings) -> Tuple[List[TrackingDetails], List[Message]]:
    non_existents = next((XP.build(ArrayOfstring, n)
                          for n in response.xpath(".//*[local-name() = $name]",
                                                  name="NonExistingWaybills")),
                         ArrayOfstring())
    results = response.xpath(".//*[local-name() = $name]",
                             name="TrackingResult")
    tracking_details = [_extract_detail(node, settings) for node in results]
    errors = _extract_errors(non_existents, settings) + parse_error_response(
        response, settings)

    return tracking_details, errors
Exemplo n.º 4
0
def parse_error_response(response: Element,
                         settings: Settings) -> List[Message]:
    error_nodes = ([response] if response.tag == 'Error' else response.xpath(
        ".//*[local-name() = $name]", name="Error"))
    errors = [XP.build(Error, node) for node in error_nodes]

    return [
        Message(
            carrier_name=settings.carrier_name,
            carrier_id=settings.carrier_id,
            code=str(error.Number),
            message=error.Description,
        ) for error in errors
    ]
Exemplo n.º 5
0
def _get_label(shipment_response: str, settings: Settings) -> Job:
    response = XP.to_xml(shipment_response)
    shipment = XP.build(
        Shipment,
        next(
            iter(response.xpath(".//*[local-name() = $name]",
                                name="shipment")), None))
    success = (shipment is not None and shipment.id is not None)
    data = (get_label_request(LabelRequest(
        shipment_id=shipment.id), settings) if success else None)

    return Job(id="get_label",
               data=data,
               fallback=("" if not success else None))
Exemplo n.º 6
0
def parse_address_validation_response(
        response: Element,
        settings: Settings) -> Tuple[AddressValidationDetails, List[Message]]:
    notes = response.xpath(".//*[local-name() = $name]", name="Note")
    success = next(
        (True
         for note in notes if XP.build(Note, note).ActionNote == "Success"),
        False)
    validation_details = AddressValidationDetails(
        carrier_id=settings.carrier_id,
        carrier_name=settings.carrier_name,
        success=success)

    return validation_details, parse_error_response(response, settings)
Exemplo n.º 7
0
    def _refund_if_submitted(shipment_details: str):
        shipment = XP.build(ShipmentInfoType, XP.to_xml(shipment_details))
        transmitted = shipment.shipment_status == 'transmitted'
        data = dict(
            id=payload.shipment_identifier,
            payload=Serializable(
                ShipmentRefundRequestType(
                    email=payload.options.get('email')), lambda request: XP.
                export(request,
                       name_='shipment-refund-request',
                       namespacedef_=
                       'xmlns="http://www.canadapost.ca/ws/shipment-v8"'))
        ) if transmitted else None

        return Job(id="refund", data=data, fallback=shipment_details)
Exemplo n.º 8
0
def parse_shipment_cancel_response(
        response: Element,
        settings: Settings) -> Tuple[ConfirmationDetails, List[Message]]:
    errors: List[Message] = parse_error_response(response, settings)
    if response.tag == 'eVSCancelResponse':
        cancel_response = XP.build(eVSCancelResponse, response)
    else:
        cancel_response = XP.build(eVSICancelResponse, response)

    if cancel_response.Status != "Cancelled":
        errors.append(
            Message(carrier_name=settings.carrier_name,
                    carrier_id=settings.carrier_id,
                    message=cancel_response.Reason,
                    code=cancel_response.Status))

    details = (ConfirmationDetails(
        carrier_id=settings.carrier_id,
        carrier_name=settings.carrier_name,
        operation="Shipment Cancel",
        success=True,
    ) if not any(errors) else None)

    return details, errors
Exemplo n.º 9
0
def parse_pickup_response(
        response: Element,
        settings: Settings) -> Tuple[PickupDetails, List[Message]]:
    reply = XP.build(
        CreatePickupReply,
        next(
            iter(
                response.xpath(".//*[local-name() = $name]",
                               name="CreatePickupReply")),
            None,
        ),
    )
    pickup = (_extract_pickup_details(reply, settings) if reply.HighestSeverity
              == NotificationSeverityType.SUCCESS.value else None)
    return pickup, parse_error_response(response, settings)
Exemplo n.º 10
0
def parse_pickup_response(
        response: Element,
        settings: Settings) -> Tuple[PickupDetails, List[Message]]:
    pickup_node = next(
        iter(response.xpath(".//*[local-name() = $name]", name="pickup")),
        None)
    pickup = XP.build(PickupV2, pickup_node)
    details: PickupDetails = PickupDetails(carrier_id=settings.carrier_id,
                                           carrier_name=settings.carrier_name,
                                           confirmation_number=str(pickup.id),
                                           pickup_date=DF.fdatetime(
                                               pickup.pickup_date,
                                               '%Y-%m-%dT%H:%M:%S'))

    return details, parse_error_response(response, settings)
Exemplo n.º 11
0
def _cancel_pickup_request(response: str, payload: PickupUpdateRequest,
                           settings: Settings):
    reply = next(
        iter(
            XP.to_xml(response).xpath(".//*[local-name() = $name]",
                                      name="CreatePickupReply")),
        None,
    )
    new_pickup = XP.build(CreatePickupReply, reply)
    data = (pickup_cancel_request(
        PickupCancelRequest(confirmation_number=payload.confirmation_number),
        settings,
    ) if new_pickup is not None and new_pickup.HighestSeverity
            == NotificationSeverityType.SUCCESS.value else None)

    return Job(id="cancel_pickup", data=data, fallback="")
Exemplo n.º 12
0
def _extract_detail(node: Element, settings: Settings) -> TrackingDetails:
    detail = XP.build(TrackingResult, node)

    return TrackingDetails(
        carrier_name=settings.carrier_name,
        carrier_id=settings.carrier_id,
        tracking_number=detail.WaybillNumber,
        events=[
            TrackingEvent(
                date=DF.date(detail.UpdateDateTime, '%Y-%m-%dT%H:%M:%S'),
                description=detail.UpdateDescription,
                location=detail.UpdateLocation,
                code=detail.UpdateCode,
                time=DF.ftime(detail.UpdateDateTime, '%Y-%m-%dT%H:%M:%S'),
            )
        ],
    )
Exemplo n.º 13
0
def parse_rate_response(
        response: Element,
        settings: Settings) -> Tuple[List[RateDetails], List[Message]]:
    price_node = next(
        response.xpath(".//*[local-name() = $name]", name="priceResponse"),
        None)
    price_response = XP.build(priceResponse, price_node)

    if price_response is not None and price_response.ratedServices is not None:
        rate_details = [
            _extract_detail((price_response.ratedServices, service), settings)
            for service in price_response.ratedServices.ratedService
        ]
    else:
        rate_details = []

    return rate_details, parse_error_response(response, settings)
Exemplo n.º 14
0
def _extract_details(response: Element, settings: Settings) -> ShipmentDetails:
    shipment_node = next(
        iter(response.xpath(".//*[local-name() = $name]", name="shipment")),
        None)
    label = next(
        iter(response.xpath(".//*[local-name() = $name]", name="labels")),
        None)
    shipment = XP.build(Shipment, shipment_node)
    tracking_number = next(iter(shipment.packages), Package()).barcode

    return ShipmentDetails(
        carrier_id=settings.carrier_id,
        carrier_name=settings.carrier_name,
        label=str(label.text),
        tracking_number=tracking_number,
        shipment_identifier=str(shipment.id),
        selected_rate=_extract_rate_details(shipment_node, settings),
    )
Exemplo n.º 15
0
def parse_shipment_cancel_response(
        response: Element,
        settings: Settings) -> Tuple[ConfirmationDetails, List[Message]]:
    void_response = XP.build(
        VoidShipmentResponse,
        next(
            iter(
                response.xpath(".//*[local-name() = $name]",
                               name="VoidShipmentResponse")), None))
    voided = void_response is not None and void_response.ShipmentVoided
    cancellation = ConfirmationDetails(
        carrier_id=settings.carrier_id,
        carrier_name=settings.carrier_name,
        success=True,
        operation="Cancel Shipment",
    ) if voided else None

    return cancellation, parse_error_response(response, settings)
Exemplo n.º 16
0
def parse_address_validation_response(
        response: Element,
        settings: Settings) -> Tuple[AddressValidationDetails, List[Message]]:
    status = XP.build(
        Response,
        next(
            iter(response.xpath(".//*[local-name() = $name]",
                                name="Response")),
            None,
        ),
    )
    success = status is not None and status.ResponseStatusCode == "1"
    validation_details = AddressValidationDetails(
        carrier_id=settings.carrier_id,
        carrier_name=settings.carrier_name,
        success=success) if success else None

    return validation_details, parse_error_response(response, settings)
Exemplo n.º 17
0
def _extract_detail(node: Element, settings: Settings) -> TrackingDetails:
    detail = XP.build(ConsignmentType, node)

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

        tracking_number=detail.ConsignmentNumber,
        events=[
            TrackingEvent(
                date=DF.fdate(status.LocalEventDate.valueOf_, '%Y%m%d'),
                description=status.StatusDescription,
                location=SF.concat_str(status.Depot, status.DepotName, join=True, separator='-'),
                code=status.StatusCode,
                time=DF.ftime(status.LocalEventTime.valueOf_, '%H%M')
            )
            for status in cast(List[StatusStructure], detail.StatusData)
        ],
        delivered=(detail.SummaryCode == "DEL")
    )
Exemplo n.º 18
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))
Exemplo n.º 19
0
def parse_pickup_cancel_response(
        response: Element,
        settings: Settings) -> Tuple[ConfirmationDetails, List[Message]]:
    status = XP.build(
        CodeDescriptionType,
        next(
            iter(
                response.xpath(".//*[local-name() = $name]",
                               name="ResponseStatus")),
            None,
        ),
    )
    success = status is not None and status.Code == "1"
    cancellation = (ConfirmationDetails(
        carrier_id=settings.carrier_id,
        carrier_name=settings.carrier_name,
        success=success,
        operation="Cancel Pickup",
    ) if success else None)

    return cancellation, parse_error_response(response, settings)
Exemplo n.º 20
0
def parse_pickup_response(
    response: Element, settings: Settings
) -> Tuple[PickupDetails, List[Message]]:
    reply = XP.build(
        PickupCreationResponse,
        next(
            iter(
                response.xpath(
                    ".//*[local-name() = $name]", name="PickupCreationResponse"
                )
            ),
            None,
        ),
    )
    pickup = (
        _extract_pickup_details(response, settings)
        if reply is not None and reply.PRN is not None
        else None
    )

    return pickup, parse_error_response(response, settings)
Exemplo n.º 21
0
def parse_pickup_update_response(
    response: Element, settings: Settings
) -> Tuple[PickupDetails, List[Message]]:
    reply = XP.build(
        ModifyPickUpResponse,
        next(
            iter(
                response.xpath(
                    ".//*[local-name() = $name]", name="ModifyPickUpResponse"
                )
            ),
            None,
        ),
    )
    pickup = (
        _extract_pickup_details(reply, settings)
        if reply is not None and reply.PickUpConfirmationNumber is not None
        else None
    )

    return pickup, parse_error_response(response, settings)
Exemplo n.º 22
0
def parse_pickup_cancel_response(
        response: Element,
        settings: Settings) -> Tuple[ConfirmationDetails, List[Message]]:
    reply = XP.build(
        CancelPickupReply,
        next(
            iter(
                response.xpath(".//*[local-name() = $name]",
                               name="CancelPickupReply")),
            None,
        ),
    )
    cancellation = ConfirmationDetails(
        carrier_id=settings.carrier_id,
        carrier_name=settings.carrier_name,
        success=reply.HighestSeverity ==
        NotificationSeverityType.SUCCESS.value,
        operation="Cancel Pickup",
    )

    return cancellation, parse_error_response(response, settings)
Exemplo n.º 23
0
def _extract_tracking_details(node: Element,
                              settings: Settings) -> TrackingDetails:
    result = XP.build(TrackingResult, node)
    is_en = settings.language == "en"
    events = [
        TrackingEvent(
            date=DF.fdate(event.local_date_time, '%Y%m%d %H%M%S'),
            description=(event.code_description_en
                         if is_en else event.code_description_fr),
            location=_format_location(event.address),
            code=event.code,
            time=DF.ftime(event.local_date_time, '%Y%m%d %H%M%S'),
        ) for event in cast(List[CanparTrackingEvent], result.events)
    ]

    return TrackingDetails(carrier_name=settings.carrier_name,
                           carrier_id=settings.carrier_id,
                           tracking_number=result.barcode,
                           events=events,
                           delivered=any(event.code == 'DEL'
                                         for event in events))
Exemplo n.º 24
0
def _cancel_pickup_request(
    response: str, payload: PickupUpdateRequest, settings: Settings
):
    reply = next(
        iter(
            XP.to_xml(response).xpath(
                ".//*[local-name() = $name]", name="PickupCreationResponse"
            )
        ),
        None,
    )
    new_pickup = XP.build(PickupCreationResponse, reply)
    data = (
        pickup_cancel_request(
            PickupCancelRequest(confirmation_number=payload.confirmation_number),
            settings,
        )
        if new_pickup is not None and new_pickup.PRN is not None
        else None
    )

    return Job(id="cancel_pickup", data=data, fallback="")
Exemplo n.º 25
0
def _extract_details(response: Element, settings: Settings) -> ShipmentDetails:
    shipment = XP.build(eVSPriorityMailIntlResponse, response)
    charges: List[ExtraServiceType] = shipment.ExtraServices.ExtraService

    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,
                               currency=Currency.USD.value,
                               total_charge=NF.decimal(shipment.TotalValue),
                               base_charge=NF.decimal(shipment.Postage),
                               extra_charges=[
                                   ChargeDetails(name=charge.ServiceName,
                                                 amount=NF.decimal(
                                                     charge.Price),
                                                 currency=Currency.USD.value)
                                   for charge in charges
                               ]))
Exemplo n.º 26
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
        )
    )
Exemplo n.º 27
0
def _create_pickup(rate_response: str, payload: PickupRequest, settings: Settings):
    rate_result = XP.build(RateResultType, XP.to_xml(rate_response))
    data = _create_pickup_request(payload, settings) if rate_result else None

    return Job(id="create_pickup", data=data, fallback="")