From 20e323621196c1faa5a59dd39e3dd51df7a6a50f Mon Sep 17 00:00:00 2001 From: Mike Keen Date: Wed, 12 Jan 2022 02:02:09 -0500 Subject: [PATCH 1/4] feat: fts params for units --- migrations/20211212200953-fulltext-search.cjs | 6 +- .../20211219184405-sqlite-triggers-units.cjs | 32 ++++- src/controllers/units.controller.js | 37 +++-- src/models/units/units.model.js | 126 +++++++++++++++++- 4 files changed, 179 insertions(+), 22 deletions(-) diff --git a/migrations/20211212200953-fulltext-search.cjs b/migrations/20211212200953-fulltext-search.cjs index 6bd98c10..f421eb5c 100644 --- a/migrations/20211212200953-fulltext-search.cjs +++ b/migrations/20211212200953-fulltext-search.cjs @@ -34,18 +34,22 @@ module.exports = { await queryInterface.sequelize.query(` CREATE VIRTUAL TABLE units_fts USING fts5( warehouseUnitId, + orgUid, + unitOwnerOrgUid, countryJuridictionOfOwner, + inCountryJuridictionOfOwner, serialNumberBlock, unitIdentifier, unitType, + intendedBuyerOrgUid, marketplace, tags, - inCountryJuridictionOfOwner, unitStatus, unitTransactionType, unitStatusReason, tokenIssuanceHash, marketplaceIdentifier, + unitsIssuanceLocation, unitRegistryLink, unitMarketplaceLink, cooresponingAdjustmentDeclaration, diff --git a/migrations/20211219184405-sqlite-triggers-units.cjs b/migrations/20211219184405-sqlite-triggers-units.cjs index 4cc0d6c4..8d67f93d 100644 --- a/migrations/20211219184405-sqlite-triggers-units.cjs +++ b/migrations/20211219184405-sqlite-triggers-units.cjs @@ -7,36 +7,44 @@ module.exports = { CREATE TRIGGER unit_insert_fts AFTER INSERT ON units BEGIN INSERT INTO units_fts( warehouseUnitId, + orgUid, + unitOwnerOrgUid, countryJuridictionOfOwner, + inCountryJuridictionOfOwner, serialNumberBlock, unitIdentifier, unitType, + intendedBuyerOrgUid, marketplace, tags, - inCountryJuridictionOfOwner, unitStatus, unitTransactionType, unitStatusReason, tokenIssuanceHash, marketplaceIdentifier, + unitsIssuanceLocation, unitRegistryLink, unitMarketplaceLink, cooresponingAdjustmentDeclaration, correspondingAdjustmentStatus ) VALUES ( new.warehouseUnitId, + new.orgUid, + new.unitOwnerOrgUid, new.countryJuridictionOfOwner, + new.inCountryJuridictionOfOwner, new.serialNumberBlock, new.unitIdentifier, new.unitType, + new.intendedBuyerOrgUid, new.marketplace, new.tags, - new.inCountryJuridictionOfOwner, new.unitStatus, new.unitTransactionType, new.unitStatusReason, new.tokenIssuanceHash, new.marketplaceIdentifier, + new.unitsIssuanceLocation, new.unitRegistryLink, new.unitMarketplaceLink, new.cooresponingAdjustmentDeclaration, @@ -55,40 +63,52 @@ module.exports = { DELETE FROM units_fts WHERE warehouseUnitId = old.warehouseUnitId; INSERT INTO units_fts( warehouseUnitId, + orgUid, + unitOwnerOrgUid, countryJuridictionOfOwner, + inCountryJuridictionOfOwner, serialNumberBlock, unitIdentifier, unitType, + intendedBuyerOrgUid, marketplace, tags, - inCountryJuridictionOfOwner, unitStatus, unitTransactionType, unitStatusReason, tokenIssuanceHash, marketplaceIdentifier, + unitsIssuanceLocation, unitRegistryLink, unitMarketplaceLink, cooresponingAdjustmentDeclaration, - correspondingAdjustmentStatus + correspondingAdjustmentStatus, + createdAt, + updatedAt ) VALUES ( new.warehouseUnitId, + new.orgUid, + new.unitOwnerOrgUid, new.countryJuridictionOfOwner, + new.inCountryJuridictionOfOwner, new.serialNumberBlock, new.unitIdentifier, new.unitType, + new.intendedBuyerOrgUid, new.marketplace, new.tags, - new.inCountryJuridictionOfOwner, new.unitStatus, new.unitTransactionType, new.unitStatusReason, new.tokenIssuanceHash, new.marketplaceIdentifier, + new.unitsIssuanceLocation, new.unitRegistryLink, new.unitMarketplaceLink, new.cooresponingAdjustmentDeclaration, - new.correspondingAdjustmentStatus + new.correspondingAdjustmentStatus, + new.createdAt, + new.updatedAt ); END; `); diff --git a/src/controllers/units.controller.js b/src/controllers/units.controller.js index 22f3fe18..7cf7314c 100644 --- a/src/controllers/units.controller.js +++ b/src/controllers/units.controller.js @@ -56,7 +56,7 @@ export const create = async (req, res, next) => { }; export const findAll = async (req, res) => { - let { page, limit, columns, orgUid } = req.query; + let { page, limit, columns, orgUid, search } = req.query; let where = orgUid ? { orgUid } : undefined; const includes = [Qualification]; @@ -76,19 +76,28 @@ export const findAll = async (req, res) => { if (!columns.length) { columns = ['warehouseUnitId']; } - - res.json( - optionallyPaginatedResponse( - await Unit.findAndCountAll({ - where, - distinct: true, - ...columnsToInclude(columns, includes), - ...paginationParams(page, limit), - }), - page, - limit, - ), - ); + + let results; + + if (search) { + results = await Unit.fts( + search, + orgUid, + paginationParams(page, limit), + columns, + ); + } + + if (!results) { + results = await Unit.findAndCountAll({ + where, + distinct: true, + ...columnsToInclude(columns, includes), + ...paginationParams(page, limit), + }); + } + + res.json(optionallyPaginatedResponse(results, page, limit)); }; export const findOne = async (req, res) => { diff --git a/src/models/units/units.model.js b/src/models/units/units.model.js index 1ee75024..c37cd905 100644 --- a/src/models/units/units.model.js +++ b/src/models/units/units.model.js @@ -2,7 +2,7 @@ import Sequelize from 'sequelize'; import { sequelize } from '../database'; -import { Qualification, Vintage } from '../../models'; +import {CoBenefit, ProjectLocation, Qualification, RelatedProject, Vintage} from '../../models'; import ModelTypes from './units.modeltypes.cjs'; import rxjs from 'rxjs'; @@ -71,6 +71,130 @@ class Unit extends Model { return super.destroy(values); } + + static async fts(searchStr, orgUid, pagination, columns = []) { + const dialect = sequelize.getDialect(); + + const handlerMap = { + sqlite: Unit.findAllSqliteFts, + mysql: Unit.findAllMySQLFts, + }; + + return handlerMap[dialect]( + searchStr, + orgUid, + pagination, + columns + .filter((col) => ![ + 'createdAt', + 'updatedAt', + 'unitBlockStart', + 'unitBlockEnd', + 'unitCount'].includes(col)) + ); + } + + static async findAllMySQLFts(searchStr, orgUid, pagination, columns = []) { + const { offset, limit } = pagination; + + let fields = '*'; + if (columns.length) { + fields = columns.join(', '); + } + + let sql = ` + SELECT ${fields} FROM units WHERE MATCH ( + unitOwnerOrgUid, + countryJuridictionOfOwner, + inCountryJuridictionOfOwner, + serialNumberBlock, + unitIdentifier, + unitType, + intendedBuyerOrgUid, + marketplace, + tags, + unitStatus, + unitTransactionType, + unitStatusReason, + tokenIssuanceHash, + marketplaceIdentifier, + unitsIssuanceLocation, + unitRegistryLink, + unitMarketplaceLink, + cooresponingAdjustmentDeclaration, + correspondingAdjustmentStatus + ) AGAINST ":search" + `; + + if (orgUid) { + sql = `${sql} AND orgUid = :orgUid`; + } + + const replacements = { search: searchStr, orgUid }; + + const count = ( + await sequelize.query(sql, { + model: Unit, + mapToModel: true, // pass true here if you have any mapped fields + replacements, + }) + ).length; + + if (limit && offset) { + sql = `${sql} ORDER BY relevance DESC LIMIT :limit OFFSET :offset`; + } + + return { + count, + rows: await sequelize.query(sql, { + model: Unit, + replacements: { ...replacements, ...{ offset, limit } }, + mapToModel: true, // pass true here if you have any mapped fields + offset, + limit, + }), + }; + } + + static async findAllSqliteFts(searchStr, orgUid, pagination, columns = []) { + const { offset, limit } = pagination; + + let fields = '*'; + if (columns.length) { + fields = columns.join(', '); + } + + searchStr = searchStr = searchStr.replaceAll('-', '+'); + + let sql = `SELECT ${fields} FROM units_fts WHERE units_fts MATCH :search`; + + if (orgUid) { + sql = `${sql} AND orgUid = :orgUid`; + } + + const replacements = { search: `${searchStr}*`, orgUid }; + + const count = ( + await sequelize.query(sql, { + model: Unit, + mapToModel: true, // pass true here if you have any mapped fields + replacements, + }) + ).length; + + if (limit && offset) { + sql = `${sql} ORDER BY rank DESC LIMIT :limit OFFSET :offset`; + } + + return { + count, + rows: await sequelize.query(sql, { + model: Unit, + mapToModel: true, // pass true here if you have any mapped fields + replacements: { ...replacements, ...{ offset, limit } }, + }), + }; + } } Unit.init(Object.assign({}, ModelTypes, virtualColumns), { From 8cee623fea3e21e2e1364b036cd696af106ad65a Mon Sep 17 00:00:00 2001 From: Mike Keen Date: Wed, 12 Jan 2022 20:34:44 -0500 Subject: [PATCH 2/4] fix: model updates --- migrations/20211212200953-fulltext-search.cjs | 4 +- .../20211219184405-sqlite-triggers-units.cjs | 16 +++---- src/models/units/units.model.js | 4 +- src/models/units/units.modeltypes.cjs | 4 +- src/models/units/units.stub.json | 20 ++++----- src/validations/units.validations.js | 4 +- tests/integration/unit.spec.js | 44 +++++++++---------- 7 files changed, 48 insertions(+), 48 deletions(-) diff --git a/migrations/20211212200953-fulltext-search.cjs b/migrations/20211212200953-fulltext-search.cjs index e3dd5a70..42361ef3 100644 --- a/migrations/20211212200953-fulltext-search.cjs +++ b/migrations/20211212200953-fulltext-search.cjs @@ -36,8 +36,8 @@ module.exports = { warehouseUnitId, orgUid, unitOwnerOrgUid, - countryJuridictionOfOwner, - inCountryJuridictionOfOwner, + countryJurisdictionOfOwner, + inCountryJurisdictionOfOwner, serialNumberBlock, unitIdentifier, unitType, diff --git a/migrations/20211219184405-sqlite-triggers-units.cjs b/migrations/20211219184405-sqlite-triggers-units.cjs index 824ff7fa..e2b98604 100644 --- a/migrations/20211219184405-sqlite-triggers-units.cjs +++ b/migrations/20211219184405-sqlite-triggers-units.cjs @@ -9,8 +9,8 @@ module.exports = { warehouseUnitId, orgUid, unitOwnerOrgUid, - countryJuridictionOfOwner, - inCountryJuridictionOfOwner, + countryJurisdictionOfOwner, + inCountryJurisdictionOfOwner, serialNumberBlock, unitIdentifier, unitType, @@ -31,8 +31,8 @@ module.exports = { new.warehouseUnitId, new.orgUid, new.unitOwnerOrgUid, - new.countryJuridictionOfOwner, - new.inCountryJuridictionOfOwner, + new.countryJurisdictionOfOwner, + new.inCountryJurisdictionOfOwner, new.serialNumberBlock, new.unitIdentifier, new.unitType, @@ -65,8 +65,8 @@ module.exports = { warehouseUnitId, orgUid, unitOwnerOrgUid, - countryJuridictionOfOwner, - inCountryJuridictionOfOwner, + countryJurisdictionOfOwner, + inCountryJurisdictionOfOwner, serialNumberBlock, unitIdentifier, unitType, @@ -87,8 +87,8 @@ module.exports = { new.warehouseUnitId, new.orgUid, new.unitOwnerOrgUid, - new.countryJuridictionOfOwner, - new.inCountryJuridictionOfOwner, + new.countryJurisdictionOfOwner, + new.inCountryJurisdictionOfOwner, new.serialNumberBlock, new.unitIdentifier, new.unitType, diff --git a/src/models/units/units.model.js b/src/models/units/units.model.js index 85e29d19..6225b04b 100644 --- a/src/models/units/units.model.js +++ b/src/models/units/units.model.js @@ -120,8 +120,8 @@ class Unit extends Model { let sql = ` SELECT ${fields} FROM units WHERE MATCH ( unitOwnerOrgUid, - countryJuridictionOfOwner, - inCountryJuridictionOfOwner, + countryJurisdictionOfOwner, + inCountryJurisdictionOfOwner, serialNumberBlock, unitIdentifier, unitType, diff --git a/src/models/units/units.modeltypes.cjs b/src/models/units/units.modeltypes.cjs index 420153e0..ff28d0bd 100644 --- a/src/models/units/units.modeltypes.cjs +++ b/src/models/units/units.modeltypes.cjs @@ -12,8 +12,8 @@ module.exports = { // organizations tables on the datalayer orgUid: Sequelize.STRING, unitOwnerOrgUid: Sequelize.STRING, - countryJuridictionOfOwner: Sequelize.STRING, - inCountryJuridictionOfOwner: Sequelize.STRING, + countryJurisdictionOfOwner: Sequelize.STRING, + inCountryJurisdictionOfOwner: Sequelize.STRING, serialNumberBlock: Sequelize.STRING, unitIdentifier: Sequelize.STRING, unitType: Sequelize.STRING, diff --git a/src/models/units/units.stub.json b/src/models/units/units.stub.json index 44cf7fa3..bd635b2e 100644 --- a/src/models/units/units.stub.json +++ b/src/models/units/units.stub.json @@ -3,14 +3,14 @@ "warehouseUnitId": "5c960ac1-a180-45a4-9850-be177e26d2fb", "orgUid": "f1c54511-865e-4611-976c-7c3c1f704662", "unitOwnerOrgUid": "f1c54511-865e-4611-976c-7c3c1f704662", - "countryJuridictionOfOwner": "USA", + "countryJurisdictionOfOwner": "USA", "serialNumberBlock": "AXJJFSLGHSHEJ1000-AXJJFSLGHSHEJ1010", "unitIdentifier": "XYZ", "unitType": "heard reduction", "intendedBuyerOrgUid": "70150fde-57f6-44a6-9486-1fef49528475", "marketplace": "Demo Marketplace", "tags": "Demo, Wind Energy", - "inCountryJuridictionOfOwner": "Maryland", + "inCountryJurisdictionOfOwner": "Maryland", "unitStatus": "Held", "unitTransactionType": "TRANSACTION_TYPE", "unitStatusReason": "Retired Status", @@ -25,14 +25,14 @@ "warehouseUnitId": "50aa22fe-20c4-4af9-a9e9-8472e73a9222", "orgUid": "f1c54511-865e-4611-976c-7c3c1f704662", "unitOwnerOrgUid": "f1c54511-865e-4611-976c-7c3c1f704662", - "countryJuridictionOfOwner": "USA", + "countryJurisdictionOfOwner": "USA", "serialNumberBlock": "AXJJFSLGHSHEJ2000-AXJJFSLGHSHEJ2010", "unitIdentifier": "XYZ", "unitType": "heard reduction", "intendedBuyerOrgUid": "70150fde-57f6-44a6-9486-1fef49528475", "marketplace": "Demo Marketplace", "tags": "Demo, Wind Energy", - "inCountryJuridictionOfOwner": "Maryland", + "inCountryJurisdictionOfOwner": "Maryland", "unitStatus": "Held", "unitTransactionType": "TRANSACTION_TYPE", "unitStatusReason": "Retired Status", @@ -47,14 +47,14 @@ "warehouseUnitId": "7703e6be-1781-4322-9a9c-502ca0dca29b", "orgUid": "35f92331-c8d7-4e9e-a8d2-cd0a86cbb2cf", "unitOwnerOrgUid": "f1c54511-865e-4611-976c-7c3c1f704662", - "countryJuridictionOfOwner": "USA", + "countryJurisdictionOfOwner": "USA", "serialNumberBlock": "AXJJFSLGHSHEJ3000-AXJJFSLGHSHEJ3010", "unitIdentifier": "XYZ", "unitType": "heard reduction", "intendedBuyerOrgUid": "70150fde-57f6-44a6-9486-1fef49528475", "marketplace": "Demo Marketplace", "tags": "Demo, Wind Energy", - "inCountryJuridictionOfOwner": "Maryland", + "inCountryJurisdictionOfOwner": "Maryland", "unitStatus": "Held", "unitTransactionType": "TRANSACTION_TYPE", "unitStatusReason": "Retired Status", @@ -69,14 +69,14 @@ "warehouseUnitId": "04582672-47a9-411b-896f-3d45974e360e", "orgUid": "f1c54511-865e-4611-976c-7c3c1f704662", "unitOwnerOrgUid": "f1c54511-865e-4611-976c-7c3c1f704662", - "countryJuridictionOfOwner": "USA", + "countryJurisdictionOfOwner": "USA", "serialNumberBlock": "AXJJFSLGHSHEJ4000-AXJJFSLGHSHEJ4010", "unitIdentifier": "XYZ", "unitType": "heard reduction", "intendedBuyerOrgUid": "70150fde-57f6-44a6-9486-1fef49528475", "marketplace": "Demo Marketplace", "tags": "Demo, Wind Energy", - "inCountryJuridictionOfOwner": "Maryland", + "inCountryJurisdictionOfOwner": "Maryland", "unitStatus": "Held", "unitTransactionType": "TRANSACTION_TYPE", "unitStatusReason": "Retired Status", @@ -94,8 +94,8 @@ "serialNumberBlock": "AXJJFSLGHSHEJ5000-AXJJFSLGHSHEJ5010", "unitIdentifier": "XYZ", "unitType": "heard reduction", - "countryJuridictionOfOwner": "USA", - "inCountryJuridictionOfOwner": "Maryland", + "countryJurisdictionOfOwner": "USA", + "inCountryJurisdictionOfOwner": "Maryland", "intendedBuyerOrgUid": "70150fde-57f6-44a6-9486-1fef49528475", "marketplace": "Demo Marketplace", "tags": "Demo, Wind Energy", diff --git a/src/validations/units.validations.js b/src/validations/units.validations.js index fcac3dcf..20c1a1ec 100644 --- a/src/validations/units.validations.js +++ b/src/validations/units.validations.js @@ -3,8 +3,8 @@ import { transformSerialNumberBlock } from '../utils/helpers'; import { newVintageScheme, existingVintageSchema } from './vintages.validation'; const unitsBaseSchema = { - countryJuridictionOfOwner: Joi.string().required(), - inCountryJuridictionOfOwner: Joi.string().optional(), + countryJurisdictionOfOwner: Joi.string().required(), + inCountryJurisdictionOfOwner: Joi.string().optional(), // must be in the form ABC123-XYZ456 serialNumberBlock: Joi.string() .regex(/[.*\D]+[0-9]+[-][.*\D]+[0-9]+$/) diff --git a/tests/integration/unit.spec.js b/tests/integration/unit.spec.js index f976205c..399b3546 100644 --- a/tests/integration/unit.spec.js +++ b/tests/integration/unit.spec.js @@ -81,11 +81,11 @@ describe('Create Unit Integration', () => { ); // The rest of the fields should match the original for each split unit - expect(splitRecord1.countryJuridictionOfOwner).to.equal( - unitRecord.countryJuridictionOfOwner, + expect(splitRecord1.countryJurisdictionOfOwner).to.equal( + unitRecord.countryJurisdictionOfOwner, ); - expect(splitRecord1.inCountryJuridictionOfOwner).to.equal( - unitRecord.inCountryJuridictionOfOwner, + expect(splitRecord1.inCountryJurisdictionOfOwner).to.equal( + unitRecord.inCountryJurisdictionOfOwner, ); expect(splitRecord1.intendedBuyerOrgUid).to.equal( unitRecord.intendedBuyerOrgUid, @@ -95,11 +95,11 @@ describe('Create Unit Integration', () => { unitRecord.tokenIssuanceHash, ); - expect(splitRecord2.countryJuridictionOfOwner).to.equal( - unitRecord.countryJuridictionOfOwner, + expect(splitRecord2.countryJurisdictionOfOwner).to.equal( + unitRecord.countryJurisdictionOfOwner, ); - expect(splitRecord2.inCountryJuridictionOfOwner).to.equal( - unitRecord.inCountryJuridictionOfOwner, + expect(splitRecord2.inCountryJurisdictionOfOwner).to.equal( + unitRecord.inCountryJurisdictionOfOwner, ); expect(splitRecord2.intendedBuyerOrgUid).to.equal( unitRecord.intendedBuyerOrgUid, @@ -142,11 +142,11 @@ describe('Create Unit Integration', () => { expect(newRecord1.serialNumberBlock).to.equal( splitRecord1.serialNumberBlock, ); - expect(newRecord1.countryJuridictionOfOwner).to.equal( - splitRecord1.countryJuridictionOfOwner, + expect(newRecord1.countryJurisdictionOfOwner).to.equal( + splitRecord1.countryJurisdictionOfOwner, ); - expect(newRecord1.inCountryJuridictionOfOwner).to.equal( - splitRecord1.inCountryJuridictionOfOwner, + expect(newRecord1.inCountryJurisdictionOfOwner).to.equal( + splitRecord1.inCountryJurisdictionOfOwner, ); expect(newRecord1.tokenIssuanceHash).to.equal( splitRecord1.tokenIssuanceHash, @@ -168,11 +168,11 @@ describe('Create Unit Integration', () => { expect(newRecord1.serialNumberBlock).to.equal( splitRecord1.serialNumberBlock, ); - expect(newRecord2.countryJuridictionOfOwner).to.equal( - splitRecord2.countryJuridictionOfOwner, + expect(newRecord2.countryJurisdictionOfOwner).to.equal( + splitRecord2.countryJurisdictionOfOwner, ); - expect(newRecord2.inCountryJuridictionOfOwner).to.equal( - splitRecord2.inCountryJuridictionOfOwner, + expect(newRecord2.inCountryJurisdictionOfOwner).to.equal( + splitRecord2.inCountryJurisdictionOfOwner, ); expect(newRecord2.tokenIssuanceHash).to.equal( splitRecord2.tokenIssuanceHash, @@ -209,13 +209,13 @@ describe('Create Unit Integration', () => { const payload = { serialNumberBlock: 'AXJJFSLGHSHEJ9000-AXJJFSLGHSHEJ9010', - countryJuridictionOfOwner: 'USA', + countryJurisdictionOfOwner: 'USA', unitType: 'removal', unitIdentifier: 'XYZ', unitStatus: 'Held', correspondingAdjustmentDeclaration: 'Commited', correspondingAdjustmentStatus: 'Pending', - inCountryJuridictionOfOwner: 'Maryland', + inCountryJurisdictionOfOwner: 'Maryland', unitsIssuanceLocation: 'TEST_LOCATION', unitRegistryLink: 'https://test.link', tokenIssuanceHash: '0x7777', @@ -285,11 +285,11 @@ describe('Create Unit Integration', () => { expect(newRecord.serialNumberBlock).to.equal( payload.serialNumberBlock, ); - expect(newRecord.countryJuridictionOfOwner).to.equal( - payload.countryJuridictionOfOwner, + expect(newRecord.countryJurisdictionOfOwner).to.equal( + payload.countryJurisdictionOfOwner, ); - expect(newRecord.inCountryJuridictionOfOwner).to.equal( - payload.inCountryJuridictionOfOwner, + expect(newRecord.inCountryJurisdictionOfOwner).to.equal( + payload.inCountryJurisdictionOfOwner, ); expect(newRecord.tokenIssuanceHash).to.equal( payload.tokenIssuanceHash, From 554cce67debb208797f897d9a0f746291c8941dc Mon Sep 17 00:00:00 2001 From: Mike Keen Date: Wed, 12 Jan 2022 21:17:26 -0500 Subject: [PATCH 3/4] fix: units columns --- src/models/units/units.model.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/models/units/units.model.js b/src/models/units/units.model.js index 6225b04b..55f503a1 100644 --- a/src/models/units/units.model.js +++ b/src/models/units/units.model.js @@ -90,6 +90,10 @@ class Unit extends Model { static async fts(searchStr, orgUid, pagination, columns = []) { const dialect = sequelize.getDialect(); + if (!columns.includes('serialNumberBlock')) { + columns.push('serialNumberBlock'); + } + const handlerMap = { sqlite: Unit.findAllSqliteFts, mysql: Unit.findAllMySQLFts, From 3fa4ff91b71d7c052ae4ca9cb7207292e031bd20 Mon Sep 17 00:00:00 2001 From: Mike Keen Date: Wed, 12 Jan 2022 21:47:23 -0500 Subject: [PATCH 4/4] fix: units columns fts edge case --- src/models/units/units.model.js | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/models/units/units.model.js b/src/models/units/units.model.js index 55f503a1..acfc1a56 100644 --- a/src/models/units/units.model.js +++ b/src/models/units/units.model.js @@ -14,6 +14,9 @@ const virtualColumns = { type: Sequelize.VIRTUAL, get() { const rawValue = this.getDataValue('serialNumberBlock'); + if (!rawValue) { + return undefined; + } return rawValue.split('-')[0]; }, }, @@ -21,6 +24,9 @@ const virtualColumns = { type: Sequelize.VIRTUAL, get() { const rawValue = this.getDataValue('serialNumberBlock'); + if (!rawValue) { + return undefined; + } return rawValue.split('-')[1]; }, }, @@ -28,6 +34,9 @@ const virtualColumns = { type: Sequelize.VIRTUAL, get() { const rawValue = this.getDataValue('serialNumberBlock'); + if (!rawValue) { + return undefined; + } const blocks = rawValue.split('-'); const blockStart = Number(blocks[0].split(/(\d+)/)[1]); const blockEnd = Number(blocks[1].split(/(\d+)/)[1]); @@ -90,15 +99,21 @@ class Unit extends Model { static async fts(searchStr, orgUid, pagination, columns = []) { const dialect = sequelize.getDialect(); - if (!columns.includes('serialNumberBlock')) { - columns.push('serialNumberBlock'); - } - const handlerMap = { sqlite: Unit.findAllSqliteFts, mysql: Unit.findAllMySQLFts, }; + // Check if we need to include the virtual field dep + for (const col of Object.keys(virtualColumns)) { + if (columns.includes(col)) { + if (!columns.includes('serialNumberBlock')) { + columns.push('serialNumberBlock'); + } + break; + } + } + return handlerMap[dialect]( searchStr, orgUid,