feat: add self-operated analytics and enforce Lastleg module boundaries

This commit is contained in:
2026-10-12 20:27:35 +08:00
parent c06e788b0f
commit a1f1d93902
174 changed files with 13514 additions and 490 deletions
@@ -46,6 +46,18 @@ lastleg:
enabled: ${LASTLEG_SMART_DISPATCH_API_ENABLED:true}
baiyue:
self-operated-analytics:
collection-mode: ${SELFOP_COLLECTION_MODE:OFF}
environment: ${DEPLOY_ENV:test}
daily-request-budget: ${SELFOP_DAILY_REQUEST_BUDGET:0}
business-min-request-interval-ms: ${SELFOP_MIN_REQUEST_INTERVAL_MS:5000}
execution-enabled: ${SELFOP_EXECUTION_ENABLED:false}
sales-publication-enabled: ${SELFOP_SALES_PUBLICATION_ENABLED:false}
integration-base-url: http://integration-service:9210
internal-service-token: ${INTERNAL_SERVICE_TOKEN:}
source-account: ${SELFOP_SOURCE_ACCOUNT:lingxing-primary}
source-query-timezone: Asia/Shanghai
quantity-unit: PCS
http:
clients:
unload-photo-file:
@@ -3588,3 +3588,304 @@ PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 新签收及新合箱必须打印并扫码确认标签;既有实物按原状态继续作业。
SET @ddl = IF(EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_return_inventory_carton' AND column_name='label_status'), 'SELECT 1', 'ALTER TABLE ll_return_inventory_carton ADD COLUMN label_status VARCHAR(32) NULL COMMENT ''WAIT_LABEL待贴标 CONFIRMED已扫码确认标签''');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 平台自营领星统计:独立事实与不可变发布版本;仅空库初始化,不自动执行。
CREATE TABLE ll_selfop_outbound_discovery_scope (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
catalog_from_utc DATETIME(3) NULL COMMENT '账号完整目录连续覆盖UTC下界,不等同销量覆盖',
catalog_until_utc DATETIME(3) NULL COMMENT '账号完整目录连续覆盖UTC上界,不等同销量覆盖',
next_sequence BIGINT NOT NULL DEFAULT 1 COMMENT '新发现任务的单调调度序号;重试沿用,只安排任务,不判断对象内容的新旧',
next_observation_sequence BIGINT NOT NULL DEFAULT 1 COMMENT '每次实际出库详情请求前分配的单调采集代次;与 task 调度序号独立,重试请求也分配新代次',
active_task_id BIGINT NULL COMMENT '当前共享发现/详情补齐任务',
lease_owner VARCHAR(128) NULL COMMENT '账号发现执行者',
lease_until_utc DATETIME(3) NULL COMMENT '账号发现租约到期时刻',
fence_token BIGINT NOT NULL DEFAULT 0 COMMENT '防止过期发现进程继续写共享暂存或派发任务',
request_budget INT NOT NULL COMMENT '一次调度允许的目录、详情请求总预算,必须为正',
time_budget_seconds INT NOT NULL COMMENT '一次调度允许占用的执行时长,必须为正',
min_request_interval_ms INT NOT NULL COMMENT '同账号请求最小间隔,按已核准配额配置',
api_budget_json JSON NULL COMMENT '账号所有采集族共用的预算、统计日、保守预留及确认消耗、尝试许可和独占交接依据',
api_cooldown_until_utc DATETIME(3) NULL COMMENT '账号全部真实请求共用冷却UTC截止,重启与跨日不清除',
api_pause_reason VARCHAR(64) NULL COMMENT '账号停止或等待的固定原因码,不保存供应商原始错误或凭据',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_discovery_account (source_account),
CONSTRAINT chk_selfop_outbound_discovery_scope CHECK (request_budget > 0 AND time_budget_seconds > 0 AND min_request_interval_ms > 0 AND fence_token >= 0 AND next_sequence > 0 AND next_observation_sequence > 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='账号共享出库目录与详情发现协调作用域';
CREATE TABLE ll_selfop_sync_scope (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
data_family VARCHAR(16) NOT NULL COMMENT 'OUTBOUND 或 INVENTORY;按账号+仓库+任务族互斥',
scope_json JSON NOT NULL COMMENT '本仓范围规则,customerMode=ALL_AUTHORIZED,库存为全部品质;当前账号全部授权货主均自营,不将当天出现的货主列表当白名单',
scope_hash CHAR(64) NOT NULL COMMENT '仓库、货主范围规则、品质、时区及单位口径的规范化摘要;不包含当天观测到的客户/SKU 集合',
business_timezone VARCHAR(64) NOT NULL COMMENT '本仓报表及调度时区,初始建议值为 Asia/Shanghai,各仓独立核准',
source_timezone VARCHAR(64) NULL COMMENT '本仓已核准的出库源时间时区',
schedule_cron VARCHAR(128) NOT NULL COMMENT '本仓、本任务族的调度表达式,按 business_timezone 执行',
stale_after_seconds INT NOT NULL COMMENT '本仓、本任务族数据过期阈值,必须为正;库存初始可采用 26 小时,后续按仓调整',
warehouse_policy_ref VARCHAR(128) NULL COMMENT '未来按仓告警/补货策略的稳定引用;一期为空,不建告警规则表',
initial_from_utc DATETIME(3) NULL COMMENT '首采固定UTC下界,按本仓业务时区减一个月',
initial_until_utc DATETIME(3) NULL COMMENT '首采固定UTC截止,重试不重新取当前时间',
discovery_from_utc DATETIME(3) NULL COMMENT '本仓已发布的连续销量覆盖UTC下界',
discovery_until_utc DATETIME(3) NULL COMMENT '本仓已发布的连续销量覆盖UTC上界,不含端点',
fact_revision BIGINT NOT NULL DEFAULT 0 COMMENT '出库事实归并修订号;内容实际变化才增加',
published_fact_revision BIGINT NOT NULL DEFAULT 0 COMMENT '本仓最后已发布销量版所使用的事实修订号',
rebuild_required TINYINT NOT NULL DEFAULT 0 COMMENT '事实变化待重建标记;跨仓修订同时置旧、新仓为 1',
invalidated_at_utc DATETIME(3) NULL COMMENT '最近一次因事实修订使当前版待重建的时刻',
published_run_id BIGINT NULL COMMENT '唯一对外可见版本,指向本任务族已发布执行批次',
lease_owner VARCHAR(128) NULL COMMENT '当前执行者令牌,不使用仅进程内锁',
lease_until_utc DATETIME(3) NULL COMMENT '租约到期时刻',
fence_token BIGINT NOT NULL DEFAULT 0 COMMENT '每次取得租约递增,事实提交和发布均校验',
known_order_cursor_id BIGINT NULL COMMENT '本仓已可靠处理的稳定订单内部标识游标',
known_order_round_max_id BIGINT NULL COMMENT '本轮已知单复查固定最大内部标识',
known_order_round_started_at_utc DATETIME(3) NULL COMMENT '本仓已知单复查轮次开始UTC时间',
known_order_round_finished_at_utc DATETIME(3) NULL COMMENT '本仓已知单完整轮转完成UTC时间',
history_round_from_utc DATETIME(3) NULL COMMENT '本仓历史核对固定UTC下界',
history_round_until_utc DATETIME(3) NULL COMMENT '本仓历史核对固定UTC上界',
history_slice_cursor_utc DATETIME(3) NULL COMMENT '本仓下一待核对历史切片UTC位置',
history_round_finished_at_utc DATETIME(3) NULL COMMENT '上一轮历史时间片全部完成时刻',
review_request_budget INT NOT NULL COMMENT '本仓单次复查最大请求数,必须为正',
review_time_budget_seconds INT NOT NULL COMMENT '本仓单次复查最大执行秒数,必须为正',
review_target_days INT NOT NULL DEFAULT 7 COMMENT '建议每 7 天轮转一遍,属于待配额验证的目标,不保证首次大量详情在单次调度内完成',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_scope (source_account,warehouse_code,data_family),
KEY idx_selfop_scope_lease (lease_until_utc),
CONSTRAINT chk_selfop_sync_scope CHECK (data_family IN ('OUTBOUND','INVENTORY') AND stale_after_seconds > 0 AND review_request_budget > 0 AND review_time_budget_seconds > 0 AND review_target_days > 0 AND fact_revision >= 0 AND published_fact_revision >= 0 AND fence_token >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='分仓任务族租约及发布指针';
CREATE TABLE ll_selfop_sync_task (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
task_no VARCHAR(64) NOT NULL COMMENT '稳定采集业务任务号,重试沿用,不展示内部数据库标识',
execution_purpose VARCHAR(16) NOT NULL COMMENT 'BUSINESS或VALIDATION;由服务端冻结用途,子任务继承',
validation_root_task_id BIGINT NULL COMMENT '验证会话唯一预算根任务,根引用自身,正式任务为空',
validation_budget_json JSON NULL COMMENT '验证根冻结硬预算、累计消耗、库存分仓页数、截止时刻及停止原因',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
task_role VARCHAR(24) NOT NULL COMMENT 'ACCOUNT_DISCOVERY 或 WAREHOUSE_SYNC',
scope_id BIGINT NULL COMMENT '分仓任务必须引用分仓作用域;仅账号共享发现为空',
warehouse_code VARCHAR(64) NULL COMMENT '来源仓库原始编码,按仓独立统计',
discovery_scope_id BIGINT NULL COMMENT '共享发现必填,引用账号发现协调器',
upstream_task_id BIGINT NULL COMMENT '出库分仓任务引用已持久化目录的共享发现切片;库存无此上游',
discovery_sequence BIGINT NULL COMMENT '共享任务及分仓子任务继承的调度顺序;重试保持不变,不用于事实覆盖判定',
observation_baseline BIGINT NULL COMMENT '共享任务建立时已分配的最大详情采集代次,分仓子任务继承;用于识别旧任务恢复期间出现的其他任务新观测',
request_key VARCHAR(128) NOT NULL COMMENT '共享发现包含切片/计划槽位;分仓任务包含仓库、任务族及切片或计划槽位;人工附请求幂等键',
request_hash CHAR(64) NOT NULL COMMENT '请求类型、查询范围、范围摘要的指纹;同键不同请求拒绝',
task_type VARCHAR(24) NOT NULL COMMENT 'SCHEDULED、MANUAL_RETRY、BACKFILL、RECHECK、REBUILD、VALIDATION;验证不由自动计划创建',
planned_at_utc DATETIME(3) NULL COMMENT '计划时点;人工请求可空',
query_from_utc DATETIME(3) NULL COMMENT '出库查询区间UTC下界,库存不填',
query_until_utc DATETIME(3) NULL COMMENT '出库查询区间UTC上界,不含端点,库存不填',
query_scope_json JSON NOT NULL COMMENT '不变的账号、货主、仓库、品质和查询条件快照;按单补查在此记录单号',
routing_manifest_json JSON NULL COMMENT '共享切片目录完整标记、每仓对象键集合/数量和详情就绪状态;各对象记录 effectiveStageId,需新代次复查时记录 refreshTaskId,完成后指向新有效暂存;不改写旧载荷',
scope_hash CHAR(64) NOT NULL COMMENT '建任务时的业务范围摘要',
status VARCHAR(20) NOT NULL COMMENT 'WAITING_SOURCE、READY、RUNNING、RETRY_WAIT、SUCCEEDED、DEAD、SAMPLE_DONE;样本结束不等于正式成功',
apply_state VARCHAR(20) NOT NULL COMMENT '正式出库归并NOT_STARTED、APPLYING、BLOCKED、APPLIED;共享发现、库存、重建及验证为NOT_APPLICABLE',
affected_warehouse_codes_json JSON NULL COMMENT '本次归并可能改变的仓集合,包含原仓与新仓;首段事实写入前登记,扩大集合须先取得新增仓租约并锁 scope,不能写完再补',
apply_started_at_utc DATETIME(3) NULL COMMENT '首段事实提交UTC时间',
apply_completed_at_utc DATETIME(3) NULL COMMENT '全部必需事实归并完成UTC时间,失败不填',
attempt_count INT NOT NULL DEFAULT 0 COMMENT '已创建的执行尝试数',
next_retry_at_utc DATETIME(3) NULL COMMENT '有限退避后下一次可执行时刻',
requested_by VARCHAR(128) NULL COMMENT '人工请求的平台操作人,仅内部审计',
result_published_run_id BIGINT NULL COMMENT '正式成功任务实际发布或复用的版本;验证和共享发现为空',
progress_json JSON NULL COMMENT '与可靠检查点一起提交的有界阶段、单位、尝试和质量进度,不保存单据集合',
progress_updated_at_utc DATETIME(3) NULL COMMENT '最后可靠业务检查点UTC时间,与执行心跳分开',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_task_no (task_no),
UNIQUE KEY uk_selfop_task_request (source_account,request_key),
KEY idx_selfop_task_poll (status,next_retry_at_utc,id),
KEY idx_selfop_task_upstream (upstream_task_id,warehouse_code),
KEY idx_selfop_task_apply (apply_state,id),
KEY idx_selfop_task_scope_list (scope_id,created_at,id),
KEY idx_selfop_task_account_list (source_account,task_role,created_at,id),
CONSTRAINT chk_selfop_sync_task CHECK (attempt_count >= 0 AND execution_purpose IN ('BUSINESS','VALIDATION') AND ((execution_purpose = 'BUSINESS' AND validation_root_task_id IS NULL AND validation_budget_json IS NULL) OR (execution_purpose = 'VALIDATION' AND validation_root_task_id IS NOT NULL AND apply_state = 'NOT_APPLICABLE' AND result_published_run_id IS NULL AND status <> 'SUCCEEDED')) AND ((task_role = 'ACCOUNT_DISCOVERY' AND scope_id IS NULL AND warehouse_code IS NULL AND discovery_scope_id IS NOT NULL) OR (task_role = 'WAREHOUSE_SYNC' AND scope_id IS NOT NULL AND warehouse_code IS NOT NULL)))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='一次计划或人工请求';
CREATE TABLE ll_selfop_sync_run (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
task_id BIGINT NOT NULL COMMENT '本次执行请求',
execution_purpose VARCHAR(16) NOT NULL COMMENT '从逻辑任务冻结继承,验证尝试不能作为正式统计版本',
scope_id BIGINT NULL COMMENT '仅账号共享发现为空;分仓执行必须有作用域',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
warehouse_code VARCHAR(64) NULL COMMENT '来源仓库原始编码,按仓独立统计',
run_role VARCHAR(24) NOT NULL COMMENT 'ACCOUNT_DISCOVERY 或 WAREHOUSE_SYNC',
upstream_task_id BIGINT NULL COMMENT '分仓出库计算引用的共享切片及其稳定暂存集合',
attempt_no INT NOT NULL COMMENT '同一请求从 1 起递增',
scope_hash CHAR(64) NOT NULL COMMENT '本版本的业务范围摘要',
scope_snapshot_json JSON NOT NULL COMMENT '分仓版只含本仓货主/品质、固定首采 [B,E0)、时区、调度与过期阈值;账号发现保存待路由仓集合,不冒充业务版',
observed_dimensions_json JSON NULL COMMENT '本次实际出现的仓库/货主集合及数量摘要,仅作采集证据;例如已观测 70 货主不等于固定授权范围',
fence_token BIGINT NOT NULL COMMENT '本尝试持有的栅栏版本',
base_published_run_id BIGINT NULL COMMENT '执行开始时的上一可见版本',
reference_sales_run_id BIGINT NULL COMMENT '库存构建开始时固定的本仓已发布销量版,用其不可变 SKU 维度生成出库已知商品占位;没有已发布销量版时为空,不读取半归并订单事实',
inventory_daily_sample_date DATE NULL COMMENT '北京时间当日首个合格计划库存发布代表日期,非代表为空',
inventory_sample_rule_version VARCHAR(32) NULL COMMENT '日库存代表选择规则 DAILY_SCHEDULED_FIRST_V1,与日标记原子保存',
status VARCHAR(24) NOT NULL COMMENT 'FETCHING、VALIDATED、ROUTED、FACTS_APPLIED、BUILDING、READY、PUBLISHED、REUSED、YIELDED、FAILED、ABORTED、SAMPLE_DONE;复用和验证不是版本头',
last_phase VARCHAR(24) NOT NULL COMMENT '失败/中止前所在阶段,支持判断是否已经归并事实',
fetch_started_at_utc DATETIME(3) NULL COMMENT '实际采集开始UTC时间',
fetch_finished_at_utc DATETIME(3) NULL COMMENT '实际采集完成UTC时间,未完成为空',
build_started_at_utc DATETIME(3) NULL COMMENT '实际开始有界候选构建UTC时间,用于构建耗时及首采合并间隔',
finished_at_utc DATETIME(3) NULL COMMENT '本次尝试终止UTC时间',
published_at_utc DATETIME(3) NULL COMMENT '实际原子切换发布指针UTC时间',
superseded_at_utc DATETIME(3) NULL COMMENT '被新发布版替代的首次UTC时间,同事务填写且重试不重置',
page_count INT NOT NULL DEFAULT 0 COMMENT '已完整获取页数',
source_total_count BIGINT NULL COMMENT '上游可靠返回的总数;未返回则为空',
unique_object_count BIGINT NOT NULL DEFAULT 0 COMMENT '规范化去重后对象数',
progress_snapshot_json JSON NULL COMMENT '尝试终止时冻结的有界可靠进度摘要,历史尝试不随逻辑任务改写',
heartbeat_at_utc DATETIME(3) NULL COMMENT '有效执行者最新UTC心跳,不代表业务检查点推进',
coverage_status VARCHAR(16) NOT NULL COMMENT 'UNKNOWN、PARTIAL、COMPLETE;分页完整与数值有效性分别判断',
covered_from_utc DATETIME(3) NULL COMMENT '本仓销量版本实际连续覆盖UTC下界',
covered_until_utc DATETIME(3) NULL COMMENT '本仓销量版本实际连续覆盖UTC上界,不含端点',
complete_day_from DATE NULL COMMENT '本仓完整自然日区间首日,包含',
complete_day_until DATE NULL COMMENT '本仓完整自然日区间末日,不含',
applied_fact_revision BIGINT NULL COMMENT '本次尝试归并后的事实修订号,库存为空',
calculated_fact_revision BIGINT NULL COMMENT '候选销量版本计算所依据的固定事实修订号',
error_code VARCHAR(64) NULL COMMENT '内部可诊断错误分类,不保存认证信息',
error_message VARCHAR(500) NULL COMMENT '脱敏后的固定错误摘要',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_run_attempt (task_id,attempt_no),
UNIQUE KEY uk_selfop_inventory_daily (source_account,warehouse_code,inventory_daily_sample_date),
KEY idx_selfop_run_scope (scope_id,id),
KEY idx_selfop_run_status (status,updated_at),
CONSTRAINT chk_selfop_inventory_daily CHECK ((inventory_daily_sample_date IS NULL AND inventory_sample_rule_version IS NULL) OR (inventory_daily_sample_date IS NOT NULL AND inventory_sample_rule_version IS NOT NULL AND inventory_sample_rule_version = 'DAILY_SCHEDULED_FIRST_V1' AND execution_purpose = 'BUSINESS' AND run_role = 'WAREHOUSE_SYNC' AND status = 'PUBLISHED' AND coverage_status = 'COMPLETE')),
CONSTRAINT chk_selfop_sync_run CHECK (attempt_no > 0 AND page_count >= 0 AND unique_object_count >= 0 AND execution_purpose IN ('BUSINESS','VALIDATION') AND (execution_purpose <> 'VALIDATION' OR status NOT IN ('PUBLISHED','REUSED')) AND (source_total_count IS NULL OR source_total_count >= 0) AND ((run_role = 'ACCOUNT_DISCOVERY' AND scope_id IS NULL AND warehouse_code IS NULL) OR (run_role = 'WAREHOUSE_SYNC' AND scope_id IS NOT NULL AND warehouse_code IS NOT NULL)))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='执行尝试、覆盖证明和版本头';
CREATE TABLE ll_selfop_sync_stage (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
run_id BIGINT NOT NULL COMMENT '首次写入该暂存对象的执行尝试',
stage_batch_id BIGINT NOT NULL COMMENT '出库取共享发现 task.id,便于断点续取;库存取本次 run.id,严禁跨尝试混页',
last_fetch_run_id BIGINT NOT NULL COMMENT '最后一次补齐该对象的执行尝试,保留重试来源',
observation_sequence BIGINT NULL COMMENT '该完整出库详情实际请求的采集代次;有效出库对象必填,目录待补对象和库存为空;不能填 task 调度序号',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
previous_warehouse_code VARCHAR(64) NULL COMMENT '路由时从已有单据识别的原仓库;归并前再校验,跨仓时通知两仓',
object_type VARCHAR(16) NOT NULL COMMENT 'OUTBOUND_ORDER 或 PRODUCT_STOCK',
object_key_hash CHAR(64) NOT NULL COMMENT '规范化业务键摘要;原业务键保留在载荷中并核对',
first_page_no INT NOT NULL COMMENT '首次发现页码',
observed_at_utc DATETIME(3) NOT NULL COMMENT '实际接收该对象的时刻',
content_hash CHAR(64) NOT NULL COMMENT '完整规范化对象摘要',
payload_json JSON NOT NULL COMMENT '目录阶段可先存订单头,详情齐后补完整 SKU;VALID 后不再修改;库存保存产品库存字段',
before_payload_json JSON NULL COMMENT '订单归并事务内记录归并前的完整规范化事实;新增单为空',
validation_status VARCHAR(16) NOT NULL COMMENT '暂存校验状态:PENDING待核验、VALID有效、INVALID异常',
validation_code VARCHAR(64) NULL COMMENT '字段缺失、冲突、未知时区等原因',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_stage_object (stage_batch_id,object_type,object_key_hash),
KEY idx_selfop_stage_history (object_type,object_key_hash,stage_batch_id),
KEY idx_selfop_stage_observation (object_type,object_key_hash,validation_status,observation_sequence),
KEY idx_selfop_stage_route (stage_batch_id,warehouse_code,validation_status),
CONSTRAINT chk_selfop_sync_stage CHECK (first_page_no > 0 AND (object_type <> 'OUTBOUND_ORDER' OR validation_status <> 'VALID' OR observation_sequence IS NOT NULL))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='待验证事实与修订证据';
CREATE TABLE ll_selfop_outbound_order (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
customer_code VARCHAR(64) NOT NULL COMMENT '领星货主原始编码,不等同平台客户标识',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
delivery_no VARCHAR(128) NOT NULL COMMENT 'OMP 发货单号,采用列表及详情同一身份',
source_no VARCHAR(128) NULL COMMENT 'WMS 来源出库单号,缺失不以内部 ID 回退展示',
source_status INT NOT NULL COMMENT '原始状态,100 已出库、99 已取消;不改造成内部状态码',
source_created_time VARCHAR(64) NULL COMMENT '来源创建时间原始字符串,不使用采集时间替代',
source_outbound_time VARCHAR(64) NULL COMMENT '来源实际出库时间原始字符串,不使用采集时间替代',
source_timezone VARCHAR(64) NULL COMMENT '解析采用的源时区',
outbound_at_utc DATETIME(3) NULL COMMENT '已核准的实际出库时间点;非出库状态可空',
business_date DATE NULL COMMENT '已核准业务时区下的出库日',
business_timezone VARCHAR(64) NOT NULL COMMENT '该事实当前归属仓所用业务时区,迁仓后重新确定业务日',
sales_eligible TINYINT NOT NULL DEFAULT 0 COMMENT '仅已出库、时间与全部数量有效时为 1',
revision_no BIGINT NOT NULL DEFAULT 1 COMMENT '该单内容变更次数,不等于拉取次数',
content_hash CHAR(64) NOT NULL COMMENT '订单头及完整 SKU 明细规范化摘要',
last_run_id BIGINT NOT NULL COMMENT '最后一次确认或修订的执行尝试',
last_observation_sequence BIGINT NOT NULL COMMENT '最后接受的完整详情采集代次;仅防旧观测重放,不按 task 调度序号拒绝较晚实际读取的事实,不冒充领星源版本号',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_order (source_account,customer_code,delivery_no),
KEY idx_selfop_order_daily (source_account,warehouse_code,sales_eligible,business_date,id),
KEY idx_selfop_order_run (last_run_id),
CONSTRAINT chk_selfop_outbound_order CHECK (revision_no > 0 AND last_observation_sequence > 0 AND sales_eligible IN (0,1) AND (sales_eligible = 0 OR (source_status = 100 AND source_timezone IS NOT NULL AND outbound_at_utc IS NOT NULL AND business_date IS NOT NULL)))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='最后确认的单据事实';
CREATE TABLE ll_selfop_outbound_item (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
order_id BIGINT NOT NULL COMMENT '对应外部出库事实',
sku_code VARCHAR(128) NOT NULL COMMENT '原始 productSku',
product_name VARCHAR(255) NULL COMMENT '来源商品名称,仅作展示',
actual_quantity DECIMAL(20,6) NOT NULL COMMENT '详情 actualDeliveryQty,必须为非负有效数值',
quantity_unit VARCHAR(32) NOT NULL COMMENT '已核准业务单位;未确认单位不发布正式数量统计',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_order_sku (order_id,sku_code),
KEY idx_selfop_item_sku (sku_code,order_id),
CONSTRAINT chk_selfop_outbound_item CHECK (actual_quantity >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='整单替换的实际出库明细';
CREATE TABLE ll_selfop_inventory_snapshot (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
snapshot_run_id BIGINT NOT NULL COMMENT 'INVENTORY 执行尝试;发布后该批明细不可修改',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
customer_code VARCHAR(64) NOT NULL COMMENT '领星货主原始编码,不等同平台客户标识',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
sku_code VARCHAR(128) NOT NULL COMMENT '原始产品 SKU',
product_quality SMALLINT NOT NULL COMMENT '来源品质,当前 0 正品、1 次品;全量均保存,不套用整箱库存',
product_name VARCHAR(255) NULL COMMENT '来源名称',
physical_quantity DECIMAL(20,6) NULL COMMENT '来源stkQty实物库存,未知为空',
available_quantity DECIMAL(20,6) NULL COMMENT '来源useStkQty可用库存,未知为空,不再次扣冻结',
frozen_quantity DECIMAL(20,6) NULL COMMENT '来源freezeQty冻结库存,未知为空',
transit_quantity DECIMAL(20,6) NULL COMMENT '来源transitQty在途数量,未知为空,不计可售库存',
source_unique_key VARCHAR(512) NULL COMMENT '原 uniqueKey4tenant,只作来源证据',
observed_at_utc DATETIME(3) NOT NULL COMMENT '所在页实际采集时间;缺行占位取本批采集完成时间',
quality_status VARCHAR(16) NOT NULL COMMENT 'VALID、UNKNOWN、INVALID;STALE 按批次年龄实时派生',
quality_reason VARCHAR(64) NULL COMMENT 'SOURCE_ROW_MISSING、FIELD_MISSING、NEGATIVE_QUANTITY 等',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_stock_snapshot (snapshot_run_id,source_account,customer_code,warehouse_code,sku_code,product_quality),
KEY idx_selfop_stock_lookup (source_account,customer_code,warehouse_code,sku_code,product_quality,snapshot_run_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='产品库存全量批次明细';
CREATE TABLE ll_selfop_sku_daily_sales (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
sales_run_id BIGINT NOT NULL COMMENT 'OUTBOUND 执行尝试,同时是计算版本',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
customer_code VARCHAR(64) NOT NULL COMMENT '领星货主原始编码,不等同平台客户标识',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
sku_code VARCHAR(128) NOT NULL COMMENT '原始产品 SKU',
business_date DATE NOT NULL COMMENT '已核准业务日',
outbound_quantity DECIMAL(20,6) NOT NULL COMMENT '有效出库实际件数之和,非负',
outbound_order_count BIGINT NOT NULL COMMENT '该维度去重发货单数,非负',
quantity_unit VARCHAR(32) NOT NULL COMMENT '同一统计维度内一致的业务单位',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_daily_version (sales_run_id,source_account,customer_code,warehouse_code,sku_code,business_date),
KEY idx_selfop_daily_window (sales_run_id,business_date,customer_code,sku_code),
CONSTRAINT chk_selfop_sku_daily_sales CHECK (outbound_quantity >= 0 AND outbound_order_count >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='完整销量版本的稀疏日事实';
CREATE TABLE ll_selfop_sku_profile (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
profile_run_id BIGINT NOT NULL COMMENT '本仓销量或库存候选版本;与对应 daily/snapshot 使用同一 run,发布后该版本全部维度行不可修改',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
customer_code VARCHAR(64) NOT NULL COMMENT '领星货主原始编码,不等同平台客户标识',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
sku_code VARCHAR(128) NOT NULL COMMENT '原始产品 SKU',
product_name VARCHAR(255) NULL COMMENT '本版本确认的名称,不实时连接其他版本名称',
quantity_unit VARCHAR(32) NULL COMMENT '本版本已核准单位;未知或两版本单位冲突时不计算混合指标',
first_seen_at_utc DATETIME(3) NULL COMMENT '本证据族真实观测到本仓商品的最早接收时刻;缺行占位不能生成观察证据',
earliest_evidence_at_utc DATETIME(3) NULL COMMENT '库存版取真实库存首次观察时刻;销量版从该版有效事实重新求最早已核准出库时间,可随改期、取消或迁仓撤回/后移',
evidence_type VARCHAR(24) NOT NULL COMMENT 'INVENTORY_OBSERVATION、VALID_OUTBOUND、NONE;不得将销量证据复制成库存真实观察证据',
evidence_run_id BIGINT NULL COMMENT '本证据族真实依据的采集批次,无证据占位为空',
last_seen_run_id BIGINT NULL COMMENT '本证据族最近真实观测批次,无证据占位为空',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_profile_version (profile_run_id,source_account,customer_code,warehouse_code,sku_code),
KEY idx_selfop_profile_evidence (profile_run_id,earliest_evidence_at_utc,customer_code,sku_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='随发布版本固定的 SKU 维度与观察依据';
@@ -0,0 +1,115 @@
openapi: 3.0.3
info:
title: Self-operated Analytics Internal Egress Authority
version: 1.0.0
paths:
/internal/lastleg/self-operated-analytics/egress/authorize:
post:
operationId: authorizeSelfoperatedEgressAttempt
summary: 一次性消费已持久预留的领星请求许可
description: >-
仅内部服务令牌。客户端已登记的 context 和 operation 必须完全匹配;
requestHash 是 Integration 对 OMP 路径和有序业务 JSON 的摘要,首次消费绑定,
后续完成必须完全匹配。同 attemptId 再次消费拒绝。allowedAttempts 固定 1,
expiresAt 最多 30 秒且不超过验证根截止或人工独占窗口。OFF 默认拒绝,
非 production 环境拒绝 BUSINESS。独占交接证明及接续预算由服务端配置核验。
security: [{ internalServiceToken: [] }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/AuthorizationRequest' }
responses:
'200':
description: HTTP 200;许可 code=200,正常拒绝 code=B0001,data 为显式预算决策
content:
application/json:
schema:
type: object
properties:
code: { type: string }
data:
oneOf:
- { $ref: '#/components/schemas/AttemptPermit' }
- { $ref: '#/components/schemas/AuthorizationDenial' }
'401': { description: 内部令牌无效 }
'503': { description: 内部令牌未配置 }
/internal/lastleg/self-operated-analytics/egress/complete:
post:
operationId: completeSelfoperatedEgressAttempt
summary: 记录真实尝试次数和账号冷却
description: >-
回调 context、operation、requestHash 必须匹配已消费许可。actualHttpAttempts 仅 0 或 1;
即使 0 也不退回预留,响应丢失同样保留保守消耗。重复已确认完成为幂等成功。
429 对账号全部采集族持久冷却;验证根 DEAD、run FAILED、禁止自动续跑。
未确认结果的许可到期后保守冷却,不使用换日、换仓、重试或重启清零预算。
security: [{ internalServiceToken: [] }]
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CompletionRequest' }
responses:
'200':
description: ApiResponse code 字符串 200,data 为布尔 true
content:
application/json:
schema:
type: object
properties:
code: { type: string }
data: { type: boolean, enum: [true] }
'401': { description: 内部令牌无效 }
components:
securitySchemes:
internalServiceToken: { type: apiKey, in: header, name: X-Internal-Service-Token }
schemas:
EgressContext:
type: object
required: [sourceAccount, executionPurpose, rootTaskId, sessionId, attemptId, exclusiveGrantId]
properties:
sourceAccount: { type: string, maxLength: 64 }
executionPurpose: { type: string, enum: [VALIDATION, BUSINESS] }
rootTaskId: { type: string, pattern: '^[0-9]+$' }
sessionId: { type: string, maxLength: 128 }
attemptId: { type: string, maxLength: 128 }
exclusiveGrantId: { type: string, maxLength: 128 }
Operation:
type: string
enum: [WAREHOUSES, OUTBOUND_QUERY, OUTBOUND_LOCATE, OUTBOUND_DETAIL, PRODUCT_INVENTORY]
AuthorizationRequest:
type: object
required: [context, operation, requestHash]
properties:
context: { $ref: '#/components/schemas/EgressContext' }
operation: { $ref: '#/components/schemas/Operation' }
requestHash: { type: string, pattern: '^[a-f0-9]{64}$' }
AuthorizationDenial:
type: object
required: [errorCode, sampleDone, waitUntil]
properties:
errorCode: { type: string, pattern: '^[A-Z][A-Z0-9_]{0,63}$' }
sampleDone: { type: boolean }
waitUntil: { type: string, format: date-time, nullable: true, description: UTC Instant 或显式 null }
AttemptPermit:
allOf:
- { $ref: '#/components/schemas/AuthorizationRequest' }
- type: object
required: [allowedAttempts, expiresAt, exclusiveConfirmed, budgetConsumed]
properties:
allowedAttempts: { type: integer, enum: [1] }
expiresAt: { type: string, format: date-time }
exclusiveConfirmed: { type: boolean, enum: [true] }
budgetConsumed: { type: boolean, enum: [true] }
CompletionRequest:
allOf:
- { $ref: '#/components/schemas/AuthorizationRequest' }
- type: object
required: [actualHttpAttempts, accountPaused]
properties:
actualHttpAttempts: { type: integer, minimum: 0, maximum: 1 }
errorCode: { type: string, nullable: true }
upstreamStatus: { type: integer, nullable: true }
sourceCode: { type: integer, nullable: true }
accountPaused: { type: boolean }
cooldownUntil: { type: string, format: date-time, nullable: true }
@@ -0,0 +1,62 @@
openapi: 3.0.3
info:
title: Platform Self-operated Analytics Sync Commands
version: 1.0.0
paths:
/api/platform/v1/last-leg/self-operated-analytics/sync-tasks:
post:
operationId: requestSelfoperatedAnalyticsSyncTask
summary: 创建人工采集、复查、重建或恢复任务
description: >-
仅平台账号且须 platform:self-operated-analytics:sync 权限。命令先持久化,
不在 HTTP 请求内运行历史采集。collectionMode 默认 OFF;VALIDATION 仅用于持久预算内的样本暂存,
BUSINESS 仅允许生产环境,并要求真实出口取得服务端核验的人工独占许可。
出库来源时间及业务时间统一 Asia/Shanghai;首次正式目标固定为 E0 前两个滚动月。
BACKFILL 单片不超过一天。RETRY 使用 taskNo 和非空 reason 恢复原分仓逻辑任务,
保留半归并屏障及旧尝试,拒绝验证会话复活、账号共享任务伪装单仓、有效执行租约及上游未齐;
requestKey 同键异载荷拒绝。成功受理只表示排队,不表示采集或发布成功。
security:
- bearerAuth: []
x-required-authorities:
- platform:self-operated-analytics:sync
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SyncCommand'
responses:
'200':
description: 平台 ApiResponse 包络,成功 code 为字符串 200;返回稳定业务任务号与 ACCEPTED
content:
application/json:
schema:
type: object
properties:
code: { type: string }
message: { type: string }
data:
type: object
properties:
taskNo: { type: string }
warehouseCode: { type: string }
status: { type: string, enum: [ACCEPTED] }
'401': { description: 未认证 }
'403': { description: 非平台身份或无独立写权限 }
components:
securitySchemes:
bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT }
schemas:
SyncCommand:
type: object
required: [requestKey, warehouseCode, action]
properties:
requestKey: { type: string, minLength: 1, maxLength: 100 }
warehouseCode: { type: string, minLength: 1, maxLength: 64 }
action: { type: string, enum: [INVENTORY, BACKFILL, RECHECK, REBUILD, RETRY, VALIDATION] }
taskNo: { type: string, minLength: 1, maxLength: 64, description: RETRY 必填,原始分仓业务任务号 }
reason: { type: string, minLength: 1, maxLength: 500, description: RETRY 必填,随操作人和原任务审计保存 }
sourceFrom: { type: string, example: '2026-10-11T00:00:00' }
sourceUntil: { type: string, example: '2026-10-12T00:00:00' }
customerCode: { type: string, maxLength: 64, description: RECHECK 必填 }
deliveryNo: { type: string, maxLength: 128, description: RECHECK 必填 }
@@ -0,0 +1,700 @@
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为可靠点合计,完整/部分/未知日数独立。
切换图表不改变完整7/30日榜单及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/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: 完整7/30日热销Top100
description: '独立截至queryAsOf昨日的完整窗口,数量大于零,数量降序、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/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: 正品库存与固定30日可售天数
description: '固定30天,不接受图表周期。可售仅品质0可用量,不扣冻结或加在途次品。先UNKNOWN/INVALID/STALE,再有效零库存为0,再校验正库存单位、窗口、观察期;零销量天数为空。 权限platform:self-operated-analytics:list。'
parameters:
- {$ref: '#/components/parameters/attention'}
- {$ref: '#/components/parameters/sortBy'}
- {$ref: '#/components/parameters/coverageDaysThreshold'}
- {$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/sync-overview:
get:
summary: 各仓任务族运行概览
description: 'warehouseCode可选。轻量读取scope/task/run/账号保护。无发布版和OFF仍返回配置任务。首采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,后页完整重传;新插入不挤移页。只读有限检查点,不展开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回退。详情含最新尝试和关联共享上游。 权限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: '纯运行元数据分页。当前尝试读同一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:
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:
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}}
Protection:
type: object
properties:
accountCooldownUntil: {type: string, format: date-time, nullable: true}
accountPauseReason: {type: string, nullable: true}
dailyRequestBudget: {type: integer, nullable: true}
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:
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'}
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}
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'}
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'}}
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}}
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}