Skip to content

Commit

Permalink
fix: update site visited logic for report verification page (#2629)
Browse files Browse the repository at this point in the history
### Changes

- Card: bcgov/cas-reporting#199 (comment)
- Updated `ReportVerification` model to include new fields and modify existing ones
- Modified `BaseReportVerificationSchema` to align with new model changes
- Updated `verificationSchema` and `verificationUiSchema` in frontend to reflect new requirements
- Adjusted `VerificationForm` component to handle new form structure

### Acceptance Criteria

- "Site visited" options (Facility X, Other, None) include required fields for threats to independence and verification conclusion
- Facility X and Other options include "Type of site visit" field
- Other option shows additional fields for site name and geographic location
- Backend model and schema align with frontend changes
- Form validation works correctly for all new fields and dependencies

### Test Plan

1. Run migrations and start the application
2. Navigate to the Verification form
3. Test each "Site visited" option:
   - Verify required fields appear for each option
   - Ensure conditional fields show/hide appropriately
4. Submit the form with various combinations of inputs
5. Verify data is correctly saved to the database
6. Check API responses include all new fields

https://www.loom.com/share/8d7c765181ea42daad40b1b9dac8669a?sid=2b18080d-aff5-4fc5-a73c-f392d83265fb
  • Loading branch information
vivanovbc authored Jan 4, 2025
1 parent 671eb6b commit 724ce1e
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 61 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Generated by Django 5.0.10 on 2024-12-28 07:38

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('reporting', '0041_reportnewentrant_reportnewentrantemission_and_more'),
]

operations = [
migrations.AlterField(
model_name='reportverification',
name='other_facility_coordinates',
field=models.CharField(
blank=True, db_comment='Geographic location of the other facility visited', max_length=100, null=True
),
),
migrations.AlterField(
model_name='reportverification',
name='other_facility_name',
field=models.CharField(
blank=True,
db_comment="Name of the other facility visited if 'Other' is selected",
max_length=100,
null=True,
),
),
migrations.AlterField(
model_name='reportverification',
name='threats_to_independence',
field=models.BooleanField(
db_comment='Indicates whether there were any threats to independence noted', default=False
),
preserve_default=False,
),
migrations.AlterField(
model_name='reportverification',
name='verification_conclusion',
field=models.CharField(
choices=[('Positive', 'Positive'), ('Modified', 'Modified'), ('Negative', 'Negative')],
db_comment='The conclusion of the verification',
default='Positive',
max_length=8,
),
preserve_default=False,
),
migrations.AlterField(
model_name='reportverification',
name='visit_name',
field=models.CharField(
db_comment='The name of the site visited (Facility X, Other, or None)', max_length=100
),
),
migrations.AlterField(
model_name='reportverification',
name='visit_type',
field=models.CharField(
blank=True,
choices=[('In person', 'In Person'), ('Virtual', 'Virtual')],
db_comment='The type of visit conducted (Virtual or In Person)',
max_length=10,
null=True,
),
),
]
19 changes: 8 additions & 11 deletions bc_obps/reporting/models/report_verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ class ScopeOfVerification(models.TextChoices):
)

threats_to_independence = models.BooleanField(
null=True,
blank=True,
db_comment="Optional field to store whether or not there is an indication of threats to independence of an other facility visited",
default=False,
db_comment="Indicates whether there were any threats to independence noted",
)

class VerificationConclusion(models.TextChoices):
Expand All @@ -50,14 +47,14 @@ class VerificationConclusion(models.TextChoices):
NEGATIVE = "Negative"

verification_conclusion = models.CharField(
null=True,
blank=True,
max_length=8,
choices=VerificationConclusion.choices,
db_comment="The conclusion of the verification",
)

visit_name = models.CharField(max_length=100, db_comment="The name of the site visited")
visit_name = models.CharField(
max_length=100, db_comment="The name of the site visited (Facility X, Other, or None)"
)

class VisitType(models.TextChoices):
IN_PERSON = "In person"
Expand All @@ -68,21 +65,21 @@ class VisitType(models.TextChoices):
choices=VisitType.choices,
null=True,
blank=True,
db_comment="Optional field to store the type of visit conducted",
db_comment="The type of visit conducted (Virtual or In Person)",
)

other_facility_name = models.CharField(
max_length=100,
null=True,
blank=True,
db_comment="Optional field to store the name of an other facility visited",
db_comment="Name of the other facility visited if 'Other' is selected",
)

other_facility_coordinates = models.CharField(
max_length=50,
max_length=100,
null=True,
blank=True,
db_comment="Optional field to store geographic coordinates of an other facility visited",
db_comment="Geographic location of the other facility visited",
)

class Meta:
Expand Down
4 changes: 2 additions & 2 deletions bc_obps/reporting/schema/report_verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class BaseReportVerificationSchema(ModelSchema):
visit_type: Optional[str] = Field(None)
other_facility_name: Optional[str] = Field(None)
other_facility_coordinates: Optional[str] = Field(None)
threats_to_independence: Optional[bool] = Field(None)
verification_conclusion: Optional[str] = Field(None)
threats_to_independence: bool
verification_conclusion: str

class Meta:
model = ReportVerification
Expand Down
53 changes: 40 additions & 13 deletions bciers/apps/reporting/src/data/verification/verification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export const verificationSchema: RJSFSchema = {
"accredited_by",
"scope_of_verification",
"visit_name",
"threats_to_independence",
"verification_conclusion",
],
properties: {
verification_body_name: {
Expand All @@ -36,7 +38,16 @@ export const verificationSchema: RJSFSchema = {
visit_name: {
title: "Sites visited",
type: "string",
enum: ["Other", "None"], // modified in components/verification/createVerificationSchema.ts
enum: ["Facility X", "Other", "None"], // modified in components/verification/createVerificationSchema.ts
},
threats_to_independence: {
title: "Were there any threats to independence noted",
type: "boolean",
},
verification_conclusion: {
title: "Verification conclusion",
type: "string",
enum: ["Positive", "Modified", "Negative"],
},
verification_note: {
//Not an actual field in the db - this is just to make the form look like the wireframes
Expand All @@ -47,9 +58,6 @@ export const verificationSchema: RJSFSchema = {
dependencies: {
visit_name: {
oneOf: [
// type_of_facility_visit field display conditon:
// visit_name has one item
// visit_name is not "Other" or "None"
{
properties: {
visit_name: {
Expand All @@ -64,17 +72,23 @@ export const verificationSchema: RJSFSchema = {
title: "Type of site visit",
enum: ["Virtual", "In person"],
},
threats_to_independence: {
type: "boolean",
},
verification_conclusion: {
type: "string",
enum: ["Positive", "Modified", "Negative"],
},
},
required: ["visit_type"],
required: [
"visit_type",
"threats_to_independence",
"verification_conclusion",
],
},
{
// other_site_details field display condition
// visit_name has one item
// visit_name is "Other"
properties: {
visit_name: {
type: "string",
minItems: 1,
enum: ["Other"],
},
other_facility_name: {
Expand All @@ -83,19 +97,17 @@ export const verificationSchema: RJSFSchema = {
},
other_facility_coordinates: {
type: "string",
title: "Geographic coordinates",
title: "Geographic coordinates of site",
},
visit_type: {
type: "string",
title: "Type of site visit",
enum: ["Virtual", "In person"],
},
threats_to_independence: {
title: "Were there any threats to independence noted",
type: "boolean",
},
verification_conclusion: {
title: "Verification conclusion",
type: "string",
enum: ["Positive", "Modified", "Negative"],
},
Expand All @@ -108,6 +120,21 @@ export const verificationSchema: RJSFSchema = {
"verification_conclusion",
],
},
{
properties: {
visit_name: {
enum: ["None"],
},
threats_to_independence: {
type: "boolean",
},
verification_conclusion: {
type: "string",
enum: ["Positive", "Modified", "Negative"],
},
},
required: ["threats_to_independence", "verification_conclusion"],
},
],
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,32 +44,32 @@ const commonMandatoryFormFields = [
key: "scope_of_verification",
},
{ label: "Sites visited", type: "combobox", key: "visit_name" },
{
label: "Were there any threats to independence noted",
type: "radio",
key: "threats_to_independence",
},
{
label: "Verification conclusion",
type: "combobox",
key: "verification_conclusion",
},
];

const specificMandatoryFields = {
facility: [{ label: "Type of site visit", type: "radio", key: "visit_type" }],
conditional: [
other: [
{ label: "Type of site visit", type: "radio", key: "visit_type" },
{
label: "Please indicate the site visited",
type: "text",
key: "other_facility_name",
},
{
label: "Geographic coordinates",
label: "Geographic coordinates of site",
type: "text",
key: "other_facility_coordinates",
},
{
label: "Were there any threats to independence noted",
type: "radio",
key: "threats_to_independence",
},
{
label: "Verification conclusion",
type: "combobox",
key: "verification_conclusion",
},
],
};

Expand All @@ -79,15 +79,19 @@ const formDataSets = {
accredited_by: "SCC",
scope_of_verification: "Supplementary Report",
visit_name: "None",
threats_to_independence: "No",
verification_conclusion: "Positive",
},
facility: {
verification_body_name: "Test",
accredited_by: "SCC",
scope_of_verification: "Supplementary Report",
visit_name: "Facility A",
visit_name: "Facility X",
visit_type: "Virtual",
threats_to_independence: "No",
verification_conclusion: "Positive",
},
conditional: {
other: {
verification_body_name: "Test",
accredited_by: "SCC",
scope_of_verification: "Supplementary Report",
Expand Down Expand Up @@ -116,7 +120,7 @@ const renderVerificationForm = () => {
// ⛏️ Helper function to simulate form POST submission and assert the result
const submitFormAndAssert = async (
fields: { label: string; type: string; key: string }[],
data: Record<string, string | number>,
data: Record<string, string | number | boolean>,
) => {
actionHandler.mockReturnValueOnce({
success: true,
Expand Down Expand Up @@ -159,12 +163,12 @@ describe("VerificationForm component", () => {
);

await waitFor(() => {
expect(screen.queryAllByText(/Required field/i)).toHaveLength(4);
expect(screen.queryAllByText(/Required field/i)).toHaveLength(6);
});
});

it(
"fills mandatory fields and submits successfully",
"fills mandatory fields for 'None' option and submits successfully",
{
timeout: 10000,
},
Expand All @@ -186,23 +190,20 @@ describe("VerificationForm component", () => {
accredited_by: "SCC",
scope_of_verification: "Supplementary Report",
visit_name: "None",
threats_to_independence: false,
verification_conclusion: "Positive",
}),
},
);
},
);

it(
"fills facility mandatory fields and submits successfully",
"fills mandatory fields for 'Facility X' option and submits successfully",
{
timeout: 10000,
},
async () => {
(verificationSchema.properties?.visit_name as any).enum = [
...(verificationSchema.properties?.visit_name as any).enum,
"Facility A",
];

renderVerificationForm();
const fields = [
...commonMandatoryFormFields,
Expand All @@ -212,18 +213,18 @@ describe("VerificationForm component", () => {
},
);
it(
"fills other conditionally mandatory fields and submits successfully",
"fills mandatory fields for 'Other' option and submits successfully",
{
timeout: 10000,
},
async () => {
renderVerificationForm();
const fields = [
...commonMandatoryFormFields,
...specificMandatoryFields.conditional,
...specificMandatoryFields.other,
];
// POST submit and assert the result
await submitFormAndAssert(fields, formDataSets.conditional);
await submitFormAndAssert(fields, formDataSets.other);
// Assertion if actionHandler was called correctly
expect(actionHandler).toHaveBeenCalledWith(
config.actionPost.endPoint,
Expand All @@ -235,11 +236,11 @@ describe("VerificationForm component", () => {
accredited_by: "SCC",
scope_of_verification: "Supplementary Report",
visit_name: "Other",
threats_to_independence: false,
verification_conclusion: "Modified",
visit_type: "Virtual",
other_facility_name: "Other Facility",
other_facility_coordinates: "Lat 41; Long 35",
threats_to_independence: false,
verification_conclusion: "Modified",
}),
},
);
Expand Down
Loading

0 comments on commit 724ce1e

Please sign in to comment.