Merge branch 'main' into dev_match
This commit is contained in:
@@ -11,3 +11,21 @@ test('客服我的钱包展示统一结算虚拟账单入口', async () => {
|
||||
assert.ok(source.includes('生成虚拟账单,不扣积分或备用金'))
|
||||
assert.ok(source.includes('support-wallet-grid'))
|
||||
})
|
||||
|
||||
test('客服钱包提供统一结算待对账列表和实际金额确认', async () => {
|
||||
const [source, service, confirmModal] = await Promise.all([
|
||||
readFile(new URL('../src/pages/admin/fund/FundSupportView.tsx', import.meta.url), 'utf8'),
|
||||
readFile(new URL('../src/services/admin/cost-center.ts', import.meta.url), 'utf8'),
|
||||
readFile(
|
||||
new URL('../src/components/admin/ManualFulfillmentConfirmModal.tsx', import.meta.url),
|
||||
'utf8',
|
||||
),
|
||||
])
|
||||
|
||||
assert.ok(source.includes('统一结算待对账'))
|
||||
assert.ok(source.includes('实际结算金额(元)'))
|
||||
assert.ok(source.includes('确认对账'))
|
||||
assert.ok(confirmModal.includes('costPending'))
|
||||
assert.ok(service.includes('/api/v1/admin/finance/on-account-bills'))
|
||||
assert.ok(service.includes('/reconcile'))
|
||||
})
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import test from 'node:test'
|
||||
|
||||
test('快手电子凭证页提供受控的历史券补发并核销入口', () => {
|
||||
const page = readFileSync(
|
||||
new URL('../src/pages/admin/AdminKuaishouIndustryPage.tsx', import.meta.url).pathname,
|
||||
'utf8',
|
||||
)
|
||||
const service = readFileSync(
|
||||
new URL('../src/services/admin/kuaishou-industry.ts', import.meta.url).pathname,
|
||||
'utf8',
|
||||
)
|
||||
|
||||
assert.ok(page.includes('历史补发并核销'), '页面必须提供补发并核销按钮')
|
||||
assert.ok(page.includes('reissueAndConsumeAdminKuaishouIndustryVoucher'), '页面必须调用专用接口')
|
||||
assert.ok(page.includes('reissueConsumeOpen'), '操作必须通过确认弹窗执行')
|
||||
assert.ok(page.includes('reissueConsumeConfirmed'), '提交前必须显式勾选确认')
|
||||
assert.ok(page.includes('临时有效期(分钟)'), '必须允许设置短期临时有效期')
|
||||
assert.ok(
|
||||
page.includes("source: 'admin_historical_reissue_consume'") === false,
|
||||
'前端不能伪造核销来源',
|
||||
)
|
||||
|
||||
assert.ok(
|
||||
service.includes('/api/v1/admin/kuaishou-industry/vouchers/reissue-consume'),
|
||||
'必须调用后端补发并核销接口',
|
||||
)
|
||||
})
|
||||
|
||||
test('历史券补发并核销结果必须展示发码、核销两个阶段', () => {
|
||||
const page = readFileSync(
|
||||
new URL('../src/pages/admin/AdminKuaishouIndustryPage.tsx', import.meta.url).pathname,
|
||||
'utf8',
|
||||
)
|
||||
|
||||
assert.ok(page.includes("kind === 'reissue-consume'"), '结果视图必须识别补发并核销动作')
|
||||
assert.ok(
|
||||
page.includes("...(kind === 'reissue-consume' ? [record.error] : [])"),
|
||||
'核销阶段失败时必须优先展示消费错误,而不是发码成功的 success 响应',
|
||||
)
|
||||
assert.ok(page.includes("['发码成功', record.sendSuccess]"), '结果必须展示发码阶段状态')
|
||||
assert.ok(page.includes("['核销成功', record.consumeSuccess]"), '结果必须展示核销阶段状态')
|
||||
assert.ok(page.includes("pushHighlight(highlights, '补发原因'"), '结果必须展示补偿原因')
|
||||
})
|
||||
@@ -8,10 +8,56 @@ test('人工成本配置直接展示标准商品,不再要求按日期扫描
|
||||
'utf8',
|
||||
)
|
||||
|
||||
assert.ok(source.includes('人工标准商品与成本配置一一对应'))
|
||||
assert.ok(source.includes('人工标准商品由人工配置自动创建'))
|
||||
assert.ok(source.includes("title: '人工标准商品'"))
|
||||
assert.ok(source.includes('SKU:{row.skuKey}'))
|
||||
assert.ok(!source.includes('扫描内部 SKU'))
|
||||
assert.ok(!source.includes('DatePicker.RangePicker'))
|
||||
assert.ok(!source.includes('rematchAdminManualFulfillments'))
|
||||
})
|
||||
|
||||
test('新增人工 SKU 直接保存配置,由后端自动创建标准商品', async () => {
|
||||
const source = await readFile(
|
||||
new URL('../src/pages/admin/cost-center/ManualSkuConfigPanel.tsx', import.meta.url),
|
||||
'utf8',
|
||||
)
|
||||
|
||||
assert.ok(source.includes('新增人工 SKU'))
|
||||
assert.ok(source.includes('openCreateConfig'))
|
||||
assert.ok(source.includes('name="skuKey"'))
|
||||
assert.ok(source.includes('保存时自动创建标准商品'))
|
||||
assert.ok(source.includes('manualSku'))
|
||||
assert.ok(source.includes("returnTo.startsWith('/admin/fulfillment-channel')"))
|
||||
})
|
||||
|
||||
test('人工商品不再允许手工创建或执行旧批量归档', async () => {
|
||||
const [productSource, serviceSource, queueSource, shellSource] = await Promise.all([
|
||||
readFile(
|
||||
new URL('../src/pages/admin/cost-center/ProductCatalogPanel.tsx', import.meta.url),
|
||||
'utf8',
|
||||
),
|
||||
readFile(
|
||||
new URL('../../backend/src/services/cost-center/product-catalog-service.ts', import.meta.url),
|
||||
'utf8',
|
||||
),
|
||||
readFile(
|
||||
new URL('../src/pages/admin/AdminFulfillmentChannelPage.tsx', import.meta.url),
|
||||
'utf8',
|
||||
),
|
||||
readFile(
|
||||
new URL('../src/pages/admin/cost-center/CostCenterShell.tsx', import.meta.url),
|
||||
'utf8',
|
||||
),
|
||||
])
|
||||
|
||||
assert.ok(!productSource.includes('归档跨渠道重复商品'))
|
||||
assert.ok(!productSource.includes('归档纯历史人工商品'))
|
||||
assert.ok(productSource.includes("productSourceFilter === 'manual'"))
|
||||
assert.ok(productSource.includes('manualNew=1'))
|
||||
assert.ok(productSource.includes('人工标准商品由人工 SKU 配置自动创建'))
|
||||
assert.ok(serviceSource.includes('cost_manual_product_managed_by_config'))
|
||||
assert.ok(queueSource.includes('manualSku=${encodeURIComponent(sku)}'))
|
||||
assert.ok(queueSource.includes("returnTo=${encodeURIComponent('/admin/fulfillment-channel')}"))
|
||||
assert.ok(shellSource.includes("searchParams.get('scope')"))
|
||||
assert.ok(shellSource.includes("searchParams.get('tab')"))
|
||||
})
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import test from 'node:test'
|
||||
|
||||
test('自动核销最近任务展示并搜索核销码', () => {
|
||||
const page = readFileSync(
|
||||
new URL('../src/pages/admin/panels/VoucherConsumePolicyPanel.tsx', import.meta.url).pathname,
|
||||
'utf8',
|
||||
)
|
||||
const service = readFileSync(
|
||||
new URL('../src/services/admin/fulfillment-channel.ts', import.meta.url).pathname,
|
||||
'utf8',
|
||||
)
|
||||
|
||||
assert.ok(page.includes("title: '核销码'"), '最近核销任务必须展示核销码列')
|
||||
assert.ok(page.includes('copyable={{ text: code }}'), '核销码必须支持一键复制')
|
||||
assert.ok(page.includes('任务号 / 订单号 / 平台单号 / 核销码'), '搜索框必须明确支持核销码')
|
||||
assert.ok(service.includes('voucher_codes: string[]'), '任务接口类型必须包含核销码数组')
|
||||
})
|
||||
@@ -8,7 +8,7 @@ const panel = readFileSync(
|
||||
)
|
||||
|
||||
test('最近核销任务提供关键词、平台、渠道和状态筛选', () => {
|
||||
assert.ok(panel.includes('placeholder="任务号 / 订单号 / 平台单号"'))
|
||||
assert.ok(panel.includes('placeholder="任务号 / 订单号 / 平台单号 / 核销码"'))
|
||||
assert.ok(panel.includes('placeholder="全部平台"'))
|
||||
assert.ok(panel.includes('placeholder="全部渠道"'))
|
||||
assert.ok(panel.includes('placeholder="全部状态"'))
|
||||
|
||||
@@ -19,3 +19,30 @@ test('第三方卡券面板提供安全删除入口并格式化生效时间', as
|
||||
assert.ok(service.includes('/api/v1/admin/cost-center/voucher-products/${productId}'))
|
||||
assert.ok(service.includes("action: 'deleted' | 'archived'"))
|
||||
})
|
||||
|
||||
test('第三方卡券新增 SKU 一次完成商品、规则和采购价', async () => {
|
||||
const [panel, service, productCatalog] = await Promise.all([
|
||||
readFile(
|
||||
new URL('../src/pages/admin/cost-center/VoucherSkuPanel.tsx', import.meta.url),
|
||||
'utf8',
|
||||
),
|
||||
readFile(new URL('../src/services/admin/cost-center.ts', import.meta.url), 'utf8'),
|
||||
readFile(
|
||||
new URL('../src/pages/admin/cost-center/ProductCatalogPanel.tsx', import.meta.url),
|
||||
'utf8',
|
||||
),
|
||||
])
|
||||
|
||||
assert.ok(panel.includes('新增卡券 SKU'))
|
||||
assert.ok(panel.includes('saveAdminVoucherProduct'))
|
||||
assert.ok(panel.includes('保存后自动生成 tpv:<内部 SKU> 标准商品和卡券渠道规则'))
|
||||
assert.ok(panel.includes('补建成本快照'))
|
||||
assert.ok(!panel.includes('批量生成渠道规则'))
|
||||
assert.ok(!panel.includes('ensureVoucherChannelRules'))
|
||||
assert.ok(service.includes('apiPost<'))
|
||||
assert.ok(service.includes("'/api/v1/admin/cost-center/voucher-products'"))
|
||||
assert.ok(!service.includes('/voucher-products/ensure-rules'))
|
||||
assert.ok(panel.includes("searchParams.get('voucherNew')"))
|
||||
assert.ok(productCatalog.includes("productSourceFilter === 'third_party_voucher'"))
|
||||
assert.ok(productCatalog.includes('voucherNew=1'))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user