From 6562e938909d8d19e041f78c8a772dd320359037 Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Wed, 2 Nov 2022 16:23:40 -0700 Subject: [PATCH 01/13] Changes for THDMI Japan signups --- .../admin/email_templates.py | 8 + .../api/_interested_user.py | 20 ++ .../api/microsetta_private_api.yaml | 6 +- microsetta_private_api/db/patches/0103.sql | 1 + microsetta_private_api/localization.py | 1 + microsetta_private_api/model/campaign.py | 3 +- microsetta_private_api/model/log_event.py | 2 + microsetta_private_api/repo/campaign_repo.py | 25 +- .../repo/interested_user_repo.py | 1 + microsetta_private_api/server.py | 5 +- .../email/submit_interest_confirmation.jinja2 | 249 ++++++++++++++ .../ja_JP/LC_MESSAGES/messages.po | 304 ++++++++++++++++++ 12 files changed, 612 insertions(+), 13 deletions(-) create mode 100644 microsetta_private_api/db/patches/0103.sql create mode 100644 microsetta_private_api/templates/email/submit_interest_confirmation.jinja2 create mode 100644 microsetta_private_api/translations/ja_JP/LC_MESSAGES/messages.po diff --git a/microsetta_private_api/admin/email_templates.py b/microsetta_private_api/admin/email_templates.py index 31b102dc5..442121bdc 100644 --- a/microsetta_private_api/admin/email_templates.py +++ b/microsetta_private_api/admin/email_templates.py @@ -71,6 +71,14 @@ class EmailMessage(Enum): EventType.EMAIL, EventSubtype.EMAIL_ADDRESS_INVALID ) + submit_interest_confirmation = ( + gettext( + "We received your sign-up"), + "email/submit_interest_confirmation.jinja2", + ("contact_name",), + EventType.EMAIL, + EventSubtype.EMAIL_SUBMIT_INTEREST_CONFIRMATION + ) def __init__(self, subject, html, required, event_type, event_sub): self.subject = subject diff --git a/microsetta_private_api/api/_interested_user.py b/microsetta_private_api/api/_interested_user.py index 0bdeed1fe..9845053c2 100644 --- a/microsetta_private_api/api/_interested_user.py +++ b/microsetta_private_api/api/_interested_user.py @@ -5,6 +5,7 @@ from microsetta_private_api.repo.interested_user_repo import InterestedUserRepo from microsetta_private_api.repo.transaction import Transaction from microsetta_private_api.exceptions import RepoException +from microsetta_private_api.repo.campaign_repo import CampaignRepo def create_interested_user(body): @@ -29,6 +30,25 @@ def create_interested_user(body): message="Failed to create interested user." ), 400 + if interested_user_id: + campaign_repo = CampaignRepo(t) + campaign_info =\ + campaign_repo.get_campaign_by_id(interested_user.campaign_id) + + if campaign_info.send_thdmi_confirmation: + try: + # Send a confirmation email + # TODO: Add more intelligent locale determination. + # Punting on that since our current campaign use cases + # are only a single language. + send_email(interested_user.email, + "submit_interest_confirmation", + {"contact_name": interested_user.first_name}, + campaign_info.language_key) + except: # noqa + # try our best to email + pass + t.commit() # opening a new transaction for address verification so we don't lose the diff --git a/microsetta_private_api/api/microsetta_private_api.yaml b/microsetta_private_api/api/microsetta_private_api.yaml index 497d1e217..5e0bededc 100644 --- a/microsetta_private_api/api/microsetta_private_api.yaml +++ b/microsetta_private_api/api/microsetta_private_api.yaml @@ -1482,6 +1482,8 @@ paths: type: string 'extension': type: string + 'send_thdmi_confirmation': + type: string required: - title - associated_projects @@ -1531,6 +1533,8 @@ paths: type: string 'extension': type: string + 'send_thdmi_confirmation': + type: string required: - campaign_id - title @@ -2731,7 +2735,7 @@ components: example: "standard" language: type: string - enum: ["en_US", "es_MX", "es_ES"] + enum: ["en_US", "es_MX", "es_ES", "ja_JP"] example: "en_US" creation_time: type: string diff --git a/microsetta_private_api/db/patches/0103.sql b/microsetta_private_api/db/patches/0103.sql new file mode 100644 index 000000000..c8dbbad3e --- /dev/null +++ b/microsetta_private_api/db/patches/0103.sql @@ -0,0 +1 @@ +ALTER TABLE campaign.campaigns ADD COLUMN send_thdmi_confirmation BOOLEAN DEFAULT FALSE; diff --git a/microsetta_private_api/localization.py b/microsetta_private_api/localization.py index 981f631b5..5359d4be7 100644 --- a/microsetta_private_api/localization.py +++ b/microsetta_private_api/localization.py @@ -5,6 +5,7 @@ EN_GB = "en_GB" ES_MX = "es_MX" ES_ES = "es_ES" +JA_JP = "ja_JP" NEW_PARTICIPANT_KEY = "new_participant" LANG_NAME_KEY = "lang_name" diff --git a/microsetta_private_api/model/campaign.py b/microsetta_private_api/model/campaign.py index 3453c9465..0b882098d 100644 --- a/microsetta_private_api/model/campaign.py +++ b/microsetta_private_api/model/campaign.py @@ -316,7 +316,7 @@ class Campaign(ModelBase): def __init__(self, campaign_id, title, instructions, header_image, permitted_countries, language_key, accepting_participants, associated_projects, language_key_alt, title_alt, - instructions_alt): + instructions_alt, send_thdmi_confirmation): self.campaign_id = campaign_id self.title = title self.instructions = instructions @@ -328,6 +328,7 @@ def __init__(self, campaign_id, title, instructions, header_image, self.language_key_alt = language_key_alt self.title_alt = title_alt self.instructions_alt = instructions_alt + self.send_thdmi_confirmation = send_thdmi_confirmation def to_api(self): return self.__dict__.copy() diff --git a/microsetta_private_api/model/log_event.py b/microsetta_private_api/model/log_event.py index 126754509..98b09c855 100644 --- a/microsetta_private_api/model/log_event.py +++ b/microsetta_private_api/model/log_event.py @@ -46,6 +46,8 @@ class EventSubtype(Enum): EMAIL_PER_PROJECT_SUMMARY = "per_project_summary" # for addresses that Melissa deems invalid EMAIL_ADDRESS_INVALID = "address_invalid" + # for confirmation emails of interested user signups + EMAIL_SUBMIT_INTEREST_CONFIRMATION = "submit_interest_confirmation" class LogEvent(ModelBase): diff --git a/microsetta_private_api/repo/campaign_repo.py b/microsetta_private_api/repo/campaign_repo.py index 7c7cb7a79..2c2298071 100644 --- a/microsetta_private_api/repo/campaign_repo.py +++ b/microsetta_private_api/repo/campaign_repo.py @@ -28,7 +28,8 @@ def _campaign_to_row(c): return (c.campaign_id, c.title, c.instructions, c.header_image, c.permitted_countries, c.language_key, c.accepting_participants, '', - c.language_key_alt, c.title_alt, c.instructions_alt) + c.language_key_alt, c.title_alt, c.instructions_alt, + send_thdmi_confirmation) def _row_to_campaign(self, r): associated_projects = ", ".join(self._get_projects(r['campaign_id'])) @@ -36,7 +37,8 @@ def _row_to_campaign(self, r): r['header_image'], r['permitted_countries'], r['language_key'], r['accepting_participants'], associated_projects, r['language_key_alt'], - r['title_alt'], r['instructions_alt']) + r['title_alt'], r['instructions_alt'], + r['send_thdmi_confirmation']) def _get_projects(self, campaign_id): with self._transaction.cursor() as cur: @@ -66,7 +68,7 @@ def get_all_campaigns(self): "SELECT campaign_id, title, instructions, header_image, " "permitted_countries, language_key, accepting_participants, " "language_key_alt, title_alt, " - "instructions_alt " + "instructions_alt, send_thdmi_confirmation " "FROM campaign.campaigns ORDER BY title" ) rows = cur.fetchall() @@ -86,24 +88,26 @@ def create_campaign(self, **kwargs): title_alt = kwargs.get('title_alt') instructions_alt = kwargs.get('instructions_alt') extension = kwargs.get('extension') + send_thdmi_confirmation = kwargs.get('send_thdmi_confirmation') with self._transaction.cursor() as cur: cur.execute( "INSERT INTO campaign.campaigns (title, instructions, " "permitted_countries, language_key, accepting_participants, " "language_key_alt, title_alt, " - "instructions_alt) " - "VALUES (%s, %s, %s, %s, %s, %s, %s, %s) " + "instructions_alt, send_thdmi_confirmation) " + "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) " "RETURNING campaign_id", (title, instructions, permitted_countries, language_key, accepting_participants, language_key_alt, title_alt, - instructions_alt) + instructions_alt, send_thdmi_confirmation) ) campaign_id = cur.fetchone()[0] if campaign_id is None: raise RepoException("Error inserting campaign into database") else: + associated_projects = associated_projects.split(",") cur.executemany( "INSERT INTO campaign.campaigns_projects (" "campaign_id,project_id" @@ -132,17 +136,19 @@ def update_campaign(self, **kwargs): title_alt = kwargs.get('title_alt') instructions_alt = kwargs.get('instructions_alt') extension = kwargs.get('extension') + send_thdmi_confirmation = kwargs.get('send_thdmi_confirmation') with self._transaction.cursor() as cur: cur.execute( "UPDATE campaign.campaigns SET title = %s, instructions = %s, " "permitted_countries = %s, language_key = %s, " "accepting_participants = %s, language_key_alt = %s, " - "title_alt = %s, instructions_alt = %s " + "title_alt = %s, instructions_alt = %s, " + "send_thdmi_confirmation = %s " "WHERE campaign_id = %s", (title, instructions, permitted_countries, language_key, accepting_participants, language_key_alt, title_alt, - instructions_alt, campaign_id) + instructions_alt, send_thdmi_confirmation, campaign_id) ) self.update_header_image(campaign_id, extension) @@ -156,7 +162,8 @@ def get_campaign_by_id(self, campaign_id): "SELECT campaign_id, title, instructions, header_image, " "permitted_countries, language_key, " "accepting_participants, " - "language_key_alt, title_alt, instructions_alt " + "language_key_alt, title_alt, instructions_alt, " + "send_thdmi_confirmation " "FROM campaign.campaigns WHERE campaign_id = %s", (campaign_id,) ) diff --git a/microsetta_private_api/repo/interested_user_repo.py b/microsetta_private_api/repo/interested_user_repo.py index c09c20e83..d5c2ed9c3 100644 --- a/microsetta_private_api/repo/interested_user_repo.py +++ b/microsetta_private_api/repo/interested_user_repo.py @@ -4,6 +4,7 @@ from microsetta_private_api.exceptions import RepoException from microsetta_private_api.model.interested_user import InterestedUser from microsetta_private_api.util.melissa import verify_address +from microsetta_private_api.tasks import send_email class InterestedUserRepo(BaseRepo): diff --git a/microsetta_private_api/server.py b/microsetta_private_api/server.py index 200996a7c..8109945f0 100644 --- a/microsetta_private_api/server.py +++ b/microsetta_private_api/server.py @@ -9,7 +9,7 @@ from microsetta_private_api.exceptions import RepoException from microsetta_private_api.celery_utils import celery, init_celery -from microsetta_private_api.localization import EN_US, ES_MX, ES_ES +from microsetta_private_api.localization import EN_US, ES_MX, ES_ES, JA_JP """ @@ -85,7 +85,8 @@ def get_locale(): if not flask.has_request_context(): return EN_US - return request.accept_languages.best_match([EN_US, ES_ES, ES_MX], + return request.accept_languages.best_match([EN_US, ES_ES, ES_MX, + JA_JP], default=EN_US) init_celery(celery, app.app) diff --git a/microsetta_private_api/templates/email/submit_interest_confirmation.jinja2 b/microsetta_private_api/templates/email/submit_interest_confirmation.jinja2 new file mode 100644 index 000000000..2e7a5bebd --- /dev/null +++ b/microsetta_private_api/templates/email/submit_interest_confirmation.jinja2 @@ -0,0 +1,249 @@ + + + + + + +

+

+ {{ _("Dear") }} {{contact_name |e}}, +

+

 

+

+ {{ _("On behalf of Danone Nutricia Research and The Microsetta Initiative (TMI) at UC San Diego, we would like to thank you for your interest in participating in our research study THDMI - The Human Diets and Microbiome Initiative.") }} +

+

+ +

+

+ {{ _("Soon you will receive an email letting you know if you were one of the first 800 individuals who signed up to participate in the project and what the next steps will be to take part. ") }} +

+

+   +

+

+ {{ _("We are also here to help! Our team is ready to assist you with any questions you may have. Please contact us at") }} microsetta@ucsd.edu +

+

 

+

{{ _("Thank you,") }}

+

{{ _("The Microsetta Team") }}

+

+   +

+

+ {{ _('Tip') }}: {{ _("To ensure our emails make it to your Inbox, not your SPAM folder, remember to add us to your safe sender's list.") }} +

+ + + diff --git a/microsetta_private_api/translations/ja_JP/LC_MESSAGES/messages.po b/microsetta_private_api/translations/ja_JP/LC_MESSAGES/messages.po new file mode 100644 index 000000000..a7838ace0 --- /dev/null +++ b/microsetta_private_api/translations/ja_JP/LC_MESSAGES/messages.po @@ -0,0 +1,304 @@ +# Japanese (Japan) translations for PROJECT. +# Copyright (C) 2022 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2022-11-01 16:48-0700\n" +"PO-Revision-Date: 2022-11-01 16:48-0700\n" +"Last-Translator: FULL NAME \n" +"Language: ja_JP\n" +"Language-Team: ja_JP \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.11.0\n" + +#: admin/email_templates.py:22 +msgid "Welcome to The Microsetta Initiative" +msgstr "" + +#: admin/email_templates.py:29 +msgid "Your Microsetta Initiative status update: attention needed" +msgstr "" + +#: admin/email_templates.py:37 admin/email_templates.py:67 +msgid "Your Microsetta Initiative status update: information needed" +msgstr "" + +#: admin/email_templates.py:45 +msgid "Your Microsetta Initiative status update and next steps" +msgstr "" + +#: admin/email_templates.py:52 +msgid "Your Microsetta Initiative status update: critical information needed" +msgstr "" + +#: admin/email_templates.py:60 +msgid "[PESTER] a thing happened" +msgstr "" + +#: admin/email_templates.py:75 +msgid "We received your sign-up" +msgstr "" + +#: templates/email/activation_email.jinja2:221 +msgid "" +"Thank you for your interest and participation in The Microsetta " +"Initiative. We will be shipping out your sample collection kit(s) soon." +msgstr "" + +#: templates/email/activation_email.jinja2:225 +msgid "" +"The kit(s) may still be en route, but you don't have to pause your " +"journey just yet. You can sign up right now to get started at " +msgstr "" + +#: templates/email/activation_email.jinja2:225 +msgid "using the following info:" +msgstr "" + +#: templates/email/activation_email.jinja2:228 +msgid "Email:" +msgstr "" + +#: templates/email/activation_email.jinja2:229 +msgid "Activation Code:" +msgstr "" + +#: templates/email/activation_email.jinja2:234 +msgid "" +"Not your first foray into the microbiome? No problem, you don't need to " +"sign up again, your kit(s) can be added to your existing account when the" +" order arrives." +msgstr "" + +#: templates/email/activation_email.jinja2:238 +#: templates/email/incorrect_sample_type.jinja2:239 +#: templates/email/missing_sample_info.jinja2:269 +#: templates/email/sample_is_valid.jinja2:228 +msgid "If you have any questions, please reply to us at " +msgstr "" + +#: templates/email/activation_email.jinja2:238 +#: templates/email/incorrect_sample_type.jinja2:239 +#: templates/email/sample_is_valid.jinja2:228 +msgid "Thank you for supporting our project." +msgstr "" + +#: templates/email/activation_email.jinja2:242 +#: templates/email/incorrect_sample_type.jinja2:243 +msgid "Sincerely," +msgstr "" + +#: templates/email/activation_email.jinja2:245 +#: templates/email/address_invalid.jinja2:250 +#: templates/email/incorrect_sample_type.jinja2:246 +#: templates/email/missing_sample_info.jinja2:273 +#: templates/email/no_associated_source.jinja2:276 +#: templates/email/sample_is_valid.jinja2:235 +#: templates/email/submit_interest_confirmation.jinja2:240 +msgid "The Microsetta Team" +msgstr "" + +#: templates/email/address_invalid.jinja2:220 +#: templates/email/incorrect_sample_type.jinja2:220 +#: templates/email/missing_sample_info.jinja2:220 +#: templates/email/no_associated_source.jinja2:220 +#: templates/email/sample_is_valid.jinja2:220 +msgid "Hello" +msgstr "" + +#: templates/email/address_invalid.jinja2:224 +msgid "" +"Thank you for your interest and participation in The Microsetta " +"Initiative. We are writing as we've encountered an issue processing your " +"transaction, and we would appreciate your assistance in helping to " +"resolve this matter." +msgstr "" + +#: templates/email/address_invalid.jinja2:226 +msgid "" +"Specifically, we were unable to verify the address to which you requested" +" we ship you kit(s)." +msgstr "" + +#: templates/email/address_invalid.jinja2:232 +msgid "" +"To resolve this issue and ensure we have a valid shipping address, please" +" click the following link or copy and paste the URL into your browser:" +msgstr "" + +#: templates/email/address_invalid.jinja2:246 +#: templates/email/no_associated_source.jinja2:272 +msgid "If you have any questions, please reply to us at" +msgstr "" + +#: templates/email/address_invalid.jinja2:249 +#: templates/email/missing_sample_info.jinja2:272 +#: templates/email/no_associated_source.jinja2:275 +#: templates/email/submit_interest_confirmation.jinja2:239 +msgid "Thank you," +msgstr "" + +#: templates/email/incorrect_sample_type.jinja2:224 +msgid "" +"We recently received the following microbiome sample from you and noticed" +" that it might have been incorrectly labeled." +msgstr "" + +#: templates/email/incorrect_sample_type.jinja2:229 +msgid "Marked" +msgstr "" + +#: templates/email/incorrect_sample_type.jinja2:229 +msgid "but appears to be" +msgstr "" + +#: templates/email/incorrect_sample_type.jinja2:236 +msgid "" +"Our lab will need verification of the type of sample you sent in before " +"they can begin processing it to ensure that your sample is sequenced " +"correctly. If you know the sample type then please reply to this email" +msgstr "" + +#: templates/email/incorrect_sample_type.jinja2:236 +msgid "" +"with this information. We will then update your profile so the collection" +" can be appropriately associated." +msgstr "" + +#: templates/email/missing_sample_info.jinja2:224 +msgid "" +"Thank you for your interest and participation in The Microsetta " +"Initiative. We are writing as we've encountered an issue processing your " +"sample, and we would appreciate your assistance in helping to resolve " +"this matter. To make sure we have the correct information, we require you" +" to confirm the type of sample you sent and the collection date and time " +"with our team. Please click on the URL below to view the collection " +"information." +msgstr "" + +#: templates/email/missing_sample_info.jinja2:236 +msgid "Based on what we can see, we think the collection type is:" +msgstr "" + +#: templates/email/missing_sample_info.jinja2:250 +msgid "" +"We require this information in order to process the collection in " +"compliance with our human subjects research protocol. Therefore, editing " +"online account information is currently locked as a preventative measure " +"to ensure we meet regulations. Not to worry - by replying to this email " +"our team is ready to assist you with updating the following information." +msgstr "" + +#: templates/email/missing_sample_info.jinja2:254 +#: templates/email/no_associated_source.jinja2:263 +msgid "Collection date" +msgstr "" + +#: templates/email/missing_sample_info.jinja2:255 +#: templates/email/no_associated_source.jinja2:264 +msgid "Collection time" +msgstr "" + +#: templates/email/missing_sample_info.jinja2:256 +#: templates/email/no_associated_source.jinja2:265 +msgid "Collection type" +msgstr "" + +#: templates/email/missing_sample_info.jinja2:263 +msgid "" +"Once we have these details, we will update the record so the specimen can" +" be processed appropriately." +msgstr "" + +#: templates/email/no_associated_source.jinja2:224 +msgid "" +"Thank you for your interest and participation in The Microsetta " +"Initiative. We are writing as we've encountered an issue processing your " +"collection, and we would appreciate your assistance in helping to resolve" +" this matter." +msgstr "" + +#: templates/email/no_associated_source.jinja2:226 +msgid "" +"Specifically, the following sample sent to the lab needs more information" +" to be included before it can be processed:" +msgstr "" + +#: templates/email/no_associated_source.jinja2:238 +msgid "" +"We require this information to process this specimen in compliance with " +"our human subjects research protocol. Please log back into the " +"participant website by clicking or copying the following URL:" +msgstr "" + +#: templates/email/no_associated_source.jinja2:245 +msgid "Your account" +msgstr "" + +#: templates/email/no_associated_source.jinja2:252 +msgid "" +"After accessing your account using the above URL, you will need to create" +" a source by clicking on one of the buttons under the \"Sources\" " +"section." +msgstr "" + +#: templates/email/no_associated_source.jinja2:258 +msgid "" +"Once a source has been created, please reply to this email with the " +"following information so that we can link the collection to your source:" +msgstr "" + +#: templates/email/sample_is_valid.jinja2:224 +msgid "" +"Thank you for your interest and participation in The Microsetta " +"Initiative. We have received your microbiome collection, and it is now in" +" the processing queue. Samples are processed within 1 – 3 months. Once " +"sequenced, you will receive an update with a link to your results." +msgstr "" + +#: templates/email/sample_is_valid.jinja2:232 +msgid "Kind regards," +msgstr "" + +#: templates/email/submit_interest_confirmation.jinja2:220 +msgid "Dear" +msgstr "" + +#: templates/email/submit_interest_confirmation.jinja2:224 +msgid "" +"On behalf of Danone Nutricia Research and The Microsetta Initiative (TMI)" +" at UC San Diego, we would like to thank you for your interest in " +"participating in our research study THDMI - The Human Diets and " +"Microbiome Initiative." +msgstr "" + +#: templates/email/submit_interest_confirmation.jinja2:230 +msgid "" +"Soon you will receive an email letting you know if you were one of the " +"first 800 individuals who signed up to participate in the project and " +"what the next steps will be to take part. " +msgstr "" + +#: templates/email/submit_interest_confirmation.jinja2:236 +msgid "" +"We are also here to help! Our team is ready to assist you with any " +"questions you may have. Please contact us at" +msgstr "" + +#: templates/email/submit_interest_confirmation.jinja2:245 +msgid "Tip" +msgstr "" + +#: templates/email/submit_interest_confirmation.jinja2:245 +msgid "" +"To ensure our emails make it to your Inbox, not your SPAM folder, " +"remember to add us to your safe sender's list." +msgstr "" + From 5563387b24e1cea06f347dd8184259bbc6ade20a Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Wed, 2 Nov 2022 16:28:28 -0700 Subject: [PATCH 02/13] Lint fixes --- microsetta_private_api/api/_interested_user.py | 1 + microsetta_private_api/repo/campaign_repo.py | 2 +- microsetta_private_api/repo/interested_user_repo.py | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/microsetta_private_api/api/_interested_user.py b/microsetta_private_api/api/_interested_user.py index 9845053c2..7da66e38e 100644 --- a/microsetta_private_api/api/_interested_user.py +++ b/microsetta_private_api/api/_interested_user.py @@ -6,6 +6,7 @@ from microsetta_private_api.repo.transaction import Transaction from microsetta_private_api.exceptions import RepoException from microsetta_private_api.repo.campaign_repo import CampaignRepo +from microsetta_private_api.tasks import send_email def create_interested_user(body): diff --git a/microsetta_private_api/repo/campaign_repo.py b/microsetta_private_api/repo/campaign_repo.py index 2c2298071..fd26f4683 100644 --- a/microsetta_private_api/repo/campaign_repo.py +++ b/microsetta_private_api/repo/campaign_repo.py @@ -29,7 +29,7 @@ def _campaign_to_row(c): c.permitted_countries, c.language_key, c.accepting_participants, '', c.language_key_alt, c.title_alt, c.instructions_alt, - send_thdmi_confirmation) + c.send_thdmi_confirmation) def _row_to_campaign(self, r): associated_projects = ", ".join(self._get_projects(r['campaign_id'])) diff --git a/microsetta_private_api/repo/interested_user_repo.py b/microsetta_private_api/repo/interested_user_repo.py index d5c2ed9c3..c09c20e83 100644 --- a/microsetta_private_api/repo/interested_user_repo.py +++ b/microsetta_private_api/repo/interested_user_repo.py @@ -4,7 +4,6 @@ from microsetta_private_api.exceptions import RepoException from microsetta_private_api.model.interested_user import InterestedUser from microsetta_private_api.util.melissa import verify_address -from microsetta_private_api.tasks import send_email class InterestedUserRepo(BaseRepo): From 0db71e4e37525fe93d566b7d6477908fc12635ea Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Wed, 2 Nov 2022 16:37:28 -0700 Subject: [PATCH 03/13] Tuple->string->list fix --- microsetta_private_api/repo/campaign_repo.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/microsetta_private_api/repo/campaign_repo.py b/microsetta_private_api/repo/campaign_repo.py index fd26f4683..38806dada 100644 --- a/microsetta_private_api/repo/campaign_repo.py +++ b/microsetta_private_api/repo/campaign_repo.py @@ -107,6 +107,9 @@ def create_campaign(self, **kwargs): if campaign_id is None: raise RepoException("Error inserting campaign into database") else: + # Python is assuming associated_project is a tuple. + # Convert to string so we can then convert to a list. + associated_projects = ','.join(associated_projects) associated_projects = associated_projects.split(",") cur.executemany( "INSERT INTO campaign.campaigns_projects (" From 444669bca09b098b06498de02f2cbe85ff46fc7c Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Wed, 2 Nov 2022 17:11:30 -0700 Subject: [PATCH 04/13] Associated Projects type fix --- microsetta_private_api/repo/campaign_repo.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/microsetta_private_api/repo/campaign_repo.py b/microsetta_private_api/repo/campaign_repo.py index 38806dada..8e9df80dd 100644 --- a/microsetta_private_api/repo/campaign_repo.py +++ b/microsetta_private_api/repo/campaign_repo.py @@ -107,10 +107,18 @@ def create_campaign(self, **kwargs): if campaign_id is None: raise RepoException("Error inserting campaign into database") else: - # Python is assuming associated_project is a tuple. - # Convert to string so we can then convert to a list. - associated_projects = ','.join(associated_projects) - associated_projects = associated_projects.split(",") + # This code is not ideal but the various campaign creation + # methods pass several different datatypes in. + if isinstance(associated_projects, tuple): + associated_projects = list(associated_projects) + elif isinstance(associated_projects, str): + if "," in associated_projects: + associated_projects = associated_projects.split(",") + else: + associated_projects = [associated_projects, ] + elif isinstance(associated_projects, int): + associated_projects = [associated_projects, ] + cur.executemany( "INSERT INTO campaign.campaigns_projects (" "campaign_id,project_id" From 54e451d19196bfce1d9cf54ca9355e70ea434d51 Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Wed, 2 Nov 2022 17:21:09 -0700 Subject: [PATCH 05/13] Fixing relativedelta usage --- microsetta_private_api/api/tests/test_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/microsetta_private_api/api/tests/test_api.py b/microsetta_private_api/api/tests/test_api.py index 81fb26d01..2919ab0a3 100644 --- a/microsetta_private_api/api/tests/test_api.py +++ b/microsetta_private_api/api/tests/test_api.py @@ -1799,7 +1799,7 @@ def test_edit_sample_locked(self): # if sample date is less than 10 years now = datetime.datetime.now() - delta = relativedelta(year=now.year-11) + delta = relativedelta(years=now.year-11) date = now+delta post_resp = self.client.put( '%s?%s' % (base_url, self.default_lang_querystring), @@ -1818,7 +1818,7 @@ def test_edit_sample_locked(self): # if sample date is greater than 30 days now = datetime.datetime.now() - delta = relativedelta(month=now.month+2) + delta = relativedelta(months=now.month+2) date = now+delta post_resp = self.client.put( '%s?%s' % (base_url, self.default_lang_querystring), From 864470614dc80941c5e828fcaa64f6c70a2de03d Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Thu, 3 Nov 2022 09:46:30 -0700 Subject: [PATCH 06/13] Add NOT NULL to column definition --- microsetta_private_api/db/patches/0103.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsetta_private_api/db/patches/0103.sql b/microsetta_private_api/db/patches/0103.sql index c8dbbad3e..e59e9d637 100644 --- a/microsetta_private_api/db/patches/0103.sql +++ b/microsetta_private_api/db/patches/0103.sql @@ -1 +1 @@ -ALTER TABLE campaign.campaigns ADD COLUMN send_thdmi_confirmation BOOLEAN DEFAULT FALSE; +ALTER TABLE campaign.campaigns ADD COLUMN send_thdmi_confirmation BOOLEAN NOT NULL DEFAULT FALSE; From 7d9f81f74327e116f149a3192174e97ce19156c0 Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Thu, 3 Nov 2022 09:48:35 -0700 Subject: [PATCH 07/13] Remove unnecessary if statement --- .../api/_interested_user.py | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/microsetta_private_api/api/_interested_user.py b/microsetta_private_api/api/_interested_user.py index 7da66e38e..a824607f0 100644 --- a/microsetta_private_api/api/_interested_user.py +++ b/microsetta_private_api/api/_interested_user.py @@ -31,24 +31,23 @@ def create_interested_user(body): message="Failed to create interested user." ), 400 - if interested_user_id: - campaign_repo = CampaignRepo(t) - campaign_info =\ - campaign_repo.get_campaign_by_id(interested_user.campaign_id) - - if campaign_info.send_thdmi_confirmation: - try: - # Send a confirmation email - # TODO: Add more intelligent locale determination. - # Punting on that since our current campaign use cases - # are only a single language. - send_email(interested_user.email, - "submit_interest_confirmation", - {"contact_name": interested_user.first_name}, - campaign_info.language_key) - except: # noqa - # try our best to email - pass + campaign_repo = CampaignRepo(t) + campaign_info =\ + campaign_repo.get_campaign_by_id(interested_user.campaign_id) + + if campaign_info.send_thdmi_confirmation: + try: + # Send a confirmation email + # TODO: Add more intelligent locale determination. + # Punting on that since our current campaign use cases + # are only a single language. + send_email(interested_user.email, + "submit_interest_confirmation", + {"contact_name": interested_user.first_name}, + campaign_info.language_key) + except: # noqa + # try our best to email + pass t.commit() From 52c80ae6b19346314c9e6079432c578ca8af4a4a Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Thu, 3 Nov 2022 09:54:39 -0700 Subject: [PATCH 08/13] Simplify conversion from string to list --- microsetta_private_api/repo/campaign_repo.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/microsetta_private_api/repo/campaign_repo.py b/microsetta_private_api/repo/campaign_repo.py index 8e9df80dd..35b02ca1d 100644 --- a/microsetta_private_api/repo/campaign_repo.py +++ b/microsetta_private_api/repo/campaign_repo.py @@ -112,10 +112,7 @@ def create_campaign(self, **kwargs): if isinstance(associated_projects, tuple): associated_projects = list(associated_projects) elif isinstance(associated_projects, str): - if "," in associated_projects: - associated_projects = associated_projects.split(",") - else: - associated_projects = [associated_projects, ] + associated_projects = associated_projects.split(",") elif isinstance(associated_projects, int): associated_projects = [associated_projects, ] From 7e0a5336e54de335a7be8d9dc45f0b2439852e41 Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Thu, 3 Nov 2022 10:18:59 -0700 Subject: [PATCH 09/13] Fix default value for send_thdmi_confirmation --- microsetta_private_api/repo/campaign_repo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsetta_private_api/repo/campaign_repo.py b/microsetta_private_api/repo/campaign_repo.py index 35b02ca1d..44f475ed8 100644 --- a/microsetta_private_api/repo/campaign_repo.py +++ b/microsetta_private_api/repo/campaign_repo.py @@ -88,7 +88,7 @@ def create_campaign(self, **kwargs): title_alt = kwargs.get('title_alt') instructions_alt = kwargs.get('instructions_alt') extension = kwargs.get('extension') - send_thdmi_confirmation = kwargs.get('send_thdmi_confirmation') + send_thdmi_confirmation = kwargs.get('send_thdmi_confirmation', False) with self._transaction.cursor() as cur: cur.execute( From 926aed9bfc290fbad1be2d550afe759f6dd7d361 Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Thu, 3 Nov 2022 10:34:46 -0700 Subject: [PATCH 10/13] Add test for associated_projects bugfix --- .../repo/tests/test_campaign_repo.py | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/microsetta_private_api/repo/tests/test_campaign_repo.py b/microsetta_private_api/repo/tests/test_campaign_repo.py index 77d9dbf60..3053281ae 100644 --- a/microsetta_private_api/repo/tests/test_campaign_repo.py +++ b/microsetta_private_api/repo/tests/test_campaign_repo.py @@ -305,6 +305,51 @@ def test_create_campaign_invalid(self): with self.assertRaises(ForeignKeyViolation): campaign_repo.create_campaign(**campaign_bad_projects) + def test_create_campaign_projects_bug(self): + # verify that a three-digit number is treated as one project ID + with Transaction() as t: + new_campaign = { + "title": "Unique Campaign Name", + "associated_projects": "145" + } + campaign_repo = CampaignRepo(t) + obs = campaign_repo.create_campaign(**new_campaign) + self.assertEqual(obs.associated_projects, "145") + t.rollback() + + # verify that a comma-delimited string stores separate IDs + with Transaction() as t: + new_campaign = { + "title": "Unique Campaign Name", + "associated_projects": "145, 147" + } + campaign_repo = CampaignRepo(t) + obs = campaign_repo.create_campaign(**new_campaign) + self.assertEqual(obs.associated_projects, "145, 147") + t.rollback() + + # verify that a list of strings stores separate IDs + with Transaction() as t: + new_campaign = { + "title": "Unique Campaign Name", + "associated_projects": ["145", "147"] + } + campaign_repo = CampaignRepo(t) + obs = campaign_repo.create_campaign(**new_campaign) + self.assertEqual(obs.associated_projects, "145, 147") + t.rollback() + + # verify that a list of ints stores separate IDs + with Transaction() as t: + new_campaign = { + "title": "Unique Campaign Name", + "associated_projects": [145, 147] + } + campaign_repo = CampaignRepo(t) + obs = campaign_repo.create_campaign(**new_campaign) + self.assertEqual(obs.associated_projects, "145, 147") + t.rollback() + def test_get_campaign_by_id_valid(self): # verify that it does not return None when using valid campaign_id with Transaction() as t: From a24c8099aefd119854efd992f0a84f8552065596 Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Thu, 3 Nov 2022 10:44:17 -0700 Subject: [PATCH 11/13] Fix project IDs in test --- .../repo/tests/test_campaign_repo.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/microsetta_private_api/repo/tests/test_campaign_repo.py b/microsetta_private_api/repo/tests/test_campaign_repo.py index 3053281ae..2dee2ac7f 100644 --- a/microsetta_private_api/repo/tests/test_campaign_repo.py +++ b/microsetta_private_api/repo/tests/test_campaign_repo.py @@ -306,48 +306,48 @@ def test_create_campaign_invalid(self): campaign_repo.create_campaign(**campaign_bad_projects) def test_create_campaign_projects_bug(self): - # verify that a three-digit number is treated as one project ID + # verify that a two-digit number is treated as one project ID with Transaction() as t: new_campaign = { "title": "Unique Campaign Name", - "associated_projects": "145" + "associated_projects": "45" } campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) - self.assertEqual(obs.associated_projects, "145") + self.assertEqual(obs.associated_projects, "45") t.rollback() # verify that a comma-delimited string stores separate IDs with Transaction() as t: new_campaign = { "title": "Unique Campaign Name", - "associated_projects": "145, 147" + "associated_projects": "45, 47" } campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) - self.assertEqual(obs.associated_projects, "145, 147") + self.assertEqual(obs.associated_projects, "45, 47") t.rollback() # verify that a list of strings stores separate IDs with Transaction() as t: new_campaign = { "title": "Unique Campaign Name", - "associated_projects": ["145", "147"] + "associated_projects": ["45", "47"] } campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) - self.assertEqual(obs.associated_projects, "145, 147") + self.assertEqual(obs.associated_projects, "45, 47") t.rollback() # verify that a list of ints stores separate IDs with Transaction() as t: new_campaign = { "title": "Unique Campaign Name", - "associated_projects": [145, 147] + "associated_projects": [45, 47] } campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) - self.assertEqual(obs.associated_projects, "145, 147") + self.assertEqual(obs.associated_projects, "45, 47") t.rollback() def test_get_campaign_by_id_valid(self): From 95afa044e0c4bcb0ca9d0382f1825024f7171338 Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Thu, 3 Nov 2022 11:03:49 -0700 Subject: [PATCH 12/13] Fix project IDs in test --- .../repo/tests/test_campaign_repo.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/microsetta_private_api/repo/tests/test_campaign_repo.py b/microsetta_private_api/repo/tests/test_campaign_repo.py index 2dee2ac7f..dfb41def0 100644 --- a/microsetta_private_api/repo/tests/test_campaign_repo.py +++ b/microsetta_private_api/repo/tests/test_campaign_repo.py @@ -310,44 +310,47 @@ def test_create_campaign_projects_bug(self): with Transaction() as t: new_campaign = { "title": "Unique Campaign Name", - "associated_projects": "45" + "associated_projects": "46" } campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) - self.assertEqual(obs.associated_projects, "45") + self.assertEqual(obs.associated_projects, "Project - qó1]øJçY\@") t.rollback() # verify that a comma-delimited string stores separate IDs with Transaction() as t: new_campaign = { "title": "Unique Campaign Name", - "associated_projects": "45, 47" + "associated_projects": "46, 48" } campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) - self.assertEqual(obs.associated_projects, "45, 47") + self.assertEqual(obs.associated_projects, + "Project - qó1]øJçY\@, Project - ÅQ%PáiZ!š@") t.rollback() # verify that a list of strings stores separate IDs with Transaction() as t: new_campaign = { "title": "Unique Campaign Name", - "associated_projects": ["45", "47"] + "associated_projects": ["46", "48"] } campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) - self.assertEqual(obs.associated_projects, "45, 47") + self.assertEqual(obs.associated_projects, + "Project - qó1]øJçY\@, Project - ÅQ%PáiZ!š@") t.rollback() # verify that a list of ints stores separate IDs with Transaction() as t: new_campaign = { "title": "Unique Campaign Name", - "associated_projects": [45, 47] + "associated_projects": [46, 48] } campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) - self.assertEqual(obs.associated_projects, "45, 47") + self.assertEqual(obs.associated_projects, + "Project - qó1]øJçY\@, Project - ÅQ%PáiZ!š@") t.rollback() def test_get_campaign_by_id_valid(self): From d62d2cc12ba41842569d3b86ad09329aa652d5b0 Mon Sep 17 00:00:00 2001 From: Cassidy Symons Date: Thu, 3 Nov 2022 11:13:13 -0700 Subject: [PATCH 13/13] Escape backslashes --- microsetta_private_api/repo/tests/test_campaign_repo.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/microsetta_private_api/repo/tests/test_campaign_repo.py b/microsetta_private_api/repo/tests/test_campaign_repo.py index dfb41def0..c7ae1c015 100644 --- a/microsetta_private_api/repo/tests/test_campaign_repo.py +++ b/microsetta_private_api/repo/tests/test_campaign_repo.py @@ -314,7 +314,7 @@ def test_create_campaign_projects_bug(self): } campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) - self.assertEqual(obs.associated_projects, "Project - qó1]øJçY\@") + self.assertEqual(obs.associated_projects, "Project - qó1]øJçY\\@") t.rollback() # verify that a comma-delimited string stores separate IDs @@ -326,7 +326,7 @@ def test_create_campaign_projects_bug(self): campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) self.assertEqual(obs.associated_projects, - "Project - qó1]øJçY\@, Project - ÅQ%PáiZ!š@") + "Project - qó1]øJçY\\@, Project - ÅQ%PáiZ!š@") t.rollback() # verify that a list of strings stores separate IDs @@ -338,7 +338,7 @@ def test_create_campaign_projects_bug(self): campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) self.assertEqual(obs.associated_projects, - "Project - qó1]øJçY\@, Project - ÅQ%PáiZ!š@") + "Project - qó1]øJçY\\@, Project - ÅQ%PáiZ!š@") t.rollback() # verify that a list of ints stores separate IDs @@ -350,7 +350,7 @@ def test_create_campaign_projects_bug(self): campaign_repo = CampaignRepo(t) obs = campaign_repo.create_campaign(**new_campaign) self.assertEqual(obs.associated_projects, - "Project - qó1]øJçY\@, Project - ÅQ%PáiZ!š@") + "Project - qó1]øJçY\\@, Project - ÅQ%PáiZ!š@") t.rollback() def test_get_campaign_by_id_valid(self):