Skip to content

Commit 1b7e38c

Browse files
antgonzaElDeveloper
authored andcommitted
Fix 1293 (#2291)
* fix #1293 * flake8 * fix errors * addressing @ElDeveloper comments
1 parent 15b849f commit 1b7e38c

File tree

10 files changed

+187
-95
lines changed

10 files changed

+187
-95
lines changed

qiita_db/study.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,28 @@ def prep_templates(self, data_type=None):
998998
return [qdb.metadata_template.prep_template.PrepTemplate(ptid)
999999
for ptid in qdb.sql_connection.TRN.execute_fetchflatten()]
10001000

1001+
def analyses(self):
1002+
"""Get all analyses where samples from this study have been used
1003+
1004+
Returns
1005+
-------
1006+
list of qiita_db.analysis.Analysis
1007+
"""
1008+
with qdb.sql_connection.TRN:
1009+
if self.sample_template is not None:
1010+
sids = self.sample_template.keys()
1011+
if sids:
1012+
sql = """SELECT DISTINCT analysis_id
1013+
FROM qiita.analysis_sample
1014+
WHERE sample_id IN %s
1015+
ORDER BY analysis_id"""
1016+
qdb.sql_connection.TRN.add(
1017+
sql, [tuple(self.sample_template.keys())])
1018+
1019+
return [qdb.analysis.Analysis(_id) for _id in
1020+
qdb.sql_connection.TRN.execute_fetchflatten()]
1021+
return []
1022+
10011023
def has_access(self, user, no_public=False):
10021024
"""Returns whether the given user has access to the study
10031025

qiita_db/support_files/patches/python_patches/58.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ def correct_redis_data(key, cmd, values_dict, user):
120120
st_cmd = Command.create(qiita_plugin, "update_sample_template",
121121
"Updates the sample template", parameters)
122122

123+
# Create the delete study command
124+
parameters = {'study': ['integer', None]}
125+
Command.create(qiita_plugin, "delete_study",
126+
"Deletes a full study", parameters)
127+
123128
# Create the delete sample template command
124129
parameters = {'study': ['integer', None]}
125130
Command.create(qiita_plugin, "delete_sample_template",

qiita_db/test/test_study.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,20 @@ def test_retrieve_prep_templates_none(self):
766766
self.assertEqual(new.prep_templates(), [])
767767
qdb.study.Study.delete(new.id)
768768

769+
def test_analyses(self):
770+
new = qdb.study.Study.create(
771+
qdb.user.User('[email protected]'),
772+
'NOT Identification of the Microbiomes for Cannabis Soils 13',
773+
self.info)
774+
775+
self.assertEqual(qdb.study.Study(1).analyses(), [
776+
qdb.analysis.Analysis(1), qdb.analysis.Analysis(2),
777+
qdb.analysis.Analysis(3)])
778+
779+
self.assertEqual(qdb.study.Study(2).analyses(), [])
780+
781+
qdb.study.Study.delete(new.id)
782+
769783
def test_environmental_packages(self):
770784
obs = self.study.environmental_packages
771785
exp = ['soil', 'plant-associated']

qiita_pet/handlers/api_proxy/studies.py

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,24 @@
77
# -----------------------------------------------------------------------------
88
from __future__ import division
99
from collections import defaultdict
10+
from json import dumps, loads
1011

1112
from future.utils import viewitems
1213

14+
from qiita_core.exceptions import IncompetentQiitaDeveloperError
15+
from qiita_core.util import execute_as_transaction
16+
from qiita_core.qiita_settings import r_client
1317
from qiita_db.user import User
1418
from qiita_db.study import Study
1519
from qiita_db.metadata_template.prep_template import PrepTemplate
20+
from qiita_db.processing_job import ProcessingJob
21+
from qiita_db.software import Software, Parameters
1622
from qiita_db.util import (supported_filepath_types,
1723
get_files_from_uploads_folders)
1824
from qiita_pet.handlers.api_proxy.util import check_access
19-
from qiita_core.exceptions import IncompetentQiitaDeveloperError
25+
26+
27+
STUDY_KEY_FORMAT = 'study_%s'
2028

2129

2230
def data_types_get_req():
@@ -35,8 +43,7 @@ def data_types_get_req():
3543
"""
3644
return {'status': 'success',
3745
'message': '',
38-
'data_types': Study.all_data_types()
39-
}
46+
'data_types': Study.all_data_types()}
4047

4148

4249
def study_get_req(study_id, user_id):
@@ -110,12 +117,35 @@ def study_get_req(study_id, user_id):
110117
study_info['show_raw_download_button'] = any([
111118
True for pt in study.prep_templates() if pt.artifact is not None])
112119

120+
# getting study processing status from redis
121+
processing = False
122+
study_info['level'] = ''
123+
study_info['message'] = ''
124+
job_info = r_client.get(STUDY_KEY_FORMAT % study_id)
125+
if job_info:
126+
job_info = defaultdict(lambda: '', loads(job_info))
127+
job_id = job_info['job_id']
128+
job = ProcessingJob(job_id)
129+
job_status = job.status
130+
processing = job_status not in ('success', 'error')
131+
if processing:
132+
study_info['level'] = 'info'
133+
study_info['message'] = 'This study is currently being processed'
134+
elif job_status == 'error':
135+
study_info['level'] = 'danger'
136+
study_info['message'] = job.log.msg.replace('\n', '</br>')
137+
else:
138+
study_info['level'] = job_info['alert_type']
139+
study_info['message'] = job_info['alert_msg'].replace(
140+
'\n', '</br>')
141+
113142
return {'status': 'success',
114143
'message': '',
115144
'study_info': study_info,
116145
'editable': study.can_edit(User(user_id))}
117146

118147

148+
@execute_as_transaction
119149
def study_delete_req(study_id, user_id):
120150
"""Delete a given study
121151
@@ -137,17 +167,17 @@ def study_delete_req(study_id, user_id):
137167
if access_error:
138168
return access_error
139169

140-
status = 'success'
141-
try:
142-
Study.delete(int(study_id))
143-
msg = ''
144-
except Exception as e:
145-
status = 'error'
146-
msg = 'Unable to delete study: %s' % str(e)
147-
return {
148-
'status': status,
149-
'message': msg
150-
}
170+
qiita_plugin = Software.from_name_and_version('Qiita', 'alpha')
171+
cmd = qiita_plugin.get_command('delete_study')
172+
params = Parameters.load(cmd, values_dict={'study': study_id})
173+
job = ProcessingJob.create(User(user_id), params)
174+
# Store the job id attaching it to the sample template id
175+
r_client.set(STUDY_KEY_FORMAT % study_id,
176+
dumps({'job_id': job.id}))
177+
178+
job.submit()
179+
180+
return {'status': 'success', 'message': ''}
151181

152182

153183
def study_prep_get_req(study_id, user_id):

qiita_pet/handlers/api_proxy/tests/test_studies.py

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ def test_study_get_req(self):
5151
exp = {
5252
'status': 'success',
5353
'study_info': {
54-
'mixs_compliant': True, 'metadata_complete': True,
55-
'reprocess': False, 'owner': '[email protected]',
54+
'mixs_compliant': True, 'metadata_complete': True, 'level': '',
55+
'reprocess': False, 'owner': '[email protected]', 'message': '',
5656
'emp_person_id': 2, 'number_samples_promised': 27,
5757
'funding': None, 'show_biom_download_button': True,
5858
'publication_pid': ['123456', '7891011'], 'vamps_id': None,
@@ -341,37 +341,6 @@ def test_study_prep_get_req_no_access(self):
341341
'message': 'User does not have access to study'}
342342
self.assertEqual(obs, exp)
343343

344-
def test_study_delete_req(self):
345-
info = {
346-
"timeseries_type_id": 1,
347-
"metadata_complete": True,
348-
"mixs_compliant": True,
349-
"number_samples_collected": 25,
350-
"number_samples_promised": 28,
351-
"study_alias": "FCM",
352-
"study_description": "DESC",
353-
"study_abstract": "ABS",
354-
"emp_person_id": qdb.study.StudyPerson(2),
355-
"principal_investigator_id": qdb.study.StudyPerson(3),
356-
"lab_person_id": qdb.study.StudyPerson(1)
357-
}
358-
359-
new_study = qdb.study.Study.create(
360-
qdb.user.User('[email protected]'), "Some New Study to delete", info)
361-
362-
study_delete_req(new_study.id, '[email protected]')
363-
364-
with self.assertRaises(qdb.exceptions.QiitaDBUnknownIDError):
365-
qdb.study.Study(new_study.id)
366-
367-
def test_study_delete_req_error(self):
368-
obs = study_delete_req(1, '[email protected]')
369-
exp = {'status': 'error',
370-
'message': 'Unable to delete study: Study "Identification of '
371-
'the Microbiomes for Cannabis Soils" cannot be '
372-
'erased because it has a sample template'}
373-
self.assertEqual(obs, exp)
374-
375344
def test_study_delete_req_no_access(self):
376345
obs = study_delete_req(1, '[email protected]')
377346
exp = {'status': 'error',
@@ -525,7 +494,7 @@ def test_study_get_tags_request(self):
525494
self.assertEqual(obs, exp)
526495

527496
# check error
528-
obs = study_get_tags_request('[email protected]', 2)
497+
obs = study_get_tags_request('[email protected]', 2000)
529498
exp = {'message': 'Study does not exist', 'status': 'error'}
530499
self.assertEqual(obs, exp)
531500

@@ -560,7 +529,7 @@ def test_study_tags_patch_request(self):
560529
self.assertEqual(obs, exp)
561530

562531
obs = study_tags_patch_request(
563-
'[email protected]', 2, 'replace', '/tags', ['testA', 'testB'])
532+
'[email protected]', 2000, 'replace', '/tags', ['testA', 'testB'])
564533
exp = {'message': 'Study does not exist', 'status': 'error'}
565534
self.assertEqual(obs, exp)
566535

qiita_pet/handlers/study_handlers/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def get(self, study_id):
2828
if study_info['status'] != 'success':
2929
raise HTTPError(404, study_info['message'])
3030

31-
if message != '':
31+
if message != '' and level != '':
3232
study_info['level'] = level
3333
study_info['message'] = message
3434

qiita_pet/handlers/study_handlers/tests/test_base.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
# The full license is in the file LICENSE, distributed with this software.
77
# -----------------------------------------------------------------------------
88
from unittest import main
9-
from json import loads
109

1110
from qiita_pet.test.tornado_test_base import TestHandlerBase
1211
from qiita_db.handlers.tests.oauthbase import OauthTestingBase
@@ -27,17 +26,6 @@ class StudyBaseInfoAJAX(TestHandlerBase):
2726
pass
2827

2928

30-
class StudyDeleteAjaxTests(TestHandlerBase):
31-
def test_delete_study(self):
32-
response = self.post('/study/delete/', {'study_id': 1})
33-
self.assertEqual(response.code, 200)
34-
exp = {'status': 'error',
35-
'message': 'Unable to delete study: Study "Identification of '
36-
'the Microbiomes for Cannabis Soils" cannot be '
37-
'erased because it has a sample template'}
38-
self.assertEqual(loads(response.body), exp)
39-
40-
4129
class DataTypesMenuAJAXTests(TestHandlerBase):
4230
def test_get(self):
4331
response = self.get('/study/description/data_type_menu/',

qiita_pet/templates/study_base.html

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,7 @@
152152
else if(confirm("Are you sure you want to delete {% raw study_title_msg %}?")) {
153153
$.post('{% raw qiita_config.portal_dir %}/study/delete/', { study_id: {{study_info['study_id']}} })
154154
.done(function ( data ) {
155-
if(data.status == "error") {
156-
bootstrapAlert(data.message.replace("\n", "<br/>"), "danger");
157-
$("#delete-study").modal('hide');
158-
} else {
159-
window.location.replace('{% raw qiita_config.portal_dir %}/study/list/');
160-
}
155+
location.reload();
161156
});
162157
}
163158
}
@@ -211,6 +206,9 @@
211206
$("#sample-summary-btn").hide();
212207
$("#add-new-preparation-btn").hide();
213208
{% end %}
209+
{% if study_info['message'] != '' %}
210+
bootstrapAlert("{{study_info['message']}}", "{{study_info['level']}}");
211+
{% end %}
214212
});
215213
</script>
216214
<style>
@@ -223,24 +221,26 @@
223221
{% end %}
224222
{% block content %}
225223
<div class="row">
226-
<div class="col-md-3">
227-
<button class="btn btn-default btn-block" onclick="populate_main_div('{% raw qiita_config.portal_dir %}/study/description/baseinfo/', { study_id: {{study_info['study_id']}} })"><span class="glyphicon glyphicon-info-sign"></span> Study Information</button>
228-
<button class="btn btn-default btn-block" onclick="populate_main_div('{% raw qiita_config.portal_dir %}/study/description/sample_template/', { study_id: {{study_info['study_id']}} })"><span class="glyphicon glyphicon-info-sign"></span> Sample Information</button>
229-
<button class="btn btn-default btn-block" onclick="populate_main_div('{% raw qiita_config.portal_dir %}/study/description/sample_summary/', { study_id: {{study_info['study_id']}} })" id="sample-summary-btn"><span class="glyphicon glyphicon-th-list"></span> Sample Summary</button>
230-
{% if editable %}
231-
<a class="btn btn-default btn-block" href="{% raw qiita_config.portal_dir %}/study/upload/{{study_info['study_id']}}"><span class="glyphicon glyphicon-upload"></span> Upload Files</a>
232-
<button class="btn btn-default btn-block" onclick="populate_main_div('{% raw qiita_config.portal_dir %}/study/new_prep_template/', { study_id: {{study_info['study_id']}} })" id="add-new-preparation-btn"><span class="glyphicon glyphicon-plus-sign"></span> Add New Preparation</button>
233-
{% end %}
234-
{% if study_info['show_biom_download_button'] %}
235-
<a class="btn btn-default btn-block" href="{% raw qiita_config.portal_dir %}/download_study_bioms/{{study_info['study_id']}}"><span class="glyphicon glyphicon-download-alt"></span> All QIIME maps and BIOMs</a>
236-
{% end %}
237-
{% if study_info['has_access_to_raw_data'] and study_info['show_raw_download_button'] %}
238-
<a class="btn btn-default btn-block" href="{% raw qiita_config.portal_dir %}/download_raw_data/{{study_info['study_id']}}"><span class="glyphicon glyphicon-download-alt"></span> All raw data</a>
239-
{% end %}
240-
<div style="text-align: center;"><small><a href="{% raw qiita_config.portal_dir %}/static/doc/html/faq.html#how-to-solve-unzip-errors">Issues opening the downloaded zip?</a></small></div>
224+
{% if study_info['level'] != 'info' %}
225+
<div class="col-md-3">
226+
<button class="btn btn-default btn-block" onclick="populate_main_div('{% raw qiita_config.portal_dir %}/study/description/baseinfo/', { study_id: {{study_info['study_id']}} })"><span class="glyphicon glyphicon-info-sign"></span> Study Information</button>
227+
<button class="btn btn-default btn-block" onclick="populate_main_div('{% raw qiita_config.portal_dir %}/study/description/sample_template/', { study_id: {{study_info['study_id']}} })"><span class="glyphicon glyphicon-info-sign"></span> Sample Information</button>
228+
<button class="btn btn-default btn-block" onclick="populate_main_div('{% raw qiita_config.portal_dir %}/study/description/sample_summary/', { study_id: {{study_info['study_id']}} })" id="sample-summary-btn"><span class="glyphicon glyphicon-th-list"></span> Sample Summary</button>
229+
{% if editable %}
230+
<a class="btn btn-default btn-block" href="{% raw qiita_config.portal_dir %}/study/upload/{{study_info['study_id']}}"><span class="glyphicon glyphicon-upload"></span> Upload Files</a>
231+
<button class="btn btn-default btn-block" onclick="populate_main_div('{% raw qiita_config.portal_dir %}/study/new_prep_template/', { study_id: {{study_info['study_id']}} })" id="add-new-preparation-btn"><span class="glyphicon glyphicon-plus-sign"></span> Add New Preparation</button>
232+
{% end %}
233+
{% if study_info['show_biom_download_button'] %}
234+
<a class="btn btn-default btn-block" href="{% raw qiita_config.portal_dir %}/download_study_bioms/{{study_info['study_id']}}"><span class="glyphicon glyphicon-download-alt"></span> All QIIME maps and BIOMs</a>
235+
{% end %}
236+
{% if study_info['has_access_to_raw_data'] and study_info['show_raw_download_button'] %}
237+
<a class="btn btn-default btn-block" href="{% raw qiita_config.portal_dir %}/download_raw_data/{{study_info['study_id']}}"><span class="glyphicon glyphicon-download-alt"></span> All raw data</a>
238+
{% end %}
239+
<div style="text-align: center;"><small><a href="{% raw qiita_config.portal_dir %}/static/doc/html/faq.html#how-to-solve-unzip-errors">Issues opening the downloaded zip?</a></small></div>
241240

242-
<div id="data-types-menu"></div>
243-
</div>
241+
<div id="data-types-menu"></div>
242+
</div>
243+
{% end %}
244244

245245
<div class="col-md-9">
246246
<!-- Study ID and study alias always on top -->

qiita_ware/private_plugin.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,40 @@ def delete_sample_or_column(job):
273273
job._set_status('success')
274274

275275

276+
def delete_study(job):
277+
"""Deletes a full study
278+
279+
Parameters
280+
----------
281+
job : qiita_db.processing_job.ProcessingJob
282+
The processing job performing the task
283+
"""
284+
with qdb.sql_connection.TRN:
285+
study_id = job.parameters.values['study']
286+
study = qdb.study.Study(study_id)
287+
288+
for a in study.analyses():
289+
artifacts = sorted(
290+
a.artifacts, key=lambda a: a.id, reverse=True)
291+
for artifact in artifacts:
292+
qdb.artifact.Artifact.delete(artifact.id)
293+
qdb.analysis.Analysis.delete(a.id)
294+
295+
artifacts = sorted(
296+
study.artifacts(), key=lambda a: a.id, reverse=True)
297+
for a in artifacts:
298+
qdb.artifact.Artifact.delete(a.id)
299+
300+
for pt in study.prep_templates():
301+
qdb.metadata_template.prep_template.PrepTemplate.delete(pt.id)
302+
303+
qdb.metadata_template.sample_template.SampleTemplate.delete(study_id)
304+
305+
qdb.study.Study.delete(study_id)
306+
307+
job._set_status('success')
308+
309+
276310
def complete_job(job):
277311
"""Deletes a sample or a column from the metadata
278312
@@ -310,6 +344,7 @@ def complete_job(job):
310344
'delete_sample_template': delete_sample_template,
311345
'update_prep_template': update_prep_template,
312346
'delete_sample_or_column': delete_sample_or_column,
347+
'delete_study': delete_study,
313348
'complete_job': complete_job}
314349

315350

0 commit comments

Comments
 (0)