/
Paff
/
declarant
Обзор
Документация
Войти
/
Paff
/
declarant
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
models.py
93 строки
5 KB
1pash1985-gif
Декларант - веб-версия для Timeweb Cloud
15 июл 2026, 09:36
15 июл 2026, 09:36
a6b08b8
Код
Авторство
О чём код?
""" Модели данных для программы обработки инвойсов. """ from dataclasses import dataclass, field from typing import Optional @dataclass class Flower: """Модель цветка в базе данных.""" full_name_en: str # Полное название на латинице (например "Hydrangea") full_name_ru: str # Полное название на русском (например "Гортензия") synonyms: list[str] = field(default_factory=list) # Список синонимов/сокращений bg_color: Optional[str] = None # Пользовательский цвет фона строки def matches(self, text: str) -> bool: """Проверяет, соответствует ли текст данному цветку.""" text_upper = text.upper().strip() # Проверяем полное название if self.full_name_en.upper() in text_upper: return True # Проверяем синонимы for synonym in self.synonyms: if synonym.upper() in text_upper: return True return False @dataclass class InvoiceItem: """Позиция в инвойсе (один цветок).""" raw_name: str # Исходное название из инвойса matched_flower: Optional[str] = None # Сопоставленное название цветка boxes_qty: int = 0 # Количество коробок stems_qty: int = 0 # Количество стеблей box_type: str = "" # Тип коробки (QB-R3, HB, и т.д.) is_matched: bool = False # Флаг успешного сопоставления @dataclass class InvoiceData: """Данные извлеченные из одного инвойса.""" file_path: str # Путь к файлу инвойса invoice_number: str = "" # Номер инвойса date: str = "" # Дата client_name: str = "" # Имя клиента (из PO# или папки) client_po: str = "" # PO# из инвойса supplier: str = "" # Поставщик (из имени файла) items: list[InvoiceItem] = field(default_factory=list) total_boxes: int = 0 # Общее количество коробок total_stems: int = 0 # Общее количество стеблей mawb: str = "" # MAWB hawb: str = "" # HAWB parse_success: bool = False # Флаг успешного парсинга errors: list[str] = field(default_factory=list) # === Поля для автозаполнения ведомости "Загрузка" (MTL) === country: str = "" # Страна происхождения (Ecuador/Colombia/Kenya/Netherlands/…) firm: str = "" # Фирма-хендлер (Zeester/eFlowers/AstraFund/M&M/…) marking: str = "" # Маркировка (IZUM, BUTA, B-BOOM55, TJ PRADO, …) awb_prefix: str = "" # Первые 4 цифры имени папки — префикс AWB (1932, 3222, 5762, 9111, 9365, 7286) @dataclass class ClientData: """Данные клиента для записи в таблицу.""" folder_name: str # Имя папки (например "1561 AIGUL") client_name: str # Имя клиента (например "AIGUL") invoices: list[InvoiceData] = field(default_factory=list) def get_total_boxes(self) -> int: """Получить общее количество коробок по всем инвойсам клиента.""" return sum(inv.total_boxes for inv in self.invoices) def get_boxes_by_flower(self) -> dict[str, int]: """Получить количество коробок по каждому цветку.""" result = {} for inv in self.invoices: for item in inv.items: flower_name = item.matched_flower or item.raw_name if flower_name not in result: result[flower_name] = 0 result[flower_name] += item.boxes_qty return result @dataclass class ProcessedResult: """Результат обработки для записи в таблицу.""" client_name: str # Имя клиента (колонка в таблице) flower_name: str # Название цветка (строка в таблице) boxes_count: int # Количество коробок source_folder: str # Исходная папка is_confirmed: bool = False # Подтверждено пользователем