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

feat: write a prototypeApplication schema with definitions based on primary application type #236

Merged
merged 13 commits into from
Sep 19, 2024
Merged
1,212 changes: 1,212 additions & 0 deletions examples/prototypeApplication/data/lawfulDevelopmentCertificate/existing.ts

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
1,736 changes: 1,736 additions & 0 deletions examples/prototypeApplication/lawfulDevelopmentCertificate/existing.json

Large diffs are not rendered by default.

1,157 changes: 1,157 additions & 0 deletions examples/prototypeApplication/lawfulDevelopmentCertificate/proposed.json

Large diffs are not rendered by default.

3,544 changes: 1,584 additions & 1,960 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

8,844 changes: 8,514 additions & 330 deletions schemas/prototypeApplication.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions types/schemas/application/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {File} from './File';
import {Metadata} from './Metadata';
import {Metadata} from '../../shared/Metadata';
import {PreAssessment} from './PreAssessment';
import {Responses} from './Responses';
import {Responses} from '../../shared/Responses';
import {Applicant} from './data/Applicant';
import {ApplicationData} from './data/ApplicationData';
import {FilesAsData} from './data/Files';
Expand Down
11 changes: 11 additions & 0 deletions types/schemas/prototypeApplication/File.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {PrototypeFileType as FileType} from './enums/FileType';

/**
* @id #File
* @description File uploaded and labeled by the user to support the application
*/
export interface File {
name: string;
type: FileType[];
description?: string;
}
5 changes: 5 additions & 0 deletions types/schemas/prototypeApplication/PreAssessment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* @id #PreAssessment
* @description The result of the application based on information provided by the applicant, prior to assessment by a planning officer. Results are determined by flags corresponding to responses; each application can have up to one result per flagset
*/
export type PreAssessment = {value: string; description: string}[]; // @todo validate/restrict array to one result per flagset
167 changes: 167 additions & 0 deletions types/schemas/prototypeApplication/data/Applicant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import {Date, Email} from '../../../shared/utils';
import {PrimaryApplicationType} from '../enums/ApplicationType';
import {UserRoles} from './User';

export type ApplicantBase = BaseApplicant | Agent;

export type BaseApplicant = ContactDetails & {
/**
* @Description The type of applicant
jessicamcinchak marked this conversation as resolved.
Show resolved Hide resolved
*/
type: 'individual' | 'company' | 'charity' | 'public' | 'parishCouncil';
/**
* @description Address information for the applicant
*/
address: ApplicantAddress;
/**
* @description Contact information for the site visit
*/
siteContact: SiteContact;
};

export interface Agent extends BaseApplicant {
/**
* @description Contact information for the agent or proxy
*/
agent: ContactDetails & {address: UserAddress};
}

export type SiteContact = {role: UserRoles} | SiteContactOther;

export interface SiteContactOther {
role: 'other';
name: string;
email: string;
phone: string;
}

export type ContactDetails = {
name: {
title?: string;
first: string;
last: string;
};
email: Email;
phone: {
primary: string;
};
company?: {
name: string;
};
};

export type UserAddress = {
line1: string;
line2?: string;
town: string;
county?: string;
postcode: string;
country?: string;
};

export type ApplicantAddress =
| {sameAsSiteAddress: true}
| ApplicantAddressNotSameSite;

export interface ApplicantAddressNotSameSite extends UserAddress {
sameAsSiteAddress: false;
}

export type OwnershipInterest = 'owner' | 'tenant' | 'occupier' | 'other';

export interface BaseOwners {
name: string;
address: UserAddress | string;
interest?: OwnershipInterest;
}

export interface OwnersNoticeGiven extends BaseOwners {
noticeGiven: true;
}

export interface OwnersNoNoticeGiven extends BaseOwners {
noticeGiven: false;
noNoticeReason: string;
}

export interface OwnersNoticeDate extends BaseOwners {
noticeDate: Date;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ownership is a nice migration story:

Our original application types used code comments to note which shape of owners we expected for various application types, ultimately justifying a type that was too-generic and made all of these options possible: https://github.com/theopensystemslab/digital-planning-data-schemas/blob/main/types/schemas/application/data/Applicant.ts#L88-L101

Now the LDCApplicant definition and so on specify only the ownership variation it actually expects!


export type MaintenanceContact = {
when:
| 'duringConstruction'
| 'afterConstruction'
| 'duringAndAfterConstruction';
address: UserAddress;
contact: ContactDetails;
}[];

export type LDCApplicant = ApplicantBase & {
/**
* @description Information about the propery owners, if different than the applicant
jessicamcinchak marked this conversation as resolved.
Show resolved Hide resolved
*/
ownership:
| {interest: Extract<OwnershipInterest, 'owner'>}
| {
interest: OwnershipInterest; // `Exclude<OwnershipInterest, "owner">` ? But I think you can be co owner & report other owners?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's bookmark this with a TODO or issue and check with the content team.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of the new prototypeApplication example payloads have ownership commented out until we resolve this type - it's a good proxy for TODO ! 👍

owners: (OwnersNoticeGiven | OwnersNoNoticeGiven)[];
};
};

export type PPApplicant = ApplicantBase & {
/**
* @description Information about the ownership certificate and propery owners, if different than the applicant
jessicamcinchak marked this conversation as resolved.
Show resolved Hide resolved
*/
ownership: {
interest: OwnershipInterest | 'owner.sole' | 'owner.co';
/**
* @description Does the land have any agricultural tenants?
*/
agriculturalTenants?: boolean;
/**
* @description Has requisite notice been given to all the known owners and agricultural tenants?
*/
noticeGiven?: boolean;
/**
* @description Has a notice of the application been published in a newspaper circulating in the area where the land is situated?
*/
noticePublished?: {
status: boolean;
date?: Date;
newspaperName?: string;
};
/**
* @description Do you know the names and addresses of all owners and agricultural tenants?
*/
ownersKnown?: 'all' | 'some' | 'none';
owners?: OwnersNoticeDate[];
certificate: 'a' | 'b' | 'c' | 'd';
/**
* @description Declaration of the accuracy of the ownership certificate, including reasonable steps taken to find all owners and publish notice
*/
declaration: {
accurate: true;
};
};
/**
* @description Contact information for the person(s) responsible for maintenace while the works are carried out
*/
maintenanceContact?: MaintenanceContact[];
};

/**
* TypeMap of PrimaryApplicationTypes to their specific Applicant models
*/
interface ApplicantVariants {
ldc: LDCApplicant;
pp: PPApplicant;
}

/**
* @internal Conditional type to return a specific or generic Applicant model, based on PrimaryApplicationType
*/
export type Applicant<TPrimary extends PrimaryApplicationType> =
TPrimary extends keyof ApplicantVariants
? ApplicantVariants[TPrimary]
: ApplicantBase;
Loading
Loading