Skip to content

Commit

Permalink
Entity upsert, try updating then try creating
Browse files Browse the repository at this point in the history
  • Loading branch information
ktuite committed Nov 10, 2023
1 parent 2a259dc commit c708f8e
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 5 deletions.
16 changes: 11 additions & 5 deletions lib/model/query/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,19 @@ const _processSubmissionEvent = (event, parentEvent) => async ({ Datasets, Entit
const dataset = (await Datasets.get(form.get().projectId, entityData.system.dataset, true))
.orThrow(Problem.user.datasetNotFound({ datasetName: entityData.system.dataset }));

// Create entity
if (entityData.system.create === '1' || entityData.system.create === 'true')
return Entities._createEntity(dataset, entityData, submissionId, submissionDef, submissionDefId, event, parentEvent);

// Or update entity
if (entityData.system.update === '1' || entityData.system.update === 'true')
return Entities._updateEntity(dataset, entityData, submissionId, submissionDef, submissionDefId, event);
try {
await Entities._updateEntity(dataset, entityData, submissionId, submissionDef, submissionDefId, event);
} catch (err) {
if ((err.problemCode === 404.8) && (entityData.system.create === '1' || entityData.system.create === 'true')) {
await Entities._createEntity(dataset, entityData, submissionId, submissionDef, submissionDefId, event, parentEvent);
} else {
throw (err);
}
}
else if (entityData.system.create === '1' || entityData.system.create === 'true')
return Entities._createEntity(dataset, entityData, submissionId, submissionDef, submissionDefId, event, parentEvent);

return null;
};
Expand Down
134 changes: 134 additions & 0 deletions test/integration/api/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -2054,5 +2054,139 @@ describe('Entities API', () => {
});
}));
});

describe('create and update in a single submission', () => {
it('should create an entity if it does not yet exist', testEntityUpdates(async (service, container) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/forms/updateEntity/submissions')
.send(testData.instances.updateEntity.one
.replace('update="1"', 'create="1" update="1"')
.replace('id="12345678-1234-4123-8234-123456789abc"', 'id="12345678-1234-4123-8234-123456789aaa"'))
.expect(200);

await exhaust(container);

await asAlice.get('/v1/projects/1/forms/updateEntity/submissions/one/audits')
.expect(200)
.then(({ body: logs }) => {
logs[0].action.should.be.eql('entity.create');
logs[1].action.should.be.eql('submission.create');
});

await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789aaa')
.expect(200)
.then(({ body: person }) => {
person.currentVersion.data.should.eql({ age: '85', first_name: 'Alicia' });
person.currentVersion.label.should.equal('Alicia (85)');
person.currentVersion.version.should.equal(1);
});
}));

it('should have create error if failed to update non-existent entity but still had error with create (e.g blank label)', testEntityUpdates(async (service, container) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/forms/updateEntity/submissions')
.send(testData.instances.updateEntity.one
.replace('update="1"', 'create="1" update="1"')
.replace('id="12345678-1234-4123-8234-123456789abc"', 'id="12345678-1234-4123-8234-123456789aaa"')
.replace('<label>Alicia (85)</label>', ''))
.expect(200);

await exhaust(container);

await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789aaa')
.expect(404);

await asAlice.get('/v1/projects/1/forms/updateEntity/submissions/one/audits')
.expect(200)
.then(({ body: logs }) => {
logs[0].action.should.be.eql('entity.error');
logs[1].action.should.be.eql('submission.create');
});
}));

it('should update an entity if it does exist', testEntityUpdates(async (service, container) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/forms/updateEntity/submissions')
.send(testData.instances.updateEntity.one
.replace('update="1"', 'create="1" update="1"'))
.expect(200);

await exhaust(container);

await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc')
.expect(200)
.then(({ body: person }) => {
person.currentVersion.data.should.eql({ age: '85', first_name: 'Alicia' });
person.currentVersion.label.should.equal('Alicia (85)');
person.currentVersion.version.should.equal(2);
});

await asAlice.get('/v1/projects/1/forms/updateEntity/submissions/one/audits')
.expect(200)
.then(({ body: logs }) => {
logs[0].action.should.be.eql('entity.update.version');
logs[1].action.should.be.eql('submission.create');
});
}));

it('should fail both update and create if uuid exists and base version is wrong', testEntityUpdates(async (service, container) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/forms/updateEntity/submissions')
.send(testData.instances.updateEntity.one
.replace('update="1"', 'create="1" update="1"')
.replace('baseVersion="1"', 'baseVersion="99"'))
.expect(200);

await exhaust(container);

await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc')
.expect(200)
.then(({ body: person }) => {
// Not updated
person.currentVersion.version.should.equal(1);
person.currentVersion.data.should.eql({ age: '22', first_name: 'Johnny' });
person.currentVersion.label.should.equal('Johnny Doe');
});

await asAlice.get('/v1/projects/1/forms/updateEntity/submissions/one/audits')
.expect(200)
.then(({ body: logs }) => {
logs[0].action.should.be.eql('entity.error');
logs[1].action.should.be.eql('submission.create');
});
}));

it('should fail both update and create on error like invalid uuid', testEntityUpdates(async (service, container) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/forms/updateEntity/submissions')
.send(testData.instances.updateEntity.one
.replace('update="1"', 'create="1" update="1"')
.replace('id="12345678-1234-4123-8234-123456789abc"', 'id="not_a_valid_uuid"'))
.expect(200);

await exhaust(container);

await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc')
.expect(200)
.then(({ body: person }) => {
// Not updated
person.currentVersion.version.should.equal(1);
person.currentVersion.data.should.eql({ age: '22', first_name: 'Johnny' });
person.currentVersion.label.should.equal('Johnny Doe');
});

await asAlice.get('/v1/projects/1/forms/updateEntity/submissions/one/audits')
.expect(200)
.then(({ body: logs }) => {
logs[0].action.should.be.eql('entity.error');
logs[1].action.should.be.eql('submission.create');
});
}));
});
});
});

0 comments on commit c708f8e

Please sign in to comment.