diff --git a/docs/client.md b/docs/client.md
deleted file mode 100644
index 73072ed..0000000
--- a/docs/client.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Работа с клиентами (покупателями)
-
-[Вернуться к содержанию](readme.md)
-
----
-
-Объект покупателя инициализируется следующим образом:
-
-```php
-$customer = new AtolOnline\Entities\Client();
-```
-
-У объекта покупателя могут быть указаны любые из следующих атрибутов:
-* email (тег ФФД 1008);
-* ИНН (тег ФФД 1128);
-* наименование (тег ФФД 1127);
-* номер телефона (тег ФФД 1008).
-
-> Все эти атрибуты являются **необязательными**.
-> Если указаны одновременно и email, и номер телефона, то ОФД отправит чек только на email.
-
-Указать эти атрибуты можно двумя способами:
-
-```php
-// 1 способ - через конструктор
-$customer = new AtolOnline\Entities\Client(
- 'John Doe', // наименование
- 'john@example.com', // email
- '+1/22/99*73s dsdas654 5s6', // номер телефона +122997365456
- '+fasd3\qe3fs_=nac990139928czc' // номер ИНН 3399013928
-);
-
-// 2 способ - через сеттеры
-$customer = (new AtolOnline\Entities\Client())
- ->setEmail('john@example.com')
- ->setInn('+fasd3\q3fs_=nac9901 3928c-c')
- ->setName('John Doe')
- ->setPhone('+1/22/99*73s dsdas654 5s6');
-
-// либо комбинация этих способов
-```
-
-Получить установленные значения атрибутов можно через геттеры:
-
-```php
-$customer->getInn();
-$customer->getEmail();
-$customer->getName();
-$customer->getPhone();
-```
-
-Объект класса приводится к JSON-строке автоматически или принудительно:
-
-```php
-echo $customer;
-$json_string = (string)$customer;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $customer->jsonSerialize();
-```
-
----
-
-[Вернуться к содержанию](readme.md)
diff --git a/docs/collection.md b/docs/collection.md
new file mode 100644
index 0000000..1c0a8b6
--- /dev/null
+++ b/docs/collection.md
@@ -0,0 +1,19 @@
+# Коллекция сущностей
+
+[Вернуться к содержанию](readme.md#toc)
+
+---
+
+Коллекциями являются объекты, способные хранить в себе [сущности](entity.md). Они унаследованы
+от `Illuminate/Support/Collection` и полностью поддерживают все
+[стандартные методы коллекций Laravel](https://laravel.com/docs/master/collections).
+
+Помимо этого, они валидируют количество и вид сущностей, которые могут хранить в себе, согласно схеме АТОЛ Онлайн API.
+
+Коллекции ведут себя аналогично самим сущностям в части приведения к массивам и json-ификации.
+
+---
+
+Читай также: [Сущность](entity.md)
+
+[Вернуться к содержанию](readme.md#toc)
diff --git a/docs/company.md b/docs/company.md
deleted file mode 100644
index d13305e..0000000
--- a/docs/company.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Работа с компанией (продавцом)
-
-[Вернуться к содержанию](readme.md)
-
----
-
-Объект компании инициализируется следующим образом:
-
-```php
-$customer = new AtolOnline\Entities\Company();
-```
-
-У объекта компании должны быть указаны все следующие атрибуты:
-* email (тег ФФД 1117);
-* ИНН (тег ФФД 1018);
-* тип системы налогообложения (тег ФФД 1055) - все типы перечислены в классе `AtolOnline\Constants\SnoTypes`;
-* адрес места расчётов (тег ФФД 1187) - для интернет-сервисов указывается URL с протоколом.
-
-> Все эти атрибуты являются **обязательными**.
-> Для тестового режима используйте значения ИНН и адреса места расчётов, [указанные здесь](https://online.atol.ru/files/ffd/test_sreda.txt).
-
-Указать эти атрибуты можно двумя способами:
-
-```php
-// 1 способ - через конструктор (все аргументы обязательны)
-$company = new AtolOnline\Entities\Company(
- 'company@example.com' // email
- AtolOnline\Constants\SnoTypes::OSN, // тип СНО
- '5544332219', // номер ИНН
- 'https://v4.online.atol.ru', // адрес места расчётов
-);
-
-// 2 способ - через сеттеры
-$company
- ->setEmail('company@example.com')
- ->setInn('5544332219')
- ->setSno(AtolOnline\Constants\SnoTypes::USN_INCOME)
- ->setPaymentAddress('https://v4.online.atol.ru');
-
-// либо комбинация этих способов
-```
-
-Получить установленные значения параметров можно через геттеры:
-
-```php
-$company->getInn();
-$company->getEmail();
-$company->getPaymentAddress();
-$company->getSno();
-```
-
-Объект класса приводится к JSON-строке автоматически или принудительно:
-
-```php
-echo $company;
-$json_string = (string)$company;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $company->jsonSerialize();
-```
-
----
-
-[Вернуться к содержанию](readme.md)
\ No newline at end of file
diff --git a/docs/correction_info.md b/docs/correction_info.md
deleted file mode 100644
index c90cade..0000000
--- a/docs/correction_info.md
+++ /dev/null
@@ -1,62 +0,0 @@
-# Работа с данными коррекции
-
-[Вернуться к содержанию](readme.md)
-
----
-
-Объект для данных коррекции инициализируется следующим образом:
-
-```php
-$info = new AtolOnline\Entities\CorrectionInfo();
-```
-
-У объекта должны быть указаны все следующие обязательные атрибуты:
-* тип коррекции (тег ФФД 1173) - все типы перечислены в классе `AtolOnline\Constants\CorrectionTypes`;
-* дата документа основания для коррекции в формате `d.m.Y` (тег ФФД 1178);
-* номер документа основания для коррекции (тег ФФД 1179).
-
-Указать эти атрибуты можно двумя способами:
-
-```php
-use AtolOnline\{Entities\CorrectionInfo, Constants\CorrectionTypes};
-
-// 1 способ - через конструктор
-$info = new CorrectionInfo(
- CorrectionTypes::SELF, // тип коррекции
- '01.01.2019', // дата документа коррекции
- '12345', // номер документа коррекции
-);
-
-// 2 способ - через сеттеры
-$info = (new CorrectionInfo())
- ->setType(CorrectionTypes::INSTRUCTION)
- ->setDate('01.01.2019')
- ->setNumber('9999');
-
-// либо комбинация этих способов
-```
-
-Получить установленные значения атрибутов можно через геттеры:
-
-```php
-$info->getType();
-$info->getDate();
-$info->getNumber();
-```
-
-Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
-
-```php
-echo $customer;
-$json_string = (string)$customer;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $customer->jsonSerialize();
-```
-
----
-
-[Вернуться к содержанию](readme.md)
\ No newline at end of file
diff --git a/docs/documents.md b/docs/documents.md
deleted file mode 100644
index 1d92174..0000000
--- a/docs/documents.md
+++ /dev/null
@@ -1,167 +0,0 @@
-# Работа с документами
-
-[Вернуться к содержанию](readme.md)
-
----
-
-Объект документа инициализируется следующим образом:
-
-```php
-$doc = new AtolOnline\Entities\Document();
-```
-
-Для документов **прихода, возврата прихода, расхода и возврата расхода** должны быть указаны все следующие обязательные атрибуты:
-* [клиент](/docs/client.md);
-* [компания](/docs/company.md);
-* [предметы расчёта](/docs/items.md);
-* [оплаты](/docs/payments.md).
-
-Для документов **коррекции прихода и коррекции расхода** должны быть указаны все следующие обязательные атрибуты:
-* [компания](/docs/company.md);
-* [оплаты](/docs/payments.md);
-* [ставки НДС](/docs/vats.md);
-* [данные коррекции](/docs/correction_info.md).
-
-Для любых документов также могут быть указаны следующие необязательные атрибуты:
-* ФИО кассира (тег ФФД - 1021).
-
-Установка атрибутов документа происходит через сеттеры.
-
-## Работа с клиентом
-
-Для этого существуют следующие методы:
-
-```php
-$doc->setClient($client);
-$doc->getClient();
-```
-
-> О работе с клиентами более подробно читайте [здесь](/docs/client.md).
-
-## Работа с компанией
-
-Для этого существуют следующие методы:
-
-```php
-$doc->setCompany($company);
-$doc->getCompany();
-```
-
-> О работе с компаниями более подробно читайте [здесь](/docs/company.md).
-
-## Работа с предметами расчёта
-
-Внутри документа существует [массив предметов расчёта](/docs/items.md#array).
-По умолчанию он пуст.
-Напрямую для манипуляций объект массива недоступен.
-Работа с ним происходит через методы документа:
-
-```php
-$doc->setItems([$item1, $item2]);
-$doc->addItem($item3);
-$doc->getItems();
-```
-
-Соответственно, эти методы выбрасывают те же исключения, что методы самого массива.
-
-## Работа с оплатами
-
-Внутри документа существует [массив оплат](/docs/payments.md#array).
-По умолчанию он пуст.
-Напрямую для манипуляций объект массива недоступен.
-Работа с ним происходит через методы документа:
-
-```php
-$doc->setPayments([$payment1, $payment2]);
-$doc->addPayment($payment3);
-$doc->getPayments();
-```
-
-Соответственно, эти методы выбрасывают те же исключения, что методы самого массива.
-
-Следует отметить, что если при выполнении метода `addPayment()` выполняются следующие условия:
-* аргументом передан объект оплаты, у которого не задана сумма,
-* ранее документу не задавались оплаты,
-то автоматически этому объекту оплаты задаётся полная сумма чека.
-
-## Работа со ставками НДС
-
-Внутри документа существует [массив ставок НДС](/docs/vats.md#array).
-По умолчанию он пуст.
-Напрямую для манипуляций объект массива недоступен.
-Работа с ним происходит через методы документа:
-
-```php
-$doc->setVats([$vat1, $vat2]);
-$doc->addVat($vat3);
-$doc->getVats();
-```
-
-Соответственно, эти методы выбрасывают те же исключения, что методы самого массива.
-
-Также существует метод `clearVats()`, который удаляет все вложенные объекты ставок НДС - из предметов расчёта и самого документа.
-
-Следует отметить, что если при выполнении метода `addVat()` выполняются следующие условия:
-* аргументом передан объект ставки, у которого не задана сумма,
-* ранее документу не задавались ставки,
-то автоматически этому объекту налога задаётся полная сумма чека, от которой расчитывается итоговый размер налога.
-
-## Общая сумма документа
-
-Расчёт происходит автоматически в следующих случаях:
-* изменение предметов расчёта (`setItems()`, `addItem()`);
-* добавление оплат (`addPayment()` в случае, когда оплата передана без суммы);
-* изменение ставок НДС (`setVats()`, `clearVats()`, `addVat()` в случае, когда ставка передана без суммы);
-* приведение объекта документа к строке.
-
-Также можно вызвать вручную метод `calcTotal()`.
-Он расчитывает полную сумму чека по предметам расчёта и пересчитывает **все** налоговые ставки.
-
-Получить итог можно с помощью метода `getTotal()`.
-
-Всё в рублях.
-
-
-## Работа с данными коррекции
-
-Если документ создаётся с целью коррекции прихода или расхода, то он обязательно должен содержать [данные коррекции](/docs/correction_info.md).
-
-Задать и получить эти данные очень просто:
-
-```php
-$doc->setCorrectionInfo(new AtolOnline\Entities\CorrectionInfo(
- AtolOnline\Constants\CorrectionTypes::SELF, // тип коррекции
- '01.01.2019', // дата документа коррекции
- '12345', // номер документа коррекции
- 'test' // описание коррекции
-));
-$doc->getCorrectionInfo();
-```
-
-## Работа с кассиром
-
-Для этого существуют следующие методы:
-
-```php
-$doc->setCashier('Иванова Лариса Васильевна');
-$doc->getCashier();
-```
-
-## Прочее
-
-Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
-
-```php
-echo $doc;
-$json_string = (string)$doc;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $doc->jsonSerialize();
-```
-
----
-
-[Вернуться к содержанию](readme.md)
diff --git a/docs/entity.md b/docs/entity.md
new file mode 100644
index 0000000..76c79bc
--- /dev/null
+++ b/docs/entity.md
@@ -0,0 +1,52 @@
+# Сущность
+
+[Вернуться к содержанию](readme.md#toc)
+
+---
+
+Сущностями являются все классы, которые необходимы для взаимодействия с API. Они находятся в директори `src/Entities` и
+расширяют абстрактный класс `AtolOnline\Entities\Entity`.
+
+Каждая сущность содержит в себе только те данные, которые необходимы согласно схемы АТОЛ Онлайн API.
+
+Ниже перечислены возможности сущностей.
+
+## Приведение к строке JSON
+
+```php
+echo $entity;
+$json_string = (string)$entity;
+```
+
+## Приведение к массиву
+
+```php
+// результат идентичен
+$json_array1 = $entity->jsonSerialize();
+$json_array2 = $entity->toArray();
+```
+
+## Чтение из массива
+
+```php
+$var = new \AtolOnline\Entities\Client('Иванов Иван');
+echo $var['name']; // 'Иванов Иван'
+$var['name'] = 'Петров Пётр'; // BadMethodCallException
+```
+
+## Fluent-сеттеры
+
+Реализованы на уровне конкретных классов сущностей, но у некоторых могут полностью отсуствовать.
+
+```php
+$entity->setFoo($value)->setBar('bar')->...
+```
+
+Сеттеры валидируют и фильтруют данные согласно схеме АТОЛ Онлайн API, а в случае ошибочных значений -- выбрасывают
+исключения.
+
+---
+
+Читай также: [Коллекция сущностей](collection.md)
+
+[Вернуться к содержанию](readme.md#toc)
diff --git a/docs/fiscalizing.md b/docs/fiscalizing.md
new file mode 100644
index 0000000..042d4be
--- /dev/null
+++ b/docs/fiscalizing.md
@@ -0,0 +1,237 @@
+# Фискализация документов
+
+[Вернуться к содержанию](readme.md#toc)
+
+---
+
+## Доступ к ККТ
+
+Для работы с облачной ККТ необходимы следующие параметры:
+
+* логин;
+* пароль;
+* код группы.
+
+Чтоы получить их, нужно:
+
+1. авторизоваться в личном кабинете [online.atol.ru](https://online.atol.ru/lk/Account/Login);
+2. на странице [Мои компании](https://online.atol.ru/lk/Company/List) нажать кнопку **Настройки интегратора**.
+ Скачается XML-файл с нужными настройками.
+
+Также для работы потребуются:
+
+* ИНН продавца;
+* URL места расчёта (ссылка на ваш интернет-сервис).
+
+## Использование
+
+Объект ККТ инициализируется следующим образом:
+
+```php
+$kkt = new AtolOnline\Api\Fiscalizer();
+```
+
+Установить параметры подключения можно двумя путями:
+
+```php
+use AtolOnline\Api\Fiscalizer;
+
+// 1 способ - через конструктор
+$kkt = new Fiscalizer(group: 'mygroup', login: 'mylogin', password: 'mypassword');
+
+// 2 способ - через сеттеры
+$kkt = (new Fiscalizer())
+ ->setLogin($login)
+ ->setGroup($group)
+ ->setPassword($password);
+```
+
+
+
+## Тестовый режим
+
+По умолчанию фискализатор создаётся для работы в тестовом режиме. Это означает, что работа с АТОЛ Онлайн API будет
+происходить [в тестовой среде](https://online.atol.ru/files/ffd/test_sreda.txt).
+
+> Под тестовым режимом работы подразумевается использование тестовых ККТ, которые принадлежат компании АТОЛ.
+
+Управление тестовым режимом происходит следующим образом:
+
+```php
+$kkt = new Fiscalizer(); // включен по умолчанию
+$kkt = new Fiscalizer(false); // выключен явно
+$kkt->setTestMode(); // включен явно
+$kkt->setTestMode(true); // включен явно
+$kkt->setTestMode(false); // выключен явно
+```
+
+**При включенном тестовом режиме используются тестовые ККТ**, т.к. перед отправкой запроса подменяются:
+
+* логин;
+* пароль;
+* группа ККТ;
+* ИНН клиента (покупателя);
+* ИНН и адрес места расчётов компании (продавца).
+
+Таким образом:
+
+* использовать тестовый режим -- безопасно;
+* при переключении тестового режима устанавливать заново свои параметры подключения не требуется.
+
+**При выключенном тестовом режиме используются ваши ККТ.**
+
+Если по каким-то причинам у вас не получится использовать тестовый режим, вы можете проводить свои тесты в боевом
+режиме (на собственной ККТ). В этом случае важно понимать следующее:
+
+1. сразу после оформления документа **прихода** необходимо оформлять точно такой же документ **возврата прихода**;
+2. [вы обязательно забудете о пункте 1](http://murphy-law.net.ru/basics.html);
+3. пп. 1 и 2 в любом случае скажутся на ваших финансовых отчётах;
+4. вся ответственность за пп. 1-3 и последствия ложится только на вас.
+
+## Авторизация на ККТ
+
+Перед первым запросом на ККТ происходит аутентификация на сервере по логину и паролю. В ответ приходит авторизационный
+токен, срок жизни коего равен **24 часам**. После первой успешной операции возможно получить этот токен следующим
+образом:
+
+```php
+$kkt->getToken(); // вернёт строку длиной 128 символа
+```
+
+Этот токен можно сохранить и переиспользовать в течение всего срока его жизни, но далее следует получить новый токен.
+
+Ранее полученный токен следует указывать до отправки запросов следующим образом:
+
+```php
+$kkt->setToken($token_string);
+```
+
+Если токен был установлен перед выполнением операции, то при выполнении операции будет использоваться именно он. Если
+операция завершится ошибочно из-за истёкшего токена, следует повторить операцию без использования метода `setToken()`,
+либо обнулив его следующим образом:
+
+```php
+$kkt->setToken(null);
+```
+
+Тогда будет получен новый токен.
+
+## Регистрация документа
+
+Для регистрации документа **прихода** необходимо вызвать метод `sell()`:
+
+```php
+$result = $kkt->sell($document);
+$result2 = $receipt->sell($kkt);
+```
+
+Для регистрации документа **возврата прихода** необходимо вызвать метод `sellRefund()`:
+
+```php
+$result = $kkt->sellRefund($document);
+$result2 = $receipt->sellRefund($kkt);
+```
+
+Для регистрации документа **расхода** необходимо вызвать метод `buy()`:
+
+```php
+$result = $kkt->buy($document);
+$result2 = $receipt->buy($kkt);
+```
+
+Для регистрации документа **возврата расхода** необходимо вызвать метод `buyRefund()`:
+
+```php
+$result = $kkt->buyRefund($document);
+$result2 = $receipt->buyRefund($kkt);
+```
+
+Для регистрации документа **коррекции прихода** необходимо вызвать метод `sellCorrection()`:
+
+```php
+$result = $kkt->sellCorrect($document);
+$result2 = $correction->sellCorrect($kkt);
+```
+
+Для регистрации документа **коррекции расхода** необходимо вызвать метод `buyCorrection()`:
+
+```php
+$result = $kkt->buyCorrect($document);
+$result2 = $correction->buyCorrect($kkt);
+```
+
+### Собственный идентификатор документа (`external_id`)
+
+Каждый документ, переданный на ККТ для регистрации, всегда имеет свой идентификатор, абсолютно уникальный среди всех
+документов когда-либо регистрировавшихся на ККТ, даже если при регистрации были ошибки. По умолчанию это UUID версии 4.
+
+Чтобы использовать собственный идентификатор, следует передать нужное строковое значение вторым параметром в любой из
+шести описанных выше методов, например:
+
+```php
+$result = $kkt->sellRefund($document, 'order_' . $order->id);
+```
+
+Если `external_id` не указан явно или имеет пустое значение, то будет сгенерирован новый UUID. Узнать его можно будет
+только в ответе от ККТ после регистрации документа в очереди на фискализацию.
+
+### Передача `callback_url`
+
+Перед регистрацией документа можно указать `callback_url`. АТОЛ отправит на указанный URL результат регистрации. По
+этому адресу должен располагаться ваш собственный обработчик статуса фискализации.
+
+```php
+$kkt->setCallbackUrl('http://example.com/process-kkt-result');
+$kkt->getCallbackUrl();
+```
+
+## Проверка статуса документа
+
+Если перед отправкой документа на регистрацию был задан `callback_url` через метод `setCallbackUrl()`, то ответ придёт
+на указанный адрес автоматически, как только документ обработается на стороне ККТ. Ответ может быть как об успешной
+регистрации, так и ошибочной.
+
+В любом случае, вам доступны два метода, с помощью которых вы можете проверять статус документа самостоятельно:
+
+```php
+$kkt->getDocumentStatus(); // делает единичный запрос
+$kkt->pollDocumentStatus(); // делает запросы до получения конечного статуса (не-wait)
+```
+
+Эти методы принимают на вход `uuid` кода регистрации. Этот UUID нужно взять из ответа, полученного при отправке
+документа на регистрацию:
+
+```php
+$sell_result = $kkt->sell($document);
+$status = $kkt->pollDocumentStatus($sell_result->uuid);
+```
+
+Метод `pollDocumentStatus()` многократно опрашивает ККТ на предмет состояния документа. Метод может принимать до трёх
+параметров:
+
+* uuid;
+* количество попыток (по умолчанию — 5);
+* время между попытками в секундах (по умолчанию — 1).
+
+```php
+// Проверять статус 10 раз на протяжении 20 секунд — каждые две секунды
+$kkt->pollDocumentStatus($sell_result->uuid, 10, 20);
+```
+
+Учитывайте, что метод вернёт результат как только сменится статус регистрации на успешный `done` или ошибочный `error`.
+
+Использовать его лучше сразу после отправки документа на регистрацию (как в примере выше).
+
+> Как правило, фискализация одного документа занимает 4-6 секунд с учётом регистрации.
+
+Метод `getDocumentStatus()` принимает на вход только `uuid` и запрашивает состояние документа лишь единожды.
+Использовать его целесообразнее в те моменты, когда нет необходимости знать успех регистрации сразу после отправки
+документа.
+
+> Обратите внимание, что АТОЛ позволяет получать статус документа в течение 32 суток с момента его регистрации.
+
+---
+
+Читай также: [Обработка ответа API](response.md)
+
+[Вернуться к содержанию](readme.md#toc)
diff --git a/docs/items.md b/docs/items.md
deleted file mode 100644
index 730a1e8..0000000
--- a/docs/items.md
+++ /dev/null
@@ -1,202 +0,0 @@
-# Работа с предметами расчёта
-
-[Вернуться к содержанию](readme.md)
-
----
-
-## Один объект
-
-Объект предмета расчёта инициализируется следующим образом:
-
-```php
-$vat = new AtolOnline\Entities\Item();
-```
-
-У объекта предмета расчёта должны быть указаны все следующие обязательные атрибуты:
-* наименование (тег ФФД - 1030);
-* цена (тег ФФД - 1079);
-* количество, вес (тег ФФД - 1023).
-
-У объекта предмета расчёта также могут быть указаны следующие необязательные атрибуты:
-* единица измерения количества (тег ФФД - 1197);
-* признак способа оплаты (тег ФФД - 1214) - перечислены в классе `AtolOnline\Constants\PaymentMethods`;
-* признак предмета расчёта (тег ФФД - 1212) - перечислены в классе `AtolOnline\Constants\PaymentObjects`;
-* [ставка НДС](/docs/vats.md);
-* дополнительный реквизит (тег ФФД - 1191).
-
-Установить многие (но не все) атрибуты можно следующими способами:
-
-```php
-use AtolOnline\{
- Constants\PaymentMethods,
- Constants\PaymentObjects,
- Constants\VatTypes,
- Entities\Item
-};
-
-// 1 способ - через конструктор
-$item = new Item(
- 'Банан', // наименование
- 100, // цена
- 1, // количество, вес
- 'кг', // единица измерения
- VatTypes::VAT20, // ставка НДС
- PaymentObjects::SERVICE, // признак предмета расчёта
- PaymentMethods::FULL_PAYMENT // признак способа расчёта
-);
-
-// 2 способ - через сеттеры
-$item = new Item();
-$item->setName('Банан');
-$item->setPrice(100);
-$item->setQuantity(2.41);
-//$item->setQuantity(2.41, 'кг');
-$item->setMeasurementUnit('кг');
-$item->setVatType(VatTypes::VAT20);
-$item->setPaymentObject(PaymentObjects::COMMODITY);
-$item->setPaymentMethod(PaymentMethods::FULL_PAYMENT);
-```
-
-Метод `setName()` проверяет входную строку на длину (до 128 символов).
-Выбрасывает исключение `AtolNameTooLongException` (если слишком длинное наименование).
-
-Метод `setPrice()` проверяет аргумент на величину (до 42949672.95) и пересчитывает общую стоимость.
-Выбрасывает исключение `AtolPriceTooHighException` (если цена слишком высока).
-
-Метод `setMeasurementUnit()` проверяет входную строку на длину (до 16 символов).
-Выбрасывает исключение `AtolUnitTooLongException` (если слишком длинная строка единицы измерения).
-
-Метод `setQuantity()` проверяет первый аргумент на величину (до 99999.999) и пересчитывает общую стоимость.
-Выбрасывает исключения:
-* `AtolQuantityTooHighException` (если количество слишком велико);
-* `AtolPriceTooHighException` (если общая стоимость слишком велика).
-
-Также вторым аргументом может принимать единицу измерения количества.
-В этом случае дополнительно работает сеттер `setMeasurementUnit()`.
-
-Метод `setVatType()` задаёт тип ставки НДС, пересчитывает размер налога и общую стоимость.
-Выбрасывает исключение `AtolPriceTooHighException` (если цена слишком высока).
-Может принимать `null` для удаления налога.
-
-Дополнительный реквизит устанавливается отдельным методом `setUserData()`:
-
-```php
-$item->setUserData('some data');
-```
-
-Он проверяет строку на длину (до 64 символов).
-Выбрасывает исключение `AtolUserdataTooLongException` (если слишком длинный дополнительный реквизит).
-
-Для установки признака предмета расчёта существует метод `setPaymentObject()`.
-На вход следует передавать одной из значений, перечисленных в классе `AtolOnline\Constants\PaymentObjects`.
-
-```php
-$item->setPaymentObject(AtolOnline\Constants\PaymentObjects::JOB);
-```
-
-Для установки признака способа оплаты существует метод `setPaymentMethod()`.
-На вход следует передавать одной из значений, перечисленных в классе `AtolOnline\Constants\PaymentMethods`.
-
-```php
-$item->setPaymentMethod(AtolOnline\Constants\PaymentMethods::FULL_PAYMENT);
-```
-
-Для получения заданных значений атрибутов реализованы соответствующие геттеры:
-
-```php
-$item->getName();
-$item->getPrice();
-$item->getQuantity();
-$item->getMeasurementUnit();
-$item->getPaymentMethod();
-$item->getPaymentObject();
-$item->getVat(); // возвращает объект ставки НДС либо null
-$item->getUserData();
-```
-
-Для пересчёта общей стоимости и размера налога существует метод `calcSum()`.
-
-```php
-$item->calcSum();
-```
-
-Этот метод отрабатывает при вызове `setPrice()`, `setQuantity()` и `setVatType()`.
-Выбрасывает исключение `AtolPriceTooHighException` (если общая сумма слишком высока).
-
-Получить уже расчитанную общую сумму можно простым геттером:
-
-```php
-$item->getSum();
-```
-
-Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
-
-```php
-echo $item;
-$json_string = (string)$item;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $item->jsonSerialize();
-```
-
-
-## Массив объектов предметов расчёта
-
-> Максимальное количество объектов в массиве - 100.
-
-Массив инициализируется следующим образом:
-
-```php
-$item_array = new AtolOnline\Entities\ItemArray();
-```
-
-Чтобы задать содержимое массива, используйте метод `set()`:
-
-```php
-$item_array->set([
- $item_object1,
- $item_object2
-]);
-```
-
-Очистить его можно передачей в сеттер пустого массива:
-
-```php
-$item_array->set([]);
-```
-
-Чтобы добавить объект к существующим элементам массива, используйте метод `add()`:
-
-```php
-$item = new AtolOnline\Entities\Item('Банан', 100, 1);
-$item_array->add($item);
-```
-
-Методы `set()` и `add()` проверяют количество элементов в массиве перед его обновлением.
-Выбрасывают исключение `AtolTooManyItemsException` (если в массиве уже максимальное количество объектов).
-
-Чтобы получить содержимое массива, используйте метод `get()`:
-
-```php
-$item_array->get();
-```
-
-Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
-
-```php
-echo $item_array;
-$json_string = (string)$item_array;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $item_array->jsonSerialize();
-```
-
----
-
-[Вернуться к содержанию](readme.md)
\ No newline at end of file
diff --git a/docs/kkt.md b/docs/kkt.md
deleted file mode 100644
index aae3c72..0000000
--- a/docs/kkt.md
+++ /dev/null
@@ -1,317 +0,0 @@
-# Работа с ККТ
-
-[Вернуться к содержанию](readme.md)
-
----
-
-## Доступ к ККТ
-
-Для работы с облачной ККТ необходимы следующие параметры:
-
-* логин;
-* пароль;
-* код группы.
-
-Чтоы получить их, нужно:
-
-1. авторизоваться в личном кабинете [online.atol.ru](https://online.atol.ru/lk/Account/Login);
-2. на странице [Мои компании](https://online.atol.ru/lk/Company/List) нажать кнопку **Настройки интегратора**.
- Скачается XML-файл с нужными настройками.
-
-Также для работы потребуются:
-
-* ИНН продавца;
-* URL места расчёта (ссылка на ваш интернет-сервис).
-
-## Использование
-
-Объект ККТ инициализируется следующим образом:
-
-```php
-$kkt = new AtolOnline\Api\Kkt();
-```
-
-## Настройка ККТ
-
-Для работы с облачной ККТ необходимы следующие параметры:
-* логин кассы;
-* пароль кассы;
-* код группы кассы;
-
-Чтоб получить их, нужно:
-1. авторизоваться на [online.atol.ru](https://online.atol.ru/lk/Account/Login);
-2. на странице [Мои компании](https://online.atol.ru/lk/Company/List) нажать кнопку **Настройки интегратора**.
- Скачается XML-файл с нужными настройками.
-
-Установить эти параметры можно двумя путями:
-
-```php
-// 1 способ - через конструктор
-$kkt = new AtolOnline\Api\Kkt($group, $login, $password);
-
-// 2 способ - через сеттеры
-$kkt = (new AtolOnline\Api\Kkt())
- ->setLogin($login)
- ->setGroup($group)
- ->setPassword($password);
-```
-
-Получить заданные параметры можно через соответствующие геттеры:
-
-```php
-$kkt->getLogin();
-$kkt->getPassword();
-$kkt->getGroup();
-```
-
-Также для работы потребуются:
-* ИНН продавца;
-* URL места расчёта (ссылка на ваш интернет-сервис).
-
-Эти параметры нужно задать [объекту компании](/docs/company.md), который будет передаваться в документах через эту ККТ.
-
-
-## Тестовый режим
-
-На самом деле, в АТОЛ Онлайн нет понятия *тестовая операция* или чего-то в этом духе.
-АТОЛ предоставляет нам отдельную тестовую среду (ККТ).
-[Её настройки](https://online.atol.ru/files/ffd/test_sreda.txt) уже указаны в коде библиотеки.
-*Под тестовым режимом работы подразумевается использование другой (тестовой) ККТ.*
-
-При включенном тестовом режиме:
-* меняется логин, пароль и группа (для обращения на тестовую ККТ)
-* между авторизацией и операцией над документом, в `Company` документа переопределяется ИНН, СНО и адрес места
-расчётов на те, что указаны в [параметрах тестовой среды](https://online.atol.ru/files/ffd/test_sreda.txt).
-
-В библиотеке есть переключатель настроек ККТ.
-С его помощью можете поменять вашу боевую ККТ на тестовую и наоборот.
-Это можно сделать одним из следующих способов:
-
-```php
-// включить в любом месте кода:
-$kkt->setTestMode();
-$kkt->setTestMode(true);
-$kkt->setTestMode(false); // выключить
-```
-
-> Если вы включили тестовый режим (как показано выше), то используются именно эта ККТ, а не ваша.
-> После выключения тестового режима настройки доступа к ККТ меняются на ваши (используется уже ваша ККТ).
-
-Для включения тестового режима необязательно задавать параметры боевой ККТ.
-
-Если по каким-то причинам у вас не получится использовать тестовый режим, вы можете проводить свои тесты в боевом
-режиме (на собственной ККТ).
-В этом случае важно понимать следующее:
-1. сразу после оформления документа **прихода** необходимо оформлять точно такой же документ **возврата прихода**;
-2. [вы обязательно забудете о пункте 1](http://murphy-law.net.ru/basics.html);
-3. пп. 1 и 2 в любом случае скажутся на ваших финансовых отчётах;
-4. вся ответственность за пп. 1-3 и последствия ложится только на вас.
-
-## Авторизация на ККТ
-
-Перед первым запросом на ККТ происходит аутентификация на сервере по логину и паролю.
-В ответ приходит авторизационный токен, срок жизни коего равен **24 часам**.
-После первой успешной операции возможно получить этот токен следующим образом:
-
-```php
-$kkt->getAuthToken(); // вернёт строку длиной 128 символа
-```
-
-Этот токен можно сохранить и переиспользовать в течение всего срока его жизни.
-Спустя это время следует получить новый токен.
-
-Для дальнейшего использования однажды полученный токен следует указывать следующим образом:
-
-```php
-$kkt->setAuthToken($token_string);
-```
-
-Если токен был установлен перед выполнением операции, то при выполнении операции будет использоваться именно он, а новый
-запрашиваться не будет. Если операция завершится ошибочно из-за истёкшего токена, следует повторить операцию без
-использования метода `setAuthToken()`, либо обнулив его следующим образом:
-
-```php
-$kkt->setAuthToken(null);
-```
-
-## Регистрация документа
-
-Для регистрации документа **прихода** необходимо вызвать метод `sell()`:
-
-```php
-$result = $kkt->sell($document);
-```
-
-Для регистрации документа **возврата прихода** необходимо вызвать метод `sellRefund()`:
-
-```php
-$result = $kkt->sellRefund($document);
-```
-
-Для регистрации документа **расхода** необходимо вызвать метод `buy()`:
-
-```php
-$result = $kkt->buy($document);
-```
-
-Для регистрации документа **возврата расхода** необходимо вызвать метод `buyRefund()`:
-
-```php
-$result = $kkt->buyRefund($document);
-```
-
-Для операций, перечисленных выше, документы не должны содержать [данных коррекции](/docs/documents.md#correction).
-Тогда как для операций коррекции, которые описаны ниже, эти данные должны присутствовать.
-
-Для регистрации документа **коррекции прихода** необходимо вызвать метод `sellCorrection()`:
-
-```php
-$result = $kkt->sellCorrection($document);
-```
-
-Для регистрации документа **коррекции расхода** необходимо вызвать метод `buyCorrection()`:
-
-```php
-$result = $kkt->buyCorrection($document);
-```
-
-Любой из перечисленных выше шести методов может выбросить исключение `AtolAuthFailedException` при ошибке
-аутентификации или авторизации.
-
-### Собственный идентификатор документа
-
-Каждый документ, переданный на ККТ для регистрации, всегда имеет свой идентификатор, абсолютно уникальный среди всех
-документов когда-либо регистрировавшихся на ККТ, даже если при регистрации были ошибки.
-По умолчанию это UUID версии 4.
-
-Чтобы использовать собственный идентификатор, следует передать нужное строковое значение вторым параметром в любой из
-шести описанных выше методов, например:
-
-```php
-$kkt->sell($document, $my_unique_id);
-$kkt->sellRefund($document, $my_unique_id);
-$kkt->buy($document, $my_unique_id);
-$kkt->buyRefund($document, $my_unique_id);
-$kkt->sellCorrection($document, $my_unique_id);
-$kkt->buyCorrection($document, $my_unique_id);
-```
-
-Если `$my_unique_id` равен `null` или пустой строке, то будет сгенерирован новый UUID.
-Узнать его можно будет только в ответе от ККТ.
-
-### Передача callback_url
-
-Перед регистрацией документа можно указать `callback_url`.
-АТОЛ отправит на указанный URL результат регистрации.
-По этому адресу должен располагаться код, который будет обрабатывать этот результат.
-
-```php
-$kkt->setCallbackUrl('http://example.com/process-kkt-result');
-$kkt->getCallbackUrl();
-```
-
-Метод `setCallbackUrl()` проверяет входную строку на длину (до 256 символов) и валидность формата url по
-регулярному выражению:
-
-```
-^http(s?)\:\/\/[0-9a-zA-Zа-яА-Я]([-.\w]*[0-9a-zA-Zа-яА-Я])*(:(0-9)*)*(\/?)([a-zAZ0-9а-яА-Я\-\.\?\,\'\/\\\+&=%$#_]*)?$
-```
-
-Выбрасывает исключения:
-* `AtolCallbackUrlTooLongException` (если слишком длинный url);
-* `AtolInvalidCallbackUrlException` (если url невалиден).
-
-## Обработка результата регистрации
-
-Методы `sell()`, `sellRefund()`, `sellCorrection()`, `buy()`, `buyRefund()` и `buyCorrection()` возвращают объект `AtolOnline\Api\KktResponse`.
-
-Этот же объект можно получить через геттер `getLastResponse()`.
-
-Этот объект содержит в себе HTTP-код ответа, массив заголовков и JSON-декодированные данные тела ответа.
-
-```php
-$result = $kkt->getLastResponse(); // вернёт последний ответ от API
-$headers = $result->getHeaders(); // вернёт заголовки
-$code = $result->getCode(); // вернёт код ответа
-$body = $result->getContent(); // вернёт JSON-декодированное тело ответа
-```
-
-Обращаться к полям JSON-декодированного объекта можно опуская вызов метода `getContent()` таким образом:
-
-```php
-// вернёт значение поля uuid
-$uuid = $result->getContent()->uuid;
-$uuid = $result->uuid;
-// вернёт текст ошибки
-$err_text = $result->getContent()->error->text;
-$err_text = $result->error->text;
-```
-
-Проверка корректности ответа (отсутствия ошибок) работает через метод `isValid()`:
-
-```php
-$kkt->getLastResponse()->isValid(); // вернёт true, если ошибок нет
-```
-
-## Проверка статуса документа
-
-Если перед отправкой документа на регистрацию был задан callback_url через метод `setCallbackUrl()`, то ответ придёт на указанный адрес автоматически, как только документ обработается на стороне ККТ.
-Ответ может быть как об успешной регистрации, так и ошибочной.
-
-В любом случае, вам доступны два метода, с помощью которых вы можете проверять статус документа самостоятельно:
-
-```php
-$kkt->getDocumentStatus();
-$kkt->pollDocumentStatus();
-```
-
-Эти методы принимают на вход `uuid` кода регистрации.
-Этот UUID можно получить из ответа, полученного при отправке документа на регистрацию:
-
-```php
-$sell_result = $kkt->sell($document);
-$kkt->pollDocumentStatus($sell_result->uuid);
-$kkt->getDocumentStatus($sell_result->uuid);
-```
-
-Метод `pollDocumentStatus()` многократно опрашивает ККТ на предмет состояния документа.
-Метод может принимать до трёх параметров:
-* uuid;
-* количество попыток (по умолчанию — 5);
-* время между попытками в секундах (по умолчанию — 1).
-
-```php
-// Проверять статус 10 раз на протяжении 20 секунд — каждые две секунды
-$kkt->pollDocumentStatus($sell_result->uuid, 10, 20);
-```
-
-Учитывайте, что метод вернёт результат как только сменится статус регистрации на успешный или ошибочный.
-
-Использовать его лучше сразу после отправки документа на регистрацию (как в примере выше).
-
-> Как правило, полная регистрация одного документа занимает 4-5 секунд.
-
-Метод `getDocumentStatus()` принимает на вход только `uuid` и запрашивает состояние документа лишь единожды.
-Использовать его целесообразнее в те моменты, когда нет необходимости знать успех регистрации сразу после отправки документа.
-
-> Обратите внимание, что АТОЛ позволяет получать статус документа в течение 32 суток с момента его регистрации.
-
-Методы `pollDocumentStatus()` и `getDocumentStatus()` возвращают объект `AtolOnline\Api\KktResponse`.
-Оба выбрасывают исключение `AtolUuidValidateException` (если переданная строка UUID невалидна).
-
-Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
-
-```php
-echo $item;
-$json_string = (string)$item;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $item->jsonSerialize();
-```
-
----
-
-[Вернуться к содержанию](readme.md)
diff --git a/docs/monitoring.md b/docs/monitoring.md
index c3dcf2f..3bb81ce 100644
--- a/docs/monitoring.md
+++ b/docs/monitoring.md
@@ -1,6 +1,6 @@
# Мониторинг ККТ
-[Вернуться к содержанию](readme.md)
+[Вернуться к содержанию](readme.md#toc)
---
@@ -12,13 +12,13 @@
```php
// можно передать параметры подключения в конструктор
-$monitor = new AtolOnline\Api\KktMonitor(
+$monitor = new AtolOnline\Api\Monitor(
login: 'mylogin',
password: 'qwerty'
);
// можно - отдельными сеттерами
-$monitor = new AtolOnline\Api\KktMonitor();
+$monitor = new AtolOnline\Api\Monitor();
->setLogin($credentials['login'])
->setPassword($credentials['password']);
```
@@ -30,7 +30,7 @@ $monitor = new AtolOnline\Api\KktMonitor();
```php
// передачей в конструктор `false` первым параметром:
-$monitor = new AtolOnline\Api\KktMonitor(false, /*...*/);
+$monitor = new AtolOnline\Api\Monitor(false, /*...*/);
// или отдельным сеттером
$monitor->setTestMode(false);
@@ -107,10 +107,12 @@ $kkt = $monitor->getOne($kkts->first()->serialNumber);
Класс `AtolOnline\Api\KktMonitor` расширяет абстрактный класс `AtolOnline\Api\AtolClient`.
-Это значит, что последний ответ от API АТОЛ всегда сохраняется объектом класса `AtolOnline\Api\KktResponse`. К нему
+Это значит, что последний ответ от API АТОЛ всегда сохраняется объектом класса `AtolOnline\Api\AtolReponse`. К нему
можно обратиться через метод `AtolOnline\Api\KktMonitor::getResponse()`, независимо от того, что возвращают другие
методы монитора.
---
-[Вернуться к содержанию](readme.md)
+Читай также: [Обработка ответа API](response.md)
+
+[Вернуться к содержанию](readme.md#toc)
diff --git a/docs/payments.md b/docs/payments.md
deleted file mode 100644
index 9829a57..0000000
--- a/docs/payments.md
+++ /dev/null
@@ -1,134 +0,0 @@
-# Работа с оплатами
-
-[Вернуться к содержанию](readme.md)
-
----
-
-## Один объект
-
-Объект оплаты инициализируется следующим образом:
-
-```php
-$payment = new AtolOnline\Entities\Payment();
-```
-
-У объекта оплаты должны быть указаны все следующие атрибуты:
-* тип оплаты (теги ФФД: 1031, 1081, 1215, 1216, 1217) - все типы перечислены в классе `AtolOnline\Constants\PaymentTypes` (по умолчанию `ELECTRON`)
-* сумма оплаты (теги ФФД: 1031, 1081, 1215, 1216, 1217; по умолчанию 0)
-
-> Все эти атрибуты являются **обязательными**.
-
-Установить атрибуты можно следующими способами:
-
-```php
-// 1 способ - через конструктор
-$payment = new AtolOnline\Entities\Payment(
- AtolOnline\Constants\PaymentTypes::OTHER, // тип оплаты
- 123.45 // сумма оплаты
-);
-
-// 2 способ - через сеттер
-$payment = (new AtolOnline\Entities\Payment())
- ->setType(AtolOnline\Constants\PaymentTypes::OTHER) // тип оплаты
- ->setSum(123.45); // сумма оплаты
-```
-
-Размер налога высчитывается автоматически из общей суммы.
-Сумму, от которой нужно расчитать размер налога, можно передать следующими способами:
-
-```php
-// 1 способ - через конструктор
-$payment = new AtolOnline\Entities\Payment(
- AtolOnline\Constants\PaymentTypes::CASH, // тип оплаты
- 1234.56 // сумма оплаты в рублях
-);
-
-// 2 способ - через сеттер
-$payment = (new AtolOnline\Entities\Payment())
- ->setType(AtolOnline\Constants\PaymentTypes::CASH) // тип оплаты
- ->setSum(1234.56); // сумма оплаты в рублях
-```
-
-Получить установленную сумму оплаты в рублях можно через геттер `getSum()`:
-
-```php
-var_dump($payment->getSum());
-```
-
-Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
-
-```php
-echo $payment;
-$json_string = (string)$payment;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $payment->jsonSerialize();
-```
-
-
-## Массив объектов оплат
-
-> Максимальное количество объектов в массиве - 10.
-
-Массив инициализируется следующим образом:
-
-```php
-$payment_array = new AtolOnline\Entities\PaymentArray();
-```
-
-Чтобы задать содержимое массива, используйте метод `set()`:
-
-```php
-use AtolOnline\{Constants\PaymentTypes, Entities\Payment};
-
-$payment_array->set([
- new Payment(PaymentTypes::ELECTRON, 123),
- new Payment(PaymentTypes::ELECTRON, 53.2),
- new Payment(PaymentTypes::ELECTRON, 23.99),
- new Payment(PaymentTypes::ELECTRON, 11.43)
-]);
-```
-
-Очистить его можно передачей в сеттер пустого массива:
-
-```php
-$payment_array->set([]);
-```
-
-Чтобы добавить объект к существующим элементам массива, используйте метод `add()`:
-
-```php
-use AtolOnline\{Constants\PaymentTypes, Entities\Payment};
-
-$payment = new Payment(PaymentTypes::PRE_PAID, 20);
-$payment_array->add($payment);
-```
-
-Методы `set()` и `add()` проверяют количество элементов в массиве перед его обновлением.
-Выбрасывают исключение `AtolTooManyPaymentsException` (если в массиве уже максимальное количество объектов).
-
-Чтобы получить содержимое массива, используйте метод `get()`:
-
-```php
-$payment_array->get();
-```
-
-Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
-
-```php
-echo $payment_array;
-$json_string = (string)$payment_array;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $payment_array->jsonSerialize();
-```
-
----
-
-[Вернуться к содержанию](readme.md)
\ No newline at end of file
diff --git a/docs/readme.md b/docs/readme.md
index 53dc201..9b95680 100644
--- a/docs/readme.md
+++ b/docs/readme.md
@@ -1,26 +1,42 @@
# Документация к библиотеке
+
+
+## Содержание
+
+* [Общий алгоритм](#getstarted)
+* [Сущность](entity.md)
+* [Коллекция сущностей](collection.md)
+* [Мониторинг ККТ](monitoring.md)
+* [Фискализация документа](fiscalizing.md)
+* [Обработка ответа API](response.md)
+
+Если вы нашли опечатку или какое-то несоответствие — делайте pull-request.
+
+
+
## Общий алгоритм
-1. Задать настройки ККТ
-2. Собрать данные о покупателе
-3. Собрать данные о продавце
-4. Собрать данные о предметах расчёта (товары, услуги и пр.)
-5. Создать документ, добавив в него покупателя, продавца и предметы расчёта
-6. Отправить документ на регистрацию:
- 6.1. *Необязательно:* задать `callback_url`, на который АТОЛ отправит HTTP POST о состоянии документа.
-7. Запомнить `uuid` из пришедшего ответа, поскольку он пригодится для последующей проверки статуса фискализации.
- > Если с документом был передан `callback_url`, то ответ придёт на этот самый URL.
- Если с документом **НЕ** был передан `callback_url` **либо** callback от АТОЛа не пришёл в течение 300 секунд (5 минут), нужно запрашивать вручную по `uuid`, пришедшему от АТОЛа в ответ на регистрацию документа.
-8. Проверить состояние документа:
- 8.1. взять `uuid` ответа, полученного на запрос фискализации;
- 8.2. отправить его в запросе состояния документа.
+1. Создать документ `AtolOnline\Entities\Receipt` или `AtolOnline\Entities\Correction`, добавив в него все необходимые
+ данные
+2. Отправить документ на регистрацию:
+ 2.1. *Необязательно:* при отправке задать `callback_url`, на который АТОЛ отправит HTTP POST о состоянии документа;
+ 2.2. *Необязательно:* при отправке задать `external_id`, чтобы присвоить свой уникальный идентификатор документа;
+3. Запомнить `uuid` из пришедшего ответа, поскольку он пригодится для последующей проверки статуса фискализации.
+ > Если с документом был передан `callback_url`, то ответ придёт на этот самый URL.
+ > Он должен быть обработан вашим сервисом в соответствии с бизнес-процессом.
+
+ > Если с документом **не был** передан `callback_url` **либо** callback от АТОЛа не пришёл в течение 300 секунд
+ > (5 минут), нужно запрашивать вручную по `uuid`, пришедшему от АТОЛа в ответ на регистрацию документа.
+4. Проверить состояние документа:
+ 4.1. взять `uuid` ответа, полученного на запрос фискализации;
+ 4.2. отправить его в запросе состояния документа.
> Данные о документе можно получить только в течение 32 суток после успешной фискализации.
-В зависимости от специфики бизнеса, в документах можно/нужно передавать также и другую информацию. Подробности в
-документациях и исходниках.
+В зависимости от специфики бизнеса, в документах можно/нужно передавать разную информацию. Подробности в документации
+АТОЛ Онлайн и исходниках библиотеки.
-### Об отправке электронного чека покупателю
+## Об отправке электронного чека покупателю
После успешной фискализации документа покупатель автоматически получит уведомление **от ОФД**, который используется в
связке с вашей ККТ:
@@ -31,19 +47,3 @@
* если на стороне ОФД необходима и подключена услуга СМС-информирования (уточняйте подробности о своего ОФД).
> Если заданы email и телефон, то ОФД отдаёт приоритет email.
-
-## Подготовка документа
-
-1. [Работа с клиентами (покупателями)](client.md)
-2. [Работа с компанией (продавцом)](company.md)
-3. [Работа с оплатами](payments.md)
-4. [Работа со ставками НДС](vats.md)
-5. [Работа с предметами расчёта](items.md)
-6. [Работа с данными коррекции](correction_info.md)
-7. [Работа с документами](documents.md)
-8. [Работа с ККТ](kkt.md)
-9. [Мониторинг ККТ](monitoring.md)
-
----
-
-Если вы нашли опечатку или какое-то несоответствие — делайте pull-request.
diff --git a/docs/response.md b/docs/response.md
new file mode 100644
index 0000000..f13ec8d
--- /dev/null
+++ b/docs/response.md
@@ -0,0 +1,57 @@
+# Обработка ответа API
+
+[Вернуться к содержанию](readme.md#toc)
+
+---
+
+Объект класса `AtolOnline\Api\AtolResponse` возвращается всеми методами, которые обращаются к АТОЛ Онлайн API.
+
+Поскольку классы `AtolOnline\Api\Fiscalizer` и `AtolOnline\Api\KktMonitor` наследуются от
+абстрактного `AtolOnline\Api\AtolClient`, они оба предоставляют метод `getLastReponse()` для возврата последнего
+полученного ответа от API.
+
+Таким образом, а общем случае необязательно сразу сохранять ответ в переменную:
+
+```php
+$response = $kkt->sell($receipt);
+```
+
+Достаточно обратиться к нему позднее:
+
+```php
+$kkt->sell($receipt);
+// ...
+$response = $kkt->getLastResponse();
+```
+
+Однако, при сложной логике и многократных запросах следует пользоваться этим с умом и осторожностью.
+
+Объект `AtolResponse` содержит в себе HTTP-код ответа, массив заголовков и JSON-декодированные данные тела ответа.
+
+```php
+$headers = $response->getHeaders(); // вернёт заголовки
+$code = $response->getCode(); // вернёт код ответа
+$body = $response->getContent(); // вернёт JSON-декодированный объект тела ответа
+```
+
+Обращаться к полям тела ответа можно опуская вызов метода `getContent()`:
+
+```php
+// вернёт значение поля uuid
+$uuid = $response->getContent()->uuid;
+$uuid = $response->uuid;
+
+// вернёт текст ошибки
+$err_text = $response->getContent()->error->text;
+$err_text = $response->error->text;
+```
+
+Проверка успешности операции доступна через метод `isSuccessful()`:
+
+```php
+$response->isSuccessful(); // вернёт true, если ошибок нет
+```
+
+---
+
+[Вернуться к содержанию](readme.md#toc)
diff --git a/docs/vats.md b/docs/vats.md
deleted file mode 100644
index 371a447..0000000
--- a/docs/vats.md
+++ /dev/null
@@ -1,128 +0,0 @@
-# Работа со ставками НДС
-
-[Вернуться к содержанию](readme.md)
-
----
-
-## Один объект
-
-Объект ставки НДС инициализируется следующим образом:
-
-```php
-use AtolOnline\Entities\Vat;
-use AtolOnline\Enums\VatTypes;
-
-$vat = new Vat(
- VatTypes::VAT10, // тип ставки
- 123.45 // сумма в рублях, от которой считать ставку
-);
-```
-
-Для типа и суммы имеются отдельные сеттеры:
-
-```php
-$vat->setType(VatTypes::VAT20)
- ->setSum(100.15); // 123.45 заменится на 100.15
-```
-
-Общую сумму, из которой расчитывается размер налога, можно увеличить, используя метод `addSum()`. Указанная в рублях
-сумма увеличится на указанные рубли. Для уменьшения суммы следует передать отрицательное число.
-
-```php
-$vat->addSum(40) // 100.15 + 40 = 140.15р
- ->addSum(-15); // 140.15 - 15 = 125.15р
-```
-
-Получить установленную сумму можно через геттер `getSum()`:
-
-```php
-$vat->getSum(); // 125.15р
-```
-
-Размер налога по ставке высчитывается из этой общей суммы. Не смотря на то, что геттер и сеттер работают с рублями, **
-расчёты производятся в копейках**. Сделать это можно через `getCalculated()`:
-
-```php
-$vat->getCalculated();
-// для примера выше это 20% от 125.15р = 25.03р
-```
-
-Разберём комплексный пример изменения типа ставки и расчётной суммы:
-
-Объект класса приводится к JSON-строке автоматически или принудительно:
-
-```php
-echo $vat;
-$json_string = (string)$vat;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $vat->jsonSerialize();
-```
-
-
-## Массив объектов ставок НДС
-
-> Максимальное количество в массиве - 6.
-
-Массив инициализируется следующим образом:
-
-```php
-$vat_array = new AtolOnline\Entities\VatArray();
-```
-
-Чтобы задать содержимое массива, используйте метод `set()`:
-
-```php
-use AtolOnline\{Constants\VatTypes, Entities\Vat};
-
-$vat_array->set([
- new Vat(VatTypes::VAT10, 123),
- new Vat(VatTypes::VAT110, 53.2),
- new Vat(VatTypes::VAT20, 23.99),
- new Vat(VatTypes::VAT120, 11.43)
-]);
-```
-
-Очистить его можно передачей в сеттер пустого массива:
-
-```php
-$vat_array->set([]);
-```
-
-Чтобы добавить объект к существующим элементам массива, используйте метод `add()`:
-
-```php
-use AtolOnline\{Constants\VatTypes, Entities\Vat};
-
-$vat = new Vat(VatTypes::VAT20, 20);
-$vat_array->add($vat);
-```
-
-Методы `set()` и `add()` проверяют количество элементов в массиве перед его обновлением.
-Выбрасывают исключение `AtolTooManyVatsException` (если в массиве уже максимальное количество объектов).
-
-Чтобы получить содержимое массива, используйте метод `get()`:
-
-```php
-$vat_array->get();
-```
-
-Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
-
-```php
-echo $vat_array;
-$json_string = (string)$vat_array;
-```
-
-Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
-
-```php
-$json_array = $vat_array->jsonSerialize();
-```
-
----
-
-[Вернуться к содержанию](readme.md)