class DiscardCommodities(APIView): @swagger_auto_schema(tags=['Customs'], operation_id=f"{ENDPOINT_ID}discard_commodity", operation_summary="Discard a commodity", responses={ 200: Operation(), 400: ErrorResponse() }, code_examples=[{ 'lang': 'bash', 'source': ''' curl --request DELETE \\ --url /v1/customs_info/<CUSTOMS_INFO_ID>/commodities/<COMMODITY_ID> \\ --header 'Authorization: Token <API_KEY>' ''' }]) def delete(self, request: Request, pk: str, ck: str): """ Discard a customs commodity. """ customs = models.Customs.access_by(request).get(pk=pk) shipment = customs.shipment_set.first() if shipment is not None and shipment.status == ShipmentStatus.purchased.value: raise PurplShipApiException( "The shipment related to this customs info has been 'purchased' and cannot be modified", status_code=status.HTTP_409_CONFLICT, code='state_error') commodity = customs.commodities.get(pk=ck) commodity.delete(keep_parents=True) serializer = Operation( dict(operation="Discard customs commodity", success=True)) return Response(serializer.data)
def delete(self, request: Request, pk: str): """ Remove a webhook. """ webhook = models.Webhook.access_by(request).get(pk=pk) webhook.delete(keep_parents=True) serializer = Operation(dict(operation="Remove webhook", success=True)) return Response(serializer.data)
def post(self, request: Request, pk: str): """ test a webhook. """ webhook = models.Webhook.access_by(request).get(pk=pk) notification, *_ = notify_subscribers([webhook], request.data) _, response = notification serializer = Operation( dict(operation="Test Webhook", success=response.ok)) return Response(serializer.data)
def delete(self, request: Request, id_or_tracking_number: str): """ Discard a shipment tracker. """ tracker = models.Tracking.access_by(request).get( Q(pk=id_or_tracking_number) | Q(tracking_number=id_or_tracking_number)) tracker.delete(keep_parents=True) serializer = Operation( dict(operation="Discard a tracker", success=True)) return Response(serializer.data)
class WebhookDetail(APIView): @swagger_auto_schema(tags=['Webhooks'], operation_id=f"{ENDPOINT_ID}retrieve", operation_summary="Retrieve a webhook", responses={ 200: Webhook(), 400: ErrorResponse() }) def get(self, request: Request, pk: str): """ Retrieve a webhook. """ webhook = models.Webhook.access_by(request).get(pk=pk) return Response(Webhook(webhook).data) @swagger_auto_schema(tags=['Webhooks'], operation_id=f"{ENDPOINT_ID}update", operation_summary="Update a webhook", request_body=WebhookData(), responses={ 200: Webhook(), 400: ErrorResponse() }) def patch(self, request: Request, pk: str): """ update a webhook. """ webhook = models.Webhook.access_by(request).get(pk=pk) SerializerDecorator[WebhookSerializer](webhook, data=request.data).save() return Response(Webhook(webhook).data) @swagger_auto_schema(tags=['Webhooks'], operation_id=f"{ENDPOINT_ID}remove", operation_summary="Remove a webhook", responses={ 200: Operation(), 400: ErrorResponse() }) def delete(self, request: Request, pk: str): """ Remove a webhook. """ webhook = models.Webhook.access_by(request).get(pk=pk) webhook.delete(keep_parents=True) serializer = Operation(dict(operation="Remove webhook", success=True)) return Response(serializer.data)
def delete(self, request: Request, pk: str): """ Discard an address. """ address = models.Address.access_by(request).get(pk=pk) shipment = address.shipper.first() or address.recipient.first() if shipment is not None: raise PurplShipApiException( "This address is linked to a shipment and cannot be removed", status_code=status.HTTP_409_CONFLICT, code='state_error') address.delete(keep_parents=True) serializer = Operation(dict(operation="Discard address", success=True)) return Response(serializer.data)
class TrackersDetails(APIView): permission_classes = [IsAuthenticatedOrReadOnly] @swagger_auto_schema( tags=["Trackers"], operation_id=f"{ENDPOINT_ID}retrieves", operation_summary="Retrieves a shipment tracker", responses={ 200: TrackingStatus(), 404: ErrorResponse() }, ) def get(self, request: Request, id_or_tracking_number: str): """ Retrieve a shipment tracker """ __filter = Q(pk=id_or_tracking_number) | Q( tracking_number=id_or_tracking_number) trackers = models.Tracking.objects.filter(__filter) if len(trackers) == 0: models.Tracking.objects.get(__filter) return Response(TrackingStatus(trackers.first()).data) @swagger_auto_schema( tags=["Trackers"], operation_id=f"{ENDPOINT_ID}remove", operation_summary="Discard a shipment tracker", responses={ 200: Operation(), 400: ErrorResponse() }, ) def delete(self, request: Request, id_or_tracking_number: str): """ Discard a shipment tracker. """ tracker = models.Tracking.access_by(request).get( Q(pk=id_or_tracking_number) | Q(tracking_number=id_or_tracking_number)) tracker.delete(keep_parents=True) serializer = Operation( dict(operation="Discard a tracker", success=True)) return Response(serializer.data)
def delete(self, request: Request, pk: str, ck: str): """ Discard a customs commodity. """ customs = models.Customs.access_by(request).get(pk=pk) shipment = customs.shipment_set.first() if shipment is not None and shipment.status == ShipmentStatus.purchased.value: raise PurplShipApiException( "The shipment related to this customs info has been 'purchased' and cannot be modified", status_code=status.HTTP_409_CONFLICT, code='state_error') commodity = customs.commodities.get(pk=ck) commodity.delete(keep_parents=True) serializer = Operation( dict(operation="Discard customs commodity", success=True)) return Response(serializer.data)
class WebhookTest(APIView): @swagger_auto_schema(tags=['Webhooks'], operation_id=f"{ENDPOINT_ID}test", operation_summary="Test a webhook", request_body=WebhookTestRequest(), responses={ 200: Operation(), 400: ErrorResponse() }) def post(self, request: Request, pk: str): """ test a webhook. """ webhook = models.Webhook.access_by(request).get(pk=pk) notification, *_ = notify_subscribers([webhook], request.data) _, response = notification serializer = Operation( dict(operation="Test Webhook", success=response.ok)) return Response(serializer.data)
def delete(self, request: Request, pk: str): """ Remove a parcel. """ parcel = models.Parcel.access_by(request).get(pk=pk) shipment = parcel.shipment_parcels.first() if shipment is not None and ( shipment.status == ShipmentStatus.purchased.value or len(shipment.shipment_parcels.all()) == 1): raise PurplShipApiException( "A shipment attached to this parcel is purchased or has only one parcel. The parcel cannot be removed!", status_code=status.HTTP_409_CONFLICT, code='state_error') parcel.delete(keep_parents=True) shipment.shipment_parcels.set( shipment.shipment_parcels.exclude(id=parcel.id)) serializer = Operation(dict(operation="Remove parcel", success=True)) reset_related_shipment_rates(shipment) return Response(serializer.data)
class AddressDetail(APIView): @swagger_auto_schema(tags=['Addresses'], operation_id=f"{ENDPOINT_ID}retrieve", operation_summary="Retrieve an address", responses={ 200: Address(), 400: ErrorResponse() }, code_examples=[{ 'lang': 'bash', 'source': ''' curl --request GET \\ --url /v1/addresses/<ADDRESS_ID> \\ --header 'Authorization: Token <API_KEY>' ''' }]) def get(self, request: Request, pk: str): """ Retrieve an address. """ address = models.Address.access_by(request).get(pk=pk) return Response(Address(address).data) @swagger_auto_schema(tags=['Addresses'], operation_id=f"{ENDPOINT_ID}update", operation_summary="Update an address", request_body=AddressData(), responses={ 200: Address(), 400: ErrorResponse() }, code_examples=[{ 'lang': 'bash', 'source': ''' curl --request PATCH \\ --url /v1/addresses/<ADDRESS_ID> \\ --header 'Authorization: Token <API_KEY>' \\ --header 'Content-Type: application/json' \\ --data '{ "city": "Pierrefonds" }' ''' }]) def patch(self, request: Request, pk: str): """ update an address. """ address = models.Address.access_by(request).get(pk=pk) shipment = address.shipper.first() or address.recipient.first() if shipment is not None and shipment.status == ShipmentStatus.purchased.value: raise PurplShipApiException( "The shipment related to this address has been 'purchased' and can no longer be modified", status_code=status.HTTP_409_CONFLICT, code='state_error') SerializerDecorator[AddressSerializer](address, data=request.data).save() reset_related_shipment_rates(shipment) return Response(Address(address).data) @swagger_auto_schema(tags=['Addresses'], operation_id=f"{ENDPOINT_ID}discard", operation_summary="Discard an address", responses={ 200: Operation(), 400: ErrorResponse() }, code_examples=[{ 'lang': 'bash', 'source': ''' curl --request DELETE \\ --url /v1/addresses/<ADDRESS_ID> \\ --header 'Authorization: Token <API_KEY>' ''' }]) def delete(self, request: Request, pk: str): """ Discard an address. """ address = models.Address.access_by(request).get(pk=pk) shipment = address.shipper.first() or address.recipient.first() if shipment is not None: raise PurplShipApiException( "This address is linked to a shipment and cannot be removed", status_code=status.HTTP_409_CONFLICT, code='state_error') address.delete(keep_parents=True) serializer = Operation(dict(operation="Discard address", success=True)) return Response(serializer.data)
class ParcelDetail(APIView): @swagger_auto_schema(tags=['Parcels'], operation_id=f"{ENDPOINT_ID}retrieve", operation_summary="Retrieve a parcel", responses={ 200: Parcel(), 400: ErrorResponse() }, code_examples=[{ 'lang': 'bash', 'source': ''' curl --request GET \\ --url /v1/parcels/<PARCEL_ID> \\ --header 'Authorization: Token <API_KEY>' ''' }]) def get(self, request: Request, pk: str): """ Retrieve a parcel. """ address = models.Parcel.access_by(request).get(pk=pk) return Response(Parcel(address).data) @swagger_auto_schema(tags=['Parcels'], operation_id=f"{ENDPOINT_ID}update", operation_summary="Update a parcel", request_body=ParcelData(), responses={ 200: Parcel(), 400: ErrorResponse() }, code_examples=[{ 'lang': 'bash', 'source': ''' curl --request PATCH \\ --url /v1/parcels/<PARCEL_ID> \\ --header 'Authorization: Token <API_KEY>' \\ --header 'Content-Type: application/json' \\ --data '{ "weight": 1.2, }' ''' }]) def patch(self, request: Request, pk: str): """ modify an existing parcel's details. """ parcel = models.Parcel.access_by(request).get(pk=pk) shipment = parcel.shipment_parcels.first() if shipment is not None and shipment.status == ShipmentStatus.purchased.value: raise PurplShipApiException( "The shipment related to this parcel has been 'purchased' and can no longer be modified", status_code=status.HTTP_409_CONFLICT, code='state_error') SerializerDecorator[ParcelSerializer](parcel, data=request.data).save() reset_related_shipment_rates(shipment) return Response(Parcel(parcel).data) @swagger_auto_schema(tags=['Parcels'], operation_id=f"{ENDPOINT_ID}discard", operation_summary="Remove a parcel", responses={ 200: Operation(), 400: ErrorResponse() }, code_examples=[{ 'lang': 'bash', 'source': ''' curl --request DELETE \\ --url /v1/parcels/<PARCEL_ID> \\ --header 'Authorization: Token <API_KEY>' ''' }]) def delete(self, request: Request, pk: str): """ Remove a parcel. """ parcel = models.Parcel.access_by(request).get(pk=pk) shipment = parcel.shipment_parcels.first() if shipment is not None and ( shipment.status == ShipmentStatus.purchased.value or len(shipment.shipment_parcels.all()) == 1): raise PurplShipApiException( "A shipment attached to this parcel is purchased or has only one parcel. The parcel cannot be removed!", status_code=status.HTTP_409_CONFLICT, code='state_error') parcel.delete(keep_parents=True) shipment.shipment_parcels.set( shipment.shipment_parcels.exclude(id=parcel.id)) serializer = Operation(dict(operation="Remove parcel", success=True)) reset_related_shipment_rates(shipment) return Response(serializer.data)
class CustomsDetail(APIView): @swagger_auto_schema(tags=['Customs'], operation_id=f"{ENDPOINT_ID}retrieve", operation_summary="Retrieve a customs info", responses={ 200: Customs(), 400: ErrorResponse() }, code_examples=[{ 'lang': 'bash', 'source': ''' curl --request GET \\ --url /v1/customs_info/<CUSTOMS_INFO_ID> \\ --header 'Authorization: Token <API_KEY>' ''' }]) def get(self, request: Request, pk: str): """ Retrieve customs declaration. """ address = models.Customs.access_by(request).get(pk=pk) return Response(Customs(address).data) @swagger_auto_schema(tags=['Customs'], operation_id=f"{ENDPOINT_ID}update", operation_summary="Update a customs info", request_body=CustomsData(), responses={ 200: Customs(), 400: ErrorResponse() }, code_examples=[{ 'lang': 'bash', 'source': ''' curl --request PATCH \\ --url /v1/customs_info/<CUSTOMS_INFO_ID> \\ --header 'Authorization: Token <API_KEY>' \\ --header 'Content-Type: application/json' \\ --data '{ "content_type": "merchandise", "duty": { "paid_by": "recipient", "currency": "CAD", "declared_value": 100, } }' ''' }]) def patch(self, request: Request, pk: str): """ modify an existing customs declaration. """ customs = models.Customs.access_by(request).get(pk=pk) shipment = customs.shipment_set.first() if shipment is not None and shipment.status == ShipmentStatus.purchased.value: raise PurplShipApiException( "The shipment related to this customs info has been 'purchased' and can no longer be modified", status_code=status.HTTP_409_CONFLICT, code='state_error') SerializerDecorator[CustomsSerializer](customs, data=request.data, context=request).save() reset_related_shipment_rates(shipment) return Response(Customs(customs).data) @swagger_auto_schema(tags=['Customs'], operation_id=f"{ENDPOINT_ID}discard", operation_summary="Discard a customs info", responses={ 200: Operation(), 400: ErrorResponse() }, code_examples=[{ 'lang': 'bash', 'source': ''' curl --request DELETE \\ --url /v1/customs_info/<CUSTOMS_INFO_ID> \\ --header 'Authorization: Token <API_KEY>' ''' }]) def delete(self, request: Request, pk: str): """ Discard a customs declaration. """ customs = models.Customs.access_by(request).get(pk=pk) shipment = customs.shipment_set.first() if shipment is not None and shipment.status == ShipmentStatus.purchased.value: raise PurplShipApiException( "The shipment related to this customs info has been 'purchased' and cannot be discarded", status_code=status.HTTP_409_CONFLICT, code='state_error') customs.delete(keep_parents=True) shipment.customs = None serializer = Operation( dict(operation="Discard customs info", success=True)) reset_related_shipment_rates(shipment) return Response(serializer.data)