Files
baiyue-firstleg/lastleg-service/src/main/resources/openapi/self-operated-analytics-v1.yaml
T

922 lines
53 KiB
YAML
Raw Normal View History

openapi: 3.0.3
info:
title: 平台自营出库销量库存及采集运行只读接口
version: 1.0.0
description: >-
全部GET要求PLATFORM身份、tenantId=0、非代登录及独立platform:self-operated-analytics:list权限。
来源及业务时区Asia/Shanghai,单位PCS,账号和仓库由服务端已配置范围校验。
经营查询首屏生成context,包含版本对、独立范围摘要、queryAsOf/queryExpiresAt。
后续列表、图表、榜单和库存复用完整上下文,版本0保持不可用,不偷偷补入新版本。
上下文最多30分钟且不超过旧销量版superseded_at_utc+7天;queryAsOf不得未来或早于所选版本发布时间。
过期/范围不符明确要求刷新整页,不能静默切版;各请求在同一REPEATABLE_READ快照内校验和读取。
五周期包含今日,CUSTOM两端包含且endDate不晚于anchorDate;只有CUSTOM接受startDate/endDate。
默认maxQueryDays366,粒度DAY。正式outboundQuantity与observedQuantity独立,全部未知仍为空。
每日COMPLETE仅证明全天覆盖及有效日行或可靠SKU存在;今日/部分日正式量空,观察量可用,未知日期保持空。
SKU区间正式量仅全部日完整才输出;observedQuantity为可靠点合计,完整/部分/未知日数独立。
热销榜跟随图表所选日期,以已采集有效出库量排序;覆盖不足标记PARTIAL,不改变30日日均分母;不触发领星请求。
运行接口不受经营context限制。动态库存时效、重建和修订待核对独立返回。
阶段进度区分ACCOUNT_SHARED/WAREHOUSE及TASK_CUMULATIVE/ATTEMPT_ONLY,不伪造总百分比。
total未知为空、计数不能跨PAGE/ORDER/INVENTORY_ROW/BUSINESS_KEY/SKU/BATCH单位求和,NONE为非计数阶段且completed/total为空、totalKnown=false;阶段检查点与心跳分开。
任务号稳定,内部诊断ID不作为业务编号回退。SKU订单数不可相加为仓总单数。
重试沿既有POST sync-tasks,action=RETRY/requestKey/warehouseCode/taskNo/reason,使用独立sync权限并最终复核资格。
security: [{bearerAuth: []}]
paths:
/api/platform/v1/last-leg/self-operated-analytics/dashboard:
get:
summary: 单仓固定版本经营总览
description: >-
平台独立只读权限platform:self-operated-analytics:list。一次一致快照固定销量和库存版本。
默认LAST_15_DAYS同时用于趋势、区间出库和热销Top10;热销按已采集有效量排序并标记覆盖状态。日均、互斥分桶及两个库存Top10固定至昨日30完整日。
不接受货主、SKU、分页、windowDays、topN或其他额外筛选。仓级趋势不套单SKU观察期。
库存严格下钻须携带原版本和drilldownFrom=DASHBOARD;截止时间由服务端根据库存真实观测重算。
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {$ref: '#/components/parameters/rangePreset'}
- {$ref: '#/components/parameters/startDate'}
- {$ref: '#/components/parameters/endDate'}
- {$ref: '#/components/parameters/bucket'}
- {$ref: '#/components/parameters/salesRunId'}
- {$ref: '#/components/parameters/inventoryRunId'}
- {$ref: '#/components/parameters/salesScopeHash'}
- {$ref: '#/components/parameters/inventoryScopeHash'}
- {$ref: '#/components/parameters/queryAsOf'}
responses:
'200':
description: 统一ApiResponse;版本或参数错误为业务失败,不降级成空图。
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/Dashboard'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/sku-sales-summary:
get:
summary: SKU五周期或历史累计清单
description: '候选为两版profile并集,SQL按选定日期聚合后按observedQuantity降序空值末尾、SKU及货主升序,再分页。未知日不填零。 权限platform:self-operated-analytics:list。'
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {$ref: '#/components/parameters/customerCode'}
- {$ref: '#/components/parameters/sku'}
- {$ref: '#/components/parameters/salesRunId'}
- {$ref: '#/components/parameters/inventoryRunId'}
- {$ref: '#/components/parameters/salesScopeHash'}
- {$ref: '#/components/parameters/inventoryScopeHash'}
- {$ref: '#/components/parameters/queryAsOf'}
- {$ref: '#/components/parameters/rangePreset'}
- {$ref: '#/components/parameters/startDate'}
- {$ref: '#/components/parameters/endDate'}
- {$ref: '#/components/parameters/bucket'}
- {$ref: '#/components/parameters/current'}
- {$ref: '#/components/parameters/size'}
responses:
'200':
description: '统一ApiResponse,业务失败HTTP200且code非200。'
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/SalesPage'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/sku-daily-sales:
get:
summary: 精确单SKU日趋势
description: 'customerCode和sku必填,精确原始业务键匹配。最多366日且返回完整升序日期轴,不分页。无候选明确业务错误。 权限platform:self-operated-analytics:list。'
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {$ref: '#/components/parameters/customerCodeRequired'}
- {$ref: '#/components/parameters/skuRequired'}
- {$ref: '#/components/parameters/salesRunId'}
- {$ref: '#/components/parameters/inventoryRunId'}
- {$ref: '#/components/parameters/salesScopeHash'}
- {$ref: '#/components/parameters/inventoryScopeHash'}
- {$ref: '#/components/parameters/queryAsOf'}
- {$ref: '#/components/parameters/rangePreset'}
- {$ref: '#/components/parameters/startDate'}
- {$ref: '#/components/parameters/endDate'}
- {$ref: '#/components/parameters/bucket'}
responses:
'200':
description: '统一ApiResponse,业务失败HTTP200且code非200。'
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/Trend'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/hot-skus:
get:
summary: 所选时段已采集热销Top100
description: '支持CUSTOM起止日期(含截止日),与总览所选时段一致;未传日期时仍使用windowDays的7/30日窗口。按已采集有效数量排序,覆盖不足由context及coverageStatus提示,不把未知当零。数量大于零,数量降序、SKU单数降序、SKU及货主升序,先Top100再分页;当前缺货仍可入榜。 权限platform:self-operated-analytics:list。'
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {$ref: '#/components/parameters/customerCode'}
- {$ref: '#/components/parameters/sku'}
- {$ref: '#/components/parameters/salesRunId'}
- {$ref: '#/components/parameters/inventoryRunId'}
- {$ref: '#/components/parameters/salesScopeHash'}
- {$ref: '#/components/parameters/inventoryScopeHash'}
- {$ref: '#/components/parameters/queryAsOf'}
- {$ref: '#/components/parameters/windowDays'}
- {$ref: '#/components/parameters/rangePreset'}
- {$ref: '#/components/parameters/startDate'}
- {$ref: '#/components/parameters/endDate'}
- {$ref: '#/components/parameters/current'}
- {$ref: '#/components/parameters/size'}
responses:
'200':
description: '统一ApiResponse,业务失败HTTP200且code非200。'
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/MetricPage'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/slow-skus:
get:
summary: 固定完整30日有库存低出库Top100
description: '固定30天,不接受windowDays或rangePreset。正品有效新鲜可售量大于零、完整窗口且起点前可靠存在。数量升序、可售量降序、SKU及货主升序。 权限platform:self-operated-analytics:list。'
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {$ref: '#/components/parameters/customerCode'}
- {$ref: '#/components/parameters/sku'}
- {$ref: '#/components/parameters/salesRunId'}
- {$ref: '#/components/parameters/inventoryRunId'}
- {$ref: '#/components/parameters/salesScopeHash'}
- {$ref: '#/components/parameters/inventoryScopeHash'}
- {$ref: '#/components/parameters/queryAsOf'}
- {$ref: '#/components/parameters/current'}
- {$ref: '#/components/parameters/size'}
responses:
'200':
description: '统一ApiResponse,业务失败HTTP200且code非200。'
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/MetricPage'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/inventory-coverage:
get:
summary: 正品库存与固定10或30日可售天数
description: '固定10或30天,不接受图表周期。可售仅品质0可用量,不扣冻结或加在途次品。先UNKNOWN/INVALID/STALE,再有效零库存为0,再校验正库存单位、窗口、观察期;零销量天数为空。 权限platform:self-operated-analytics:list。'
parameters:
- {$ref: '#/components/parameters/coverageBucket'}
- {$ref: '#/components/parameters/bucketRuleVersion'}
- {$ref: '#/components/parameters/coverageSelection'}
- {$ref: '#/components/parameters/drilldownFrom'}
- {$ref: '#/components/parameters/attention'}
- {$ref: '#/components/parameters/sortBy'}
- {$ref: '#/components/parameters/coverageDaysThreshold'}
- {name: salesWindowDays, in: query, schema: {type: integer, enum: [10, 30], default: 30}, description: 仅库存明细使用的完整自然日窗口}
- {name: salesWindowEndDate, in: query, schema: {type: string, format: date}, description: 含当日的窗口截止日,默认固定查询基准的北京时间昨日;必须早于查询当日,分页须携带原窗口}
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {$ref: '#/components/parameters/customerCode'}
- {$ref: '#/components/parameters/sku'}
- {$ref: '#/components/parameters/salesRunId'}
- {$ref: '#/components/parameters/inventoryRunId'}
- {$ref: '#/components/parameters/salesScopeHash'}
- {$ref: '#/components/parameters/inventoryScopeHash'}
- {$ref: '#/components/parameters/queryAsOf'}
- {$ref: '#/components/parameters/current'}
- {$ref: '#/components/parameters/size'}
responses:
'200':
description: '统一ApiResponse,业务失败HTTP200且code非200。'
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/InventoryMetricPage'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/sync-overview:
get:
summary: 各仓任务族运行概览
description: 'warehouseCode可选。轻量读取scope/task/run/账号保护。无发布版和OFF仍返回配置任务;无正式scope时可显示冻结唯一仓码的最近普通VALIDATION根,不计入正式同步成功、覆盖或发布。首采COMPLETE须正式发布覆盖且无rebuild或未闭合归并。共享上游明确账号共享范围。 权限platform:self-operated-analytics:list。'
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCodeOptional'}
- {$ref: '#/components/parameters/dataFamily'}
responses:
'200':
description: '统一ApiResponse,业务失败HTTP200且code非200。'
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/Overview'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/sync-tasks:
get:
summary: 本仓逻辑采集任务
description: '任务按创建时间及稳定键倒序。首屏返回listUpperCreatedAt/listUpperId,后页完整重传;新插入不挤移页。普通VALIDATION根按冻结唯一仓码归属本仓,无需正式scope;仓库目录发现根不进入分仓视图。只读有限检查点,不展开stage或大manifest。 权限platform:self-operated-analytics:list。'
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {$ref: '#/components/parameters/dataFamily'}
- {$ref: '#/components/parameters/taskType'}
- {$ref: '#/components/parameters/status'}
- {$ref: '#/components/parameters/taskNo'}
- {$ref: '#/components/parameters/dateFrom'}
- {$ref: '#/components/parameters/dateUntil'}
- {$ref: '#/components/parameters/current'}
- {$ref: '#/components/parameters/size'}
- {$ref: '#/components/parameters/listUpperCreatedAt'}
- {$ref: '#/components/parameters/listUpperId'}
responses:
'200':
description: '统一ApiResponse,业务失败HTTP200且code非200。'
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/TaskPage'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/sync-tasks/{taskNo}:
get:
summary: 本仓业务任务号详情
description: '路径taskNo为稳定业务任务号,实际归属与请求账号仓必须一致。不以内部ID回退。详情含最新尝试和关联共享上游;普通VALIDATION根以冻结唯一仓码匹配,可在无正式scope时读取。progress.stages保留实际阶段计数,HTTP次数和终态NONE不作为样本行数。 权限platform:self-operated-analytics:list。'
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {name: taskNo, in: path, required: true, schema: {type: string, maxLength: 64}}
responses:
'200':
description: '统一ApiResponse,业务失败HTTP200且code非200。'
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/TaskDetail'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/sync-runs:
get:
summary: 本仓或任务号的尝试历史
description: '纯运行元数据分页,包含冻结唯一仓码匹配本仓的普通VALIDATION根尝试,无需正式scope;目录发现根不进入分仓视图。当前尝试读同一attemptNo的task进度,终态尝试只读run冻结快照;心跳过期UNCONFIRMED,不自动改判成功失败。 权限platform:self-operated-analytics:list。'
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {$ref: '#/components/parameters/dataFamily'}
- {$ref: '#/components/parameters/taskType'}
- {$ref: '#/components/parameters/status'}
- {$ref: '#/components/parameters/taskNo'}
- {$ref: '#/components/parameters/dateFrom'}
- {$ref: '#/components/parameters/dateUntil'}
- {$ref: '#/components/parameters/current'}
- {$ref: '#/components/parameters/size'}
- {$ref: '#/components/parameters/listUpperCreatedAt'}
- {$ref: '#/components/parameters/listUpperId'}
responses:
'200':
description: '统一ApiResponse,业务失败HTTP200且code非200。'
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/AttemptPage'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/owners:
get:
summary: 已采集货主编码分页
description: 固定同屏版本,只读权限platform:self-operated-analytics:list。不调用外部API。概览不接受SKU/attention/sortBy/分页/图表范围,候选不存在data为空。
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {$ref: '#/components/parameters/salesRunId'}
- {$ref: '#/components/parameters/inventoryRunId'}
- {$ref: '#/components/parameters/salesScopeHash'}
- {$ref: '#/components/parameters/inventoryScopeHash'}
- {$ref: '#/components/parameters/queryAsOf'}
- {$ref: '#/components/parameters/keyword'}
- {$ref: '#/components/parameters/current'}
- {$ref: '#/components/parameters/size'}
responses:
'200':
description: 统一ApiResponse
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/OwnerPage'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
/api/platform/v1/last-leg/self-operated-analytics/owner-overview:
get:
summary: 单货主完整候选30日经营概览
description: 固定同屏版本,只读权限platform:self-operated-analytics:list。不调用外部API。概览不接受SKU/attention/sortBy/分页/图表范围,候选不存在data为空。
parameters:
- {$ref: '#/components/parameters/sourceAccount'}
- {$ref: '#/components/parameters/warehouseCode'}
- {$ref: '#/components/parameters/salesRunId'}
- {$ref: '#/components/parameters/inventoryRunId'}
- {$ref: '#/components/parameters/salesScopeHash'}
- {$ref: '#/components/parameters/inventoryScopeHash'}
- {$ref: '#/components/parameters/queryAsOf'}
- {$ref: '#/components/parameters/customerCodeRequired'}
- {$ref: '#/components/parameters/coverageDaysThreshold'}
responses:
'200':
description: 统一ApiResponse
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/OwnerOverview'}
'401': {description: 缺少可信认证身份}
'403': {description: 非平台身份或缺少独立只读权限}
components:
securitySchemes:
bearerAuth: {type: http, scheme: bearer, bearerFormat: JWT}
parameters:
coverageBucket:
name: coverageBucket
in: query
description: 与非ALL attention和coverageSelection互斥,须配套固定规则版本;SQL分页前采用与总览相同互斥谓词。
schema: {type: string, enum: [DAYS_0_30, DAYS_30_60, DAYS_60_90, DAYS_GT_90, NO_OUTBOUND_30D, NO_AVAILABLE, UNKNOWN]}
bucketRuleVersion: {name: bucketRuleVersion, in: query, description: 不带coverageBucket时禁止单独传入, schema: {type: string, enum: [COVERAGE_DISTRIBUTION_V1]}}
coverageSelection: {name: coverageSelection, in: query, description: 正式有限正可售天数候选,在SQL分页前过滤,与非ALL attention及coverageBucket互斥, schema: {type: string, enum: [FINITE_POSITIVE]}}
drilldownFrom: {name: drilldownFrom, in: query, description: 必须固定原版本,服务端在真实库存有效期与查询到期较早者阻断并要求刷新总览;不增加权限, schema: {type: string, enum: [DASHBOARD]}}
keyword: {name: keyword, in: query, schema: {type: string, minLength: 1, maxLength: 64}, description: 区分大小写的货主编码字面前缀,先过滤去重再分页}
attention: {name: attention, in: query, schema: {type: string, default: ALL, enum: [ALL, NO_OUTBOUND_30D, COVERAGE_GT_THRESHOLD, FROZEN_STOCK, DEFECTIVE_STOCK, UNASSESSABLE]}}
sortBy: {name: sortBy, in: query, schema: {type: string, default: AVAILABLE_DESC, enum: [AVAILABLE_DESC, COVERAGE_DAYS_DESC, PHYSICAL_DESC, OUTBOUND_30D_ASC]}, description: 完整候选先筛选后按未舍入值排序分页,未知末尾,同值SKU和货主升序}
coverageDaysThreshold: {name: coverageDaysThreshold, in: query, schema: {type: integer, minimum: 1}, description: COVERAGE_GT_THRESHOLD必填,严格大于且未舍入比较,不设置默认经营政策}
sourceAccount: {name: sourceAccount, in: query, required: true, schema: {type: string, minLength: 1, maxLength: 64}}
warehouseCode: {name: warehouseCode, in: query, required: true, schema: {type: string, minLength: 1, maxLength: 64}}
customerCode: {name: customerCode, in: query, required: false, schema: {type: string, minLength: 1, maxLength: 64}}
sku: {name: sku, in: query, required: false, schema: {type: string, minLength: 1, maxLength: 128}}
rangePreset: {name: rangePreset, in: query, required: false, schema: {type: string, enum: [TODAY, LAST_3_DAYS, THIS_WEEK, LAST_15_DAYS, THIS_MONTH, CUSTOM], default: TODAY}}
startDate: {name: startDate, in: query, required: false, schema: {type: string, format: date}}
endDate: {name: endDate, in: query, required: false, schema: {type: string, format: date}}
bucket: {name: bucket, in: query, required: false, schema: {type: string, enum: [DAY], default: DAY}}
windowDays: {name: windowDays, in: query, required: false, schema: {type: integer, enum: [7, 30], default: 30}}
current: {name: current, in: query, required: false, schema: {type: integer, minimum: 1, default: 1}}
size: {name: size, in: query, required: false, schema: {type: integer, minimum: 1, maximum: 100, default: 20}}
salesRunId: {name: salesRunId, in: query, required: false, schema: {type: string, pattern: '^[0-9]+$'}}
inventoryRunId: {name: inventoryRunId, in: query, required: false, schema: {type: string, pattern: '^[0-9]+$'}}
salesScopeHash: {name: salesScopeHash, in: query, required: false, schema: {type: string, pattern: '^[0-9a-f]{64}$'}}
inventoryScopeHash: {name: inventoryScopeHash, in: query, required: false, schema: {type: string, pattern: '^[0-9a-f]{64}$'}}
queryAsOf: {name: queryAsOf, in: query, required: false, schema: {type: string, format: date-time}}
dataFamily: {name: dataFamily, in: query, required: false, schema: {type: string, enum: [OUTBOUND, INVENTORY]}}
taskType: {name: taskType, in: query, required: false, schema: {type: string}}
status: {name: status, in: query, required: false, schema: {type: string}}
taskNo: {name: taskNo, in: query, required: false, schema: {type: string, maxLength: 64}}
dateFrom: {name: dateFrom, in: query, required: false, schema: {type: string, format: date}}
dateUntil: {name: dateUntil, in: query, required: false, schema: {type: string, format: date}}
listUpperCreatedAt: {name: listUpperCreatedAt, in: query, required: false, schema: {type: string, format: date-time}}
listUpperId: {name: listUpperId, in: query, required: false, schema: {type: string, pattern: '^[0-9]+$'}}
warehouseCodeOptional: {name: warehouseCode, in: query, schema: {type: string, minLength: 1, maxLength: 64}}
customerCodeRequired: {name: customerCode, in: query, required: true, schema: {type: string, minLength: 1, maxLength: 64}}
skuRequired: {name: sku, in: query, required: true, schema: {type: string, minLength: 1, maxLength: 128}}
schemas:
DashboardContext:
allOf:
- {$ref: '#/components/schemas/Context'}
- type: object
properties:
fixedWindowStartDate: {type: string, format: date}
fixedWindowEndDateExclusive: {type: string, format: date}
fixedWindowDays: {type: integer, enum: [30]}
inventoryFreshUntil: {type: string, format: date-time, nullable: true}
inventoryDrilldownExpiresAt: {type: string, format: date-time, nullable: true}
DashboardMetric:
type: object
properties:
value: {type: number, nullable: true}
knownSubtotal: {type: number, nullable: true}
unit: {type: string, enum: [PCS, PCS_PER_DAY, SKU]}
dataStatus: {type: string, enum: [COMPLETE, PARTIAL, UNKNOWN]}
unknownSkuCount: {type: string, nullable: true}
reasonCodes: {type: array, items: {type: string}}
outboundQuantity: {type: number, nullable: true}
observedQuantity: {type: number, nullable: true}
DashboardKpis:
type: object
properties:
intervalOutboundQuantity: {$ref: '#/components/schemas/DashboardMetric'}
averageDailyOutboundQuantity30d: {$ref: '#/components/schemas/DashboardMetric'}
physicalQuantity: {$ref: '#/components/schemas/DashboardMetric'}
availableQuantity: {$ref: '#/components/schemas/DashboardMetric'}
physicalSkuCount: {$ref: '#/components/schemas/DashboardMetric'}
noOutboundSkuCount30d: {$ref: '#/components/schemas/DashboardMetric'}
CoverageDistribution:
type: object
description: 数值桶按未舍入交叉乘积判断;七桶互斥守恒。库存版未发布时计数为空,不把销量候选伪造成库存总量。
properties:
bucketRuleVersion: {type: string, enum: [COVERAGE_DISTRIBUTION_V1]}
candidateSkuCount: {type: string, nullable: true}
excludedZeroPhysicalSkuCount: {type: string, nullable: true}
dataStatus: {type: string, enum: [COMPLETE, PARTIAL, UNKNOWN]}
reasonCodes: {type: array, items: {type: string}}
unknownReasons: {type: object, additionalProperties: {type: string}}
buckets:
type: array
minItems: 7
maxItems: 7
items:
type: object
properties:
bucketCode: {type: string, enum: [DAYS_0_30, DAYS_30_60, DAYS_60_90, DAYS_GT_90, NO_OUTBOUND_30D, NO_AVAILABLE, UNKNOWN]}
skuCount: {type: string, nullable: true}
knownPhysicalQuantity: {type: number, nullable: true}
unknownPhysicalSkuCount: {type: string, nullable: true}
DashboardRankingItem:
type: object
properties:
customerCode: {type: string}
sku: {type: string}
productName: {type: string, nullable: true}
value: {type: number}
unit: {type: string, enum: [PCS, DAY]}
windowOutboundQuantity: {type: number, nullable: true, description: 榜单实际窗口出库量;热销在部分覆盖时为已采集量}
skuOutboundOrderCount: {type: string, nullable: true}
physicalQuantity: {type: number, nullable: true}
availableQuantity: {type: number, nullable: true}
frozenQuantity: {type: number, nullable: true}
defectivePhysicalQuantity: {type: number, nullable: true}
averageDailyOutboundQuantity: {type: number, nullable: true}
inventoryCoverageDays: {type: number, nullable: true}
DashboardRanking:
type: object
description: eligibleCount来自完整候选;items最多10项,不用Top100数量冒充全量合格数。
properties:
windowStartDate: {type: string, format: date}
windowEndDateExclusive: {type: string, format: date}
calculationWindowDays: {type: integer, minimum: 1, description: 热销为所选日期天数;库存榜固定30}
eligibleCount: {type: string, nullable: true}
unassessableCount: {type: string, nullable: true}
items: {type: array, maxItems: 10, items: {$ref: '#/components/schemas/DashboardRankingItem'}}
dataStatus: {type: string, enum: [COMPLETE, PARTIAL, UNKNOWN]}
reasonCodes: {type: array, items: {type: string}}
Dashboard:
type: object
properties:
context: {$ref: '#/components/schemas/DashboardContext'}
kpis: {$ref: '#/components/schemas/DashboardKpis'}
salesTrend:
type: object
properties:
summary: {$ref: '#/components/schemas/SalesSummary'}
points: {type: array, maxItems: 366, items: {$ref: '#/components/schemas/Point'}}
coverageDistribution: {$ref: '#/components/schemas/CoverageDistribution'}
hotSkus: {$ref: '#/components/schemas/DashboardRanking'}
longCoverageSkus: {$ref: '#/components/schemas/DashboardRanking'}
noOutboundSkus: {$ref: '#/components/schemas/DashboardRanking'}
OwnerOption:
type: object
properties:
customerCode: {type: string}
customerName: {type: string, nullable: true}
OwnerPage:
type: object
properties:
context: {$ref: '#/components/schemas/Context'}
records: {type: array, items: {$ref: '#/components/schemas/OwnerOption'}}
current: {type: integer}
size: {type: integer}
total: {type: string}
pages: {type: string}
excludedReasons: {type: object, additionalProperties: {type: string}}
QuantityTotal:
type: object
properties:
overallTotal: {type: number, nullable: true}
knownSubtotal: {type: number, nullable: true}
unknownSkuCount: {type: string}
dataStatus: {type: string, enum: [COMPLETE, PARTIAL, UNKNOWN]}
reasonCodes: {type: array, items: {type: string}}
RiskShare:
type: object
description: 分母为同一OwnerOverview的physicalQuantity。未知时正式命中与比例为空。未设置阈值返回THRESHOLD_NOT_SET。
properties:
matchedSkuCount: {type: string, nullable: true}
matchedPhysicalQuantity: {type: number, nullable: true}
physicalQuantityRatio: {type: number, minimum: 0, maximum: 1, nullable: true}
knownMatchedSkuCount: {type: string, nullable: true}
knownMatchedPhysicalQuantity: {type: number, nullable: true}
unassessableSkuCount: {type: string}
unassessableKnownPhysicalQuantity: {type: number, nullable: true}
reasonCodes: {type: array, items: {type: string}}
OwnerOverview:
type: object
nullable: true
properties:
context: {$ref: '#/components/schemas/Context'}
customerCode: {type: string}
customerName: {type: string, nullable: true}
skuCount: {type: string, nullable: true}
physicalSkuCount: {$ref: '#/components/schemas/QuantityTotal'}
physicalQuantity: {$ref: '#/components/schemas/QuantityTotal'}
availableQuantity: {$ref: '#/components/schemas/QuantityTotal'}
frozenQuantity: {$ref: '#/components/schemas/QuantityTotal'}
defectivePhysicalQuantity: {$ref: '#/components/schemas/QuantityTotal'}
transitQuantity: {$ref: '#/components/schemas/QuantityTotal'}
outboundQuantity30d: {$ref: '#/components/schemas/QuantityTotal'}
averageDailyOutboundQuantity: {$ref: '#/components/schemas/QuantityTotal'}
noOutbound30d: {$ref: '#/components/schemas/RiskShare'}
coverageAboveThreshold: {$ref: '#/components/schemas/RiskShare'}
Context:
type: object
properties:
salesRunId: {type: string, nullable: true}
inventoryRunId: {type: string, nullable: true}
salesScopeHash: {type: string, nullable: true}
inventoryScopeHash: {type: string, nullable: true}
queryAsOf: {type: string, format: date-time, nullable: true}
queryExpiresAt: {type: string, format: date-time, nullable: true}
businessTimezone: {type: string, nullable: true}
anchorDate: {type: string, format: date, nullable: true}
rangeStartDate: {type: string, format: date, nullable: true}
rangeEndDateExclusive: {type: string, format: date, nullable: true}
calculationWindowDays: {type: integer, nullable: true}
completeDayFrom: {type: string, format: date, nullable: true}
completeDayUntil: {type: string, format: date, nullable: true}
salesCoveredFrom: {type: string, format: date-time, nullable: true}
salesCoveredUntil: {type: string, format: date-time, nullable: true}
salesPublishedAt: {type: string, format: date-time, nullable: true}
inventoryObservedFrom: {type: string, format: date-time, nullable: true}
inventoryObservedUntil: {type: string, format: date-time, nullable: true}
salesStatus: {type: string, nullable: true}
inventoryStatus: {type: string, nullable: true}
rebuildRequired: {type: boolean, nullable: true}
revisionReviewStatus: {type: string, nullable: true}
reasonCodes: {type: array, items: {type: string}}
SalesSummary:
type: object
properties:
sourceAccount: {type: string, nullable: true}
warehouseCode: {type: string, nullable: true}
customerCode: {type: string, nullable: true}
sku: {type: string, nullable: true}
productName: {type: string, nullable: true}
quantityUnit: {type: string, nullable: true}
outboundQuantity: {type: number, nullable: true}
observedQuantity: {type: number, nullable: true}
dataStatus: {type: string, nullable: true}
reasonCodes: {type: array, items: {type: string}}
completeDayCount: {type: integer, nullable: true}
partialDayCount: {type: integer, nullable: true}
unknownDayCount: {type: integer, nullable: true}
Point:
type: object
properties:
businessDate: {type: string, format: date, nullable: true}
outboundQuantity: {type: number, nullable: true}
observedQuantity: {type: number, nullable: true}
dataStatus: {type: string, nullable: true}
reasonCodes: {type: array, items: {type: string}}
quantityUnit: {type: string, nullable: true}
coveredFrom: {type: string, format: date-time, nullable: true}
coveredUntil: {type: string, format: date-time, nullable: true}
Trend:
type: object
properties:
context: {$ref: '#/components/schemas/Context'}
summary: {$ref: '#/components/schemas/SalesSummary'}
points: {type: array, items: {$ref: '#/components/schemas/Point'}}
Metric:
type: object
properties:
customerName: {type: string, nullable: true}
defectivePhysicalQuantity: {type: number, nullable: true}
outboundQuantity30d: {type: number, nullable: true}
lastObservedOutboundDate: {type: string, format: date, nullable: true}
observedHistoryStartDate: {type: string, format: date, nullable: true}
attentionReasons: {type: array, items: {type: string}}
quantityStatuses: {type: object, additionalProperties: {type: string, enum: [VALID, UNKNOWN, STALE]}}
sourceAccount: {type: string, nullable: true}
customerCode: {type: string, nullable: true}
warehouseCode: {type: string, nullable: true}
sku: {type: string, nullable: true}
productName: {type: string, nullable: true}
quantityUnit: {type: string, nullable: true}
outboundQuantity: {type: number, nullable: true}
skuOutboundOrderCount: {type: string, nullable: true}
todayObservedQuantity: {type: number, nullable: true}
physicalQuantity: {type: number, nullable: true}
availableQuantity: {type: number, nullable: true}
frozenQuantity: {type: number, nullable: true}
transitQuantity: {type: number, nullable: true}
inventoryObservedAt: {type: string, format: date-time, nullable: true}
averageDailyOutboundQuantity: {type: number, nullable: true}
inventoryCoverageDays: {type: number, nullable: true}
inventoryQuality: {type: string, nullable: true}
salesCoverage: {type: string, nullable: true}
observationEligible: {type: boolean, nullable: true}
earliestReliableEvidenceAt: {type: string, format: date-time, nullable: true}
status: {type: string, nullable: true}
reasonCodes: {type: array, items: {type: string}}
InventoryMetric:
description: 库存独立窗口响应。windowOutboundQuantity为所选完整10或30日销量;未知保持null,零销量状态NO_OUTBOUND_IN_WINDOW不除零。30日专属筛选及总览下钻不能用于10日或历史截止窗口。
type: object
properties:
customerName: {type: string, nullable: true}
defectivePhysicalQuantity: {type: number, nullable: true}
windowOutboundQuantity: {type: number, nullable: true}
lastObservedOutboundDate: {type: string, format: date, nullable: true}
observedHistoryStartDate: {type: string, format: date, nullable: true}
attentionReasons: {type: array, items: {type: string}}
quantityStatuses: {type: object, additionalProperties: {type: string, enum: [VALID, UNKNOWN, STALE]}}
sourceAccount: {type: string, nullable: true}
customerCode: {type: string, nullable: true}
warehouseCode: {type: string, nullable: true}
sku: {type: string, nullable: true}
productName: {type: string, nullable: true}
quantityUnit: {type: string, nullable: true}
skuOutboundOrderCount: {type: string, nullable: true}
physicalQuantity: {type: number, nullable: true}
availableQuantity: {type: number, nullable: true}
frozenQuantity: {type: number, nullable: true}
transitQuantity: {type: number, nullable: true}
inventoryObservedAt: {type: string, format: date-time, nullable: true}
averageDailyOutboundQuantity: {type: number, nullable: true}
inventoryCoverageDays: {type: number, nullable: true}
inventoryQuality: {type: string, nullable: true}
salesCoverage: {type: string, nullable: true}
observationEligible: {type: boolean, nullable: true}
earliestReliableEvidenceAt: {type: string, format: date-time, nullable: true}
status: {type: string, nullable: true}
reasonCodes: {type: array, items: {type: string}}
Protection:
type: object
properties:
accountCooldownUntil: {type: string, format: date-time, nullable: true}
accountPauseReason: {type: string, nullable: true}
dailyRequestBudget: {type: integer, minimum: 0, nullable: true, description: "BUSINESS 为 0,表示不限制累计请求次数;VALIDATION 为每日请求上限。实际请求计数继续累计。"}
reservedHttpRequests: {type: string, nullable: true}
confirmedHttpRequests: {type: string, nullable: true}
budgetDate: {type: string, format: date, nullable: true}
Validation:
type: object
properties:
validationSessionNo: {type: string, nullable: true}
budgetLimits: {type: object, additionalProperties: {type: string, nullable: true}}
budgetConsumed: {type: object, additionalProperties: {type: string, nullable: true}}
deadlineAt: {type: string, format: date-time, nullable: true}
stopReason: {type: string, nullable: true}
Attempt:
type: object
properties:
runId: {type: string, nullable: true}
taskNo: {type: string, nullable: true}
attemptNo: {type: integer, nullable: true}
status: {type: string, nullable: true}
phase: {type: string, nullable: true}
executionPurpose: {type: string, nullable: true}
startedAt: {type: string, format: date-time, nullable: true}
finishedAt: {type: string, format: date-time, nullable: true}
phaseStartedAt: {type: string, format: date-time, nullable: true}
progressUpdatedAt: {type: string, format: date-time, nullable: true}
heartbeatAt: {type: string, format: date-time, nullable: true}
executionHealth: {type: string, nullable: true}
elapsedSeconds: {type: string, nullable: true}
errorCode: {type: string, nullable: true}
failureSummary: {type: string, nullable: true}
retryable: {type: boolean, nullable: true}
coverageStatus: {type: string, nullable: true}
coveredFrom: {type: string, format: date-time, nullable: true}
coveredUntil: {type: string, format: date-time, nullable: true}
publishedAt: {type: string, format: date-time, nullable: true}
progress: {$ref: '#/components/schemas/Progress'}
Task:
type: object
properties:
createdAt: {type: string, format: date-time, nullable: true, description: 当前任务创建时间,重试和阶段切换不重置}
elapsedSeconds: {type: string, nullable: true, description: 自创建起的累计秒数,含排队和重试;活动任务截止本次读取,终态任务截止任务最后更新时间;不是单次执行耗时}
taskNo: {type: string, nullable: true}
taskType: {type: string, nullable: true}
dataFamily: {type: string, nullable: true}
warehouseCode: {type: string, nullable: true}
taskRole: {type: string, nullable: true}
executionPurpose: {type: string, nullable: true}
queryFrom: {type: string, format: date-time, nullable: true}
queryUntil: {type: string, format: date-time, nullable: true}
taskStatus: {type: string, nullable: true}
applyState: {type: string, nullable: true}
attemptCount: {type: integer, nullable: true}
latestAttemptNo: {type: integer, nullable: true}
resultPublicationState: {type: string, nullable: true}
resultPublishedRunId: {type: string, nullable: true}
nextRetryAt: {type: string, format: date-time, nullable: true}
allowedActions: {type: array, items: {type: string}}
actionBlockReason: {type: string, nullable: true}
progressUpdatedAt: {type: string, format: date-time, nullable: true}
progress: {$ref: '#/components/schemas/Progress'}
validation: {$ref: '#/components/schemas/Validation'}
latestAttempt: {$ref: '#/components/schemas/Attempt'}
dependencyState:
type: string
enum: [NONE, WAITING_CONFIRMED, WAITING_UNCONFIRMED, SATISFIED, FAILED]
description: 仅直接upstreamTaskId且账号及用途一致证明依赖;时间窗口相交不构成依赖。
blockingReason: {type: string, nullable: true, description: 当前执行阻塞原因码,与恢复操作资格actionBlockReason分开}
progressSourceTaskNo: {type: string, nullable: true, description: 确认等待时指向直接上游,否则指向本任务;计数仍保留在各自Task.progress,不复制到本仓}
stageEstimate: {$ref: '#/components/schemas/StageEstimate'}
StageEstimate:
type: object
description: 本任务当前阶段估算,不能当作全任务ETA;进度与估算整体按progressIdentity和validUntil接收。计数包含复用时测速基线重建,采样仅来自已提交检查点。
properties:
status: {type: string, enum: [AVAILABLE, UNAVAILABLE, PAUSED]}
progressIdentity: {type: string}
completed: {type: string, nullable: true}
total: {type: string, nullable: true}
sampleFrom: {type: string, format: date-time, nullable: true}
sampleUntil: {type: string, format: date-time, nullable: true}
completedDelta: {type: string, nullable: true}
ratePerSecond: {type: number, nullable: true}
remainingSeconds: {type: string, nullable: true}
estimatedAt: {type: string, format: date-time}
validUntil: {type: string, format: date-time, nullable: true}
unavailableReason:
type: string
nullable: true
enum: [TERMINAL, PAUSED, HEALTH_UNCONFIRMED, TOTAL_UNKNOWN, INVALID_PROGRESS, STAGE_COMPLETE, SAMPLING, NO_RECENT_PROGRESS, SAMPLE_EXPIRED, INVALID_SAMPLE]
TaskDetail:
type: object
properties:
task: {$ref: '#/components/schemas/Task'}
sharedUpstream: {$ref: '#/components/schemas/Task'}
protection: {$ref: '#/components/schemas/Protection'}
observedAt: {type: string, format: date-time, nullable: true}
InventoryDailySamples:
type: object
nullable: true
description: 仅库存任务族提供。北京时间近30个完整日的正式日代表积累;缺日不补零或沿用旧批次,不是周转率。
required: [windowFrom, windowUntil, expectedDays, sampleCount, missingDates]
properties:
windowFrom: {type: string, format: date, description: 包含起日}
windowUntil: {type: string, format: date, description: 排他上界,即北京时间今日}
expectedDays: {type: integer, enum: [30]}
sampleCount: {type: integer, minimum: 0, maximum: 30}
missingDates: {type: array, items: {type: string, format: date}}
accumulationStartedOn: {type: string, format: date, nullable: true, description: 本仓最早正式日代表日期,无样本时为空}
Warehouse:
type: object
properties:
warehouseCode: {type: string, nullable: true}
warehouseName: {type: string, nullable: true}
dataFamily: {type: string, nullable: true}
executionEnabled: {type: boolean, nullable: true}
publicationEnabled: {type: boolean, nullable: true}
disabledReason: {type: string, nullable: true}
nextScheduledAt: {type: string, format: date-time, nullable: true, description: 自动采集下一计划时刻;显式连续BUSINESS模式下销量为下个北京时间00点05分,库存沿仓库计划;执行被禁用时为空,不代表当前任务预计完成时间}
observedAt: {type: string, format: date-time, nullable: true}
initialFrom: {type: string, format: date-time, nullable: true}
initialUntil: {type: string, format: date-time, nullable: true}
initialCoverageStatus: {type: string, nullable: true}
salesCoveredFrom: {type: string, format: date-time, nullable: true}
salesCoveredUntil: {type: string, format: date-time, nullable: true}
lastSuccessfulTaskNo: {type: string, nullable: true}
lastSucceededAt: {type: string, format: date-time, nullable: true}
lastPublishedAt: {type: string, format: date-time, nullable: true}
inventoryObservedFrom: {type: string, format: date-time, nullable: true}
inventoryObservedUntil: {type: string, format: date-time, nullable: true}
dataFreshness: {type: string, nullable: true}
rebuildRequired: {type: boolean, nullable: true}
revisionReviewStatus: {type: string, nullable: true}
inventoryDailySamples: {$ref: '#/components/schemas/InventoryDailySamples'}
currentTask: {$ref: '#/components/schemas/Task'}
activeTasks:
type: array
maxItems: 8
description: 本仓本类型活动或等待任务,RUNNING优先,再按创建时间倒序;currentTask取活动首项,无活动时取最近任务。
items: {$ref: '#/components/schemas/Task'}
sharedUpstream: {$ref: '#/components/schemas/Task'}
protection: {$ref: '#/components/schemas/Protection'}
Overview:
type: object
properties:
sourceAccount: {type: string, nullable: true}
environmentLabel: {type: string, nullable: true}
collectionMode: {type: string, nullable: true}
observedAt: {type: string, format: date-time, nullable: true}
warehouses: {type: array, items: {$ref: '#/components/schemas/Warehouse'}}
accountActivity:
allOf: [{$ref: '#/components/schemas/Task'}]
nullable: true
description: 来源账号明确活动指针指向的正式采集任务,独立展示,不代表任一仓库的依赖或数量。
Progress:
type: object
properties:
progressScope: {type: string, nullable: true}
countBasis: {type: string, nullable: true}
attemptNo: {type: string, nullable: true}
scanRound: {type: string, nullable: true}
phase: {type: string, nullable: true}
completed: {type: string, nullable: true}
total: {type: string, nullable: true}
totalKnown: {type: boolean, nullable: true}
unit: {type: string, nullable: true}
sliceFrom: {type: string, format: date-time, nullable: true}
sliceUntil: {type: string, format: date-time, nullable: true}
stageStartedAt: {type: string, format: date-time, nullable: true}
stageFinishedAt: {type: string, format: date-time, nullable: true}
validationState: {type: string, nullable: true}
invalidCount: {type: string, nullable: true}
unknownCount: {type: string, nullable: true}
pendingReviewCount: {type: string, nullable: true}
countUnit: {type: string, nullable: true}
summaryAsOf: {type: string, format: date-time, nullable: true}
directoryComplete: {type: boolean, nullable: true}
stages: {type: array, items: {$ref: '#/components/schemas/Progress'}}
SalesPage:
type: object
properties:
context: {$ref: '#/components/schemas/Context'}
records: {type: array, items: {$ref: '#/components/schemas/SalesSummary'}}
current: {type: integer, nullable: true}
size: {type: integer, nullable: true}
total: {type: string, nullable: true}
pages: {type: string, nullable: true}
excludedReasons: {type: object, additionalProperties: {type: string, nullable: true}}
MetricPage:
type: object
properties:
context: {$ref: '#/components/schemas/Context'}
records: {type: array, items: {$ref: '#/components/schemas/Metric'}}
current: {type: integer, nullable: true}
size: {type: integer, nullable: true}
total: {type: string, nullable: true}
pages: {type: string, nullable: true}
excludedReasons: {type: object, additionalProperties: {type: string, nullable: true}}
InventoryMetricPage:
type: object
properties:
context: {$ref: '#/components/schemas/Context'}
records: {type: array, items: {$ref: '#/components/schemas/InventoryMetric'}}
current: {type: integer, nullable: true}
size: {type: integer, nullable: true}
total: {type: string, nullable: true}
pages: {type: string, nullable: true}
excludedReasons: {type: object, additionalProperties: {type: string, nullable: true}}
TaskPage:
type: object
properties:
records: {type: array, items: {$ref: '#/components/schemas/Task'}}
current: {type: integer, nullable: true}
size: {type: integer, nullable: true}
total: {type: string, nullable: true}
listUpperCreatedAt: {type: string, format: date-time, nullable: true}
listUpperId: {type: string, nullable: true}
observedAt: {type: string, format: date-time, nullable: true}
AttemptPage:
type: object
properties:
records: {type: array, items: {$ref: '#/components/schemas/Attempt'}}
current: {type: integer, nullable: true}
size: {type: integer, nullable: true}
total: {type: string, nullable: true}
listUpperCreatedAt: {type: string, format: date-time, nullable: true}
listUpperId: {type: string, nullable: true}
observedAt: {type: string, format: date-time, nullable: true}