import assert from 'node:assert/strict' import process from 'node:process' import { closeDb, query } from '../src/db/client.js' import { WORK_ORDER_STATUS } from '../src/domain/work-order-status.js' import { createWorkOrder } from '../src/repositories/worker-platform/work-order-management-repo.js' import type { WorkOrderRow } from '../src/repositories/worker-platform/types.js' import { publishAdminOrderServiceProfile, saveAdminOrderServiceProfile, type OrderServiceProfileConfig, } from '../src/services/worker-platform/order-service-profile-service.js' import { getOrderServiceByPlatformOrderId, submitOrderServiceMaterial, } from '../src/services/worker-platform/order-service-public-service.js' import { processDueOrderServiceAutoPublishJobs } from '../src/services/worker-platform/order-service-auto-publish-service.js' import { randomId } from '../src/utils/random.js' import { nowIso } from '../src/utils/time.js' if (process.env.ORDER_SERVICE_SMOKE !== '1') { throw new Error('请显式设置 ORDER_SERVICE_SMOKE=1 后运行;该脚本只用于本地测试库') } const categoryId = Number(process.env.ORDER_SERVICE_SMOKE_CATEGORY_ID || 1) const platformOrderId = `SMOKE-${Date.now()}` let workOrder: WorkOrderRow | null = null let originalProfile: { id: number name: string title: string description: string guideImage: Record fields: OrderServiceProfileConfig['fields'] screenshots: OrderServiceProfileConfig['screenshots'] autoPublish: OrderServiceProfileConfig['autoPublish'] submitText: string successText: string } | null = null try { const profileResult = await query<{ id: number name: string title: string description: string guide_image_json: Record fields_json: OrderServiceProfileConfig['fields'] screenshots_json: Record auto_publish_json: Record submit_text: string success_text: string current_version_id: number }>( ` SELECT p.* FROM order_service_profiles p WHERE p.category_id = $1 AND p.current_version_id IS NOT NULL LIMIT 1 `, [categoryId], ) const profile = profileResult.rows[0] assert.ok(profile, '测试分类缺少已发布订单服务配置') originalProfile = { id: Number(profile.id), name: profile.name, title: profile.title, description: profile.description, guideImage: profile.guide_image_json, fields: profile.fields_json, screenshots: profile.screenshots_json as OrderServiceProfileConfig['screenshots'], autoPublish: profile.auto_publish_json as OrderServiceProfileConfig['autoPublish'], submitText: profile.submit_text, successText: profile.success_text, } const smokeFields: OrderServiceProfileConfig['fields'] = [ { key: 'account', label: '游戏账号', type: 'text', required: true, placeholder: '请输入账号', helpText: '', options: [], sortOrder: 10, }, ] const saved = await saveAdminOrderServiceProfile({ categoryId, name: '本地订单服务烟测', title: '本地订单服务烟测', description: '测试完成后自动恢复', guideImage: {}, fields: smokeFields, screenshots: { enabled: false, required: false, minCount: 0, maxCount: 3, label: '截图', helpText: '', }, autoPublish: { enabled: true, requireVoucherConsume: true, retryMax: 1, }, submitText: '提交烟测资料', successText: '烟测资料已提交', }) const draftStatus = await query<{ status: string }>( `SELECT status FROM order_service_profiles WHERE id = $1`, [saved.profile.id], ) assert.equal(draftStatus.rows[0]?.status, 'draft') const stillPublished = await getPublishedProfile(categoryId) assert.equal(stillPublished.title, originalProfile.title) const published = await publishAdminOrderServiceProfile(saved.profile.id) const publishedConfig = await getPublishedProfile(categoryId) assert.equal(publishedConfig.title, '本地订单服务烟测') workOrder = await createWorkOrder({ workOrderNo: `WKSMOKE${Date.now()}`, platformOrderId, productName: '订单服务烟测商品', categoryId, status: WORK_ORDER_STATUS.PENDING_MATERIAL, rewardAmount: 100, requiredDepositAmount: 0, depositThresholdAmount: 0, sharingEnabled: false, sharingTotalQuantity: 1, sharingUnitReward: 0, timeoutMinutes: 30, timeoutPolicy: 'reopen', acceptanceMode: 'standard', materialJson: JSON.stringify({ source: { smoke: true } }), requirementJson: JSON.stringify({ fields: smokeFields }), serviceProfileId: saved.profile.id, serviceProfileVersionId: published.versionId, serviceProfileSnapshotJson: JSON.stringify({ profileId: saved.profile.id, categoryId, versionId: published.versionId, versionNo: published.versionNo, config: publishedConfig, }), now: nowIso(), }) assert.ok(workOrder, '创建烟测工单失败') const publicInfo = await getOrderServiceByPlatformOrderId(platformOrderId) assert.equal(publicInfo.items[0]?.title, '本地订单服务烟测') assert.equal(publicInfo.items[0]?.canSubmit, true) await saveAdminOrderServiceProfile({ categoryId, name: '未发布修改', title: '未发布修改不应泄漏', description: 'draft-only', guideImage: {}, fields: smokeFields, screenshots: { enabled: false, required: false, minCount: 0, maxCount: 3, label: '截图', helpText: '', }, autoPublish: { enabled: true, requireVoucherConsume: true, retryMax: 1, }, submitText: '不应泄漏', successText: '不应泄漏', }) const afterDraftEdit = await getOrderServiceByPlatformOrderId(platformOrderId) assert.equal(afterDraftEdit.items[0]?.title, '本地订单服务烟测') await submitOrderServiceMaterial(platformOrderId, { workOrderId: workOrder.id, fields: { account: 'smoke-account' }, screenshots: [], }) await assert.rejects(() => submitOrderServiceMaterial(platformOrderId, { workOrderId: workOrder?.id, fields: { account: 'changed' }, screenshots: [], }), ) await waitForAutoPublishJob(workOrder.id) const afterPublish = await getOrderServiceByPlatformOrderId(platformOrderId) assert.equal(afterPublish.items[0]?.state, WORK_ORDER_STATUS.OPEN) assert.match(afterPublish.items[0]?.message || '', /高峰期/) const job = await query<{ status: string; attempt_count: number }>( `SELECT status, attempt_count FROM order_service_auto_publish_jobs WHERE work_order_id = $1`, [workOrder.id], ) assert.equal(job.rows[0]?.status, 'succeeded') console.log( JSON.stringify( { ok: true, categoryId, profileId: saved.profile.id, versionNo: published.versionNo, platformOrderId, finalStatus: afterPublish.items[0]?.state, finalMessage: afterPublish.items[0]?.message, }, null, 2, ), ) } finally { if (workOrder) { await query('DELETE FROM work_orders WHERE id = $1', [workOrder.id]).catch(() => undefined) } if (originalProfile) { const restored = await saveAdminOrderServiceProfile({ categoryId, name: originalProfile.name, title: originalProfile.title, description: originalProfile.description, guideImage: originalProfile.guideImage, fields: originalProfile.fields, screenshots: originalProfile.screenshots, autoPublish: originalProfile.autoPublish, submitText: originalProfile.submitText, successText: originalProfile.successText, }).catch(() => null) if (restored) { await publishAdminOrderServiceProfile(restored.profile.id).catch(() => undefined) } } await closeDb() } async function getPublishedProfile(categoryIdValue: number) { const result = await query<{ config_json: OrderServiceProfileConfig }>( ` SELECT v.config_json FROM order_service_profiles p JOIN order_service_profile_versions v ON v.id = p.current_version_id WHERE p.category_id = $1 LIMIT 1 `, [categoryIdValue], ) const config = result.rows[0]?.config_json assert.ok(config, '未找到已发布订单服务配置') return config } async function waitForAutoPublishJob(workOrderId: number) { const deadline = Date.now() + 5_000 while (Date.now() < deadline) { await Promise.all([ processDueOrderServiceAutoPublishJobs(10), processDueOrderServiceAutoPublishJobs(10), ]) const result = await query<{ status: string }>( `SELECT status FROM order_service_auto_publish_jobs WHERE work_order_id = $1`, [workOrderId], ) const status = result.rows[0]?.status if (status === 'succeeded' || status === 'failed' || status === 'skipped') return await new Promise((resolve) => setTimeout(resolve, 100)) } throw new Error('自动发布任务在 5 秒内未结束') }