Deleting a digest makes it sendable again
The dispatch timestamp survived the deletion, so removing a message in Slack left the digest permanently swallowed. Deleting now rewinds the window to the newest digest that still stands.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { desc, eq, inArray } from 'drizzle-orm'
|
import { and, desc, eq, inArray, isNull } from 'drizzle-orm'
|
||||||
import { db } from '../db'
|
import { db } from '../db'
|
||||||
import { appSettings, reportRuns, type ReportRun } from '../schema'
|
import { appSettings, reportRuns, type ReportRun } from '../schema'
|
||||||
|
|
||||||
@@ -54,6 +54,17 @@ export async function markReportRunDeleted(id: string): Promise<void> {
|
|||||||
await db.update(reportRuns).set({ deletedAt: new Date() }).where(eq(reportRuns.id, id))
|
await db.update(reportRuns).set({ deletedAt: new Date() }).where(eq(reportRuns.id, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function findLatestSentRun(): Promise<ReportRun | undefined> {
|
||||||
|
const rows = await db
|
||||||
|
.select()
|
||||||
|
.from(reportRuns)
|
||||||
|
.where(and(eq(reportRuns.sent, true), isNull(reportRuns.deletedAt)))
|
||||||
|
.orderBy(desc(reportRuns.toAt))
|
||||||
|
.limit(1)
|
||||||
|
|
||||||
|
return rows[0]
|
||||||
|
}
|
||||||
|
|
||||||
export async function listReportRuns(limit: number): Promise<ReportRun[]> {
|
export async function listReportRuns(limit: number): Promise<ReportRun[]> {
|
||||||
return db.select().from(reportRuns).orderBy(desc(reportRuns.createdAt)).limit(limit)
|
return db.select().from(reportRuns).orderBy(desc(reportRuns.createdAt)).limit(limit)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { recordAudit } from '~/data/repositories/audit'
|
import { recordAudit } from '~/data/repositories/audit'
|
||||||
import {
|
import {
|
||||||
clearSetting,
|
clearSetting,
|
||||||
|
findLatestSentRun,
|
||||||
findReportRun,
|
findReportRun,
|
||||||
markReportRunDeleted,
|
markReportRunDeleted,
|
||||||
readSettings,
|
readSettings,
|
||||||
@@ -167,6 +168,14 @@ export async function performDeleteMessage(viewer: Viewer, formData: FormData):
|
|||||||
|
|
||||||
await markReportRunDeleted(run.id)
|
await markReportRunDeleted(run.id)
|
||||||
|
|
||||||
|
const previous = await findLatestSentRun()
|
||||||
|
|
||||||
|
if (previous) {
|
||||||
|
await writeSetting('slack.lastSentAt', previous.toAt.toISOString())
|
||||||
|
} else {
|
||||||
|
await clearSetting('slack.lastSentAt')
|
||||||
|
}
|
||||||
|
|
||||||
await recordAudit({
|
await recordAudit({
|
||||||
actorId: viewer.id,
|
actorId: viewer.id,
|
||||||
actorLabel: viewer.email,
|
actorLabel: viewer.email,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { db } from '~/data/db'
|
|||||||
import { appSettings } from '~/data/schema'
|
import { appSettings } from '~/data/schema'
|
||||||
import { listReportRuns, writeSetting } from '~/data/repositories/settings'
|
import { listReportRuns, writeSetting } from '~/data/repositories/settings'
|
||||||
import { readSlackConfig, reportScope, runWeeklyReport } from '~/lib/report-settings'
|
import { readSlackConfig, reportScope, runWeeklyReport } from '~/lib/report-settings'
|
||||||
|
import { performDeleteMessage } from '~/lib/admin-settings'
|
||||||
import { makeBrand, makeProject } from '../support/admin'
|
import { makeBrand, makeProject } from '../support/admin'
|
||||||
import { makePost } from '../support/entries'
|
import { makePost } from '../support/entries'
|
||||||
|
|
||||||
@@ -129,10 +130,10 @@ describe('Doppelter Versand', () => {
|
|||||||
|
|
||||||
await makePost(project.id, { number: 1, slug: 'eins', status: 'published', publishAt: new Date() })
|
await makePost(project.id, { number: 1, slug: 'eins', status: 'published', publishAt: new Date() })
|
||||||
await writeSetting('slack.botToken', 'xoxb-1234')
|
await writeSetting('slack.botToken', 'xoxb-1234')
|
||||||
await writeSetting('slack.channel', 'C123')
|
await writeSetting('slack.channel', 'C0123456')
|
||||||
|
|
||||||
vi.stubGlobal('fetch', vi.fn(async () => new Response(
|
vi.stubGlobal('fetch', vi.fn(async () => new Response(
|
||||||
JSON.stringify({ ok: true, channel: 'C123', ts: '1785600000.000100' }),
|
JSON.stringify({ ok: true, channel: 'C0123456', ts: '1785600000.000100' }),
|
||||||
{ headers: { 'content-type': 'application/json' } },
|
{ headers: { 'content-type': 'application/json' } },
|
||||||
)))
|
)))
|
||||||
|
|
||||||
@@ -143,3 +144,37 @@ describe('Doppelter Versand', () => {
|
|||||||
expect(second.reason).toBe('nothing_published')
|
expect(second.reason).toBe('nothing_published')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Löschen nimmt den Versand zurück', () => {
|
||||||
|
it('macht den Bericht nach dem Löschen wieder sendbar', async () => {
|
||||||
|
const brand = await makeBrand()
|
||||||
|
const project = await makeProject(brand.id)
|
||||||
|
|
||||||
|
await makePost(project.id, { number: 1, slug: 'eins', status: 'published', publishAt: new Date() })
|
||||||
|
await writeSetting('slack.botToken', 'xoxb-1234')
|
||||||
|
await writeSetting('slack.channel', 'C0123456')
|
||||||
|
|
||||||
|
vi.stubGlobal('fetch', vi.fn(async () => new Response(
|
||||||
|
JSON.stringify({ ok: true, channel: 'C0123456', ts: '1785600000.000100' }),
|
||||||
|
{ headers: { 'content-type': 'application/json' } },
|
||||||
|
)))
|
||||||
|
|
||||||
|
const first = await runWeeklyReport({ origin, trigger: 'test' })
|
||||||
|
|
||||||
|
expect(first.reason).toBe('sent')
|
||||||
|
expect((await runWeeklyReport({ origin, trigger: 'test' })).reason).toBe('nothing_published')
|
||||||
|
|
||||||
|
const form = new FormData()
|
||||||
|
|
||||||
|
form.set('runId', first.run.id)
|
||||||
|
|
||||||
|
const deleted = await performDeleteMessage(
|
||||||
|
{ id: 'u1', name: 'Admin', email: '[email protected]', isAdmin: true, assignments: [] },
|
||||||
|
form,
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(deleted.message).toBe('messageDeleted')
|
||||||
|
expect(deleted.status).toBe('ok')
|
||||||
|
expect((await runWeeklyReport({ origin, trigger: 'test' })).reason).toBe('sent')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user