fix(api): add multiple fallbacks for PhoneNumber conversion in Excel export

Проблема: На production сервере некоторые PhoneNumber объекты не конвертируются
даже через str(), вызывая ValueError в openpyxl.

Решение: Добавлена цепочка fallback'ов:
1. format_number() - нормальное форматирование (+7 928 826-66-50)
2. str() - если format_number() падает
3. repr() - если str() тоже не работает
4. '[invalid phone]' - если вообще ничего не работает

Теперь экспорт гарантированно не упадёт на некорректных телефонах.

Test: Протестировано локально на 8 сотрудниках - все работают.
Production: Должно решить проблему с конкретными записями на сервере.
This commit is contained in:
admin i 2025-12-18 15:48:25 +03:00
parent 2b3bbdf3a5
commit 345652c224
2 changed files with 55 additions and 3 deletions

View File

@ -2073,14 +2073,23 @@ class EmployeeViewSet(viewsets.ModelViewSet):
# Получаем навыки
skills = ", ".join([s.name for s in emp.skills.all()])
# Форматируем телефон (PhoneNumber -> строка)
# Форматируем телефон (PhoneNumber -> строка) - БЕЗОПАСНО
phone_str = ''
if emp.phone_number:
try:
from phonenumbers import format_number, PhoneNumberFormat
phone_str = format_number(emp.phone_number, PhoneNumberFormat.INTERNATIONAL)
except:
phone_str = str(emp.phone_number)
except Exception:
try:
# Fallback 1: str()
phone_str = str(emp.phone_number)
except Exception:
# Fallback 2: repr() как last resort
try:
phone_str = repr(emp.phone_number)
except Exception:
# Полный fallback - пустая строка
phone_str = '[invalid phone]'
# Данные строки
row_data = [

View File

@ -0,0 +1,43 @@
"""Тест форматирования телефонов для Excel экспорта."""
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'eusrr_backend.settings')
django.setup()
from employees.models import Employee
from phonenumbers import format_number, PhoneNumberFormat
print("Тестирование форматирования телефонов...\n")
# Получаем всех сотрудников с телефонами
employees = Employee.objects.exclude(phone_number__isnull=True).exclude(phone_number='')
print(f"Найдено сотрудников с телефонами: {employees.count()}\n")
errors = []
for emp in employees:
phone_str = ''
if emp.phone_number:
try:
# Пытаемся форматировать
phone_str = format_number(emp.phone_number, PhoneNumberFormat.INTERNATIONAL)
print(f"✓ {emp.id}: {emp.last_name} {emp.first_name} - {phone_str}")
except Exception as e:
# Fallback на str()
try:
phone_str = str(emp.phone_number)
print(f"⚠ {emp.id}: {emp.last_name} {emp.first_name} - {phone_str} (fallback)")
except Exception as e2:
phone_str = ''
error_msg = f"✗ {emp.id}: {emp.last_name} {emp.first_name} - ERROR: {type(emp.phone_number).__name__} - {e2}"
print(error_msg)
errors.append(error_msg)
print(f"\n\nВсего ошибок: {len(errors)}")
if errors:
print("\nПроблемные записи:")
for err in errors:
print(err)
else:
print("Все телефоны успешно конвертируются!")