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

922 lines
53 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}