diff --git a/dokogen/ui.py b/dokogen/ui.py index 349d0d0..ec02b92 100644 --- a/dokogen/ui.py +++ b/dokogen/ui.py @@ -20,7 +20,7 @@ from . import ( from .verify import ( check_declension_morpher, check_company_dadata, check_declension_ai, check_company_ai, - COMPANY_FIELDS, + COMPANY_FIELDS, compare_company_values, ) from .api_settings import load_api_settings, save_api_settings @@ -550,6 +550,36 @@ class DokoGenApp: lines.append(f" {label}: {v}") lines.append("\nНажмите «✓ Применить», чтобы подставить данные") self._verify_log('\n'.join(lines)) + + # Сравнение полученных значений с введёнными (серьёзные расхождения — красным) + current = { + 'full_name': self.model.full_name, + 'short_name': self.model.short_name, + 'address': self.model.address, + 'inn': self.model.inn, + 'kpp': self.model.kpp, + 'ogrn': self.model.ogrn, + 'ogrn_date': self.model.ogrn_date, + 'chief_position': self.model.chief_position, + 'chief_fio': self.model.chief_fio, + } + if 'full_name' in d: + new_vals = d # DaData — фактические данные + else: + new_vals = d.get('proposals') or {} # ИИ — предложения + diffs = compare_company_values(current, new_vals) + if diffs: + warn = "⚠ ВНИМАНИЕ! НАЙДЕНЫ РАСХОЖДЕНИЯ:\n" + for label, old_v, new_v in diffs: + warn += f"• {label}: было «{old_v}», стало «{new_v}»\n" + self._verify_text.tag_configure('warn', foreground='red', + font=('Arial', 14, 'bold')) + self._verify_text.config(state=tk.NORMAL) + self._verify_text.insert(tk.END, '\n' + warn, 'warn') + self._verify_text.config(state=tk.DISABLED) + self.log(f"⚠ ВНИМАНИЕ: найдены расхождения ({len(diffs)}): " + + '; '.join(f"{l}: {o} → {n}" for l, o, n in diffs[:3])) + # Общий лог с ответом сервиса summary = '' if 'full_name' in d: diff --git a/dokogen/verify.py b/dokogen/verify.py index 7af0ed6..f0b4670 100644 --- a/dokogen/verify.py +++ b/dokogen/verify.py @@ -323,6 +323,54 @@ COMPANY_FIELDS = [ ('chief_fio', 'Руководитель (ФИО)'), ] +# Поля для сравнения: (ключ, подпись, тип) +# type: text — регистр/пунктуация игнорируются; digits — любое отличие = расхождение +_COMPARE_FIELDS = [ + ('full_name', 'Наименование', 'text'), + ('short_name', 'Краткое наименование', 'text'), + ('address', 'Юридический адрес', 'text'), + ('inn', 'ИНН', 'digits'), + ('kpp', 'КПП', 'digits'), + ('ogrn', 'ОГРН', 'digits'), + ('ogrn_date', 'Дата ОГРН', 'text'), + ('chief_position', 'Руководитель (должность)', 'text'), + ('chief_fio', 'Руководитель (ФИО)', 'text'), +] + + +def _norm_compare(s): + """Нормализация для сравнения: регистр, ё→е, пробелы/точки/дефисы/кавычки убираются.""" + s = (s or '').lower().replace('ё', 'е') + s = re.sub(r'[\s.,;:()«»"\'\-—–]+', '', s) + return s + + +def _norm_digits(s): + """Только цифры.""" + return re.sub(r'\D', '', s or '') + + +def compare_company_values(old_data, new_data): + """Сравнивает старые и новые значения реквизитов организации. + + Возвращает список расхождений: [(подпись, было, стало), ...]. + - text: разница в регистре/пунктуации (ИВАНОВ И.И. vs Иванов И.И.) НЕ считается; + - digits (ИНН/КПП/ОГРН): любое отличие цифр = расхождение. + """ + diffs = [] + for key, label, ftype in _COMPARE_FIELDS: + old = (old_data or {}).get(key) or '' + new = (new_data or {}).get(key) or '' + if not old or not new: + continue + if ftype == 'digits': + if _norm_digits(old) != _norm_digits(new): + diffs.append((label, old, new)) + else: + if _norm_compare(old) != _norm_compare(new): + diffs.append((label, old, new)) + return diffs + def check_company_ai(company_data, api_key, model='deepseek-chat', base_url=None): """ИИ-проверка реквизитов организации.