arm-tabular-parser/api/contracts/recognition-result.schema.json
Andrey Epifancev 947d2a6a51 contract: v1.1 — OsvRow.extra, CONTRACT_VERSION 1.1, копия схемы
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 11:57:22 +04:00

199 lines
10 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.1",
"description": "Один файл (stored_file) → один job → N документов. Сервисы не знают БД: только структура файла. Нормализация счетов, резолв контрагентов, проверки — в arm-core.",
"$comment": "Версионирование: schema_version = MAJOR.MINOR. MINOR (1.1) — необязательные поля и новые значения enum; MAJOR (2.0) — удаление/переименование полей, смена типов или семантики. Потребитель принимает тот же MAJOR и любой MINOR. Новый MINOR раскатывается сначала на потребителей (ядро и сервисы обновляют копии схем раньше, чем производитель начнёт слать 1.1), потому что закрытые enum отвергают незнакомые значения.",
"type": "object",
"required": ["schema_version", "job_id", "file_id", "service", "status", "documents"],
"properties": {
"schema_version": { "type": "string", "pattern": "^1\\.\\d+$", "description": "MAJOR.MINOR; производитель контракта v1.1 пишет \"1.1\"" },
"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" },
"extra": { "type": ["object", "null"], "description": "нераспознанные колонки внутри таблицы: заголовок колонки → текст ячейки (§1.2)", "additionalProperties": { "type": ["string", "null"] } }
}
}
},
"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"], "minimum": 0, "maximum": 100 },
"inn": { "type": ["string", "null"] },
"inn_confidence": { "type": ["number", "null"], "minimum": 0, "maximum": 100 },
"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"], "minimum": 0, "maximum": 100 },
"line_name": { "type": "string" },
"line_name_confidence": { "type": ["number", "null"], "minimum": 0, "maximum": 100 },
"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" }
}
}
}
}
}
}
}
}
}
}