优化
This commit is contained in:
@@ -12,7 +12,7 @@ import process from 'node:process'
|
||||
const DEFAULT_GATEWAY = 'http://8.163.30.128:9000'
|
||||
const DEFAULT_USERNAME = 'platform_admin'
|
||||
const DEFAULT_PASSWORD = 'ChangeMe123!'
|
||||
const DEFAULT_MODULES = ['customers', 'overseas-storage-fees', 'system', 'master-data', 'suppliers', 'domestic-container', 'orders', 'fee-items', 'pricing', 'downloads', 'inbound-weight-ocr', 'inbound-measurement', 'phase3-container-loading', 'phase3-loading', 'phase3-loading-model-bridge', 'phase3-pda-convergence', 'phase3-evidence-gate', 'supplemental', 'supplemental-boundaries', 'ocean-bookings', 'truck-appointments', 'service-center-flow', 'phase3-customs', 'phase3-port-schedules', 'phase3-carrier-schedule-queries', 'phase3-loading-finalize', 'phase3-outbound-dispatch', 'phase3-outbound-aggregate', 'phase3-dispatch-gate', 'phase3-waiting-for-loading', 'phase3-warehouse-rbac', 'phase3-order-splitting', 'manual-state-matrix', 'finance', 'finance-full-fixtures', 'finance-reconciliation-full', 'finance-settlement-full']
|
||||
const DEFAULT_MODULES = ['customers', 'overseas-storage-fees', 'system', 'master-data', 'suppliers', 'domestic-container', 'orders', 'fee-items', 'pricing', 'downloads', 'inbound-weight-ocr', 'inbound-measurement', 'phase3-container-loading', 'phase3-loading', 'phase3-loading-model-bridge', 'phase3-pda-convergence', 'phase3-evidence-gate', 'supplemental', 'supplemental-boundaries', 'ocean-bookings', 'truck-appointments', 'service-center-flow', 'phase3-customs', 'phase3-port-schedules', 'phase3-carrier-schedule-queries', 'phase3-loading-finalize', 'phase3-outbound-dispatch', 'phase3-outbound-aggregate', 'phase3-dispatch-gate', 'phase3-waiting-for-loading', 'phase3-warehouse-rbac', 'phase3-order-splitting', 'manual-state-matrix', 'finance', 'finance-full-fixtures', 'finance-reconciliation-full', 'finance-settlement-full', 'customer-operating-statistics']
|
||||
const WEIGHT_IMAGE_PATH = 'C:/Users/BY-OY/Desktop/上传图片包/测量图片/测量图片/orig_1cf27695-b2c3-44b3-98e3-c0be8b80f79a.JPG'
|
||||
const CUSTOMER_FIELDS = [
|
||||
'id', 'tenantCode', 'tenantName', 'status', 'legalName', 'legalRepresentative',
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
const MODULE = 'customer-operating-statistics'
|
||||
const OPTIONS = { scenario: 'customer-detail-operating-statistics', deploymentBlocker: true }
|
||||
|
||||
function id(value) { return value == null ? '' : String(value) }
|
||||
function decimal(value) { return typeof value === 'number' || (typeof value === 'string' && /^-?\d+(\.\d+)?$/.test(value)) }
|
||||
function nonNegative(value) { return decimal(value) && Number(value) >= 0 }
|
||||
|
||||
export async function run(context) {
|
||||
const customerId = id(context.context.customerId || context.createdResources.customer?.tenantId)
|
||||
context.assert(MODULE, '取得客户详情统计客户隔离键', null, Boolean(customerId), `customerId=${customerId || 'missing'}`, OPTIONS)
|
||||
if (!customerId) return
|
||||
|
||||
const orderPath = `/api/platform/v1/orders/first-leg/tenant-statistics?tenantId=${encodeURIComponent(customerId)}`
|
||||
const orderResponse = await context.request('GET', orderPath)
|
||||
const orders = context.apiSuccess(MODULE, '查询累计与本月已提交主运单统计', orderResponse, `customerId=${customerId}`, OPTIONS)
|
||||
context.assert(MODULE, '运单统计返回上海时区半开月份边界与客户隔离键', orderResponse,
|
||||
id(orders?.tenantId) === customerId && nonNegative(orders?.totalSubmittedOrders)
|
||||
&& nonNegative(orders?.currentMonthSubmittedOrders) && orders?.zoneId === 'Asia/Shanghai'
|
||||
&& Boolean(orders?.monthStart) && Boolean(orders?.nextMonthStart) && Boolean(orders?.asOf),
|
||||
`tenantId=${id(orders?.tenantId) || 'missing'}, zoneId=${orders?.zoneId || 'missing'}`, OPTIONS)
|
||||
|
||||
const financePath = `/api/platform/finance/v1/customer-accounts/${encodeURIComponent(customerId)}/summary`
|
||||
const financeResponse = await context.request('GET', financePath)
|
||||
const finance = context.apiSuccess(MODULE, '查询非VOIDED正式结算应收汇总', financeResponse, `customerId=${customerId}`, OPTIONS)
|
||||
context.assert(MODULE, '应收汇总保持CNY十进制金额与客户隔离键', financeResponse,
|
||||
id(finance?.customerId) === customerId && finance?.currency === 'CNY'
|
||||
&& ['totalReceivable', 'receivedAmount', 'outstandingReceivable'].every((field) => nonNegative(finance?.[field]))
|
||||
&& Number(finance?.outstandingReceivable) <= Number(finance?.totalReceivable),
|
||||
`customerId=${id(finance?.customerId) || 'missing'}, currency=${finance?.currency || 'missing'}`, OPTIONS)
|
||||
|
||||
const transitPath = `/api/platform/v1/customers/${encodeURIComponent(customerId)}/container-transit-summary`
|
||||
const transitResponse = await context.request('GET', transitPath)
|
||||
const transit = context.apiSuccess(MODULE, '查询已开船未到仓在途柜量', transitResponse, `customerId=${customerId}`, OPTIONS)
|
||||
context.assert(MODULE, '在途柜量保持TEU小数、未知柜型与客户隔离键', transitResponse,
|
||||
id(transit?.customerId) === customerId && nonNegative(transit?.containerCount)
|
||||
&& nonNegative(transit?.totalTeu) && nonNegative(transit?.unknownContainerCount)
|
||||
&& Number(transit?.unknownContainerCount) <= Number(transit?.containerCount) && Boolean(transit?.definition),
|
||||
`customerId=${id(transit?.customerId) || 'missing'}, totalTeu=${transit?.totalTeu ?? 'missing'}, unknown=${transit?.unknownContainerCount ?? 'missing'}`, OPTIONS)
|
||||
}
|
||||
@@ -7,6 +7,13 @@ import { fileURLToPath } from 'node:url'
|
||||
const here = path.dirname(fileURLToPath(import.meta.url))
|
||||
const acceptance = fs.readFileSync(path.join(here, '..', 'admin-test-env-acceptance.mjs'), 'utf8')
|
||||
const system = fs.readFileSync(path.join(here, 'system.mjs'), 'utf8')
|
||||
const operatingStatistics = fs.readFileSync(path.join(here, 'customer-operating-statistics.mjs'), 'utf8')
|
||||
const repositoryRoot = path.join(here, '..', '..')
|
||||
const orderStatisticsTest = fs.readFileSync(path.join(repositoryRoot, 'order', 'src', 'test', 'java', 'com', 'baiyue', 'order', 'service', 'TenantOrderStatisticsServiceTest.java'), 'utf8')
|
||||
+ fs.readFileSync(path.join(repositoryRoot, 'order', 'src', 'test', 'java', 'com', 'baiyue', 'order', 'repository', 'TenantOrderStatisticsSqlContractTest.java'), 'utf8')
|
||||
const financeStatisticsTest = fs.readFileSync(path.join(repositoryRoot, 'finance', 'src', 'test', 'java', 'com', 'baiyue', 'finance', 'CustomerAccountSummaryBehaviorTest.java'), 'utf8')
|
||||
const transitStatisticsTest = fs.readFileSync(path.join(repositoryRoot, 'firstleg', 'src', 'test', 'java', 'com', 'baiyue', 'firstleg', 'customerstatistics', 'CustomerTransitStatisticsServiceTest.java'), 'utf8')
|
||||
+ fs.readFileSync(path.join(repositoryRoot, 'firstleg', 'src', 'test', 'java', 'com', 'baiyue', 'firstleg', 'customerstatistics', 'CustomerTransitStatisticsContractTest.java'), 'utf8')
|
||||
|
||||
test('客户验收覆盖审核资质上传、回查和鉴权下载', () => {
|
||||
assert.match(acceptance, /files\/qualifications\/\$\{tenantId\}\/required-package/)
|
||||
@@ -30,3 +37,22 @@ test('客户验收覆盖客户维度操作日志列表和详情快照', () => {
|
||||
assert.match(acceptance, /JSON\.parse\(auditDetail\[field\]\)/)
|
||||
assert.match(acceptance, /snapshotsAreRedacted/)
|
||||
})
|
||||
|
||||
test('客户详情经营统计模块登记三项独立正式接口与精度字段', () => {
|
||||
assert.match(acceptance, /'customer-operating-statistics'/)
|
||||
assert.match(operatingStatistics, /orders\/first-leg\/tenant-statistics\?tenantId=/)
|
||||
assert.match(operatingStatistics, /customer-accounts\/\$\{encodeURIComponent\(customerId\)\}\/summary/)
|
||||
assert.match(operatingStatistics, /container-transit-summary/)
|
||||
for (const field of ['currentMonthSubmittedOrders', 'outstandingReceivable', 'totalTeu', 'unknownContainerCount']) {
|
||||
assert.match(operatingStatistics, new RegExp(field))
|
||||
}
|
||||
})
|
||||
|
||||
test('后端统计契约测试覆盖客户详情已确认边界口径', () => {
|
||||
for (const marker of ["order_role = 'master'", 'submitted_at is not null', 'monthstart', 'nextmonthstart', 'doesNotContain\\\("status ="\\\)']) assert.match(orderStatisticsTest, new RegExp(marker, 'i'))
|
||||
for (const marker of ['VOIDED', 'totalReceivable', 'receivedAmount', 'outstandingReceivable']) assert.match(financeStatisticsTest, new RegExp(marker, 'i'))
|
||||
for (const marker of ['actual_sailing_at', 'actual_warehouse_arrival_at', 'CANCELLED', 'FAILED', '20\\*=1', '40\\*=2', '45\\*=2.25', '2.25', 'unknown']) assert.match(transitStatisticsTest, new RegExp(marker, 'i'))
|
||||
assert.match(orderStatisticsTest, /tenant_id|tenantSubmittedStatistics/)
|
||||
assert.match(financeStatisticsTest, /customerId|customer_id/)
|
||||
assert.match(transitStatisticsTest, /customerId|customer_id/)
|
||||
})
|
||||
|
||||
@@ -11,8 +11,8 @@ $ErrorActionPreference = 'Stop'
|
||||
$Repo = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
||||
$Workspace = (Resolve-Path (Join-Path $Repo '..')).Path
|
||||
$Acceptance = Join-Path $Workspace '.codex-tmp\p23-04-acceptance'
|
||||
$ExpectedSha256 = 'EB965FCBCE23B7A6E565530C13188B1C55FAB43B8FD4E3408DED91D57454A7DF'
|
||||
$ExpectedLines = 14456
|
||||
$ExpectedSha256 = 'CA250057CAB91D248E31BCC5A66CADE72F81EB9906B19B8E3CB09BD60B112F29'
|
||||
$ExpectedLines = 14708
|
||||
|
||||
if ($TargetHost -notin @('127.0.0.1', 'localhost')) {
|
||||
[Console]::Error.WriteLine('Refusing non-local database; only 127.0.0.1 or localhost is allowed.')
|
||||
|
||||
Reference in New Issue
Block a user