diff --git a/core/core_config.py b/core/core_config.py index 409c96af..5fc4d64e 100644 --- a/core/core_config.py +++ b/core/core_config.py @@ -78,6 +78,16 @@ "Extraction continue on", ] +HEADING_FOR_SELECTING_SAMPLE_EXTRACTION_ON_EXTRACTION = [ + "Sample Name", + "Extraction CodeID", + "Select extraction", +] + +ERROR_TOO_MANY_SAMPLE_PROJECTS = [ + "The number of sample projects is too large to be presented" +] + # ################ PROTOCOL PARAMETER SETTINGS ############################## # ## Headings used when defining the custom protocol parameters HEADING_FOR_DEFINING_PROTOCOL_PARAMETERS = [ @@ -236,7 +246,9 @@ ERROR_STATE_ALREADY_DEFINED = ["State is already defined"] ERROR_CITY_ALREADY_DEFINED = ["City is already defined"] -ERROR_NEXT_ACTION_ALREADY_DEFINED = ["Next Action for the protocol type is already defined"] +ERROR_NEXT_ACTION_ALREADY_DEFINED = [ + "Next Action for the protocol type is already defined" +] ERROR_SAMPLE_NOT_FOUND = ["Sample was not found"] diff --git a/core/models.py b/core/models.py index e4a79504..f7c24a50 100644 --- a/core/models.py +++ b/core/models.py @@ -401,6 +401,7 @@ def get_id(self): class StatesForMolecule(models.Model): molecule_state_name = models.CharField(max_length=50) molecule_state_display = models.CharField(max_length=80, null=True, blank=True) + external_action = models.BooleanField(default=False, null=True, blank=True) class Meta: db_table = "core_states_for_molecule" diff --git a/core/utils/samples.py b/core/utils/samples.py index 843161c2..9b8e287f 100644 --- a/core/utils/samples.py +++ b/core/utils/samples.py @@ -1528,9 +1528,6 @@ def get_selection_from_excel_data(data, heading, check_field, field_id): else: selected.append(row[field_id]) selected_row.append(row) - import pdb - - pdb.set_trace() return selected, selected_row diff --git a/wetlab/class_views/external_file_preparation.py b/wetlab/class_views/external_file_preparation.py new file mode 100644 index 00000000..2c0ff0e4 --- /dev/null +++ b/wetlab/class_views/external_file_preparation.py @@ -0,0 +1,132 @@ +from django.shortcuts import render +from django.views import View +import core.models # import Protocols, ProtocolParameters, MoleculeParameterValue, SampleProjects +import core.core_config +import core.utils.samples + +class ExternalFilePreparationView(View): + template_name = "wetlab/external_file_preparation.html" + package = __package__.split(".")[0] + + def get(self, request, *args, **kwargs): + # collect the data to be shown in the form + return render(request, self.template_name, {"search_data": self.get_search_data}) + + def post(self, request, *args, **kwargs): + + if request.POST.get("action") == "externalFilePreparation": + # get the customer request to get the list of samples which where + # showed in the excel form. + selecting_samples = {} + if "protocol" in request.POST: + protocol_id = request.POST["protocol"] + # find out the protocol type from the protocol id + if core.models.Protocols.objects.filter(pk__exact=protocol_id).exists(): + p_obj = core.models.Protocols.objects.get(pk__exact=protocol_id) + # get the protocol type + p_type = p_obj.get_type() + selecting_samples["protocol"] = protocol_id + selecting_samples["protocol_type"] = p_type + if "DNA" in p_type or "RNA" in p_type: + # get the extraction object and then samples + selecting_samples["samples"] = self.get_extraction_samples(p_obj) + if len(selecting_samples["samples"]) > 0: + selecting_samples["heading"] = core.core_config.HEADING_FOR_SELECTING_SAMPLE_EXTRACTION_ON_EXTRACTION + selecting_samples["heading_string"] = ",".join(selecting_samples["heading"]) + return render(request, self.template_name, {"selecting_samples": selecting_samples}) + + elif request.POST.get("action") == "selectSamples": + heading = request.POST["heading"].split(",") + heading.insert(-1, "extract_id") + down_param_obj = list( + core.models.ProtocolParameters.objects.filter( + protocol_id__pk=request.POST["protocolID"], parameter_download=True + ) + ) + down_param_list = list( + core.models.ProtocolParameters.objects.filter( + protocol_id__pk=request.POST["protocolID"], parameter_download=True + ).values_list("parameter_name", flat=True) + ) + project_list = [] + if "DNA" in request.POST["protocolType"] or "RNA" in request.POST["protocolType"]: + map_sample_extraction = {} + extractions, _ = core.utils.samples.get_selection_from_excel_data( + request.POST["selected_samples"], heading, "Select extraction", "extract_id" + ) + if len(extractions) > 0: + data_for_download = {} + sample_ids = [] + # split the extraction that have different sample project + for extraction in extractions: + sample_id = core.models.MoleculePreparation.objects.get(pk__exact=extraction).sample + map_sample_extraction.setdefault(sample_id, []).append(extraction) + sample_ids.append(sample_id) + # need to check if using the list + # sample_ids = list(core.models.MoleculePreparation.objects.filter(pk_in=extractions).order_by('id').values_list("sample", flat=True) + sample_by_project = self.split_samples_by_project(sample_ids) + + if len(sample_by_project) > 6: + error_message = core.core_config.ERROR_TOO_MANY_SAMPLE_PROJECTS + return render(request, self.template_name, {"error_message": error_message, "search_data": self.get_search_data()}) + for project, samples in sample_by_project.items(): + project_name = project.sample_project_name + project_list.append(project_name) + data_for_download[project_name] = {} + + proj_fields = list(core.models.SampleProjectsFields.objects.filter(sample_projects_id=project, sample_project_downloadable=True).values_list("sample_project_field_name", flat=True)) + data_for_download[project_name]["heading"] = ["sample name"] + proj_fields + ["extraction code"] + down_param_list + for sample in samples: + s_name = sample.sample_name + s_proj_values = list(core.models.SampleProjectsFieldsValue.objects.filter(sample_id=sample, sample_project_field_id__sample_project_field_name__in=proj_fields).values_list("sample_project_field_value", flat=True)) + for extract_id in map_sample_extraction[sample]: + extract_field_values = list( + core.models.MoleculeParameterValue.objects.filter( + molecule_id__pk=extract_id, molecule_parameter_id__in=down_param_obj + ).values_list("parameter_value", flat=True) + ) + extract_code_id = core.models.MoleculePreparation.objects.get(pk__exact=extract_id).molecule_code_id + data_for_download[project_name].setdefault("values", []).append([s_name] + s_proj_values + [extract_code_id] + extract_field_values) + return render(request, self.template_name, {"data_for_download": data_for_download, "project_list": project_list}) + return render(request, self.template_name, {"search_data": self.get_search_data()}) + + def get_extraction_samples(self, protocol_obj): + # get the extraction object and then samples + if protocol_obj.extractions.filter(external_use=True).exists(): + extract_objs = protocol_obj.extractions.filter(external_use=True) + return list(extract_objs.values_list("sample__sample_name", "molecule_code_id", "pk")) + return [] + + def get_search_data(self): + search_data = {} + if core.models.SampleProjects.objects.filter(apps_name__iexact=self.package).exists(): + search_data["s_projects"] = list( + core.models.SampleProjects.objects.filter( + apps_name__iexact=self.package + ).values_list("sample_project_name", "id") + ) + + if core.models.Protocols.objects.filter(type__apps_name__iexact=self.package).exists(): + search_data["protocols"] = list( + core.models.Protocols.objects.filter( + type__apps_name__iexact=self.package + ).values_list("name", "id") + ) + + return search_data + + def split_samples_by_project(self, sample_objs: list) -> dict: + """Get the samples and split them by project + + Args: + sample_ids (list): List of sample ids + + Returns: + dict: Dictionary with the project obj as key and the sample objs as value + """ + sample_projects = {} + for sample_obj in sample_objs: + # sample_obj = core.models.Samples.objects.get(pk=sample_obj) + s_project = sample_obj.sample_project + sample_projects.setdefault(s_project, []).append(sample_obj) + return sample_projects diff --git a/wetlab/templates/wetlab/external_file_preparation.html b/wetlab/templates/wetlab/external_file_preparation.html index 6e8cb935..8fb2da8b 100644 --- a/wetlab/templates/wetlab/external_file_preparation.html +++ b/wetlab/templates/wetlab/external_file_preparation.html @@ -2,6 +2,7 @@ {% block content %} {% include "wetlab/menu.html" %} {% include "core/cdn_table_functionality.html" %} +{% include 'core/jexcel_functionality.html' %}
{% include 'registration/login_inline.html' %} @@ -17,7 +18,105 @@

{{error_message}}

{% endif %} - {% if selecting %} + {% if selecting_samples.heading %} +
+
+
+

Select the samples for preparing output data

+
+
+ {% csrf_token %} + + + + +
+
+
+ + +
+
+
+
+
+ {% elif data_for_download %} +
+
+ + {% for project_name, project_data in data_for_download.items %} + {% else %}
@@ -45,11 +144,12 @@

{{error_message}}

- +
@@ -75,41 +175,68 @@

{{error_message}}

-
- -
-


-
+

Fields marked in Red are mandatory

-

Fields marked with * are mandatory

- {% endif %} - {% if external_file_information %} -
-
-
-
New External File has been added
-
-

{{ external_file_information.external_file_name }} has been succesfully stored

-

Click on the "Add new external file" button for adding a new file

-