From 08e986a9dc46a9cfafb1bdefdec254dd0d391337 Mon Sep 17 00:00:00 2001 From: colts661 Date: Mon, 11 Dec 2023 02:42:39 -0800 Subject: [PATCH 1/4] added lookup endpoint; added tests --- .../api/_interested_user.py | 16 ++ .../api/microsetta_private_api.yaml | 27 ++ .../repo/perk_fulfillment_repo.py | 54 ++++ .../repo/tests/test_perk_fulfillment_repo.py | 256 ++++++++++++++++++ 4 files changed, 353 insertions(+) diff --git a/microsetta_private_api/api/_interested_user.py b/microsetta_private_api/api/_interested_user.py index 3adaf869a..31781bff3 100644 --- a/microsetta_private_api/api/_interested_user.py +++ b/microsetta_private_api/api/_interested_user.py @@ -7,7 +7,9 @@ from microsetta_private_api.exceptions import RepoException from microsetta_private_api.repo.campaign_repo import CampaignRepo from microsetta_private_api.repo.melissa_repo import MelissaRepo +from microsetta_private_api.repo.perk_fulfillment_repo import PerkFulfillmentRepo from microsetta_private_api.tasks import send_email +from microsetta_private_api.admin.admin_impl import validate_admin_access def create_interested_user(body): @@ -276,3 +278,17 @@ def _validate_user_match(interested_user, email): # someone doesn't stumble upon a valid email and/or id. # if they don't both match, treat as invalid return interested_user.email == email + + +def search_ffq_codes_by_email(email, token_info): + validate_admin_access(token_info) + + with Transaction() as t: + pfr = PerkFulfillmentRepo(t) + ffq_diag = pfr.get_ffq_codes_by_email(email) + ffq_codes_obj = { + "ffq_codes": ffq_diag + } + if ffq_diag is None: + return jsonify(code=404, message="Email not found"), 404 + return jsonify(ffq_codes_obj), 200 diff --git a/microsetta_private_api/api/microsetta_private_api.yaml b/microsetta_private_api/api/microsetta_private_api.yaml index 9e980225e..7f959fec7 100644 --- a/microsetta_private_api/api/microsetta_private_api.yaml +++ b/microsetta_private_api/api/microsetta_private_api.yaml @@ -2209,6 +2209,33 @@ paths: $ref: '#/components/responses/401Unauthorized' '404': $ref: '#/components/responses/404NotFound' + + '/admin/search/ffq_codes/{email}': + get: + operationId: microsetta_private_api.api._interested_user.search_ffq_codes_by_email + tags: + - Admin + summary: Retrieve FFQ codes by an email query + description: Retrieve FFQ codes by an email query + parameters: + - in: path + name: email + description: user email address to search for + schema: + type: string + example: "test@test.com" + required: true + responses: + '200': + description: Object containing ffq codes and info related to the email (if any) + content: + application/json: + schema: + type: object + '401': + $ref: '#/components/responses/401Unauthorized' + '404': + $ref: '#/components/responses/404NotFound' '/admin/search/interested_users/{email}': get: diff --git a/microsetta_private_api/repo/perk_fulfillment_repo.py b/microsetta_private_api/repo/perk_fulfillment_repo.py index f11aaf947..dd611b00c 100644 --- a/microsetta_private_api/repo/perk_fulfillment_repo.py +++ b/microsetta_private_api/repo/perk_fulfillment_repo.py @@ -793,3 +793,57 @@ def check_perk_fulfillment_active(self): ) row = cur.fetchone() return row['perk_fulfillment_active'] + + def get_ffq_codes_by_email(self, email): + email = "%" + email + "%" + with self._transaction.dict_cursor() as cur: + # Note: Use left join to differentiate email not found possibility + cur.execute( + """ + WITH all_codes AS ( + SELECT + iu.email, + tr.created AS transaction_created_time, + frc.ffq_registration_code, + frc.registration_code_used + FROM campaign.interested_users AS iu + LEFT JOIN campaign.transaction AS tr + ON iu.interested_user_id = tr.interested_user_id + LEFT JOIN campaign.fundrazr_transaction_perk AS ftp + ON tr.id = ftp.transaction_id + LEFT JOIN campaign.fundrazr_ffq_codes AS ffc + ON ftp.id = ffc.fundrazr_transaction_perk_id + LEFT JOIN campaign.ffq_registration_codes AS frc + ON ffc.ffq_registration_code = frc.ffq_registration_code + WHERE iu.email ILIKE %s + ), count_codes AS ( + SELECT + ac1.email, + COUNT(ac1.ffq_registration_code) AS num_codes + FROM all_codes AS ac1 + GROUP BY ac1.email + ) + SELECT DISTINCT + ac.email, + CASE WHEN + cc.num_codes = 0 THEN NULL + ELSE + ac.transaction_created_time + END, + ac.ffq_registration_code, + ac.registration_code_used + FROM all_codes AS ac + LEFT JOIN count_codes AS cc + ON ac.email = cc.email + WHERE + ac.ffq_registration_code IS NOT NULL + OR + cc.num_codes = 0 + ORDER BY + ac.email ASC, + ac.registration_code_used DESC + """, + (email,) + ) + rows = cur.fetchall() + return [dict(row) for row in rows] diff --git a/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py b/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py index 467a7c5c3..92022ff78 100644 --- a/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py +++ b/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py @@ -12,6 +12,7 @@ from microsetta_private_api.model.campaign import (FundRazrPayment, Item, Shipping) from microsetta_private_api.model.address import Address +from microsetta_private_api.model.activation_code import ActivationCode from microsetta_private_api.model.daklapack_order import DaklapackOrder from microsetta_private_api.repo.account_repo import AccountRepo from microsetta_private_api.repo.admin_repo import AdminRepo @@ -1173,6 +1174,261 @@ def _count_fundrazr_ffq_codes(self, t): ) res = cur.fetchone() return res[0] + + + def test_get_ffq_codes_by_email(self): + # simplistic setup by directly play with test db + # interested users + with Transaction() as t: + cur = t.cursor() + emails = ["iu@foo.com"] * 3 + ["iu2@baz.com", "test@foo.com"] + cur.execute( + "INSERT INTO campaign.interested_users " + \ + "(campaign_id, first_name, last_name, email) VALUES " + \ + ", ".join([ + f"('{self.test_campaign_id1}', 'First', 'Last', '{email}')" + for email in emails + ]) + \ + "RETURNING interested_user_id" + ) + iu_ids = [tup[0] for tup in cur.fetchall()] + t.commit() + + # Test: no ffq without transaction + with Transaction() as t: + pfr = PerkFulfillmentRepo(t) + ffq_code = pfr.get_ffq_codes_by_email("iu2@baz.com") + self.assertEqual(len(ffq_code), 1) + self.assertEqual(ffq_code[0]['email'], "iu2@baz.com") + self.assertIsNone(ffq_code[0]['transaction_created_time']) + self.assertIsNone(ffq_code[0]['ffq_registration_code']) + + ffq_code = pfr.get_ffq_codes_by_email(emails[0]) + self.assertIsNone(ffq_code[0]['ffq_registration_code']) + + # transactions + with Transaction() as t: + cur = t.cursor() + tx_ids = { + f"MT{idx + 1}": iu_id + for idx, iu_id in enumerate(iu_ids) + } + tx_ids['MT6'] = iu_ids[-1] # extra tx for test@foo.com + cur.execute( + "INSERT INTO campaign.transaction VALUES " + \ + ", ".join([ + f"('{tx_id}', '{iu_id}', 'fundrazr', '4Tqx5', " + \ + "'2023-01-01', 100, 100, 'usd', 'First', 'Last', " + \ + "'fake@bar.com', 'paypal', 'coolcool', TRUE)" + for tx_id, iu_id in tx_ids.items() + ]) + ) + t.commit() + + # Test: no ffq with transaction + with Transaction() as t: + pfr = PerkFulfillmentRepo(t) + + # unique email with no code + ffq_code = pfr.get_ffq_codes_by_email("iu2@baz.com") + self.assertEqual(len(ffq_code), 1) + self.assertEqual(ffq_code[0]['email'], "iu2@baz.com") + self.assertIsNone(ffq_code[0]['transaction_created_time']) + self.assertIsNone(ffq_code[0]['ffq_registration_code']) + + # duplicate email with no code + ffq_code = pfr.get_ffq_codes_by_email("iu@foo.com") + self.assertEqual(len(ffq_code), 1) + self.assertEqual(ffq_code[0]['email'], "iu@foo.com") + self.assertIsNone(ffq_code[0]['ffq_registration_code']) + + # fundrazr transaction perks + with Transaction() as t: + cur = t.cursor() + cur.execute( + "INSERT INTO campaign.fundrazr_transaction_perk " + \ + "(transaction_id, perk_id, quantity, processed) VALUES " + \ + ", ".join([ + f"('{tx_id}', '3QeVd', 1, TRUE)" for tx_id in tx_ids + if tx_id != 'MT3' + ]) + \ + "RETURNING id" + ) + ftp_ids = { + tup[0]: tx_id + for tup, tx_id in zip(cur.fetchall(), tx_ids) + } + t.commit() + + with Transaction() as t: + cur = t.cursor() + cur.execute( + "INSERT INTO campaign.fundrazr_transaction_perk " + "(transaction_id, perk_id, quantity, processed) VALUES " + "('MT5', '3QeW6', 1, TRUE)" + "RETURNING id" + ) # extra ftp for test@foo.com + ftp_ids[cur.fetchone()[0]] = 'MT5' + t.commit() + + # ffq registration codes + new_ffq_codes = [ActivationCode.generate_code() for _ in range(6)] + ffq_reg_codes = [ # odd idx: used + (code, 'NULL') if idx % 2 == 0 else (code, "'2023-02-01'") + for idx, code in enumerate(new_ffq_codes) + ] + with Transaction() as t: + cur = t.cursor() + cur.execute( + "INSERT INTO campaign.ffq_registration_codes VALUES " + \ + ", ".join([ + f"('{code}', {used})" for code, used in ffq_reg_codes + ]) + ) + t.commit() + + # fundrazr ffq codes + fundrazr_ffq_codes = dict() + ftp_ids_lst = list(ftp_ids.keys()) + for idx, code in enumerate(new_ffq_codes): + if idx <= 3: + fundrazr_ffq_codes[code] = ftp_ids_lst[idx] + else: # 2 codes + fundrazr_ffq_codes[code] = ftp_ids_lst[4] + with Transaction() as t: + cur = t.cursor() + cur.execute( + "INSERT INTO campaign.fundrazr_ffq_codes VALUES " + \ + ", ".join([ + f"('{ftp_id}', '{code}')" + for code, ftp_id in fundrazr_ffq_codes.items() + ]) + ) + t.commit() + + # Test: email not found + with Transaction() as t: + pfr = PerkFulfillmentRepo(t) + ffq_code = pfr.get_ffq_codes_by_email("fake@email.com") + self.assertEqual(len(ffq_code), 0) + + # Test: 1 ffq code + with Transaction() as t: + pfr = PerkFulfillmentRepo(t) + ffq_code = pfr.get_ffq_codes_by_email("iu2@baz.com") + self.assertEqual(len(ffq_code), 1) + self.assertEqual(ffq_code[0]['email'], "iu2@baz.com") + self.assertEqual( + ffq_code[0]['transaction_created_time'].strftime('%Y-%m-%d'), + '2023-01-01' + ) + self.assertEqual( + ffq_code[0]['ffq_registration_code'], new_ffq_codes[2] + ) + self.assertIsNone(ffq_code[0]['registration_code_used']) + + # Test: 3 duplicate emails, 2 codes + with Transaction() as t: + pfr = PerkFulfillmentRepo(t) + ffq_code = pfr.get_ffq_codes_by_email("iu@foo.com") + self.assertEqual(len(ffq_code), 2) + self.assertTrue( + ffq_code[0]['email'] == ffq_code[1]['email'] == "iu@foo.com" + ) + self.assertEqual( + ffq_code[0]['transaction_created_time'].strftime('%Y-%m-%d'), + '2023-01-01' + ) + got_codes = [ + ffq_code[i]['ffq_registration_code'] + for i in range(2) + ] + self.assertEqual(set(got_codes), set(new_ffq_codes[:2])) + + # Test: unique email, 3 codes + with Transaction() as t: + pfr = PerkFulfillmentRepo(t) + ffq_code = pfr.get_ffq_codes_by_email("test@foo.com") + self.assertEqual(len(ffq_code), 3) + self.assertTrue( + ffq_code[0]['email'] == ffq_code[2]['email'] == "test@foo.com" + ) + self.assertEqual( + ffq_code[2]['transaction_created_time'].strftime('%Y-%m-%d'), + '2023-01-01' + ) + got_codes = [ + ffq_code[i]['ffq_registration_code'] + for i in range(3) + ] + self.assertEqual(set(got_codes), set(new_ffq_codes[3:])) + + # Test: match multiple emails + with Transaction() as t: + pfr = PerkFulfillmentRepo(t) + ffq_code = pfr.get_ffq_codes_by_email("iu") + self.assertEqual(len(ffq_code), 3) + self.assertTrue( + ffq_code[1]['email'] == ffq_code[2]['email'] == "iu@foo.com" + ) + self.assertEqual(ffq_code[0]['email'], "iu2@baz.com") + self.assertEqual( + ffq_code[1]['transaction_created_time'].strftime('%Y-%m-%d'), + '2023-01-01' + ) + got_codes = [ + ffq_code[i]['ffq_registration_code'] + for i in range(3) + ] + self.assertEqual(set(got_codes), set(new_ffq_codes[:3])) + + # Test: match multiple emails + with Transaction() as t: + pfr = PerkFulfillmentRepo(t) + ffq_code = pfr.get_ffq_codes_by_email("foo.com") + self.assertEqual(len(ffq_code), 5) + got_codes = [ + ffq_code[i]['ffq_registration_code'] + for i in range(5) + ] + self.assertNotIn(new_ffq_codes[2], got_codes) + + # clear down + with Transaction() as t: + cur = t.cursor() + + # fundrazr ffq codes + cur.execute( + "DELETE FROM campaign.fundrazr_ffq_codes AS ffc " + "WHERE ffc.ffq_registration_code " + f"IN {str(tuple(new_ffq_codes))}" + ) + + # ffq registration codes + cur.execute( + "DELETE FROM campaign.ffq_registration_codes AS frc " + "WHERE frc.ffq_registration_code " + f"IN {str(tuple(new_ffq_codes))}" + ) + + # fundrazr transaction perks + cur.execute( + "DELETE FROM campaign.fundrazr_transaction_perk AS ftp " + f"WHERE ftp.id IN {str(tuple(ftp_ids.keys()))}" + ) + + # transactions + cur.execute( + "DELETE FROM campaign.transaction AS tr " + f"WHERE tr.id IN {str(tuple(tx_ids.keys()))}" + ) + + # interested users + cur.execute( + "DELETE FROM campaign.interested_users AS iu " + f"WHERE iu.interested_user_id IN {str(tuple(iu_ids))}" + ) + t.commit() if __name__ == '__main__': From 8ffa1c0c59f295f92762617445bd31891a989fd6 Mon Sep 17 00:00:00 2001 From: colts661 Date: Mon, 11 Dec 2023 12:57:22 -0800 Subject: [PATCH 2/4] fixed whitespaces --- .../api/_interested_user.py | 3 +- .../repo/perk_fulfillment_repo.py | 8 +-- .../repo/tests/test_perk_fulfillment_repo.py | 51 +++++++++---------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/microsetta_private_api/api/_interested_user.py b/microsetta_private_api/api/_interested_user.py index 31781bff3..eea32f3d0 100644 --- a/microsetta_private_api/api/_interested_user.py +++ b/microsetta_private_api/api/_interested_user.py @@ -7,7 +7,8 @@ from microsetta_private_api.exceptions import RepoException from microsetta_private_api.repo.campaign_repo import CampaignRepo from microsetta_private_api.repo.melissa_repo import MelissaRepo -from microsetta_private_api.repo.perk_fulfillment_repo import PerkFulfillmentRepo +from microsetta_private_api.repo.perk_fulfillment_repo import\ + PerkFulfillmentRepo from microsetta_private_api.tasks import send_email from microsetta_private_api.admin.admin_impl import validate_admin_access diff --git a/microsetta_private_api/repo/perk_fulfillment_repo.py b/microsetta_private_api/repo/perk_fulfillment_repo.py index dd611b00c..9be1b75d4 100644 --- a/microsetta_private_api/repo/perk_fulfillment_repo.py +++ b/microsetta_private_api/repo/perk_fulfillment_repo.py @@ -793,7 +793,7 @@ def check_perk_fulfillment_active(self): ) row = cur.fetchone() return row['perk_fulfillment_active'] - + def get_ffq_codes_by_email(self, email): email = "%" + email + "%" with self._transaction.dict_cursor() as cur: @@ -801,7 +801,7 @@ def get_ffq_codes_by_email(self, email): cur.execute( """ WITH all_codes AS ( - SELECT + SELECT iu.email, tr.created AS transaction_created_time, frc.ffq_registration_code, @@ -818,7 +818,7 @@ def get_ffq_codes_by_email(self, email): WHERE iu.email ILIKE %s ), count_codes AS ( SELECT - ac1.email, + ac1.email, COUNT(ac1.ffq_registration_code) AS num_codes FROM all_codes AS ac1 GROUP BY ac1.email @@ -839,7 +839,7 @@ def get_ffq_codes_by_email(self, email): ac.ffq_registration_code IS NOT NULL OR cc.num_codes = 0 - ORDER BY + ORDER BY ac.email ASC, ac.registration_code_used DESC """, diff --git a/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py b/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py index 92022ff78..df203a3bc 100644 --- a/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py +++ b/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py @@ -1174,21 +1174,20 @@ def _count_fundrazr_ffq_codes(self, t): ) res = cur.fetchone() return res[0] - - - def test_get_ffq_codes_by_email(self): + + def test_get_ffq_codes_by_email(self): # simplistic setup by directly play with test db # interested users with Transaction() as t: cur = t.cursor() emails = ["iu@foo.com"] * 3 + ["iu2@baz.com", "test@foo.com"] cur.execute( - "INSERT INTO campaign.interested_users " + \ - "(campaign_id, first_name, last_name, email) VALUES " + \ + "INSERT INTO campaign.interested_users " + + "(campaign_id, first_name, last_name, email) VALUES " + ", ".join([ - f"('{self.test_campaign_id1}', 'First', 'Last', '{email}')" + f"('{self.test_campaign_id1}', 'First', 'Last', '{email}')" for email in emails - ]) + \ + ]) + "RETURNING interested_user_id" ) iu_ids = [tup[0] for tup in cur.fetchall()] @@ -1210,15 +1209,15 @@ def test_get_ffq_codes_by_email(self): with Transaction() as t: cur = t.cursor() tx_ids = { - f"MT{idx + 1}": iu_id + f"MT{idx + 1}": iu_id for idx, iu_id in enumerate(iu_ids) } tx_ids['MT6'] = iu_ids[-1] # extra tx for test@foo.com cur.execute( - "INSERT INTO campaign.transaction VALUES " + \ + "INSERT INTO campaign.transaction VALUES " + ", ".join([ - f"('{tx_id}', '{iu_id}', 'fundrazr', '4Tqx5', " + \ - "'2023-01-01', 100, 100, 'usd', 'First', 'Last', " + \ + f"('{tx_id}', '{iu_id}', 'fundrazr', '4Tqx5', " + + "'2023-01-01', 100, 100, 'usd', 'First', 'Last', " + "'fake@bar.com', 'paypal', 'coolcool', TRUE)" for tx_id, iu_id in tx_ids.items() ]) @@ -1246,16 +1245,16 @@ def test_get_ffq_codes_by_email(self): with Transaction() as t: cur = t.cursor() cur.execute( - "INSERT INTO campaign.fundrazr_transaction_perk " + \ - "(transaction_id, perk_id, quantity, processed) VALUES " + \ + "INSERT INTO campaign.fundrazr_transaction_perk " + + "(transaction_id, perk_id, quantity, processed) VALUES " + ", ".join([ f"('{tx_id}', '3QeVd', 1, TRUE)" for tx_id in tx_ids if tx_id != 'MT3' - ]) + \ + ]) + "RETURNING id" ) ftp_ids = { - tup[0]: tx_id + tup[0]: tx_id for tup, tx_id in zip(cur.fetchall(), tx_ids) } t.commit() @@ -1270,7 +1269,7 @@ def test_get_ffq_codes_by_email(self): ) # extra ftp for test@foo.com ftp_ids[cur.fetchone()[0]] = 'MT5' t.commit() - + # ffq registration codes new_ffq_codes = [ActivationCode.generate_code() for _ in range(6)] ffq_reg_codes = [ # odd idx: used @@ -1280,7 +1279,7 @@ def test_get_ffq_codes_by_email(self): with Transaction() as t: cur = t.cursor() cur.execute( - "INSERT INTO campaign.ffq_registration_codes VALUES " + \ + "INSERT INTO campaign.ffq_registration_codes VALUES " + ", ".join([ f"('{code}', {used})" for code, used in ffq_reg_codes ]) @@ -1293,25 +1292,25 @@ def test_get_ffq_codes_by_email(self): for idx, code in enumerate(new_ffq_codes): if idx <= 3: fundrazr_ffq_codes[code] = ftp_ids_lst[idx] - else: # 2 codes + else: # 2 codes fundrazr_ffq_codes[code] = ftp_ids_lst[4] with Transaction() as t: cur = t.cursor() cur.execute( - "INSERT INTO campaign.fundrazr_ffq_codes VALUES " + \ + "INSERT INTO campaign.fundrazr_ffq_codes VALUES " + ", ".join([ f"('{ftp_id}', '{code}')" for code, ftp_id in fundrazr_ffq_codes.items() ]) ) t.commit() - + # Test: email not found with Transaction() as t: pfr = PerkFulfillmentRepo(t) ffq_code = pfr.get_ffq_codes_by_email("fake@email.com") self.assertEqual(len(ffq_code), 0) - + # Test: 1 ffq code with Transaction() as t: pfr = PerkFulfillmentRepo(t) @@ -1340,7 +1339,7 @@ def test_get_ffq_codes_by_email(self): '2023-01-01' ) got_codes = [ - ffq_code[i]['ffq_registration_code'] + ffq_code[i]['ffq_registration_code'] for i in range(2) ] self.assertEqual(set(got_codes), set(new_ffq_codes[:2])) @@ -1358,11 +1357,11 @@ def test_get_ffq_codes_by_email(self): '2023-01-01' ) got_codes = [ - ffq_code[i]['ffq_registration_code'] + ffq_code[i]['ffq_registration_code'] for i in range(3) ] self.assertEqual(set(got_codes), set(new_ffq_codes[3:])) - + # Test: match multiple emails with Transaction() as t: pfr = PerkFulfillmentRepo(t) @@ -1377,7 +1376,7 @@ def test_get_ffq_codes_by_email(self): '2023-01-01' ) got_codes = [ - ffq_code[i]['ffq_registration_code'] + ffq_code[i]['ffq_registration_code'] for i in range(3) ] self.assertEqual(set(got_codes), set(new_ffq_codes[:3])) @@ -1388,7 +1387,7 @@ def test_get_ffq_codes_by_email(self): ffq_code = pfr.get_ffq_codes_by_email("foo.com") self.assertEqual(len(ffq_code), 5) got_codes = [ - ffq_code[i]['ffq_registration_code'] + ffq_code[i]['ffq_registration_code'] for i in range(5) ] self.assertNotIn(new_ffq_codes[2], got_codes) From 9d8d411892aa60f118d598c1686c788aafe9924a Mon Sep 17 00:00:00 2001 From: colts661 Date: Tue, 12 Dec 2023 11:34:57 -0800 Subject: [PATCH 3/4] reformat test setup, teardown --- .../repo/tests/test_perk_fulfillment_repo.py | 331 ++++++++---------- 1 file changed, 137 insertions(+), 194 deletions(-) diff --git a/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py b/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py index df203a3bc..99173581e 100644 --- a/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py +++ b/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py @@ -316,20 +316,102 @@ def setUp(self, verify_address_result): res = cur.fetchone() self.sub_ftp_id = res[0] + # dummy information for ffq code search + # interested users + fake_ffq_emails = ["iu@foo.com"] * 3 + [ + "iu2@baz.com", "test@foo.com", "empty@b.com", "empty2@b.com" + ] + ["empty@dup.com"] * 3 + cur.execute( + "INSERT INTO campaign.interested_users " + + "(campaign_id, first_name, last_name, email) VALUES " + + ", ".join([ + f"('{self.test_campaign_id1}', 'Fir', 'Last', '{email}')" + for email in fake_ffq_emails + ]) + + "RETURNING interested_user_id" + ) + self.iu_ids = [tup[0] for tup in cur.fetchall()] + + # transactions + self.tx_ids = { + f"MT{idx + 1}": iu_id + for idx, iu_id in enumerate(self.iu_ids) if idx < 6 + } + self.tx_ids['MT7'] = self.iu_ids[-6] # extra tx for test@foo.com + cur.execute( + "INSERT INTO campaign.transaction VALUES " + + ", ".join([ + f"('{tx_id}', '{iu_id}', 'fundrazr', '4Tqx5', " + + "'2023-01-01', 100, 100, 'usd', 'Fir', 'Last', " + + "'fake@bar.com', 'paypal', 'coolcool', TRUE)" + for tx_id, iu_id in self.tx_ids.items() + ]) + ) + + # fundrazr transaction perks + cur.execute( + "INSERT INTO campaign.fundrazr_transaction_perk " + + "(transaction_id, perk_id, quantity, processed) VALUES " + + ", ".join([ + f"('{tx_id}', '3QeVd', 1, TRUE)" for tx_id in self.tx_ids + if tx_id not in ['MT3', 'MT6'] + ]) + + "RETURNING id" + ) + self.dummy_ftp_ids = [tup[0] for tup in cur.fetchall()] + cur.execute( + "INSERT INTO campaign.fundrazr_transaction_perk " + "(transaction_id, perk_id, quantity, processed) VALUES " + "('MT5', '3QeW6', 1, TRUE) " + "RETURNING id" + ) # extra ftp for test@foo.com + self.dummy_ftp_ids.append(cur.fetchone()[0]) + + # ffq registration codes + self.new_ffq_codes = [ + ActivationCode.generate_code() + for _ in range(6) + ] + ffq_reg_codes = [ # odd idx: used + (code, 'NULL') if idx % 2 == 0 else (code, "'2023-02-01'") + for idx, code in enumerate(self.new_ffq_codes) + ] + cur.execute( + "INSERT INTO campaign.ffq_registration_codes VALUES " + + ", ".join([ + f"('{code}', {used})" for code, used in ffq_reg_codes + ]) + ) + + # fundrazr ffq codes + fundrazr_ffq_codes = {} + for idx, code in enumerate(self.new_ffq_codes): + if idx <= 3: + fundrazr_ffq_codes[code] = self.dummy_ftp_ids[idx] + else: # 2 codes + fundrazr_ffq_codes[code] = self.dummy_ftp_ids[4] + cur.execute( + "INSERT INTO campaign.fundrazr_ffq_codes VALUES " + + ", ".join([ + f"('{ftp_id}', '{code}')" + for code, ftp_id in fundrazr_ffq_codes.items() + ]) + ) + t.commit() def tearDown(self): with Transaction() as t: cur = t.cursor() cur.execute( - "DELETE FROM campaign.campaigns_projects " - "WHERE campaign_id = %s", - (self.test_campaign_id1,) + "DELETE FROM campaign.fundrazr_ffq_codes AS ffc " + "WHERE ffc.ffq_registration_code In %s", + (tuple(self.new_ffq_codes), ) ) cur.execute( - "DELETE FROM campaign.campaigns " - "WHERE campaign_id = %s", - (self.test_campaign_id1, ) + "DELETE FROM campaign.ffq_registration_codes AS frc " + "WHERE frc.ffq_registration_code IN %s", + (tuple(self.new_ffq_codes), ) ) cur.execute( "DELETE FROM campaign.fundrazr_transaction_perk " @@ -339,19 +421,38 @@ def tearDown(self): self.ffq_ftp_id, self.kit_ftp_id, self.two_kit_ftp_id, - self.sub_ftp_id + self.sub_ftp_id, + *self.dummy_ftp_ids ), ) ) cur.execute( "DELETE FROM campaign.transaction " "WHERE id IN %s", - (( - FFQ_TRANSACTION_ID, - KIT_TRANSACTION_ID, - TWO_KIT_TRANSACTION_ID, - SUB_TRANSACTION_ID - ), ) + ( + ( + FFQ_TRANSACTION_ID, + KIT_TRANSACTION_ID, + TWO_KIT_TRANSACTION_ID, + SUB_TRANSACTION_ID, + *self.tx_ids + ), + ) + ) + cur.execute( + "DELETE FROM campaign.interested_users AS iu " + "WHERE iu.interested_user_id IN %s", + (tuple(self.iu_ids), ) + ) + cur.execute( + "DELETE FROM campaign.campaigns_projects " + "WHERE campaign_id = %s", + (self.test_campaign_id1,) + ) + cur.execute( + "DELETE FROM campaign.campaigns " + "WHERE campaign_id = %s", + (self.test_campaign_id1, ) ) t.commit() @@ -1176,144 +1277,33 @@ def _count_fundrazr_ffq_codes(self, t): return res[0] def test_get_ffq_codes_by_email(self): - # simplistic setup by directly play with test db - # interested users - with Transaction() as t: - cur = t.cursor() - emails = ["iu@foo.com"] * 3 + ["iu2@baz.com", "test@foo.com"] - cur.execute( - "INSERT INTO campaign.interested_users " + - "(campaign_id, first_name, last_name, email) VALUES " + - ", ".join([ - f"('{self.test_campaign_id1}', 'First', 'Last', '{email}')" - for email in emails - ]) + - "RETURNING interested_user_id" - ) - iu_ids = [tup[0] for tup in cur.fetchall()] - t.commit() - - # Test: no ffq without transaction with Transaction() as t: pfr = PerkFulfillmentRepo(t) - ffq_code = pfr.get_ffq_codes_by_email("iu2@baz.com") - self.assertEqual(len(ffq_code), 1) - self.assertEqual(ffq_code[0]['email'], "iu2@baz.com") - self.assertIsNone(ffq_code[0]['transaction_created_time']) - self.assertIsNone(ffq_code[0]['ffq_registration_code']) - - ffq_code = pfr.get_ffq_codes_by_email(emails[0]) - self.assertIsNone(ffq_code[0]['ffq_registration_code']) - - # transactions - with Transaction() as t: - cur = t.cursor() - tx_ids = { - f"MT{idx + 1}": iu_id - for idx, iu_id in enumerate(iu_ids) - } - tx_ids['MT6'] = iu_ids[-1] # extra tx for test@foo.com - cur.execute( - "INSERT INTO campaign.transaction VALUES " + - ", ".join([ - f"('{tx_id}', '{iu_id}', 'fundrazr', '4Tqx5', " + - "'2023-01-01', 100, 100, 'usd', 'First', 'Last', " + - "'fake@bar.com', 'paypal', 'coolcool', TRUE)" - for tx_id, iu_id in tx_ids.items() - ]) - ) - t.commit() - # Test: no ffq with transaction - with Transaction() as t: - pfr = PerkFulfillmentRepo(t) + # Test: email not found + ffq_code = pfr.get_ffq_codes_by_email("fake@email.com") + self.assertEqual(len(ffq_code), 0) - # unique email with no code - ffq_code = pfr.get_ffq_codes_by_email("iu2@baz.com") + # Test: no ffq without transaction + ffq_code = pfr.get_ffq_codes_by_email("empty2@b.com") # unique self.assertEqual(len(ffq_code), 1) - self.assertEqual(ffq_code[0]['email'], "iu2@baz.com") + self.assertEqual(ffq_code[0]['email'], "empty2@b.com") self.assertIsNone(ffq_code[0]['transaction_created_time']) self.assertIsNone(ffq_code[0]['ffq_registration_code']) - # duplicate email with no code - ffq_code = pfr.get_ffq_codes_by_email("iu@foo.com") + ffq_code = pfr.get_ffq_codes_by_email("empty@dup.com") # duplicate self.assertEqual(len(ffq_code), 1) - self.assertEqual(ffq_code[0]['email'], "iu@foo.com") + self.assertEqual(ffq_code[0]['email'], "empty@dup.com") self.assertIsNone(ffq_code[0]['ffq_registration_code']) - # fundrazr transaction perks - with Transaction() as t: - cur = t.cursor() - cur.execute( - "INSERT INTO campaign.fundrazr_transaction_perk " + - "(transaction_id, perk_id, quantity, processed) VALUES " + - ", ".join([ - f"('{tx_id}', '3QeVd', 1, TRUE)" for tx_id in tx_ids - if tx_id != 'MT3' - ]) + - "RETURNING id" - ) - ftp_ids = { - tup[0]: tx_id - for tup, tx_id in zip(cur.fetchall(), tx_ids) - } - t.commit() - - with Transaction() as t: - cur = t.cursor() - cur.execute( - "INSERT INTO campaign.fundrazr_transaction_perk " - "(transaction_id, perk_id, quantity, processed) VALUES " - "('MT5', '3QeW6', 1, TRUE)" - "RETURNING id" - ) # extra ftp for test@foo.com - ftp_ids[cur.fetchone()[0]] = 'MT5' - t.commit() - - # ffq registration codes - new_ffq_codes = [ActivationCode.generate_code() for _ in range(6)] - ffq_reg_codes = [ # odd idx: used - (code, 'NULL') if idx % 2 == 0 else (code, "'2023-02-01'") - for idx, code in enumerate(new_ffq_codes) - ] - with Transaction() as t: - cur = t.cursor() - cur.execute( - "INSERT INTO campaign.ffq_registration_codes VALUES " + - ", ".join([ - f"('{code}', {used})" for code, used in ffq_reg_codes - ]) - ) - t.commit() - - # fundrazr ffq codes - fundrazr_ffq_codes = dict() - ftp_ids_lst = list(ftp_ids.keys()) - for idx, code in enumerate(new_ffq_codes): - if idx <= 3: - fundrazr_ffq_codes[code] = ftp_ids_lst[idx] - else: # 2 codes - fundrazr_ffq_codes[code] = ftp_ids_lst[4] - with Transaction() as t: - cur = t.cursor() - cur.execute( - "INSERT INTO campaign.fundrazr_ffq_codes VALUES " + - ", ".join([ - f"('{ftp_id}', '{code}')" - for code, ftp_id in fundrazr_ffq_codes.items() - ]) - ) - t.commit() - - # Test: email not found - with Transaction() as t: - pfr = PerkFulfillmentRepo(t) - ffq_code = pfr.get_ffq_codes_by_email("fake@email.com") - self.assertEqual(len(ffq_code), 0) + # Test: no ffq with transaction + ffq_code = pfr.get_ffq_codes_by_email("empty@b.com") + self.assertEqual(len(ffq_code), 1) + self.assertEqual(ffq_code[0]['email'], "empty@b.com") + self.assertIsNone(ffq_code[0]['transaction_created_time']) + self.assertIsNone(ffq_code[0]['ffq_registration_code']) - # Test: 1 ffq code - with Transaction() as t: - pfr = PerkFulfillmentRepo(t) + # Test: 1 ffq code ffq_code = pfr.get_ffq_codes_by_email("iu2@baz.com") self.assertEqual(len(ffq_code), 1) self.assertEqual(ffq_code[0]['email'], "iu2@baz.com") @@ -1322,13 +1312,11 @@ def test_get_ffq_codes_by_email(self): '2023-01-01' ) self.assertEqual( - ffq_code[0]['ffq_registration_code'], new_ffq_codes[2] + ffq_code[0]['ffq_registration_code'], self.new_ffq_codes[2] ) self.assertIsNone(ffq_code[0]['registration_code_used']) - # Test: 3 duplicate emails, 2 codes - with Transaction() as t: - pfr = PerkFulfillmentRepo(t) + # Test: 3 duplicate emails, 2 codes ffq_code = pfr.get_ffq_codes_by_email("iu@foo.com") self.assertEqual(len(ffq_code), 2) self.assertTrue( @@ -1342,11 +1330,9 @@ def test_get_ffq_codes_by_email(self): ffq_code[i]['ffq_registration_code'] for i in range(2) ] - self.assertEqual(set(got_codes), set(new_ffq_codes[:2])) + self.assertEqual(set(got_codes), set(self.new_ffq_codes[:2])) - # Test: unique email, 3 codes - with Transaction() as t: - pfr = PerkFulfillmentRepo(t) + # Test: unique email, 3 codes ffq_code = pfr.get_ffq_codes_by_email("test@foo.com") self.assertEqual(len(ffq_code), 3) self.assertTrue( @@ -1360,11 +1346,9 @@ def test_get_ffq_codes_by_email(self): ffq_code[i]['ffq_registration_code'] for i in range(3) ] - self.assertEqual(set(got_codes), set(new_ffq_codes[3:])) + self.assertEqual(set(got_codes), set(self.new_ffq_codes[3:])) - # Test: match multiple emails - with Transaction() as t: - pfr = PerkFulfillmentRepo(t) + # Test: match multiple emails ffq_code = pfr.get_ffq_codes_by_email("iu") self.assertEqual(len(ffq_code), 3) self.assertTrue( @@ -1379,56 +1363,15 @@ def test_get_ffq_codes_by_email(self): ffq_code[i]['ffq_registration_code'] for i in range(3) ] - self.assertEqual(set(got_codes), set(new_ffq_codes[:3])) + self.assertEqual(set(got_codes), set(self.new_ffq_codes[:3])) - # Test: match multiple emails - with Transaction() as t: - pfr = PerkFulfillmentRepo(t) ffq_code = pfr.get_ffq_codes_by_email("foo.com") self.assertEqual(len(ffq_code), 5) got_codes = [ ffq_code[i]['ffq_registration_code'] for i in range(5) ] - self.assertNotIn(new_ffq_codes[2], got_codes) - - # clear down - with Transaction() as t: - cur = t.cursor() - - # fundrazr ffq codes - cur.execute( - "DELETE FROM campaign.fundrazr_ffq_codes AS ffc " - "WHERE ffc.ffq_registration_code " - f"IN {str(tuple(new_ffq_codes))}" - ) - - # ffq registration codes - cur.execute( - "DELETE FROM campaign.ffq_registration_codes AS frc " - "WHERE frc.ffq_registration_code " - f"IN {str(tuple(new_ffq_codes))}" - ) - - # fundrazr transaction perks - cur.execute( - "DELETE FROM campaign.fundrazr_transaction_perk AS ftp " - f"WHERE ftp.id IN {str(tuple(ftp_ids.keys()))}" - ) - - # transactions - cur.execute( - "DELETE FROM campaign.transaction AS tr " - f"WHERE tr.id IN {str(tuple(tx_ids.keys()))}" - ) - - # interested users - cur.execute( - "DELETE FROM campaign.interested_users AS iu " - f"WHERE iu.interested_user_id IN {str(tuple(iu_ids))}" - ) - t.commit() - + self.assertNotIn(self.new_ffq_codes[2], got_codes) if __name__ == '__main__': unittest.main() From 4de73f66c4df61d2f53c0547707bef9c0de1463b Mon Sep 17 00:00:00 2001 From: colts661 Date: Tue, 12 Dec 2023 16:41:18 -0800 Subject: [PATCH 4/4] fixed style --- .../repo/tests/test_perk_fulfillment_repo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py b/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py index 99173581e..395892120 100644 --- a/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py +++ b/microsetta_private_api/repo/tests/test_perk_fulfillment_repo.py @@ -1285,13 +1285,13 @@ def test_get_ffq_codes_by_email(self): self.assertEqual(len(ffq_code), 0) # Test: no ffq without transaction - ffq_code = pfr.get_ffq_codes_by_email("empty2@b.com") # unique + ffq_code = pfr.get_ffq_codes_by_email("empty2@b.com") # unique self.assertEqual(len(ffq_code), 1) self.assertEqual(ffq_code[0]['email'], "empty2@b.com") self.assertIsNone(ffq_code[0]['transaction_created_time']) self.assertIsNone(ffq_code[0]['ffq_registration_code']) - ffq_code = pfr.get_ffq_codes_by_email("empty@dup.com") # duplicate + ffq_code = pfr.get_ffq_codes_by_email("empty@dup.com") # duplicate self.assertEqual(len(ffq_code), 1) self.assertEqual(ffq_code[0]['email'], "empty@dup.com") self.assertIsNone(ffq_code[0]['ffq_registration_code']) @@ -1373,5 +1373,6 @@ def test_get_ffq_codes_by_email(self): ] self.assertNotIn(self.new_ffq_codes[2], got_codes) + if __name__ == '__main__': unittest.main()