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

Conversation

jessicamcinchak
Copy link
Member

@jessicamcinchak jessicamcinchak commented Aug 29, 2024

I know this is a VERY BIG PR - but it wasn't a particularly easy one to break up, so thanks in advance for patience reviewing !

Here's a summary of key changes:

  • The prototypeApplication schema now has "real" type definitions which are feature-parity with the original application schema - but now enhanced with rules-based variations based on the primary applicationType
    • I've added comments below to highlight specific examples that demonstrate the new benefits of this, and places where there's still a few open questions
    • In annotating these types, I've dropped a lot of @id notations as we used to use per Idox feedback about this and opted for just @descriptions, so please take a look at the generated JSON too and see how this compares
  • All application examples now have an equivalent prototypeApplication example for side-by-side comparisons of what's changing (13 example payloads in total => 26 new files here)

What I haven't done here:

  • Regenerated any example application data (it'd be great to do this in the near future in order to pick up & check against latest service changes, but I don't want to muddle the side-by-side comparisons for initial feedback)
  • Perfected the rules per primary application type - this is especially lacking across data.proposal for this MVP, definitely one to revisit separately soon ! Also, it'll never be perfect
  • Defined all application types - I've gone for feature-parity with types covered by the original application schema here, which is already "householder" centric in-line with upcoming integration expectations


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!

pp: PPApplicationData;
listed: NonFeeCarryingApplicationData;
landDrainageConsent: FeeCarryingApplicationData;
Copy link
Member Author

@jessicamcinchak jessicamcinchak Sep 17, 2024

Choose a reason for hiding this comment

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

Again, nice migration win in here of now explicitly defining which application types are "fee carrying" and which are not. There's a big semantic difference between fee: 0 & fee: "notApplicable" that is now better communicated, no longer confusable based on a union type !

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this is nice! I had imagined these maps would always be application type specific, but this is a great solution.

@@ -174,15 +174,15 @@ type BasePlanningDesignation =
*/
type NonIntersectingPlanningDesignation = {
intersects: false;
} & BasePlanningDesignation;
} & {value: BasePlanningDesignation};
Copy link
Member Author

Choose a reason for hiding this comment

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

PlanningDesignations are actually an interesting case where I'm not totally convinced we want to migrate to a new enum structure? Will be curious to hear BOPS feedback on this.

Designations & constraints aren't the same typical value/description object enums like ProjectTypes (which make sense to simplify to string enums!) because other properties are also/still present (eg intersects).

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this is good to flag that they aren't true "enums" as per the rest.

There might be a middle ground where they still end up in a fairly formal anyOf but keep a single enum-like key (as opposed to having to have a perfectly matching value and description).

Agreed that reaching out for feedback here seems best!

@@ -1,4 +1,4 @@
import {URL} from '../../shared/utils';
import {URL} from './utils';

/**
* @id #Responses
Copy link
Member Author

@jessicamcinchak jessicamcinchak Sep 17, 2024

Choose a reason for hiding this comment

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

Note that Responses are now shared between the application & prototypeApplication, but nearly all else is re-defined fresh (eg even Metadata requires updated FileType enum structure).

The shared folder is generally still sparsely populated, this will make more sense to refactor once prototypeApplication replaces application in my opinion ! It's felt much easier to just keep them totally seperate while doing this comparison/migration exercise rather than try to refactor/share more in same go.

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense!

"Integer": {
"format": "integer",
"type": "number"
},
Copy link
Member Author

@jessicamcinchak jessicamcinchak Sep 17, 2024

Choose a reason for hiding this comment

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

This is a first attempt at adding a specific "Integer" type via utils defintions - this works well as an initial placeholder, but isn't technically meaningful yet !

I'm aiming for "type": "integer" as supported by JSON Schema, but with a way of generating from ts-json-schema-generator.

Copy link
Member Author

@jessicamcinchak jessicamcinchak Sep 18, 2024

Choose a reason for hiding this comment

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

Okay further investigation here:

Is it insane to think about switching TS generation libs? This thread has a lot of comparison notes, opinions: vega/ts-json-schema-generator#101 (one for a followup discussion/PR for sure!)

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah that's a frustrating limitation to hit.

It looks like ajv-formats support int32 and floats, so it might just be that this is the recommended library to use (or one with similar support).

Not sure how well this would work cross-language or in other contexts - it's definitely far from ideal, and we should strive to have the generated .json file be the source of truth here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Another option (I've not tried yet) might be multipleOf: 1 (docs).

Awkward workaround, but maybe one of these two options might get us to v1.

// name: 'PrototypeApplication',
// schema: prototypeApplicationSchema,
// examples: getJSONExamples<PrototypeApplication>('prototypeApplication'),
// },
Copy link
Member Author

Choose a reason for hiding this comment

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

This didn't work so smoothly & throws a number of type errors !

One to sort out in a follow-up PR I think, and for here I'm just relying on TS definitions & pnpm build-json-examples as the "validation" check (eg building the JSON example fails if type errors).

Copy link
Contributor

Choose a reason for hiding this comment

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

Happy for this to be a follow up!

/**
* @id #FileType
* @description Types of planning documents and drawings
*/
export type FileType =
export type PrototypeFileType =
Copy link
Member Author

@jessicamcinchak jessicamcinchak Sep 18, 2024

Choose a reason for hiding this comment

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

A few temporary "renames" required else we'll throw an error that more than one type with same name can't be exported ! Again, these will get simplified once prototypeApplication replaces application

@jessicamcinchak jessicamcinchak changed the title wip: prototype a new spec that supports definitions specific to primary application types feat: write a prototypeApplication schema with definitions based on primary application type Sep 18, 2024
@jessicamcinchak jessicamcinchak marked this pull request as ready for review September 18, 2024 11:26
@@ -712,6 +712,6 @@ export const landDrainageConsent: Application = {
payable: [],
},
},
schema: `https://theopensystemslab.github.io/digital-planning-data-schemas/${version}/schema.json`,
schema: `https://theopensystemslab.github.io/digital-planning-data-schemas/${version}/schemas/application.json`,
Copy link
Member Author

Choose a reason for hiding this comment

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

When we re-organised the file structure, we missed updating existing example payload URLs - so those are handled here! Sorry it makes for another 13 x 2 files changed though 🙈

Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch thanks!

@jessicamcinchak jessicamcinchak requested a review from a team September 18, 2024 11:28
Copy link
Contributor

@DafyddLlyr DafyddLlyr left a comment

Choose a reason for hiding this comment

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

Huge effort! 🙌

A few very minor comments - pretty much all typos and annotation suggestions.

All looks good to me, happy to help and fix forward some of the outstanding issues around tests and types.

@@ -712,6 +712,6 @@ export const landDrainageConsent: Application = {
payable: [],
},
},
schema: `https://theopensystemslab.github.io/digital-planning-data-schemas/${version}/schema.json`,
schema: `https://theopensystemslab.github.io/digital-planning-data-schemas/${version}/schemas/application.json`,
Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch thanks!

@@ -174,15 +174,15 @@ type BasePlanningDesignation =
*/
type NonIntersectingPlanningDesignation = {
intersects: false;
} & BasePlanningDesignation;
} & {value: BasePlanningDesignation};
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this is good to flag that they aren't true "enums" as per the rest.

There might be a middle ground where they still end up in a fairly formal anyOf but keep a single enum-like key (as opposed to having to have a perfectly matching value and description).

Agreed that reaching out for feedback here seems best!

@@ -1,4 +1,4 @@
import {URL} from '../../shared/utils';
import {URL} from './utils';

/**
* @id #Responses
Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense!

"Integer": {
"format": "integer",
"type": "number"
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah that's a frustrating limitation to hit.

It looks like ajv-formats support int32 and floats, so it might just be that this is the recommended library to use (or one with similar support).

Not sure how well this would work cross-language or in other contexts - it's definitely far from ideal, and we should strive to have the generated .json file be the source of truth here.

// name: 'PrototypeApplication',
// schema: prototypeApplicationSchema,
// examples: getJSONExamples<PrototypeApplication>('prototypeApplication'),
// },
Copy link
Contributor

Choose a reason for hiding this comment

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

Happy for this to be a follow up!

pp: PPApplicationData;
listed: NonFeeCarryingApplicationData;
landDrainageConsent: FeeCarryingApplicationData;
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this is nice! I had imagined these maps would always be application type specific, but this is a great solution.

* @id #UKRegion
* @description The UK region that contains this address sourced from planning.data.gov.uk/dataset/region, where London is a proxy for the Greater London Authority (GLA) area
*/
export type UKRegion =
Copy link
Contributor

Choose a reason for hiding this comment

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

(Not new in this PR, but just noticed!) These are actually regions of England and not the UK - maybe a question for Planning Data would be if this is always going to be the case.

Copy link
Member Author

Choose a reason for hiding this comment

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

Aha this is a great shout - I think we should probably be using "England" throughout for clarity. Going to find + replace this one in a followup PR 👍

export interface LondonProperty extends UKProperty {
region: Extract<UKRegion, 'London'>;
titleNumber?: {
known: 'Yes' | 'No';
Copy link
Contributor

Choose a reason for hiding this comment

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

We may want a pass through all binary choices to make them booleans.

*/
newStoreys?: NewBuildingsOrStoreys;
/**
* @description Project cost
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Worth adding GBP?

jessicamcinchak and others added 2 commits September 19, 2024 22:25
Co-authored-by: Dafydd Llŷr Pearson <[email protected]>
@jessicamcinchak jessicamcinchak merged commit 610f2f7 into main Sep 19, 2024
3 checks passed
@jessicamcinchak jessicamcinchak deleted the jess/prototype-application-definitions branch September 19, 2024 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants