# Расчёт стоимости заказа + отправка данных по REST API + email (пример реализации)

### ⚠ Важно <a href="#vazhno" id="vazhno"></a>

Этот пример показывает **общую логику работы Python-скрипта в Nextbot**.

{% hint style="info" %}
**Это не строгий шаблон. Вы можете:**

* менять структуру данных
* добавлять или убирать поля в форме
* изменять названия параметров в функции
* дорабатывать логику расчёта
  {% endhint %}

Используйте пример как основу, а не как обязательную инструкцию "сделать один в один".

## Задача

**Пользователь заполняет форму:**

* материал
* размеры
* имя
* телефон
* email
* согласие на обработку персональных данных

**Нужно:**

1. Посчитать стоимость
2. Отправить данные по REST API
3. Отправить email клиенту с предварительным расчетом заказа

***

{% stepper %}
{% step %}

#### Шаг 1. Создание функции

Создайте функцию, например, с названием:

```
process_data
```

Название может быть любым, главное, чтобы оно описывало действие функции.

**Параметры функции**

Добавьте параметр:

| Имя параметра | Тип параметра | Инструкция для параметра |
| ------------- | ------------- | ------------------------ |
| material      | Строка        | Название материала       |

<figure><img src="/files/YC2HZqeSQxJ7xuBcH8ZJ" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Шаг 2. Добавление действия "Форма персональных данных"

Внутри функции нажмите:

* [ ] **"Добавить действие"** → **"Форма персональных данных"**

**Поля формы**

Добавьте необходимые поля формы персональных данных:

<table><thead><tr><th width="123.80078125">Название параметра</th><th width="136.671875">Название поля</th><th width="113.3671875">Тип поля</th><th width="123.3203125">Источник</th><th>Дополнительно</th></tr></thead><tbody><tr><td>material</td><td>Материал</td><td>Строка</td><td>Из функции</td><td>Параметр функции: "material"</td></tr><tr><td>width</td><td>Ширина в метрах</td><td>Строка</td><td>Текст</td><td><br></td></tr><tr><td>length</td><td>Длина в метрах</td><td>Строка</td><td>Текст</td><td><br></td></tr><tr><td>client_name</td><td>Имя</td><td>Строка</td><td>Текст</td><td><br></td></tr><tr><td>phone</td><td>Телефон</td><td>Телефон</td><td>Текст</td><td><br></td></tr><tr><td>email</td><td>email</td><td>Email</td><td>Текст</td><td><br></td></tr><tr><td>agreement</td><td>-</td><td>Чекбокс согласия</td><td>Текст</td><td><strong>Пример:</strong> “Cогласен с &#x3C;a href="https://app.nextbot.ru/">политикой обработки персональных данных&#x3C;/a>”</td></tr></tbody></table>

<figure><img src="/files/4MPFZ1xUAvlwI2Q3Ifkh" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Шаг 3. Добавление действия после отправки формы -"Python Script"

1. Внизу блока действия **"Форма персональных данных"** нажмите:
   * [ ] **Добавить действие → Python Script**
2. Замените стандартный шаблон на ваш скрипт.

<details>

<summary><strong>Пример PYTHON скрипта для комплексной обработки заявки после заполнения формы ПД</strong></summary>

```python
# Доступные параметры в словаре args:
# args["form_data"]["material"] - Материал (тип: string)
# args["form_data"]["width"] - Ширина в метрах (тип: string)
# args["form_data"]["length"] - Длина в метрах (тип: string)
# args["form_data"]["client_name"] - Имя (тип: string)
# args["form_data"]["phone"] - Телефон (тип: string)
# args["form_data"]["email"] - email (тип: string)
# args["form_data"]["agreement"]["value"] - значение согласия (тип: bool)
# args["form_data"]["agreement"]["consent_text"] - текст согласия (тип: string)
# args["form_data"]["agreement"]["date_agreement"] - дата согласия (тип: string)

debug("Комплексная обработка заявки")

form_data = args.get("form_data", {})

# --- 1. Получение и валидация данных ---

material = form_data.get("material", "").strip()
phone = form_data.get("phone", "").strip()
receiver_email = form_data.get("email", "").strip()
agreement = form_data.get("agreement", "")

# Безопасное преобразование в float
def to_float(value):
    try:
        return float(str(value).replace(",", "."))
    except:
        return 0

width = to_float(form_data.get("width", 0))
length = to_float(form_data.get("length", 0))

if width <= 0 or length <= 0:
    debug("Некорректные размеры")

    result = {
        "status": "error",
        "message": "Некорректные размеры"
    }
else:

    # --- 2. Расчёт ---
    price_per_m2 = 100 # пример 
    area = width * length
    total = round(area * price_per_m2, 2)

    debug(f"Площадь: {area}")
    debug(f"Стоимость: {total}")

    # --- 3. Подготовка payload ---
    payload = {
        "material": material,
        "width": width,
        "length": length,
        "area": area,
        "total": total,
        "phone": phone,
        "email": receiver_email,
        "agreement": agreement,
        "source": "pd_form"
    }

    # --- 4. Отправка в API ---
    try:
        debug("Отправка по POST запроса...")

        response = requests.post(
            "https://api.company.com/orders", # ваш API-эндпоинт 
            json=payload
        )
        response.raise_for_status()

        debug("POST запрос успешно отправлено")

    except Exception as e:
        debug(f"Ошибка REST API: {str(e)}")

    # --- 5. Email (только если есть email и согласие) ---
    if receiver_email and agreement.get("value", False):

        try:
            debug("Подготовка email")

            smtp_server = "smtp.gmail.com"
            smtp_port = 465

            sender_email = "your@gmail.com" # ваш email для отправки писем
            sender_password = "xxxx xxxx xxxx xxxx"  # пароль приложения

            subject = "Предварительный расчет стоимости"
           
            body = (
                "Здравствуйте!\n\n"
                f"Материал: {material}\n"
                f"Площадь: {area} м2\n"
                f"Стоимость: {total} руб.\n\n"
                "С вами свяжется менеджер для уточнения деталей."
            )

            MIMEText = email["mime"]["text"]["MIMEText"]
            msg = MIMEText(body, "plain")

            msg.add_header("Subject", subject)
            msg.add_header("From", sender_email)
            msg.add_header("To", receiver_email)

            context = ssl.create_default_context()

            with smtplib.SMTP_SSL(smtp_server, smtp_port, context=context) as server:
                debug("Подключение к SMTP...")
                server.login(sender_email, sender_password)
                server.sendmail(sender_email, receiver_email, msg.as_string())

            debug("Email отправлен")

        except Exception as e:
            debug(f"Ошибка email: {str(e)}")

    else:
        debug("Email не отправлен (нет email или согласия)")

    # --- 6. Результат ---
    result = {
        "status": "success",
        "total": total,
        "area": area
    }

```

</details>

{% hint style="warning" %}
**Обязательно проверьте**

* указан корректный API endpoint
* email отправителя и пароль приложения корректные (подробно о настройках gmail аккаунта можете почитать [здесь](/functional/functions/sending-result/python/otpravka-e-mail.md))
* логика расчёта соответствует вашей задаче
  {% endhint %}

{% hint style="info" %}
**Вы можете найти больше информации про использование Python скрипта** [**в статье**](/functional/integrations/python.md)**.**
{% endhint %}

**Тестирование**

1. Включите **режим отладки** в Python Script\
   (это позволит видеть логи, но увеличит стоимость вызова)
2. Нажмите **"Тестировать код"**.
3. Введите тестовые значения в поля "material", "form\_data.length", "form\_data.width", например:
   * material: `Гипсокартон`
   * form\_data.width: `2`
   * form\_data.length: `3`
   * form\_data.client\_name: `Катерина`
   * form\_data.phone: `79991111234`
   * form\_data.email: `client@mail.com`
   * form\_data.agreement.value: `Да`
   * form\_data.agreement.conse2nt\_text: `Cогласен с политикой обработки персональных данных`
   * form\_data.agreement.date\_agreement: `2026-03-23T07:22:01.133Z`

     <figure><img src="/files/H14PUFpdSmAtVvEsZE5b" alt=""><figcaption></figcaption></figure>
4. Нажмите **"Запустить тест"**.

<details>

<summary><strong>Пример результата</strong></summary>

{% code overflow="wrap" %}

```json
{
  "status": "success",
  "total": 600,
  "area": 6
}
```

{% endcode %}

<figure><img src="/files/VjWg8Ht58r23oRnY53yV" alt=""><figcaption></figcaption></figure>

</details>
{% endstep %}

{% step %}

#### Шаг 4. Добавить в [системный промпт](/functional/setting-up-agent/system-prompt.md) инструкцию по использованию функций.

Добавьте в системный промпт инструкцию для вызова функции **process\_data**.

Например:

> Если пользователь хочет оформить заказ — запроси материал и вызови функцию process\_data.

<details>

<summary><strong>Пример простого системного промпта</strong></summary>

{% code overflow="wrap" %}

```markdown
Ты консультант в магазине стройматериалов. Твоя задача — уточнить, какой строительный материал нужен клиенту, и затем вызвать функцию `process_data`. Не нужно уточнять никаких дополнительных параметров или задавать сопутствующие вопросы.

# Steps

1. Приветствуй клиента и прояви готовность помочь с выбором стройматериалов.
2. Узнай, какой именно материал нужен клиенту.
3. Как только клиент отвечает, вызови функцию `process_data`.
4. Заверши взаимодействие, поблагодарив клиента за его выбор.

# Output Format

Напиши ответ в формате диалога. Разговор должен быть дружелюбным, кратким и ориентированным на клиента.

# Examples

**Пример**  
- Консультант: Добрый день! Чем могу помочь?  
- Клиент: Мне нужен гипсокартон.  
- Консультант: Отлично, сейчас всё посчитаем!  
- process_data()  

# Notes

- Не инициируй диалог, кроме как для приветствия и предложения помощи.
- Не уточняй количества, марки или других характеристик материалов.
```

{% endcode %}

</details>
{% endstep %}

{% step %}

#### Шаг 5. Тестирование в диалоге (тестовый чат).

1. Включите **режим отладки** в Python Script\
   (это позволит видеть логи, но увеличит стоимость вызова).
2. Откройте [**Тестовый чат**](/functional/chat.md)**.**
3. Начните диалог, например:

   > Хочу заказать гипсокартон

**Что произойдёт дальше**

1. Агент вызовет функцию `process_data`
2. Пользователь получит ссылку на форму
3. После отправки формы автоматически:

* будет рассчитана стоимость
* данные отправятся по API
* клиент получит email с расчётом

<details>

<summary><strong>Пример результата</strong></summary>

В диалоге:

{% code overflow="wrap" %}

```
Форма персональных данных успешно заполнена и отправлена пользователем. Функция: process_data.
Результат:
Python Script result:
{
  "status": "success",
  "total": 600,
  "area": 6
}
```

{% endcode %}

Логи выполнения Python скрипта:

{% code overflow="wrap" %}

```
1. [

2.   "Комплексная обработка заявки",

3.   "Площадь: 6.0",

4.   "Стоимость: 600.0",

5.   "Отправка в CRM...",

6.   "Успешно отправлено в CRM",

7.   "Подготовка email",

8.   "Подключение к SMTP...",

9.   "Email отправлен"

10. ]
```

{% endcode %}

<figure><img src="/files/eb5XlLEiWP6J75NyGze7" alt=""><figcaption></figcaption></figure>

Клиент получил еmail:

<figure><img src="/files/biG9ib3C7ERviM7kFpKs" alt=""><figcaption></figcaption></figure>

Тело запроса, отправленное по REST API:

{% code overflow="wrap" %}

```json
{
  "material": "гипсокартон",
  "width": 2,
  "length": 3,
  "area": 6,
  "total": 600,
  "phone": "79991111234",
  "email": "client@mail.com",
  "agreement": {
    "value": true,
    "consent_text": "Cогласен с <a href=\"https://app.nextbot.ru/\">политикой обработки персональных данных</a>",
    "date_agreement": "2026-03-23T07:44:16.924Z"
  },
  "source": "pd_form"
}
```

{% endcode %}

</details>
{% endstep %}
{% endstepper %}


---

# 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://doc.nextbot.ru/functional/functions/sending-result/forma-personalnykh-dannykh/deistviya-posle-otpravki-formy/deistvie-posle-otpravki-pdn-formy-python-script/raschyot-stoimosti-zakaza-+-otpravka-dannykh-po-rest-api-+-email-primer-realizacii.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.
