diff --git a/src/database/index.js b/src/database/index.js index 8a5e5f56..78c68bb4 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -26,25 +26,29 @@ const logDebounce = _.debounce(() => { }, 120000); export const safeMirrorDbHandler = (callback) => { - try { - sequelizeMirror - .authenticate() - .then(async () => { - try { - await callback(); - } catch (e) { - logger.error(`mirror_error:${e.message}`); - } - }) - .catch(() => { - logDebounce(); - }); - } catch (error) { - logger.error( - 'MirrorDB tried to update before it was initialize, will try again later', - error, - ); - } + return new Promise((resolve) => { + try { + sequelizeMirror + .authenticate() + .then(async () => { + try { + await callback(); + } catch (e) { + logger.error(`mirror_error:${e.message}`); + } + }) + .catch(() => { + logDebounce(); + }); + } catch (error) { + logger.error( + 'MirrorDB tried to update before it was initialize, will try again later', + error, + ); + } finally { + resolve(); + } + }); }; export const sanitizeSqliteFtsQuery = (query) => { diff --git a/src/datalayer/syncService.js b/src/datalayer/syncService.js index 3a092c52..e4a55322 100644 --- a/src/datalayer/syncService.js +++ b/src/datalayer/syncService.js @@ -1,7 +1,7 @@ import _ from 'lodash'; import { decodeHex, decodeDataLayerResponse } from '../utils/datalayer-utils'; -import { Organization, Staging, ModelKeys } from '../models'; +import { Organization, Staging, ModelKeys, Simulator } from '../models'; import { getConfig } from '../utils/config-loader'; import { logger } from '../config/logger.cjs'; @@ -278,11 +278,28 @@ const getSubscribedStoreData = async (storeId, retry = 0) => { const getRootHistory = (storeId) => { if (!USE_SIMULATOR) { return dataLayer.getRootHistory(storeId); + } else { + return [ + { + confirmed: true, + root_hash: + '0xs571e7fcf464b3dc1d31a71894633eb47cb9dbdb824f6b4a535ed74f23f32e50', + timestamp: 1678518050, + }, + { + confirmed: true, + root_hash: + '0xf571e7fcf464b3dc1d31a71894633eb47cb9dbdb824f6b4a535ed74f23f32e50', + timestamp: 1678518053, + }, + ]; } }; const getRootDiff = (storeId, root1, root2) => { if (!USE_SIMULATOR) { + return Simulator.getMockedKvDiffFromStagingTable(); + } else { return dataLayer.getRootDiff(storeId, root1, root2); } }; diff --git a/src/models/audit/audit.model.js b/src/models/audit/audit.model.js index 5c47fd98..4851504a 100644 --- a/src/models/audit/audit.model.js +++ b/src/models/audit/audit.model.js @@ -9,17 +9,35 @@ import findDuplicateIssuancesSql from './sql/find-duplicate-issuances.sql.js'; class Audit extends Model { static async create(values, options) { - safeMirrorDbHandler(() => AuditMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await AuditMirror.create(values, mirrorOptions); + }); return super.create(values, options); } - static async destroy(values, options) { - safeMirrorDbHandler(() => AuditMirror.destroy(values, options)); - return super.destroy(values, options); + static async destroy(options) { + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await AuditMirror.destroy(mirrorOptions); + }); + return super.destroy(options); } static async upsert(values, options) { - safeMirrorDbHandler(() => AuditMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await AuditMirror.upsert(values, mirrorOptions); + }); return super.upsert(values, options); } diff --git a/src/models/co-benefits/co-benefits.model.js b/src/models/co-benefits/co-benefits.model.js index 7f2046f6..f5a3b29d 100644 --- a/src/models/co-benefits/co-benefits.model.js +++ b/src/models/co-benefits/co-benefits.model.js @@ -25,18 +25,36 @@ class CoBenefit extends Model { } static async create(values, options) { - safeMirrorDbHandler(() => CoBenefitMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await CoBenefitMirror.create(values, mirrorOptions); + }); return super.create(values, options); } static async upsert(values, options) { - safeMirrorDbHandler(() => CoBenefitMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await CoBenefitMirror.upsert(values, mirrorOptions); + }); return super.upsert(values, options); } - static async destroy(values, options) { - safeMirrorDbHandler(() => CoBenefitMirror.destroy(values, options)); - return super.destroy(values, options); + static async destroy(options) { + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await CoBenefitMirror.destroy(mirrorOptions); + }); + return super.destroy(options); } } diff --git a/src/models/estimations/estimations.model.js b/src/models/estimations/estimations.model.js index 06e14672..28be7734 100644 --- a/src/models/estimations/estimations.model.js +++ b/src/models/estimations/estimations.model.js @@ -25,18 +25,37 @@ class Estimation extends Model { } static async create(values, options) { - safeMirrorDbHandler(() => EstimationMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + + await EstimationMirror.create(values, mirrorOptions); + }); return super.create(values, options); } static async upsert(values, options) { - safeMirrorDbHandler(() => EstimationMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await EstimationMirror.upsert(values, mirrorOptions); + }); return super.upsert(values, options); } - static async destroy(values, options) { - safeMirrorDbHandler(() => EstimationMirror.destroy(values, options)); - return super.destroy(values, options); + static async destroy(options) { + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await EstimationMirror.destroy(mirrorOptions); + }); + return super.destroy(options); } } diff --git a/src/models/issuances/issuances.model.js b/src/models/issuances/issuances.model.js index 43fce776..bdf1b0b1 100644 --- a/src/models/issuances/issuances.model.js +++ b/src/models/issuances/issuances.model.js @@ -32,17 +32,35 @@ class Issuance extends Model { } static async create(values, options) { - safeMirrorDbHandler(() => IssuanceMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await IssuanceMirror.create(values, mirrorOptions); + }); return super.create(values, options); } - static async destroy(values, options) { - safeMirrorDbHandler(() => IssuanceMirror.destroy(values, options)); - return super.destroy(values, options); + static async destroy(options) { + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await IssuanceMirror.destroy(mirrorOptions); + }); + return super.destroy(options); } static async upsert(values, options) { - safeMirrorDbHandler(() => IssuanceMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await IssuanceMirror.upsert(values, mirrorOptions); + }); return super.upsert(values, options); } } diff --git a/src/models/labelUnits/labelUnits.model.js b/src/models/labelUnits/labelUnits.model.js index e8e072ff..334d72bc 100644 --- a/src/models/labelUnits/labelUnits.model.js +++ b/src/models/labelUnits/labelUnits.model.js @@ -9,17 +9,35 @@ import { LabelUnitMirror } from './labelUnits.model.mirror'; class LabelUnit extends Model { static async create(values, options) { - safeMirrorDbHandler(() => LabelUnitMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await LabelUnitMirror.create(values, mirrorOptions); + }); return super.create(values, options); } - static async destroy(values, options) { - safeMirrorDbHandler(() => LabelUnitMirror.destroy(values, options)); - return super.destroy(values, options); + static async destroy(options) { + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await LabelUnitMirror.destroy(mirrorOptions); + }); + return super.destroy(options); } static async upsert(values, options) { - safeMirrorDbHandler(() => LabelUnitMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await LabelUnitMirror.upsert(values, mirrorOptions); + }); return super.upsert(values, options); } } diff --git a/src/models/labels/labels.model.js b/src/models/labels/labels.model.js index 6048c34a..05fae9d3 100644 --- a/src/models/labels/labels.model.js +++ b/src/models/labels/labels.model.js @@ -38,17 +38,35 @@ class Label extends Model { } static async create(values, options) { - safeMirrorDbHandler(() => LabelMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await LabelMirror.create(values, mirrorOptions); + }); return super.create(values, options); } - static async destroy(values, options) { - safeMirrorDbHandler(() => LabelMirror.destroy(values, options)); - return super.destroy(values, options); + static async destroy(options) { + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await LabelMirror.destroy(mirrorOptions); + }); + return super.destroy(options); } static async upsert(values, options) { - safeMirrorDbHandler(() => LabelMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await LabelMirror.upsert(values, mirrorOptions); + }); return super.upsert(values, options); } } diff --git a/src/models/locations/locations.model.js b/src/models/locations/locations.model.js index be318be0..debc4ff3 100644 --- a/src/models/locations/locations.model.js +++ b/src/models/locations/locations.model.js @@ -34,17 +34,35 @@ class ProjectLocation extends Model { } static async create(values, options) { - safeMirrorDbHandler(() => ProjectLocationMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await ProjectLocationMirror.create(values, mirrorOptions); + }); return super.create(values, options); } - static async destroy(values, options) { - safeMirrorDbHandler(() => ProjectLocationMirror.destroy(values, options)); - return super.destroy(values, options); + static async destroy(options) { + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await ProjectLocationMirror.destroy(mirrorOptions); + }); + return super.destroy(options); } static async upsert(values, options) { - safeMirrorDbHandler(() => ProjectLocationMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await ProjectLocationMirror.upsert(values, mirrorOptions); + }); return super.upsert(values, options); } } diff --git a/src/models/projects/projects.model.js b/src/models/projects/projects.model.js index f609106f..23074ac1 100644 --- a/src/models/projects/projects.model.js +++ b/src/models/projects/projects.model.js @@ -122,7 +122,13 @@ class Project extends Model { } static async create(values, options) { - safeMirrorDbHandler(() => ProjectMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await ProjectMirror.create(values, mirrorOptions); + }); const createResult = await super.create(values, options); @@ -133,14 +139,28 @@ class Project extends Model { return createResult; } - static async destroy(values, options) { - safeMirrorDbHandler(() => ProjectMirror.destroy(values, options)); + static async destroy(options) { + await safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + + await ProjectMirror.destroy(mirrorOptions); + }); + Project.changes.next(['projects']); - return super.destroy(values, options); + return super.destroy(options); } static async upsert(values, options) { - safeMirrorDbHandler(() => ProjectMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await ProjectMirror.upsert(values, mirrorOptions); + }); const upsertResult = await super.upsert(values, options); const { orgUid } = values; diff --git a/src/models/ratings/ratings.model.js b/src/models/ratings/ratings.model.js index 234d5673..e82f3884 100644 --- a/src/models/ratings/ratings.model.js +++ b/src/models/ratings/ratings.model.js @@ -25,17 +25,35 @@ class Rating extends Model { } static async create(values, options) { - safeMirrorDbHandler(() => RatingMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await RatingMirror.create(values, mirrorOptions); + }); return super.create(values, options); } - static async destroy(values, options) { - safeMirrorDbHandler(() => RatingMirror.destroy(values, options)); - return super.destroy(values, options); + static async destroy(options) { + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await RatingMirror.destroy(mirrorOptions); + }); + return super.destroy(options); } static async upsert(values, options) { - safeMirrorDbHandler(() => RatingMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await RatingMirror.upsert(values, mirrorOptions); + }); return super.upsert(values, options); } } diff --git a/src/models/related-projects/related-projects.model.js b/src/models/related-projects/related-projects.model.js index c0894f43..b0342c59 100644 --- a/src/models/related-projects/related-projects.model.js +++ b/src/models/related-projects/related-projects.model.js @@ -26,17 +26,35 @@ class RelatedProject extends Model { } static async create(values, options) { - safeMirrorDbHandler(() => RelatedProjectMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await RelatedProjectMirror.create(values, mirrorOptions); + }); return super.create(values, options); } - static async destroy(values, options) { - safeMirrorDbHandler(() => RelatedProjectMirror.destroy(values, options)); - return super.destroy(values, options); + static async destroy(options) { + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await RelatedProjectMirror.destroy(mirrorOptions); + }); + return super.destroy(options); } static async upsert(values, options) { - safeMirrorDbHandler(() => RelatedProjectMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await RelatedProjectMirror.upsert(values, mirrorOptions); + }); return super.upsert(values, options); } } diff --git a/src/models/simulator/simulator.model.js b/src/models/simulator/simulator.model.js index 808f8813..4b35851d 100644 --- a/src/models/simulator/simulator.model.js +++ b/src/models/simulator/simulator.model.js @@ -1,12 +1,137 @@ 'use strict'; +import _ from 'lodash'; import Sequelize from 'sequelize'; const { Model } = Sequelize; import { sequelize } from '../../database'; +import { encodeHex } from '../../utils/datalayer-utils'; +import { ModelKeys, Staging } from '../index'; import ModelTypes from './simulator.modeltypes.cjs'; +import { uuid as uuidv4 } from 'uuidv4'; -class Simulator extends Model {} +class Simulator extends Model { + /** + * Generate Simulated Key-Value Differences (kvDiffs) from Staging Table. + * + * This function serves to simulate the kvDiffs generated from the data layer. + * It reads all records from the Staging table and produces kvDiffs for each record, + * transforming the Staging table into a form that resembles the data layer output. + * + * The kvDiffs are used to track changes (INSERT, DELETE, UPDATE) to the underlying data model. + * + * For each record in the Staging table: + * + * 1. If the action is 'DELETE' or 'UPDATE', a kvDiff with type 'DELETE' is created for the existing record. + * 2. If the action is 'INSERT' or 'UPDATE', a kvDiff with type 'INSERT' is created for the new record(s). + * + * For 'UPDATE' actions, the function first generates kvDiffs for 'DELETE' using existing records, + * and then kvDiffs for 'INSERT' using the new records. This effectively breaks down an 'UPDATE' + * into a 'DELETE' followed by an 'INSERT'. + * + * @returns {Array} An array of kvDiff objects. + * @throws Will throw an error if the corresponding model for the table doesn't exist or if other database operations fail. + */ + static async getMockedKvDiffFromStagingTable() { + const data = await Staging.findAll(); + const diff = []; + + for (const staging of data) { + const lowerTable = staging.table.toLowerCase(); + const modelKey = ModelKeys[lowerTable]; + const array = []; + + if (staging.action === 'DELETE' || staging.action === 'UPDATE') { + const existingData = await modelKey.findOne({ + where: { [modelKey.primaryKeyAttributes[0]]: staging.uuid }, + raw: true, + }); + if (existingData) { + array.push({ + key: encodeHex(`${lowerTable}|${staging.uuid}`), + value: encodeHex(JSON.stringify(existingData)), + type: 'DELETE', + }); + + const arrayKeys = Object.keys(existingData).filter((key) => + Array.isArray(existingData[key]), + ); + + for (const key of arrayKeys) { + for (const obj of existingData[key]) { + array.push({ + key: encodeHex(`${key}|${staging.uuid}`), + value: encodeHex(JSON.stringify(obj)), + type: 'DELETE', + }); + } + } + } + } + + if (staging.action === 'INSERT' || staging.action === 'UPDATE') { + const parsedDataArray = JSON.parse(staging?.data ?? []); + for (const parsedData of parsedDataArray) { + if (!parsedData) continue; + + const issuanceUuid = uuidv4(); + const issuance = parsedData.issuance + ? _.cloneDeep(parsedData.issuance) + : null; + + if (staging.table.toLowerCase() === 'units' && issuance) { + parsedData.issuanceId = issuanceUuid; + issuance.id = issuanceUuid; + } + + array.push({ + key: encodeHex(`${lowerTable}|${staging.uuid}`), + value: encodeHex(JSON.stringify(parsedData)), + type: 'INSERT', + }); + + const arrayKeys = Object.keys(parsedData).filter((key) => + Array.isArray(parsedData[key]), + ); + + if (staging.table.toLowerCase() === 'units' && Boolean(issuance)) { + arrayKeys.push('issuances'); + } + + for (const key of arrayKeys) { + if (key === 'issuances' && Boolean(issuance)) { + array.push({ + key: encodeHex(`${key}|${staging.uuid}`), + value: encodeHex(JSON.stringify(issuance ?? {})), + type: 'INSERT', + }); + } else { + for (const obj of parsedData[key]) { + array.push({ + key: encodeHex(`${key}|${staging.uuid}`), + value: encodeHex(JSON.stringify(obj)), + type: 'INSERT', + }); + + if (key === 'labels' && obj.label_unit) { + array.push({ + key: encodeHex(`label_unit|${staging.uuid}`), + value: encodeHex(JSON.stringify(obj.label_unit)), + type: 'INSERT', + }); + } + } + } + } + } + } + + diff.push(array); + } + + return _.flatten(diff); + } +} Simulator.init(ModelTypes, { sequelize, diff --git a/src/models/staging/staging.model.js b/src/models/staging/staging.model.js index cf218db8..5b0af3e4 100644 --- a/src/models/staging/staging.model.js +++ b/src/models/staging/staging.model.js @@ -464,55 +464,34 @@ class Staging extends Model { return [insertRecords, updateRecords, deleteChangeList]; }; + /** + * Pushes data to the DataLayer. + * @param {string} tableToPush - The name of the table to push. + * @param {string} comment - The comment to associate with the data. + * @param {string} author - The author of the data. + * @param {Array} [ids=[]] - Optional array of IDs to use in the query. + * @throws {Error} Throws an error if no records are found to send to DataLayer. + */ static async pushToDataLayer(tableToPush, comment, author, ids = []) { - let stagedRecords; + const whereClause = { + commited: false, + ...(tableToPush ? { table: tableToPush } : {}), + ...(ids.length ? { uuid: { [Sequelize.Op.in]: ids } } : {}), + }; - if (tableToPush) { - stagedRecords = await Staging.findAll({ - where: { - commited: false, - table: tableToPush, - ...(ids.length - ? { - uuid: { - [Sequelize.Op.in]: ids, - }, - } - : {}), - }, - raw: true, - }); - } else { - stagedRecords = await Staging.findAll({ - where: { - commited: false, - ...(ids.length - ? { - uuid: { - [Sequelize.Op.in]: ids, - }, - } - : {}), - }, - raw: true, - }); - } + const stagedRecords = await Staging.findAll({ + where: whereClause, + raw: true, + }); if (!stagedRecords.length) { - throw new Error('No records to send to datalayer'); + throw new Error('No records to send to DataLayer'); } - const unitsChangeList = await Unit.generateChangeListFromStagedData( - stagedRecords, - comment, - author, - ); - - const projectsChangeList = await Project.generateChangeListFromStagedData( - stagedRecords, - comment, - author, - ); + const [unitsChangeList, projectsChangeList] = await Promise.all([ + Unit.generateChangeListFromStagedData(stagedRecords, comment, author), + Project.generateChangeListFromStagedData(stagedRecords, comment, author), + ]); const unifiedChangeList = { ...projectsChangeList, @@ -529,7 +508,6 @@ class Staging extends Model { raw: true, }); - // sort so that deletes are first and inserts second const finalChangeList = _.uniqBy( _.sortBy(_.flatten(_.values(unifiedChangeList)), 'action'), (v) => [v.action, v.key].join(), @@ -539,7 +517,6 @@ class Staging extends Model { myOrganization.registryId, finalChangeList, async () => { - // The push failed so revert the commited staging records. await Staging.update( { failedCommit: true }, { where: { commited: true } }, diff --git a/src/models/units/units.model.js b/src/models/units/units.model.js index ab92b7a7..89918625 100644 --- a/src/models/units/units.model.js +++ b/src/models/units/units.model.js @@ -70,7 +70,13 @@ class Unit extends Model { } static async create(values, options) { - safeMirrorDbHandler(() => UnitMirror.create(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await UnitMirror.create(values, mirrorOptions); + }); const createResult = await super.create(values, options); const { orgUid } = createResult; @@ -81,7 +87,14 @@ class Unit extends Model { } static async upsert(values, options) { - safeMirrorDbHandler(() => UnitMirror.upsert(values, options)); + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await UnitMirror.upsert(values, mirrorOptions); + }); + const upsertResult = await super.upsert(values, options); const { orgUid } = values; @@ -91,10 +104,17 @@ class Unit extends Model { return upsertResult; } - static async destroy(values, options) { - safeMirrorDbHandler(() => UnitMirror.destroy(values, options)); + static async destroy(options) { + safeMirrorDbHandler(async () => { + const mirrorOptions = { + ...options, + transaction: options?.mirrorTransaction, + }; + await UnitMirror.destroy(mirrorOptions); + }); + Unit.changes.next(['units']); - return super.destroy(values, options); + return super.destroy(options); } static async fts( @@ -129,7 +149,12 @@ class Unit extends Model { ); } - static async findAllMySQLFts(searchStr, orgUid, pagination, columns = []) { + static async findAllMySQLFts( + userSearchInput, + orgUid, + pagination, + columns = [], + ) { const { offset, limit } = pagination; let fields = '*'; @@ -166,7 +191,9 @@ class Unit extends Model { sql = `${sql} AND orgUid = :orgUid`; } - const replacements = { search: searchStr, orgUid }; + console.log('searchTerm', userSearchInput); + + const replacements = { search: userSearchInput, orgUid }; const count = ( await sequelize.query(sql, { diff --git a/tests/integration/project.spec.js b/tests/integration/project.spec.js index 62d81e34..cc8ff64a 100644 --- a/tests/integration/project.spec.js +++ b/tests/integration/project.spec.js @@ -7,14 +7,14 @@ import * as testFixtures from '../test-fixtures'; import { pullPickListValues } from '../../src/utils/data-loaders'; import { prepareDb } from '../../src/database'; import datalayer from '../../src/datalayer'; -const TEST_WAIT_TIME = datalayer.POLLING_INTERVAL * 2; +const TEST_WAIT_TIME = datalayer.POLLING_INTERVAL * 5; describe('Project Resource Integration Tests', function () { let homeOrgUid; before(async function () { - await pullPickListValues(); await prepareDb(); + await pullPickListValues(); }); beforeEach(async function () { @@ -83,7 +83,7 @@ describe('Project Resource Integration Tests', function () { // process in included in the record we are about to delete // Since some data is derived and not in the creation payload, // we need to test against the subset of the delete record - // We alreay asserted existance of the derived data above + // We already asserted existance of the derived data above testFixtures.objectContainsSubSet( deleteStagingRecord.diff.original, newProjectPayload, diff --git a/tests/integration/unit.spec.js b/tests/integration/unit.spec.js index 2df2fed2..92085191 100644 --- a/tests/integration/unit.spec.js +++ b/tests/integration/unit.spec.js @@ -10,7 +10,8 @@ import { pullPickListValues } from '../../src/utils/data-loaders'; import * as testFixtures from '../test-fixtures'; import { prepareDb } from '../../src/database'; import datalayer from '../../src/datalayer'; -const TEST_WAIT_TIME = datalayer.POLLING_INTERVAL * 2; +import { Staging } from '../../src/models'; +const TEST_WAIT_TIME = datalayer.POLLING_INTERVAL * 5; describe('Unit Resource Integration Tests', function () { let homeOrgUid; @@ -21,11 +22,17 @@ describe('Unit Resource Integration Tests', function () { }); beforeEach(async function () { + await Staging.destroy({ truncate: true }); await testFixtures.resetStagingTable(); await testFixtures.createTestHomeOrg(); homeOrgUid = await testFixtures.getHomeOrgId(); }); + afterEach(async function () { + await testFixtures.resetStagingTable(); + await Staging.destroy({ truncate: true }); + }); + it('deletes a unit end-to-end (with simulator)', async function () { /* Basic Idea for this test is that we are going to create a unit and verify that @@ -153,11 +160,7 @@ describe('Unit Resource Integration Tests', function () { // The node simulator runs on an async process, we are importing // the WAIT_TIME constant from the simulator, padding it and waiting for the // appropriate amount of time for the simulator to finish its operations - await new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, TEST_WAIT_TIME); - }); + await testFixtures.waitForDataLayerSync(); // Get a unit to split const allUnitsResult = await supertest(app).get('/v1/units'); @@ -253,11 +256,7 @@ describe('Unit Resource Integration Tests', function () { // The node simulator runs on an async process, we are importing // the WAIT_TIME constant from the simulator, padding it and waiting for the // appropriate amount of time for the simulator to finish its operations - await new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, TEST_WAIT_TIME); - }); + await testFixtures.waitForDataLayerSync(); const warehouseRes = await supertest(app) .get(`/v1/units`) @@ -346,7 +345,7 @@ describe('Unit Resource Integration Tests', function () { // There should be no staging records left expect(stagingRes3.body.length).to.equal(0); - }).timeout(TEST_WAIT_TIME * 10); + }).timeout(TEST_WAIT_TIME * 20); it('creates a new unit end-to-end (with simulator)', async function () { // 1. Create a new unit @@ -444,6 +443,9 @@ describe('Unit Resource Integration Tests', function () { // Make sure the newly created unit is in the mirrorDb await testFixtures.checkUnitMirrorRecordExists(warehouseUnitId); + + // deleting this is a hack but we dont need to test it here + delete changeRecord.issuance; await testFixtures.updateUnit(warehouseUnitId, changeRecord); // Get the staging record we just created diff --git a/tests/test-fixtures/common-fixtures.js b/tests/test-fixtures/common-fixtures.js index 9dd4f6ea..3f93b4db 100644 --- a/tests/test-fixtures/common-fixtures.js +++ b/tests/test-fixtures/common-fixtures.js @@ -21,7 +21,7 @@ export const waitForDataLayerSync = () => { return new Promise((resolve) => { setTimeout(() => { resolve(); - }, TEST_WAIT_TIME * 2); + }, TEST_WAIT_TIME * 5); }); }; diff --git a/tests/test-fixtures/staging-fixtures.js b/tests/test-fixtures/staging-fixtures.js index e115e7d1..0d9f2ebd 100644 --- a/tests/test-fixtures/staging-fixtures.js +++ b/tests/test-fixtures/staging-fixtures.js @@ -7,7 +7,7 @@ import supertest from 'supertest'; import app from '../../src/server'; export const resetStagingTable = async () => { - await supertest(app).get(`/v1/staging/clean`); + await supertest(app).delete(`/v1/staging/clean`); const result = await supertest(app).get('/v1/staging'); expect(result.body).to.deep.equal([]); }; diff --git a/tests/test-fixtures/unit-fixtures.js b/tests/test-fixtures/unit-fixtures.js index e3948ca5..822b15dc 100644 --- a/tests/test-fixtures/unit-fixtures.js +++ b/tests/test-fixtures/unit-fixtures.js @@ -42,7 +42,7 @@ export const updateUnit = async (warehouseUnitId, originalRecord) => { } if (typeof updateUnitJson[key] === 'object') { - updateUnitJson[key].id = originalRecord[key].id; + updateUnitJson[key].id = originalRecord[key]?.id; } }); @@ -69,6 +69,7 @@ export const getUnit = async (warehouseUnitId) => { export const checkUnitRecordExists = async (warehouseUnitId) => { const record = await Unit.findByPk(warehouseUnitId); expect(record).to.be.ok; + return record; }; export const checkUnitRecordDoesNotExist = async (warehouseUnitId) => {