arm-ka-docs/contracts/recognition-result.schema.json
Andrey Epifancev 65c3809efe Контракт v1.0: схема результата распознавания без пометки «черновик»
- title без «ЧЕРНОВИК v1, уточнить в Срезе 2»
- $comment о правилах версионирования (MAJOR.MINOR)
- NOT_IMPLEMENTED в перечне error.code
- пустой documents допустим только при status = error (if/then, minItems: 1 для done и needs_check)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 17:58:47 +04:00

198 lines
9.4 KiB
JSON
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.

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "arm-ka/recognition-result/v1",
"title": "Результат распознавания файла (tabular-parser / scan-gateway), контракт v1.0",
"description": "Один файл (stored_file) → один job → N документов. Сервисы не знают БД: только структура файла. Нормализация счетов, резолв контрагентов, проверки — в arm-core.",
"$comment": "Версионирование: schema_version = MAJOR.MINOR. MINOR (1.1) — необязательные поля и новые значения enum; MAJOR (2.0) — удаление/переименование полей, смена типов или семантики. Потребитель принимает тот же MAJOR и любой MINOR.",
"type": "object",
"required": ["schema_version", "job_id", "file_id", "service", "status", "documents"],
"properties": {
"schema_version": { "const": "1.0" },
"job_id": { "type": "string", "format": "uuid" },
"file_id": { "type": "string", "format": "uuid" },
"service": {
"type": "object",
"required": ["name", "version"],
"properties": {
"name": { "enum": ["tabular-parser", "scan-gateway"] },
"version": { "type": "string" }
}
},
"status": { "enum": ["done", "needs_check", "error"] },
"error": {
"type": ["object", "null"],
"properties": {
"code": { "enum": ["UNSUPPORTED_FORMAT", "UNREADABLE", "TIMEOUT", "SCHEMA_MISMATCH", "NOT_IMPLEMENTED", "FILE_READ_ERROR", "INVALID_FORMAT", "INVALID_DOCUMENT", "RECOGNITION_FAILED", "UNKNOWN_ERROR"] },
"message": { "type": "string" }
}
},
"metrics": {
"type": "object",
"properties": {
"duration_ms": { "type": "integer" },
"pages": { "type": "integer" },
"rows": { "type": "integer" },
"fields_total": { "type": "integer" },
"fields_low_confidence": { "type": "integer" },
"fields_unrecognized": { "type": "integer" },
"warnings": { "type": "array", "items": { "type": "string" } }
}
},
"raw_s3_key": { "type": ["string", "null"], "description": "scan-gateway: raw/{job_id}.json — сырой ответ ИС Сканирование; в БД не регистрируется" },
"documents": {
"type": "array",
"items": { "oneOf": [ { "$ref": "#/$defs/osvDocument" }, { "$ref": "#/$defs/statementDocument" } ] }
}
},
"if": {
"properties": { "status": { "enum": ["done", "needs_check"] } },
"required": ["status"]
},
"then": {
"properties": { "documents": { "minItems": 1 } }
},
"$defs": {
"money": { "type": ["string", "null"], "pattern": "^-?\\d+(\\.\\d{1,2})?$", "description": "Decimal как строка, чтобы не терять копейки в JSON" },
"osvDocument": {
"type": "object",
"required": ["document_type", "locator", "header", "group_schema", "rows"],
"properties": {
"document_type": { "const": "OSV" },
"locator": { "type": "string", "examples": ["sheet:Лист_1"] },
"header": {
"type": "object",
"required": ["organization_name", "account_code_raw", "period_text"],
"properties": {
"organization_name": { "type": "string", "description": "как в r1 файла" },
"organization_inn": { "type": ["string", "null"] },
"account_code_raw": { "type": "string", "examples": ["60", "58.03"] },
"period_text": { "type": "string", "examples": ["1 квартал 2025 г.", "2024 г."] },
"period_year": { "type": ["integer", "null"] },
"period_quarter": { "enum": ["Q1", "Q2", "Q3", "Q4", null] },
"is_cumulative": { "type": ["boolean", "null"], "description": "по тексту; ядро может переопределить по данным (OQ-02)" },
"data_type": { "enum": ["BU", "NU", "SUM", "CURRENCY", "QUANTITY", null] },
"currency": { "type": ["string", "null"], "examples": ["RUB", "руб."] },
"header_variant": { "enum": [1, 2] }
}
},
"group_schema": {
"type": "array",
"description": "порядок группировок из шапки, после первого ACCOUNT",
"items": {
"type": "object",
"required": ["type"],
"properties": {
"type": { "enum": ["ACCOUNT", "DEPARTMENT", "COUNTERPARTY", "CONTRACT", "OTHER"] },
"name": { "type": "string", "description": "исходный текст из шапки" },
"has_inn": { "type": "boolean" }
}
}
},
"columns": {
"type": "object",
"description": "диагностика: какие колонки листа были приняты за шесть сумм и ИНН",
"additionalProperties": { "type": "string" }
},
"rows": {
"type": "array",
"items": {
"type": "object",
"required": ["row_number", "level", "row_value", "group_type"],
"properties": {
"row_number": { "type": "integer" },
"level": { "type": "integer" },
"parent_row_number": { "type": ["integer", "null"] },
"row_value": { "type": "string" },
"group_type": { "enum": ["ACCOUNT", "DEPARTMENT", "COUNTERPARTY", "CONTRACT", "OTHER", "TOTAL"] },
"group_name": { "type": ["string", "null"] },
"account_code_raw": { "type": ["string", "null"], "description": "код текущей ветки, как в файле (60.1)" },
"counterparty_name": { "type": ["string", "null"] },
"counterparty_inn": { "type": ["string", "null"] },
"data_type": { "enum": ["BU", "NU", "SUM", "CURRENCY", "QUANTITY", null] },
"opening_debit": { "$ref": "#/$defs/money" },
"opening_credit": { "$ref": "#/$defs/money" },
"turnover_debit": { "$ref": "#/$defs/money" },
"turnover_credit": { "$ref": "#/$defs/money" },
"closing_debit": { "$ref": "#/$defs/money" },
"closing_credit": { "$ref": "#/$defs/money" }
}
}
},
"checks": {
"type": "object",
"properties": {
"total_row_matches_root": { "type": "boolean" },
"balance_identity_violations": { "type": "array", "items": { "type": "integer" }, "description": "row_number строк, где opening−turnover≠closing" },
"parent_sum_violations": { "type": "array", "items": { "type": "integer" } }
}
}
}
},
"statementDocument": {
"type": "object",
"required": ["document_type", "locator", "header", "columns", "lines"],
"properties": {
"document_type": { "enum": ["BALANCE", "INCOME", "OTHER"] },
"locator": { "type": "string", "examples": ["pages:1-2"] },
"header": {
"type": "object",
"properties": {
"form_name": { "type": "string" },
"organization_name": { "type": ["string", "null"] },
"organization_name_confidence": { "type": ["number", "null"] },
"inn": { "type": ["string", "null"] },
"inn_confidence": { "type": ["number", "null"] },
"report_date_text": { "type": ["string", "null"] },
"report_date": { "type": ["string", "null"], "format": "date" },
"units": { "type": ["string", "null"], "examples": ["тыс. руб."] },
"okud": { "type": ["string", "null"] },
"okpo": { "type": ["string", "null"] },
"okopf": { "type": ["string", "null"] },
"okfs": { "type": ["string", "null"] },
"address": { "type": ["string", "null"] }
}
},
"columns": {
"type": "array",
"items": {
"type": "object",
"required": ["column_index", "label"],
"properties": {
"column_index": { "type": "integer" },
"label": { "type": "string", "examples": ["На 30 сентября 2025 г."] },
"period_date": { "type": ["string", "null"], "format": "date" }
}
}
},
"lines": {
"type": "array",
"items": {
"type": "object",
"required": ["line_code", "line_name", "values"],
"properties": {
"line_code": { "type": "string" },
"line_code_confidence": { "type": ["number", "null"] },
"line_name": { "type": "string" },
"line_name_confidence": { "type": ["number", "null"] },
"values": {
"type": "array",
"items": {
"type": "object",
"required": ["column_index"],
"properties": {
"column_index": { "type": "integer" },
"amount": { "$ref": "#/$defs/money" },
"string_value": { "type": ["string", "null"] },
"confidence": { "type": ["number", "null"], "minimum": 0, "maximum": 100 },
"is_recognized": { "type": "boolean" }
}
}
}
}
}
}
}
}
}
}