发送消息ok

This commit is contained in:
yml
2026-04-12 13:48:32 +08:00
parent 0029147bc4
commit 381d18f3c9
11 changed files with 608 additions and 4 deletions
@@ -115,3 +115,92 @@ export async function findLatestSuccessfulMessageDeliveryByTask(taskId, channel)
return result.rows[0] || null
}
export async function listMessageDeliveries({
page = 1,
pageSize = 20,
provider = '',
platform = '',
status = '',
shopId = '',
platformOrderId = '',
taskNo = '',
dateFrom = '',
dateTo = '',
} = {}) {
const offset = (page - 1) * pageSize
const filters = []
const params = []
if (provider) {
params.push(provider)
filters.push(`md.provider = $${params.length}`)
}
if (platform) {
params.push(platform)
filters.push(`md.platform = $${params.length}`)
}
if (status) {
params.push(status)
filters.push(`md.status = $${params.length}`)
}
if (shopId) {
params.push(shopId)
filters.push(`md.shop_id = $${params.length}`)
}
if (platformOrderId) {
params.push(`%${platformOrderId}%`)
filters.push(`md.platform_order_id ILIKE $${params.length}`)
}
if (taskNo) {
params.push(`%${taskNo}%`)
filters.push(`ft.task_no ILIKE $${params.length}`)
}
if (dateFrom) {
params.push(dateFrom)
filters.push(`md.created_at >= $${params.length}`)
}
if (dateTo) {
params.push(dateTo)
filters.push(`md.created_at <= $${params.length}`)
}
const whereClause = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : ''
const fromClause = `
FROM message_deliveries md
LEFT JOIN fulfillment_tasks ft ON ft.id = md.task_id
`
const totalResult = await query(
`SELECT COUNT(*)::int AS total ${fromClause} ${whereClause}`,
params,
)
params.push(pageSize)
params.push(offset)
const itemsResult = await query(
`
SELECT
md.*,
ft.task_no,
ft.task_status
${fromClause}
${whereClause}
ORDER BY md.id DESC
LIMIT $${params.length - 1} OFFSET $${params.length}
`,
params,
)
return {
items: itemsResult.rows,
total: Number(totalResult.rows[0]?.total || 0),
}
}
+2
View File
@@ -4,6 +4,7 @@ import authRouter from './admin/auth.js'
import auditLogsRouter from './admin/audit-logs.js'
import dashboardRouter from './admin/dashboard.js'
import inventoryRouter from './admin/inventory.js'
import messageDeliveriesRouter from './admin/message-deliveries.js'
import ordersRouter from './admin/orders.js'
import platformConfigRouter from './admin/platform-config.js'
import { requireAdminSession } from './admin/shared.js'
@@ -23,6 +24,7 @@ router.use(platformConfigRouter)
router.use(ordersRouter)
router.use(tasksRouter)
router.use(inventoryRouter)
router.use(messageDeliveriesRouter)
router.use(webhookEventsRouter)
router.use((req, res) => {
@@ -0,0 +1,17 @@
import { Router } from 'express'
import { getAdminMessageDeliveries } from '../../services/admin/admin-service.js'
import { createJsonHandler } from './shared.js'
const router = Router()
router.get('/message-deliveries', createJsonHandler(
(req) => getAdminMessageDeliveries(req.query),
{
successMessage: 'ok',
errorMessage: '读取消息发送记录失败',
scope: '[admin/message-deliveries]',
},
))
export default router
@@ -32,6 +32,7 @@ import {
} from '../../repositories/task-inventory-binding-repo.js'
import { createTaskEvent, listTaskEventsByTaskId } from '../../repositories/task-event-repo.js'
import { getWebhookEventById, listWebhookEvents, listWebhookEventsByOrderId } from '../../repositories/webhook-event-repo.js'
import { listMessageDeliveries } from '../../repositories/message-delivery-repo.js'
import { createHttpError } from '../../utils/http.js'
import { formatFenToAmount, normalizeFen, parseAmountToFen } from '../../utils/money.js'
import { nowIso } from '../../utils/time.js'
@@ -197,6 +198,28 @@ export async function getAdminTasks(query = {}) {
}
}
export async function getAdminMessageDeliveries(query = {}) {
const page = normalizePage(query.page)
const pageSize = normalizePageSize(query.pageSize)
const { items, total } = await listMessageDeliveries({
page,
pageSize,
provider: String(query.provider || '').trim(),
platform: String(query.platform || '').trim(),
status: String(query.status || '').trim(),
shopId: String(query.shopId || '').trim(),
platformOrderId: String(query.platformOrderId || '').trim(),
taskNo: String(query.taskNo || '').trim(),
dateFrom: normalizeDateQuery(query.dateFrom),
dateTo: normalizeDateQuery(query.dateTo, true),
})
return {
items: items.map(mapAdminMessageDeliveryListItem),
pagination: { page, pageSize, total },
}
}
export async function getAdminTaskDetail(taskId) {
const task = await getTaskById(Number(taskId))
@@ -1103,6 +1126,33 @@ function mapAdminFulfillmentBindingConfigItem(item) {
}
}
function mapAdminMessageDeliveryListItem(item) {
return {
deliveryId: Number(item.id),
provider: String(item.provider || '').trim(),
platform: String(item.platform || '').trim(),
shopId: String(item.shop_id || '').trim(),
shopName: String(item.shop_name || '').trim(),
channel: String(item.channel || '').trim(),
orderId: item.order_id ? Number(item.order_id) : null,
taskId: item.task_id ? Number(item.task_id) : null,
taskNo: String(item.task_no || '').trim(),
taskStatus: String(item.task_status || '').trim(),
platformOrderId: String(item.platform_order_id || '').trim(),
recipientKey: String(item.recipient_key || '').trim(),
messageContent: String(item.message_content || '').trim(),
claimUrl: String(item.claim_url || '').trim(),
status: String(item.status || '').trim(),
requestUrl: String(item.request_url || '').trim(),
responseStatus: Number(item.response_status || 0),
response: safeParseJson(item.response_json),
errorMessage: String(item.error_message || '').trim(),
sentAt: item.sent_at || null,
createdAt: item.created_at,
updatedAt: item.updated_at,
}
}
function matchesObservedProduct(binding, observed) {
const provider = String(binding?.provider || '').trim()
const platform = String(binding?.platform || '').trim()
@@ -28,7 +28,7 @@ export async function ensureAgisoXianyuClaimMessageDeliveredForTask({ order, tas
return { sent: false, skipped: true, reason: 'missing_endpoint_or_access_token_or_app_secret' }
}
const successful = findLatestSuccessfulMessageDeliveryByTask(task.id, AGISO_XIANYU_MESSAGE_CHANNEL)
const successful = await findLatestSuccessfulMessageDeliveryByTask(task.id, AGISO_XIANYU_MESSAGE_CHANNEL)
if (successful) {
return { sent: false, skipped: true, reason: 'already_sent', deliveryId: successful.id }
}
@@ -52,7 +52,7 @@ export async function ensureAgisoXianyuClaimMessageDeliveredForTask({ order, tas
apiVersion: String(config.apiVersion || '1').trim() || '1',
})
const createdAt = nowIso()
const delivery = createMessageDelivery({
const delivery = await createMessageDelivery({
provider: 'agiso',
platform: String(order.platform || '').trim() || 'unknown',
shopId: String(order.shop_id || '').trim(),
@@ -85,7 +85,7 @@ export async function ensureAgisoXianyuClaimMessageDeliveredForTask({ order, tas
const rawText = await response.text()
const parsed = safeParseJson(rawText)
const success = isAgisoSendSuccess(response.status, parsed)
const updated = updateMessageDelivery(delivery.id, {
const updated = await updateMessageDelivery(delivery.id, {
status: success ? 'success' : 'failed',
response_status: response.status,
response_json: JSON.stringify(parsed ?? { rawText }),
@@ -104,7 +104,7 @@ export async function ensureAgisoXianyuClaimMessageDeliveredForTask({ order, tas
}
} catch (error) {
const message = error instanceof Error ? error.message : String(error || '发送消息失败')
updateMessageDelivery(delivery.id, {
await updateMessageDelivery(delivery.id, {
status: 'failed',
response_status: 0,
response_json: '{}',