# Pre-Product

Within the pre-product domain, two distinct product types will be taken into consideration: **Pre-Product** and **Pre-Miscellaneous**.

The products integrated into the system undergo serialization using the `PreProductViewSet` before being inserted into the product table. During this insertion process, they are assigned either the values of `ProductTypes.pre_product` or `ProductTypes.pre_miscellaneous` for the `Products.product_type` parameter.

A signal is generated with every commit made to the Product table, and these signals are monitored by the `product_receiver {omnitron.products.receivers.product_receiver()}`. This receiver disregards commits with product types `pre_product` and `pre_miscellaneous`.

After every product commit that comes before actualization, it will be updated with `PreProductViewSet`, and during the update process, it will be actualized based on the value of `approved=True`.

**pre\_product​**

It is a simple product that comes before productization. When productized, it will take the value `ProductTypes.simple` as the `product_type`.

**pre\_miscellaneous​**

It is a non-saleable product that comes before productization. When productized, it will take the value `ProductTypes.miscellaneous` as the `product_type`. Non-saleable products can be found in the cart, but their direct sales are prohibited (for example, shopping bags).

## <mark style="color:red;">Serializer​</mark> <a href="#serializer" id="serializer"></a>

The `PreProductSerializer {omnitron.products.resources.serializers.PreProductSerializer}` extends the `ProductSerializer`, but it includes additional fields that are different from the `ProductSerializer` and are not present in the model: `approved:BooleanField` and `run_product_mapping:NullBooleanField`.

**approved: BooleanField​**

When this boolean field is true, the `ProductService._approve_pre_product()` method will be invoked during the update process to productize pre-products.

**run\_product\_mapping: NullBooleanField**[**​**](broken://pages/n1RuTBxyllethNor0GLO)

This boolean field is nullable. When it is true, the `ProductService._run_product_mapping()` method will be called during the update process to perform attribute mapping for products.

## Mapping​ <a href="#mapping" id="mapping"></a>

During the creation or update of pre-products, if `run_product_mapping` is set to True, they undergo a mapping process. The mapping process depends on the key values defined in `settings.PRODUCT_MAPPING_KEY_LIST` and the `language` value sent as kwargs during the update process or obtained from `translation.get_language() {django.utils.translation.get_language()}`.

Here's a pseudo example we can create for the mapping process:

```python
settings:
    PRODUCT_MAPPING_KEY_LIST=['size']
    LANGUAGE_CODE='tr-tr'
    LANGUAGES=[('tr-tr', 'Turkish'), ('en-us', 'English')]

script:
    attribute_old = Attribute(
        key=”size_erp”,
        is_localizable=True,
        pre_attribute=True)
    attribute_new = Attribute(
        key=”size”,
        is_localizable=True,
        pre_attribute=False)

    // Let's assume a pre-defined mapping.
    // Mapping(mapping_key=”size”,
    //      input_kwargs={“attributes__size_erp__isnull”: False})
    
    product.set_attribute(
            key=”size_erp”,
            value=”Large”,
            language=”en-us”)
    product.set_attribute(
            key=”size”,
            value=”Büyük”,
            language=”tr-tr”)
    ProductService._run_product_mapping(product, language=”tr-tr”)
```

The attribute key named `size_erp` of our product has been converted to the `size` key through mapping, and its value has been mapped from "Large" to "Büyük".

## Service​ <a href="#service" id="service"></a>

There is no separate service for pre-products; instead, all service operations are conducted through the `ProductService {omnitron.products.service.ProductService}`. The service structure will be detailed in the product documentation.

## <mark style="color:red;">ViewSet</mark>​ <a href="#viewset" id="viewset"></a>

The `PreProductViewSet {omnitron.products.resources.views.PreProductViewSet}` is extended from `ModelViewSet`, `MultiSerializerViewSetMixin`, and `FileFilterableViewSetMixin`, and it can be accessed via the `/api/v1/pre_products` endpoint.

Inherited from `ModelViewSet`, it allows `GET`, `POST`, `PUT`, `PATCH`, and `DELETE` methods. The `perform_create()` and `perform_update()` functions are overridden to perform create/update operations on the relevant service, `ProductService`.

Inherited from `MultiSerializerViewSetMixin`, it includes the `detailed()` and `detailed_list()` functions but does not override them. Within the `serializer_action_classes`, `ProductDetailedSerializer` is defined for both `detailed` and `detailed_list`.

Inherited from `FileFilterableViewSetMixin`, it includes the `filter_queryset()`, `filter_import_queryset()`, and `initialize_request()` functions but does not override them. It holds the `file_filter_fieldname:List` list, which is used to intersect with the header fields of uploaded files in `FileFilterableViewSetMixin`.

### <mark style="color:red;">HTTP Methods​</mark> <a href="#http-methods" id="http-methods"></a>

### `GET` Get List of All Pre-Products​ <a href="#get-get-list-of-all-pre-products" id="get-get-list-of-all-pre-products"></a>

**Path:** `/api/v1/pre_products/`

This method retrieves the products that fulfil the condition `product_type__in=[ProductTypes.pre_product, ProductTypes.pre_miscellaneous]` from the Product table. It takes filter parameters found in ProductFilter `{omnitron.products.resources.filters.ProductFilter}` as query parameters and has a wide range of filtering options.

**Example Request​**

```
api/v1/pre_products/?is_active=True&attributes__renk=ANTRASIT
```

**Example Response​**

```json
HTTP200
[
    {
        "pk": 402,
        "name": "Banyo Halısı Desen 3 60x100+50x60cm",
        "base_code": "1KBAPA0195",
        "sku": "2672880315949",
        "product_type": "-1",
        "is_active": true,
        "parent": null,
        "attributes": {
            "erp_ProductAtt06Desc": "(60X100)+(50X60)",
            "integration_ProductAtt12Desc": "%50 + %20 PROMOSYON",
            "erp_ProductAtt12Desc": "%50 + %20 PROMOSYON",
            "uretim_yeri": "ÇİN",
            "renk": "ANTRASİT",
            "integration_ProductAtt03Desc": "2011/2012 KIŞ",
            "erp_ProductAtt07Desc": "50+50 promosyon",
            "erp_color": "ANTRASİT",
            "materyal": "%100 POLYESTER",
            "integration_ProductAtt22Desc": "5,50 x 9,00 cm",
            "integration_ProductAtt14Desc": "60X100+50X60 CM MAKİNE KESMESİ",
            "erp_ProductHierarchyLevel01": "TEKSTİL",
            "erp_ProductAtt13Desc": "YER GRUBU %50+%50",
            "integration_ProductAtt05Desc": "%50+%20 OUTLET PROMOSYONU",
            "erp_ProductAtt09Desc": "Flannel Baby Touch Machine",
            "erp_ProductAtt02Desc": "Yer Grubu - Paspas",
            "integration_ProductAtt15Desc": "%50+%50 PROMOSYON",
            "erp_ProductAtt20Desc": "%100 POLYESTER",
            "filtre_renk1": "Gri",
            "erp_ProductAtt22Desc": "5,50 x 9,00 cm",
            "erp_ProductAtt15Desc": "%50+%50 PROMOSYON",
            "erp_ProductCode": "1KBAPA0195244",
            "integration_ProductAtt13Desc": "YER GRUBU %50+%50",
            "integration_ProductAtt01Desc": "DIŞ ALIM",
            "erp_ProductAtt05Desc": "%50+%20 OUTLET PROMOSYONU",
            "boyut": "(60X100)+(50X60)",
            "erp_ProductAtt14Desc": "60X100+50X60 CM MAKİNE KESMESİ",
            "erp_ProductAtt01Desc": "DIŞ ALIM",
            "erp_ProductHierarchyLevel02": "Yer Grubu",
            "integration_ProductCode": "1KBAPA0195244",
            "integration_ProductAtt07Desc": "50+50 promosyon",
            "erp_ProductAtt03Desc": "2011/2012 KIŞ",
            "integration_ProductAtt09Desc": "Flannel Baby Touch Machine",
            "integration_ProductHierarchyLevel01": "TEKSTİL",
            "integration_ProductHierarchyLevel02": "Yer Grubu",
            "erp_ProductAtt25Desc": "ÇİN",
            "integration_ProductAtt02Desc": "Yer Grubu - Paspas"
        },
        "attributes_kwargs": {
            "erp_ProductHierarchyLevel01": {
                "value": "TEKSTİL",
                "data_type": "dropdown",
                "label": "TEKSTİL"
            },
            "erp_ProductHierarchyLevel02": {
                "value": "Yer Grubu",
                "data_type": "dropdown",
                "label": "Yer Grubu"
            },
            "filtre_renk1": {
                "value": "Gri",
                "data_type": "dropdown",
                "label": "Gri"
            },
            "erp_color": {
                "value": "ANTRASİT",
                "data_type": "dropdown",
                "label": "ANTRASİT"
            },
            "integration_ProductHierarchyLevel01": {
                "value": "TEKSTİL",
                "data_type": "dropdown",
                "label": "TEKSTİL"
            },
            "integration_ProductHierarchyLevel02": {
                "value": "Yer Grubu",
                "data_type": "dropdown",
                "label": "Yer Grubu"
            },
            "renk": {
                "value": "ANTRASİT",
                "data_type": "dropdown",
                "label": "ANTRASİT"
            }
        },
        "extra_attributes": {},
        "group_products": [],
        "productimage_set": [{
                "pk": 592,
                "status": "active",
                "image": "http://.../media/products/2017/01/23/402/1ece7020bcc8.jpg",
                "order": 0,
                "created_date": "2017-01-23T08:34:48.487333Z",
                "specialimage_set": [],
                "modified_date": "2017-01-23T08:34:48.487367Z"
            },
            {
                "pk": 593,
                "status": "active",
                "image": "http://.../media/products/2017/01/23/402/4375a49a5e2a.jpg",
                "order": 1,
                "created_date": "2017-01-23T08:34:48.590416Z",
                "specialimage_set": [],
                "modified_date": "2017-01-23T08:34:48.590456Z"
            }
        ],
        "attribute_set": 16,
        "custom_attribute_set": null,
        "productization_date": null,
        "listing_code": null,
        "data_source": null,
        "modified_date": "2017-02-02T11:15:40.058780Z"
    },
    {...},
    {...}
]
```

***

### `POST` Create a Single Pre-Product​ <a href="#post-create-a-single-pre-product" id="post-create-a-single-pre-product"></a>

**Path:** `/api/v1/pre_products/`

This method records new objects to the Products table. It's validated with `PreProductSerializer`; if the data is not appropriate or the `product_type` value is neither `ProductTypes.pre_product` nor `ProductTypes.pre_miscellaneous`, an HTTP 404 error is returned. The flawless data is sent to the `ProductService.create_product()` method for processing, and the service executes the recording operation.

**Example Request​**

```json
{
    "product_type": "string", // "-1" (pre_product), "5" (miscellaneous)
    "sku": "string",
    "attributes_kwargs": "string",
    "data_source": "string",
    "product_type": "string",
    "name": "string",
    "parent": "string",
    "listing_code": "string",
    "is_child_update": "string",
    "is_active": "string",
    "extra_attributes": "string",
    "productization_date": "string",
    "custom_attribute_set": "string",
    "run_product_mapping": "string",
    "attribute_set": "string",
    "group_products": "string",
    "update_product_meta_name": "string",
    "base_code": "string",
    "attributes": "string",
    "approved": "string"
}
```

**Example Response​**

```
HTTP200
```

***

### `DELETE` Delete a Single Pre-Product​ <a href="#delete-delete-a-single-pre-product" id="delete-delete-a-single-pre-product"></a>

**Path:** `/api/v1/pre_products/{pk}/`

This method deletes the object from the Products table corresponding to the relevant primary key. An HTTP 404 error is returned if the object cannot be found.

**Example Request​**

```
/api/v1/pre_products/402/
```

**Example Response​**

```
HTTP200
```

***

### `GET` Get a Single Pre-Product​ <a href="#get-get-a-single-pre-product" id="get-get-a-single-pre-product"></a>

**Path:** `/api/v1/pre_products/{pk}/`

This method retrieves the object from the Products table corresponding to the relevant primary key. An HTTP 404 error is returned if the object cannot be found.

**Example Request​**

```
/api/v1/pre_products/402/
```

**Example Response​**

```
HTTP200
{
    "pk": 415,
    "name": "Banyo Halısı Desen 2 50x80+45x50cm",
    "base_code": "1KBAPA0197",
    "sku": "2672880316076",
    "product_type": "-1",
    "is_active": true,
    "parent": null,
    "attributes": {
        "erp_ProductAtt06Desc": "(50X80)+(45X50) CM",
        "integration_ProductAtt12Desc": "%50 + %20 PROMOSYON",
        "erp_ProductAtt12Desc": "%50 + %20 PROMOSYON",
        "uretim_yeri": "ÇİN",
        "renk": "TOPRAK",
        "integration_ProductAtt03Desc": "2011/2012 KIŞ",
        "erp_ProductAtt07Desc": "50+50 promosyon",
        "erp_color": "TOPRAK",
        "materyal": "%100 POLYESTER",
        "integration_ProductAtt22Desc": "5,50 x 9,00 cm",
        "integration_ProductAtt14Desc": "50X80+45X50 CM MAKİNE KESMESİ",
        "erp_ProductHierarchyLevel01": "TEKSTİL",
        "erp_ProductAtt13Desc": "YER GRUBU %50+%50",
        "integration_ProductAtt05Desc": "%50+%20 OUTLET PROMOSYONU",
        "erp_ProductAtt09Desc": "Flannel Baby Touch Machine",
        "erp_ProductAtt02Desc": "Yer Grubu - Paspas",
        "integration_ProductAtt15Desc": "%50+%50 PROMOSYON",
        "erp_ProductAtt20Desc": "%100 POLYESTER",
        "filtre_renk1": "Toprak",
        "erp_ProductAtt22Desc": "5,50 x 9,00 cm",
        "erp_ProductAtt15Desc": "%50+%50 PROMOSYON",
        "erp_ProductCode": "1KBAPA0197102",
        "integration_ProductAtt13Desc": "YER GRUBU %50+%50",
        "integration_ProductAtt01Desc": "DIŞ ALIM",
        "erp_ProductAtt05Desc": "%50+%20 OUTLET PROMOSYONU",
        "boyut": "(50X80)+(45X50) CM",
        "erp_ProductAtt14Desc": "50X80+45X50 CM MAKİNE KESMESİ",
        "erp_ProductAtt01Desc": "DIŞ ALIM",
        "erp_ProductHierarchyLevel02": "Yer Grubu",
        "integration_ProductCode": "1KBAPA0197102",
        "integration_ProductAtt07Desc": "50+50 promosyon",
        "erp_ProductAtt03Desc": "2011/2012 KIŞ",
        "integration_ProductAtt09Desc": "Flannel Baby Touch Machine",
        "integration_ProductHierarchyLevel01": "TEKSTİL",
        "integration_ProductHierarchyLevel02": "Yer Grubu",
        "erp_ProductAtt25Desc": "ÇİN",
        "integration_ProductAtt02Desc": "Yer Grubu - Paspas"
    },
    "attributes_kwargs": {
        "erp_ProductHierarchyLevel01": {
            "value": "TEKSTİL",
            "data_type": "dropdown",
            "label": "TEKSTİL"
        },
        "erp_ProductHierarchyLevel02": {
            "value": "Yer Grubu",
            "data_type": "dropdown",
            "label": "Yer Grubu"
        },
        "filtre_renk1": {
            "value": "Toprak",
            "data_type": "dropdown",
            "label": "Toprak"
        },
        "erp_color": {
            "value": "TOPRAK",
            "data_type": "dropdown",
            "label": "TOPRAK"
        },
        "integration_ProductHierarchyLevel01": {
            "value": "TEKSTİL",
            "data_type": "dropdown",
            "label": "TEKSTİL"
        },
        "integration_ProductHierarchyLevel02": {
            "value": "Yer Grubu",
            "data_type": "dropdown",
            "label": "Yer Grubu"
        },
        "renk": {
            "value": "TOPRAK",
            "data_type": "dropdown",
            "label": "TOPRAK"
        }
    },
    "extra_attributes": {},
    "group_products": [],
    "productimage_set": [{
            "pk": 608,
            "status": "active",
            "image": "http://.../media/products/2017/01/23/aa578d275807.jpg",
            "order": 0,
            "created_date": "2017-01-23T08:34:50.032604Z",
            "specialimage_set": [],
            "modified_date": "2017-01-23T08:34:50.032631Z"
        },
        {
            "pk": 609,
            "status": "active",
            "image": "http://.../media/products/2017/01/23/415/69e29c79caf2.jpg",
            "order": 1,
            "created_date": "2017-01-23T08:34:50.132254Z",
            "specialimage_set": [],
            "modified_date": "2017-01-23T08:34:50.132280Z"
        }
    ],
    "attribute_set": 13,
    "custom_attribute_set": null,
    "productization_date": null,
    "listing_code": null,
    "data_source": null,
    "modified_date": "2017-02-02T11:15:41.020549Z"
}
```

***

### `PATCH` Update a Single Pre-Product​ <a href="#patch-update-a-single-pre-product" id="patch-update-a-single-pre-product"></a>

**Path:** `/api/v1/pre_products/{pk}/`

This method partially updates the object from the Products table corresponding to the relevant primary key. It's validated with `PreProductSerializer`; if the data is not appropriate or the `product_type` value is neither `ProductTypes.pre_product` nor `ProductTypes.pre_miscellaneous`, an HTTP 404 error is returned. An HTTP 404 error is returned if the object cannot be found. The partial update method updates only the parameters sent as data.

***

### `PUT` Update a Single Pre-Product​ <a href="#put-update-a-single-pre-product" id="put-update-a-single-pre-product"></a>

**Path:** `/api/v1/pre_products/{pk}/`

This method updates the object from the Products table corresponding to the relevant primary key. It's validated with `PreProductSerializer`; if the data is not appropriate or the `product_type` value is neither `ProductTypes.pre_product` nor `ProductTypes.pre_miscellaneous`, an HTTP 404 error is returned. An HTTP 404 error is returned if the object cannot be found. The update method updates the entire object. The flawless data is sent to the `ProductService.update_product()` method for processing, and the service executes the update operation.

***

### `POST` Bulk Create Pre-Products​ <a href="#post-bulk-create-pre-products" id="post-bulk-create-pre-products"></a>

**Path:** `/api/v1/pre_products/bulk_create/`

This method asynchronously creates new objects in the Products table in bulk with an uploaded CSV or Excel file. Each creation process is delayed as a separate task. Since each task handles its own serialization, if there's an error, only the task that encountered the error will fail.

This method accepts formdata as a request and includes the path of the CSV or Excel file as `filename`. As a response, it returns the `cache_key` parameter stored in Redis for async tasks. In the creation process, the `sku` parameter is mandatory and must be present in the file.

**Example Request​**

```
/api/v1/pre_products/bulk_create/
-F 'filename=@/path/create.csv'
```

**Example Response​**

```json
HTTP200
{
"cache_key": "5c6ba584-156a-42d6-8b86-ca9c7d1a36c6"
}
```

***

### `GET` Bulk Create Cache Key Status​ <a href="#get-bulk-create-cache-key-status" id="get-bulk-create-cache-key-status"></a>

**Path:** `/api/v1/pre_products/{cache_key}/bulk_create_status/`

This method queries the status of an executed bulk create operation.

**Example Request​**

```
/api/v1/pre_products/5c6ba584-156a-42d6-8b86-ca9c7d1a36c6/bulk_create_status/
```

**Example Response​**

```
HTTP200
{
    "progress": [
        11,
        11
    ],
    "completed": true,
    "errors": [],
    "chunk_count": 11
}
```

***

### `POST` Bulk Update Pre-Products​ <a href="#post-bulk-update-pre-products" id="post-bulk-update-pre-products"></a>

**Path:** `/api/v1/pre_products/bulk_update/`

This method asynchronously updates objects in the Products table in bulk with an uploaded CSV or Excel file. Each update process is delayed as a separate task. Since each task handles its own serialization, if there's an error, only the task that encountered the error will fail.

This method accepts formdata as a request, and the path of the CSV or Excel file is sent within the `filename` parameter. As a response, it returns the `cache_key` parameter stored in Redis for async tasks. The update operation is performed similar to partial update based on the "sku" parameter in the file, updating only the parameters sent as data.

**Example Request​**

```
/api/v1/pre_products/bulk_update/
-F 'filename=@/path/update.csv'
```

**Example Response​**

```json
HTTP200
{
"cache_key": "5c6ba584-156a-42d6-8b86-ca9c7d1a36c6"
}
```

***

### `GET` Bulk Update Cache Key Status​ <a href="#get-bulk-update-cache-key-status" id="get-bulk-update-cache-key-status"></a>

**Path:** `/api/v1/pre_products/{cache_key}/bulk_update_status/`

This method queries the status of an executed bulk update operation.

**Example Request​**

```
/api/v1/pre_products/5c6ba584-156a-42d6-8b86-ca9c7d1a36c6/bulk_update_status/
```

**Example Response​**

```json
HTTP200
{
    "progress": [
        11,
        11
    ],
    "completed": true,
    "errors": [],
    "chunk_count": 11
}
```

***

### `GET` Get List of All Pre-Products - Detailed​ <a href="#get-get-list-of-all-pre-products---detailed" id="get-get-list-of-all-pre-products---detailed"></a>

**Path:** `/api/v1/pre_products/detailed/`

This method retrieves products from the Product table that fulfil the condition `product_type__in=[ProductTypes.pre_product, ProductTypes.pre_miscellaneous]`. It uses `ProductDetailedSerializer` instead of `PreProductSerializer`, and in this ViewSet, it's specified as `detailed_list` within the `serializer_action_classes` inherited from `MultiSerializerViewSetMixin`.

It takes filter parameters found in ProductFilter `{omnitron.products.resources.filters.ProductFilter}` as query parameters and has a wide range of filtering options.

***

### `GET` Get a Single Pre-Product - Detailed​ <a href="#get-get-a-single-pre-product---detailed" id="get-get-a-single-pre-product---detailed"></a>

**Path:** `/api/v1/pre_products/{pk}/detailed/`

This method retrieves the object from the Product table corresponding to the relevant primary key. An HTTP 404 error is returned if the object cannot be found. It uses `ProductDetailedSerializer` instead of `PreProductSerializer`, and in this ViewSet, it's specified as detailed within the `serializer_action_classes` inherited from `MultiSerializerViewSetMixin`.

***


---

# 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/omnitron/integration/product/pre-product.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.
