Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul #502

Merged
merged 72 commits into from
Feb 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
46fab7f
Initial commit for testing
cassidysymons Jan 12, 2023
3b2319f
Adjustment for testing
cassidysymons Jan 12, 2023
5daccbc
Survey & consent adjustments
cassidysymons Jan 17, 2023
3e4df72
Initial kit testing
cassidysymons Jan 19, 2023
62f4231
Debug
cassidysymons Jan 20, 2023
91183bf
Survey updates
cassidysymons Jan 20, 2023
dc6dd0e
Survey adjustments
cassidysymons Jan 23, 2023
bbf8131
Survey adjustments
cassidysymons Jan 24, 2023
d8222fc
Adjustments
cassidysymons Jan 25, 2023
704d84b
Adjustments
cassidysymons Jan 25, 2023
984a691
Adjustments
cassidysymons Jan 25, 2023
e48fc14
Adjustments
cassidysymons Jan 26, 2023
6f054c3
Adjustments
cassidysymons Jan 30, 2023
9c706f0
Adjustments
cassidysymons Feb 1, 2023
f45d8f5
Adjustments
cassidysymons Feb 1, 2023
6aff808
Adjustments
cassidysymons Feb 1, 2023
2bd9d50
Adjustments
cassidysymons Feb 1, 2023
4326d16
Adjustments
cassidysymons Feb 1, 2023
1d5d520
Adjustments
cassidysymons Feb 1, 2023
90b5fb9
Adjustments
cassidysymons Feb 1, 2023
501a694
Adjustments
cassidysymons Feb 2, 2023
5440e7a
Adjustments
cassidysymons Feb 3, 2023
da4dc7b
Merge branch 'master-overhaul' into csymons_overhaul_api
cassidysymons Feb 7, 2023
caae5df
Update microsetta_private_api/api/microsetta_private_api.yaml
cassidysymons Feb 14, 2023
3e12273
Update microsetta_private_api/db/patches/0109.sql
cassidysymons Feb 14, 2023
66d2b78
Update microsetta_private_api/repo/consent_repo.py
cassidysymons Feb 14, 2023
c0ca17b
Update microsetta_private_api/repo/sample_repo.py
cassidysymons Feb 14, 2023
fa12f3a
Code review changes
cassidysymons Feb 14, 2023
41a2be4
Code review changes
cassidysymons Feb 14, 2023
f83f16c
Code review changes
cassidysymons Feb 15, 2023
fdc267d
Test adjustments
cassidysymons Feb 15, 2023
2b0490e
Test adjustments
cassidysymons Feb 15, 2023
8e53a85
Test adjustments
cassidysymons Feb 15, 2023
2786344
Test adjustments
cassidysymons Feb 15, 2023
b5305b5
Test adjustments
cassidysymons Feb 15, 2023
3bb97bd
Test adjustments
cassidysymons Feb 15, 2023
7071a33
Test adjustments
cassidysymons Feb 15, 2023
5ceadc6
Test adjustments
cassidysymons Feb 15, 2023
e2e340f
Test adjustments
cassidysymons Feb 15, 2023
0086554
Test adjustments
cassidysymons Feb 15, 2023
a38eb97
Test adjustments
cassidysymons Feb 15, 2023
3b4ebd6
Test adjustments
cassidysymons Feb 15, 2023
b1ed548
Test adjustments
cassidysymons Feb 15, 2023
fa1174c
Test adjustments
cassidysymons Feb 15, 2023
2731c07
Test adjustments
cassidysymons Feb 15, 2023
fb0c58b
Test adjustments
cassidysymons Feb 15, 2023
30e610a
Test adjustments
cassidysymons Feb 15, 2023
901799d
Test adjustments
cassidysymons Feb 15, 2023
7eda22d
Test adjustments
cassidysymons Feb 15, 2023
ba1592c
Test adjustments
cassidysymons Feb 15, 2023
65e7d5b
Test adjustments
cassidysymons Feb 15, 2023
5a13935
Test adjustments
cassidysymons Feb 15, 2023
6709e37
Test adjustments
cassidysymons Feb 15, 2023
13fd456
Test adjustments
cassidysymons Feb 15, 2023
088bd48
Test adjustments
cassidysymons Feb 15, 2023
32a7c82
Test adjustments
cassidysymons Feb 15, 2023
04ec724
Test adjustments
cassidysymons Feb 15, 2023
9c02304
Test adjustments
cassidysymons Feb 15, 2023
80c0140
Test adjustments
cassidysymons Feb 15, 2023
1b1df99
Gender question adjustment
cassidysymons Feb 17, 2023
20befd7
Correct format for height and weight
cassidysymons Feb 21, 2023
84c55d3
Test fix
cassidysymons Feb 21, 2023
6fb00d0
Source scrub/delete adjustments
cassidysymons Feb 22, 2023
2ea05b8
Source scrub/delete adjustments - fixes
cassidysymons Feb 22, 2023
b4bcaf4
Source scrub/delete adjustments - fixes
cassidysymons Feb 22, 2023
835cfed
Source scrub/delete adjustments - fixes
cassidysymons Feb 22, 2023
7afe8d8
Source scrub/delete adjustments - fixes
cassidysymons Feb 22, 2023
dce550f
Source scrub/delete adjustments - fixes
cassidysymons Feb 22, 2023
9042f45
Source scrub/delete adjustments - fixes
cassidysymons Feb 22, 2023
a7f5926
Source scrub/delete adjustments - fixes
cassidysymons Feb 22, 2023
684ef82
Source scrub/delete adjustments - fixes
cassidysymons Feb 22, 2023
7fa3689
Source scrub/delete adjustments - fixes
cassidysymons Feb 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion microsetta_private_api/LEGACY/locale_data/english_gut.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@
'TEXT_I_HAVE_READ_SIMPLIFIED': 'Yes, you will be in this research study.',
'PERSON_ATTAINING_ASSENT': 'Signature Of Person Obtaining Assent',
'TEXT_ASSENT_WITNESS': 'In my judgment, the participant is voluntarily and knowingly giving assent and possesses the legal capacity to give assent to participate in the study.',
'OBTAINER_NAME': 'Name of person obtaining assent',
'ASSENT_OBTAINER': 'Name of person obtaining assent',
'TEXT_I_HAVE_READ_PARENT': 'I have read (or someone has read to me) this form. I am aware that I am being asked to provide consent for my child to be in a research study. I voluntarily agree to allow my child to participate in this study. I understand how my child’s personal data will be processed, my related rights, and that I consent to the processing of my child’s sample and data as provided in this document.',
'PARTICIPANT_NAME': 'Participant name',
'PARTICIPANT_PARENT_1': 'Parent/Guardian name',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
'TEXT_I_HAVE_READ_SIMPLIFIED': 'Sí, estarás en este estudio de investigación.',
'PERSON_ATTAINING_ASSENT': 'Firma de la persona que obtiene el consentimiento',
'TEXT_ASSENT_WITNESS': 'A mi juicio, el participante está dando su consentimiento voluntaria y conscientemente y posee la capacidad legal de dar su consentimiento para participar en el estudio.',
'OBTAINER_NAME': 'Nombre de la persona que obtiene el consentimiento',
'ASSENT_OBTAINER': 'Nombre de la persona que obtiene el consentimiento',
'TEXT_I_HAVE_READ_PARENT': 'He leído (o alguien me ha leído) este formulario. Soy consciente de que se le está pidiendo a mi hijo que participe en un estudio de investigación. Acepto voluntariamente que mi hijo participe en este estudio',
'PARTICIPANT_NAME': 'Nombre del participante',
'PARTICIPANT_EMAIL': 'Correo electrónico del participante',
Expand Down
2 changes: 1 addition & 1 deletion microsetta_private_api/LEGACY/locale_data/spanish_gut.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
'TEXT_I_HAVE_READ_SIMPLIFIED': 'Sí, estarás en este estudio de investigación.',
'PERSON_ATTAINING_ASSENT': 'Firma de la persona que obtiene el consentimiento',
'TEXT_ASSENT_WITNESS': 'A mi juicio, el participante está dando su consentimiento voluntaria y conscientemente y posee la capacidad legal de dar su consentimiento para participar en el estudio.',
'OBTAINER_NAME': 'Nombre de la persona que obtiene el consentimiento',
'ASSENT_OBTAINER': 'Nombre de la persona que obtiene el consentimiento',
'TEXT_I_HAVE_READ_PARENT': 'He leído (o alguien me ha leído) este formulario. Soy consciente de que se le está pidiendo a mi hijo que participe en un estudio de investigación. Acepto voluntariamente que mi hijo participe en este estudio',
'PARTICIPANT_NAME': 'Nombre del participante',
'PARTICIPANT_PARENT_1': 'Nombre del Padre de Familia / Guardian',
Expand Down
58 changes: 23 additions & 35 deletions microsetta_private_api/admin/admin_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,20 @@ def generate_activation_codes(body, token_info):
return jsonify(results), 200


def generate_ffq_codes(body, token_info):
validate_admin_access(token_info)

quantity = body.get("code_quantity", 1)
with Transaction() as t:
admin_repo = AdminRepo(t)
code_list = []
for i in range(quantity):
code_list.append(admin_repo.create_ffq_code())
t.commit()

return jsonify(code_list), 200


def list_barcode_query_fields(token_info):
validate_admin_access(token_info)

Expand Down Expand Up @@ -821,7 +835,6 @@ def delete_account(account_id, token_info):
src_repo = SourceRepo(t)
samp_repo = SampleRepo(t)
sar_repo = SurveyAnswersRepo(t)
template_repo = SurveyTemplateRepo(t)

acct = acct_repo.get_account(account_id)
if acct is None:
Expand All @@ -831,8 +844,6 @@ def delete_account(account_id, token_info):
if acct.account_type == 'deleted':
return None, 204

sample_count = 0
account_has_external = False
sources = src_repo.get_sources_in_account(
account_id,
allow_revoked=True
Expand All @@ -845,44 +856,21 @@ def delete_account(account_id, token_info):
allow_revoked=True
)

has_samples = len(samples) > 0
sample_count += len(samples)
has_external = template_repo.has_external_surveys(account_id,
source.id)

if has_external:
account_has_external = True

for sample in samples:
# we scrub rather than disassociate in the event that the
# sample is in our freezers but not with an up-to-date scan
samp_repo.scrub(account_id, source.id, sample.id)

surveys = sar_repo.list_answered_surveys(account_id, source.id)
if has_samples or has_external:
# if we have samples or external surveys, we need to scrub
# survey / source free text
for survey_id in surveys:
sar_repo.scrub(account_id, source.id, survey_id)

# We're including scrubbed sources to detect external surveys
# so we need to make sure the source isn't already scrubbed
if source.source_data.date_revoked is None:
src_repo.scrub(account_id, source.id)

if not has_samples and not has_external:
# if we do not have associated samples, or external surveys,
# then the source is safe to delete
for survey_id in surveys:
sar_repo.delete_answered_survey(account_id, survey_id)
src_repo.delete_source(account_id, source.id)

# an account is safe to delete if there are no associated samples
# and does not have external surveys
if sample_count > 0 or account_has_external:
acct_repo.scrub(account_id)
else:
acct_repo.delete_account(account_id)
for survey_id in surveys:
sar_repo.scrub(account_id, source.id, survey_id)

# We're including scrubbed sources to detect external surveys
# so we need to make sure the source isn't already scrubbed
if source.source_data.date_revoked is None:
src_repo.scrub(account_id, source.id)

acct_repo.scrub(account_id)

t.commit()

Expand Down
20 changes: 18 additions & 2 deletions microsetta_private_api/admin/tests/test_admin_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ def setup_test_data():
12345,
"US"
),
"fakekit",
"en_US")
"en_US",
True)
acct_repo.create_account(acc)

with t.cursor() as cur:
Expand Down Expand Up @@ -1269,3 +1269,19 @@ def mock_func(*args, **kwargs):
data=json.dumps(info),
headers=MOCK_HEADERS)
self.assertEqual(204, response.status_code)

def test_generate_ffq_codes(self):
input_json = json.dumps({"code_quantity": 2})

response = self.client.post(
"api/admin/generate_ffq_codes",
content_type='application/json',
data=input_json,
headers=MOCK_HEADERS
)
self.assertEqual(200, response.status_code)

response_obj = json.loads(response.data)

for ffq_code in response_obj:
self.assertEqual("TMI", ffq_code[0:3])
23 changes: 19 additions & 4 deletions microsetta_private_api/admin/tests/test_admin_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ def setup_test_data():
12345,
"US"
),
"fakekit",
"en_US")
"en_US",
True)
acct_repo.create_account(acc)

acc = Account(ADMIN_ACCT_ID,
Expand All @@ -107,8 +107,8 @@ def setup_test_data():
12345,
"US"
),
"fakekit",
"en_US")
"en_US",
True)
acct_repo.create_account(acc)
t.commit()

Expand Down Expand Up @@ -1323,3 +1323,18 @@ def test_set_kit_uuids_for_dak_order(self):
self.assertEqual(len(curr_records), 2)
for expected_record in expected_records:
self.assertIn(expected_record, curr_records)

def test_create_ffq_code(self):
with Transaction() as t:
admin_repo = AdminRepo(t)
ffq_code = admin_repo.create_ffq_code()

with t.dict_cursor() as cur:
cur.execute(
"SELECT registration_code_used "
"FROM campaign.ffq_registration_codes "
"WHERE ffq_registration_code = %s",
(ffq_code,)
)
row = cur.fetchone()
self.assertEqual(row['registration_code_used'], None)
19 changes: 11 additions & 8 deletions microsetta_private_api/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
from ._consent import (
render_consent_doc,
check_consent_signature,
sign_consent_doc
sign_consent_doc,
get_signed_consent
)
from ._source import (
create_source, read_source, update_source, delete_source,
read_sources, create_human_source_from_consent,
check_duplicate_source_name, scrub_source
create_source, read_source, update_source, read_sources,
create_human_source_from_consent, check_duplicate_source_name,
scrub_source
)
from ._survey import (
read_survey_template, read_survey_templates, read_answered_survey,
Expand Down Expand Up @@ -45,7 +46,7 @@
get_vioscreen_dietary_scores_descriptions,
get_vioscreen_food_components_by_code,
get_vioscreen_food_components_descriptions,
get_vioscreen_sessions
get_vioscreen_sessions, get_vioscreen_registry_entries, check_ffq_code
)

from ._campaign import (
Expand Down Expand Up @@ -82,13 +83,13 @@
'create_source',
'read_source',
'update_source',
'delete_source',
'scrub_source',
'read_sources',
'check_duplicate_source_name',
'create_human_source_from_consent',
'check_consent_signature',
'sign_consent_doc',
'get_signed_consent',
'read_survey_template',
'read_survey_templates',
'read_answered_survey',
Expand Down Expand Up @@ -124,7 +125,9 @@
'create_interested_user',
'get_interested_user_address_update',
'put_interested_user_address_update',
'get_vioscreen_sessions',
'get_vioscreen_registry_entries',
'check_ffq_code',
'get_opt_out',
'put_opt_out',
'get_vioscreen_sessions'
'put_opt_out'
]
3 changes: 2 additions & 1 deletion microsetta_private_api/api/_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ def update_account(account_id, body, token_info):
body['address']['city'],
body['address']['state'],
body['address']['post_code'],
body['address']['country_code']
body['address']['country_code'],
body['address']['street2']
)
acc.language = body['language']

Expand Down
21 changes: 18 additions & 3 deletions microsetta_private_api/api/_consent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from microsetta_private_api.repo.consent_repo import ConsentRepo
from microsetta_private_api.repo.transaction import Transaction
from microsetta_private_api.api.literals import CONSENT_DOC_NOT_FOUND_MSG
from werkzeug.exceptions import NotFound


def render_consent_doc(account_id, language_tag, token_info):
Expand Down Expand Up @@ -52,7 +53,6 @@ def check_consent_signature(account_id, source_id, consent_type, token_info):


def sign_consent_doc(account_id, source_id, consent_type, body, token_info):

_validate_account_access(token_info, account_id)

with Transaction() as t:
Expand All @@ -62,12 +62,27 @@ def sign_consent_doc(account_id, source_id, consent_type, body, token_info):
try:
consent_repo.sign_consent(account_id, consent_sign)
t.commit()
except Exception:
return jsonify(code=404, message=CONSENT_DOC_NOT_FOUND_MSG), 404
except NotFound as e:
return jsonify(code=404, message=e.description), 404

response = jsonify({"result": True})
response.status_code = 201
response.headers['Location'] = '/api/accounts/%s' % \
(account_id)

return response


def get_signed_consent(account_id, source_id, consent_type, token_info):
_validate_account_access(token_info, account_id)

with Transaction() as t:
consent_repo = ConsentRepo(t)
signed_consent = consent_repo.get_latest_signed_consent(
source_id,
consent_type
)
if signed_consent is None:
return jsonify(code=404, message="No signed consent found"), 404

return jsonify(signed_consent.to_api()), 200
Loading