@rentcheck/biz 1.0.0
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/dist/api/inspection-template/build-template-features.d.ts +10 -0
- package/dist/api/inspection-template/build-template-features.js +215 -0
- package/dist/api/inspection-template/build-template-features.js.map +1 -0
- package/dist/api/inspection-template/index.d.ts +7 -0
- package/dist/api/inspection-template/index.js +6 -0
- package/dist/api/inspection-template/index.js.map +1 -0
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.js +15 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +28 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +20 -0
- package/src/api/inspection-template/build-template-features.ts +387 -0
- package/src/api/inspection-template/index.ts +3 -0
- package/src/utils/constants.ts +11 -0
- package/src/utils/index.ts +1 -0
- package/tsconfig.dev.json +5 -0
- package/tsconfig.json +27 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Feature, Inspection, InspectionTemplate, Property } from '@rentcheck/types';
|
|
2
|
+
export declare const parseTemplateRoomName: (name: string) => string;
|
|
3
|
+
export declare const sectionCanExistMultipleTimes: (sectionName: string) => boolean;
|
|
4
|
+
type BuildTemplateFeaturesParams = {
|
|
5
|
+
inspection: Inspection;
|
|
6
|
+
property: Property;
|
|
7
|
+
inspectionTemplate: InspectionTemplate;
|
|
8
|
+
};
|
|
9
|
+
export declare const buildTemplateFeatures: ({ inspection, property, inspectionTemplate, }: BuildTemplateFeaturesParams) => Promise<Feature[]>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.buildTemplateFeatures = exports.sectionCanExistMultipleTimes = exports.parseTemplateRoomName = void 0;
|
|
13
|
+
const utils_1 = require("../../utils");
|
|
14
|
+
const createResponsesForFeature = (feature) => feature.questions.map((q) => {
|
|
15
|
+
if (q.type === 'yes/no') {
|
|
16
|
+
return 'Yes';
|
|
17
|
+
}
|
|
18
|
+
return '';
|
|
19
|
+
});
|
|
20
|
+
const createEmptyFeature = (inspection, basicFeatureProps, section, sectionName, sectionNameWithOrdinal) => (Object.assign(Object.assign({}, basicFeatureProps), { id: '', inspection_id: inspection.id, property_id: inspection.propertyID, section: {
|
|
21
|
+
name: sectionName,
|
|
22
|
+
name_with_ordinal: sectionNameWithOrdinal !== null && sectionNameWithOrdinal !== void 0 ? sectionNameWithOrdinal : sectionName,
|
|
23
|
+
type: section.type,
|
|
24
|
+
}, images: [], videos: [], image_links: [], video_links: [], rating: undefined, incomplete: true, not_applicable: false, notes: '', responses: createResponsesForFeature(basicFeatureProps), uploaded: false, revision_requested: false, revision_requested_update: false, edited_by_reviewer: false, review_notes: '', reviewed_by: undefined, reviewed_at: undefined, maintenance_flags: [], created_date: new Date(), updated_date: new Date() }));
|
|
25
|
+
const createFeaturesFromSection = (inspection, section, sectionName, sectionNameWithOrdinal) => {
|
|
26
|
+
if (!section.features.length) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* If fast track is enabled, we only create one feature for the section
|
|
31
|
+
* with the name of the section as feature name and a predefined description.
|
|
32
|
+
*/
|
|
33
|
+
if (inspection.fast_track) {
|
|
34
|
+
const basicFeatureProps = {
|
|
35
|
+
name: sectionName,
|
|
36
|
+
description: '',
|
|
37
|
+
is_rating_required: true,
|
|
38
|
+
reference_photos: [],
|
|
39
|
+
number_of_photos_required: 1,
|
|
40
|
+
questions: [],
|
|
41
|
+
};
|
|
42
|
+
if (section.type === 'room') {
|
|
43
|
+
basicFeatureProps.description =
|
|
44
|
+
`Stand back from each corner to ` +
|
|
45
|
+
`ensure you get photos of the ${sectionName} in its entirety.`;
|
|
46
|
+
}
|
|
47
|
+
else if (section.type === 'section') {
|
|
48
|
+
basicFeatureProps.description =
|
|
49
|
+
`Take any additional ${sectionName}` +
|
|
50
|
+
` photos that you would like to document.`;
|
|
51
|
+
}
|
|
52
|
+
return [
|
|
53
|
+
createEmptyFeature(inspection, basicFeatureProps, section, sectionName, sectionNameWithOrdinal),
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* If fast track is not enabled, we create features based on the template
|
|
58
|
+
* features for the section.
|
|
59
|
+
*/
|
|
60
|
+
return section.features.map((tf) => createEmptyFeature(inspection, tf, section, sectionName, sectionNameWithOrdinal));
|
|
61
|
+
};
|
|
62
|
+
const parseTemplateRoomName = (name) => {
|
|
63
|
+
if (name === 'Floors') {
|
|
64
|
+
return 'Floor';
|
|
65
|
+
}
|
|
66
|
+
if (name === 'Full Bathrooms') {
|
|
67
|
+
return 'Full Bathroom';
|
|
68
|
+
}
|
|
69
|
+
if (name === 'Half Bathrooms') {
|
|
70
|
+
return 'Half Bathroom';
|
|
71
|
+
}
|
|
72
|
+
if (name === 'Bedrooms') {
|
|
73
|
+
return 'Bedroom';
|
|
74
|
+
}
|
|
75
|
+
return name;
|
|
76
|
+
};
|
|
77
|
+
exports.parseTemplateRoomName = parseTemplateRoomName;
|
|
78
|
+
const sectionCanExistMultipleTimes = (sectionName) => [
|
|
79
|
+
'Bedroom',
|
|
80
|
+
'Bedrooms',
|
|
81
|
+
'Full Bathroom',
|
|
82
|
+
'Full Bathrooms',
|
|
83
|
+
'Half Bathroom',
|
|
84
|
+
'Half Bathrooms',
|
|
85
|
+
'Floor',
|
|
86
|
+
'Floors',
|
|
87
|
+
].includes(sectionName);
|
|
88
|
+
exports.sectionCanExistMultipleTimes = sectionCanExistMultipleTimes;
|
|
89
|
+
const addOrdinalToFloorSection = (number) => {
|
|
90
|
+
/**
|
|
91
|
+
* America has no concept of a ground floor, so we add 1 to the number
|
|
92
|
+
* to get the correct floor name. /shrug
|
|
93
|
+
*/
|
|
94
|
+
const floor = number + 1;
|
|
95
|
+
if (floor % 10 === 1) {
|
|
96
|
+
return `${floor}st Floor`;
|
|
97
|
+
}
|
|
98
|
+
if (floor % 10 === 2) {
|
|
99
|
+
return `${floor}nd Floor`;
|
|
100
|
+
}
|
|
101
|
+
if (floor % 10 === 3) {
|
|
102
|
+
return `${floor}rd Floor`;
|
|
103
|
+
}
|
|
104
|
+
return `${floor}th Floor`;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Adds an ordinal to the section to account for repeatable sections.
|
|
108
|
+
*
|
|
109
|
+
* @param sectionName Floor, Bedroom, Full Bathroom, Half Bathroom
|
|
110
|
+
* @param number index of the section, 0 indexed
|
|
111
|
+
* @returns the updated section name, e.g. "First Floor", "Second Bedroom"
|
|
112
|
+
*/
|
|
113
|
+
const addOrdinalToSectionName = (sectionName, number) => {
|
|
114
|
+
if (sectionName === 'Floor') {
|
|
115
|
+
return addOrdinalToFloorSection(number);
|
|
116
|
+
}
|
|
117
|
+
return `${utils_1.Constants.ordinalPrefixes[number]} ${sectionName}`;
|
|
118
|
+
};
|
|
119
|
+
const createFeaturesFromRepeatableSection = (sectionName, section, inspection, property) => {
|
|
120
|
+
const sectionCount = sectionName === 'Floor'
|
|
121
|
+
? property.floors
|
|
122
|
+
: inspection.rooms.filter((r) => r === sectionName).length;
|
|
123
|
+
return new Array(sectionCount)
|
|
124
|
+
.fill(null)
|
|
125
|
+
.map((_, i) => createFeaturesFromSection(inspection, section, sectionName, addOrdinalToSectionName(sectionName, i)))
|
|
126
|
+
.flat();
|
|
127
|
+
};
|
|
128
|
+
const parseSelectedSectionName = (name) => {
|
|
129
|
+
if (/(\d)+(st|nd|rd|th) Floor/.test(name)) {
|
|
130
|
+
return 'Floors';
|
|
131
|
+
}
|
|
132
|
+
if (/\w+ Full Bathroom/.test(name)) {
|
|
133
|
+
return 'Full Bathrooms';
|
|
134
|
+
}
|
|
135
|
+
if (/\w+ Half Bathroom/.test(name)) {
|
|
136
|
+
return 'Half Bathrooms';
|
|
137
|
+
}
|
|
138
|
+
if (/\w+ Bedroom/.test(name)) {
|
|
139
|
+
return 'Bedrooms';
|
|
140
|
+
}
|
|
141
|
+
return name;
|
|
142
|
+
};
|
|
143
|
+
const createFeaturesForSpecificFeaturesTemplate = (inspection, inspectionTemplate) => {
|
|
144
|
+
var _a;
|
|
145
|
+
const features = [];
|
|
146
|
+
const selectedFeatures = Array.from((_a = inspection.selected_features) !== null && _a !== void 0 ? _a : []);
|
|
147
|
+
for (const selectedFeature of selectedFeatures) {
|
|
148
|
+
const sectionName = parseSelectedSectionName(selectedFeature.section);
|
|
149
|
+
const section = inspectionTemplate.sections.find((s) => s.name === sectionName);
|
|
150
|
+
if (!section) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
const selectedFeaturesInSection = section.features.filter((f) => selectedFeature.feature === f.name);
|
|
154
|
+
const limitedSection = Object.assign(Object.assign({}, section), { features: selectedFeaturesInSection });
|
|
155
|
+
/**
|
|
156
|
+
* For selected features we create sections in the template regardless of
|
|
157
|
+
* property rooms. We assume all that logic already happened in the backend
|
|
158
|
+
* at the time of inspection creation
|
|
159
|
+
*/
|
|
160
|
+
features.push(...createFeaturesFromSection(inspection, limitedSection, section.name, selectedFeature.room_name));
|
|
161
|
+
}
|
|
162
|
+
return features;
|
|
163
|
+
};
|
|
164
|
+
const createFeaturesForAllRoomsTemplate = (inspection, inspectionTemplate, property) => {
|
|
165
|
+
const features = [];
|
|
166
|
+
for (const section of inspectionTemplate.sections) {
|
|
167
|
+
/**
|
|
168
|
+
* We create sections in the template regardless of
|
|
169
|
+
* property rooms.
|
|
170
|
+
*/
|
|
171
|
+
if (section.type === 'section') {
|
|
172
|
+
features.push(...createFeaturesFromSection(inspection, section, section.name));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* For room type sections we first check if the room exists on
|
|
176
|
+
* the property/inspection. If it does we create the features for that room.
|
|
177
|
+
*/
|
|
178
|
+
if (section.type === 'room') {
|
|
179
|
+
/**
|
|
180
|
+
* Some section names use plural nomenclature, while the property rooms
|
|
181
|
+
* are all singular, that's why we first need to change
|
|
182
|
+
*/
|
|
183
|
+
const singularName = (0, exports.parseTemplateRoomName)(section.name);
|
|
184
|
+
if (!inspection.rooms.includes(singularName)) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* If this is a section that can be repeated (Bedroom, Bathroom, etc.)
|
|
189
|
+
* we need to create features for each room of that type.
|
|
190
|
+
*/
|
|
191
|
+
if ((0, exports.sectionCanExistMultipleTimes)(section.name)) {
|
|
192
|
+
features.push(...createFeaturesFromRepeatableSection(singularName, section, inspection, property));
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
features.push(...createFeaturesFromSection(inspection, section, singularName));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return features;
|
|
200
|
+
};
|
|
201
|
+
const buildTemplateFeatures = (_a) => __awaiter(void 0, [_a], void 0, function* ({ inspection, property, inspectionTemplate, }) {
|
|
202
|
+
const features = [];
|
|
203
|
+
if (!property) {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
if (inspectionTemplate.template_type === 'all-rooms') {
|
|
207
|
+
features.push(...createFeaturesForAllRoomsTemplate(inspection, inspectionTemplate, property));
|
|
208
|
+
}
|
|
209
|
+
if (inspectionTemplate.template_type === 'specific-features') {
|
|
210
|
+
features.push(...createFeaturesForSpecificFeaturesTemplate(inspection, inspectionTemplate));
|
|
211
|
+
}
|
|
212
|
+
return features;
|
|
213
|
+
});
|
|
214
|
+
exports.buildTemplateFeatures = buildTemplateFeatures;
|
|
215
|
+
//# sourceMappingURL=build-template-features.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-template-features.js","sourceRoot":"","sources":["../../../src/api/inspection-template/build-template-features.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const InspectionTemplateBiz: {
|
|
2
|
+
buildTemplateFeatures: ({ inspection, property, inspectionTemplate, }: {
|
|
3
|
+
inspection: import("@rentcheck/types").Inspection;
|
|
4
|
+
property: import("@rentcheck/types").Property;
|
|
5
|
+
inspectionTemplate: import("@rentcheck/types").InspectionTemplate;
|
|
6
|
+
}) => Promise<import("@rentcheck/types").Feature[]>;
|
|
7
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InspectionTemplateBiz = void 0;
|
|
4
|
+
const build_template_features_1 = require("./build-template-features");
|
|
5
|
+
exports.InspectionTemplateBiz = { buildTemplateFeatures: build_template_features_1.buildTemplateFeatures };
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/inspection-template/index.ts"],"names":[],"mappings":";;;AAAA,uEAAkE;AAErD,QAAA,qBAAqB,GAAG,EAAE,qBAAqB,EAArB,+CAAqB,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ordinalPrefixes: string[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ordinalPrefixes = void 0;
|
|
4
|
+
exports.ordinalPrefixes = [
|
|
5
|
+
'First',
|
|
6
|
+
'Second',
|
|
7
|
+
'Third',
|
|
8
|
+
'Fourth',
|
|
9
|
+
'Fifth',
|
|
10
|
+
'Sixth',
|
|
11
|
+
'Seventh',
|
|
12
|
+
'Eighth',
|
|
13
|
+
'Ninth',
|
|
14
|
+
];
|
|
15
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,eAAe,GAAG;IAC9B,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,SAAS;IACT,QAAQ;IACR,OAAO;CACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as Constants from './constants';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.Constants = void 0;
|
|
27
|
+
exports.Constants = __importStar(require("./constants"));
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yDAAyC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rentcheck/biz",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "RC biz",
|
|
5
|
+
"types": "lib/index.d.ts",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"build:watch": "tsc --watch",
|
|
10
|
+
"test": "cross-env NODE_ENV=test jest --verbose --forceExit"
|
|
11
|
+
},
|
|
12
|
+
"author": "engineering@getrentcheck.com",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@rentcheck/types": "^1.0.460",
|
|
16
|
+
"@types/node": "^20.11.30",
|
|
17
|
+
"jest": "^29.7.0",
|
|
18
|
+
"typescript": "^5.4.3"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Building,
|
|
3
|
+
Feature,
|
|
4
|
+
Inspection,
|
|
5
|
+
InspectionTemplate,
|
|
6
|
+
OfflineFeature,
|
|
7
|
+
Property,
|
|
8
|
+
TemplateFeature,
|
|
9
|
+
TemplateSection,
|
|
10
|
+
Timestamp,
|
|
11
|
+
} from '@rentcheck/types';
|
|
12
|
+
|
|
13
|
+
import { Constants } from '../../utils';
|
|
14
|
+
|
|
15
|
+
type BasicFeatureProps = Pick<
|
|
16
|
+
TemplateFeature,
|
|
17
|
+
| 'name'
|
|
18
|
+
| 'description'
|
|
19
|
+
| 'is_rating_required'
|
|
20
|
+
| 'reference_photos'
|
|
21
|
+
| 'number_of_photos_required'
|
|
22
|
+
| 'questions'
|
|
23
|
+
>;
|
|
24
|
+
|
|
25
|
+
const createResponsesForFeature = (feature: BasicFeatureProps): string[] =>
|
|
26
|
+
feature.questions.map((q) => {
|
|
27
|
+
if (q.type === 'yes/no') {
|
|
28
|
+
return 'Yes';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return '';
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const createEmptyFeature = (
|
|
35
|
+
inspection: Inspection,
|
|
36
|
+
basicFeatureProps: BasicFeatureProps,
|
|
37
|
+
section: TemplateSection,
|
|
38
|
+
sectionName: string,
|
|
39
|
+
sectionNameWithOrdinal?: string
|
|
40
|
+
): OfflineFeature => ({
|
|
41
|
+
...basicFeatureProps,
|
|
42
|
+
|
|
43
|
+
id: '',
|
|
44
|
+
inspection_id: inspection.id,
|
|
45
|
+
property_id: inspection.propertyID,
|
|
46
|
+
|
|
47
|
+
section: {
|
|
48
|
+
name: sectionName,
|
|
49
|
+
name_with_ordinal: sectionNameWithOrdinal ?? sectionName,
|
|
50
|
+
type: section.type,
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
images: [],
|
|
54
|
+
videos: [],
|
|
55
|
+
image_links: [],
|
|
56
|
+
video_links: [],
|
|
57
|
+
rating: undefined,
|
|
58
|
+
incomplete: true,
|
|
59
|
+
not_applicable: false,
|
|
60
|
+
notes: '',
|
|
61
|
+
responses: createResponsesForFeature(basicFeatureProps),
|
|
62
|
+
|
|
63
|
+
uploaded: false,
|
|
64
|
+
|
|
65
|
+
revision_requested: false,
|
|
66
|
+
revision_requested_update: false,
|
|
67
|
+
edited_by_reviewer: false,
|
|
68
|
+
review_notes: '',
|
|
69
|
+
reviewed_by: undefined,
|
|
70
|
+
reviewed_at: undefined,
|
|
71
|
+
|
|
72
|
+
maintenance_flags: [],
|
|
73
|
+
|
|
74
|
+
created_date: new Date() as unknown as Timestamp,
|
|
75
|
+
updated_date: new Date() as unknown as Timestamp,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const createFeaturesFromSection = (
|
|
79
|
+
inspection: Inspection,
|
|
80
|
+
section: TemplateSection,
|
|
81
|
+
sectionName: string,
|
|
82
|
+
sectionNameWithOrdinal?: string
|
|
83
|
+
): Feature[] => {
|
|
84
|
+
if (!section.features.length) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* If fast track is enabled, we only create one feature for the section
|
|
90
|
+
* with the name of the section as feature name and a predefined description.
|
|
91
|
+
*/
|
|
92
|
+
if (inspection.fast_track) {
|
|
93
|
+
const basicFeatureProps: BasicFeatureProps = {
|
|
94
|
+
name: sectionName,
|
|
95
|
+
description: '',
|
|
96
|
+
is_rating_required: true,
|
|
97
|
+
reference_photos: [],
|
|
98
|
+
number_of_photos_required: 1,
|
|
99
|
+
questions: [],
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
if (section.type === 'room') {
|
|
103
|
+
basicFeatureProps.description =
|
|
104
|
+
`Stand back from each corner to ` +
|
|
105
|
+
`ensure you get photos of the ${sectionName} in its entirety.`;
|
|
106
|
+
} else if (section.type === 'section') {
|
|
107
|
+
basicFeatureProps.description =
|
|
108
|
+
`Take any additional ${sectionName}` +
|
|
109
|
+
` photos that you would like to document.`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return [
|
|
113
|
+
createEmptyFeature(
|
|
114
|
+
inspection,
|
|
115
|
+
basicFeatureProps,
|
|
116
|
+
section,
|
|
117
|
+
sectionName,
|
|
118
|
+
sectionNameWithOrdinal
|
|
119
|
+
),
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* If fast track is not enabled, we create features based on the template
|
|
125
|
+
* features for the section.
|
|
126
|
+
*/
|
|
127
|
+
return section.features.map((tf) =>
|
|
128
|
+
createEmptyFeature(
|
|
129
|
+
inspection,
|
|
130
|
+
tf,
|
|
131
|
+
section,
|
|
132
|
+
sectionName,
|
|
133
|
+
sectionNameWithOrdinal
|
|
134
|
+
)
|
|
135
|
+
);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export const parseTemplateRoomName = (name: string) => {
|
|
139
|
+
if (name === 'Floors') {
|
|
140
|
+
return 'Floor';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (name === 'Full Bathrooms') {
|
|
144
|
+
return 'Full Bathroom';
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (name === 'Half Bathrooms') {
|
|
148
|
+
return 'Half Bathroom';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (name === 'Bedrooms') {
|
|
152
|
+
return 'Bedroom';
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return name;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export const sectionCanExistMultipleTimes = (sectionName: string) =>
|
|
159
|
+
[
|
|
160
|
+
'Bedroom',
|
|
161
|
+
'Bedrooms',
|
|
162
|
+
'Full Bathroom',
|
|
163
|
+
'Full Bathrooms',
|
|
164
|
+
'Half Bathroom',
|
|
165
|
+
'Half Bathrooms',
|
|
166
|
+
'Floor',
|
|
167
|
+
'Floors',
|
|
168
|
+
].includes(sectionName);
|
|
169
|
+
|
|
170
|
+
const addOrdinalToFloorSection = (number: number) => {
|
|
171
|
+
/**
|
|
172
|
+
* America has no concept of a ground floor, so we add 1 to the number
|
|
173
|
+
* to get the correct floor name. /shrug
|
|
174
|
+
*/
|
|
175
|
+
const floor = number + 1;
|
|
176
|
+
|
|
177
|
+
if (floor % 10 === 1) {
|
|
178
|
+
return `${floor}st Floor`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (floor % 10 === 2) {
|
|
182
|
+
return `${floor}nd Floor`;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (floor % 10 === 3) {
|
|
186
|
+
return `${floor}rd Floor`;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return `${floor}th Floor`;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Adds an ordinal to the section to account for repeatable sections.
|
|
194
|
+
*
|
|
195
|
+
* @param sectionName Floor, Bedroom, Full Bathroom, Half Bathroom
|
|
196
|
+
* @param number index of the section, 0 indexed
|
|
197
|
+
* @returns the updated section name, e.g. "First Floor", "Second Bedroom"
|
|
198
|
+
*/
|
|
199
|
+
const addOrdinalToSectionName = (sectionName: string, number: number) => {
|
|
200
|
+
if (sectionName === 'Floor') {
|
|
201
|
+
return addOrdinalToFloorSection(number);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return `${Constants.ordinalPrefixes[number]} ${sectionName}`;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const createFeaturesFromRepeatableSection = (
|
|
208
|
+
sectionName: string,
|
|
209
|
+
section: TemplateSection,
|
|
210
|
+
inspection: Inspection,
|
|
211
|
+
property: Property
|
|
212
|
+
): Feature[] => {
|
|
213
|
+
const sectionCount =
|
|
214
|
+
sectionName === 'Floor'
|
|
215
|
+
? (property as Building).floors
|
|
216
|
+
: inspection.rooms.filter((r) => r === sectionName).length;
|
|
217
|
+
|
|
218
|
+
return new Array(sectionCount)
|
|
219
|
+
.fill(null)
|
|
220
|
+
.map((_, i) =>
|
|
221
|
+
createFeaturesFromSection(
|
|
222
|
+
inspection,
|
|
223
|
+
section,
|
|
224
|
+
sectionName,
|
|
225
|
+
addOrdinalToSectionName(sectionName, i)
|
|
226
|
+
)
|
|
227
|
+
)
|
|
228
|
+
.flat();
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const parseSelectedSectionName = (name: string) => {
|
|
232
|
+
if (/(\d)+(st|nd|rd|th) Floor/.test(name)) {
|
|
233
|
+
return 'Floors';
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (/\w+ Full Bathroom/.test(name)) {
|
|
237
|
+
return 'Full Bathrooms';
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (/\w+ Half Bathroom/.test(name)) {
|
|
241
|
+
return 'Half Bathrooms';
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (/\w+ Bedroom/.test(name)) {
|
|
245
|
+
return 'Bedrooms';
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return name;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const createFeaturesForSpecificFeaturesTemplate = (
|
|
252
|
+
inspection: Inspection,
|
|
253
|
+
inspectionTemplate: InspectionTemplate
|
|
254
|
+
): Feature[] => {
|
|
255
|
+
const features: Feature[] = [];
|
|
256
|
+
|
|
257
|
+
const selectedFeatures = Array.from(inspection.selected_features ?? []);
|
|
258
|
+
|
|
259
|
+
for (const selectedFeature of selectedFeatures) {
|
|
260
|
+
const sectionName = parseSelectedSectionName(selectedFeature.section);
|
|
261
|
+
const section = inspectionTemplate.sections.find(
|
|
262
|
+
(s) => s.name === sectionName
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
if (!section) {
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const selectedFeaturesInSection = section.features.filter(
|
|
270
|
+
(f) => selectedFeature.feature === f.name
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
const limitedSection = { ...section, features: selectedFeaturesInSection };
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* For selected features we create sections in the template regardless of
|
|
277
|
+
* property rooms. We assume all that logic already happened in the backend
|
|
278
|
+
* at the time of inspection creation
|
|
279
|
+
*/
|
|
280
|
+
features.push(
|
|
281
|
+
...createFeaturesFromSection(
|
|
282
|
+
inspection,
|
|
283
|
+
limitedSection,
|
|
284
|
+
section.name,
|
|
285
|
+
selectedFeature.room_name
|
|
286
|
+
)
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return features;
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
const createFeaturesForAllRoomsTemplate = (
|
|
294
|
+
inspection: Inspection,
|
|
295
|
+
inspectionTemplate: InspectionTemplate,
|
|
296
|
+
property: Property
|
|
297
|
+
): Feature[] => {
|
|
298
|
+
const features: Feature[] = [];
|
|
299
|
+
|
|
300
|
+
for (const section of inspectionTemplate.sections) {
|
|
301
|
+
/**
|
|
302
|
+
* We create sections in the template regardless of
|
|
303
|
+
* property rooms.
|
|
304
|
+
*/
|
|
305
|
+
if (section.type === 'section') {
|
|
306
|
+
features.push(
|
|
307
|
+
...createFeaturesFromSection(inspection, section, section.name)
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* For room type sections we first check if the room exists on
|
|
313
|
+
* the property/inspection. If it does we create the features for that room.
|
|
314
|
+
*/
|
|
315
|
+
if (section.type === 'room') {
|
|
316
|
+
/**
|
|
317
|
+
* Some section names use plural nomenclature, while the property rooms
|
|
318
|
+
* are all singular, that's why we first need to change
|
|
319
|
+
*/
|
|
320
|
+
const singularName = parseTemplateRoomName(section.name);
|
|
321
|
+
|
|
322
|
+
if (!inspection.rooms.includes(singularName)) {
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* If this is a section that can be repeated (Bedroom, Bathroom, etc.)
|
|
328
|
+
* we need to create features for each room of that type.
|
|
329
|
+
*/
|
|
330
|
+
if (sectionCanExistMultipleTimes(section.name)) {
|
|
331
|
+
features.push(
|
|
332
|
+
...createFeaturesFromRepeatableSection(
|
|
333
|
+
singularName,
|
|
334
|
+
section,
|
|
335
|
+
inspection,
|
|
336
|
+
property
|
|
337
|
+
)
|
|
338
|
+
);
|
|
339
|
+
} else {
|
|
340
|
+
features.push(
|
|
341
|
+
...createFeaturesFromSection(inspection, section, singularName)
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return features;
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
type BuildTemplateFeaturesParams = {
|
|
351
|
+
inspection: Inspection;
|
|
352
|
+
property: Property;
|
|
353
|
+
inspectionTemplate: InspectionTemplate;
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
export const buildTemplateFeatures = async ({
|
|
357
|
+
inspection,
|
|
358
|
+
property,
|
|
359
|
+
inspectionTemplate,
|
|
360
|
+
}: BuildTemplateFeaturesParams): Promise<Feature[]> => {
|
|
361
|
+
const features: Feature[] = [];
|
|
362
|
+
|
|
363
|
+
if (!property) {
|
|
364
|
+
return [];
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (inspectionTemplate.template_type === 'all-rooms') {
|
|
368
|
+
features.push(
|
|
369
|
+
...createFeaturesForAllRoomsTemplate(
|
|
370
|
+
inspection,
|
|
371
|
+
inspectionTemplate,
|
|
372
|
+
property
|
|
373
|
+
)
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (inspectionTemplate.template_type === 'specific-features') {
|
|
378
|
+
features.push(
|
|
379
|
+
...createFeaturesForSpecificFeaturesTemplate(
|
|
380
|
+
inspection,
|
|
381
|
+
inspectionTemplate
|
|
382
|
+
)
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return features;
|
|
387
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as Constants from './constants';
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// target options
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"target": "es6",
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"allowSyntheticDefaultImports": true,
|
|
9
|
+
|
|
10
|
+
// typeorm
|
|
11
|
+
"emitDecoratorMetadata": true,
|
|
12
|
+
"experimentalDecorators": true,
|
|
13
|
+
"sourceMap": true,
|
|
14
|
+
|
|
15
|
+
// directories
|
|
16
|
+
"rootDir": "src",
|
|
17
|
+
"outDir": "dist",
|
|
18
|
+
|
|
19
|
+
// workspace
|
|
20
|
+
"declaration": true,
|
|
21
|
+
"composite": true
|
|
22
|
+
|
|
23
|
+
// other options
|
|
24
|
+
},
|
|
25
|
+
"include": ["src/**/*"],
|
|
26
|
+
"exclude": ["node_modules"]
|
|
27
|
+
}
|