182 lines
4.5 KiB
TypeScript
182 lines
4.5 KiB
TypeScript
import { query } from '../db/client.js'
|
|
import type {
|
|
WebhookEventCreateInput,
|
|
WebhookEventListQueryInput,
|
|
WebhookEventUpdatePatch,
|
|
} from '../types/repository-inputs.js'
|
|
import type {
|
|
WebhookEventListQueryResult,
|
|
WebhookEventRow,
|
|
} from '../types/repository-rows.js'
|
|
|
|
export async function createWebhookEvent(input: WebhookEventCreateInput): Promise<WebhookEventRow | null> {
|
|
const result = await query<WebhookEventRow>(
|
|
`
|
|
INSERT INTO webhook_events (
|
|
provider,
|
|
platform,
|
|
shop_id,
|
|
shop_name,
|
|
event_type,
|
|
event_key,
|
|
signature_valid,
|
|
headers_json,
|
|
query_json,
|
|
body_json,
|
|
processed,
|
|
process_error,
|
|
related_order_id,
|
|
created_at
|
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9::jsonb, $10::jsonb, $11, $12, $13, $14)
|
|
RETURNING *
|
|
`,
|
|
[
|
|
input.provider,
|
|
input.platform,
|
|
input.shopId || '',
|
|
input.shopName || '',
|
|
input.eventType,
|
|
input.eventKey,
|
|
Boolean(input.signatureValid),
|
|
input.headersJson || '{}',
|
|
input.queryJson || '{}',
|
|
input.bodyJson || '{}',
|
|
Boolean(input.processed),
|
|
input.processError || '',
|
|
input.relatedOrderId || null,
|
|
input.createdAt,
|
|
],
|
|
)
|
|
|
|
return result.rows[0] || null
|
|
}
|
|
|
|
export async function updateWebhookEvent(
|
|
eventId: number | string,
|
|
patch: WebhookEventUpdatePatch,
|
|
): Promise<WebhookEventRow | null> {
|
|
const current = await getWebhookEventById(eventId)
|
|
if (!current) {
|
|
return null
|
|
}
|
|
|
|
const next = { ...current, ...patch }
|
|
const result = await query<WebhookEventRow>(
|
|
`
|
|
UPDATE webhook_events
|
|
SET
|
|
processed = $1,
|
|
process_error = $2,
|
|
related_order_id = $3
|
|
WHERE id = $4
|
|
RETURNING *
|
|
`,
|
|
[Boolean(next.processed), next.process_error || '', next.related_order_id || null, Number(eventId)],
|
|
)
|
|
|
|
return result.rows[0] || null
|
|
}
|
|
|
|
export async function getWebhookEventById(eventId: number | string): Promise<WebhookEventRow | null> {
|
|
const result = await query<WebhookEventRow>('SELECT * FROM webhook_events WHERE id = $1 LIMIT 1', [
|
|
Number(eventId),
|
|
])
|
|
return result.rows[0] || null
|
|
}
|
|
|
|
export async function listWebhookEvents({
|
|
page = 1,
|
|
pageSize = 20,
|
|
provider = '',
|
|
platform = '',
|
|
platformOrderId = '',
|
|
processed = '',
|
|
visibility = 'important',
|
|
relatedOrderId = '',
|
|
dateFrom = '',
|
|
dateTo = '',
|
|
}: WebhookEventListQueryInput = {}): Promise<WebhookEventListQueryResult> {
|
|
const offset = (page - 1) * pageSize
|
|
const filters: string[] = []
|
|
const params: unknown[] = []
|
|
|
|
if (provider) {
|
|
params.push(provider)
|
|
filters.push(`provider = $${params.length}`)
|
|
}
|
|
|
|
if (platform) {
|
|
params.push(platform)
|
|
filters.push(`platform = $${params.length}`)
|
|
}
|
|
|
|
if (platformOrderId) {
|
|
params.push(`%${platformOrderId}%`)
|
|
filters.push(`(event_key ILIKE $${params.length} OR body_json::text ILIKE $${params.length})`)
|
|
}
|
|
|
|
if (processed === '0' || processed === '1') {
|
|
params.push(processed === '1')
|
|
filters.push(`processed = $${params.length}`)
|
|
}
|
|
|
|
if (visibility === 'ignored') {
|
|
filters.push(`process_error LIKE 'ignored_%'`)
|
|
} else if (visibility === 'important') {
|
|
filters.push(`(process_error = '' OR process_error NOT LIKE 'ignored_%')`)
|
|
}
|
|
|
|
if (relatedOrderId) {
|
|
params.push(Number(relatedOrderId))
|
|
filters.push(`related_order_id = $${params.length}`)
|
|
}
|
|
|
|
if (dateFrom) {
|
|
params.push(dateFrom)
|
|
filters.push(`created_at >= $${params.length}`)
|
|
}
|
|
|
|
if (dateTo) {
|
|
params.push(dateTo)
|
|
filters.push(`created_at <= $${params.length}`)
|
|
}
|
|
|
|
const whereClause = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : ''
|
|
const totalResult = await query<{ [column: string]: unknown, total: number }>(
|
|
`SELECT COUNT(*)::int AS total FROM webhook_events ${whereClause}`,
|
|
params,
|
|
)
|
|
|
|
params.push(pageSize)
|
|
params.push(offset)
|
|
const itemsResult = await query<WebhookEventRow>(
|
|
`
|
|
SELECT *
|
|
FROM webhook_events
|
|
${whereClause}
|
|
ORDER BY id DESC
|
|
LIMIT $${params.length - 1} OFFSET $${params.length}
|
|
`,
|
|
params,
|
|
)
|
|
|
|
return {
|
|
items: itemsResult.rows,
|
|
total: Number(totalResult.rows[0]?.total || 0),
|
|
}
|
|
}
|
|
|
|
export async function listWebhookEventsByOrderId(orderId: number | string): Promise<WebhookEventRow[]> {
|
|
const result = await query<WebhookEventRow>(
|
|
`
|
|
SELECT *
|
|
FROM webhook_events
|
|
WHERE related_order_id = $1
|
|
ORDER BY id DESC
|
|
`,
|
|
[Number(orderId)],
|
|
)
|
|
|
|
return result.rows
|
|
}
|