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

2024-08-29 | MAIN --> PROD | DEV (377d210) --> STAGING #4241

Merged
merged 5 commits into from
Aug 29, 2024
Merged
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
11 changes: 8 additions & 3 deletions backend/audit/views/pre_dissemination_download_view.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect
from django.views.generic import View

Expand Down Expand Up @@ -33,7 +34,11 @@ def get(self, request, report_id):
)
i2d_data = intake_to_dissem.load_all()

filename = generate_presubmission_report(i2d_data)
download_url = get_download_url(filename)
filename, workbook_bytes = generate_presubmission_report(i2d_data)
response = HttpResponse(
workbook_bytes,
content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
)
response["Content-Disposition"] = f"attachment; filename={filename}"

return redirect(download_url)
return response
2 changes: 1 addition & 1 deletion backend/cypress/support/auditee-certification.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function testAuditeeCertification() {
// 2. Sign and date, submit and go back to checklist
cy.get('#auditee_name').type('John Doe');
cy.get('#auditee_title').type('Auditee');
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__button').trigger('click');
cy.get('.usa-date-picker__calendar__date--today').click();
cy.get('.usa-button').contains('Agree to auditee certification').click();
};
2 changes: 1 addition & 1 deletion backend/cypress/support/auditor-certification.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function testAuditorCertification() {
// 2. Sign and date, submit and go back to checklist
cy.get('#auditor_name').type('Jane Doe');
cy.get('#auditor_title').type('Auditor');
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__button').trigger('click');
cy.get('.usa-date-picker__calendar__date--today').click();
cy.get('.usa-button').contains('Agree to auditor certification').click();
};
16 changes: 1 addition & 15 deletions backend/dissemination/api_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

# These are API versions we want live.
live = {
"dissemination": ["api_v1_0_3", "api_v1_1_0", "api_v1_1_1"],
"dissemination": ["api_v1_0_3", "api_v1_1_0"],
"support": ["admin_api_v1_1_0"],
}

Expand Down Expand Up @@ -47,20 +47,6 @@ def exec_sql(location, version, filename):
curs.execute(sql)


def create_materialized_view(location):
"""
Create or recreate the dissemination_combined materialized view.
We only want this done once on startup, regardless of the API version.
"""
conn = connection(get_conn_string())
conn.autocommit = True
with conn.cursor() as curs:
path = f"{location}/sql/create_materialized_views.sql"
logger.info("EXEC SQL create_materialized_views.sql")
sql = open(path, "r").read()
curs.execute(sql)


def create_views(location, version):
exec_sql(location, version, "create_views.sql")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ class Command(BaseCommand):
"""

def handle(self, *args, **kwargs):
api_versions.create_materialized_view("dissemination")
api_versions.create_functions("dissemination")
api_versions.create_functions("support")
api_versions.create_live_views("dissemination")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ def add_arguments(self, parser):
def handle(self, *args, **options):
path = "dissemination/sql"
if options["create"]:
# Other API views may rely on the materialized view. So, drop and recreate them.
api_versions.drop_live_views("dissemination")
api_versions.exec_sql_at_path(path, "create_materialized_views.sql")
api_versions.create_live_views("dissemination")
elif options["drop"]:
api_versions.exec_sql_at_path(path, "drop_materialized_views.sql")
elif options["refresh"]:
Expand Down
53 changes: 14 additions & 39 deletions backend/dissemination/summary_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@
import time
import openpyxl as pyxl

from boto3 import client as boto3_client
from botocore.client import ClientError, Config

from django.conf import settings
from fs.memoryfs import MemoryFS

from openpyxl.workbook.defined_name import DefinedName
from openpyxl.utils import quote_sheetname
Expand Down Expand Up @@ -606,40 +602,19 @@ def create_workbook(data, protect_sheets=False):
return (workbook, t1 - t0)


def persist_workbook(workbook):
def prepare_workbook_for_download(workbook):

t0 = time.time()
s3_client = boto3_client(
service_name="s3",
region_name=settings.AWS_S3_PRIVATE_REGION_NAME,
aws_access_key_id=settings.AWS_PRIVATE_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_PRIVATE_SECRET_ACCESS_KEY,
endpoint_url=settings.AWS_S3_PRIVATE_INTERNAL_ENDPOINT,
config=Config(signature_version="s3v4"),
)
now = datetime.utcnow().strftime("%Y%m%d%H%M%S")
filename = f"fac-summary-report-{now}.xlsx"

# Save the workbook directly to a BytesIO object
workbook_bytes = io.BytesIO()
workbook.save(workbook_bytes)
workbook_bytes.seek(0)

with MemoryFS() as mem_fs:
now = datetime.utcnow().strftime("%Y%m%d%H%M%S")
filename = f"fac-summary-report-{now}.xlsx"
s3_dir = "temp"

workbook_write_fp = mem_fs.openbin(filename, mode="w")
workbook.save(workbook_write_fp)
workbook_read_fp = mem_fs.openbin(filename, mode="r")
workbook_read_fp.seek(0)
content = workbook_read_fp.read()
workbook_bytes = io.BytesIO(content)

try:
s3_client.put_object(
Body=workbook_bytes,
Bucket=settings.AWS_PRIVATE_STORAGE_BUCKET_NAME,
Key=f"{s3_dir}/{filename}",
)
except ClientError:
logger.warn(f"Unable to put summary report file {filename} in S3!")
raise
t1 = time.time()
return (f"temp/{filename}", t1 - t0)
return (filename, workbook_bytes, t1 - t0)


def generate_summary_report(report_ids, include_private=False):
Expand All @@ -651,12 +626,12 @@ def generate_summary_report(report_ids, include_private=False):
data = separate_notes_single_fields_from_array_fields(data)
(workbook, tcw) = create_workbook(data)
insert_dissem_coversheet(workbook, bool(tribal_report_ids), include_private)
(filename, tpw) = persist_workbook(workbook)
(filename, workbook_bytes, tpw) = prepare_workbook_for_download(workbook)
t1 = time.time()
logger.info(
f"SUMMARY_REPORTS generate_summary_report\n\ttotal: {t1-t0} ttri: {ttri} tgrdd: {tgrdd} tcw: {tcw} tpw: {tpw}"
)
return filename
return (filename, workbook_bytes)


# Ignore performance profiling for the presub.
Expand All @@ -667,9 +642,9 @@ def generate_presubmission_report(i2d_data):
insert_precert_coversheet(workbook)
workbook.security.workbookPassword = str(uuid.uuid4())
workbook.security.lockStructure = True
(filename, _) = persist_workbook(workbook)
(filename, workbook_bytes, _) = prepare_workbook_for_download(workbook)

return filename
return (filename, workbook_bytes)


def separate_notes_single_fields_from_array_fields(data):
Expand Down
2 changes: 1 addition & 1 deletion backend/dissemination/test_summary_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def test_generate_summary_report_returns_filename(self):
baker.make(FederalAward, report_id=g)
self.refresh_materialized_view()

filename = generate_summary_report(report_ids)
filename, _ = generate_summary_report(report_ids)

self.assertTrue(filename.startswith, "fac-summary-report-")
self.assertTrue(filename.endswith, ".xlsx")
Expand Down
Loading
Loading