Files
kontur-focus-lib/kontur_focus/focus_compliance.py
2025-11-14 18:27:09 +03:00

279 lines
13 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from kontur_focus.req import Request
from dotenv import load_dotenv
import os
from datetime import datetime
class FocusCompliance(Request):
_basedir = os.path.abspath(os.path.dirname(__file__))
_focus_base_url = None
check_models = [
{
'name': 'corporate',
'description': 'Корпоративный сегмент',
'risk_model_id': 'a9457161-0454-448a-bc2c-83a89cd51b42'
},
{
'name': '115-fz',
'description': '115 ФЗ для некредитных финансовых организаций',
'risk_model_id': '887ee87c-3a43-48d7-a4ad-05c0a64ff53a'
}
]
def __init__(self, inn: str = None, ogrn: str = None):
load_dotenv()
super().__init__(
base_url=os.environ.get('FOCUS_COMPLIANCE_BASE_URL'),
api_key=os.environ.get('FOCUS_COMPLIANCE_ACCESS_KEY'),
inn=inn,
ogrn=ogrn
)
self._focus_base_url = f"/banks/{os.environ.get('FOCUS_COMPLIANCE_BANK_ID')}"
def _save_file(self, filename: str, content, file_type: str = 'pdf', path: str = None) -> dict:
current_datetime = datetime.now().strftime('%d-%m-%Y_%H-%M')
f_name = f'{filename}_{self.inn}_{current_datetime}.{file_type}'
if not path:
file_path = os.path.join(self._basedir, f_name)
else:
file_path = os.path.join(path, f_name)
try:
with open(file_path, mode='wb') as file:
file.write(content)
return {'success': True, 'filename': f_name, 'path': file_path}
except Exception as e:
return {'success': False, 'message': e}
# Компании
def company_is_foreign_agent(self) -> dict:
"""Вхождение организации и ее руководителей в список иностранных агентов
:return: Дата формирования реестра, а также признаки присутствия или отсутствия в списках иностранных агентов
:rtype: dict
"""
response = self.get(path=f'{self._focus_base_url}/companies/lists')
foreign_agent_list = response['foreignAgentList']
company_in_list = []
persons_in_company_in_list = []
for item in foreign_agent_list['uls']:
if item['listItemStatus'] == 'NotInList':
continue
else:
company_in_list.append(item)
for person in foreign_agent_list['fls']:
if person['listItemStatus'] == 'NotInList':
continue
else:
persons_in_company_in_list.append(person)
fal_data = {
'list_date': str(foreign_agent_list['actualListDate']).split('T')[0],
'company_in_list': True if company_in_list else False,
'persons_in_company_in_list': True if persons_in_company_in_list else False
}
return fal_data
def search_global_company_profiles_id(self, company_name: str = None, search_accuracy: str = 'Max') -> list:
"""Поиск сводной информации по санкционным профилям ЮЛ
:param company_name: Наименование компании
:type company_name: str
:param search_accuracy: Точность поиска
:type search_accuracy: str
:return: Список идентификаторов профилей
:rtype: list
"""
if self.inn:
query = self.inn
elif company_name:
query = company_name
else:
return {'success': False, 'result': 'Не указан ИНН или наименование контрагента'}
try:
response = self.get(f'{self._focus_base_url}/companies/profiles/search', query=query, searchAccuracy=search_accuracy)
profiles = response['legalEntityProfiles']
if not profiles:
return {'success': True, 'result': profiles}
elif len(profiles) > 1:
return {'success': True, 'result': [profile['id'] for profile in profiles]}
else:
return {'success': True, 'result': [profiles[0]['id']]}
except KeyError:
return {'success': False, 'result': 'Key Error'}
def full_legal_entity_sanctions_profile(self, profile_id_list: list) -> dict:
"""Просмотр полной информации определенного санкционного профиля ЮЛ
:param profile_id_list: Идентификатор санкционного профиля ЮЛ. Идентификатор возвращается в методе
«Поиск сводной информации по санкционным профилям ЮЛ» -
GET /banks/{bankId}/companies/profiles/search
:type profile_id_list: list
:return: Полная информация по профилю ЮЛ
:rtype: dict
"""
if not profile_id_list:
return {'success': False, 'message': 'Не указан список ID профилей'}
else:
try:
profile = profile_id_list[0]
response = self.get(path=f'{self._focus_base_url}/companies/profiles/{profile}')
return {'success': True, 'result': response}
except KeyError:
return {'success': False, 'result': 'Ошибка в ID профиля.'}
def legal_entity_profile_report(self, profile_id_list: list, path: str = None) -> dict:
"""Получение печатного отчета по профилю ЮЛ
:param profile_id_list: Список идентификаторов санкционных профилей компании
:type profile_id_list: list
:param path: Путь сохранения файла, по-умолчанию файл сохраняется в текущий каталог
:type path: str, optional
:return: Отчет о результате сохранения файла
:rtype: dict
"""
if not profile_id_list:
return {'success': False, 'message': 'No profiles is specified'}
elif len(profile_id_list) > 1:
files = []
for profile_id in profile_id_list:
response = self.get(f'{self._focus_base_url}/companies/profiles/{profile_id}/report')
result = self._save_file(
filename=f'Отчет_по_профилю_{profile_id_list[0]}_{profile_id}',
content=response.content,
file_type='docx',
path=path
)
files.append(result)
return {'success': True, 'files': files}
else:
response = self.get(f'{self._focus_base_url}/companies/profiles/{profile_id_list[0]}/report')
result = self._save_file(
filename=f'Отчет_по_профилю_{profile_id_list[0]}',
content=response.content,
file_type='docx',
path=path
)
return {'success': True, 'files': [result]}
def full_company_report(self, model: str = '115-fz', path: str = None) -> dict:
"""Запрос на полную проверку и построение печатного отчёта по организации
:param model: Идентификатор модели, по которой пройдет проверка.
Идентификатор возвращается в методе «Получение списка рисковых моделей организации»
GET /banks/{bankId}/models, defaults to '115-fz'
:type model: str, optional
:param path: Путь сохранения файла, по-умолчанию файл сохраняется в текущий каталог, defaults to None
:type path: str, optional
:return: Отчет о результате сохранения файла
:rtype: dict
"""
if model == '115-fz':
model_id = [d['risk_model_id'] for d in self.check_models if d['name'] == model][0]
else:
model_id = [d['risk_model_id'] for d in self.check_models if d['name'] == 'corporate'][0]
response = self.get(f'{self._focus_base_url}/models/{model_id}/fullCompanyReport')
result = self._save_file(
filename='Полный_отчет',
content=response.content,
file_type='docx',
path=path
)
return {'success': True, 'file': result}
# Физлица
def person_is_foreign_agent(self):
"""Вхождение физлица в список иностранных агентов
:return: True или False
:rtype: bool
"""
response = self.get(path=f'{self._focus_base_url}/individuals')
fa = response[0]['foreignAgents']
return True if fa else False
def search_global_person_profiles_id(self) -> list:
"""Поиск сводной информации по санкционным/ПДЛ профилям ФЛ
:return: Список идентификаторов профилей
:rtype: list
"""
try:
response = self.get(f'{self._focus_base_url}/individuals/profiles/search', query=self.inn)
return response
except KeyError:
return None
def full_individual_report(self, path: str = None, passport: str = None, fio: str = None) -> dict:
"""Запрос на построение печатного отчёта по физ лицу
Необходимо обязательно указать либо ИНН, либо ФИО и номер паспорта
:param path: Путь сохранения файла, по-умолчанию файл сохраняется в текущий каталог, defaults to None
:type path: str, optional
:param passport: Номер паспорты, defaults to None
:type passport: str, optional
:param fio: ФИО (хотя бы фамилия и имя), defaults to None
:type fio: str, optional
:return: Отчет о результате сохранения файла
:rtype: dict
"""
if self.inn:
response = self.get(path=f'{self._focus_base_url}/formFullIndividualReport')
elif not self.inn and passport and fio:
response = self.get(path=f'{self._focus_base_url}/formFullIndividualReport', passportNumber=passport, fio=fio)
else:
return {'success': False, 'result': 'Необходимо указать: либо ИНН, либо ФИО (хотя бы фамилию и имя) и паспорт'}
try:
if response.status_code == 200:
result = self._save_file(
filename='Полный_отчет',
content=response.content,
file_type='docx',
path=path
)
return {'success': True, 'file': result}
else:
return {'success': False, 'result': 'Ошибка получения отчета. Проверьте корректность ИНН, ФИО или паспортных данных.'}
except AttributeError:
return {'success': False, 'result': 'Ошибка получения отчета. Проверьте корректность ИНН, ФИО или паспортных данных.'}
# Иноагенты
def get_foreign_agents_list(self, fa_type: str = None) -> list: # Не работает, если нет подключенной лицензии
"""Получение списка иноагентов
:param fa_type: Тип иноагента (i - физ. лица, l - юридические лица), если не указано, выгружаются все типы, defaults to None
:type fa_type: str, optional
:return: Список данных по иноагентам
:rtype: list
"""
response = self.get(path=f'{self._focus_base_url}/foreign-agents')
result = None
if fa_type == 'i':
individuals = response['individuals']
result = individuals
elif fa_type == 'l':
legal_entities = response['legalEntities']
result = legal_entities
else:
result = [response]
return result