# Tax Articles Normalization

## Проблема

В Tax Articles были обнаружены проблемы с кодировкой символов, которые приводили к тому, что отчет **Tax Articles Revenue Report** показывал 0 вместо реальных сумм для некоторых статей.

### Две найденные проблемы:

#### 1. Типографские кавычки (Curly Quotes)

**Проблема:** В базе данных использовались типографские (curly) кавычки `"` `"` (Unicode U+201C/U+201D), а в коде Python - обычные прямые кавычки `"` (ASCII 0x22).

**Пример:**
```
БД:  "Məşğulluq haqqında"  (типографские)
Код: "Məşğulluq haqqında"  (прямые)
```

**Затронутые статьи:**
- VM 164.1.42 - "Məşğulluq haqqında"
- VM 164.1.51 - "Tibbi sığorta haqqında"
- Vergi Məcəlləsinin 102.1-ci
- Vergi Məcəlləsinin 106.1.24-cü
- Vergi Məcəlləsinin 207.7-ci

#### 2. Unicode Нормализация (NFD vs NFC)

**Проблема:** В базе данных использовалась NFD форма (decomposed - буква + диакритический знак), а в коде - NFC форма (composed - готовая буква).

**Пример:**
```
NFD: s + cedilla (2 символа) = ş
NFC: ş (1 символ)
```

**Затронутые статьи:**
- VM 164.1.34-1
- VM 164.1.41-2
- VM 164.1.47
- Vergi Məcəlləsinin 106.1.5-ci

## Решение

### Автоматическое исправление

Создан скрипт `taxes_az/normalize_tax_articles.py`, который автоматически:

1. **Заменяет типографские кавычки на прямые**
   - Использует SQL REPLACE с HEX значениями для точной замены байтов
   - `E2809C` (U+201C) → `22` (ASCII ")
   - `E2809D` (U+201D) → `22` (ASCII ")

2. **Нормализует Unicode в форму NFC**
   - Конвертирует разложенные символы в композитные
   - Обеспечивает соответствие с кодом Python

### Запуск скрипта

Скрипт запускается автоматически после каждой миграции благодаря хуку в `hooks.py`:

```python
after_migrate = [
    "taxes_az.create_item_group.create_item_groups",
    "taxes_az.normalize_tax_articles.normalize_on_migrate"
]
```

### Ручной запуск

Если нужно запустить вручную:

```bash
cd /home/frappe/frappe-bench
bench --site [site-name] execute "
from taxes_az.normalize_tax_articles import normalize_tax_articles
normalize_tax_articles()
"
```

## Установка на новой машине

При установке приложения на новой машине:

1. **Установите приложение:**
   ```bash
   bench get-app https://github.com/your-repo/taxes_az
   bench --site [site-name] install-app taxes_az
   ```

2. **Скрипт нормализации запустится автоматически** во время установки (через after_migrate hook)

3. **Проверьте логи:**
   ```bash
   bench --site [site-name] console
   ```
   Вы должны увидеть:
   ```
   Tax Articles normalized: X curly quotes fixed, Y NFC normalized
   ```

## Проверка

Для проверки что все исправлено правильно:

```bash
cd /home/frappe/frappe-bench
bench --site [site-name] mariadb --execute "
SELECT COUNT(*) as remaining_problems
FROM \`tabTax Article\`
WHERE HEX(article_name) LIKE '%E2809C%'
   OR HEX(article_name) LIKE '%E2809D%';
"
```

Результат должен быть: `remaining_problems: 0`

## Fixtures

Файл fixtures (`taxes_az/fixtures/tax_article.json`) также был обновлен:
- Заменены типографские кавычки на прямые
- Применена NFC нормализация

При экспорте новых fixtures они будут автоматически в правильном формате, так как данные в БД уже нормализованы.

## Технические детали

### Файлы

- **Скрипт нормализации:** `taxes_az/normalize_tax_articles.py`
- **Hooks конфигурация:** `taxes_az/hooks.py`
- **Fixtures (обновлен):** `taxes_az/fixtures/tax_article.json`
- **Отчет использующий маппинг:** `taxes_az/report/tax_articles_revenue_report/`

### HEX коды

| Тип кавычки | Символ | Unicode | UTF-8 HEX |
|-------------|--------|---------|-----------|
| Левая типографская | " | U+201C | E2 80 9C |
| Правая типографская | " | U+201D | E2 80 9D |
| Прямая | " | ASCII 0x22 | 22 |

### Логирование

Все действия логируются в Frappe Error Log с заголовком "Tax Article Normalization".

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

**2026-02-02:** Первая версия
- Исправлено 5 статей с кавычками
- Исправлено 4 статьи с NFD нормализацией
- Добавлен автоматический скрипт в hooks
- Обновлены fixtures

## Поддержка

При проблемах проверьте:
1. Логи миграции: `bench --site [site-name] migrate`
2. Error Log в интерфейсе Frappe
3. Запустите скрипт вручную для диагностики
