Skip to content

Commit

Permalink
chore: backend attachments with form data
Browse files Browse the repository at this point in the history
  • Loading branch information
pbastia committed Nov 26, 2024
1 parent 0cd5c45 commit 93cda80
Show file tree
Hide file tree
Showing 13 changed files with 208 additions and 107 deletions.
53 changes: 48 additions & 5 deletions bc_obps/reporting/api/attachments.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from typing import Any, Literal
from typing import List, Literal, Tuple
from common.api.utils.current_user_utils import get_current_user_guid
from common.permissions import authorize
from django.http import HttpRequest
from django.db import transaction
from django.http import HttpRequest, StreamingHttpResponse
from ninja import File, Form, UploadedFile
from registration.decorators import handle_http_errors
from reporting.constants import EMISSIONS_REPORT_TAGS
from reporting.models import report_version
from reporting.models.report_attachment import ReportAttachment
from reporting.schema.generic import Message
from reporting.schema.report_attachments import ReportAttachmentsIn
from reporting.schema.report_attachment import ReportAttachmentOut
from service.error_service import custom_codes_4xx
from .router import router

Expand All @@ -17,8 +22,46 @@
auth=authorize("approved_industry_user"),
)
@handle_http_errors()
def save_report_attachments(request: HttpRequest, report_version_id: int, payload: ReportAttachmentsIn) -> Literal[200]:
def save_report_attachments(
request: HttpRequest,
report_version_id: int,
file_types: Form[List[str]],
files: List[UploadedFile] = File(...),
) -> Literal[200]:

print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print(payload)
for f in files:
print(f)
print("~~~")
for n in file_types:
print(n)

for index, file_type in enumerate(file_types):
ReportAttachment.objects.filter(report_version_id=report_version_id, attachment_type=file_type).delete()

attachment = ReportAttachment(
report_version_id=report_version_id,
attachment=files[index],
attachment_type=file_type,
)
attachment.save()
attachment.set_create_or_update(get_current_user_guid(request))

return 200


@router.get("report-version/{report_version_id}/attachments")
def load_report_attachments(
request: HttpRequest,
report_version_id: int,
) -> Tuple[Literal[200], List[ReportAttachmentOut]]:
return ReportAttachment.objects.filter(report_version_id=report_version_id)


@router.get("report-version/{report_version_id}/attachments/{file_id}")
def download_report_attachment_file(request: HttpRequest, report_version_id: int, file_id: int):

file = ReportAttachment.objects.get(id=file_id, report_version_id=report_version_id)

response = StreamingHttpResponse(streaming_content=file)
response['Content-Disposition'] = f'attachment; filename={file.name}'
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.0.8 on 2024-11-13 18:43
# Generated by Django 5.0.8 on 2024-11-14 23:36

import django.db.models.deletion
from django.db import migrations, models
Expand All @@ -13,43 +13,30 @@ class Migration(migrations.Migration):

operations = [
migrations.CreateModel(
name='ReportAttachments',
name='ReportAttachment',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True, null=True)),
('updated_at', models.DateTimeField(blank=True, null=True)),
('archived_at', models.DateTimeField(blank=True, null=True)),
(
'verification_statement',
'attachment',
models.FileField(
db_comment='The verification statement uploaded as part of the report', upload_to='documents'
db_comment='A file uploaded as an attachment to a report', upload_to='report_attachments/%Y/'
),
),
(
'wci_352_362',
models.FileField(
blank=True,
db_comment='The additional documentation required under WCI.352 and WCI.362',
null=True,
upload_to='documents',
),
),
(
'additional_reportable_information',
models.FileField(
blank=True,
db_comment='Additional reportable information, if required.',
null=True,
upload_to='documents',
),
),
(
'confidentiality_request',
models.FileField(
blank=True,
db_comment='Confidentiality request form, if confidentiality is requested under B.C. Reg. 249/2015 Reporting Regulation',
null=True,
upload_to='documents',
'attachment_type',
models.CharField(
choices=[
('verification_statement', 'Verification Statement'),
('wci_352_362', 'Wci 352 362'),
('additional_reportable_information', 'Additional Reportable Information'),
('confidentiality_request', 'Confidentiality Request'),
('other', 'Other'),
],
db_comment='The type of attachment this record represents',
max_length=1000,
),
),
(
Expand All @@ -72,6 +59,15 @@ class Migration(migrations.Migration):
to='registration.user',
),
),
(
'report_version',
models.ForeignKey(
db_comment='The report version this attachment belongs to',
on_delete=django.db.models.deletion.CASCADE,
related_name='report_attachments',
to='reporting.reportversion',
),
),
(
'updated_by',
models.ForeignKey(
Expand All @@ -84,8 +80,16 @@ class Migration(migrations.Migration):
),
],
options={
'db_table': 'erc"."report_attachments',
'db_table_comment': 'Table containing the required attachments for a report.',
'db_table': 'erc"."report_attachment',
'db_table_comment': 'Table containing the file information for the report attachments',
},
),
migrations.AddConstraint(
model_name='reportattachment',
constraint=models.UniqueConstraint(
condition=models.Q(('attachment_type', 'other'), _negated=True),
fields=('report_version', 'attachment_type'),
name='unique_attachment_type_per_report_version',
),
),
]
4 changes: 2 additions & 2 deletions bc_obps/reporting/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from .report_non_attributable_emissions import ReportNonAttributableEmissions
from .report_product import ReportProduct
from .report_verification import ReportVerification
from .report_attachments import ReportAttachments
from .report_attachment import ReportAttachment

__all__ = [
"ReportDataBaseModel",
Expand Down Expand Up @@ -64,5 +64,5 @@
"ReportNonAttributableEmissions",
"ReportRawActivityData",
"ReportVerification",
"ReportAttachments",
"ReportAttachment",
]
40 changes: 40 additions & 0 deletions bc_obps/reporting/models/report_attachment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from django.db import models
from django.db.models import Q, CharField, FileField, ForeignKey
from registration.models.time_stamped_model import TimeStampedModel
from reporting.models.report_version import ReportVersion

FOLDER_NAME = 'report_attachments/%Y/'


class ReportAttachment(TimeStampedModel):

class ReportAttachmentType(models.TextChoices):
verification_statement = "verification_statement"
wci_352_362 = "wci_352_362"
additional_reportable_information = "additional_reportable_information"
confidentiality_request = "confidentiality_request"

report_version = ForeignKey(
ReportVersion,
on_delete=models.CASCADE,
related_name="report_attachments",
db_comment="The report version this attachment belongs to",
)
attachment = FileField(upload_to=FOLDER_NAME, db_comment="A file uploaded as an attachment to a report")
attachment_type = CharField(
max_length=1000,
choices=ReportAttachmentType.choices,
db_comment="The type of attachment this record represents",
)

class Meta:
db_table_comment = "Table containing the file information for the report attachments"
db_table = 'erc"."report_attachment'
app_label = "reporting"
constraints = [
# Check that only one attachment type is present, except if the attachment type is 'other'
models.UniqueConstraint(
name="unique_attachment_type_per_report_version",
fields=['report_version', 'attachment_type'],
)
]
38 changes: 0 additions & 38 deletions bc_obps/reporting/models/report_attachments.py

This file was deleted.

9 changes: 9 additions & 0 deletions bc_obps/reporting/schema/report_attachment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from ninja import Schema
from reporting.models.report_attachment import ReportAttachment


class ReportAttachmentOut(Schema):

class Meta:
model = ReportAttachment
fields = ['id', 'attachment', 'attachment_type']
17 changes: 0 additions & 17 deletions bc_obps/reporting/schema/report_attachments.py

This file was deleted.

Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ import { HasReportVersion } from "../../utils/defaultPageFactory";
import AttachmentsForm from "./AttachmentsForm";

const Attachments: React.FC<HasReportVersion> = ({ version_id }) => {
return (
<Suspense fallback="Loading Production Data Form">
<AttachmentsForm version_id={version_id} />
</Suspense>
);
return <AttachmentsForm version_id={version_id} />;
};

export default Attachments;
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,34 @@ import { getSignOffAndSubmitSteps } from "../taskList/5_signOffSubmit";
import postAttachments from "@bciers/actions/api/postAttachments";
import MultiStepWrapperWithTaskList from "./MultiStepWrapperWithTaskList";
import AttachmentElement from "./AttachmentElement";
import { useState } from "react";

interface Props extends HasReportVersion {}

const AttachmentsForm: React.FC<Props> = ({ version_id }) => {
const taskListElements = getSignOffAndSubmitSteps(version_id);
const [files, setFiles] = useState<{ [filename: string]: File }>({});

const handleSubmit = async (data: any) => {
await postAttachments(version_id, data.formData);
const handleChange = (fileType: string, file: File | undefined) => {
if (file) {
setFiles({ ...files, [fileType]: file });
} else {
const { [fileType]: removed, ...prunedFiles } = files;
setFiles(prunedFiles);
}
};

const handleSubmit = async () => {
console.log("Submit!", files);

const formData = new FormData();
for (const [fileType, file] of Object.entries(files)) {
formData.append("files", file);
formData.append("file_types", fileType);
}

await postAttachments(version_id, formData);
console.log(formData);
};

return (
Expand All @@ -21,11 +41,20 @@ const AttachmentsForm: React.FC<Props> = ({ version_id }) => {
steps={multiStepHeaderSteps}
initialStep={4}
taskListElements={taskListElements}
onSubmit={handleSubmit}
cancelUrl="#"
>
<p>
Please upload any of the documents below that is applicable to your
report:
</p>
<AttachmentElement
title="Verification statement"
onFileChange={(file) => handleChange("verification_statement", file)}
/>
<AttachmentElement
title="Test field"
value="Abc.pdf"
onFileChange={() => {}}
title="WCI.352 and WCI.362"
onFileChange={(file) => handleChange("wci_352_362", file)}
/>
</MultiStepWrapperWithTaskList>
</>
Expand Down
Loading

0 comments on commit 93cda80

Please sign in to comment.