diff --git a/os-loader.js b/os-loader.js index 2e46c6fa7..982f841a7 100644 --- a/os-loader.js +++ b/os-loader.js @@ -32,6 +32,7 @@ async function OpenSearchUpdateHandler(req, res) { clm_no clm_total comment + dms_id ins_co_nm owner_owing ownr_co_nm diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 846759de7..56f9b58a8 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -2442,6 +2442,9 @@ exports.ACTIVE_SHOP_BY_USER = `query ACTIVE_SHOP_BY_USER($user: String) { associations(where: {active: {_eq: true}, useremail: {_eq: $user}}) { id shopid + bodyshop { + rr_dealerid + } } }`; diff --git a/server/opensearch/os-handler.js b/server/opensearch/os-handler.js index 663e8a015..6068c6464 100644 --- a/server/opensearch/os-handler.js +++ b/server/opensearch/os-handler.js @@ -4,6 +4,7 @@ const queries = require("../graphql-client/queries"); const client = require("../graphql-client/graphql-client").client; const { pick, isNil } = require("lodash"); const { getClient } = require("../../libs/awsUtils"); +const { JOB_DOCUMENT_FIELDS, getGlobalSearchQueryStringFields } = require("./os-search-config"); async function OpenSearchUpdateHandler(req, res) { try { @@ -21,27 +22,7 @@ async function OpenSearchUpdateHandler(req, res) { switch (req.body.table.name) { case "jobs": - document = pick(req.body.event.data.new, [ - "id", - "bodyshopid", - "clm_no", - "clm_total", - "comment", - "ins_co_nm", - "owner_owing", - "ownr_co_nm", - "ownr_fn", - "ownr_ln", - "ownr_ph1", - "ownr_ph2", - "plate_no", - "ro_number", - "status", - "v_model_yr", - "v_make_desc", - "v_model_desc", - "v_vin" - ]); + document = pick(req.body.event.data.new, JOB_DOCUMENT_FIELDS); document.bodyshopid = req.body.event.data.new.shopid; break; case "vehicles": @@ -197,15 +178,18 @@ async function OpenSearchSearchHandler(req, res) { user: req.user.email }); - if (assocs.length === 0) { + if (assocs.associations.length === 0) { res.sendStatus(401); + return; } const osClient = await getClient(); + const activeAssociation = assocs.associations[0]; const bodyShopIdMatchOverride = isNil(process.env.BODY_SHOP_ID_MATCH_OVERRIDE) - ? assocs.associations[0].shopid + ? activeAssociation.shopid : process.env.BODY_SHOP_ID_MATCH_OVERRIDE; + const isReynoldsEnabled = Boolean(activeAssociation.bodyshop?.rr_dealerid); const { body } = await osClient.search({ ...(index ? { index } : { index: ["jobs", "vehicles", "owners", "bills", "payments"] }), @@ -241,21 +225,8 @@ async function OpenSearchSearchHandler(req, res) { query: `*${search}*`, // Weighted Fields fields: [ - "*ro_number^20", - "*clm_no^14", - "*v_vin^12", - "*plate_no^12", - "*ownr_ln^10", - "transactionid^10", - "paymentnum^10", - "invoice_number^10", - "*ownr_fn^8", - "*ownr_co_nm^8", - "*ownr_ph1^8", - "*ownr_ph2^8", - "*vendor.name^8", - "*comment^6" - // "*" + ...getGlobalSearchQueryStringFields({ isReynoldsEnabled }) + // "*" ] } } diff --git a/server/opensearch/os-search-config.js b/server/opensearch/os-search-config.js new file mode 100644 index 000000000..3ef8bdcdf --- /dev/null +++ b/server/opensearch/os-search-config.js @@ -0,0 +1,69 @@ +/** + * Fields to be included in the job document indexed in OpenSearch. These fields are used for both indexing and + * searching. + * @type {string[]} + */ +const JOB_DOCUMENT_FIELDS = [ + "id", + "bodyshopid", + "clm_no", + "clm_total", + "comment", + "dms_id", + "ins_co_nm", + "owner_owing", + "ownr_co_nm", + "ownr_fn", + "ownr_ln", + "ownr_ph1", + "ownr_ph2", + "plate_no", + "ro_number", + "status", + "v_model_yr", + "v_make_desc", + "v_model_desc", + "v_vin" +]; + +/** + * Fields to be included in the global search query string. These fields are used for constructing the search query. + * @type {string[]} + */ +const BASE_GLOBAL_SEARCH_QUERY_STRING_FIELDS = [ + "*ro_number^20", + "*clm_no^14", + "*v_vin^12", + "*plate_no^12", + "*ownr_ln^10", + "transactionid^10", + "paymentnum^10", + "invoice_number^10", + "*ownr_fn^8", + "*ownr_co_nm^8", + "*ownr_ph1^8", + "*ownr_ph2^8", + "*vendor.name^8", + "*comment^6" +]; + +/** + * Returns the fields to be included in the global search query string. If Reynolds is enabled, it includes the dms_id + * field with a higher boost. + * @param param0 + * @param param0.isReynoldsEnabled + * @returns {string[]} + */ +const getGlobalSearchQueryStringFields = ({ isReynoldsEnabled = false } = {}) => { + if (!isReynoldsEnabled) { + return BASE_GLOBAL_SEARCH_QUERY_STRING_FIELDS; + } + + return ["*dms_id^20", ...BASE_GLOBAL_SEARCH_QUERY_STRING_FIELDS]; +}; + +module.exports = { + JOB_DOCUMENT_FIELDS, + BASE_GLOBAL_SEARCH_QUERY_STRING_FIELDS, + getGlobalSearchQueryStringFields +}; diff --git a/server/opensearch/tests/os-search-config.test.js b/server/opensearch/tests/os-search-config.test.js new file mode 100644 index 000000000..d6e08a006 --- /dev/null +++ b/server/opensearch/tests/os-search-config.test.js @@ -0,0 +1,21 @@ +import { describe, expect, it } from "vitest"; +import { createRequire } from "module"; + +const require = createRequire(import.meta.url); +const { JOB_DOCUMENT_FIELDS, BASE_GLOBAL_SEARCH_QUERY_STRING_FIELDS, getGlobalSearchQueryStringFields } = require( + "../os-search-config" +); + +describe("os-search-config", () => { + it("indexes dms_id on job documents", () => { + expect(JOB_DOCUMENT_FIELDS).toContain("dms_id"); + }); + + it("includes dms_id in global search fields for Reynolds shops", () => { + expect(getGlobalSearchQueryStringFields({ isReynoldsEnabled: true })).toContain("*dms_id^20"); + }); + + it("keeps the default search fields unchanged for non-Reynolds shops", () => { + expect(getGlobalSearchQueryStringFields()).toEqual(BASE_GLOBAL_SEARCH_QUERY_STRING_FIELDS); + }); +});