# Cancellations & Refunds

Orders/Orders/Order No: 123123123 should be canceled on the Omnitron’s left sidebar menu.

The detail page is reached by selecting the order to be processed as stated before. Cancellations related to the order can be made on the detail page.

<figure><img src="https://694447771-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVufPVrRNtGmK1TUsnRU3%2Fuploads%2F6CYdI039lrcosPPpQ4H9%2Fimage.png?alt=media&#x26;token=cce2628d-d8ad-41a2-8011-2ef1816f8397" alt=""><figcaption></figcaption></figure>

***

## Process

During the cancellation process, the `cancel_status` value of the order is checked. If the Cancel\_status field is `CancelStatus.approved`, an OrderUpdateCancelStatusException error will occur when trying to change it from this status to the CancelStatus.confirmed status. If the Cancel\_status field is CancelStatus.waiting\_for\_payment, trying to switch to the following statuses \[waiting,confirmation\_waiting,confirmed,approved,rejected] OrderUpdateCancelStatusException error will occur. If the value is `CancelStatus.waiting`, a `OrderCancelMoreThenOneException` is thrown. A check is performed to determine whether the `is_all` value is `True`, and the `cancel_items` array is full. A check is performed to determine whether the `is_cargo_refund` value is `True`, and the `cancel_items` or `is_all` value is `True`. In case of an error, an OrderCancelOverlappingParameterException is issued.

The canceled product objects are checked for value reasons. In case of an error, an OrderCancelMissingReasonException is issued.

The payment options of the order are checked. If the payment type is credit card, the payment transactions are checked and the order payment amount is calculated. If the payment type is not a credit card, the order amount is taken from the order object. If the Payment\_option field is PaymentType.credit\_card, a payment record is expected. If not, an OrderCancelPurchaseTransactionNotFound error occurs. If the refund amount is less than 0, an OrderCancelNoRefundableAmountException error occurs. If the Payment\_option field is PaymentType.pay\_on\_delivery, the products in the order are checked. If there are order items belonging to different statuses, an OrderCancelMultipleItemStatusException error occurs. Forced\_refund control is performed on order items. If this field is active, forced\_refund\_amount is expected to be delivered, OrderCancelManuallyException error occurs in undelivered transactions.

An OrderCancelMoreThenOneException error occurs if there is a product with the status CancelStatus.waiting, CancelStatus.approved or CancelStatus.manuel\_refund\_need among the order items.

OrderCancelItemsIsNotConsistent error occurs when order items that are to be canceled are delivered, and an item that does not exist on the order is transmitted.

OrderCancelItemMultipleDataSourcesFoundException error occurs when order items have more than one supplier.

​​Cancellation or refund can be made at the same time during the transaction. In this case, requests must be submitted separately. If they are submitted together, a CancelOrderItemMixedException error occurs.

The `can_be_sent_to_erp` value is checked for status approval during the order process.

The payment options of the order are checked. If the payment type is credit card, the payment transactions are checked and the order payment amount is calculated. If the payment type is not a credit card, the order amount is taken from the order object.

If the cancel\_status of the products in the order is \[CancelStatus.waiting,CancelStatus approved or CancelStatus.manuel\_refund\_need], an `OrderCancelMoreThenOneException` is sent.

If the order contains an invoice\_number, the `cancellation_type` will be a refund; if not, it will be cancellation.

If there is a `forced_refund_amount`, the refund is made with the `forced_refund_amount value`. If not, it is calculated with the `calculate_refund` function according to the strategy selected in the settings.

The `CancellationPlan` object is created depending on the order status. If the created `CancellationPlan` status is `confirmation_waiting`, the order cancellation process is completed with the use of the approve or reject buttons on the Front-End.

If the orders are linked to customers" ERP systems, approval is assessed using the `approved_order_cancel` function to obtain approval from the ERP system, and the process is completed by changing the cancellation status of the order.

***

## Statuses

The statuses for the stages of the order cancellation process are provided below.

**omnicore.orders.enums.CancelStatus**

The values ​​that the cancel\_status field that the order can take. Indicates at what stage the cancellation process is on the order.

* waiting,
* confirmation\_waiting,
* confirmed, approved,
* rejected,
* waiting\_for\_payment,
* manuel\_refund\_need,
* completed

**omnicore.orders.enums.CancellationType**

Indicates whether the operation is canceled or refunded on CancellationRequest.

* cancel
* refund

**omnicore.orders.enums.CancellationRequestStatus**

Indicates the stage of the CancellationRequest values ​​that occur with the cancellation request.

* OPEN,
* WAITING,
* CONFIRMATION\_WAITING,
* CONFIRMED,
* WAITING\_APPROVAL,
* APPROVED,
* REJECTED,
* WAITING\_FOR\_PAYMENT,
* MANUEL\_REFUND\_NEED,
* COMPLETED

**omnicore.orders.enums.OrderStatus**

It is stored in the status field on the order and indicates the current stage.

* cancellation\_waiting,
* cancelled, waiting,
* payment\_waiting,
* confirmation\_waiting,
* approved, preparing,
* shipped,
* shipped\_and\_informed,
* ready\_for\_pickup,
* attempted\_delivery,
* review\_started,
* review\_waiting,
* delivered,
* refunded

***

## `POST` Create Cancellation Request

Path: `/api/v1/orders/{order_pk}/cancel/`

```json
{
"order": "<order_pk>",
"is_all": false,
"reasons": {'35': 1},
"forced_refund_amount": "13,12",
"cancel_items": [35,12],
"refund_invoice_number":"123213",
"is_cargo_refund":false,
"retail_store_remote_id":"12",
"staff_remote_id":"1",
"return_details":false
}

```

**Response / 200**

```json
return_details == False     
    {"success": True}      

return_details == True      
    OrderDetailedSerializer.data

```

**Response / 400**

```json
{"order": [u"Invalid pk "123" – object does not exist."]}       
```

**Response / 406**

```json
     {"non_field_errors": u"Order cancel is not valid", "error_code": u"cancel_100"}
```

**Viewset**

Employs the cancel method of the omnitron.orders.resources.views.OrderViewSet Class. With the request, this part is triggered and the cancellation process of the order will start.

**Service**

Employs the cancel method of the omnitron.orders.service.OrderService Class. When the cancellation request is sent, the process will be transmitted with the following service. The parameters received by the service and the return value are listed.

Service name: cancel\_order

Received parameters :

* order
* reasons
* is\_all
* cancel\_items
* forced\_refund\_amount
* is\_cargo\_refund
* refund\_invoice\_number
* next\_status
* ibans
* holder\_names

Return value: Order

**Used Methods**

```
CancellationStrategy
omnitron.orders.service.OrderService._create_cancellation_request
omnitron.orders.service.OrderService._validate_cancellation_info
omnitron.orders.service.OrderService._create_cancellation_plan
omnitron.orders.service.OrderService.approved_order_cancel
```

**Strategy**

During the cancellation process of the order, the `CANCELLATION_STRATEGY` variable in the settings.py file defines the strategies from StrategyOne to StrategyEleven in the strategy.py file on a company basis. Strategy classes are essentially derived from the `omnitron.orders.strategies.CancellationStrategy` class.

\<img src={image2} width="460" style={{'borderRadius':'10px'}}/>

**Serializer**

OrderCancelSerializer: Controls the parameters and structures that can make the request thrown to initiate the cancellation process.

| **Name**                | **Description**                                                                                                                                           |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| order                   | Orders with statuses other than \[cancelled, refunded, cancellation\_waiting]                                                                             |
| is\_all                 | <ul><li>boolean</li><li>Default:False</li><li>Used to cancel all products.</li><li>If {`true`}, the cancel\_items value must be an empty array.</li></ul> |
| cancel\_items           | The order\_item list to be canceled.                                                                                                                      |
| forced\_refund\_amount  | <ul><li>Decimal</li><li>allow\_null=True</li><li>The field {`for`} entering the refund amount optionally</li></ul>                                        |
| reasons                 | <ul><li>DictField</li><li>{`{order_item_id : CancellationReason}`}</li><li>Cancellation reason</li></ul>                                                  |
| is\_cargo\_refund       | <ul><li>boolean</li><li>required=False</li><li>Cargo refund</li></ul>                                                                                     |
| refund\_invoice\_number | <ul><li>CharField</li><li>required=False, default=None</li><li>Refund invoice number</li></ul>                                                            |
| ibans                   | <ul><li>DictField</li><li>required=False</li></ul>                                                                                                        |
| holder\_name            | <ul><li>DictField</li><li>required=False</li></ul>                                                                                                        |

## `POST` Reject Cancellation Request

Path: `/api/v1/orders/{order_pk}/cancellation_reject_order/`

The method that permits the rejection of the order cancellation process.

**Response / 200**

```
  OrderDetailedSerializer.data
```

**Response / 404**

```
{
    "detail": "Not found."
}
```

**Service**

reject\_order\_cancel method of the omnitron.orders.service.OrderService class is used.

Service name: reject\_order\_cancel

Received parameter: order

Return Value: order

**Used Methods**

```
omnitron.orders.service.OrderService._update_cancellation_request
omnitron.orders.service.OrderService.update_cancellation_plan
```

## `POST` Approve Cancellation Request

Path:`/api/v1/orders/{order_pk}/cancellation_approved_order/`

The method that permits the approval of the order cancellation process.

```json
{
"invoice_number":"1321213123"
}
```

**Response / 200**

```
OrderDetailedSerializer.data
```

**Service**

`approved_order_cancel` method of the omnitron.orders.service.OrderService class is used.

Service name: approved\_order\_cancel

Received parameters:

* order
* invoice\_number
* payment\_plan

Return value: order

**Used Methods**

```
omnitron.orders.service.OrderService._update_cancellation_request
omnitron.orders.service.OrderService.update_cancellation_plan
```

**Serializer**

Controls the parameters and structures of the requester thrown to confirm the cancellation.

`omnitron.orders.resources.serializers.CancellationApprovedOrderSerializer`

* invoice\_number:
  * CharField
  * Default: None
  * Invoice number
* payment\_plan
  * JsonField
  * required=False

## Cancellation Status

It is used to update the cancel\_status fields of orders and order items whose cancellation process has been initiated.

### `POST` Update Cancellation Status

Path: `/api/v1/orders/{order_pk}/update_cancel_status/`

**Request**

```json
{
"cancel_status": "manuel_refund_need",
"order": 45,
"order_items": [118]
}
```

**Response / 200**

```
OrderDetailedSerializer.data
```

**Serializer**

CancelStatusUpdateSerializer: Controls the requesting parameters and structures to update status on cancellation.

* order:
  * Order
* order\_items:
  * ListField
  * required=False
  * OrderItem
* cancel\_status:
  * omnicore.orders.enums.CancelStatus (Values ​​in the Status section)

## Cancellation Requests

The method that permits the creation of cancellation requests. Used for the products in the order. `GET`, `POST`, `PUT` and `DELETE` features are used.

### `GET` Cancellation Requests

Path: `/api/v1/cancellation_requests/`

**Response**

```json
{
    "count": 13,
    "next": "{customer_omnitron_url}/api/v1/cancellation_requests/?page=4",
    "previous": "{customer_omnitron_url}/api/v1/cancellation_requests/?page=2",
    "results": [
        {
            "id": 5,
            "cancellation_type": "refund",
            "status": "open",
            "easy_return": 1,
            "created_date": "2021-06-03T07:25:24.520026Z",
            "modified_date": "2021-06-03T07:25:24.520106Z",
            "uuid": "abcacaec-9644-408b-9b45-ce96847a5d90",
            "description": "Description",
            "iban": "TRXXXXX10009999901234567890",
            "holder_name": "Courier Company Name",
            "reason": 2,
            "order_item": 416
           },..]
}

```

### `GET` Cancellation Request Detail

Path: `/api/v1/cancellation_requests/{id}/`

**Response**

```json
{
  "id": 5,
  "cancellation_type": "refund",
  "status": "open",
  "easy_return": "1",
  "created_date": "2021-06-03T07:25:24.520026Z",
  "modified_date": "2021-06-03T07:25:24.520106Z",
  "uuid": "abcacaec-9644-408b-9b45-ce96847a5d90",
  "description": "Description",
  "iban": "TR320010009999901234567890",
  "holder_name": "Courier Company Name",
  "reason": 2,
  "order_item": 416
}
```

### `PUT` Update Cancellation Request

Path: `/api/v1/cancellation_requests/{id}/`

```json
{
    "id": 5,
    "cancellation_type": "refund",
    "status": "open",
    "easy_return": 1,
    "created_date": "2021-06-03T07:25:24.520026Z",
    "modified_date": "2021-06-03T07:25:24.520106Z",
    "uuid": "abcacaec-9644-408b-9b45-ce96847a5d90",
    "description": "Description",
    "iban": "TR320010009999901234567890",
    "holder_name": "Courier Company Name",
    "reason":1,
    "order_item": 416
}
```

**Response**

```json
{
    "id": 5,
    "cancellation_type": "refund",
    "status": "open",
    "easy_return": 1,
    "created_date": "2021-06-03T07:25:24.520026Z",
    "modified_date": "2021-06-03T07:25:24.520106Z",
    "uuid": "abcacaec-9644-408b-9b45-ce96847a5d90",
    "description": "Description",
    "iban": "TR320010009999901234567890",
    "holder_name": "Courier Company Name",
    "reason": 1,
    "order_item": 416
}
```

### `POST` Create Cancellation Request

Path: `/api/v1/cancellation_requests/`

```json
{
  "order_item": 116,
  "cancellation_type": "refund",
  "reason": 1
}
```

**Response**

```
HTTP200
```

### `DELETE` Cancellation Request

Path: `/api/v1/cancellation_requests/{id}/`

**Response**

```
HTTP204
```

**Viewset**

Uses the omnitron.orders.resources.views.CancellationRequestViewSet class. ViewSet handles requests for CancellationRequest transactions. After the controls are made, the service is triggered to perform the transaction.

**Serializer**

`omnitron.orders.resources.serializers.CancellationRequestSerializer`

Controls the parameters and their structures in requests to the Viewset.

| **Name**             | **Description**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Id =                 | IntegerField(label="ID", read\_only=True)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| cancellation\_type = | EnumField(enum\_type=\<enum "CancellationType">)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| status =             | EnumField(enum\_type=\<enum "CancellationRequestStatus">, read\_only=True)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| easy\_return =       | <ul><li>CancellationEasyReturnSerializer(read\_only=True): Easy cancellation model</li><li>id = IntegerField(label="ID", read\_only=True)</li><li>status = EnumField(enum\_type=\<enum "CancellationEasyReturnStatus">, read\_only=True)</li><li>shipping\_company = EnumField(enum\_type=\<enum "ShippingCompany">, read\_only=True)</li><li>created\_date = DateTimeField(read\_only=True)</li><li>modified\_date = DateTimeField(read\_only=True)</li><li>uuid = UUIDField(required=False, validators=\[\<UniqueValidator(queryset=CancellationEasyReturn.objects.all())>])</li><li>code = CharField(max\_length=64, validators=\[\<UniqueValidator(queryset=CancellationEasyReturn.objects.all())>])</li><li>start\_date = DateTimeField(allow\_null=True, required=False)</li><li>end\_date = DateTimeField(allow\_null=True, required=False)</li><li>max\_count = IntegerField(allow\_null=True, max\_value=2147483647, min\_value=0, required=False)</li><li>raw\_request = CharField(style={`{"base_template": "textarea.html"}`})</li><li>raw\_response = CharField(style={`{"base_template": "textarea.html"}`})</li></ul> |
| created\_date =      | DateTimeField(read\_only=True)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| modified\_date =     | DateTimeField(read\_only=True)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| uuid =               | UUIDField(required=False, validators=\[\<UniqueValidator(queryset=CancellationRequest.objects.all())>])                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| description =        | CharField(allow\_blank=True, allow\_null=True, required=False, style={\`{"base\_template": "textarea.html"}\`})                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| iban =               | CharField(allow\_blank=True, allow\_null=True, max\_length=34, required=False)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| holder\_name =       | CharField(allow\_blank=True, allow\_null=True, max\_length=255, required=False)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| reason =             | PrimaryKeyRelatedField(queryset=CancellationReason.objects.all())                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| order\_item =        | PrimaryKeyRelatedField(queryset=OrderItem.objects.all(), validators=\[\<UniqueValidator(queryset=CancellationRequest.objects.all())>])                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |

**Service**

`omnitron.orders.service CancellationRequestApprovalService.create_cancellation_request` method is used.

Service name: create\_cancellation\_request

Received parameters:

* order\_item
* cancellation\_type
* reason
* iban
* holder\_name
* description

Return value: cancellation\_request

## Cancellation Reasons

The class for CREATING, UPDATING and DELETING the selected cancellation reasons during the cancellation process.

### `GET` Cancellation Reasons

Path: `/api/v1/cancellation_reasons/`

**Response**

```json
{
    "count": 11,
    "next": "{customer_omnitron_url}/api/v1/cancellation_reasons/?page=4",
    "previous": "{customer_omnitron_url}/api/v1/cancellation_reasons/?page=2",
    "results": [
        {
            "pk": 1,
            "cancellation_type": "cancel",
            "extra_information_needed": false,
            "order": 100,
            "subject": "I bought wrong product.",
            "is_active": true,
            "send_to_remote": false
        },…]
}
```

### `POST` Create Cancellation Reason

Path: `/api/v1/cancellation_reasons/`

```json
{
    "cancellation_type": "refund",
    "extra_information_needed": true,
    "order": 100,
    "subject": "Cancellation Reason",
    "is_active": true,
    "send_to_remote": false
}
```

**Response**

```json
{
    "pk": 11,
    "cancellation_type": "refund",
    "extra_information_needed": true,
    "order": 100,
    "subject": "Cancellation Reason",
    "is_active": true,
    "send_to_remote": false
}
```

### `PUT` Update Cancellation Reason

Path: `/api/v1/cancellation_reasons/{id}/`

```json
{
    "cancellation_type": "refund",
    "extra_information_needed": true,
    "order": 100,
    "subject": "Another Cancellation Reason",
    "is_active": true,
    "send_to_remote": false
}
```

**Response**

```json
{
    "pk": 11,
    "cancellation_type": "refund",
    "extra_information_needed": true,
    "order": 100,
    "subject": "Another Cancellation Reason",
    "is_active": true,
    "send_to_remote": false
}
```

### `DELETE` Cancellation Reason

Path: `/api/v1/cancellation_reasons/{id}/`

**Response**

```
HTTP204
```

**Viewset**

Uses the omnitron.orders.resources.views.CancellationReasonViewSet class. ViewSet meets requests for cancellation responses. After the controls are made, the service is triggered to perform the transaction.

**Serializer**

omnitron.orders.resources.serializers.CancellationReasonSerializer: Controls the parameters and their structures in requests to the ViewSet.

| **Name**                     | **Description**                                                   |
| ---------------------------- | ----------------------------------------------------------------- |
| pk =                         | IntegerField(label="ID", read\_only=True)                         |
| cancellation\_type =         | EnumField(enum\_type=\<enum "CancellationType">)                  |
| extra\_information\_needed = | BooleanField(required=False)                                      |
| order =                      | IntegerField(max\_value=2147483647, min\_value=0, required=False) |
| subject =                    | CharField(max\_length=100)                                        |
| is\_active =                 | BooleanField(required=False)                                      |
| send\_to\_remote =           | BooleanField(required=False)                                      |

**Service**

The omnitron.orders.service.CancellationReasonService class is derived from the omnicore.orders.service.BaseCancellationReasonService class. Adding, deleting and updating transactions are done through the Services.

Service name: create\_cancellation\_reason

Received parameters:

* subject
* cancellation\_type
* extra\_information\_needed(default=False)
* order(default=100)

Return value: CancellationReason

Service name: update\_cancellation\_reason

Received parameters:

* instance
* subject(default=None)

Return value: instance

Service name: delete\_cancellation\_reason

Received parameters: instance

## Cancellation Plans

The cancellation\_plan is created when the cancellation process is started for the order. It is used to update the status of the CancellationPlan record.

### `GET` Cancellation Plan Statuses

Path: `/api/v1/cancellation_plans/cancellation_plan_statuses/`

**Response**

```json
{
    "cancellation_plan_statuses": {
        "confirmed": "Confirmed",
        "manuel_refund_need": "Manuel Refund Need",
        "completed": "Completed",
        "confirmation_waiting": "Confirmation Waiting",
        "rejected": "Rejected",
        "failed": "Failed",
        "waiting": "Waiting",
        "cancelled": "Cancelled",
        "waiting_for_payment": "Waiting For Payment",
        "approved": "Approved"
    }
}
```

### `POST` Update Cancellation Plan Status

Path: `/api/v1/cancellation_plans/{pk}/update_status/`

```json
{
    "order":32,
    "status": "waiting"
}
```

**Response**

```
HTTP200
```

**Viewset**

Uses the omnitron.orders.resources.views.CancellationPlanViewSet class. Derived from rest\_framework.viewsets.ReadOnlyModelViewSet and omnitron.channels.resources.views.IntegrationMappingMixin classes.

CancellationPlan records allow services to be triggered by responding to status update or current status requests.

**Serializer**

omnitron.orders.resources.serializers.CancellationPlanSerializer: Controls parameters and structures in delivered requests.

| **Name**                         | **Description**                                                  |
| -------------------------------- | ---------------------------------------------------------------- |
| order =                          | OrderSerializer()                                                |
| order\_previous\_status =        | EnumField(enum\_type=OrderStatus)                                |
| status =                         | EnumField(enum\_type=CancellationPlanStatus)                     |
| plan\_type =                     | EnumField(enum\_type=CancellationPlanType)                       |
| cancellationplanorderitem\_set = | CancellationPlanOrderItemSerializer( many=True, read\_only=True) |
| invoice\_number =                | serializers.CharField(required=False)                            |
| created\_by =                    | UserSerializer()                                                 |
| last\_updated\_by =              | serializers.SerializerMethodField()                              |

**Service**

Uses the omnitron.orders.service.CancellationPlanService class. Contains the status update service triggered by the View.

Service name: update\_status

Received parameters:

* instance
* Status

Return value: instance
