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

external survey - skin scoring app #583

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
39 changes: 38 additions & 1 deletion microsetta_private_api/api/_survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from microsetta_private_api.repo.transaction import Transaction
from microsetta_private_api.repo.vioscreen_repo import VioscreenRepo
from microsetta_private_api.util import vioscreen, myfoodrepo, vue_adapter, \
polyphenol_ffq
polyphenol_ffq, skin_scoring_app_ffq
ayobi marked this conversation as resolved.
Show resolved Hide resolved
from microsetta_private_api.util.vioscreen import VioscreenAdminAPI
from microsetta_private_api.config_manager import SERVER_CONFIG

Expand Down Expand Up @@ -43,6 +43,7 @@ def read_survey_templates(account_id, source_id, language_tag, token_info):
SurveyTemplateRepo.VIOSCREEN_ID,
SurveyTemplateRepo.POLYPHENOL_FFQ_ID,
SurveyTemplateRepo.SPAIN_FFQ_ID,
SurveyTemplateRepo.SKIN_SCORING_APP_FFQ_ID,
SurveyTemplateRepo.BASIC_INFO_ID,
SurveyTemplateRepo.AT_HOME_ID,
SurveyTemplateRepo.LIFESTYLE_ID,
Expand Down Expand Up @@ -181,6 +182,37 @@ def _remote_survey_url_spain_ffq(transaction, account_id, source_id):
return SERVER_CONFIG['spain_ffq_url']


def _remote_survey_url_skin_scoring_app_ffq(transaction,
account_id,
source_id,
language_tag):
st_repo = SurveyTemplateRepo(transaction)

skin_scoring_app_ffq_id, study = \
st_repo.get_skin_scoring_app_ffq_id_if_exists(account_id,
source_id)

if skin_scoring_app_ffq_id is None:
study = 'SBI'
ayobi marked this conversation as resolved.
Show resolved Hide resolved
sample_repo = SampleRepo(transaction)
samples = sample_repo.get_samples_by_source(account_id, source_id)
for s in samples:
for s_p in s.sample_projects:
if s_p.startswith('SBI'):
study = 'SBI'
break

skin_scoring_app_ffq_id = \
st_repo.create_skin_scoring_app_ffq_entry(account_id,
source_id,
language_tag,
study)

return skin_scoring_app_ffq.gen_ffq_url(skin_scoring_app_ffq_id,
study,
language_tag)


def read_survey_template(account_id, source_id, survey_template_id,
language_tag, token_info, survey_redirect_url=None,
vioscreen_ext_sample_id=None,
Expand Down Expand Up @@ -220,6 +252,11 @@ def read_survey_template(account_id, source_id, survey_template_id,
url = _remote_survey_url_spain_ffq(t,
account_id,
source_id)
elif survey_template_id == \
SurveyTemplateRepo.SKIN_SCORING_APP_FFQ_ID:
url = _remote_survey_url_skin_scoring_app_ffq(t,
account_id,
source_id)
else:
raise ValueError(f"Cannot generate URL for survey "
f"{survey_template_id}")
Expand Down
2 changes: 2 additions & 0 deletions microsetta_private_api/api/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,8 @@ def delete_dummy_accts():
template_repo.delete_polyphenol_ffq(curr_acct_id,
curr_source.id)
template_repo.delete_spain_ffq(curr_acct_id, curr_source.id)
template_repo.delete_skin_scoring_app_ffq(curr_acct_id,
curr_source.id)

# Dissociate all samples linked to this source from all
# answered surveys linked to this source, then delete all
Expand Down
38 changes: 38 additions & 0 deletions microsetta_private_api/api/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ def test_surveys(self):
[SurveyTemplateRepo.VIOSCREEN_ID,
SurveyTemplateRepo.POLYPHENOL_FFQ_ID,
SurveyTemplateRepo.SPAIN_FFQ_ID,
SurveyTemplateRepo.SKIN_SCORING_APP_FFQ_ID,
SurveyTemplateRepo.BASIC_INFO_ID,
SurveyTemplateRepo.AT_HOME_ID,
SurveyTemplateRepo.LIFESTYLE_ID,
Expand Down Expand Up @@ -625,6 +626,42 @@ def test_bobo_takes_polyphenol_ffq(self):
)
check_response(resp, 404)

@skipIf(SERVER_CONFIG['skin_scoring_app_ffq_url'] in
('', 'ssafq_placeholder'),
"Skin Scoring App FFQ secrets not provided")
def test_bobo_takes_skin_scoring_app_ffq(self):
bobo = self._bobo_to_claim_a_sample()

# take Skin Scoring App FFQ
resp = self.client.get(
'/api/accounts/%s/sources/%s/survey_templates/10005'
'?language_tag=en_US' %
(ACCT_ID, bobo['source_id']),
headers=MOCK_HEADERS
)
check_response(resp)
data = json.loads(resp.data)
exp_start = SERVER_CONFIG['skin_scoring_app_ffq_url']
url = data['survey_template_text']['url']
self.assertTrue(url.startswith(exp_start))

# verify we err if we attempt to answer the survey. an "answer" here is
# undefined
resp = self.client.post(
'/api/accounts/%s/sources/%s/surveys'
'?language_tag=en_US' %
(ACCT_ID, bobo['source_id']),
content_type='application/json',
data=json.dumps(
{
"survey_template_id":
SurveyTemplateRepo.SKIN_SCORING_APP_FFQ_ID,
"survey_text": {'key': 'stuff'}
}),
headers=MOCK_HEADERS
)
check_response(resp, 404)

@skipIf(SERVER_CONFIG['spain_ffq_url'] in ('', 'sffq_placeholder'),
"Spain FFQ secrets not provided")
def test_bobo_takes_spain_ffq(self):
Expand Down Expand Up @@ -693,6 +730,7 @@ def test_bobo_takes_all_local_surveys(self):
SurveyTemplateRepo.MYFOODREPO_ID,
SurveyTemplateRepo.POLYPHENOL_FFQ_ID,
SurveyTemplateRepo.SPAIN_FFQ_ID,
SurveyTemplateRepo.SKIN_SCORING_APP_FFQ_ID,
SurveyTemplateRepo.BASIC_INFO_ID,
SurveyTemplateRepo.AT_HOME_ID,
SurveyTemplateRepo.LIFESTYLE_ID,
Expand Down
14 changes: 14 additions & 0 deletions microsetta_private_api/db/patches/0143.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CREATE TABLE ag.skin_scoring_app_ffq_registry (
skin_scoring_app_ffq_id VARCHAR PRIMARY KEY,
account_id UUID NOT NULL,
source_id UUID,
language_tag VARCHAR,
study VARCHAR,
deleted BOOLEAN NOT NULL DEFAULT false,
creation_timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),

CONSTRAINT fk_skin_scoring_app_ffq_registry_account FOREIGN KEY (account_id) REFERENCES ag.account(id),
CONSTRAINT fk_skin_scoring_app_ffq_registry_source FOREIGN KEY (source_id) REFERENCES ag.source(id)
);

CREATE INDEX skin_scoring_app_ffq_registry_source ON ag.skin_scoring_app_ffq_registry (account_id, source_id);
122 changes: 121 additions & 1 deletion microsetta_private_api/repo/survey_template_repo.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import random
import string
from werkzeug.exceptions import NotFound

from microsetta_private_api.config_manager import SERVER_CONFIG
Expand All @@ -23,6 +25,7 @@ class SurveyTemplateRepo(BaseRepo):
MYFOODREPO_ID = 10002
POLYPHENOL_FFQ_ID = 10003
SPAIN_FFQ_ID = 10004
SKIN_SCORING_APP_FFQ_ID = 10005
BASIC_INFO_ID = 10
AT_HOME_ID = 11
LIFESTYLE_ID = 12
Expand Down Expand Up @@ -105,6 +108,12 @@ class SurveyTemplateRepo(BaseRepo):
"1.0",
"remote"
),
SKIN_SCORING_APP_FFQ_ID: SurveyTemplateLinkInfo(
SKIN_SCORING_APP_FFQ_ID,
"Skin Scoring App FFQ",
"1.0",
"remote"
),
BASIC_INFO_ID: SurveyTemplateLinkInfo(
BASIC_INFO_ID,
"Basic Information",
Expand Down Expand Up @@ -755,6 +764,115 @@ def delete_spain_ffq(self, account_id, source_id):
AND source_id=%s""",
(account_id, source_id))

def create_skin_scoring_app_ffq_entry(self,
account_id,
source_id,
language_tag,
study):
"""Return a newly created Skin Scoring App FFQ ID

Parameters
----------
account_id : str, UUID
The account UUID
source_id : str, UUID
The source UUID
language_tag: str
The user's language tag
study: str
The study variable we'll pass to L'Oréal's FFQ

Returns
-------
str
The newly created Skin Scoring App FFQ ID
"""
characters = string.ascii_lowercase + string.digits
skin_scoring_app_ffq_id = ''.join(random.choices(characters, k=8))

with self._transaction.cursor() as cur:
cur.execute("""INSERT INTO ag.skin_scoring_app_ffq_registry
(skin_scoring_app_ffq_id, account_id,
source_id, language_tag, study)
VALUES (%s, %s, %s, %s, %s)""",
(skin_scoring_app_ffq_id, account_id,
source_id, language_tag, study))
ayobi marked this conversation as resolved.
Show resolved Hide resolved

# Put a survey into ag_login_surveys
cur.execute("INSERT INTO ag_login_surveys("
"ag_login_id, "
"survey_id, "
"vioscreen_status, "
"source_id, "
"survey_template_id) "
"VALUES(%s, %s, %s, %s, %s)",
(account_id, skin_scoring_app_ffq_id, None, source_id,
SurveyTemplateRepo.SKIN_SCORING_APP_FFQ_ID))

return skin_scoring_app_ffq_id

def get_skin_scoring_app_ffq_id_if_exists(self,
account_id,
source_id):
"""Return a Skin Scoring App FFQ ID if one exists

Parameters
----------
account_id : str, UUID
The account UUID
source_id : str, UUID
The source UUID

Returns
-------
(UUID, str) or (None, None)
The associated Skin Scoring App FFQ ID and study
It's impossible to find one without the other
"""
with self._transaction.cursor() as cur:
cur.execute("""SELECT skin_scoring_app_ffq_id, study
FROM ag.skin_scoring_app_ffq_registry
WHERE account_id=%s AND source_id=%s""",
(account_id, source_id))
res = cur.fetchone()

if res is None:
return (None, None)
else:
return res

def delete_skin_scoring_app_ffq(self, account_id, source_id):
"""Intended for admin use, remove Skin Scoring App FFQ entries

This method is idempotent.

This method deletes ALL Skin Scoring App FFQ surveys associated with an
account and source

This is a hard delete, we REMOVE rows rather than setting a flag

Parameters
----------
account_id : str, UUID
The account UUID
source_id : str, UUID
The source UUID
"""
with self._transaction.cursor() as cur:
existing, _ = \
self.get_skin_scoring_app_ffq_id_if_exists(account_id,
source_id)
if existing is not None:
cur.execute("""DELETE FROM ag.ag_login_surveys
WHERE ag_login_id=%s
AND source_id=%s
AND survey_id=%s""",
(account_id, source_id, existing))
cur.execute("""DELETE FROM ag.skin_scoring_app_ffq_registry
WHERE account_id=%s
AND source_id=%s""",
(account_id, source_id))

def get_vioscreen_sample_to_user(self):
"""Obtain a mapping of sample barcode to vioscreen user"""
with self._transaction.cursor() as cur:
Expand Down Expand Up @@ -1127,6 +1245,7 @@ def has_external_surveys(self, account_id, source_id):
getters = (self.get_myfoodrepo_id_if_exists,
self.get_polyphenol_ffq_id_if_exists,
self.get_spain_ffq_id_if_exists,
self.get_skin_scoring_app_ffq_id_if_exists,
self.get_vioscreen_all_ids_if_exists)

for get in getters:
Expand Down Expand Up @@ -1306,7 +1425,8 @@ def _generate_empty_survey(self, survey_template_id, return_tuple=False):
if survey_template_id in [self.VIOSCREEN_ID,
self.MYFOODREPO_ID,
self.POLYPHENOL_FFQ_ID,
self.SPAIN_FFQ_ID]:
self.SPAIN_FFQ_ID,
self.SKIN_SCORING_APP_FFQ_ID]:
raise ValueError("survey_template_id must be for a local "
"survey")
else:
Expand Down
1 change: 1 addition & 0 deletions microsetta_private_api/server_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"fundrazr_organization": "fundrazr_org_placeholder",
"polyphenol_ffq_url": "pffq_placeholder",
"spain_ffq_url": "sffq_placeholder",
"skin_scoring_app_ffq_url": "ssafq_placeholder",
"fulfillment_account_id": "000fc4cd-8fa4-db8b-e050-8a800c5d81b7",
"google_geocoding_url": "https://maps.googleapis.com/maps/api/geocode/json",
"google_geocoding_key": "geocoding_key_placeholder",
Expand Down
12 changes: 12 additions & 0 deletions microsetta_private_api/util/skin_scoring_app_ffq.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from microsetta_private_api.config_manager import SERVER_CONFIG


def gen_ffq_url(skin_scoring_app_ffq_id, study, language_tag):
language_tag = language_tag.lower()

url = SERVER_CONFIG['skin_scoring_app_ffq_url']
url += f"?yid={skin_scoring_app_ffq_id}"
url += f"&country={language_tag}"
url += f"&study={study}"

return url
Loading