예제 #1
0
    def cancel(payload: dict,
               carrier_filter: dict = None,
               carrier: models.Carrier = None) -> ConfirmationResponse:
        carrier = carrier or next(
            iter(Carriers.list(**{
                **(carrier_filter or {}), 'active': True
            })), None)
        print(carrier)
        if carrier is None:
            raise NotFound('No configured and active carrier found')

        request = purplship.Pickup.cancel(
            PickupCancelRequest(**DP.to_dict(payload)))
        gateway = purplship.gateway[carrier.data.carrier_name].create(
            carrier.data.dict())

        # The request call is wrapped in identity to simplify mocking in tests
        confirmation, messages = identity(
            lambda: request.from_(gateway).parse())

        if confirmation is None:
            raise PurplShipApiException(
                detail=ErrorResponse(messages=messages),
                status_code=status.HTTP_400_BAD_REQUEST)

        return ConfirmationResponse(confirmation=confirmation,
                                    messages=messages)
예제 #2
0
    def schedule(payload: dict,
                 carrier_filter: dict = None,
                 carrier: models.Carrier = None) -> PickupResponse:
        carrier = carrier or next(
            iter(Carriers.list(**{
                **(carrier_filter or {}), 'active': True
            })), None)

        if carrier is None:
            raise NotFound('No configured and active carrier found')

        request = purplship.Pickup.schedule(
            PickupRequest(**DP.to_dict(payload)))
        gateway = purplship.gateway[carrier.data.carrier_name].create(
            carrier.data.dict())

        # The request call is wrapped in identity to simplify mocking in tests
        pickup, messages = identity(lambda: request.from_(gateway).parse())

        if pickup is None:
            raise PurplShipApiException(
                detail=ErrorResponse(messages=messages),
                status_code=status.HTTP_400_BAD_REQUEST)

        return PickupResponse(pickup=Pickup(
            **{
                **payload,
                **DP.to_dict(pickup),
                'id': f'pck_{uuid.uuid4().hex}',
                'test_mode': carrier.test,
            }),
                              messages=messages)
예제 #3
0
    def track(payload: dict,
              carrier_filter: dict = None,
              carrier: models.Carrier = None) -> TrackingResponse:
        carrier = carrier or next(
            iter(Carriers.list(**{
                **(carrier_filter or {}), 'active': True
            })), None)

        if carrier is None:
            raise NotFound('No configured and active carrier found')

        request = purplship.Tracking.fetch(
            TrackingRequest(**DP.to_dict(payload)))
        gateway = purplship.gateway[carrier.data.carrier_name].create(
            carrier.data.dict())

        # The request call is wrapped in identity to simplify mocking in tests
        results, messages = identity(lambda: request.from_(gateway).parse())

        if any(messages or []) and not any(results or []):
            raise PurplShipApiException(
                detail=ErrorResponse(messages=messages),
                status_code=status.HTTP_404_NOT_FOUND)

        return TrackingResponse(tracking=(Tracking(
            **{
                **DP.to_dict(results[0]),
                'id': f'trk_{uuid.uuid4().hex}',
                'test_mode': carrier.test,
            }) if any(results) else None),
                                messages=messages)
예제 #4
0
    def create(payload: dict,
               resolve_tracking_url: Callable[[Shipment], str] = None,
               carrier: models.Carrier = None) -> Shipment:
        selected_rate = next(
            (Rate(**rate) for rate in payload.get('rates')
             if rate.get('id') == payload.get('selected_rate_id')), None)

        if selected_rate is None:
            raise NotFound(
                f'Invalid selected_rate_id "{payload.get("selected_rate_id")}" \n '
                f'Please select one of the following: [ {", ".join([r.get("id") for r in payload.get("rates")])} ]'
            )

        carrier = carrier or Carriers.retrieve(
            carrier_id=selected_rate.carrier_id).data
        request = ShipmentRequest(
            **{
                **DP.to_dict(payload), 'service': selected_rate.service
            })
        gateway = purplship.gateway[carrier.carrier_name].create(
            carrier.dict())

        # The request is wrapped in identity to simplify mocking in tests
        shipment, messages = identity(
            lambda: purplship.Shipment.create(request).from_(gateway).parse())

        if shipment is None:
            raise PurplShipApiException(
                detail=ErrorResponse(messages=messages),
                status_code=status.HTTP_400_BAD_REQUEST)

        shipment_rate = ({
            **DP.to_dict(shipment.selected_rate), 'id':
            f'rat_{uuid.uuid4().hex}'
        } if shipment.selected_rate is not None else DP.to_dict(selected_rate))

        def generate_tracking_url():
            if resolve_tracking_url is None:
                return ''

            return f"{resolve_tracking_url(shipment)}{'?test' if carrier.test else ''}"

        return Shipment(
            **{
                **payload,
                **DP.to_dict(shipment), "id": f"shp_{uuid.uuid4().hex}",
                "test_mode": carrier.test,
                "selected_rate": shipment_rate,
                "service": shipment_rate["service"],
                "selected_rate_id": shipment_rate["id"],
                "tracking_url": generate_tracking_url(),
                "status": ShipmentStatus.purchased.value,
                "created_at": datetime.now().strftime(
                    "%Y-%m-%d %H:%M:%S.%f%z"),
                "messages": messages
            })
예제 #5
0
    def fetch(payload: dict, user=None) -> RateResponse:
        request = purplship.Rating.fetch(RateRequest(**DP.to_dict(payload)))

        carrier_settings_list = [
            carrier.data for carrier in Carriers.list(carrier_ids=payload.get(
                'carrier_ids', []),
                                                      active=True,
                                                      user=user)
        ]
        gateways = [
            purplship.gateway[c.carrier_name].create(c.dict())
            for c in carrier_settings_list
        ]
        compatible_gateways = [
            g for g in gateways if 'get_rates' in g.features
        ]

        if len(compatible_gateways) == 0:
            raise NotFound("No configured and active carriers specified")

        # The request call is wrapped in identity to simplify mocking in tests
        rates, messages = identity(
            lambda: request.from_(*compatible_gateways).parse())

        if not any(rates) and any(messages):
            raise PurplShipApiException(
                detail=ErrorResponse(messages=messages),
                status_code=status.HTTP_400_BAD_REQUEST)

        def consolidate_rate(rate: Rate) -> Rate:
            carrier = next((c for c in carrier_settings_list
                            if c.carrier_id == rate.carrier_id))
            return Rate(
                **{
                    'id': f'rat_{uuid.uuid4().hex}',
                    'carrier_ref': carrier.id,
                    'test_mode': carrier.test,
                    **DP.to_dict(rate)
                })

        rates: List[Rate] = sorted(map(consolidate_rate, rates),
                                   key=lambda rate: rate.total_charge)

        return RateResponse(rates=sorted(rates,
                                         key=lambda rate: rate.total_charge),
                            messages=messages)
예제 #6
0
    def validate(payload: dict, carrier_filter: dict) -> AddressValidation:
        carrier = next(iter(Carriers.list(**(carrier_filter or {}))), None)

        if carrier is None:
            raise NotFound('No configured and active carrier found')

        request = purplship.Address.validate(
            AddressValidationRequest(**DP.to_dict(payload)))
        gateway = purplship.gateway[carrier.data.carrier_name].create(
            carrier.data.dict())

        # The request call is wrapped in identity to simplify mocking in tests
        validation, messages = identity(lambda: request.from_(gateway).parse())

        if validation is None:
            raise PurplShipApiException(
                detail=ErrorResponse(messages=messages),
                status_code=status.HTTP_400_BAD_REQUEST)

        return AddressValidation(validation=validation, messages=messages)