def test_list_receipt(self): """Method to test receipt index""" donation_table = DynamoTable('donations') receipt_id = "asdf1234" existing_receipts = donation_table.query_hash("receipt_id", receipt_id, index="ReceiptIndex", limit=10) assert not existing_receipts # Add a record data = { "campaign_id": "my_campaign", "donation_on": arrow.utcnow().isoformat(), "donator_name": "John Doeski", "donator_email": "*****@*****.**", "donation_cents": 1000, "receipt_id": receipt_id, "email_bucket": "my_bucket", "email_key": "key1" } donation_table.put_item(data) existing_receipts = donation_table.query_hash("receipt_id", receipt_id, index="ReceiptIndex", limit=10) assert len(existing_receipts) == 1
def test_list_unrelated_receipts(self): """Method to test receipt index""" donation_table = DynamoTable('donations') # Add a record data = { "campaign_id": "my_campaign", "donation_on": arrow.utcnow().isoformat(), "donator_name": "John Doeski", "donator_email": "*****@*****.**", "donation_cents": 1000, "receipt_id": "alsdf3234", "email_bucket": "my_bucket", "email_key": "key1" } donation_table.put_item(data) data["receipt_id"] = "adsfghdfg" donation_table.put_item(data) data["receipt_id"] = "hjydfgsdfg" donation_table.put_item(data) existing_receipts = donation_table.query_hash("receipt_id", "jfghghjf", index="ReceiptIndex", limit=10) assert not existing_receipts
def process_email_handler(event, context): logger = logging.getLogger("boto3") logger.setLevel(logging.WARN) print("Received event: " + json.dumps(event, indent=2)) # Check if S3 event or CloudWatch invocation. If just keeping things hot, exit. if "Records" in event: if "s3" in event["Records"][0]: key = event["Records"][0]["s3"]["object"]["key"] bucket = event["Records"][0]["s3"]["bucket"]["name"] else: print("Not an email. Move along...") return # Load message from S3 s3 = boto3.resource('s3') email_obj = s3.Object(bucket, key) email_mime = email_obj.get()['Body'].read().decode('utf-8') # Detect Charity for sup_charity in SUPPORTED_CHARITIES: class_ = getattr(charity, sup_charity["class"]) charity_class = class_(email_mime) # Detect charity if charity_class.is_receipt(): # Found the charity # Get campaign ID and campaign data campaign_id = charity_class.get_campaign_id() print("CAMPAIGN ID: {}".format(campaign_id)) campaign_table = DynamoTable('campaigns') campaign_key = {"campaign_id": campaign_id} campaign = campaign_table.get_item(campaign_key) if not campaign: print("WARNING: **** CAMPAIGN DOES NOT EXIST ****") dm_email = DonatematesEmail(charity_class.from_email) dm_email.send_campaign_does_not_exist() return True # Setup email sender dm_email = DonatematesEmail(charity_class.from_email, campaign["campaigner_email"]) # Get donation receipt data = charity_class.parse_email() data["receipt_id"] = data["receipt_id"].strip() # Validate this is a new donation donation_table = DynamoTable('donations') existing_receipts = donation_table.query_hash("receipt_id", data["receipt_id"], index="ReceiptIndex", limit=10) if existing_receipts: # This receipt already exists! print( "WARNING: **** Duplicate receipt detected - Campaign: {} - Receipt: {} - Bucket: {} - Key: {} ****" .format(campaign_id, data["receipt_id"], bucket, key)) # Notify user we didn't process it dm_email.send_duplicate_receipt(campaign_id, data["receipt_id"], key) return True # Add donation record data["campaign_id"] = campaign_id data["donation_on"] = arrow.utcnow().isoformat() data["email_bucket"] = bucket data["email_key"] = key print("DONATION DATA:") print(data) store_donation(data) # Get updated total donation donation_total_cents = donation_table.integer_sum_attribute( "campaign_id", campaign_id, "donation_cents") # Notify the Donor if campaign["campaign_status"] == "cancelled": # If cancelled, only notify donor and let them know the campaign isn't going on. dm_email.send_campaign_cancelled() else: # Send standard confirmation to donor dm_email.send_donation_confirmation(data["donation_cents"]) # Notify the campaigner if the campaign is active only if campaign["campaign_status"] == "active": # Update notification time (for future possible digest emails) campaign_table.update_attribute(campaign_key, "notified_on", arrow.utcnow().isoformat()) if donation_total_cents >= campaign["match_cents"]: # Update campaign status to "matched" campaign_table.update_attribute(campaign_key, "campaign_status", "matched") # Send campaign completion email! dm_email.send_campaign_matched(data["donor_name"], data["donation_cents"], donation_total_cents, campaign["match_cents"]) else: # Send normal update dm_email.send_campaign_update(data["donor_name"], data["donation_cents"], donation_total_cents, campaign["match_cents"]) # Exit return True # If you get here, you didn't successfully parse the email or it was unsupported # Save email to error bucket s3.Object('parse-fail-donatemates', '{}'.format( shortuuid.uuid())).copy_from(CopySource='{}/{}'.format(bucket, key)) # Reply to user print( "WARNING: **** Failed to detect a supported charity - Email Key: {} ****" .format(key))