docs: OQ-138 закрыт, контракт — $comment и примеры (M-12), §12/§7, статус Среза 2b #45
@ -450,7 +450,8 @@ variance = |amount_a − amount_b|; variance_pct = variance / min(amount_a, amou
|
|||||||
(+1215), `1300`, `1400`, `1500`, `1600 = 1100 + 1200`, `1700 = 1300 + 1400 + 1500`, `1600 = 1700` — и ОФР — `2100`, `2200`,
|
(+1215), `1300`, `1400`, `1500`, `1600 = 1100 + 1200`, `1700 = 1300 + 1400 + 1500`, `1600 = 1700` — и ОФР — `2100`, `2200`,
|
||||||
`2300`; **мягкими** (предупреждение) — `2400 = 2300 − 2410 + 2420` и варианты ФСБУ 4/2023 (`2400 = 2300 + 2410 + 2460`,
|
`2300`; **мягкими** (предупреждение) — `2400 = 2300 − 2410 + 2420` и варианты ФСБУ 4/2023 (`2400 = 2300 + 2410 + 2460`,
|
||||||
`2410 = 2411 + 2412`), `2500 = 2400 + 2510 + 2520 + 2530` и «сумма пятизначных подстрок = родитель»
|
`2410 = 2411 + 2412`), `2500 = 2400 + 2510 + 2520 + 2530` и «сумма пятизначных подстрок = родитель»
|
||||||
(`ASSUMPTION(OQ-12)`). Допуск ±1 в единицах формы, расходы — двойной расчёт знаков (`abs_terms`). Межформенная проверка
|
(`ASSUMPTION(OQ-12)`). Допуск ±1 в единицах формы (расхождение до 0,001 % наибольшего числа соотношения — округление,
|
||||||
|
мягкое, OQ-138), расходы — двойной расчёт знаков (`abs_terms`). Межформенная проверка
|
||||||
`1370 − 1370(начало года) = 2400` парсером не выполняется. Это сигнал о структуре и данных файла, а не замена проверок
|
`1370 − 1370(начало года) = 2400` парсером не выполняется. Это сигнал о структуре и данных файла, а не замена проверок
|
||||||
ядра: ядро (Срез 3) пересчитывает §7 и ведёт акцепт (`financial_statement_meta.checks_accepted_*`).
|
ядра: ядро (Срез 3) пересчитывает §7 и ведёт акцепт (`financial_statement_meta.checks_accepted_*`).
|
||||||
|
|
||||||
@ -875,11 +876,11 @@ OQ-92 (пустые «Организация»/«Группа компаний»
|
|||||||
отсутствующий код = 0, соотношение проверяется, только если присутствует его цель; правая часть считается дважды — как
|
отсутствующий код = 0, соотношение проверяется, только если присутствует его цель; правая часть считается дважды — как
|
||||||
записано и с членами `abs_terms` по модулю (1С выгружает расходы со знаком минус, 66н — в скобках). Результат —
|
записано и с членами `abs_terms` по модулю (1С выгружает расходы со знаком минус, 66н — в скобках). Результат —
|
||||||
`documents[].checks` (`relations_failed`, `soft_relations_failed`, `duplicate_line_codes`) и предупреждения.
|
`documents[].checks` (`relations_failed`, `soft_relations_failed`, `duplicate_line_codes`) и предупреждения.
|
||||||
**Фактически сходятся полные формы только у Межениновской**: книга НПЗ (`npz/2025-Q3`) — ББ `needs_check`: `1600 = 1700`
|
Расхождение жёсткого соотношения больше ±1, но не больше 0,001 % от наибольшего по модулю числа соотношения — **округление итогов** (OQ-138, решение владельца 06.10.2026: единицам шапки верим): уходит в `soft_relations_failed` с предупреждением «сошлось в пределах округления», статус не меняется (`rounding_tolerance_percent` в словаре). Пример: книга НПЗ (`npz/2025-Q3`) — `1600 = 1700` расходится на 1.94 / 9.02 / 2.48 при итогах ~17 млрд,
|
||||||
расходится на 1.94 / 9.02 / 2.48 руб., потому что значения в рублях с копейками при шапке «тыс. руб.»; допуск ±1 остаётся
|
ОФР Унагранде Компани (стр. 1) — итог 2100 округлён до тысяч, ОФР Унагранде Групп 3 кв. 2025 — 2200 = −1 365 000 как
|
||||||
(решение владельца 06.10.2026, вариант А, OQ-138). ОФР НПЗ и ОФР Унагранде (стр. 1) тоже `needs_check` по 2100/2200/2300
|
малая разность слагаемых ~393 млн; все `done`. Пятизначная подстрока относится к ближайшей четырёхзначной строке выше с
|
||||||
по той же причине; ББ Унагранде (стр. 1) — только актив, `1600 = 1700` не сходится. Это сигнал о данных файла, а не о
|
теми же тремя первыми цифрами (12310 под 1230). ББ Унагранде (стр. 1) — только актив, `1600 = 1700` не сходится,
|
||||||
неверно угаданной структуре; допуск под файл не подгоняется.
|
`needs_check`.
|
||||||
8. **Расшифровки** (0710003/0710004, пояснения, лист «Примечания» шаблона) — `DISCLOSURE` с `locator` и шапкой, если
|
8. **Расшифровки** (0710003/0710004, пояснения, лист «Примечания» шаблона) — `DISCLOSURE` с `locator` и шапкой, если
|
||||||
нашлась, без `columns`/`lines`; на статус не влияет (OQ-23). Книга только из таких листов — `done`.
|
нашлась, без `columns`/`lines`; на статус не влияет (OQ-23). Книга только из таких листов — `done`.
|
||||||
9. **Склейка**: листы-продолжения внутри книги присоединяются к последнему открытому документу формы, если число колонок
|
9. **Склейка**: листы-продолжения внутри книги присоединяются к последнему открытому документу формы, если число колонок
|
||||||
|
|||||||
@ -161,9 +161,9 @@ arm-tabular-parser#11, OQ-131…OQ-135. ИНН организаций в шап
|
|||||||
| Шаблоны | `templates/` | 66н и ФСБУ 4/2023: коды есть, сумм и шапки нет; заголовок на две строки; в шаблоне ФСБУ «АКТИВ» и код 1110 в одной строке (OQ-142) |
|
| Шаблоны | `templates/` | 66н и ФСБУ 4/2023: коды есть, сумм и шапки нет; заголовок на две строки; в шаблоне ФСБУ «АКТИВ» и код 1110 в одной строке (OQ-142) |
|
||||||
|
|
||||||
**Манифест** `tabular-parser/api/tests/statements_manifest.yaml`: для каждого из 18 файлов — организация, ИНН, документы по
|
**Манифест** `tabular-parser/api/tests/statements_manifest.yaml`: для каждого из 18 файлов — организация, ИНН, документы по
|
||||||
порядку (`type`, `status`, `complete`, причина `needs_check`, `failed_relations`). Статусы сверены прогоном: `done` только
|
порядку (`type`, `status`, `complete`, причина `needs_check`, `failed_relations`). Статусы сверены прогоном: `done` — полные
|
||||||
у Межениновской (ББ и ОФР); остальные — `needs_check` по данным файла (рубли с копейками при шапке «тыс. руб.», только
|
формы (Межениновская ББ и ОФР, книга НПЗ, ОФР стр. 1 Унагранде Компани и Групп 3 кв. 2025: расхождения итогов —
|
||||||
актив, страница 2 без шапки, шаблон без сумм), НПЗ — `1600 = 1700` расходится на 1.94 / 9.02 / 2.48 руб. (OQ-138).
|
округление, мягкие, OQ-138); `needs_check` — по данным файла: только актив (ББ стр. 1), страница 2 без шапки, шаблон без сумм.
|
||||||
Таблица «файл → статус» — README `tabular-parser`, «Парсер форм».
|
Таблица «файл → статус» — README `tabular-parser`, «Парсер форм».
|
||||||
|
|
||||||
**Golden** `fixtures/golden/expected_statement_parse/<тот же путь без расширения>.json` — 24 снимка (18 реальных файлов +
|
**Golden** `fixtures/golden/expected_statement_parse/<тот же путь без расширения>.json` — 24 снимка (18 реальных файлов +
|
||||||
|
|||||||
@ -143,7 +143,7 @@
|
|||||||
| OQ-135 | Отчёт 1С «Анализ счета» с отбором по контрагентам группы (`fixtures/analysis-reports/`, в именах файлов «ОСВ_…ПоКомпаниямГруппы»): не ОСВ, но содержит ВГО по корреспонденции счетов. Нужен ли отдельный тип документа для Среза 5, или ВГО считаются только из ОСВ | пакет ДКБ 06.10.2026 | `document_type`, Срез 5 | открыт: допущение — не разбирать; парсер отвечает `INVALID_DOCUMENT` |
|
| OQ-135 | Отчёт 1С «Анализ счета» с отбором по контрагентам группы (`fixtures/analysis-reports/`, в именах файлов «ОСВ_…ПоКомпаниямГруппы»): не ОСВ, но содержит ВГО по корреспонденции счетов. Нужен ли отдельный тип документа для Среза 5, или ВГО считаются только из ОСВ | пакет ДКБ 06.10.2026 | `document_type`, Срез 5 | открыт: допущение — не разбирать; парсер отвечает `INVALID_DOCUMENT` |
|
||||||
| OQ-136 | ИНН организаций пакета ДКБ (Цимлянский, НКЗ, Новоросметалл, Приманыческий, Агрокомплекс) в шапках ОСВ отсутствуют; для теста консолидации по этим группам нужны ИНН и состав ГК/ГСК (выгрузка ЕЦП или список от ДКБ) | пакет ДКБ 06.10.2026 | seed/фикстуры справочников, тесты Среза 4–5 на новых группах | открыт |
|
| OQ-136 | ИНН организаций пакета ДКБ (Цимлянский, НКЗ, Новоросметалл, Приманыческий, Агрокомплекс) в шапках ОСВ отсутствуют; для теста консолидации по этим группам нужны ИНН и состав ГК/ГСК (выгрузка ЕЦП или список от ДКБ) | пакет ДКБ 06.10.2026 | seed/фикстуры справочников, тесты Среза 4–5 на новых группах | открыт |
|
||||||
| OQ-137 | Раскладка горячих папок ИС Сканирование: scan-gateway кладёт `Input/<job_id>_<original_name>` через временный `Tmp/.<имя>.part`, ничего не удаляет; PDFWorker старого АРМ (`RSHB/armka_file_worker`, проверен в контуре) кладёт `Input/<task_id>.<ext>` через временный `<назначение>.<uuid>.tmp` рядом (ИС игнорирует `*.tmp`), читает батч `Output/<task_id>/*.json` и удаляет `Output/<task_id>/` и входящий файл после чтения. Какая раскладка актуальна? | сравнение `armka_file_worker` (README «Файлы», `clients.py`) и `scan-gateway/gateway/hotfolder.py`, `smb.py`; OQ-78, OQ-79 | scan-gateway (спека `image-recognition-gateway`, эмулятор, тесты) | **закрыт владельцем 06.10.2026: «правильно как в FileWorker»** — имя `<job_id>.<ext>`, временный `*.tmp` рядом с назначением (каталог `Tmp` из OQ-79 не нужен), очистка `Output/<job_id>/` и входящего файла после чтения; `Output/<job_id>/*.json` батчем и стабилизация набора (OQ-78) остаются. Реализация — arm-scan-gateway #6 |
|
| OQ-137 | Раскладка горячих папок ИС Сканирование: scan-gateway кладёт `Input/<job_id>_<original_name>` через временный `Tmp/.<имя>.part`, ничего не удаляет; PDFWorker старого АРМ (`RSHB/armka_file_worker`, проверен в контуре) кладёт `Input/<task_id>.<ext>` через временный `<назначение>.<uuid>.tmp` рядом (ИС игнорирует `*.tmp`), читает батч `Output/<task_id>/*.json` и удаляет `Output/<task_id>/` и входящий файл после чтения. Какая раскладка актуальна? | сравнение `armka_file_worker` (README «Файлы», `clients.py`) и `scan-gateway/gateway/hotfolder.py`, `smb.py`; OQ-78, OQ-79 | scan-gateway (спека `image-recognition-gateway`, эмулятор, тесты) | **закрыт владельцем 06.10.2026: «правильно как в FileWorker»** — имя `<job_id>.<ext>`, временный `*.tmp` рядом с назначением (каталог `Tmp` из OQ-79 не нужен), очистка `Output/<job_id>/` и входящего файла после чтения; `Output/<job_id>/*.json` батчем и стабилизация набора (OQ-78) остаются. Реализация — arm-scan-gateway #6 |
|
||||||
| OQ-138 | Единицы «тыс. руб.» в шапке против значений в рублях с копейками в выгрузках 1С (Унагранде Компани/Групп, НПЗ) и тысяч с дробями (Межениновская): кто и где приводит единицы. Примеры: книга НПЗ (`npz/2025-Q3`) — ББ `needs_check`, `1600 = 1700` расходится на 1.94 / 9.02 / 2.48 руб.; ОФР НПЗ и ОФР Унагранде (стр. 1) — `needs_check` по 2100/2200/2300 по той же причине; полные формы по факту сходятся только у Межениновской | `fixtures/statements-xlsx/README.md`, tabular-parser design 2b D-6, D-7, решения №22–24 (R-11, R-13, R-14) | Срез 3 (маппинг форм), §8 (КФО в тыс. руб.) | допущение принято (решение владельца 06.10.2026, вариант А): парсер отдаёт значения и `units` как в файле, при «тыс.» и ≥ 10 % значений с дробной частью — предупреждение; допуск ±1 не меняется, не нормализуем; приведение единиц — ядро/аналитик (Срез 3) |
|
| OQ-138 | Единицы «тыс. руб.» в шапке против значений в рублях с копейками в выгрузках 1С (Унагранде Компани/Групп, НПЗ) и тысяч с дробями (Межениновская): кто и где приводит единицы. Примеры: книга НПЗ (`npz/2025-Q3`) — ББ `needs_check`, `1600 = 1700` расходится на 1.94 / 9.02 / 2.48 руб.; ОФР НПЗ и ОФР Унагранде (стр. 1) — `needs_check` по 2100/2200/2300 по той же причине; полные формы по факту сходятся только у Межениновской | `fixtures/statements-xlsx/README.md`, tabular-parser design 2b D-6, D-7, решения №22–24 (R-11, R-13, R-14) | Срез 3 (маппинг форм), §8 (КФО в тыс. руб.) | **закрыт решением владельца 06.10.2026:** единица «тыс. руб.» в шапке считается верной, значения отдаются как в файле; расхождения итогов в пределах округления (до 0,001 % наибольшего числа соотношения) статус не портят — мягкие нарушения «в пределах округления» (arm-tabular-parser#20). Книга НПЗ, ОФР стр. 1 Унагранде — `done`. Принимать ли расхождение и приводить ли единицы — решает КА в ядре (акцепт проверок, Срез 3) |
|
||||||
| OQ-139 | Форма без колонки кодов: сопоставление по именам строк из шаблонов 66н/ФСБУ (словарь `statement_lines.yaml`, `line_code_confidence < 100`)? Сейчас документ без строк и `needs_check` («колонка кодов не найдена») | решение владельца 06.10.2026 (вопрос 6), tabular-parser design 2b D-4 | §12 п. 2, Срез 3 | открыт: нужен реальный файл без колонки кодов; допущение — не сопоставлять по именам |
|
| OQ-139 | Форма без колонки кодов: сопоставление по именам строк из шаблонов 66н/ФСБУ (словарь `statement_lines.yaml`, `line_code_confidence < 100`)? Сейчас документ без строк и `needs_check` («колонка кодов не найдена») | решение владельца 06.10.2026 (вопрос 6), tabular-parser design 2b D-4 | §12 п. 2, Срез 3 | открыт: нужен реальный файл без колонки кодов; допущение — не сопоставлять по именам |
|
||||||
| OQ-140 | Страница-продолжение в отдельном файле (1С печатает ББ/ОФР постранично, один файл = страница): склейка в ядре по ЮЛ + период + тип формы; признак `is_continuation` / `form_page` в контракте (MINOR, две необязательных поля) | решение владельца 06.10.2026 (вопрос 2), design 2b D-8 | §12 п. 9, Срез 3, контракт v1.x | допущение принято: страницы разных файлов не склеиваются; страница 2 без шапки — документ с пустой шапкой и `needs_check`, «загрузите форму одним файлом» |
|
| OQ-140 | Страница-продолжение в отдельном файле (1С печатает ББ/ОФР постранично, один файл = страница): склейка в ядре по ЮЛ + период + тип формы; признак `is_continuation` / `form_page` в контракте (MINOR, две необязательных поля) | решение владельца 06.10.2026 (вопрос 2), design 2b D-8 | §12 п. 9, Срез 3, контракт v1.x | допущение принято: страницы разных файлов не склеиваются; страница 2 без шапки — документ с пустой шапкой и `needs_check`, «загрузите форму одним файлом» |
|
||||||
| OQ-141 | Строка без кода, но с суммами в ОФР ФСБУ 4/2023 (НПЗ «Реализация иного имущества…»): хранить ли (OQ-36 расширяется с расшифровочных строк на строки с суммами) | `fixtures/statements-xlsx/npz`, design 2b D-6 | Срез 3, DBML `financial_statement_line` (хранит только строки с кодом) | допущение принято: строки без кода не отдаются, при наличии сумм — предупреждение «строк без кода с суммами пропущено: N» |
|
| OQ-141 | Строка без кода, но с суммами в ОФР ФСБУ 4/2023 (НПЗ «Реализация иного имущества…»): хранить ли (OQ-36 расширяется с расшифровочных строк на строки с суммами) | `fixtures/statements-xlsx/npz`, design 2b D-6 | Срез 3, DBML `financial_statement_line` (хранит только строки с кодом) | допущение принято: строки без кода не отдаются, при наличии сумм — предупреждение «строк без кода с суммами пропущено: N» |
|
||||||
|
|||||||
@ -106,7 +106,7 @@ Change'и: `tabular-parser/openspec/changes/slice-2a-osv-parser` (issue arm-tabu
|
|||||||
- **Не сделано / риски:** xlsb проверен только рукописным синтетическим файлом (OQ-102); ИНН из текста строки не
|
- **Не сделано / риски:** xlsb проверен только рукописным синтетическим файлом (OQ-102); ИНН из текста строки не
|
||||||
извлекался (OQ-100; реализовано позже в tabular-parser PR #15); счета с буквой в первом сегменте не распознаются (OQ-103).
|
извлекался (OQ-100; реализовано позже в tabular-parser PR #15); счета с буквой в первом сегменте не распознаются (OQ-103).
|
||||||
|
|
||||||
### Срез 2b — ББ/ОФР из Excel (`tabular-parser`) — реализован, ожидает ревью и merge
|
### Срез 2b — ББ/ОФР из Excel (`tabular-parser`) — закрыт 06.10.2026 (tabular-parser #16, docs #27, fixtures #10; follow-up arm-tabular-parser#20)
|
||||||
|
|
||||||
- `tabular-parser`: ББ/ОФР из Excel по §12 в тот же `statementDocument`; поиск листов с формами по содержимому
|
- `tabular-parser`: ББ/ОФР из Excel по §12 в тот же `statementDocument`; поиск листов с формами по содержимому
|
||||||
(в 2a такие листы пропускаются с предупреждением `skipped: statement (slice 2b)`); словари синонимов `rules/*.yaml`;
|
(в 2a такие листы пропускаются с предупреждением `skipped: statement (slice 2b)`); словари синонимов `rules/*.yaml`;
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
"job_id": "3f1c7a2e-5b64-4d0a-9c1e-8a7b6d5e4f30",
|
"job_id": "3f1c7a2e-5b64-4d0a-9c1e-8a7b6d5e4f30",
|
||||||
"file_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
|
"file_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
|
||||||
"service": { "name": "tabular-parser", "version": "0.3.0" },
|
"service": { "name": "tabular-parser", "version": "0.3.0" },
|
||||||
"status": "needs_check",
|
"status": "done",
|
||||||
"metrics": { "duration_ms": 412, "rows": 7, "warnings": ["sheet=Бухгалтерский баланс. Лист 1 значений с дробной частью при единице тыс. руб.: 3"] },
|
"metrics": { "duration_ms": 412, "rows": 7, "warnings": ["sheet=Бухгалтерский баланс. Лист 1 значений с дробной частью при единице тыс. руб.: 3"] },
|
||||||
"documents": [
|
"documents": [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -44,8 +44,7 @@
|
|||||||
{ "column_index": 1, "amount": "-12.30", "confidence": 90, "is_recognized": true }
|
{ "column_index": 1, "amount": "-12.30", "confidence": 90, "is_recognized": true }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"checks": { "relations_failed": [], "soft_relations_failed": [], "duplicate_line_codes": [] }
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
"$id": "arm-ka/recognition-result/v1",
|
"$id": "arm-ka/recognition-result/v1",
|
||||||
"title": "Результат распознавания файла (tabular-parser / scan-gateway), контракт v1.2",
|
"title": "Результат распознавания файла (tabular-parser / scan-gateway), контракт v1.2",
|
||||||
"description": "Один файл (stored_file) → один job → N документов. Сервисы не знают БД: только структура файла. Нормализация счетов, резолв контрагентов, проверки — в arm-core.",
|
"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 отвергают незнакомые значения.",
|
"$comment": "Версионирование: schema_version = MAJOR.MINOR. MINOR (1.1, 1.2, …) — необязательные поля и новые значения enum; MAJOR (2.0) — удаление/переименование полей, смена типов или семантики. Потребитель принимает тот же MAJOR и любой MINOR. Новый MINOR раскатывается сначала на потребителей (ядро и сервисы обновляют копии схем раньше, чем производитель начнёт слать новый MINOR), потому что закрытые enum отвергают незнакомые значения.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["schema_version", "job_id", "file_id", "service", "status", "documents"],
|
"required": ["schema_version", "job_id", "file_id", "service", "status", "documents"],
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -210,7 +210,7 @@
|
|||||||
"description": "Результаты самопроверки формы по соотношениям §7 (tabular-parser). Отсутствие объекта — «не проверялось» (OCR-путь); пустые массивы — «проверено, сошлось».",
|
"description": "Результаты самопроверки формы по соотношениям §7 (tabular-parser). Отсутствие объекта — «не проверялось» (OCR-путь); пустые массивы — «проверено, сошлось».",
|
||||||
"properties": {
|
"properties": {
|
||||||
"relations_failed": { "type": "array", "items": { "$ref": "#/$defs/failedRelation" }, "description": "нарушения жёстких соотношений: документ needs_check" },
|
"relations_failed": { "type": "array", "items": { "$ref": "#/$defs/failedRelation" }, "description": "нарушения жёстких соотношений: документ needs_check" },
|
||||||
"soft_relations_failed": { "type": "array", "items": { "$ref": "#/$defs/failedRelation" }, "description": "нарушения мягких соотношений (OQ-12, подстроки «в том числе»): только предупреждение" },
|
"soft_relations_failed": { "type": "array", "items": { "$ref": "#/$defs/failedRelation" }, "description": "нарушения мягких соотношений (OQ-12, подстроки «в том числе») и жёстких в пределах округления итогов (OQ-138): только предупреждение" },
|
||||||
"duplicate_line_codes": { "type": "array", "items": { "type": "string" }, "description": "коды строк, встретившиеся в документе больше одного раза (осталась первая строка)" }
|
"duplicate_line_codes": { "type": "array", "items": { "type": "string" }, "description": "коды строк, встретившиеся в документе больше одного раза (осталась первая строка)" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user