datawinners/entity/view/unique_id.py
import json
import elasticutils
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_view_exempt, csrf_response_exempt
from datawinners.accountmanagement.decorators import is_datasender
from datawinners.common.constant import DELETED_IDENTIFICATION_NUMBER
from datawinners.entity.helper import delete_entity_instance
from datawinners.entity.views import log_activity, get_success_message
from datawinners.main.database import get_database_manager
from datawinners.project.helper import get_projects_by_unique_id_type
from datawinners.search.entity_search import SubjectQuery
from datawinners.search.index_utils import es_questionnaire_field_name
from datawinners.settings import ELASTIC_SEARCH_URL, ELASTIC_SEARCH_TIMEOUT
from mangrove.datastore.documents import EntityActionDocument, HARD_DELETE, SOFT_DELETE
from mangrove.datastore.entity import get_by_short_code
from mangrove.form_model.form_model import get_form_model_by_entity_type, header_fields
from mangrove.transport import TransportInfo
def _log_soft_deleted_unique_ids(all_ids, dbm, entity_type):
for id in all_ids:
dbm._save_document(EntityActionDocument(entity_type, id, SOFT_DELETE))
def _soft_delete_unique_ids(all_ids, entity_type, dbm, request):
if all_ids:
transport_info = TransportInfo("web", request.user.username, "")
delete_entity_instance(dbm, all_ids, entity_type, transport_info)
_log_soft_deleted_unique_ids(all_ids, dbm, entity_type)
log_activity(request, DELETED_IDENTIFICATION_NUMBER, "%s: [%s]" % (entity_type.capitalize(), ", ".join(all_ids)))
def _delete_unique_id_from_elastic_search(dbm, entity_type, document_id):
elasticutils.get_es(urls=ELASTIC_SEARCH_URL, timeout=ELASTIC_SEARCH_TIMEOUT).delete(dbm.database_name, entity_type,
document_id)
def _refresh_elastic_search_index(dbm):
elasticutils.get_es(urls=ELASTIC_SEARCH_URL, timeout=ELASTIC_SEARCH_TIMEOUT).refresh(index=dbm.database_name)
def _hard_delete_unique_ids(unique_ids, dbm, form_model, request):
for unique_id in unique_ids:
entity = get_by_short_code(dbm, unique_id, form_model.entity_type)
_delete_unique_id_from_elastic_search(dbm, form_model.entity_type[0], entity.id)
entity.invalidate()
dbm._save_document(EntityActionDocument(form_model.entity_type[0], unique_id, HARD_DELETE))
entity.delete()
if unique_ids:
_refresh_elastic_search_index(dbm)
log_activity(request, DELETED_IDENTIFICATION_NUMBER, "%s: [%s]" % (request.POST['entity_type'], ", ".join(unique_ids)))
def _check_if_questionnaire_has_submissions_with_unique_id(manager, project, unique_id, entity_type):
field_names = [_get_unique_id_es_field_name(field, project.id, project.is_entity_registration_form())
for field in project.get_questions_for_entity([entity_type])]
doc_type = project.entity_type[0] if project.is_entity_registration_form() else project.id
query = elasticutils.S().es(urls=ELASTIC_SEARCH_URL, timeout=ELASTIC_SEARCH_TIMEOUT).indexes(
manager.database_name).doctypes(doc_type)[:1]
for field_name in field_names:
params = {field_name: unique_id}
query = query.filter(**params)
return list(query.values_list('void' if project.is_entity_registration_form() else 'status'))
def _get_unique_id_es_field_name(field, project_id, entity_questionnaire=False):
unique_id_field_name = es_questionnaire_field_name(field.code, project_id)
if not entity_questionnaire:
unique_id_field_name += '_unique_code_exact'
else:
unique_id_field_name += "_unique_code"
return unique_id_field_name
def _get_unique_ids_to_hard_delete(unique_ids, entity_type, manager):
projects = get_projects_by_unique_id_type(manager, [entity_type])
unique_ids_with_submissions = []
for project in projects:
for unique_id in unique_ids:
if unique_id in unique_ids_with_submissions:
continue
if _check_if_questionnaire_has_submissions_with_unique_id(manager, project, unique_id, entity_type):
unique_ids_with_submissions.append(unique_id)
return set(unique_ids) - set(unique_ids_with_submissions)
@csrf_view_exempt
@csrf_response_exempt
@login_required
@is_datasender
def delete_subjects(request):
manager = get_database_manager(request.user)
entity_type = request.POST['entity_type']
form_model = get_form_model_by_entity_type(manager, [entity_type])
all_ids = _subject_short_codes_to_delete(request, form_model, entity_type)
hard_delete_unique_ids = _get_unique_ids_to_hard_delete(all_ids, entity_type, manager)
_hard_delete_unique_ids(hard_delete_unique_ids, manager, form_model, request)
unique_ids_to_soft_delete = list(set(all_ids) - set(hard_delete_unique_ids))
_soft_delete_unique_ids(unique_ids_to_soft_delete, entity_type, manager, request)
message = get_success_message(entity_type)
return HttpResponse(json.dumps({'success': True, 'message': message}))
def _subject_short_codes_to_delete(request, form_model, entity_type):
if request.POST.get("all_selected") == 'true':
search_query = request.POST.get('search_query')
subject_list = SubjectQuery().query(request.user, entity_type, search_query)
short_code_index = header_fields(form_model).keys().index("short_code")
return [s[short_code_index] for s in subject_list]
return request.POST['all_ids'].split(';')