- 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>
198 lines
9.4 KiB
JSON
198 lines
9.4 KiB
JSON
{
|
||
"$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" }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|