diff --git a/lib/model/query/entities.js b/lib/model/query/entities.js index 9d7c08e7d..b677eb45a 100644 --- a/lib/model/query/entities.js +++ b/lib/model/query/entities.js @@ -195,24 +195,14 @@ SELECT actions FROM dataset_form_defs WHERE "datasetId" = ${datasetId} AND "formDefId" = ${formDefId}`); -const _getLastRunIndex = (maybeOne, datasetId, entityUuid, runId) => maybeOne(sql` - SELECT "runIndex" - FROM entity_defs - JOIN entities ON entity_defs."entityId" = entities."id" - WHERE entities."datasetId" = ${datasetId} - AND entities."uuid" = ${entityUuid} - AND entity_defs."runId" = ${runId} - AND entity_defs."runId" IS NOT NULL - ORDER BY "runIndex" DESC LIMIT 1`); - const _holdSubmission = (run, submissionId, submissionDefId, branchId, baseVersion) => run(sql` INSERT INTO entity_submission_backlog ("submissionId", "submissionDefId", "branchId", "baseVersion", "loggedAt") VALUES (${submissionId}, ${submissionDefId}, ${branchId}, ${baseVersion}, CLOCK_TIMESTAMP()) `); -const _checkHeldSubmission = (maybeOne, runId, runIndex) => maybeOne(sql` +const _checkHeldSubmission = (maybeOne, branchId, baseVersion) => maybeOne(sql` SELECT * FROM entity_submission_backlog - WHERE "runId"=${runId} AND "runIndex" = ${runIndex}`); + WHERE "branchId"=${branchId} AND "baseVersion" = ${baseVersion}`); const _createEntity = (dataset, entityData, submissionId, submissionDef, submissionDefId, event, parentEvent) => async ({ Audits, Entities }) => { // If dataset requires approval on submission to create an entity and this event is not @@ -331,7 +321,7 @@ const _updateEntity = (dataset, entityData, submissionId, submissionDef, submiss }; // Entrypoint to where submissions (a specific version) become entities -const _processSubmissionEvent = (event, parentEvent) => async ({ Datasets, Entities, Submissions, Forms, oneFirst }) => { +const _processSubmissionEvent = (event, parentEvent) => async ({ Audits, Datasets, Entities, Submissions, Forms, maybeOne, oneFirst }) => { const { submissionId, submissionDefId } = event.details; const form = await Forms.getByActeeId(event.acteeId); @@ -396,7 +386,18 @@ const _processSubmissionEvent = (event, parentEvent) => async ({ Datasets, Entit } } else if (entityData.system.create === '1' || entityData.system.create === 'true') - return Entities._createEntity(dataset, entityData, submissionId, submissionDef, submissionDefId, event, parentEvent); + await Entities._createEntity(dataset, entityData, submissionId, submissionDef, submissionDefId, event, parentEvent); + + // Check for held submissions that follow this one in the same branch + if (entityData.system.branchId != null) { + const currentBaseVersion = parseInt(entityData.system.baseVersion, 10); + const nextSub = await _checkHeldSubmission(maybeOne, entityData.system.branchId, currentBaseVersion + 1); + if (nextSub.isDefined()) { + const { submissionId: nextSubmissionId, submissionDefId: nextSubmissionDefId } = nextSub.get(); + await Audits.log({ id: event.actorId }, 'submission.reprocess', { acteeId: event.acteeId }, + { submissionId: nextSubmissionId, submissionDefId: nextSubmissionDefId }); + } + } return null; }; diff --git a/lib/worker/jobs.js b/lib/worker/jobs.js index a2bea03f2..2efbf5536 100644 --- a/lib/worker/jobs.js +++ b/lib/worker/jobs.js @@ -18,6 +18,7 @@ const jobs = { 'submission.update.version': [ require('./submission').submissionUpdateVersion, require('./entity').createOrUpdateEntityFromSubmission ], 'submission.update': [ require('./entity').createOrUpdateEntityFromSubmission ], + 'submission.reprocess': [ require('./entity').createOrUpdateEntityFromSubmission ], 'form.create': [ require('./form').create ], 'form.update.draft.set': [ require('./form').updateDraftSet ], diff --git a/test/integration/api/datasets.js b/test/integration/api/datasets.js index f089954e3..b115002fb 100644 --- a/test/integration/api/datasets.js +++ b/test/integration/api/datasets.js @@ -3894,7 +3894,7 @@ describe('datasets and entities', () => { })); }); - describe.only('dataset-specific verbs', () => { + describe('dataset-specific verbs', () => { describe('dataset.create', () => { it('should NOT allow a new form that creates a dataset without user having dataset.create verb', testServiceFullTrx(async (service, { run }) => { await run(sql`UPDATE roles SET verbs = (verbs - 'dataset.create') WHERE system in ('manager')`); diff --git a/test/integration/api/offline-entities.js b/test/integration/api/offline-entities.js index b2e0ec596..d72f6b56a 100644 --- a/test/integration/api/offline-entities.js +++ b/test/integration/api/offline-entities.js @@ -291,7 +291,7 @@ describe('Offline Entities', () => { entity.aux.currentVersion.data.should.eql({ age: '22', first_name: 'Johnny' }); })); - it.only('should apply later run received earlier', testOfflineEntities(async (service, container) => { + it('should apply later run received earlier', testOfflineEntities(async (service, container) => { const asAlice = await service.login('alice'); const branchId = uuid(); const dataset = await container.Datasets.get(1, 'people', true).then(getOrNotFound); @@ -317,8 +317,8 @@ describe('Offline Entities', () => { await exhaust(container); - const s = await container.all(sql`select * from entity_submission_backlog`); - console.log(s); + const backlogCount = await container.oneFirst(sql`select count(*) from entity_submission_backlog`); + backlogCount.should.equal(1); await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') .send(testData.instances.offlineEntity.one