Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions src/support/prompts-storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -714,12 +714,16 @@ export async function upsertPrompts({
updated_by: updatedBy,
};

if (match && match.status !== 'active') {
// eslint-disable-next-line no-continue
continue;
}

if (match) {
// Restore-on-match: when an incoming prompt matches an existing row we
// update that row. This includes rows that were previously soft-deleted
// (status !== 'active') — the update sets status back to 'active' (via
// `row.status`, default 'active'), restoring the prompt. Previously a
// soft-deleted match was dropped entirely (no insert, no update, no
// restore), so re-importing an identical prompt silently no-oped while
// the API still returned 201 with created:0/skipped:N. Excluding the
// restore left brands with only soft-deleted rows unable to re-create
// identical prompts.
toUpdate.push({ ...row, id: match.id });
processed.push({ ...row, prompt_id: promptId });
} else {
Expand Down
32 changes: 23 additions & 9 deletions test/support/prompts-storage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -886,12 +886,14 @@ describe('prompts-storage', () => {
expect(result.updated).to.equal(1);
});

it('skips a deleted prompt matched by prompt_id without updating or inserting', async () => {
it('restores a soft-deleted prompt matched by prompt_id (update back to active, no insert)', async () => {
const deletedRow = {
id: 'row-uuid', prompt_id: 'del-1', text: 'Deleted text', regions: [], status: 'deleted',
};
const existingData = { data: [deletedRow], error: null };
const updateStub = sinon.stub().returns({ eq: () => thenable({ error: null }) });
const updateEqStub = sinon.stub().returns(thenable({ error: null }));
const updateStub = sinon.stub().returns({ eq: updateEqStub });
const insertSpy = sinon.stub().returns({ select: () => thenable({ data: [], error: null }) });
const client = {
from: (table) => {
if (table === 'prompts') {
Expand All @@ -904,7 +906,7 @@ describe('prompts-storage', () => {
}),
}),
}),
insert: () => ({ select: () => thenable({ data: [], error: null }) }),
insert: insertSpy,
update: updateStub,
};
}
Expand All @@ -917,20 +919,28 @@ describe('prompts-storage', () => {
prompts: [{ id: 'del-1', prompt: 'Deleted text', regions: [] }],
postgrestClient: client,
});
expect(result.updated).to.equal(0);
// Match on the soft-deleted row now updates it instead of skipping.
expect(result.updated).to.equal(1);
expect(result.created).to.equal(0);
expect(result.skipped).to.equal(1);
expect(updateStub.callCount).to.equal(0);
expect(result.skipped).to.equal(0);
expect(insertSpy.callCount).to.equal(0);
expect(updateStub.callCount).to.equal(1);
// The patch restores status to 'active'.
expect(updateStub.firstCall.args[0]).to.include({ status: 'active' });
// ...targeting the existing soft-deleted row by its uuid.
expect(updateEqStub.calledWith('id', 'row-uuid')).to.equal(true);
});

it('skips a deleted prompt matched by text+regions without inserting', async () => {
it('restores a soft-deleted prompt matched by text+regions (update back to active, no insert)', async () => {
const deletedRow = {
id: 'row-uuid', prompt_id: 'del-2', text: 'Same text', regions: ['us'], status: 'deleted',
};
const existingData = { data: [deletedRow], error: null };
const insertSpy = sinon.stub().returns({
select: () => thenable({ data: [], error: null }),
});
const updateEqStub = sinon.stub().returns(thenable({ error: null }));
const updateStub = sinon.stub().returns({ eq: updateEqStub });
const client = {
from: (table) => {
if (table === 'prompts') {
Expand All @@ -941,7 +951,7 @@ describe('prompts-storage', () => {
}),
}),
insert: insertSpy,
update: () => ({ eq: () => thenable({ error: null }) }),
update: updateStub,
};
}
return makeChain({});
Expand All @@ -954,9 +964,13 @@ describe('prompts-storage', () => {
prompts: [{ prompt: 'Same text', regions: ['us'] }],
postgrestClient: client,
});
expect(result.skipped).to.equal(1);
expect(result.updated).to.equal(1);
expect(result.created).to.equal(0);
expect(result.skipped).to.equal(0);
expect(insertSpy.callCount).to.equal(0);
expect(updateStub.callCount).to.equal(1);
expect(updateStub.firstCall.args[0]).to.include({ status: 'active' });
expect(updateEqStub.calledWith('id', 'row-uuid')).to.equal(true);
});

it('throws on insert error', async () => {
Expand Down
Loading