def perform_advanced_search(user_id, get_params): """Задача для выполнения расширенного поиска.""" formset = get_search_form('advanced', get_params) # Валидация запроса try: if not formset.is_valid(): errors = [] errors.extend(formset.errors) errors.extend(formset.non_form_errors()) return { 'validation_errors': errors, 'get_params': get_params } except ValidationError: return { 'validation_errors': _('Некоректні умови пошуку'), 'get_params': get_params } # Разбивка поисковых данных на поисковые группы search_groups = get_search_groups(formset.cleaned_data) # Пользователь user = get_user_or_anonymous(user_id) # Поиск в ElasticSearch по каждой группе s = get_elastic_results(search_groups, user) # Сортировка if get_params.get('sort_by'): s = sort_results(s, get_params['sort_by'][0]) else: s = s.sort('_score') # Фильтрация, агрегация s, aggregations = filter_results(s, get_params) # Пагинация results_on_page = int(get_params.get('show', [10])[0]) if results_on_page > 100: results_on_page = 100 elif results_on_page < 10: results_on_page = 10 res_from = results_on_page * (int(get_params['page'][0]) - 1) if get_params.get('page') else 0 res_to = res_from + results_on_page items = [] for i in s[res_from:res_to]: item = i.to_dict() item['meta'] = i.meta.to_dict() items.append(filter_app_data(item, user)) results = { 'items': items, 'total': s.count() } return { 'aggregations': aggregations, 'results': results, 'get_params': get_params }
def perform_favorites_search(favorites_ids, user_id, get_params): """Задача для выполнения простого поиска.""" # Формирование поискового запроса ElasticSearch client = Elasticsearch(settings.ELASTIC_HOST, timeout=settings.ELASTIC_TIMEOUT) # Пользователь user = get_user_or_anonymous(user_id) q = Q( 'bool', must=[Q('terms', _id=favorites_ids)], ) s = Search(using=client, index=settings.ELASTIC_INDEX_NAME).source( excludes=["*.DocBarCode", "*.DOCBARCODE"] ).query(q) # Сортировка if get_params.get('sort_by'): s = sort_results(s, get_params['sort_by'][0]) else: s = s.sort('_score') # Пагинация results_on_page = int(get_params.get('show', [10])[0]) if results_on_page > 100: results_on_page = 100 elif results_on_page < 10: results_on_page = 10 res_from = results_on_page * (int(get_params['page'][0]) - 1) if get_params.get('page') else 0 res_to = res_from + results_on_page items = [] for i in s[res_from:res_to]: item = i.to_dict() item['meta'] = i.meta.to_dict() items.append(filter_app_data(item, user)) results = { 'items': items, 'total': s.count() } return { 'results': results, 'get_params': get_params }
def create_favorites_results_file(user_id, favorites_ids, get_params, lang_code): """Возвращает url файла с результатами содержимого в избранном.""" client = Elasticsearch(settings.ELASTIC_HOST, timeout=settings.ELASTIC_TIMEOUT) q = Q( 'bool', must=[Q('terms', _id=favorites_ids)], ) s = Search(using=client, index=settings.ELASTIC_INDEX_NAME).query(q) if s.count() <= 5000: # Сортировка if get_params.get('sort_by'): s = sort_results(s, get_params['sort_by'][0]) else: s = s.sort('_score') # Данные для Excel-файла user = get_user_or_anonymous(user_id) # Данные для Excel-файла data = prepare_data_for_search_report(s, lang_code, user) directory_path = os.path.join( settings.MEDIA_ROOT, 'search_results', ) os.makedirs(directory_path, exist_ok=True) # Имя файла с результатами поиска file_name = f"{get_unique_filename('favorites')}.xlsx" file_path = os.path.join(directory_path, file_name) # Формировние и сохранение Excel-файла create_search_res_doc(data, file_path) # Возврат url сформированного файла с результатами поиска return os.path.join(settings.MEDIA_URL, 'search_results', file_name) return False
def create_advanced_search_results_file(user_id, get_params, lang_code): """Возвращает url файла с результатами расширенного поиска.""" formset = get_search_form('advanced', get_params) # Валидация запроса if formset.is_valid(): # Разбивка поисковых данных на поисковые группы search_groups = get_search_groups(formset.cleaned_data) # Поиск в ElasticSearch по каждой группе user = get_user_or_anonymous(user_id) s = get_elastic_results(search_groups, user) # Фильтрация # Возможные фильтры filters = [ { 'title': 'obj_type', 'field': 'Document.idObjType' }, { 'title': 'obj_state', 'field': 'search_data.obj_state' }, { 'title': 'registration_status_color', 'field': 'search_data.registration_status_color' }, ] # Если включены платные услуги, то необходимо включить возможность фильтрации по коду MarkCurrentStatusCodeType paid_services_settings, created = PaidServicesSettings.objects.get_or_create() """ ВРЕМЕННО ОТКРЫТЬ ДОСТУП ВСЕМ """ # if paid_services_settings.enabled: # filters.append({ # 'title': 'mark_status', # 'field': 'Document.MarkCurrentStatusCodeType.keyword' # }) filters.append({ 'title': 'mark_status', 'field': 'Document.MarkCurrentStatusCodeType.keyword' }) for item in filters: if get_params.get(f"filter_{item['title']}"): # Фильтрация в основном запросе s = s.filter('terms', **{item['field']: get_params.get(f"filter_{item['title']}")}) if s.count() <= 5000: s = s.source(['search_data', 'Document', 'Claim', 'Patent', 'TradeMark', 'MadridTradeMark', 'Design', 'Geo', 'Certificate']) # Сортировка if get_params.get('sort_by'): s = sort_results(s, get_params['sort_by'][0]) else: s = s.sort('_score') # Данные для Excel-файла data = prepare_data_for_search_report(s, lang_code, user) directory_path = os.path.join( settings.MEDIA_ROOT, 'search_results', ) os.makedirs(directory_path, exist_ok=True) # Имя файла с результатами поиска file_name = f"{get_unique_filename('advanced_search')}.xlsx" file_path = os.path.join(directory_path, file_name) # Формировние и сохранение Excel-файла create_search_res_doc(data, file_path) # Возврат url сформированного файла с результатами поиска return os.path.join( settings.MEDIA_URL, 'search_results', file_name ) return False
def create_simple_search_results_file(user_id, get_params, lang_code): """Возвращает url файла с результатами простого поиска.""" formset = get_search_form('simple', get_params) # Валидация запроса if formset.is_valid(): client = Elasticsearch(settings.ELASTIC_HOST, timeout=settings.ELASTIC_TIMEOUT) user = get_user_or_anonymous(user_id) qs = None for s in formset.cleaned_data: elastic_field = SimpleSearchField.objects.get(pk=s['param_type']).elastic_index_field if elastic_field: query = prepare_query(s['value'], elastic_field.field_type) if elastic_field.field_type == 'text': fields = [ f"{elastic_field.field_name}^2", f"{elastic_field.field_name}.exact^3", f"{elastic_field.field_name}.*", ] # if '*' in query: # fields = [ # # f"{inid_schedule.elastic_index_field.field_name}^2", # f"{elastic_field.field_name}.exact^2", # ] # else: # fields = [ # # f"{inid_schedule.elastic_index_field.field_name}^2", # f"{elastic_field.field_name}.exact^2", # f"{elastic_field.field_name}.*", # ] else: fields = [ f"{elastic_field.field_name}", ] q = Q( 'query_string', query=query, fields=fields, quote_field_suffix=".exact", default_operator='AND' ) # Nested тип if elastic_field.parent: q = Q( 'nested', path=elastic_field.parent.field_name, query=q, ) if qs is not None: qs &= q else: qs = q qs = filter_bad_apps(qs) s = Search(using=client, index=settings.ELASTIC_INDEX_NAME).query(qs) # Сортировка if get_params.get('sort_by'): s = sort_results(s, get_params['sort_by'][0]) else: s = s.sort('_score') # Фильтрация # Возможные фильтры filters = [ { 'title': 'obj_type', 'field': 'Document.idObjType' }, { 'title': 'obj_state', 'field': 'search_data.obj_state' }, { 'title': 'registration_status_color', 'field': 'search_data.registration_status_color' }, ] # Если включены платные услуги, то необходимо включить возможность фильтрации по коду MarkCurrentStatusCodeType paid_services_settings, created = PaidServicesSettings.objects.get_or_create() """ ВРЕМЕННО ОТКРЫТЬ ДОСТУП ВСЕМ """ # if paid_services_settings.enabled: # filters.append({ # 'title': 'mark_status', # 'field': 'Document.MarkCurrentStatusCodeType.keyword' # }) filters.append({ 'title': 'mark_status', 'field': 'Document.MarkCurrentStatusCodeType.keyword' }) for item in filters: if get_params.get(f"filter_{item['title']}"): # Фильтрация в основном запросе s = s.filter('terms', **{item['field']: get_params.get(f"filter_{item['title']}")}) if s.count() <= 5000: s = s.source(['search_data', 'Document', 'Claim', 'Patent', 'TradeMark', 'MadridTradeMark', 'Design', 'Geo', 'Certificate']) # Данные для Excel-файла data = prepare_data_for_search_report(s, lang_code, user) directory_path = os.path.join( settings.MEDIA_ROOT, 'search_results', ) os.makedirs(directory_path, exist_ok=True) # Имя файла с результатами поиска file_name = f"{get_unique_filename('simple_search')}.xlsx" file_path = os.path.join(directory_path, file_name) # Формировние и сохранение Excel-файла create_search_res_doc(data, file_path) # Возврат url сформированного файла с результатами поиска return os.path.join( settings.MEDIA_URL, 'search_results', file_name ) return False
def get_order_documents(user_id, id_app_number, id_cead_doc, ip_user): """Возвращает название файла документа или архива с документами, заказанного(ых) через "стол заказов".""" # Получение документа (заявки) из ElasticSearch client = Elasticsearch(settings.ELASTIC_HOST, timeout=settings.ELASTIC_TIMEOUT) q = Q( 'bool', must=[Q('match', _id=id_app_number)], ) user = get_user_or_anonymous(user_id) s = Search(index=settings.ELASTIC_INDEX_NAME).using(client).query(q).execute() if not s: return {} hit = s[0].to_dict() # Список id cead hit_id_cead_list = [] if hit['Document']['idObjType'] in (1, 2, 3): for doc in hit['DOCFLOW']['DOCUMENTS']: if doc['DOCRECORD'].get('DOCIDDOCCEAD'): hit_id_cead_list.append(doc['DOCRECORD']['DOCIDDOCCEAD']) # Если это охранный документ, то нужно ещё добавить в список документы заявки if hit['search_data']['obj_state'] == 2: q = Q( 'query_string', query=f"search_data.obj_state:1 AND search_data.app_number:{hit['search_data']['app_number']}", ) s = Search(index=settings.ELASTIC_INDEX_NAME).using(client).query(q).execute() if s: app_hit = s[0].to_dict() for doc in app_hit.get('DOCFLOW', {}).get('DOCUMENTS', []): if doc['DOCRECORD'].get('DOCIDDOCCEAD'): hit_id_cead_list.append(doc['DOCRECORD']['DOCIDDOCCEAD']) elif hit['Document']['idObjType'] == 4: for doc in hit['TradeMark']['DocFlow']['Documents']: if doc['DocRecord'].get('DocIdDocCEAD'): hit_id_cead_list.append(doc['DocRecord']['DocIdDocCEAD']) elif hit['Document']['idObjType'] == 6: for doc in hit['Design']['DocFlow']['Documents']: if doc['DocRecord'].get('DocIdDocCEAD'): hit_id_cead_list.append(doc['DocRecord']['DocIdDocCEAD']) # Входит ли id_cead_doc в список документов заявки if isinstance(id_cead_doc, list): is_in_list = set(list(map(int, id_cead_doc))).issubset(set(hit_id_cead_list)) else: is_in_list = id_cead_doc in hit_id_cead_list if is_in_list and user_has_access_to_docs(user, hit): # Создание заказа order = OrderService( # user=request.user, user_id=user_id, ip_user=ip_user, app_id=id_app_number ) order.save() if isinstance(id_cead_doc, list): for item in id_cead_doc: OrderDocument.objects.create(order=order, id_cead_doc=item) else: OrderDocument.objects.create(order=order, id_cead_doc=id_cead_doc) order = get_completed_order(order.id) if order: file_zip_name = f"docs_{order.id}.zip" file_path_zip = os.path.join( settings.ORDERS_ROOT, str(order.user_id), str(order.id), file_zip_name ) with ZipFile(file_path_zip, 'w') as zip_: for document in order.orderdocument_set.all(): zip_.write( os.path.join( settings.DOCUMENTS_MOUNT_FOLDER, 'OrderService', str(order.user_id), str(order.id), document.file_name), f"{document.file_name}" ) return os.path.join( settings.MEDIA_URL, 'OrderService', str(order.user_id), str(order.id), file_zip_name ) return False
def perform_simple_search(user_id, get_params): """Задача для выполнения простого поиска.""" formset = get_search_form('simple', get_params) # Валидация запроса try: if not formset.is_valid(): errors = [] errors.extend(formset.errors) errors.extend(formset.non_form_errors()) return { 'validation_errors': errors, 'get_params': get_params } except ValidationError: return { 'validation_errors': _('Некоректні умови пошуку'), 'get_params': get_params } # Формирование поискового запроса ElasticSearch client = Elasticsearch(settings.ELASTIC_HOST, timeout=settings.ELASTIC_TIMEOUT) # Пользователь user = get_user_or_anonymous(user_id) qs = None for s in formset.cleaned_data: if s: elastic_field = SimpleSearchField.objects.get(pk=s['param_type']).elastic_index_field if elastic_field: query = prepare_query(s['value'], elastic_field.field_type) if elastic_field.field_type == 'text': fields = [ f"{elastic_field.field_name}^2", f"{elastic_field.field_name}.exact^3", f"{elastic_field.field_name}.*", ] # if '*' in query: # fields = [ # # f"{inid_schedule.elastic_index_field.field_name}^2", # f"{elastic_field.field_name}.exact^2", # ] # else: # fields = [ # f"{elastic_field.field_name}^2", # f"{elastic_field.field_name}.exact^2", # f"{elastic_field.field_name}.*", # ] else: fields = [ f"{elastic_field.field_name}", ] q = Q( 'query_string', query=query, fields=fields, quote_field_suffix=".exact", default_operator='AND' ) # Nested тип if elastic_field.parent: q = Q( 'nested', path=elastic_field.parent.field_name, query=q, ) if qs is not None: qs &= q else: qs = q # Не включать в список результатов заявки, по которым выдан патент qs = filter_bad_apps(qs) s = Search(using=client, index=settings.ELASTIC_INDEX_NAME).query(qs).source( excludes=["*.DocBarCode", "*.DOCBARCODE"] ) # Сортировка if get_params.get('sort_by'): s = sort_results(s, get_params['sort_by'][0]) else: s = s.sort('_score') # Фильтрация, агрегация s, aggregations = filter_results(s, get_params) results_on_page = int(get_params.get('show', [10])[0]) if results_on_page > 100: results_on_page = 100 elif results_on_page < 10: results_on_page = 10 res_from = results_on_page * (int(get_params['page'][0]) - 1) if get_params.get('page') else 0 res_to = res_from + results_on_page items = [] for i in s[res_from:res_to]: item = i.to_dict() item['meta'] = i.meta.to_dict() items.append(filter_app_data(item, user)) results = { 'items': items, 'total': s.count() } return { 'aggregations': aggregations, 'results': results, 'get_params': get_params }
def get_app_details(id_app_number, user_id): """Задача для получения деталей по заявке.""" user = get_user_or_anonymous(user_id) client = Elasticsearch(settings.ELASTIC_HOST, timeout=settings.ELASTIC_TIMEOUT) q = Q( 'bool', must=[Q('match', _id=id_app_number)], ) # Фильтр заявок, которые не положено отоборажать q = filter_bad_apps(q) s = Search(index=settings.ELASTIC_INDEX_NAME).using(client).query(q).source( excludes=["*.DocBarCode", "*.DOCBARCODE"] ).execute() if not s: return {} hit = s[0].to_dict() if hit['Document']['idObjType'] in (1, 2, 3): hit['biblio_data'] = hit['Claim'] if hit['search_data']['obj_state'] == 1 else hit['Patent'] # Оповещения transactions = hit.get('TRANSACTIONS', {}).get('TRANSACTION', []) if type(transactions) is dict: transactions = [transactions] hit['transactions'] = transactions # Документы заявки (библиографические) hit['biblio_documents'] = AppDocuments.get_app_documents(id_app_number) # Если это патент, то необходимо объеденить документы, платежи и т.д. с теми которые были на этапе заявки if hit['search_data']['obj_state'] == 2: extend_doc_flow(hit) hit['DOCFLOW']['DOCUMENTS'] = search_services.application_filter_documents_im_um_ld( hit['biblio_data'], hit.get('DOCFLOW', {}).get('DOCUMENTS', []) ) elif hit['Document']['idObjType'] == 4: if hit['TradeMark'].get('DocFlow', {}).get('Documents'): hit['TradeMark']['DocFlow']['Documents'] = search_services.application_filter_documents_tm_id( hit['TradeMark'].get('DocFlow', {}).get('Documents', []) ) elif hit['Document']['idObjType'] == 6: if hit['Design'].get('DocFlow', {}).get('Documents'): hit['Design']['DocFlow']['Documents'] = search_services.application_filter_documents_tm_id( hit['Design'].get('DocFlow', {}).get('Documents', []) ) # Сортировка документов заявки по дате sort_doc_flow(hit) # Сортировка оповещений if hit['search_data']['obj_state'] == 2: search_services.application_sort_transactions(hit) hit['meta'] = {'id': id_app_number} return filter_app_data(hit, user)