feat(selfop): add warehouse dashboard and exact inventory drilldowns
This commit is contained in:
@@ -21,6 +21,39 @@ info:
|
||||
重试沿既有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固定至昨日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五周期或历史累计清单
|
||||
@@ -149,6 +182,10 @@ paths:
|
||||
summary: 正品库存与固定30日可售天数
|
||||
description: '固定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'}
|
||||
@@ -338,6 +375,14 @@ 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和货主升序}
|
||||
@@ -370,6 +415,99 @@ components:
|
||||
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]}
|
||||
outboundQuantity30d: {type: number, nullable: true}
|
||||
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, enum: [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:
|
||||
|
||||
Reference in New Issue
Block a user