# Quotation

Quotations are purchase offers that occur after a basket submission. The user wants to create a quotation from the products in their basket and can create a new quotation by giving a name.

If the division of the user is main-division then the initial status of quotation will be set to pending status. If the division of the user is sub-division the initial status of quotation depends on `IS_SUB_DIVISION_QUOTATION_APPROVAL_REQUIRED` dynamic setting. If it is true the status will be set to request approval, if it is false the status will be set to pending status. The default value of this setting is true.

There is a hierarchy regarding updating the quotation. You can understand this structure better in the attached image.

## How to Manage Quotations?

There are 2 API services to manage quotations:

Via omnishop platform `/api/v1/my-quotations/` endpoint to manage operations for users to their own quotations. Via omnitron admin users can use `/api/v1/quotations/` endpoint to manage operations on all quotations.

Both parts perform similar operations. Let's consider both separately. First, let's look at the requests that are sent via commerce. Requests to the B2B project via Commerce are sent to `/api/v1/my-quotations/.`

### List Quotations

**Example Request**

```
curl --location 'http://{B2B_URL}/api/v1/my-quotations/' \
--header 'Authorization: Token {token}'
```

**Example Response (200 OK)**

```javascript
{
    "count": 1,
    "next": "",
    "previous": null,
    "results": [
        {
            "id": 89,
            "number": "351284518745",
            "total_amount": "69.97",
            "net_amount": "69.97",
            "name": "Test",
            "user": {
                "id": 268,
                "first_name": "first",
                "last_name": "last",
                "email": "akinon@akinon.com",
                "division": {
                    "id": 1,
                    "name": "Akinon Main Division",
                    "phone_number": "02123332211",
                    "erp_code": "AKI01"
                }
            },
            "created_at": "2023-11-30T13:34:44.520172Z",
            "modified_at": "2023-12-04T17:46:00.668207Z",
            "status": "cancelled"
        }
    ]
}
```

Users can filter quotations by name, user, status, total\_amount, created\_at, modified\_at, division and phone\_number. For example:

```
curl --location '{B2B_Backend_URL}/api/v1/my-quotations/?status=cancelled' \
--header 'Authorization: Token {token}'
```

### List Quotations Detail

There are eight different statuses for quotations. These are cancelled, request\_approval, pending, draft, sending\_approval\_request, approved, rejected and expired.

* Cancelled: The quotation has been canceled by the owner.
* Request Approval: Created by a sub-division, awaiting approval from the main division.
* Pending: Approved by the main division or created by a division, awaiting approval from the superuser.
* Draft: Used by the superuser to edit the quotation.
* Sending Approval Request: Utilized by the superuser to send the quotation to the owner for approval.
* Approved: Successfully approved by the superuser and is ready for ordering.
* Rejected: Rejected either by the superuser or the main division.
* Expired: The quotation has expired.

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/my-quotations/<quotation.id>/' \
--header 'Authorization: Token {token}'
```

**Example Response (200 OK)**

```json
{
    "id": 88,
    "number": "257932207177",
    "total_amount": "39.98",
    "net_amount": "39.98",
    "name": "segment quotation test",
    "user": {
        "id": 2,
        "first_name": "first",
        "last_name": "last",
        "email": "akinon@akinon.com",
        "division": {
            "id": 1,
            "name": "Akinon Main Division",
            "phone_number": "02123332211",
            "erp_code": "AKI01"
        }
    },
    "created_at": "2023-11-29T11:38:52.208717Z",
    "modified_at": "2023-11-29T11:39:09.283115Z",
    "status": "approved",
    "quotation_items": [
        {
            "product_remote_id": 1,
            "quantity": 2,
            "price": "19.99",
            "total_amount": "39.98",
            "product": {
                "sku": "dummy01",
                "name": "dummy",
                "price": "19.99",
                "asorti": "1573772",
                "category": "Şapka",
                "currency": "try",
                "variants": {},
                "product_image": "https://<address>/file.jpg"
            },
            "divisions": [
                {
                    "id": 1,
                    "name": "Akinon Main Division",
                    "address": "221B Baker Street, London center. k",
                    "erp_code": "AKI01",
                    "quantity": 2
                }
            ]
        }
    ],
    "discount": null,
    "expiration_date": "2023-12-14T11:38:52.208517Z",
    "segment_remote_id": 3,
    "comments": [
        {
            "id": 291,
            "user": {
                "id": 38,
                "first_name": "first",
                "last_name": "last",
                "email": "akinon@akinon.com",
                "division": {
                    "id": 1,
                    "name": "Akinon Main Division",
                    "phone_number": "02123332211",
                    "erp_code": "AKI01"
                }
            },
            "comment_type": "approval",
            "text": "it is ok.",
            "created_at": "2023-12-05T14:56:06.771530Z",
            "modified_at": "2023-12-05T14:56:06.771556Z"
        },
    ]
}
```

### Create Quotation

Before creating a quotation, users have to add products to their basket.

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/my-quotations/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Token {token}' \
--data '{
    "name": "Quotation 1"
}'
```

**Example Response (200 OK)**

```javascript
{
    "name": "Quotation 1"
}
```

### Cancel Quotation

After the create quotation users can cancel & reject their quotation from the my-quotations endpoint but can not approve. Because firstly, the quotation should be sent to the divisions for approval. Once the quotation is approved, it is sent back to the quotation owners for their approval. Following their approval, the quotation can then be converted into orders.

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/my-quotations/<quotation.id>/cancel/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Token {token}' \
--data '{
    "reason": "I dont want to do it"
}'
```

### Reject Quotation

In order to reject a quotation, you must be the owner of the quotation or be affiliated with the main-division.

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/my-quotations/<quotation.id>/reject/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Token {token}' \
--data '{
    "reason": "I dont want to do it"
}'
```

To see the comments of a quotation use the following API:

```
curl --location 'http://{B2B_Backend_URL}/api/v1/my-quotations/<quotation.id>/comments/' \
--header 'Authorization: Token {token}'
```

To Add comment for a quotation use the following API:

```
curl --location 'http://{B2B_Backend_URL}/api/v1/my-quotations/<quotation.id>/comments/' \
--header 'Authorization: Token {token}'
```

### Approve Pending Request Approval Quotation

Approve for Pending Quotation use the following API: Requests created by sub-division users wait as request\_approval before becoming requests as status. In this section, request\_approval is used to approve the pending requests and put them on pending. If the quotation's status is set to request\_approval and the creator user is affiliated with the main division, one can approve the quotation. If the quotation status is different or the user's division type is not main, the request will not be successful.

**Example Request**

```
curl --location --request POST '{B2B_Backend_URL}/api/v1/my-quotations/<quotation.id>/approve_pending/' \
--header 'Authorization: Token {token}'
```

### Approve Quotation

Requests created by the sub-division users pass to the "sending\_request\_approval" status after they are approved by the parent dealer. Here it waits for the bidder's approval.

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/my-quotations/<quotation.id>/approve/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Token {token}' \
--data '{
    "text": "ok"
}'
```

## Admin Operations on Quotations

### List Quotations

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/' \
--header 'Authorization: Token {token}'
```

Users can filter quotations by name, user, status, total\_amount, created\_at, modified\_at, division and phone\_number.

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/?number=593075984145' \
--header 'Authorization: Token {token}'
```

### List Quotations Detail

There are eight different statuses for quotations. These are cancelled, request\_approval, pending, draft, sending\_approval\_request, approved, rejected and expired.

* Cancelled: The quotation has been canceled by the owner.
* Request Approval: Created by a sub-division, awaiting approval from the main division.
* Pending: Approved by the main division or created by a division, awaiting approval from the superuser.
* Draft: Used by the superuser to edit the quotation.
* Sending Approval Request: Utilized by the superuser to send the quotation to the owner for approval.
* Approved: Successfully approved by the superuser and is ready for ordering.
* Rejected: Rejected either by the superuser or the main division.
* Expired: The quotation has expired.

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/' \
--header 'Authorization: Token {token}'
```

### List Quotation Comments

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/comments/' \
--header 'Authorization: Token {token}'
```

**Example Response (200 OK)**

```json
[
    {
        "id": 288,
        "user": {
            "id": 268,
            "first_name": "first",
            "last_name": "last",
            "email": "akinon@akinon.com",
            "division": {
                "id": 1,
                "name": "Akinon Main Division",
                "phone_number": "02123332211",
                "erp_code": "AKI01"
            }
        },
        "comment_type": "rejection",
        "text": "text for rejection",
        "created_at": "2023-12-05T11:55:54.175573Z",
        "modified_at": "2023-12-05T11:55:54.175593Z"
    }
]
```

### Add Product to Quotation

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/add_product_by_sku/' \
--header 'Authorization: Token {token}'
--header 'Content-Type: application/json' \
--data '{
    "division": 2,
    "quantity": 1,
    "sku": "dummy01"
}'
```

**Example Response (200 OK)**

```json
{
    "id": 76,
    "number": "63779097837",
    "total_amount": "389.83",
    "net_amount": "369.84",
    "name": "without segment id",
    "user": {
        "id": 38,
        "first_name": "first",
        "last_name": "last",
        "email": "akinon@akinon.com",
        "division": {
            "id": 1,
            "name": "Akinon Main Division",
            "phone_number": "02123332211",
            "erp_code": "AKI01"
        }
    },
    "created_at": "2023-11-22T07:23:10.979832Z",
    "modified_at": "2023-12-05T14:41:34.014032Z",
    "status": "draft",
    "quotation_items": [
        {
            "product_remote_id": 1,
            "quantity": 16,
            "price": "19.99",
            "total_amount": "319.84",
            "product": {
                "sku": "dummy01",
                "name": "dummy",
                "price": "19.99",
                "asorti": "1573772",
                "category": "Şapka",
                "currency": "try",
                "variants": {},
                "product_image": "https://file.jpg"
            },
            "divisions": [
                {
                    "id": 2,
                    "name": "SADA",
                    "address": "Sada",
                    "erp_code": "213213",
                    "quantity": 1
                },
                {
                    "id": 1,
                    "name": "Akinon Main Division",
                    "address": "221B Baker Street, London center. k",
                    "erp_code": "AKI01",
                    "quantity": 16
                }
            ]
        },
    ],
    "discount": null,
    "expiration_date": "2023-12-07T07:23:10.979628Z",
    "segment_remote_id": null
}
```

### Add Comments to Quotation

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/comments/' \
--header 'Authorization: Token {token}'
--header 'Content-Type: application/json' \
--data '{
    "text": "Comment 1"
}'
```

**Example Response (200 OK)**

```json
{
    "id": 290,
    "user": {
        "id": 38,
        "first_name": "first",
        "last_name": "last",
        "email": "akinon@akinon.com",
        "division": {
            "id": 1,
            "name": "Akinon Main Division",
            "phone_number": "02123332211",
            "erp_code": "AKI01"
        }
    },
    "comment_type": "conversation",
    "text": "Comment 1",
    "created_at": "2023-12-05T14:45:26.421232Z",
    "modified_at": "2023-12-05T14:45:26.421253Z"
}
```

### Create Discount for Quotation

There are two different discount types, percentage and fixed. percentage is used to define a 'percentage' discount on the price. Used 'fixed' when you want to apply a fixed price discount.

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/discount/' \
--header 'Authorization: Token {token}'
--header 'Content-Type: application/json' \
--data '{
    "value": "10",
    "discount_type": "percentage" # or "fixed"
}'
```

**Example Response (200 OK)**

```json
{
    "id": 298,
    "value": "10.00",
    "discount_type": "percentage",
    "discount_amount": "38.98",
    "net_amount": "350.85",
    "created_at": "2023-12-05T14:47:09.059855Z",
    "modified_at": "2023-12-05T14:47:09.059889Z"
}
```

### Delete Discount for Quotation

**Example Request**

```
curl --location --request DELETE '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/discount/' \
--header 'Authorization: Token {token}' \
--header 'Content-Type: application/json' \
--data '{
    "value": "12",
    "discount_type": "percentage"
}'
```

### Update Quotation

**Example Request**

```
curl --location --request PUT '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/' \
--header 'Authorization: Token {token}'\
--header 'Content-Type: application/json' \
--data '{
    "product_remote_id": 1,
    "division": 1,
    "quantity": 5
}'
```

**Example Response (200 OK)**

```json
{
    "id": 76,
    "number": "63779097837",
    "total_amount": "169.94",
    "net_amount": "169.94",
    "name": "without segment id",
    "user": {
        "id": 38,
        "first_name": "first",
        "last_name": "last",
        "email": "akinon@akinon.com",
        "division": {
            "id": 1,
            "name": "Akinon Main Division",
            "phone_number": "02123332211",
            "erp_code": "AKI01"
        }
    },
    "created_at": "2023-11-22T07:23:10.979832Z",
    "modified_at": "2023-12-05T14:53:29.425783Z",
    "status": "draft",
    "quotation_items": [
        {
            "product_remote_id": 1,
            "quantity": 1,
            "price": "19.99",
            "total_amount": "19.99",
            "product": {
                "sku": "dummy01",
                "name": "dummy",
                "price": "19.99",
                "category": "Şapka",
                "currency": "try",
                "variants": {},
                "base_code": "1573772",
                "product_image": "https://file.jpg"
            },
            "divisions": [
                {
                    "id": 2,
                    "name": "SADA",
                    "address": "ASDASDA asd as da sd as das asdS",
                    "erp_code": "213213",
                    "quantity": 1
                },
                {
                    "id": 1,
                    "name": "Akinon Main Division",
                    "address": "221B Baker Street, London center. k",
                    "erp_code": "AKI01",
                    "quantity": 5
                }
            ]
        }
    ],
    "discount": null,
    "expiration_date": "2023-12-07T07:23:10.979628Z",
    "segment_remote_id": null
}
```

### Set Quotation Status as Draft

**Example Request**

```
curl --location --request POST '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/draft/' \
--header 'Authorization: Token {token}'
```

### Approve Quotation

After the quotation is approved, orders are created on the b2b according to the division count in quotation and `B2B_BULK_PROCESSES_BATCH_SIZE` environment variable. Let's say that the quotation below is approved and `B2B_BULK_PROCESSES_BATCH_SIZE` value is 500.

| Product   | Division   | Quantity |
| --------- | ---------- | -------- |
| Product X | Division A | 600      |
| Product Y | Division A | 300      |
| Product X | Division B | 300      |

**Since the environment value of `B2B_BULK_PROCESSES_BATCH_SIZE` is 500, orders are divided into pieces of 500.**

Following orders will be created.

**Order 1:**\
Division A − Product X \* 500

**Order 2:**\
Division A − Product X \* 100 − Product Y \* 300

**Order 3:**\
Division B − Product X \* 300

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/approve/' \
--header 'Authorization: Token {token}'\
--header 'Content-Type: application/json' \
--data '{
    "text": "it is ok."
}'
```

**Example Response (200 OK)**

```json
{
    "id": 76,
    "number": "63779097837",
    "total_amount": "169.94",
    "net_amount": "169.94",
    "name": "without segment id",
    "user": {
        "id": 38,
        "first_name": "first",
        "last_name": "last",
        "email": "akinon@akinon.com",
        "division": {
            "id": 1,
            "name": "Akinon Main Division",
            "phone_number": "02123332211",
            "erp_code": "AKI01"
        }
    },
    "created_at": "2023-11-22T07:23:10.979832Z",
    "modified_at": "2023-12-05T14:56:06.694967Z",
    "status": "approved",
    "quotation_items": [
        {
            "product_remote_id": 1,
            "quantity": 5,
            "price": "19.99",
            "total_amount": "99.95",
            "product": {
                "sku": "dummy01",
                "name": "dummy",
                "price": "19.99",
                "asorti": "1573772",
                "category": "Şapka",
                "currency": "try",
                "variants": {},
                "product_image": "https://file.jpg"
            },
            "divisions": [
                {
                    "id": 2,
                    "name": "SADA",
                    "address": "ASDASDA asd as da sd as das asdS",
                    "erp_code": "213213",
                    "quantity": 1
                },
                {
                    "id": 1,
                    "name": "Akinon Main Division",
                    "address": "221B Baker Street, London center. k",
                    "erp_code": "AKI01",
                    "quantity": 5
                }
            ]
        }
    ],
    "discount": null,
    "expiration_date": "2023-12-07T07:23:10.979628Z",
    "segment_remote_id": null
}
```

### Get Quotation Orders

There are three status for orders. These are pending, created and failed. Once orders are created, they enter the "pending" status. This means that the Order is waiting to be created as an order on commerce. When the order is created on commerce, the status is updated to “created”. If an error occurs during this process, the "failed" status is used.

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/orders/' \
--header 'Authorization: Token {token}''
```

**Example Response (200 OK)**

```javascript
[
    {
        "id": 206,
        "remote_number": "2465661458111961",
        "division": {
            "id": 2,
            "name": "SADA",
            "phone_number": "05XXXXXXXXX",
            "erp_code": "213213"
        },
        "order_items": [
            {
                "id": 174,
                "product_remote_id": 1,
                "quantity": 1,
                "data": {
                    "sku": "dummy01",
                    "name": "dummy",
                    "price": "19.99",
                    "category": "Şapka",
                    "currency": "try",
                    "variants": {},
                    "base_code": "1573772",
                    "product_image": "https://file.jpg"
                },
                "created_at": "2023-12-05T14:56:06.716593Z",
                "modified_at": "2023-12-05T14:56:06.716606Z"
            }
        ],
        "expected_amount": "19.99",
        "expected_net_amount": "19.99",
        "discount_amount": "0.00",
        "created_at": "2023-12-05T14:56:06.713154Z",
        "modified_at": "2023-12-05T14:56:09.057338Z",
        "status": "created"
    }
]
```

### Reject Quotation

In order to reject a quotation, you must be the owner of the quotation or be affiliated with the main-division.

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/reject/' \
--header 'Authorization: Token {token}' \
--header 'Content-Type: application/json' \
--data '{
    "reason": "I don'\''t like it."
}'
```

### Send Approval Request to Quotation

**Example Request**

```
curl --location --request POST '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/send_approval_request/' \
--header 'Authorization: Token {token}''
```

### Trigger Order Creation

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/trigger_order_creation/' \
--header 'Authorization: Token {token}' \
--header 'Content-Type: application/json' \
--data '{
    "order": 76
}'
```

### Export Quotations (List)

Exports existing quotations together with their related order data based on the specified query parameters. Each quotation produces one row per related order; quotations that have no orders are exported as a single row with `order_remote_number` and `order_status` set to `null`. Filtering query parameters supported by the list endpoint (e.g. `status`, `number`, `created_at`) are honored to scope the export. Returns a cache key for status tracking.

**Request Parameters**

| Parameter          | Description                                                                                                                                                                                                                                               |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| fields             | Specifies the fields to be included in the export file. Available fields: **id, number, total\_amount, net\_amount, name, user, created\_at, modified\_at, status, order\_remote\_number, order\_status**. If omitted, all available fields are exported. |
| format             | Specifies the file format for the export. Acceptable values are `csv` and `xls`. The default is `xls`.                                                                                                                                                    |
| limit              | Limits the number of quotations to be exported.                                                                                                                                                                                                           |
| status\_cache\_key | A query parameter to track the status of the file export using the cache key returned from the initial request.                                                                                                                                           |

**Example Request**

```
curl --location --request GET '{B2B_Backend_URL}/api/v1/quotations/?fields=number&fields=status&fields=order_remote_number&fields=order_status' \
--header 'Authorization: Token {token}' \
--header 'Content-Type: application/json'
```

**Example Response (200 OK)**

```
{
"cache_key": "beacaa8ba65571e3840e28a11f17481e"
}
```

### Export Quotation Detail

Exports the quotation items of a single quotation. The request fields are merged with the fields defined in the `QUOTATION_ITEM_EXPORT_FIELDS` dynamic setting before building the file.

**Request Parameters**

| Parameter          | Description                                                                                                                                           |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| fields             | Specifies the fields to be included in the export file. Available fields: **product\_remote\_id, quantity, price, total\_amount, product, divisions** |
| format             | Specifies the file format for the export. Acceptable values are `csv` and `xls`. The default is `xls`.                                                |
| limit              | Limits the number of quotation items to be exported.                                                                                                  |
| status\_cache\_key | A query parameter to track the status of the file export using the cache key returned from the initial request.                                       |

**Example Request**

```
curl --location --request GET '{B2B_Backend_URL}/api/v1/quotations/<quotation.id>/?fields=product_remote_id&fields=quantity&fields=price' \
--header 'Authorization: Token {token}' \
--header 'Content-Type: application/json'
```

**Example Response (200 OK)**

```
{
"cache_key": "beacaa8ba65571e3840e28a11f17481e"
}
```

### Export File Status

Checks the status of an export file using the cache key obtained from either the list or detail export request. Provides information on whether the file is ready for download. Use the same endpoint (list or detail) that initiated the export.

**Example Request**

```
curl --location '{B2B_Backend_URL}/api/v1/quotations/?status_cache_key=beacaa8ba65571e3840e28a11f17481e' \
--header 'Authorization: Token {token}'
```

**Example Response**

```
{
  "is_ready": true,
  "url": "{url}/export_file/beacaa8ba65571e3840e28a11f17481e.xls",
  "status": "completed"
}
```

**Response Parameters**

| Field     | Description                                                                       |
| --------- | --------------------------------------------------------------------------------- |
| is\_ready | Indicates whether the file is ready for download (`true` or `false`).             |
| url       | The URL to download the exported file once it is ready.                           |
| status    | Provides the current status of the export process (e.g., `waiting,` `completed`). |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://apidocs.akinon.com/b2b/quotation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
