Skip to content

MasyaSmv/aton-statement-parser

Repository files navigation

aton-statement-parser

Пакет для парсинга XML-отчётов брокера Атон (формат BIS:BISPeriod) в удобную структуру данных, чтобы в проекте можно было:

  • передать путь до XML-файла,
  • получить объект отчёта (Report),
  • быстро выбрать нужный блок (Trades, MoneyInOut, StockInOut, …),
  • найти операцию по OperID,
  • собрать список всех OperID (например, для сверки с БД),
  • работать с атрибутами строк через удобные геттеры (строки/даты/числа) без «магических» индексов массива.

Цель: минимальная боль при работе с реальными отчётами (namespaces, windows-1251, разные форматы дат, дробные числа).


Быстрый старт (планируемый API)

use MasyaSmv\AtonStatementParser\AtonStatementParser;

$report = AtonStatementParser::fromFile('/path/to/report.xml');

// Доступ к секциям (универсально)
$trades = $report->section('Trades')->rows();      // Row[]
$money  = $report->section('MoneyInOut')->rows();  // Row[]

// Поиск по OperID
$row = $report->findOperId('567890123');           // Row|null

// Список всех OperID (для сверки)
$ids = $report->operIds();                         // array<int|string>

// Удобные геттеры атрибутов
$type = $report->section('Trades')->rows()[0]->getString('TradeType');
$date = $report->section('Trades')->rows()[0]->getDate('OperDateSort'); // DateTimeImmutable|null

Проблемы, которые решает пакет

1) Namespace BIS

XML использует xmlns:BIS=..., значит нельзя просто «по имени тега» — нужен XPath с корректной регистрацией namespace.

2) Кодировка windows-1251

В шапке отчёта встречается encoding="windows-1251". Пакет должен безопасно перевести документ в UTF-8 перед парсингом.

3) Разные форматы дат

В отчётах встречаются:

  • 29.12.2023
  • 02.10.24
  • 16.11.18
  • 26.12.24 / (мусорные хвосты)

Нужен нормализатор даты: трим + поддержка d.m.Y и d.m.y.

4) Десятичные числа

Количество и суммы — строки с точностью (100000.00000000). Базовый слой хранит как string, а геттеры умеют приводить к float/int при необходимости.


Архитектура (как планируем)

Основные сущности

  • Report — весь отчёт, доступ к секциям и общим данным.
  • Section — один блок внутри отчёта (например Trades, MoneyInOut).
  • Row — одна строка <BIS:Row .../> внутри секции. Хранит атрибуты + типовые геттеры.

Уровни удобства

  1. Базовый (универсальный): Report/Section/Row — работает для любых секций без генерации десятков DTO.
  2. Продвинутый (DTO для популярных секций): TradeDto, MoneyInOutDto и т.п. — добавляются постепенно, когда станет понятно, что реально часто используется.

Структура проекта (план)

src/
  AtonStatementParser.php          // fromFile/fromString
  Report/
    Report.php                     // секции + commonData
    Section.php                    // имя секции + Row[]
    Row.php                        // атрибуты BIS:Row + геттеры
  Xml/
    XmlLoader.php                  // чтение файла, encoding -> utf8, DOM
    XPathFactory.php               // DOMXPath + регистрация namespace
  Normalizers/
    DateNormalizer.php             // даты (d.m.y / d.m.Y, мусорные хвосты)
    NumberNormalizer.php           // числа/десятичные строки
    StringNormalizer.php           // trim/cleanup
  Exceptions/
    ParseException.php
    InvalidXmlException.php

tests/
  Fixtures/
    aton/
      ...xml
  ...

Roadmap / План работ

✅ Уже сделано

  • Базовый каркас пакета (autoload, структура, базовые тесты)
  • Fixtures подключены в тесты
  • Composer scripts: test, cs:*, stan

Этап A — «сразу полезно» (ядро парсинга)

  • AtonStatementParser::fromFile(string $path): Report
  • AtonStatementParser::fromString(string $xml): Report
  • Report->section(string $name): Section
  • Section->rows(): array<Row>
  • Report->operIds(): array (собрать OperID по секциям)
  • Report->findOperId(string $id): ?Row
  • Unit-тесты на fixtures (operIds/findOperId/section)

Этап B — нормализация типов (typed getters)

  • Row->getString($key)
  • Row->getInt($key)
  • Row->getFloat($key)
  • Row->getDecimalString($key) (без потери точности)
  • Row->getBool($key)
  • Row->getDate($key): ?DateTimeImmutable
  • Поддержка форматов дат/времени из реальных отчётов:
    • dd.mm.yy → расширение до dd.mm.yyyy
    • OperDateSort="dd.mm.yyyy 0:00:00" (время всегда 00:00:00)
    • OperTimeSort="01.01.1900 HH:ii:ss" (дата фиксированная, важно время)
    • значения вида 26.12.24 / (чистка мусора)
    • стабильный парсинг даты без “текущего времени” (через ! в форматах)
  • Тесты на даты/числа + реалистичный fixture

🚧 Запланировано

Этап C — доменные секции (удобный API без раздувания Row)

  • Row->getStringRequired() / getIntRequired() / getDecimalStringRequired() / getDateRequired() (кидают исключение с контекстом)
  • Доменные “обёртки” по секциям:
    • TradeRow (секция Trades)
    • MoneyInOutRow (секция MoneyInOut)
    • StockInOutRow (секция StockInOut)
    • ClientMoneyConvertRow (секция ClientMoneyConvert)
  • Сахар на уровне Report/Section:
    • Report->trades(): array<TradeRow> (или section('Trades')->asTrades())
    • Report->moneyInOut(): array<MoneyInOutRow>
  • Тесты доменных секций

Этап D — DTO (точечно, только нужное)

  • TradeDto, MoneyInOutDto (минимальный набор полей, нужный проекту)
  • Мапперы секций → DTO (через доменные row-обёртки)
  • Тесты DTO-маппинга (валидные/невалидные строки, обязательные поля)

Этап E — удобства для больших отчётов

  • Фильтрация/поиск по секции:
    • section()->filter(fn(Row $r) => ...)
    • section()->firstWhere(...)
  • Индексация по OperID (лениво или при первом вызове)
  • Улучшение ошибок парсинга (контекст: секция, ключ, значение)
  • (Опционально) оптимизация под большие XML (если реально потребуется)

Fixtures и безопасность

  • В репозиторий коммитим только обезличенные XML.
  • Реальные отчёты для локальной отладки — держать в tests/FixturesLocal/ (и добавить в .gitignore).

Рекомендуется добавить .gitattributes, чтобы не ловить «невидимые» правки концов строк (LF/CRLF).


Installation

composer require masyasmv/aton-statement-parser

Development

composer install
composer test
composer cs:fix
composer cs:check
composer stan

License

MIT. См. файл LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages