@pdtf/schemas 2.2.0 → 2.3.0-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -59,8 +59,25 @@ const con29ROverlay = require("./src/schemas/v2/overlays/con29R.json");
59
59
  const con29DWOverlay = require("./src/schemas/v2/overlays/con29DW.json");
60
60
  const rdsOverlay = require("./src/schemas/v2/overlays/rds.json");
61
61
  const oc1Overlay = require("./src/schemas/v2/overlays/oc1.json");
62
+ const piqOverlay = require("./src/schemas/v2/overlays/piq.json");
62
63
 
63
- const overlaysMap = { baspiV4: baspiOverlay, ta6ed4: ta6Overlay, null: {} };
64
+ const overlaysMap = {
65
+ // either the version or the edition is added to the key for future proofing
66
+ baspiV4: baspiOverlay,
67
+ ta6ed4: ta6Overlay,
68
+ ta7ed3: ta7Overlay,
69
+ ta10ed3: ta10Overlay,
70
+ lpe1ed4: lpe1Overlay,
71
+ fme1ed2: fme1Overlay,
72
+ llc1v2: llc1Overlay,
73
+ nts2023: ntsOverlay,
74
+ con29R2019: con29ROverlay,
75
+ con29DW: con29DWOverlay,
76
+ rdsV333: rdsOverlay,
77
+ oc1v21: oc1Overlay,
78
+ piqV3: piqOverlay,
79
+ null: {},
80
+ };
64
81
 
65
82
  const transactionSchemas = {
66
83
  "https://trust.propdata.org.uk/schemas/v1/pdtf-transaction.json":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pdtf/schemas",
3
- "version": "2.2.0",
3
+ "version": "2.3.0-2",
4
4
  "description": "Property Data Trust Framework Schemas and Utilities",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -25,7 +25,6 @@
25
25
  "county": "Herts",
26
26
  "postcode": "AL3 5AF"
27
27
  },
28
-
29
28
  "delayFactors": {
30
29
  "hasDelayFactors": { "yesNo": "No" }
31
30
  },
@@ -6,6 +6,7 @@
6
6
  "description": "A schema defining the PDTF transaction data structure, supporting mapping to BASPI, Law Society and RICS Data Schema elements.",
7
7
  "baspiRequired": ["participants", "propertyPack"],
8
8
  "ta6Required": ["participants", "propertyPack"],
9
+ "ntsRequired": ["propertyPack"],
9
10
  "properties": {
10
11
  "$schema": {
11
12
  "type": "string"
@@ -131,6 +132,7 @@
131
132
  "type": "object",
132
133
  "baspiRequired": ["materialFacts", "additionalLegalInfo"],
133
134
  "ta6Required": ["materialFacts", "additionalLegalInfo"],
135
+ "ntsRequired": ["materialFacts"],
134
136
  "properties": {
135
137
  "materialFacts": {
136
138
  "type": "object",
@@ -180,6 +182,7 @@
180
182
  "environmentalIssues",
181
183
  "additionalInformation"
182
184
  ],
185
+ "ntsRequired": ["ownership", "councilTax", "energyEfficiency"],
183
186
  "properties": {
184
187
  "address": {
185
188
  "baspiRef": "A1.1",
@@ -349,6 +352,7 @@
349
352
  "ntsRef": "A3",
350
353
  "title": "Price information",
351
354
  "type": "object",
355
+ "ntsRequired": ["price", "priceQualifier"],
352
356
  "properties": {
353
357
  "price": {
354
358
  "ntsRef": "A3.1",
@@ -1013,6 +1017,7 @@
1013
1017
  "title": "Ownership",
1014
1018
  "type": "object",
1015
1019
  "baspiRequired": ["ownershipsToBeTransferred"],
1020
+ "ntsRequired": ["ownershipsToBeTransferred"],
1016
1021
  "properties": {
1017
1022
  "ownershipsToBeTransferred": {
1018
1023
  "baspiRef": "A1.3",
@@ -1025,6 +1030,7 @@
1025
1030
  "title": "Ownership to be transferred",
1026
1031
  "type": "object",
1027
1032
  "baspiRequired": ["ownershipType"],
1033
+ "ntsRequired": ["ownershipType"],
1028
1034
  "properties": {
1029
1035
  "titleNumber": {
1030
1036
  "baspiRef": "A1.3.0.1",
@@ -3422,6 +3428,11 @@
3422
3428
  "sharedOwnershipPercentage",
3423
3429
  "sharedOwnershipRent",
3424
3430
  "sharedOwnershipRentFrequency"
3431
+ ],
3432
+ "ntsRequired": [
3433
+ "sharedOwnershipPercentage",
3434
+ "sharedOwnershipRent",
3435
+ "sharedOwnershipRentFrequency"
3425
3436
  ]
3426
3437
  }
3427
3438
  ]
@@ -3433,6 +3444,10 @@
3433
3444
  "startYearOfLease",
3434
3445
  "lengthOfLeaseInYears"
3435
3446
  ],
3447
+ "ntsRequired": [
3448
+ "startYearOfLease",
3449
+ "lengthOfLeaseInYears"
3450
+ ],
3436
3451
  "properties": {
3437
3452
  "startYearOfLease": {
3438
3453
  "baspiRef": "A1.4.1.1",
@@ -5161,15 +5176,18 @@
5161
5176
  "ta7Ref": "1.2",
5162
5177
  "lpe1Ref": "3",
5163
5178
  "piqRef": "A1.3.3",
5179
+ "ntsRef": "A1.4",
5164
5180
  "title": "Ground Rent",
5165
5181
  "type": "object",
5166
5182
  "lpe1Required": ["isGroundRentPayable"],
5167
5183
  "baspiRequired": ["isGroundRentPayable"],
5168
5184
  "ta7Required": ["isGroundRentPayable"],
5185
+ "ntsRequired": ["isGroundRentPayable"],
5169
5186
  "properties": {
5170
5187
  "isGroundRentPayable": {
5171
5188
  "baspiRef": "A1.4.2.1",
5172
5189
  "ta7Ref": "1.2.1",
5190
+ "ntsRef": "A1.4.1",
5173
5191
  "title": "Does the seller pay ground rent for the property?",
5174
5192
  "type": "string",
5175
5193
  "enum": ["Yes", "No"]
@@ -5194,7 +5212,7 @@
5194
5212
  "annualGroundRent": {
5195
5213
  "baspiRef": "A1.4.2.2",
5196
5214
  "ta7Ref": "1.2a",
5197
- "ntsRef": "A1.4",
5215
+ "ntsRef": "A1.4.2",
5198
5216
  "lpe1Ref": "3.1",
5199
5217
  "piqRef": "A1.3.3",
5200
5218
  "rdsRef": "TenureAgreements/RentPayable/Value",
@@ -5208,7 +5226,7 @@
5208
5226
  },
5209
5227
  "rentSubjectToIncrease": {
5210
5228
  "baspiRef": "A1.4.2.3",
5211
- "ntsRef": "A1.5",
5229
+ "ntsRef": "A1.4.3",
5212
5230
  "ta7Ref": "1.2c",
5213
5231
  "piqRef": "A1.3.4",
5214
5232
  "type": "object",
@@ -5218,6 +5236,7 @@
5218
5236
  "baspiRef": "A1.4.2.3.1",
5219
5237
  "piqRef": "A1.3.4.1",
5220
5238
  "ta7Ref": "1.2c.1",
5239
+ "ntsRef": "1.4.3.1",
5221
5240
  "type": "string",
5222
5241
  "title": "",
5223
5242
  "enum": ["Yes", "No"]
@@ -5225,6 +5244,7 @@
5225
5244
  },
5226
5245
  "lpe1Required": ["yesNo"],
5227
5246
  "baspiRequired": ["yesNo"],
5247
+ "ntsRequired": ["yesNo"],
5228
5248
  "discriminator": {
5229
5249
  "propertyName": "yesNo"
5230
5250
  },
@@ -5244,6 +5264,7 @@
5244
5264
  "rentReviewFrequency": {
5245
5265
  "baspiRef": "A1.4.2.3.2",
5246
5266
  "ta7Ref": "1.2d",
5267
+ "ntsRef": "1.4.3.2",
5247
5268
  "title": "How often is the rent reviewed?",
5248
5269
  "type": "string"
5249
5270
  },
@@ -5251,6 +5272,7 @@
5251
5272
  "baspiRef": "A1.4.2.3.3",
5252
5273
  "piqRef": "A1.3.4.2",
5253
5274
  "ta7Ref": "1.2e",
5275
+ "ntsRef": "1.4.3.3",
5254
5276
  "title": "How is the increase calculated?",
5255
5277
  "description": "e.g. set figure, doubling, in line with Retail Price Index, Consumer Price Index, etc",
5256
5278
  "type": "string"
@@ -5263,6 +5285,10 @@
5263
5285
  "baspiRequired": [
5264
5286
  "rentReviewFrequency",
5265
5287
  "rentIncreaseCalculated"
5288
+ ],
5289
+ "ntsRequired": [
5290
+ "rentReviewFrequency",
5291
+ "rentIncreaseCalculated"
5266
5292
  ]
5267
5293
  }
5268
5294
  ]
@@ -8212,6 +8238,7 @@
8212
8238
  "title": "Energy Efficiency",
8213
8239
  "type": "object",
8214
8240
  "baspiRequired": ["certificate", "greenDealLoan"],
8241
+ "ntsRequired": ["certificate"],
8215
8242
  "ta6Required": ["certificateIsSupplied", "greenDealLoan"],
8216
8243
  "properties": {
8217
8244
  "certificateIsSupplied": {
@@ -8224,6 +8251,7 @@
8224
8251
  "baspiRef": "A1.8.3.1",
8225
8252
  "type": "object",
8226
8253
  "baspiRequired": ["currentEnergyRating"],
8254
+ "ntsRequired": ["currentEnergyRating"],
8227
8255
  "properties": {
8228
8256
  "certificateNumber": {
8229
8257
  "type": "string"
@@ -8630,6 +8658,7 @@
8630
8658
  "councilTaxBand",
8631
8659
  "councilTaxAffectingAlterations"
8632
8660
  ],
8661
+ "ntsRequired": ["councilTaxBand"],
8633
8662
  "properties": {
8634
8663
  "councilTaxBand": {
8635
8664
  "baspiRef": "A1.9.1",
@@ -36816,6 +36845,248 @@
36816
36845
  }
36817
36846
  }
36818
36847
  }
36848
+ },
36849
+ "valuationComparisonData": {
36850
+ "title": "Valuation Comparison Data",
36851
+ "description": "A collection of data used to compare the valuations (market values) of properties in the real estate or property market.",
36852
+ "type": "object",
36853
+ "properties": {
36854
+ "propertyDetails": {
36855
+ "title": "Property Details",
36856
+ "description": "Details and information related to individual properties for valuation comparison.",
36857
+ "type": "array",
36858
+ "items": {
36859
+ "type": "object",
36860
+ "properties": {
36861
+ "propertyListingInfo": {
36862
+ "title": "Property Listing Information",
36863
+ "description": "Information related to the pricing and status of a property listing.",
36864
+ "type": "object",
36865
+ "properties": {
36866
+ "listingType": {
36867
+ "title": "Listing Type",
36868
+ "type": "string",
36869
+ "enum": ["Recently Sold", "Currently On Sale"],
36870
+ "description": "Type of property listing, indicating whether it was recently sold or is currently on sale."
36871
+ }
36872
+ },
36873
+ "discriminator": {
36874
+ "propertyName": "listingType"
36875
+ },
36876
+ "oneOf": [
36877
+ {
36878
+ "title": "Recently Sold Property",
36879
+ "description": "Specific information about a property that was recently sold.",
36880
+ "properties": {
36881
+ "listingType": {
36882
+ "const": "Recently Sold"
36883
+ },
36884
+ "soldDate": {
36885
+ "title": "Sold Date",
36886
+ "type": "string",
36887
+ "format": "date-time",
36888
+ "description": "The date when the property was sold."
36889
+ },
36890
+ "soldPrice": {
36891
+ "title": "Sold Price",
36892
+ "type": "number",
36893
+ "description": "The amount for which the property was sold."
36894
+ }
36895
+ }
36896
+ },
36897
+ {
36898
+ "title": "Property Currently On Sale",
36899
+ "description": "Specific information about a property that is currently listed for sale.",
36900
+ "properties": {
36901
+ "listingType": {
36902
+ "const": "Currently On Sale"
36903
+ },
36904
+ "listedDate": {
36905
+ "title": "Listed Date",
36906
+ "type": "string",
36907
+ "format": "date-time",
36908
+ "description": "The date when the property was listed for sale."
36909
+ },
36910
+ "listPrice": {
36911
+ "title": "List Price",
36912
+ "type": "number",
36913
+ "description": "The asking price for the property currently on sale."
36914
+ }
36915
+ }
36916
+ }
36917
+ ]
36918
+ },
36919
+ "propertyFullDescription": {
36920
+ "title": "Property Description",
36921
+ "description": "A detailed description of the property.",
36922
+ "type": "string"
36923
+ },
36924
+ "uprn": {
36925
+ "title": "Unique Property Reference Number (UPRN)",
36926
+ "description": "A unique identifier for the property.",
36927
+ "type": "string"
36928
+ },
36929
+ "propertyType": {
36930
+ "title": "Type of Property",
36931
+ "description": "The type or category of the property.",
36932
+ "type": "string"
36933
+ },
36934
+ "marketingTenure": {
36935
+ "title": "Marketing Tenure",
36936
+ "description": "The type of tenure being marketed for the property.",
36937
+ "type": "string",
36938
+ "enum": [
36939
+ "Commonhold",
36940
+ "Freehold",
36941
+ "Leasehold",
36942
+ "Share of Freehold",
36943
+ "Shared Ownership"
36944
+ ]
36945
+ },
36946
+ "basicDetails": {
36947
+ "title": "Basic Property Details",
36948
+ "description": "Basic information about the property.",
36949
+ "type": "object",
36950
+ "properties": {
36951
+ "bedrooms": {
36952
+ "title": "Number of Bedrooms",
36953
+ "description": "The total number of bedrooms in the property.",
36954
+ "type": "integer"
36955
+ },
36956
+ "bathrooms": {
36957
+ "title": "Number of Bathrooms",
36958
+ "description": "The total number of bathrooms in the property.",
36959
+ "type": "integer"
36960
+ },
36961
+ "buildInformation": {
36962
+ "title": "Information related to property build",
36963
+ "description": "Details related to the construction of the property.",
36964
+ "type": "object",
36965
+ "properties": {
36966
+ "internalArea": {
36967
+ "title": "Total internal floor area",
36968
+ "description": "The total internal floor area of the property.",
36969
+ "type": "object",
36970
+ "properties": {
36971
+ "area": {
36972
+ "title": "Internal area value",
36973
+ "description": "The numerical value of the internal floor area.",
36974
+ "type": "number",
36975
+ "minimum": 0
36976
+ },
36977
+ "units": {
36978
+ "title": "Internal area units",
36979
+ "description": "The units of measurement for the internal floor area.",
36980
+ "type": "string",
36981
+ "enum": ["square metres", "square feet"]
36982
+ }
36983
+ }
36984
+ },
36985
+ "yearOfBuild": {
36986
+ "title": "Year the property was built",
36987
+ "description": "The year when the property was constructed.",
36988
+ "type": "integer"
36989
+ }
36990
+ }
36991
+ }
36992
+ }
36993
+ },
36994
+ "media": {
36995
+ "title": "Media",
36996
+ "description": "Media content related to the property listing.",
36997
+ "type": "array",
36998
+ "items": {
36999
+ "type": "object",
37000
+ "properties": {
37001
+ "mediaType": {
37002
+ "title": "Type of media",
37003
+ "description": "The type of media content (e.g., images, floorplans, brochures) related to the property.",
37004
+ "type": "string",
37005
+ "enum": [
37006
+ "Image",
37007
+ "Floorplan",
37008
+ "Brochure",
37009
+ "Virtual tour",
37010
+ "Audio tour",
37011
+ "EPC",
37012
+ "EPC graph",
37013
+ "Other"
37014
+ ]
37015
+ },
37016
+ "mediaUrl": {
37017
+ "title": "Media URL",
37018
+ "description": "The URL or link to access the media content.",
37019
+ "type": "string",
37020
+ "format": "uri"
37021
+ },
37022
+ "caption": {
37023
+ "title": "Caption",
37024
+ "description": "A descriptive caption or label for the media content.",
37025
+ "type": "string"
37026
+ }
37027
+ }
37028
+ }
37029
+ }
37030
+ }
37031
+ }
37032
+ },
37033
+ "propertyPricing": {
37034
+ "title": "Property Pricing Estimates",
37035
+ "description": "Detailed property pricing estimates, including rental estimates, market value, and yield calculations.",
37036
+ "type": "object",
37037
+ "properties": {
37038
+ "rentalEstimate": {
37039
+ "title": "Rental Estimate",
37040
+ "description": "Estimated rental income for the property.",
37041
+ "type": "object",
37042
+ "properties": {
37043
+ "estimatedAmount": {
37044
+ "title": "Rental Estimate Amount",
37045
+ "description": "The estimated rental amount for the property.",
37046
+ "type": "number"
37047
+ },
37048
+ "paymentFrequency": {
37049
+ "title": "Payment Frequency",
37050
+ "description": "The frequency at which the rental amount is calculated.",
37051
+ "type": "string",
37052
+ "enum": ["Per Week", "Per Calendar Month", "Per Year"]
37053
+ }
37054
+ }
37055
+ },
37056
+ "estimatedPrice": {
37057
+ "title": "Estimated Price",
37058
+ "description": "Approximation of the property's current market value",
37059
+ "type": "number"
37060
+ },
37061
+ "yield": {
37062
+ "title": "Yield",
37063
+ "description": "Return on investment (ROI) generated by an income-producing asset",
37064
+ "type": "number"
37065
+ },
37066
+ "priceEstimationDetails": {
37067
+ "type": "object",
37068
+ "title": "Credibility and Pricing Methodology",
37069
+ "description": "Information about the credibility of property pricing estimates and the methodology used in their calculation.",
37070
+ "properties": {
37071
+ "credibilitySources": {
37072
+ "type": "array",
37073
+ "title": "Data Sources",
37074
+ "description": "The sources of data used for property pricing estimates.",
37075
+ "items": {
37076
+ "type": "string"
37077
+ }
37078
+ },
37079
+ "pricingMethodology": {
37080
+ "title": "Pricing Methodology",
37081
+ "description": "Description of the methodology used to estimate property pricing.",
37082
+ "type": "string",
37083
+ "default": "This estimate is based on a combination of market research, historical sales data, and current market trends. It may not represent the exact market value."
37084
+ }
37085
+ }
37086
+ }
37087
+ }
37088
+ }
37089
+ }
36819
37090
  }
36820
37091
  }
36821
37092
  }
@@ -1,14 +1,29 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://trust.propdata.org.uk/schemas/v2/overlays/nts.json",
4
+ "required": [
5
+ "propertyPack"
6
+ ],
4
7
  "properties": {
5
8
  "propertyPack": {
9
+ "required": [
10
+ "materialFacts"
11
+ ],
6
12
  "properties": {
7
13
  "materialFacts": {
14
+ "required": [
15
+ "ownership",
16
+ "councilTax",
17
+ "energyEfficiency"
18
+ ],
8
19
  "properties": {
9
20
  "priceInformation": {
10
21
  "ntsRef": "A3",
11
22
  "title": "Price information",
23
+ "required": [
24
+ "price",
25
+ "priceQualifier"
26
+ ],
12
27
  "properties": {
13
28
  "price": {
14
29
  "ntsRef": "A3.1",
@@ -31,9 +46,15 @@
31
46
  "ownership": {
32
47
  "ntsRef": "A1.1",
33
48
  "title": "Ownership",
49
+ "required": [
50
+ "ownershipsToBeTransferred"
51
+ ],
34
52
  "properties": {
35
53
  "ownershipsToBeTransferred": {
36
54
  "items": {
55
+ "required": [
56
+ "ownershipType"
57
+ ],
37
58
  "oneOf": [
38
59
  null,
39
60
  null,
@@ -45,6 +66,11 @@
45
66
  "oneOf": [
46
67
  null,
47
68
  {
69
+ "required": [
70
+ "sharedOwnershipPercentage",
71
+ "sharedOwnershipRent",
72
+ "sharedOwnershipRentFrequency"
73
+ ],
48
74
  "properties": {
49
75
  "sharedOwnershipPercentage": {
50
76
  "ntsRef": "A1.7.1",
@@ -68,6 +94,10 @@
68
94
  ]
69
95
  },
70
96
  "leaseTerm": {
97
+ "required": [
98
+ "startYearOfLease",
99
+ "lengthOfLeaseInYears"
100
+ ],
71
101
  "properties": {
72
102
  "startYearOfLease": {
73
103
  "ntsRef": "A1.2",
@@ -80,16 +110,34 @@
80
110
  }
81
111
  },
82
112
  "groundRent": {
113
+ "ntsRef": "A1.4",
114
+ "title": "Ground Rent",
115
+ "discriminator": {
116
+ "propertyName": "isGroundRentPayable"
117
+ },
83
118
  "oneOf": [
84
- null,
85
119
  {
86
120
  "properties": {
121
+ "isGroundRentPayable": {
122
+ "enum": [
123
+ "No"
124
+ ]
125
+ }
126
+ }
127
+ },
128
+ {
129
+ "properties": {
130
+ "isGroundRentPayable": {
131
+ "enum": [
132
+ "Yes"
133
+ ]
134
+ },
87
135
  "annualGroundRent": {
88
- "ntsRef": "A1.4",
136
+ "ntsRef": "A1.4.2",
89
137
  "title": "What is the annual ground rent payable? (£)"
90
138
  },
91
139
  "rentSubjectToIncrease": {
92
- "ntsRef": "A1.5",
140
+ "ntsRef": "A1.4.3",
93
141
  "title": "Is the ground rent subject to increase?",
94
142
  "discriminator": {
95
143
  "propertyName": "yesNo"
@@ -110,14 +158,52 @@
110
158
  "enum": [
111
159
  "Yes"
112
160
  ]
161
+ },
162
+ "rentReviewFrequency": {
163
+ "ntsRef": "1.4.3.2",
164
+ "title": "How often is the rent reviewed?"
165
+ },
166
+ "rentIncreaseCalculated": {
167
+ "ntsRef": "1.4.3.3",
168
+ "title": "How is the increase calculated?",
169
+ "description": "e.g. set figure, doubling, in line with Retail Price Index, Consumer Price Index, etc"
113
170
  }
114
- }
171
+ },
172
+ "required": [
173
+ "rentReviewFrequency",
174
+ "rentIncreaseCalculated"
175
+ ]
115
176
  }
116
- ]
177
+ ],
178
+ "required": [
179
+ "yesNo"
180
+ ],
181
+ "properties": {
182
+ "yesNo": {
183
+ "ntsRef": "1.4.3.1",
184
+ "enum": [
185
+ "Yes",
186
+ "No"
187
+ ]
188
+ }
189
+ }
117
190
  }
118
191
  }
119
192
  }
120
- ]
193
+ ],
194
+ "required": [
195
+ "isGroundRentPayable"
196
+ ],
197
+ "properties": {
198
+ "isGroundRentPayable": {
199
+ "ntsRef": "A1.4.1",
200
+ "title": "Does the seller pay ground rent for the property?",
201
+ "enum": [
202
+ "Yes",
203
+ "No"
204
+ ]
205
+ }
206
+ }
121
207
  }
122
208
  }
123
209
  }
@@ -128,9 +214,24 @@
128
214
  }
129
215
  }
130
216
  },
217
+ "energyEfficiency": {
218
+ "required": [
219
+ "certificate"
220
+ ],
221
+ "properties": {
222
+ "certificate": {
223
+ "required": [
224
+ "currentEnergyRating"
225
+ ]
226
+ }
227
+ }
228
+ },
131
229
  "councilTax": {
132
230
  "ntsRef": "A2",
133
231
  "title": "Council Tax",
232
+ "required": [
233
+ "councilTaxBand"
234
+ ],
134
235
  "properties": {
135
236
  "councilTaxBand": {
136
237
  "ntsRef": "A2.1",
@@ -33341,6 +33341,255 @@
33341
33341
  }
33342
33342
  }
33343
33343
  }
33344
+ },
33345
+ "valuationComparisonData": {
33346
+ "title": "Valuation Comparison Data",
33347
+ "description": "A collection of data used to compare the valuations (market values) of properties in the real estate or property market.",
33348
+ "type": "object",
33349
+ "properties": {
33350
+ "propertyDetails": {
33351
+ "title": "Property Details",
33352
+ "description": "Details and information related to individual properties for valuation comparison.",
33353
+ "type": "array",
33354
+ "items": {
33355
+ "type": "object",
33356
+ "properties": {
33357
+ "propertyListingInfo": {
33358
+ "title": "Property Listing Information",
33359
+ "description": "Information related to the pricing and status of a property listing.",
33360
+ "type": "object",
33361
+ "properties": {
33362
+ "listingType": {
33363
+ "title": "Listing Type",
33364
+ "type": "string",
33365
+ "enum": [
33366
+ "Recently Sold",
33367
+ "Currently On Sale"
33368
+ ],
33369
+ "description": "Type of property listing, indicating whether it was recently sold or is currently on sale."
33370
+ }
33371
+ },
33372
+ "oneOf": [
33373
+ {
33374
+ "title": "Recently Sold Property",
33375
+ "description": "Specific information about a property that was recently sold.",
33376
+ "properties": {
33377
+ "listingType": {
33378
+ "const": "Recently Sold"
33379
+ },
33380
+ "soldDate": {
33381
+ "title": "Sold Date",
33382
+ "type": "string",
33383
+ "format": "date-time",
33384
+ "description": "The date when the property was sold."
33385
+ },
33386
+ "soldPrice": {
33387
+ "title": "Sold Price",
33388
+ "type": "number",
33389
+ "description": "The amount for which the property was sold."
33390
+ }
33391
+ }
33392
+ },
33393
+ {
33394
+ "title": "Property Currently On Sale",
33395
+ "description": "Specific information about a property that is currently listed for sale.",
33396
+ "properties": {
33397
+ "listingType": {
33398
+ "const": "Currently On Sale"
33399
+ },
33400
+ "listedDate": {
33401
+ "title": "Listed Date",
33402
+ "type": "string",
33403
+ "format": "date-time",
33404
+ "description": "The date when the property was listed for sale."
33405
+ },
33406
+ "listPrice": {
33407
+ "title": "List Price",
33408
+ "type": "number",
33409
+ "description": "The asking price for the property currently on sale."
33410
+ }
33411
+ }
33412
+ }
33413
+ ]
33414
+ },
33415
+ "propertyFullDescription": {
33416
+ "title": "Property Description",
33417
+ "description": "A detailed description of the property.",
33418
+ "type": "string"
33419
+ },
33420
+ "uprn": {
33421
+ "title": "Unique Property Reference Number (UPRN)",
33422
+ "description": "A unique identifier for the property.",
33423
+ "type": "string"
33424
+ },
33425
+ "propertyType": {
33426
+ "title": "Type of Property",
33427
+ "description": "The type or category of the property.",
33428
+ "type": "string"
33429
+ },
33430
+ "marketingTenure": {
33431
+ "title": "Marketing Tenure",
33432
+ "description": "The type of tenure being marketed for the property.",
33433
+ "type": "string",
33434
+ "enum": [
33435
+ "Commonhold",
33436
+ "Freehold",
33437
+ "Leasehold",
33438
+ "Share of Freehold",
33439
+ "Shared Ownership"
33440
+ ]
33441
+ },
33442
+ "basicDetails": {
33443
+ "title": "Basic Property Details",
33444
+ "description": "Basic information about the property.",
33445
+ "type": "object",
33446
+ "properties": {
33447
+ "bedrooms": {
33448
+ "title": "Number of Bedrooms",
33449
+ "description": "The total number of bedrooms in the property.",
33450
+ "type": "integer"
33451
+ },
33452
+ "bathrooms": {
33453
+ "title": "Number of Bathrooms",
33454
+ "description": "The total number of bathrooms in the property.",
33455
+ "type": "integer"
33456
+ },
33457
+ "buildInformation": {
33458
+ "title": "Information related to property build",
33459
+ "description": "Details related to the construction of the property.",
33460
+ "type": "object",
33461
+ "properties": {
33462
+ "internalArea": {
33463
+ "title": "Total internal floor area",
33464
+ "description": "The total internal floor area of the property.",
33465
+ "type": "object",
33466
+ "properties": {
33467
+ "area": {
33468
+ "title": "Internal area value",
33469
+ "description": "The numerical value of the internal floor area.",
33470
+ "type": "number",
33471
+ "minimum": 0
33472
+ },
33473
+ "units": {
33474
+ "title": "Internal area units",
33475
+ "description": "The units of measurement for the internal floor area.",
33476
+ "type": "string",
33477
+ "enum": [
33478
+ "square metres",
33479
+ "square feet"
33480
+ ]
33481
+ }
33482
+ }
33483
+ },
33484
+ "yearOfBuild": {
33485
+ "title": "Year the property was built",
33486
+ "description": "The year when the property was constructed.",
33487
+ "type": "integer"
33488
+ }
33489
+ }
33490
+ }
33491
+ }
33492
+ },
33493
+ "media": {
33494
+ "title": "Media",
33495
+ "description": "Media content related to the property listing.",
33496
+ "type": "array",
33497
+ "items": {
33498
+ "type": "object",
33499
+ "properties": {
33500
+ "mediaType": {
33501
+ "title": "Type of media",
33502
+ "description": "The type of media content (e.g., images, floorplans, brochures) related to the property.",
33503
+ "type": "string",
33504
+ "enum": [
33505
+ "Image",
33506
+ "Floorplan",
33507
+ "Brochure",
33508
+ "Virtual tour",
33509
+ "Audio tour",
33510
+ "EPC",
33511
+ "EPC graph",
33512
+ "Other"
33513
+ ]
33514
+ },
33515
+ "mediaUrl": {
33516
+ "title": "Media URL",
33517
+ "description": "The URL or link to access the media content.",
33518
+ "type": "string",
33519
+ "format": "uri"
33520
+ },
33521
+ "caption": {
33522
+ "title": "Caption",
33523
+ "description": "A descriptive caption or label for the media content.",
33524
+ "type": "string"
33525
+ }
33526
+ }
33527
+ }
33528
+ }
33529
+ }
33530
+ }
33531
+ },
33532
+ "propertyPricing": {
33533
+ "title": "Property Pricing Estimates",
33534
+ "description": "Detailed property pricing estimates, including rental estimates, market value, and yield calculations.",
33535
+ "type": "object",
33536
+ "properties": {
33537
+ "rentalEstimate": {
33538
+ "title": "Rental Estimate",
33539
+ "description": "Estimated rental income for the property.",
33540
+ "type": "object",
33541
+ "properties": {
33542
+ "estimatedAmount": {
33543
+ "title": "Rental Estimate Amount",
33544
+ "description": "The estimated rental amount for the property.",
33545
+ "type": "number"
33546
+ },
33547
+ "paymentFrequency": {
33548
+ "title": "Payment Frequency",
33549
+ "description": "The frequency at which the rental amount is calculated.",
33550
+ "type": "string",
33551
+ "enum": [
33552
+ "Per Week",
33553
+ "Per Calendar Month",
33554
+ "Per Year"
33555
+ ]
33556
+ }
33557
+ }
33558
+ },
33559
+ "estimatedPrice": {
33560
+ "title": "Estimated Price",
33561
+ "description": "Approximation of the property's current market value",
33562
+ "type": "number"
33563
+ },
33564
+ "yield": {
33565
+ "title": "Yield",
33566
+ "description": "Return on investment (ROI) generated by an income-producing asset",
33567
+ "type": "number"
33568
+ },
33569
+ "priceEstimationDetails": {
33570
+ "type": "object",
33571
+ "title": "Credibility and Pricing Methodology",
33572
+ "description": "Information about the credibility of property pricing estimates and the methodology used in their calculation.",
33573
+ "properties": {
33574
+ "credibilitySources": {
33575
+ "type": "array",
33576
+ "title": "Data Sources",
33577
+ "description": "The sources of data used for property pricing estimates.",
33578
+ "items": {
33579
+ "type": "string"
33580
+ }
33581
+ },
33582
+ "pricingMethodology": {
33583
+ "title": "Pricing Methodology",
33584
+ "description": "Description of the methodology used to estimate property pricing.",
33585
+ "type": "string",
33586
+ "default": "This estimate is based on a combination of market research, historical sales data, and current market trends. It may not represent the exact market value."
33587
+ }
33588
+ }
33589
+ }
33590
+ }
33591
+ }
33592
+ }
33344
33593
  }
33345
33594
  }
33346
33595
  }
@@ -3734,5 +3734,48 @@
3734
3734
  "documentType": {},
3735
3735
  "externalIds": {}
3736
3736
  }
3737
+ },
3738
+ "valuationComparisonData": {
3739
+ "propertyDetails": {
3740
+ "propertyListingInfo": {
3741
+ "listingType": {},
3742
+ "soldDate": {},
3743
+ "soldPrice": {},
3744
+ "listedDate": {},
3745
+ "listPrice": {}
3746
+ },
3747
+ "propertyFullDescription": {},
3748
+ "uprn": {},
3749
+ "propertyType": {},
3750
+ "marketingTenure": {},
3751
+ "basicDetails": {
3752
+ "bedrooms": {},
3753
+ "bathrooms": {},
3754
+ "buildInformation": {
3755
+ "internalArea": {
3756
+ "area": {},
3757
+ "units": {}
3758
+ },
3759
+ "yearOfBuild": {}
3760
+ }
3761
+ },
3762
+ "media": {
3763
+ "mediaType": {},
3764
+ "mediaUrl": {},
3765
+ "caption": {}
3766
+ }
3767
+ },
3768
+ "propertyPricing": {
3769
+ "rentalEstimate": {
3770
+ "estimatedAmount": {},
3771
+ "paymentFrequency": {}
3772
+ },
3773
+ "estimatedPrice": {},
3774
+ "yield": {},
3775
+ "priceEstimationDetails": {
3776
+ "credibilitySources": {},
3777
+ "pricingMethodology": {}
3778
+ }
3779
+ }
3737
3780
  }
3738
3781
  }
@@ -26,7 +26,7 @@ test("exports a property pack schema, v2 with baspi overlay by default", () => {
26
26
  ).toEqual("A");
27
27
  });
28
28
 
29
- test("sample is valid", () => {
29
+ test("sample is valid BASPI", () => {
30
30
  const testSchema = getTransactionSchema();
31
31
  expect(
32
32
  testSchema.properties.propertyPack.properties.materialFacts.baspiRef
@@ -255,6 +255,32 @@ test("correctly gets a subschema validator for a TA6 overlay which fails to vali
255
255
  expect(isValid).toBe(false);
256
256
  });
257
257
 
258
+ test("correctly gets a subschema validator for an NTS overlay", () => {
259
+ const path = "/propertyPack";
260
+ const clonedExampleTransaction = JSON.parse(
261
+ JSON.stringify(exampleTransaction)
262
+ );
263
+ const data = jp.get(clonedExampleTransaction, path);
264
+ const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
265
+ "nts2023",
266
+ ]);
267
+ let isValid = validator(data);
268
+ expect(isValid).toBe(true);
269
+ });
270
+
271
+ test("correctly gets a subschema validator for an LPE1 overlay", () => {
272
+ const path = "/propertyPack";
273
+ const clonedExampleTransaction = JSON.parse(
274
+ JSON.stringify(exampleTransaction)
275
+ );
276
+ const data = jp.get(clonedExampleTransaction, path);
277
+ const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
278
+ "lpe1ed4",
279
+ ]);
280
+ let isValid = validator(data);
281
+ expect(isValid).toBe(false);
282
+ });
283
+
258
284
  test("correctly gets a subschema validator which validates", () => {
259
285
  const path = "/propertyPack/materialFacts/notices";
260
286
  const validator = getSubschemaValidator(path);
@@ -25,12 +25,22 @@
25
25
  "type": "string"
26
26
  },
27
27
  "CreationDate": {
28
- "type": "string",
29
- "format": "date"
28
+ "type": "object",
29
+ "properties": {
30
+ "Value": {
31
+ "type": "string",
32
+ "format": "date"
33
+ }
34
+ }
30
35
  },
31
36
  "RegistrationDate": {
32
- "type": "string",
33
- "format": "date"
37
+ "type": "object",
38
+ "properties": {
39
+ "Value": {
40
+ "type": "string",
41
+ "format": "date"
42
+ }
43
+ }
34
44
  },
35
45
  "Category": {
36
46
  "type": "string"
@@ -46,37 +56,74 @@
46
56
  },
47
57
  "Location": {
48
58
  "type": "object",
49
- "required": ["line1", "Postcode"],
59
+ "required": ["AddressLine"],
50
60
  "properties": {
51
- "line1": {
52
- "type": "string"
53
- },
54
- "line2": {
55
- "type": "string"
56
- },
57
- "line3": {
58
- "type": "string"
61
+ "PostcodeZone": {
62
+ "type": "object",
63
+ "required": ["Postcode"],
64
+ "properties": {
65
+ "Postcode": {
66
+ "type": "string"
67
+ }
68
+ }
59
69
  },
60
- "Postcode": {
61
- "type": "string"
70
+ "AddressLine": {
71
+ "type": "object",
72
+ "properties": {
73
+ "IndexNumeric": {
74
+ "type": "array",
75
+ "items": {
76
+ "type": "object",
77
+ "properties": {
78
+ "Value": {
79
+ "type": "number"
80
+ }
81
+ }
82
+ },
83
+ "minItems": 0
84
+ },
85
+ "Line": {
86
+ "type": "array",
87
+ "items": {
88
+ "type": "string"
89
+ },
90
+ "minItems": 0
91
+ }
92
+ }
62
93
  }
63
94
  }
64
95
  },
65
96
  "LocationDominantBuilding": {
66
97
  "type": "object",
67
- "required": ["line1", "Postcode"],
98
+ "required": ["AddressLine"],
68
99
  "properties": {
69
- "line1": {
70
- "type": "string"
71
- },
72
- "line2": {
73
- "type": "string"
74
- },
75
- "line3": {
76
- "type": "string"
100
+ "PostcodeZone": {
101
+ "type": "object",
102
+ "required": ["Postcode"],
103
+ "properties": {
104
+ "Postcode": {
105
+ "type": "string"
106
+ }
107
+ }
77
108
  },
78
- "Postcode": {
79
- "type": "string"
109
+ "AddressLine": {
110
+ "type": "object",
111
+ "properties": {
112
+ "IndexNumeric": {
113
+ "type": "array",
114
+ "items": {
115
+ "type": "number"
116
+ },
117
+ "minItems": 0
118
+ },
119
+ "Line": {
120
+ "type": "array",
121
+ "items": {
122
+ "type": "string"
123
+ },
124
+ "minItems": 0
125
+ }
126
+ }
80
127
  }
81
128
  }
82
129
  },
@@ -115,19 +162,45 @@
115
162
  },
116
163
  "ApplicantAddress": {
117
164
  "type": "object",
118
- "required": ["line1", "Postcode"],
165
+ "required": ["AddressLine"],
119
166
  "properties": {
120
- "line1": {
121
- "type": "string"
122
- },
123
- "line2": {
124
- "type": "string"
125
- },
126
- "line3": {
127
- "type": "string"
167
+ "PostcodeZone": {
168
+ "type": "object",
169
+ "required": ["Postcode"],
170
+ "properties": {
171
+ "Postcode": {
172
+ "type": "string"
173
+ }
174
+ }
128
175
  },
129
- "Postcode": {
130
- "type": "string"
176
+ "AddressLine": {
177
+ "type": "object",
178
+ "properties": {
179
+ "IndexNumeric": {
180
+ "type": "array",
181
+ "items": {
182
+ "type": "object",
183
+ "properties": {
184
+ "Value": {
185
+ "type": "number"
186
+ }
187
+ }
188
+ },
189
+ "minItems": 0
190
+ },
191
+ "Line": {
192
+ "type": "array",
193
+ "items": {
194
+ "type": "object",
195
+ "properties": {
196
+ "Value": {
197
+ "type": "string"
198
+ }
199
+ }
200
+ },
201
+ "minItems": 0
202
+ }
203
+ }
131
204
  }
132
205
  }
133
206
  },
@@ -184,7 +257,15 @@
184
257
  "minItems": 0
185
258
  },
186
259
  "ChargeExtent": {
187
- "type": "string"
260
+ "type": "object",
261
+ "properties": {
262
+ "Value": {
263
+ "type": "string"
264
+ },
265
+ "format": {
266
+ "type": "string"
267
+ }
268
+ }
188
269
  }
189
270
  }
190
271
  },