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

[treasury-report] Update Send Treasury Report by email button to only send the email and not trigger the step function #516

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 7 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,10 @@ repos:
args: [--fix]
# Run the formatter.
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'main'
hooks:
- id: mypy
args: [--ignore-missing-imports]
additional_dependencies:
- pydantic
110 changes: 7 additions & 103 deletions api/src/services/uploads/uploads.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
deleteUploadFile,
s3UploadFilePutSignedUrl,
getSignedUrl,
startStepFunctionExecution,
sendSqsMessage,
} from 'src/lib/aws'
import { db } from 'src/lib/db'
import { logger } from 'src/lib/logger'
Expand All @@ -23,9 +23,6 @@ import {
getUploadsByExpenditureCategory,
getValidUploadsInCurrentPeriod,
sendTreasuryReport,
SubrecipientLambdaPayload,
ProjectLambdaPayload,
CreateArchiveLambdaPayload,
EmailLambdaPayload,
} from './uploads'
import type { StandardScenario } from './uploads.scenarios'
Expand All @@ -42,7 +39,7 @@ jest.mock('src/lib/aws', () => ({
deleteUploadFile: jest.fn(),
s3UploadFilePutSignedUrl: jest.fn(),
getSignedUrl: jest.fn(),
startStepFunctionExecution: jest.fn(),
sendSqsMessage: jest.fn(),
}))
jest.mock('uuid', () => ({
v4: () => '00000000-0000-0000-0000-000000000000',
Expand Down Expand Up @@ -379,6 +376,8 @@ describe('treasury report', () => {
beforeEach(() => {
jest.resetAllMocks()
process.env.TREASURY_STEP_FUNCTION_ARN = 'test-arn'
process.env.TREASURY_EMAIL_SQS_URL =
'https://sqs.us-east-1.amazon.com/fake_aws_account_key/fake_queue'
})

scenario(
Expand All @@ -387,91 +386,8 @@ describe('treasury report', () => {
mockCurrentUser(scenario.user.one)
const mockOrganization = scenario.organization.one
const mockReportingPeriod = scenario.reportingPeriod.one
const mockUpload = scenario.upload.two
const mockUser = scenario.user.one

const projectPayload: ProjectLambdaPayload = {
'1A': {
organization: {
id: mockOrganization.id,
preferences: {
current_reporting_period_id: mockReportingPeriod.id,
},
},
user: {
email: mockUser.email,
id: mockUser.id,
},
outputTemplateId: mockReportingPeriod.outputTemplateId,
uploadsToAdd: {
[mockUpload.agencyId]: {
objectKey: `uploads/${mockOrganization.id}/${mockUpload.agencyId}/${mockReportingPeriod.id}/${mockUpload.id}/${mockUpload.filename}`,
createdAt: mockUpload.createdAt,
filename: mockUpload.filename,
},
},
uploadsToRemove: {},
ProjectType: '1A',
},
'1B': {
organization: {
id: mockOrganization.id,
preferences: {
current_reporting_period_id: mockReportingPeriod.id,
},
},
user: {
email: mockUser.email,
id: mockUser.id,
},
outputTemplateId: mockReportingPeriod.outputTemplateId,
uploadsToAdd: {},
uploadsToRemove: {},
ProjectType: '1B',
},
'1C': {
organization: {
id: mockOrganization.id,
preferences: {
current_reporting_period_id: mockReportingPeriod.id,
},
},
user: {
email: mockUser.email,
id: mockUser.id,
},
outputTemplateId: mockReportingPeriod.outputTemplateId,
uploadsToAdd: {},
uploadsToRemove: {},
ProjectType: '1C',
},
}
const subrecipientPayload: SubrecipientLambdaPayload = {
Subrecipient: {
organization: {
id: mockOrganization.id,
preferences: {
current_reporting_period_id: mockReportingPeriod.id,
},
},
user: {
email: mockUser.email,
id: mockUser.id,
},
outputTemplateId: mockReportingPeriod.outputTemplateId,
},
}

const zipPayload: CreateArchiveLambdaPayload = {
zip: {
organization: {
id: mockOrganization.id,
preferences: {
current_reporting_period_id: mockReportingPeriod.id,
},
},
},
}
const emailPayload: EmailLambdaPayload = {
email: {
organization: {
Expand All @@ -487,24 +403,12 @@ describe('treasury report', () => {
},
}

const input = JSON.stringify({
'1A': {},
'1B': {},
'1C': {},
Subrecipient: {},
zip: {},
email: {},
...projectPayload,
...subrecipientPayload,
...zipPayload,
...emailPayload,
})
const input = emailPayload
const result = await sendTreasuryReport()

expect(result).toBe(true)
expect(startStepFunctionExecution).toHaveBeenCalledWith(
'test-arn',
`Force-kick-off-00000000-0000-0000-0000-000000000000`,
expect(sendSqsMessage).toHaveBeenCalledWith(
'https://sqs.us-east-1.amazon.com/fake_aws_account_key/fake_queue',
input
)
}
Expand Down
38 changes: 4 additions & 34 deletions api/src/services/uploads/uploads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import type {
MutationResolvers,
UploadRelationResolvers,
} from 'types/graphql'
import { v4 as uuidv4 } from 'uuid'

import { RedwoodError } from '@redwoodjs/api'

Expand All @@ -16,7 +15,7 @@ import {
s3UploadFilePutSignedUrl,
getSignedUrl,
getS3UploadFileKey,
startStepFunctionExecution,
sendSqsMessage,
} from 'src/lib/aws'
import { ROLES } from 'src/lib/constants'
import { db } from 'src/lib/db'
Expand Down Expand Up @@ -370,41 +369,12 @@ export const sendTreasuryReport: MutationResolvers['sendTreasuryReport'] =
const organization = await db.organization.findFirst({
where: { id: context.currentUser.agency.organizationId },
})
const reportingPeriod = await db.reportingPeriod.findFirst({
where: { id: organization.preferences['current_reporting_period_id'] },
})
const projectLambdaPayload: ProjectLambdaPayload =
await getUploadsByExpenditureCategory(organization, reportingPeriod)
const subrecipientLambdaPayload: SubrecipientLambdaPayload =
await getSubrecipientLambdaPayload(
organization,
context.currentUser,
reportingPeriod
)
const createArchiveLambdaPayload: CreateArchiveLambdaPayload =
await getCreateArchiveLambdaPayload(organization)

const emailLambdaPayload: EmailLambdaPayload =
await getEmailLambdaPayload(organization, context.currentUser)

const input = {
'1A': {},
'1B': {},
'1C': {},
Subrecipient: {},
zip: {},
email: {},
...projectLambdaPayload,
...subrecipientLambdaPayload,
...createArchiveLambdaPayload,
...emailLambdaPayload,
}

await startStepFunctionExecution(
process.env.TREASURY_STEP_FUNCTION_ARN,
`Force-kick-off-${uuidv4()}`,
JSON.stringify(input)
)
const input = emailLambdaPayload

await sendSqsMessage(process.env.TREASURY_EMAIL_SQS_URL, input)
return true
} catch (error) {
logger.error(error, 'Error sending Treasury Report')
Expand Down
14 changes: 9 additions & 5 deletions python/src/functions/create_archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Any

import boto3
import structlog
from aws_lambda_typing.context import Context
from mypy_boto3_s3.client import S3Client
from pydantic import BaseModel
Expand All @@ -20,7 +21,7 @@ class CreateArchiveLambdaPayload(BaseModel):


@reset_contextvars
def handle(event: dict[str, Any], _context: Context):
def handle(event: dict[str, Any], _context: Context) -> dict[str, Any]:
"""Lambda handler for creating an archive of CSV files in S3

Args:
Expand Down Expand Up @@ -64,8 +65,11 @@ def handle(event: dict[str, Any], _context: Context):


def create_archive(
org_id: int, reporting_period_id: int, s3_client: S3Client, logger=None
):
org_id: int,
reporting_period_id: int,
s3_client: S3Client,
logger: structlog.stdlib.BoundLogger = None,
) -> None:
"""Create a zip archive of CSV files in S3"""

if logger is None:
Expand All @@ -91,8 +95,8 @@ def create_archive(
with tempfile.NamedTemporaryFile() as file:
with zipfile.ZipFile(file, "w") as zipf:
for target_file in target_files:
obj = s3_client.get_object(Bucket=S3_BUCKET, Key=target_file)
zipf.writestr(target_file, obj["Body"].read())
target_obj = s3_client.get_object(Bucket=S3_BUCKET, Key=target_file)
zipf.writestr(target_file, target_obj["Body"].read())

zipf.close()
file.flush()
Expand Down
6 changes: 3 additions & 3 deletions python/src/functions/generate_presigned_url_and_send_email.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
from typing import Optional, Tuple
from typing import Any, Optional, Tuple

import boto3
import chevron
Expand Down Expand Up @@ -28,7 +28,7 @@ class SendTreasuryEmailLambdaPayload(BaseModel):


@reset_contextvars
def handle(event: SendTreasuryEmailLambdaPayload, context: Context):
def handle(event: SendTreasuryEmailLambdaPayload, context: Context) -> dict[str, Any]:
"""Lambda handler for emailing Treasury reports

Given a user and organization object- send an email to the user that
Expand Down Expand Up @@ -102,7 +102,7 @@ def generate_email(
def process_event(
payload: SendTreasuryEmailLambdaPayload,
logger: structlog.stdlib.BoundLogger,
):
) -> bool:
"""
This function is structured as followed:
1) Check to see if the s3 object exists:
Expand Down
Loading
Loading