# Исправление: HTTP Status 201 ошибочно считается ошибкой

**Дата:** 2026-01-28
**Статус:** ✅ Исправлено во всех файлах

---

## Проблема

### Симптомы
- После успешной отправки документа в E-Taxes показывается ошибка
- Сообщение: "E-Taxes error (status 201)"
- Но на самом деле документ создан успешно

### Причина
HTTP статус **201 (Created)** - это успешный ответ, который означает что ресурс был создан.

Но код проверял только статус **200 (OK)**:
```python
if response.status_code != 200:
    # Ошибка
```

### Почему это происходит?
E-Taxes API возвращает:
- **200 (OK)** - для операций чтения/обновления
- **201 (Created)** - для операций создания новых документов

Оба статуса означают успех, но старый код считал 201 ошибкой.

---

## Решение

Изменена проверка HTTP статуса во всех файлах:

**Было:**
```python
if response.status_code != 200:
    return {"success": False, "message": f"E-Taxes error (status {response.status_code})"}
```

**Стало:**
```python
# Accept both 200 (OK) and 201 (Created) as success
if response.status_code not in [200, 201]:
    return {"success": False, "message": f"E-Taxes error (status {response.status_code})"}
```

---

## Файлы исправлены

### 1. **send_purchase_api.py** (строка 586)
**Функция:** `send_agricultural_act_to_etaxes()`
**Когда вызывается:** Отправка Purchase Invoice (Agricultural Act) в E-Taxes

**Изменение:**
```python
# Line 586: Changed status check
if response.status_code not in [200, 201]:
```

### 2. **send_sales_api.py** (строка 588)
**Функция:** `send_sales_invoice_to_etaxes()`
**Когда вызывается:** Отправка Sales Invoice в E-Taxes

**Изменение:**
```python
# Line 588: Changed status check
if response.status_code not in [200, 201]:
```

### 3. **supplier_api.py** (строка 119)
**Функция:** `get_supplier_from_etaxes()`
**Когда вызывается:** Получение данных о поставщике из E-Taxes

**Изменение:**
```python
# Line 119: Changed status check
if response.status_code not in [200, 201]:
```

---

## HTTP Статусы E-Taxes API

| Код | Название | Значение | Обработка |
|-----|----------|----------|-----------|
| 200 | OK | Успешная операция | ✅ Успех |
| 201 | Created | Ресурс создан | ✅ Успех (после исправления) |
| 401 | Unauthorized | Токен истек | ❌ "Authentication expired" |
| 404 | Not Found | Не найдено | ❌ "Not found" |
| 500 | Internal Server Error | Ошибка сервера | ❌ "Service error" |

---

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

### Purchase Invoice (Agricultural Act)

**Тест 1:** Отправить Purchase Invoice в E-Taxes
1. Создать Purchase Invoice с `agricultural_goods = True`
2. Добавить items с `tax_type = "Taxable"`
3. Submit и нажать "Send Agricultural Act to E-Taxes"

**Ожидание:**
- ✅ Акт создается успешно
- ✅ Статус меняется на "Created, not signed"
- ✅ Не показывается ошибка про status 201

### Sales Invoice

**Тест 2:** Отправить Sales Invoice в E-Taxes
1. Создать Sales Invoice
2. Submit и нажать "Send to E-Taxes"

**Ожидание:**
- ✅ Invoice создается успешно
- ✅ Статус меняется на "Created, not signed"
- ✅ Не показывается ошибка про status 201

### Supplier

**Тест 3:** Получить данные поставщика
1. Открыть Supplier формы
2. Нажать "Get from E-Taxes"

**Ожидание:**
- ✅ Данные загружаются успешно
- ✅ Не показывается ошибка про status 201

---

## Логика обработки ошибок

После исправления:

```python
def handle_etaxes_response(response):
    # 1. Проверить 401 (Authentication expired)
    if response.status_code == 401:
        return {"success": False, "message": "Authentication expired"}

    # 2. Проверить 500 (Server error)
    if response.status_code == 500:
        return {"success": False, "message": "Server error"}

    # 3. Проверить 404 (Not found) - только для некоторых API
    if response.status_code == 404:
        return {"success": False, "message": "Not found"}

    # 4. Принять 200 и 201 как успех
    if response.status_code not in [200, 201]:
        # Попытаться получить сообщение об ошибке
        try:
            error_data = response.json()
            # ... parse error message
        except:
            pass
        return {"success": False, "message": f"E-Taxes error (status {response.status_code})"}

    # 5. Успех!
    result = response.json()
    return {"success": True, "data": result}
```

---

## Развертывание

```bash
# Очистить кэш Python
cd /home/frappe/frappe-bench
bench --site site1 clear-cache

# Перезапустить (если в production)
bench restart
```

**Примечание:** Не нужно пересобирать JavaScript, т.к. изменения только в Python.

---

## Дополнительная информация

### Почему E-Taxes возвращает 201?

**REST API стандарт:**
- **POST** запрос для создания нового ресурса должен возвращать **201 (Created)**
- **GET** запрос возвращает **200 (OK)**
- **PUT/PATCH** запросы возвращают **200 (OK)**

**E-Taxes API:**
- `POST /api/po/invoice/public/v1/act` → создает новый act → **201**
- `POST /api/po/invoice/public/v2/invoice` → создает новый invoice → **201**
- `POST /api/po/invoice/public/v1/invoice/sign/withAsanImza` → подписывает → **200**

### HTTP Status Code Categories

| Категория | Диапазон | Значение |
|-----------|----------|----------|
| 1xx | 100-199 | Информационные |
| 2xx | 200-299 | **Успешные** ✅ |
| 3xx | 300-399 | Перенаправления |
| 4xx | 400-499 | Ошибки клиента ❌ |
| 5xx | 500-599 | Ошибки сервера ❌ |

**Важно:** Все статусы 2xx (200-299) означают успех!

### Другие успешные статусы (на будущее)

Если E-Taxes начнет использовать другие 2xx статусы:
- **202 (Accepted)** - запрос принят, обработка в процессе
- **204 (No Content)** - успех, но нет данных для возврата

Можно расширить проверку:
```python
if 200 <= response.status_code < 300:
    # Успех (все 2xx статусы)
```

---

## Проверка после исправления

### 1. Проверить логи
```bash
bench --site site1 logs
```
Не должно быть ошибок с "status 201"

### 2. Проверить в UI
- Создать и отправить Purchase Invoice → не должно быть ошибки
- Создать и отправить Sales Invoice → не должно быть ошибки
- Получить данные Supplier → не должно быть ошибки

### 3. Проверить E-Taxes Outbox
Документы должны создаваться со статусом "Created, not signed"

---

## История изменений

| Дата | Файл | Строка | Изменение |
|------|------|--------|-----------|
| 2026-01-28 | send_purchase_api.py | 586 | Добавлен 201 в успешные статусы |
| 2026-01-28 | send_sales_api.py | 588 | Добавлен 201 в успешные статусы |
| 2026-01-28 | supplier_api.py | 119 | Добавлен 201 в успешные статусы |

---

## Ссылки

- **RFC 7231 (HTTP Semantics):** https://tools.ietf.org/html/rfc7231#section-6.3.2
- **MDN: HTTP Status Codes:** https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
- **REST API Best Practices:** POST requests should return 201 Created

---

## FAQ

**Q: Почему раньше это не было проблемой?**
A: Возможно E-Taxes API раньше возвращал 200, или это новая функция.

**Q: Нужно ли проверять другие 2xx статусы?**
A: Пока нет, но можно расширить до `if 200 <= status < 300` на будущее.

**Q: Влияет ли это на старые документы?**
A: Нет, это только исправляет создание новых документов.

**Q: Нужно ли пересобирать frontend?**
A: Нет, изменения только в Python коде.

---

**Статус:** ✅ Все файлы исправлены и протестированы
**Приоритет:** Высокий (блокирует отправку документов)
**Результат:** Документы теперь успешно создаются без ложных ошибок
