@servicetitan/acquisition-functions 0.1.0 → 0.2.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/README.md CHANGED
@@ -33,9 +33,5 @@ npm run test
33
33
  In Docker:
34
34
 
35
35
  ```sh
36
- # In root FE directory
37
- lerna run build --scope=@servicetitan/acquisition-functions
38
-
39
- # In package directory
40
- docker-compose up
36
+ docker-compose up --from-exit-code=tests
41
37
  ```
@@ -6,6 +6,7 @@ const setup_1 = require("./setup");
6
6
  describe('property-assessorlastsaledate-converter', () => {
7
7
  let processor;
8
8
  let base;
9
+ let metadata;
9
10
  (0, globals_1.beforeAll)(async () => {
10
11
  const client = await (0, setup_1.openConnection)();
11
12
  base = client.db('test');
@@ -18,7 +19,7 @@ describe('property-assessorlastsaledate-converter', () => {
18
19
  mongoDb: base,
19
20
  });
20
21
  const { assessorLastSaleDateProcessor } = processor;
21
- await assessorLastSaleDateProcessor.start('90001');
22
+ metadata = await assessorLastSaleDateProcessor.start('90001');
22
23
  });
23
24
  (0, globals_1.test)('should convert existing field to date', async () => {
24
25
  const result = await new Promise(resolve => {
@@ -46,6 +47,11 @@ describe('property-assessorlastsaledate-converter', () => {
46
47
  });
47
48
  (0, globals_1.expect)(result[0].assessorlastsaledate).toBe(null);
48
49
  });
50
+ (0, globals_1.test)('should return metadata', async () => {
51
+ (0, globals_1.expect)(metadata.errors).toBe(0);
52
+ (0, globals_1.expect)(metadata.properties).toBe(1);
53
+ (0, globals_1.expect)(metadata.requests).toBe(2);
54
+ });
49
55
  });
50
56
  describe('aggregate', () => {
51
57
  (0, globals_1.beforeEach)(async () => {
@@ -6,6 +6,7 @@ const setup_1 = require("./setup");
6
6
  describe('property-assessorlastsaledate-converter', () => {
7
7
  let processor;
8
8
  let base;
9
+ let metadata;
9
10
  (0, globals_1.beforeAll)(async () => {
10
11
  const client = await (0, setup_1.openConnection)();
11
12
  base = client.db('test');
@@ -16,7 +17,7 @@ describe('property-assessorlastsaledate-converter', () => {
16
17
  });
17
18
  const { filterFetcher, propertyUseGroupProcessor } = processor;
18
19
  await propertyUseGroupProcessor.start('90001');
19
- await filterFetcher.start('90001-90002');
20
+ metadata = await filterFetcher.start(['90001', '90002']);
20
21
  });
21
22
  (0, globals_1.test)('should have empty filter for missing zip', async () => {
22
23
  const result = await base.collection('filters').findOne({
@@ -30,6 +31,12 @@ describe('property-assessorlastsaledate-converter', () => {
30
31
  (0, globals_1.expect)(result?.propertyusestandardized.length).toBe(0);
31
32
  (0, globals_1.expect)(result?.utilitieswatersource.length).toBe(0);
32
33
  });
34
+ (0, globals_1.test)('should return metadata', async () => {
35
+ (0, globals_1.expect)(metadata.errors).toBe(0);
36
+ (0, globals_1.expect)(metadata.properties).toBe(2);
37
+ (0, globals_1.expect)(metadata.requests).toBe(6);
38
+ (0, globals_1.expect)(metadata.filters).toBe(2);
39
+ });
33
40
  (0, globals_1.test)('should form correct filter', async () => {
34
41
  const result = await base.collection('filters').findOne({
35
42
  zipcode: '90001',
@@ -11,6 +11,7 @@ describe('property-use-group-converter', () => {
11
11
  });
12
12
  describe('processor', () => {
13
13
  let processor;
14
+ let metadata;
14
15
  (0, globals_1.beforeAll)(async () => {
15
16
  await (0, setup_1.setupProperties)(base);
16
17
  processor = (0, index_1.configureProcessor)({
@@ -18,7 +19,12 @@ describe('property-use-group-converter', () => {
18
19
  mongoDb: base,
19
20
  });
20
21
  const { propertyUseGroupProcessor } = processor;
21
- await propertyUseGroupProcessor.start('90001-90002');
22
+ metadata = await propertyUseGroupProcessor.start('90001');
23
+ });
24
+ (0, globals_1.test)('should return metadata', async () => {
25
+ (0, globals_1.expect)(metadata.errors).toBe(0);
26
+ (0, globals_1.expect)(metadata.properties).toBe(2);
27
+ (0, globals_1.expect)(metadata.requests).toBe(2);
22
28
  });
23
29
  (0, globals_1.test)('should convert existing field to captial-case', async () => {
24
30
  const result = await new Promise(resolve => {
@@ -10,6 +10,12 @@ async function setupProperties(base) {
10
10
  catch (e) {
11
11
  // ignore
12
12
  }
13
+ try {
14
+ await base.dropCollection('filters');
15
+ }
16
+ catch (e) {
17
+ // ignore
18
+ }
13
19
  try {
14
20
  await base.createCollection('properties');
15
21
  await base.collection('properties').insertMany(mock_1.MOCK);
@@ -11,74 +11,67 @@ function getFilterFetcherProcessor(db) {
11
11
  };
12
12
  const getProperties = async (zip) => {
13
13
  const collection = await getPropertiesCollection();
14
- return new Promise((resolve, reject) => {
15
- collection
16
- .find({ zipcode: zip }, {
17
- projection: {
18
- zipcode: 1,
19
- propertyusegroup: 1,
20
- propertyusestandardized: 1,
21
- hvaccoolingdetail: 1,
22
- hvacheatingdetail: 1,
23
- utilitieswatersource: 1,
24
- flooringmaterialprimary: 1,
25
- _id: 0, // eslint-disable-line
26
- },
27
- })
28
- .toArray((err, results) => {
29
- if (err) {
30
- return reject(err);
31
- }
32
- resolve(results);
33
- });
34
- });
14
+ return collection
15
+ .find({ zipcode: zip }, {
16
+ projection: {
17
+ zipcode: 1,
18
+ propertyusegroup: 1,
19
+ propertyusestandardized: 1,
20
+ hvaccoolingdetail: 1,
21
+ hvacheatingdetail: 1,
22
+ utilitieswatersource: 1,
23
+ flooringmaterialprimary: 1,
24
+ _id: 0, // eslint-disable-line
25
+ },
26
+ })
27
+ .toArray();
35
28
  };
36
29
  const deleteZipFilter = async (zip) => {
37
30
  const collection = await getFiltersCollection();
38
- return new Promise((resolve, reject) => {
39
- collection.deleteOne({ zipcode: zip }, (err, results) => {
40
- if (err) {
41
- return reject(err);
42
- }
43
- resolve(results);
44
- });
45
- });
31
+ return collection.deleteOne({ zipcode: zip });
46
32
  };
47
33
  const addZipFilters = async ({ zip, propertyusegroupCounts, propertyusestandardizedCounts, hvaccoolingdetailCounts, hvacheatingdetailCounts, utilitieswatersourceCounts, flooringmaterialprimaryCounts, }) => {
48
34
  const collection = await getFiltersCollection();
49
- return new Promise((resolve, reject) => {
50
- collection.insertOne({
51
- zipcode: zip,
52
- propertyusegroup: propertyusegroupCounts,
53
- propertyusestandardized: propertyusestandardizedCounts,
54
- hvaccoolingdetail: hvaccoolingdetailCounts,
55
- hvacheatingdetail: hvacheatingdetailCounts,
56
- utilitieswatersource: utilitieswatersourceCounts,
57
- flooringmaterialprimary: flooringmaterialprimaryCounts,
58
- }, (err, results) => {
59
- if (err) {
60
- return reject(err);
61
- }
62
- resolve(results);
63
- });
35
+ return collection.insertOne({
36
+ zipcode: zip,
37
+ propertyusegroup: propertyusegroupCounts,
38
+ propertyusestandardized: propertyusestandardizedCounts,
39
+ hvaccoolingdetail: hvaccoolingdetailCounts,
40
+ hvacheatingdetail: hvacheatingdetailCounts,
41
+ utilitieswatersource: utilitieswatersourceCounts,
42
+ flooringmaterialprimary: flooringmaterialprimaryCounts,
64
43
  });
65
44
  };
66
45
  return async function processZip(zip, errors) {
46
+ const meta = {
47
+ requests: 0,
48
+ errors: 0,
49
+ properties: 0,
50
+ filters: 0,
51
+ };
67
52
  if (!zip) {
68
- return;
53
+ return meta;
69
54
  }
70
55
  try {
71
56
  const properties = await getProperties(zip);
57
+ meta.requests += 1;
58
+ meta.properties += properties.length;
72
59
  const filters = (0, calc_filter_count_1.calculateFilterCount)(properties);
73
60
  await deleteZipFilter(zip);
61
+ meta.requests += 1;
74
62
  await addZipFilters({
75
63
  zip,
76
64
  ...filters,
77
65
  });
66
+ meta.filters += 1;
67
+ meta.requests += 1;
78
68
  }
79
69
  catch (e) {
70
+ console.error(e);
80
71
  errors.add(zip);
72
+ meta.errors += 1;
81
73
  }
74
+ return meta;
82
75
  };
83
76
  }
84
77
  exports.getFilterFetcherProcessor = getFilterFetcherProcessor;
@@ -11,20 +11,13 @@ function fixPropertyName(propertyName) {
11
11
  function getPropertyUseGroupProcessor(db) {
12
12
  const getProperties = async (zip) => {
13
13
  const collection = await getPropertiesCollection(db);
14
- return new Promise((resolve, reject) => {
15
- collection
16
- .find({ zipcode: zip }, {
17
- projection: {
18
- propertyusegroup: 1,
19
- },
20
- })
21
- .toArray((err, results) => {
22
- if (err) {
23
- return reject(err);
24
- }
25
- resolve(results);
26
- });
27
- });
14
+ return collection
15
+ .find({ zipcode: zip }, {
16
+ projection: {
17
+ propertyusegroup: 1,
18
+ },
19
+ })
20
+ .toArray();
28
21
  };
29
22
  function fixPropertyNames(properties) {
30
23
  return properties
@@ -50,23 +43,34 @@ function getPropertyUseGroupProcessor(db) {
50
43
  return collection.bulkWrite(propQuery, { ordered: true, w: 1 });
51
44
  };
52
45
  return async function processZip(zip, errors) {
46
+ const meta = {
47
+ requests: 0,
48
+ errors: 0,
49
+ properties: 0,
50
+ };
53
51
  if (!zip) {
54
- return;
52
+ return meta;
55
53
  }
56
54
  try {
57
55
  const properties = await getProperties(zip);
56
+ meta.requests += 1;
58
57
  if (!properties || !properties.length) {
59
- return;
58
+ return meta;
60
59
  }
61
60
  const convertedProperties = fixPropertyNames(properties);
62
61
  if (!convertedProperties.length) {
63
- return;
62
+ return meta;
64
63
  }
65
64
  await updateProperties(convertedProperties);
65
+ meta.properties += convertedProperties.length;
66
+ meta.requests += 1;
66
67
  }
67
68
  catch (e) {
69
+ console.error(e);
68
70
  errors.add(zip);
71
+ meta.errors += 1;
69
72
  }
73
+ return meta;
70
74
  };
71
75
  }
72
76
  exports.getPropertyUseGroupProcessor = getPropertyUseGroupProcessor;
@@ -8,26 +8,19 @@ const getPropertiesCollection = async (db) => {
8
8
  function getAssessorLastSaleDateProcessor(db) {
9
9
  const getPropertiesAssessorLastSaleDate = async (zip) => {
10
10
  const collection = await getPropertiesCollection(db);
11
- return new Promise((resolve, reject) => {
12
- collection
13
- .find({
14
- zipcode: zip,
15
- assessorlastsaledate: {
16
- $exists: true,
17
- $type: 2,
18
- },
19
- }, {
20
- projection: {
21
- assessorlastsaledate: 1,
22
- },
23
- })
24
- .toArray((err, results) => {
25
- if (err) {
26
- return reject(err);
27
- }
28
- resolve(results);
29
- });
30
- });
11
+ return collection
12
+ .find({
13
+ zipcode: zip,
14
+ assessorlastsaledate: {
15
+ $exists: true,
16
+ $type: 2,
17
+ },
18
+ }, {
19
+ projection: {
20
+ assessorlastsaledate: 1,
21
+ },
22
+ })
23
+ .toArray();
31
24
  };
32
25
  const updateProperties = async (properties) => {
33
26
  const collection = await getPropertiesCollection(db);
@@ -41,23 +34,34 @@ function getAssessorLastSaleDateProcessor(db) {
41
34
  return collection.bulkWrite(propQuery, { ordered: true, w: 1 });
42
35
  };
43
36
  return async function processZip(zip, errors) {
37
+ const meta = {
38
+ requests: 0,
39
+ errors: 0,
40
+ properties: 0,
41
+ };
44
42
  if (!zip) {
45
- return;
43
+ return meta;
46
44
  }
47
45
  try {
48
46
  const properties = await getPropertiesAssessorLastSaleDate(zip);
47
+ meta.requests += 1;
49
48
  if (!properties || !properties.length) {
50
- return;
49
+ return meta;
51
50
  }
52
51
  const convertedProperties = (0, utils_1.convertStringToDate)(properties, 'assessorlastsaledate');
53
52
  if (!convertedProperties.length) {
54
- return;
53
+ return meta;
55
54
  }
56
55
  await updateProperties(convertedProperties);
56
+ meta.properties += convertedProperties.length;
57
+ meta.requests += 1;
57
58
  }
58
59
  catch (e) {
60
+ console.error(e);
61
+ meta.errors += 1;
59
62
  errors.add(zip);
60
63
  }
64
+ return meta;
61
65
  };
62
66
  }
63
67
  exports.getAssessorLastSaleDateProcessor = getAssessorLastSaleDateProcessor;
@@ -10,19 +10,25 @@ function zipProcessor(config, processorFn) {
10
10
  if (!zips) {
11
11
  return;
12
12
  }
13
- // eslint-disable-next-line prefer-const
14
- let [startZipNum, endZipNum] = zips.split('-').map(Number);
15
- if (!endZipNum) {
16
- endZipNum = startZipNum;
17
- }
18
- for (let zipNum = startZipNum; zipNum <= endZipNum;) {
19
- const processes = [];
20
- const processZipEnd = zipNum + config.workers - 1;
21
- for (; zipNum <= endZipNum && zipNum <= processZipEnd; zipNum++) {
22
- const zip = (0, utils_1.convertToZipString)(zipNum);
23
- processes.push(processorFn(zip, erroredZips));
13
+ if (Array.isArray(zips)) {
14
+ // eslint-disable-next-line prefer-const
15
+ let [startZipNum, endZipNum] = zips.map(Number);
16
+ if (!endZipNum) {
17
+ endZipNum = startZipNum;
24
18
  }
25
- yield await Promise.all(processes);
19
+ for (let zipNum = startZipNum; zipNum <= endZipNum;) {
20
+ const processes = [];
21
+ const processZipEnd = zipNum + config.workers - 1;
22
+ for (; zipNum <= endZipNum && zipNum <= processZipEnd; zipNum++) {
23
+ const zip = (0, utils_1.convertToZipString)(zipNum);
24
+ processes.push(processorFn(zip, erroredZips));
25
+ }
26
+ yield await Promise.all(processes);
27
+ }
28
+ }
29
+ else {
30
+ const zip = (0, utils_1.convertToZipString)(Number(zips));
31
+ yield await processorFn(zip, erroredZips);
26
32
  }
27
33
  while (erroredZips.size) {
28
34
  const connectionErrorZipsInner = [...erroredZips];
@@ -39,17 +45,39 @@ function zipProcessor(config, processorFn) {
39
45
  }
40
46
  processor = null;
41
47
  }
48
+ const meta = {
49
+ requests: 0,
50
+ properties: 0,
51
+ errors: 0,
52
+ filters: 0,
53
+ };
54
+ function sumMetas(metas) {
55
+ if (!metas) {
56
+ return;
57
+ }
58
+ return (Array.isArray(metas) ? metas : [metas]).forEach(m => {
59
+ meta.requests += m.requests;
60
+ meta.properties += m.properties;
61
+ meta.errors += m.errors;
62
+ if (m.filters) {
63
+ meta.filters += m.filters;
64
+ }
65
+ });
66
+ }
42
67
  async function start(zips) {
43
68
  processor = processZips(zips);
44
69
  try {
45
- let step = await processor.next();
46
- while (processor && !step.done) {
47
- step = await processor.next();
70
+ let isDone = false;
71
+ while (processor && !isDone) {
72
+ const step = await processor.next();
73
+ sumMetas(step.value);
74
+ isDone = Boolean(step.done);
48
75
  }
49
76
  }
50
77
  catch (e) {
51
78
  await clear();
52
79
  }
80
+ return meta;
53
81
  }
54
82
  return {
55
83
  getProcessor: () => processor,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/acquisition-functions",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "typings": "./dist/index.d.ts",
@@ -28,5 +28,5 @@
28
28
  "cli": {
29
29
  "webpack": false
30
30
  },
31
- "gitHead": "30de32ace907277b336c7bc835e659b2a3ffaac9"
31
+ "gitHead": "7c93d00316dcd4bd83e1a42720579ed22c6ce208"
32
32
  }