diff --git a/src/server/db/campaigns.test.ts b/src/server/db/campaigns.test.ts index 74c475e..f25d59e 100644 --- a/src/server/db/campaigns.test.ts +++ b/src/server/db/campaigns.test.ts @@ -102,6 +102,13 @@ describe('updateCampaign', () => { const result = await updateCampaign('tenant1', 'uuid-1', {}) expect(result.ok).toBe(false) }) + + it('gibt err zurück wenn Kampagne nicht im Draft-Status', async () => { + mockClient.query.mockResolvedValueOnce([]) + const result = await updateCampaign('tenant1', 'uuid-1', { name: 'Neu' }) + expect(result.ok).toBe(false) + if (!result.ok) expect(result.error.message).toContain('Draft-Status') + }) }) describe('updateCampaignStatus', () => { @@ -119,4 +126,20 @@ describe('updateCampaignStatus', () => { const result = await updateCampaignStatus('tenant1', 'uuid-1', 'sent') expect(result.ok).toBe(false) }) + + it('setzt scheduledAt ohne cron_expression zu überschreiben', async () => { + const scheduled = new Date('2026-05-01T09:00:00Z') + mockClient.query.mockResolvedValueOnce([{ ...mockRow, status: 'scheduled', scheduled_at: scheduled }]) + const result = await updateCampaignStatus('tenant1', 'uuid-1', 'scheduled', { scheduledAt: scheduled }) + expect(result.ok).toBe(true) + expect(mockClient.query).toHaveBeenCalledWith( + expect.stringContaining('scheduled_at'), + expect.arrayContaining([scheduled]) + ) + // cron_expression darf NICHT im Query sein + expect(mockClient.query).not.toHaveBeenCalledWith( + expect.stringContaining('cron_expression'), + expect.anything() + ) + }) }) diff --git a/src/server/db/campaigns.ts b/src/server/db/campaigns.ts index 67bdfac..e723fff 100644 --- a/src/server/db/campaigns.ts +++ b/src/server/db/campaigns.ts @@ -99,12 +99,25 @@ export async function updateCampaignStatus( status: CampaignStatus, extra?: { scheduledAt?: Date; cronExpression?: string } ): Promise> { + const fields: string[] = ['status = $1'] + const values: unknown[] = [status] + let idx = 2 + + if (extra?.scheduledAt !== undefined) { + fields.push(`scheduled_at = $${idx++}`) + values.push(extra.scheduledAt) + } + if (extra?.cronExpression !== undefined) { + fields.push(`cron_expression = $${idx++}`) + values.push(extra.cronExpression) + } + + values.push(id) try { const rows = await withTenant(tenantId, (client) => client.query( - `UPDATE campaigns SET status = $1, scheduled_at = $2, cron_expression = $3 - WHERE id = $4 RETURNING *`, - [status, extra?.scheduledAt ?? null, extra?.cronExpression ?? null, id] + `UPDATE campaigns SET ${fields.join(', ')} WHERE id = $${idx} RETURNING *`, + values ) ) if (rows.length === 0) return err(new Error('Kampagne nicht gefunden'))