diff --git a/docs/focus-compliance.rst b/docs/focus-compliance.rst index cd56c94..b68ab00 100644 --- a/docs/focus-compliance.rst +++ b/docs/focus-compliance.rst @@ -38,6 +38,8 @@ .. autofunction:: kontur_focus.FocusCompliance.legal_entity_profile_report(profile_id_list, path) +.. autofunction:: kontur_focus.FocusCompliance.full_company_report(model, path) + Пример вывода результат по отчету: .. code-block:: python @@ -49,3 +51,5 @@ --------------- .. autofunction:: kontur_focus.FocusCompliance.person_is_foreign_agent() + +.. autofunction:: kontur_focus.FocusCompliance.full_individual_report(path, passport, fio) diff --git a/docs/out/doctrees/environment.pickle b/docs/out/doctrees/environment.pickle index 7ea3079..65484c9 100644 Binary files a/docs/out/doctrees/environment.pickle and b/docs/out/doctrees/environment.pickle differ diff --git a/docs/out/doctrees/focus-compliance.doctree b/docs/out/doctrees/focus-compliance.doctree index b4540c4..b7fa608 100644 Binary files a/docs/out/doctrees/focus-compliance.doctree and b/docs/out/doctrees/focus-compliance.doctree differ diff --git a/docs/out/doctrees/focus.doctree b/docs/out/doctrees/focus.doctree index d4920b0..8ff389f 100644 Binary files a/docs/out/doctrees/focus.doctree and b/docs/out/doctrees/focus.doctree differ diff --git a/docs/out/doctrees/index.doctree b/docs/out/doctrees/index.doctree index bf459e3..d3545d1 100644 Binary files a/docs/out/doctrees/index.doctree and b/docs/out/doctrees/index.doctree differ diff --git a/docs/out/doctrees/open-api.doctree b/docs/out/doctrees/open-api.doctree index 7dd5c11..ef679f1 100644 Binary files a/docs/out/doctrees/open-api.doctree and b/docs/out/doctrees/open-api.doctree differ diff --git a/docs/out/doctrees/setup.doctree b/docs/out/doctrees/setup.doctree index f240acd..4aa5900 100644 Binary files a/docs/out/doctrees/setup.doctree and b/docs/out/doctrees/setup.doctree differ diff --git a/docs/out/html/.buildinfo b/docs/out/html/.buildinfo index 00206bf..c1b4c87 100644 --- a/docs/out/html/.buildinfo +++ b/docs/out/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file records the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 3a7299b0099bb3e771f87abcb181d65d +config: efdb4d1baf9a7408e2f9188275d85035 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/out/html/.buildinfo.bak b/docs/out/html/.buildinfo.bak new file mode 100644 index 0000000..00206bf --- /dev/null +++ b/docs/out/html/.buildinfo.bak @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file records the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 3a7299b0099bb3e771f87abcb181d65d +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/out/html/_modules/index.html b/docs/out/html/_modules/index.html new file mode 100644 index 0000000..236508e --- /dev/null +++ b/docs/out/html/_modules/index.html @@ -0,0 +1,105 @@ + + + + +
+ + +
+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) -> list:
+ """Поиск сводной информации по санкционным профилям ЮЛ
+
+ :param company_name: Наименование компании
+ :type company_name: 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)
+ 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 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]}',
+ 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')
+ if not self.inn and passport and fio:
+ response = self.get(path=f'{self._focus_base_url}/formFullIndividualReport', passportNumber=passport, fio=fio)
+ else:
+ return {'success': True, 'result': 'Необходимо указать: либо ИНН, либо ФИО (хотя бы фамилию и имя) и паспорт'}
+
+ result = self._save_file(
+ filename='Полный_отчет',
+ content=response.content,
+ file_type='docx',
+ path=path
+ )
+
+ return {'success': True, 'file': 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
+company_is_foreign_agent()search_global_company_profiles_id()legal_entity_profile_report()full_company_report()Поиск сводной информации по санкционным профилям ЮЛ
Список идентификаторов профилей
+company_name (str) – Наименование компании
list
+Список идентификаторов профилей
+list
Запрос на полную проверку и построение печатного отчёта по организации
+model (str, optional) – Идентификатор модели, по которой пройдет проверка. +Идентификатор возвращается в методе «Получение списка рисковых моделей организации» +GET /banks/{bankId}/models, defaults to „115-fz“
path (str, optional) – Путь сохранения файла, по-умолчанию файл сохраняется в текущий каталог, defaults to None
Отчет о результате сохранения файла
+dict
+Пример вывода результат по отчету:
[{'success': True, 'filename': '<имя_файла>', 'path': '<полный_путь_файла>'}]
Необходимо обязательно указать либо ИНН, либо ФИО и номер паспорта
+path (str, optional) – Путь сохранения файла, по-умолчанию файл сохраняется в текущий каталог, defaults to None
passport (str, optional) – Номер паспорты, defaults to None
fio (str, optional) – ФИО (хотя бы фамилия и имя), defaults to None
Отчет о результате сохранения файла
+dict
+