mirror of
https://github.com/anthonyaxenov/atol-online.git
synced 2024-11-24 11:19:35 +00:00
Initial commit, v0.1.0-b
This commit is contained in:
commit
1db2d5b49f
23
.github/workflows/tests.yml
vendored
Normal file
23
.github/workflows/tests.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
name: Composer and phpunit tests
|
||||||
|
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
|
||||||
|
- name: Validate composer.json and composer.lock
|
||||||
|
run: composer validate
|
||||||
|
|
||||||
|
- name: Install composer dependencies
|
||||||
|
run: composer install --prefer-dist --no-progress --no-suggest
|
||||||
|
|
||||||
|
- name: Run phpunit tests
|
||||||
|
uses: php-actions/phpunit@v1.0.0
|
||||||
|
with:
|
||||||
|
# Configuration file location
|
||||||
|
config: ./phpunit.xml
|
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/.idea
|
||||||
|
/vendor
|
||||||
|
/atol_log
|
||||||
|
*.log
|
||||||
|
/config.php
|
||||||
|
*cache*
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Антон Аксенов (aka Anthony Axenov)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
110
README.md
Normal file
110
README.md
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
# АТОЛ Онлайн
|
||||||
|
|
||||||
|
Библиотека для фискализации чеков по 54-ФЗ через [облачную ККТ АТОЛ](https://online.atol.ru/).
|
||||||
|
|
||||||
|
## Системные требования
|
||||||
|
|
||||||
|
* PHP 7.2+
|
||||||
|
* composer
|
||||||
|
* php-json
|
||||||
|
|
||||||
|
## Начало работы
|
||||||
|
|
||||||
|
### Подключение библиотеки
|
||||||
|
|
||||||
|
1. Подключить пакет к вашему проекту:
|
||||||
|
```bash
|
||||||
|
composer require axenov/atol-online
|
||||||
|
```
|
||||||
|
2. В нужном месте проекта объявить параметры, используя константы, и подключить **composer**, если это не сделано ранее:
|
||||||
|
```php
|
||||||
|
require($project_root.'/vendor/autoload.php');
|
||||||
|
```
|
||||||
|
где $project_root — абсолютный путь к корневой директории вашего проекта.
|
||||||
|
|
||||||
|
### Тестирование кода библиотеки
|
||||||
|
|
||||||
|
Файлы тестов находятся в директории `/tests` корня репозитория.
|
||||||
|
|
||||||
|
Для запуска тестов необходимо перейти в корень вашего проекта и выполнить команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./vendor/bin/phpunit
|
||||||
|
```
|
||||||
|
|
||||||
|
## Настройка ККТ
|
||||||
|
|
||||||
|
Для работы с облачной ККТ необходимы следующие параметры:
|
||||||
|
* логин;
|
||||||
|
* пароль;
|
||||||
|
* код группы.
|
||||||
|
|
||||||
|
Чтоб получить их, нужно:
|
||||||
|
1. авторизоваться на [online.atol.ru](https://online.atol.ru/lk/Account/Login);
|
||||||
|
2. на странице [Мои компании](https://online.atol.ru/lk/Company/List) нажать кнопку **Настройки интегратора**.
|
||||||
|
Скачается XML-файл с нужными настройками.
|
||||||
|
|
||||||
|
Также для работы потребуются:
|
||||||
|
* ИНН продавца;
|
||||||
|
* URL места расчёта (ссылка на ваш интернет-сервис).
|
||||||
|
|
||||||
|
## Использование библиотеки
|
||||||
|
|
||||||
|
### Доступные методы и классы
|
||||||
|
|
||||||
|
Весь исходный код находится в директории [`/src`](/src).
|
||||||
|
|
||||||
|
**Комментарии phpDoc есть буквально к каждому классу, методу или полю.
|
||||||
|
Прокомментировано вообще всё.**
|
||||||
|
|
||||||
|
1. Обращайтесь к [документации](/docs).
|
||||||
|
2. Обращайтесь к [исходному коду](/src).
|
||||||
|
3. Обращайтесь к [тестам](/test).
|
||||||
|
4. **Используйте подсказки вашей IDE.**
|
||||||
|
|
||||||
|
Тогда у вас не возникнет затруднений.
|
||||||
|
|
||||||
|
Для тех, кто решил подробно разобраться в работе библиотеки, отдельно отмечу нюансы, которые могут ускользнуть от внимания:
|
||||||
|
1. Класс `AtolOnline\Api\Kkt` унаследован от `GuzzleHttp\Client` со всеми вытекающими;
|
||||||
|
2. Все классы, унаследованные от `AtolOnline\Entities\AtolEntity` приводятся к JSON-строке.
|
||||||
|
|
||||||
|
### Общий алгоритм
|
||||||
|
|
||||||
|
1. Задать настройки ККТ
|
||||||
|
2. Собрать данные о покупателе
|
||||||
|
3. Собрать данные о продавце
|
||||||
|
4. Собрать данные о предметах расчёта (товары, услуги и пр.)
|
||||||
|
5. Создать документ, добавив в него покупателя, продавца и предметы расчёта
|
||||||
|
6. Отправить документ на регистрацию:
|
||||||
|
6.1. *Необязательно:* задать `callback_url`, на который АТОЛ отправит HTTP POST о состоянии документа.
|
||||||
|
7. Запомнить `uuid` из пришедшего ответа, поскольку он пригодится для последующей проверки статуса фискализации.
|
||||||
|
> Если с документом был передан `callback_url`, то ответ придёт на этот самый URL.
|
||||||
|
Если с документом **НЕ** был передан `callback_url` **либо** callback от АТОЛа не пришёл в течение 300 секунд (5 минут), нужно запрашивать вручную по `uuid`, пришедшему от АТОЛа в ответ на регистрацию документа.
|
||||||
|
8. Проверить состояние документа (нет необходимости, если передавался `callback_url`):
|
||||||
|
8.1. взять `uuid` ответа, полученного на запрос фискализации;
|
||||||
|
8.2. отправить его в запросе состояния документа.
|
||||||
|
> Данные о документе можно получить только в течение 32 суток после успешной фискализации.
|
||||||
|
|
||||||
|
## Об отправке электронного чека покупателю
|
||||||
|
|
||||||
|
После успешной фискализации документа покупатель автоматически получит уведомление **от ОФД**, который используется в связке с вашей ККТ:
|
||||||
|
* **по email**, если в документе указан email клиента;
|
||||||
|
* **по смс**:
|
||||||
|
* если в документе указан номер телефона клиента;
|
||||||
|
* если на стороне ОФД необходима и подключена услуга СМС-информирования (уточняйте подробности о своего ОФД).
|
||||||
|
|
||||||
|
> Если заданы email и телефон, то отдаётся приоритет email.
|
||||||
|
|
||||||
|
## Дополнительные ресурсы
|
||||||
|
|
||||||
|
**Discord-сервер для обсуждения этой библиотеки: [discord.gg/mFYTQmp](https://discord.gg/mFYTQmp)**
|
||||||
|
|
||||||
|
Функционал, находящийся в разработке: [ROADMAP.md](ROADMAP.md)
|
||||||
|
|
||||||
|
Официальные ресурсы АТОЛ Онлайн:
|
||||||
|
* **[Вся документация](https://online.atol.ru/lib/)**
|
||||||
|
* Telegram-канал: [@atolonline](https://t.me/atolonline)
|
||||||
|
|
||||||
|
## Лицензия
|
||||||
|
|
||||||
|
Вы имеете право использовать код из этого репозитория только на условиях **[лицензии MIT](LICENSE)**.
|
67
ROADMAP.md
Normal file
67
ROADMAP.md
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# Roadmap
|
||||||
|
|
||||||
|
Здесь перечислены реализованные функции и находящиеся в разработке.
|
||||||
|
|
||||||
|
Порядок их упоминания здесь может не совпадать с порядком реализации.
|
||||||
|
|
||||||
|
Эталонная реализация подразумевает полную поддержку всех методов API и обеих схем документов:
|
||||||
|
* [Документы прихода, возврата прихода, расхода, возврата расхода](https://online.atol.ru/possystem/v4/schema/sell)
|
||||||
|
* [Документы коррекции прихода, коррекции расхода](https://online.atol.ru/possystem/v4/schema/correction)
|
||||||
|
|
||||||
|
## Общий функционал библиотеки
|
||||||
|
|
||||||
|
- [x] Переключение настроек доступа к ККТ при переключении тестового режима
|
||||||
|
- [x] Тесты для класса налоговой ставки (+ массив)
|
||||||
|
- [ ] Тесты для класса оплаты (+ массив)
|
||||||
|
- [x] Тесты для класса предмета расчёта (+ массив)
|
||||||
|
- [x] Тесты для класса клиента
|
||||||
|
- [x] Тесты для класса компании
|
||||||
|
- [ ] Тесты для класса данных коррекций
|
||||||
|
- [ ] Тесты для класса документа
|
||||||
|
- [ ] Тесты для класса ответа ККТ
|
||||||
|
- [ ] Тесты для регистрации документа прихода
|
||||||
|
- [ ] Тесты для регистрации документа возврата прихода
|
||||||
|
- [ ] Тесты для регистрации документа коррекции прихода
|
||||||
|
- [ ] Тесты для регистрации документа расхода
|
||||||
|
- [ ] Тесты для регистрации документа возврата расхода
|
||||||
|
- [ ] Тесты для регистрации документа коррекции расхода
|
||||||
|
- [ ] Вообще все расчёты вообще везде должны быть строго в копейках. Рубли (дроби) должны быть только в JSON-представлениях
|
||||||
|
- [ ] Валидатор схемы для документов прихода, возврата прихода, расхода, возврата расхода
|
||||||
|
- [ ] Валидатор схемы для документов коррекции прихода, коррекции расхода
|
||||||
|
|
||||||
|
## Поддержка методов API (регистрация документов)
|
||||||
|
|
||||||
|
- [x] приход
|
||||||
|
- [x] расход
|
||||||
|
- [x] возврат прихода
|
||||||
|
- [x] возврат расхода
|
||||||
|
- [x] коррекция прихода
|
||||||
|
- [x] коррекция расхода
|
||||||
|
- [x] проверка статуса документа
|
||||||
|
|
||||||
|
## Документы прихода, возврата прихода, расхода, возврата расхода
|
||||||
|
|
||||||
|
- [x] Пoддержка `receipt.client` (обязательный)
|
||||||
|
- [x] Пoддержка `receipt.company` (обязательный)
|
||||||
|
- [x] Пoддержка `receipt.items` (обязательный)
|
||||||
|
- [x] Пoддержка `receipt.total` (обязательный)
|
||||||
|
- [x] Пoддержка `receipt.payments` (обязательный)
|
||||||
|
- [x] Пoддержка `receipt.vats`
|
||||||
|
- [ ] Пoддержка `receipt.additional_check_props`
|
||||||
|
- [x] Пoддержка `receipt.cashier`
|
||||||
|
- [ ] Пoддержка `receipt.additional_user_props`
|
||||||
|
- [ ] Пoддержка `receipt.agent_info`
|
||||||
|
- [ ] Пoддержка `receipt.supplier_info`
|
||||||
|
- [ ] Пoддержка `receipt.items.agent_info`
|
||||||
|
- [ ] Пoддержка `receipt.items.supplier_info`
|
||||||
|
- [ ] Пoддержка `receipt.items.nomenclature_code`
|
||||||
|
- [ ] Пoддержка `receipt.items.excise`
|
||||||
|
- [ ] Пoддержка `receipt.items.country_code`
|
||||||
|
- [ ] Пoддержка `receipt.items.declaration_number`
|
||||||
|
|
||||||
|
## Документы коррекции прихода, коррекции расхода
|
||||||
|
|
||||||
|
- [x] Пoддержка `correction.company` (обязательный)
|
||||||
|
- [x] Пoддержка `correction.vats` (обязательный)
|
||||||
|
- [x] Пoддержка `correction.correction_info` (обязательный)
|
||||||
|
- [x] Пoддержка `correction.cashier`
|
45
composer.json
Normal file
45
composer.json
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"name": "axenov/atol-online",
|
||||||
|
"description": "Library to use cloud cash register in e-commerce according to Russian Federal Law #54",
|
||||||
|
"license": "MIT",
|
||||||
|
"type": "library",
|
||||||
|
"version": "0.1.0-b",
|
||||||
|
"keywords": [
|
||||||
|
"54-fz",
|
||||||
|
"atol",
|
||||||
|
"atol-online"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/anthonyaxenov/atol-online",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Anthony Axenov",
|
||||||
|
"homepage": "http://anthonyaxenov.ru",
|
||||||
|
"email": "anthonyaxenov@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/anthonyaxenov/atol-online",
|
||||||
|
"issues": "https://github.com/anthonyaxenov/atol-online/issues",
|
||||||
|
"chat": "https://discord.gg/mFYTQmp"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2",
|
||||||
|
"ext-json": "*",
|
||||||
|
"guzzlehttp/guzzle": "^6.5",
|
||||||
|
"psr/log": "^1.1",
|
||||||
|
"ramsey/uuid": "^3.9"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^8.5"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"src/AtolOnline/Api/",
|
||||||
|
"src/AtolOnline/Exceptions/",
|
||||||
|
"src/AtolOnline/Entities/",
|
||||||
|
"src/AtolOnline/Traits/",
|
||||||
|
"src/AtolOnline/Constants/",
|
||||||
|
"tests/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
1996
composer.lock
generated
Normal file
1996
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
75
docs/client.md
Normal file
75
docs/client.md
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# Работа с клиентами (покупателями)
|
||||||
|
|
||||||
|
Объект покупателя инициализируется следующим образом:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$customer = new AtolOnline\Entities\Client();
|
||||||
|
```
|
||||||
|
|
||||||
|
У объекта покупателя могут быть указаны любые из следующих атрибутов:
|
||||||
|
* email (тег ФФД 1008);
|
||||||
|
* ИНН (тег ФФД 1128);
|
||||||
|
* наименование (тег ФФД 1127);
|
||||||
|
* номер телефона (тег ФФД 1008).
|
||||||
|
|
||||||
|
> Все эти атрибуты являются **необязательными**.
|
||||||
|
> Если указаны одновременно и email, и номер телефона, то ОФД отправит чек только на email.
|
||||||
|
|
||||||
|
Указать эти атрибуты можно двумя способами:
|
||||||
|
|
||||||
|
```php
|
||||||
|
// 1 способ - через конструктор
|
||||||
|
$customer = new AtolOnline\Entities\Client(
|
||||||
|
'John Doe', // наименование
|
||||||
|
'+1/22/99*73s dsdas654 5s6', // номер телефона +122997365456
|
||||||
|
'john@example.com', // email
|
||||||
|
'+fasd3\qe3fs_=nac990139928czc' // номер ИНН 3399013928
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2 способ - через сеттеры
|
||||||
|
$customer = (new AtolOnline\Entities\Client())
|
||||||
|
->setEmail('john@example.com')
|
||||||
|
->setInn('+fasd3\q3fs_=nac9901 3928c-c') // 3399013928
|
||||||
|
->setName('John Doe')
|
||||||
|
->setPhone('+1/22/99*73s dsdas654 5s6'); // +122997365456
|
||||||
|
|
||||||
|
// либо комбинация этих способов
|
||||||
|
```
|
||||||
|
|
||||||
|
Метод `setEmail()` проверяет входную строку на длину (до 64 символов) и валидность формата email.
|
||||||
|
Выбрасывает исключения:
|
||||||
|
* `AtolEmailTooLongException` (если слишком длинный email);
|
||||||
|
* `AtolEmailValidateException` (если email невалиден).
|
||||||
|
|
||||||
|
Метод `setInn()` чистит входную строку от всех символов, кроме цифр, и проверяет длину (либо 10, либо 12 цифр).
|
||||||
|
Выбрасывает исключение `AtolInnWrongLengthException` (если длина строка ИНН некорректна).
|
||||||
|
|
||||||
|
Метод `setName()` проверяет входную строку на длину (до 256 символов).
|
||||||
|
Выбрасывает исключение `AtolNameTooLongException` (если слишком длинное наименование).
|
||||||
|
|
||||||
|
Метод `setPhone()` чистит входную строку от всех символов, кроме цифр и знака `+`, и проверяет длину (до 64 символов).
|
||||||
|
Выбрасывает исключение `AtolPhoneTooLongException` (если слишком длинный номер телефона).
|
||||||
|
|
||||||
|
Конструктор может выбрасывать любое из указанных выше исключений, если в него передаются значения.
|
||||||
|
|
||||||
|
Получить установленные значения атрибутов можно через геттеры:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$customer->getInn();
|
||||||
|
$customer->getEmail();
|
||||||
|
$customer->getName();
|
||||||
|
$customer->getPhone();
|
||||||
|
```
|
||||||
|
|
||||||
|
Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
echo $customer;
|
||||||
|
$json_string = (string)$customer;
|
||||||
|
```
|
||||||
|
|
||||||
|
Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$json_array = $customer->jsonSerialize();
|
||||||
|
```
|
72
docs/company.md
Normal file
72
docs/company.md
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# Работа с компанией (продавцом)
|
||||||
|
|
||||||
|
Объект компании инициализируется следующим образом:
|
||||||
|
|
||||||
|
```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(
|
||||||
|
AtolOnline\Constants\SnoTypes::OSN, // тип СНО
|
||||||
|
'5544332219', // номер ИНН
|
||||||
|
'https://v4.online.atol.ru', // адрес места расчётов
|
||||||
|
'company@example.com' // email
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2 способ - через сеттеры
|
||||||
|
$company = (new AtolOnline\Entities\Company())
|
||||||
|
->setEmail('company@example.com')
|
||||||
|
->setInn('5544332219')
|
||||||
|
->setSno(AtolOnline\Constants\SnoTypes::USN_INCOME)
|
||||||
|
->setPaymentAddress('https://v4.online.atol.ru');
|
||||||
|
|
||||||
|
// либо комбинация этих способов
|
||||||
|
```
|
||||||
|
|
||||||
|
Метод `setEmail()` проверяет входную строку на длину (до 64 символов) и валидность формата email.
|
||||||
|
Выбрасывает исключения:
|
||||||
|
* `AtolEmailTooLongException` (если слишком длинный email);
|
||||||
|
* `AtolEmailValidateException` (если email невалиден).
|
||||||
|
|
||||||
|
Метод `setInn()` чистит входную строку от всех символов, кроме цифр, и проверяет длину (либо 10, либо 12 цифр).
|
||||||
|
Выбрасывает исключение `AtolInnWrongLengthException` (если длина строка ИНН некорректна).
|
||||||
|
|
||||||
|
Метод `setPaymentAddress()` проверяет длину (до 256 символов).
|
||||||
|
Выбрасывает исключение `AtolPaymentAddressTooLongException` (если слишком длинный адрес места расчётов).
|
||||||
|
|
||||||
|
Конструктор может выбрасывать любое из указанных выше исключений, если в него передаются параметры.
|
||||||
|
|
||||||
|
Получить установленные значения параметров можно через геттеры:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$company->getInn();
|
||||||
|
$company->getEmail();
|
||||||
|
$company->getPaymentAddress();
|
||||||
|
$company->getSno();
|
||||||
|
```
|
||||||
|
|
||||||
|
Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
echo $company;
|
||||||
|
$json_string = (string)$company;
|
||||||
|
```
|
||||||
|
|
||||||
|
Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$json_array = $company->jsonSerialize();
|
||||||
|
```
|
65
docs/correction_info.md
Normal file
65
docs/correction_info.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# Работа с данными коррекции
|
||||||
|
|
||||||
|
Объект для данных коррекции инициализируется следующим образом:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$info = new AtolOnline\Entities\CorrectionInfo();
|
||||||
|
```
|
||||||
|
|
||||||
|
У объекта должны быть указаны все следующие обязательные атрибуты:
|
||||||
|
* тип коррекции (тег ФФД 1173) - все типы перечислены в классе `AtolOnline\Constants\CorrectionTypes`;
|
||||||
|
* дата документа основания для коррекции в формате `d.m.Y` (тег ФФД 1178);
|
||||||
|
* номер документа основания для коррекции (тег ФФД 1179);
|
||||||
|
* описание коррекции (тег ФФД 1177).
|
||||||
|
|
||||||
|
Указать эти атрибуты можно двумя способами:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use AtolOnline\{Entities\CorrectionInfo, Constants\CorrectionTypes};
|
||||||
|
|
||||||
|
// 1 способ - через конструктор
|
||||||
|
$info = new CorrectionInfo(
|
||||||
|
CorrectionTypes::SELF, // тип коррекции
|
||||||
|
'01.01.2019', // дата документа коррекции
|
||||||
|
'12345', // номер документа коррекции
|
||||||
|
'test' // описание коррекции
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2 способ - через сеттеры
|
||||||
|
$info = (new CorrectionInfo())
|
||||||
|
->setType(CorrectionTypes::INSTRUCTION)
|
||||||
|
->setDate('01.01.2019')
|
||||||
|
->setName('test')
|
||||||
|
->setNumber('9999');
|
||||||
|
|
||||||
|
// либо комбинация этих способов
|
||||||
|
```
|
||||||
|
|
||||||
|
Получить установленные значения атрибутов можно через геттеры:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$info->getType();
|
||||||
|
$info->getDate();
|
||||||
|
$info->getName();
|
||||||
|
$info->getNumber();
|
||||||
|
```
|
||||||
|
|
||||||
|
Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
echo $customer;
|
||||||
|
$json_string = (string)$customer;
|
||||||
|
```
|
||||||
|
|
||||||
|
Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$json_array = $customer->jsonSerialize();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
159
docs/documents.md
Normal file
159
docs/documents.md
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
# Работа с документами
|
||||||
|
|
||||||
|
Объект документа инициализируется следующим образом:
|
||||||
|
|
||||||
|
```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()`.
|
||||||
|
|
||||||
|
Всё в рублях.
|
||||||
|
|
||||||
|
<a name='correction'></a>
|
||||||
|
## Работа с данными коррекции
|
||||||
|
|
||||||
|
Если документ создаётся с целью коррекции прихода или расхода, то он обязательно должен содержать [данные коррекции](/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();
|
||||||
|
```
|
194
docs/items.md
Normal file
194
docs/items.md
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
# Работа с предметами расчёта
|
||||||
|
|
||||||
|
## Один объект
|
||||||
|
|
||||||
|
Объект предмета расчёта инициализируется следующим образом:
|
||||||
|
|
||||||
|
```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();
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="array"></a>
|
||||||
|
## Массив объектов предметов расчёта
|
||||||
|
|
||||||
|
> Максимальное количество объектов в массиве - 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();
|
||||||
|
```
|
217
docs/kkt.md
Normal file
217
docs/kkt.md
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
# Работа с ККТ
|
||||||
|
|
||||||
|
Объект ККТ инициализируется следующим образом:
|
||||||
|
|
||||||
|
```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) уже указаны в коде библиотеки.
|
||||||
|
*Под тестовым режимом работы подразумевается использование этой тестовой ККТ.*
|
||||||
|
|
||||||
|
В библиотеке есть переключатель настроек ККТ.
|
||||||
|
С его помощью можете поменять вашу боевую ККТ на тестовую и наоборот.
|
||||||
|
Это можно сделать одним из следующих способов:
|
||||||
|
|
||||||
|
```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 и последствия ложится только на вас.
|
||||||
|
|
||||||
|
## Регистрация документа
|
||||||
|
|
||||||
|
Для регистрации документа **прихода** необходимо вызвать метод `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).
|
||||||
|
Тогда как для операций коррекции, которые описаны ниже, эти данные должны присутствовать.
|
||||||
|
|
||||||
|
Для регистрации документа **коррекции прихода** необходимо вызвать метод `sellRefund()`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$result = $kkt->sellCorrection($document);
|
||||||
|
```
|
||||||
|
|
||||||
|
Для регистрации документа **коррекции расхода** необходимо вызвать метод `buyRefund()`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$result = $kkt->buyCorrection($document);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Передача callback_url
|
||||||
|
|
||||||
|
Перед регистрацией документа можно указать `callback_url`.
|
||||||
|
АТОЛ отправит на указанный URL результат регистрации.
|
||||||
|
Вам необходимо расположить по этому адресу скрипт, обрабатывающий этот результат.
|
||||||
|
|
||||||
|
```php
|
||||||
|
$kkt->setCallbackUrl('http://example.com/process-kkt-result');
|
||||||
|
$kkt->getCallbackUrl();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Обработка результата регистрации
|
||||||
|
|
||||||
|
Методы `sell()`, `sellRefund()`, `sellCorrection()`, `buy()`, `buyRefund()` и `buyCorrection()` возвращают объект `AtolOnline\Api\KktResponse`.
|
||||||
|
|
||||||
|
Этот же объект можно получить через геттер `getLastResponse()`.
|
||||||
|
|
||||||
|
Этот объект содержит в себе HTTP-код ответа, массив заголовков и JSON-декодированные данные тела ответа.
|
||||||
|
|
||||||
|
```php
|
||||||
|
$result = $kkt->getLastResponse();
|
||||||
|
$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->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();
|
||||||
|
```
|
126
docs/payments.md
Normal file
126
docs/payments.md
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
# Работа с оплатами
|
||||||
|
|
||||||
|
## Один объект
|
||||||
|
|
||||||
|
Объект оплаты инициализируется следующим образом:
|
||||||
|
|
||||||
|
```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();
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="array"></a>
|
||||||
|
## Массив объектов оплат
|
||||||
|
|
||||||
|
> Максимальное количество объектов в массиве - 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();
|
||||||
|
```
|
14
docs/readme.md
Normal file
14
docs/readme.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Документация к библиотеке atol-online
|
||||||
|
|
||||||
|
Содержание:
|
||||||
|
1. [Работа с клиентами (покупателями)](client.md)
|
||||||
|
2. [Работа с компанией (продавцом)](company.md)
|
||||||
|
3. [Работа с оплатами](payments.md)
|
||||||
|
4. [Работа со ставками НДС](vats.md)
|
||||||
|
5. [Работа с предметами расчёта](items.md)
|
||||||
|
6. [Работа с документами](documents.md)
|
||||||
|
7. [Работа с ККТ](kkt.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Если вы нашли опечатку или какое-то несоответствие — делайте pull-request.
|
186
docs/vats.md
Normal file
186
docs/vats.md
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
# Работа со ставками НДС
|
||||||
|
|
||||||
|
## Один объект
|
||||||
|
|
||||||
|
Объект ставки НДС инициализируется следующим образом:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$vat = new AtolOnline\Entities\Vat();
|
||||||
|
```
|
||||||
|
|
||||||
|
У объекта ставки должны быть указаны все следующие атрибуты:
|
||||||
|
* тип ставки (теги ФФД: 1199 для предмета расчёта; 1105, 1104, 1103, 1102, 1107, 1106 для чека) - все типы перечислены в классе `AtolOnline\Constants\VatTypes` (по умолчанию `NONE`)
|
||||||
|
* размер налога (теги ФФД: 1200 для предмета расчёта; 1105, 1104, 1103, 1102, 1107, 1106 для чека)
|
||||||
|
|
||||||
|
> Все эти атрибуты являются **обязательными**.
|
||||||
|
|
||||||
|
Установить тип ставки НДС можно следующими способами:
|
||||||
|
|
||||||
|
```php
|
||||||
|
// 1 способ - через конструктор
|
||||||
|
$vat = new AtolOnline\Entities\Vat(
|
||||||
|
AtolOnline\Constants\VatTypes::VAT20 // тип ставки
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2 способ - через сеттер
|
||||||
|
$vat = (new AtolOnline\Entities\Vat())
|
||||||
|
->setType(AtolOnline\Constants\VatTypes::VAT20); // тип ставки
|
||||||
|
```
|
||||||
|
|
||||||
|
Размер налога высчитывается автоматически из общей суммы.
|
||||||
|
Сумму, от которой нужно расчитать размер налога, можно передать следующими способами:
|
||||||
|
|
||||||
|
```php
|
||||||
|
// 1 способ - через конструктор
|
||||||
|
$vat = new AtolOnline\Entities\Vat(
|
||||||
|
AtolOnline\Constants\VatTypes::VAT10, // тип ставки
|
||||||
|
1234.56 // общая сумма в рублях
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2 способ - через сеттер
|
||||||
|
$vat = (new AtolOnline\Entities\Vat())
|
||||||
|
->setType(AtolOnline\Constants\VatTypes::VAT10) // тип ставки
|
||||||
|
->setSum(150); // общая сумма в рублях
|
||||||
|
```
|
||||||
|
|
||||||
|
Сумму можно установить и до установки типа ставки.
|
||||||
|
Объект её запомнит и пересчитает итоговый размер налога при смене типа ставки:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$vat = (new AtolOnline\Entities\Vat())
|
||||||
|
->setSum(150) // общая сумма в рублях
|
||||||
|
->setType(AtolOnline\Constants\VatTypes::VAT10); // тип ставки
|
||||||
|
```
|
||||||
|
|
||||||
|
Получить установленную расчётную сумму в рублях можно через геттер `getSum()`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
var_dump($vat->getSum());
|
||||||
|
// double(150)
|
||||||
|
```
|
||||||
|
|
||||||
|
Получить расчитанный размер налога в рублях можно через геттер `getFinalSum()`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
var_dump($vat->getFinalSum());
|
||||||
|
// double(15): для примера выше это 10% от 150р = 15р
|
||||||
|
```
|
||||||
|
|
||||||
|
Общую сумму, из которой расчитывается размер налога, можно увеличить, используя метод `addSum()`.
|
||||||
|
Указанная в рублях сумма увеличится и итоговый размер налога пересчитается.
|
||||||
|
Для уменьшения суммы следует передать отрицательное число.
|
||||||
|
|
||||||
|
Разберём комплексный пример изменения типа ставки и расчётной суммы:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use AtolOnline\{Entities\Vat, Constants\VatTypes};
|
||||||
|
|
||||||
|
$vat = new Vat(VatTypes::VAT20, 120);
|
||||||
|
echo "НДС20 от 120р: ";
|
||||||
|
var_dump($vat->getFinalSum());
|
||||||
|
|
||||||
|
echo "НДС10 от 120р: ";
|
||||||
|
$vat->setType(VatTypes::VAT10);
|
||||||
|
var_dump($vat->getFinalSum());
|
||||||
|
|
||||||
|
$vat->addSum(40);
|
||||||
|
echo "НДС10 от {$vat->getSum()}р: ";
|
||||||
|
var_dump($vat->getFinalSum());
|
||||||
|
|
||||||
|
$vat->setType(VatTypes::VAT20)->addSum(-20);
|
||||||
|
echo "НДС20 от {$vat->getSum()}р: ";
|
||||||
|
var_dump($vat->getFinalSum());
|
||||||
|
|
||||||
|
$vat->setType(VatTypes::VAT120);
|
||||||
|
echo "НДС20/120 от {$vat->getSum()}р: ";
|
||||||
|
var_dump($vat->getFinalSum());
|
||||||
|
```
|
||||||
|
|
||||||
|
Результат будет следующим:
|
||||||
|
|
||||||
|
```
|
||||||
|
НДС20 от 120р:
|
||||||
|
double(24)
|
||||||
|
НДС10 от 120р:
|
||||||
|
double(12)
|
||||||
|
НДС10 от 160р:
|
||||||
|
double(16)
|
||||||
|
НДС20 от 140р:
|
||||||
|
double(28)
|
||||||
|
НДС20/120 от 140р:
|
||||||
|
double(23.33)
|
||||||
|
```
|
||||||
|
|
||||||
|
Объект класса приводится к JSON-строке автоматически или принудительным приведением к `string`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
echo $vat;
|
||||||
|
$json_string = (string)$vat;
|
||||||
|
```
|
||||||
|
|
||||||
|
Чтобы получить те же данные в виде массива, нужно вызвать метод `jsonSerialize()`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$json_array = $vat->jsonSerialize();
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="array"></a>
|
||||||
|
## Массив объектов ставок НДС
|
||||||
|
|
||||||
|
> Максимальное количество в массиве - 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();
|
||||||
|
```
|
25
phpunit.xml
Normal file
25
phpunit.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
|
||||||
|
backupGlobals="false"
|
||||||
|
backupStaticAttributes="false"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
colors="true"
|
||||||
|
convertErrorsToExceptions="true"
|
||||||
|
convertNoticesToExceptions="true"
|
||||||
|
convertWarningsToExceptions="true"
|
||||||
|
processIsolation="false"
|
||||||
|
stopOnFailure="false">
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Unit">
|
||||||
|
<file>ClientTest.php</file>
|
||||||
|
<file>CompanyTest.php</file>
|
||||||
|
<file>VatTest.php</file>
|
||||||
|
<directory suffix="Test.php">./tests/Unit</directory>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="Feature">
|
||||||
|
<file>ItemTest.php</file>
|
||||||
|
<directory suffix="Test.php">./tests/Feature</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
</phpunit>
|
500
src/AtolOnline/Api/Kkt.php
Normal file
500
src/AtolOnline/Api/Kkt.php
Normal file
@ -0,0 +1,500 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Api;
|
||||||
|
|
||||||
|
use AtolOnline\{Entities\Document,
|
||||||
|
Exceptions\AtolCorrectionInfoException,
|
||||||
|
Exceptions\AtolKktLoginEmptyException,
|
||||||
|
Exceptions\AtolKktLoginTooLongException,
|
||||||
|
Exceptions\AtolKktPasswordEmptyException,
|
||||||
|
Exceptions\AtolUuidValidateException,
|
||||||
|
Exceptions\AtolWrongDocumentTypeException
|
||||||
|
};
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use Ramsey\Uuid\Uuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс для отправки запросов на ККТ
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Api
|
||||||
|
*/
|
||||||
|
class Kkt extends Client
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var bool Флаг тестового режима работы
|
||||||
|
*/
|
||||||
|
protected $is_test_mode = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Настройки доступа к ККТ
|
||||||
|
*/
|
||||||
|
protected $kkt_config = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \AtolOnline\Api\KktResponse|null Последний ответ сервера АТОЛ
|
||||||
|
*/
|
||||||
|
protected $last_response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|null Токен авторизации
|
||||||
|
*/
|
||||||
|
private $auth_token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kkt constructor.
|
||||||
|
*
|
||||||
|
* @param string|null $group
|
||||||
|
* @param string|null $login
|
||||||
|
* @param string|null $pass
|
||||||
|
* @param bool $test_mode Флаг тестового режима
|
||||||
|
* @param array $guzzle_config Конфигурация GuzzleHttp
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolKktLoginEmptyException Логин ККТ не может быть пустым
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolKktLoginTooLongException Слишком длинный логин ККТ
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolKktPasswordEmptyException Пароль ККТ не может быть пустым
|
||||||
|
* @see https://guzzle.readthedocs.io/en/latest/request-options.html
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
?string $group = null,
|
||||||
|
?string $login = null,
|
||||||
|
?string $pass = null,
|
||||||
|
bool $test_mode = false,
|
||||||
|
array $guzzle_config = []
|
||||||
|
) {
|
||||||
|
$this->resetKktConfig();
|
||||||
|
if ($group) {
|
||||||
|
$this->setGroup($group);
|
||||||
|
}
|
||||||
|
if ($login) {
|
||||||
|
$this->setLogin($login);
|
||||||
|
}
|
||||||
|
if ($login) {
|
||||||
|
$this->setPassword($pass);
|
||||||
|
}
|
||||||
|
$this->setTestMode($test_mode);
|
||||||
|
$guzzle_config['base_uri'] = $this->getEndpoint();
|
||||||
|
$guzzle_config['http_errors'] = $guzzle_config['http_errors'] ?? false;
|
||||||
|
parent::__construct($guzzle_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает группу доступа к ККТ
|
||||||
|
*
|
||||||
|
* @param string $group
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setGroup(string $group)
|
||||||
|
{
|
||||||
|
$this->kkt_config['prod']['group'] = $group;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает группу доступа к ККТ в соответствии с флагом тестового режима
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getGroup(): string
|
||||||
|
{
|
||||||
|
return $this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['group'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает логин доступа к ККТ
|
||||||
|
*
|
||||||
|
* @param string $login
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolKktLoginEmptyException Логин ККТ не может быть пустым
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolKktLoginTooLongException Слишком длинный логин ККТ
|
||||||
|
*/
|
||||||
|
public function setLogin(string $login)
|
||||||
|
{
|
||||||
|
if (empty($login)) {
|
||||||
|
throw new AtolKktLoginEmptyException();
|
||||||
|
} elseif (strlen($login) > 100) {
|
||||||
|
throw new AtolKktLoginTooLongException($login, 100);
|
||||||
|
}
|
||||||
|
$this->kkt_config['prod']['login'] = $login;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает логин доступа к ККТ в соответствии с флагом тестового режима
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLogin(): string
|
||||||
|
{
|
||||||
|
return $this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['login'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает пароль доступа к ККТ
|
||||||
|
*
|
||||||
|
* @param string $password
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolKktPasswordEmptyException Пароль ККТ не может быть пустым
|
||||||
|
*/
|
||||||
|
public function setPassword(string $password)
|
||||||
|
{
|
||||||
|
if (empty($password)) {
|
||||||
|
throw new AtolKktPasswordEmptyException();
|
||||||
|
}
|
||||||
|
$this->kkt_config['prod']['pass'] = $password;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает логин ККТ в соответствии с флагом тестового режима
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPassword(): string
|
||||||
|
{
|
||||||
|
return $this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['pass'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает URL для приёма колбеков
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCallbackUrl(string $url)
|
||||||
|
{
|
||||||
|
$this->kkt_config['prod']['callback_url'] = $url;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает URL для приёма колбеков
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCallbackUrl(): string
|
||||||
|
{
|
||||||
|
return $this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['callback_url'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает последний ответ сервера
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getLastResponse()
|
||||||
|
{
|
||||||
|
return $this->last_response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает флаг тестового режима
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isTestMode(): bool
|
||||||
|
{
|
||||||
|
return $this->is_test_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает флаг тестового режима
|
||||||
|
*
|
||||||
|
* @param bool $test_mode
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setTestMode(bool $test_mode = true)
|
||||||
|
{
|
||||||
|
$this->is_test_mode = $test_mode;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Регистрирует документ прихода
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Document $document
|
||||||
|
* @return \AtolOnline\Api\KktResponse
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
|
||||||
|
*/
|
||||||
|
public function sell(Document $document)
|
||||||
|
{
|
||||||
|
if ($document->getCorrectionInfo()) {
|
||||||
|
throw new AtolCorrectionInfoException('В документе есть данные коррекции');
|
||||||
|
}
|
||||||
|
return $this->registerDocument('sell', 'receipt', $document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Регистрирует документ возврата прихода
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Document $document
|
||||||
|
* @return \AtolOnline\Api\KktResponse
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException Слишком большая сумма
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
|
||||||
|
*/
|
||||||
|
public function sellRefund(Document $document)
|
||||||
|
{
|
||||||
|
if ($document->getCorrectionInfo()) {
|
||||||
|
throw new AtolCorrectionInfoException('В документе есть данные коррекции');
|
||||||
|
}
|
||||||
|
return $this->registerDocument('sell_refund', 'receipt', $document->clearVats());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Регистрирует документ коррекции прихода
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Document $document
|
||||||
|
* @return \AtolOnline\Api\KktResponse
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе отсутствуют данные коррекции
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||||
|
*/
|
||||||
|
public function sellCorrection(Document $document)
|
||||||
|
{
|
||||||
|
if (!$document->getCorrectionInfo()) {
|
||||||
|
throw new AtolCorrectionInfoException();
|
||||||
|
}
|
||||||
|
$document->setClient(null)->setItems([]);
|
||||||
|
return $this->registerDocument('sell_correction', 'correction', $document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Регистрирует документ расхода
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Document $document
|
||||||
|
* @return \AtolOnline\Api\KktResponse
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
|
||||||
|
*/
|
||||||
|
public function buy(Document $document)
|
||||||
|
{
|
||||||
|
if ($document->getCorrectionInfo()) {
|
||||||
|
throw new AtolCorrectionInfoException('В документе есть данные коррекции');
|
||||||
|
}
|
||||||
|
return $this->registerDocument('buy', 'receipt', $document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Регистрирует документ возврата расхода
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Document $document
|
||||||
|
* @return \AtolOnline\Api\KktResponse
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException Слишком большая сумма
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
|
||||||
|
*/
|
||||||
|
public function buyRefund(Document $document)
|
||||||
|
{
|
||||||
|
if ($document->getCorrectionInfo()) {
|
||||||
|
throw new AtolCorrectionInfoException('В документе есть данные коррекции');
|
||||||
|
}
|
||||||
|
return $this->registerDocument('buy_refund', 'receipt', $document->clearVats());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Регистрирует документ коррекции расхода
|
||||||
|
*
|
||||||
|
* @param Document $document
|
||||||
|
* @return \AtolOnline\Api\KktResponse
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе отсутствуют данные коррекции
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||||
|
*/
|
||||||
|
public function buyCorrection(Document $document)
|
||||||
|
{
|
||||||
|
if (!$document->getCorrectionInfo()) {
|
||||||
|
throw new AtolCorrectionInfoException();
|
||||||
|
}
|
||||||
|
$document->setClient(null)->setItems([]);
|
||||||
|
return $this->registerDocument('buy_correction', 'correction', $document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверяет статус чека на ККТ один раз
|
||||||
|
*
|
||||||
|
* @param string $uuid UUID регистрации
|
||||||
|
* @return \AtolOnline\Api\KktResponse
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolUuidValidateException Некорректный UUID документа
|
||||||
|
*/
|
||||||
|
public function getDocumentStatus(string $uuid)
|
||||||
|
{
|
||||||
|
$uuid = trim($uuid);
|
||||||
|
if (!Uuid::isValid($uuid)) {
|
||||||
|
throw new AtolUuidValidateException($uuid);
|
||||||
|
}
|
||||||
|
$this->auth();
|
||||||
|
return $this->sendAtolRequest('GET', 'report/'.$uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверяет статус чека на ККТ нужное количество раз с указанным интервалом.
|
||||||
|
* Вернёт результат как только при очередной проверке сменится статус регистрации документа.
|
||||||
|
*
|
||||||
|
* @param string $uuid UUID регистрации
|
||||||
|
* @param int $retry_count Количество попыток
|
||||||
|
* @param int $timeout Таймаут в секундах между попытками
|
||||||
|
* @return \AtolOnline\Api\KktResponse
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolException Некорректный UUID документа
|
||||||
|
*/
|
||||||
|
public function pollDocumentStatus(string $uuid, int $retry_count = 5, int $timeout = 1)
|
||||||
|
{
|
||||||
|
$try = 0;
|
||||||
|
do {
|
||||||
|
$response = $this->getDocumentStatus($uuid);
|
||||||
|
if ($response->isValid() && $response->getContent()->status == 'done') {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
sleep($timeout);
|
||||||
|
}
|
||||||
|
++$try;
|
||||||
|
} while ($try < $retry_count);
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Сбрасывает настройки ККТ по умолчанию
|
||||||
|
*/
|
||||||
|
protected function resetKktConfig(): void
|
||||||
|
{
|
||||||
|
$this->kkt_config['prod']['group'] = '';
|
||||||
|
$this->kkt_config['prod']['login'] = '';
|
||||||
|
$this->kkt_config['prod']['pass'] = '';
|
||||||
|
$this->kkt_config['prod']['url'] = 'https://online.atol.ru/possystem/v4';
|
||||||
|
$this->kkt_config['prod']['callback_url'] = '';
|
||||||
|
|
||||||
|
$this->kkt_config['test']['group'] = 'v4-online-atol-ru_4179';
|
||||||
|
$this->kkt_config['test']['login'] = 'v4-online-atol-ru';
|
||||||
|
$this->kkt_config['test']['pass'] = 'iGFFuihss';
|
||||||
|
$this->kkt_config['test']['url'] = 'https://testonline.atol.ru/possystem/v4';
|
||||||
|
$this->kkt_config['test']['callback_url'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает набор заголовков для HTTP-запроса
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getHeaders()
|
||||||
|
{
|
||||||
|
$headers['Content-type'] = 'application/json; charset=utf-8';
|
||||||
|
if ($this->getAuthToken()) {
|
||||||
|
$headers['Token'] = $this->auth_token;
|
||||||
|
}
|
||||||
|
return $headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает адрес сервера в соответствии с флагом тестового режима
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getEndpoint(): string
|
||||||
|
{
|
||||||
|
return $this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['url'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает полный URL до метода API
|
||||||
|
*
|
||||||
|
* @param string $to_method
|
||||||
|
* @param array|null $get_parameters
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function makeUrl(string $to_method, array $get_parameters = null)
|
||||||
|
{
|
||||||
|
$url = $this->getEndpoint().($this->getAuthToken() ? '/'.$this->getGroup() : '').'/'.$to_method;
|
||||||
|
if ($get_parameters && is_array($get_parameters)) {
|
||||||
|
$url .= '?'.http_build_query($get_parameters);
|
||||||
|
}
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Делает запрос, возвращает декодированный ответ
|
||||||
|
*
|
||||||
|
* @param string $http_method Метод HTTP (GET, POST и пр)
|
||||||
|
* @param string $api_method Метод API
|
||||||
|
* @param mixed $data Данные для передачи
|
||||||
|
* @param array|null $options Параметры Guzzle
|
||||||
|
* @return \AtolOnline\Api\KktResponse
|
||||||
|
* @see https://guzzle.readthedocs.io/en/latest/request-options.html
|
||||||
|
*/
|
||||||
|
protected function sendAtolRequest(string $http_method, string $api_method, $data = null, array $options = null)
|
||||||
|
{
|
||||||
|
$http_method = strtoupper($http_method);
|
||||||
|
$options['headers'] = $this->getHeaders();
|
||||||
|
$url = $http_method == 'GET'
|
||||||
|
? $this->makeUrl($api_method, $data)
|
||||||
|
: $this->makeUrl($api_method, ['token' => $this->getAuthToken()]);
|
||||||
|
if ($http_method != 'GET') {
|
||||||
|
$options['json'] = $data;
|
||||||
|
}
|
||||||
|
$response = $this->request($http_method, $url, $options);
|
||||||
|
return $this->last_response = new KktResponse($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Производит авторизацию на ККТ и получает токен доступа для дальнейших HTTP-запросов
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function auth()
|
||||||
|
{
|
||||||
|
if (!$this->getAuthToken()) {
|
||||||
|
$result = $this->sendAtolRequest('GET', 'getToken', [
|
||||||
|
'login' => $this->getLogin(),
|
||||||
|
'pass' => $this->getPassword(),
|
||||||
|
]);
|
||||||
|
if (!$result->isValid() || !$result->getContent()->token) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->auth_token = $result->getContent()->token;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Отправляет документ на регистрацию
|
||||||
|
*
|
||||||
|
* @param string $api_method Метод API
|
||||||
|
* @param string $type Тип документа: receipt, correction
|
||||||
|
* @param \AtolOnline\Entities\Document $document Объект документа
|
||||||
|
* @return \AtolOnline\Api\KktResponse
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
protected function registerDocument(string $api_method, string $type, Document $document)
|
||||||
|
{
|
||||||
|
$type = trim($type);
|
||||||
|
if (!in_array($type, ['receipt', 'correction'])) {
|
||||||
|
throw new AtolWrongDocumentTypeException($type);
|
||||||
|
}
|
||||||
|
$this->auth();
|
||||||
|
$data = [
|
||||||
|
'timestamp' => date('d.m.y H:i:s'),
|
||||||
|
'external_id' => Uuid::uuid4()->toString(),
|
||||||
|
'service' => ['callback_url' => $this->getCallbackUrl()],
|
||||||
|
$type => $document,
|
||||||
|
];
|
||||||
|
return $this->sendAtolRequest('POST', trim($api_method), $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает текущий токен авторизации
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getAuthToken()
|
||||||
|
{
|
||||||
|
return $this->auth_token;
|
||||||
|
}
|
||||||
|
}
|
123
src/AtolOnline/Api/KktResponse.php
Normal file
123
src/AtolOnline/Api/KktResponse.php
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Api;
|
||||||
|
|
||||||
|
use JsonSerializable;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс AtolResponse, описывающий ответ от ККТ
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Api
|
||||||
|
*/
|
||||||
|
class KktResponse implements JsonSerializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int Код ответа сервера
|
||||||
|
*/
|
||||||
|
protected $code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \stdClass Содержимое ответа сервера
|
||||||
|
*/
|
||||||
|
protected $content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Заголовки ответа
|
||||||
|
*/
|
||||||
|
protected $headers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AtolResponse constructor.
|
||||||
|
*
|
||||||
|
* @param \Psr\Http\Message\ResponseInterface $response
|
||||||
|
*/
|
||||||
|
public function __construct(ResponseInterface $response)
|
||||||
|
{
|
||||||
|
$this->code = $response->getStatusCode();
|
||||||
|
$this->headers = $response->getHeaders();
|
||||||
|
$this->content = json_decode($response->getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает заголовки ответа
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getHeaders(): array
|
||||||
|
{
|
||||||
|
return $this->headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает запрошенный параметр из декодированного объекта результата
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function __get($name)
|
||||||
|
{
|
||||||
|
return $this->getContent()->$name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает код ответа
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getCode(): int
|
||||||
|
{
|
||||||
|
return $this->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает объект результата запроса
|
||||||
|
*
|
||||||
|
* @return \stdClass
|
||||||
|
*/
|
||||||
|
public function getContent(): stdClass
|
||||||
|
{
|
||||||
|
return $this->content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверяет успешность запроса по соержимому результата
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isValid()
|
||||||
|
{
|
||||||
|
return !empty($this->getCode())
|
||||||
|
&& !empty($this->getContent())
|
||||||
|
&& empty($this->getContent()->error)
|
||||||
|
&& (int)$this->getCode() < 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает текстовое представление
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return json_encode($this->jsonSerialize(), JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'code' => $this->code,
|
||||||
|
'headers' => $this->headers,
|
||||||
|
'body' => $this->content,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
28
src/AtolOnline/Constants/CorrectionTypes.php
Normal file
28
src/AtolOnline/Constants/CorrectionTypes.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Константы, определяющие типы документов коррекции
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Constants
|
||||||
|
*/
|
||||||
|
class CorrectionTypes
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Самостоятельно
|
||||||
|
*/
|
||||||
|
const SELF = 'self';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* По предписанию
|
||||||
|
*/
|
||||||
|
const INSTRUCTION = 'instruction';
|
||||||
|
}
|
54
src/AtolOnline/Constants/PaymentMethods.php
Normal file
54
src/AtolOnline/Constants/PaymentMethods.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Константы, определяющие признаки способов расчёта. Тег ФФД - 1214.
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Constants
|
||||||
|
*/
|
||||||
|
class PaymentMethods
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Предоплата 100% до передачи предмета расчёта
|
||||||
|
*/
|
||||||
|
const FULL_PREPAYMENT = 'full_prepayment';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Частичная предоплата до передачи предмета расчёта
|
||||||
|
*/
|
||||||
|
const PREPAYMENT = 'prepayment';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Аванс
|
||||||
|
*/
|
||||||
|
const ADVANCE = 'advance';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Полная оплата с учётом аванса/предоплаты в момент передачи предмета расчёта
|
||||||
|
*/
|
||||||
|
const FULL_PAYMENT = 'full_payment';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Частичный расчёт в момент передачи предмета расчёта (дальнейшая оплата в кредит)
|
||||||
|
*/
|
||||||
|
const PARTIAL_PAYMENT = 'partial_payment';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Передача предмета расчёта в кредит
|
||||||
|
*/
|
||||||
|
const CREDIT = 'credit';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Оплата кредита
|
||||||
|
*/
|
||||||
|
const CREDIT_PAYMENT = 'credit_payment';
|
||||||
|
|
||||||
|
}
|
108
src/AtolOnline/Constants/PaymentObjects.php
Normal file
108
src/AtolOnline/Constants/PaymentObjects.php
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Константы, определяющие признаки предметов расчёта. Тег ФФД - 1212.
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Constants
|
||||||
|
*/
|
||||||
|
class PaymentObjects
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Товар, кроме подакцизного
|
||||||
|
*/
|
||||||
|
const COMMODITY = 'commodity';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Товар подакцизный
|
||||||
|
*/
|
||||||
|
const EXCISE = 'excise';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Работа
|
||||||
|
*/
|
||||||
|
const JOB = 'job';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Услуга
|
||||||
|
*/
|
||||||
|
const SERVICE = 'service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ставка азартной игры
|
||||||
|
*/
|
||||||
|
const GAMBLING_BET = 'gambling_bet';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Выигрыш азартной игры
|
||||||
|
*/
|
||||||
|
const GAMBLING_PRIZE = 'gambling_prize';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Лотерея
|
||||||
|
*/
|
||||||
|
const LOTTERY = 'lottery';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Выигрыш лотереи
|
||||||
|
*/
|
||||||
|
const LOTTERY_PRIZE = 'lottery_prize';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Предоставление результатов интеллектуальной деятельности
|
||||||
|
*/
|
||||||
|
const INTELLECTUAL_ACTIVITY = 'intellectual_activity';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Платёж (задаток, кредит, аванс, предоплата, пеня, штраф, бонус и пр.)
|
||||||
|
*/
|
||||||
|
const PAYMENT = 'payment';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Агентское вознаграждение
|
||||||
|
*/
|
||||||
|
const AGENT_COMMISSION = 'agent_commission';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Составной предмет расчёта
|
||||||
|
*/
|
||||||
|
const COMPOSITE = 'composite';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Другой предмет расчёта
|
||||||
|
*/
|
||||||
|
const ANOTHER = 'another';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Имущественное право
|
||||||
|
*/
|
||||||
|
const PROPERTY_RIGHT = 'property_right';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Внереализационный доход
|
||||||
|
*/
|
||||||
|
const NON_OPERATING_GAIN = 'non-operating_gain';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Страховые взносы
|
||||||
|
*/
|
||||||
|
const INSURANCE_PREMIUM = 'insurance_premium';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Торговый сбор
|
||||||
|
*/
|
||||||
|
const SALES_TAX = 'sales_tax';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Курортный сбор
|
||||||
|
*/
|
||||||
|
const RESORT_FEE = 'resort_fee';
|
||||||
|
}
|
53
src/AtolOnline/Constants/PaymentTypes.php
Normal file
53
src/AtolOnline/Constants/PaymentTypes.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Константы, определяющие виды оплат. Тег ФФД - 1031, 1081, 1215, 1216, 1217.
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Constants
|
||||||
|
*/
|
||||||
|
class PaymentTypes
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Расчёт наличными. Тег ФФД - 1031.
|
||||||
|
*/
|
||||||
|
const CASH = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Расчёт безналичными. Тег ФФД - 1081.
|
||||||
|
*/
|
||||||
|
const ELECTRON = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Предварительная оплата (зачет аванса). Тег ФФД - 1215.
|
||||||
|
*/
|
||||||
|
const PRE_PAID = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Предварительная оплата (кредит). Тег ФФД - 1216.
|
||||||
|
*/
|
||||||
|
const CREDIT = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Иная форма оплаты (встречное предоставление). Тег ФФД - 1217.
|
||||||
|
*/
|
||||||
|
const OTHER = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Расширенный типы оплаты
|
||||||
|
* Для каждого фискального типа оплаты можно указать расширенный тип оплаты
|
||||||
|
*/
|
||||||
|
const ADD_5 = 5;
|
||||||
|
const ADD_6 = 6;
|
||||||
|
const ADD_7 = 7;
|
||||||
|
const ADD_8 = 8;
|
||||||
|
const ADD_9 = 9;
|
||||||
|
}
|
48
src/AtolOnline/Constants/ReceiptOperationTypes.php
Normal file
48
src/AtolOnline/Constants/ReceiptOperationTypes.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Константы, определяющие типы операций (чеков)
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Constants
|
||||||
|
*/
|
||||||
|
class ReceiptOperationTypes
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Приход (мы продали)
|
||||||
|
*/
|
||||||
|
const SELL = 'sell';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возврат прихода (нам вернули предмет расчёта, мы вернули деньги)
|
||||||
|
*/
|
||||||
|
const SELL_REFUND = 'sell_refund';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Коррекция прихода
|
||||||
|
*/
|
||||||
|
const SELL_CORRECTION = 'sell_correction';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Расход (мы купили)
|
||||||
|
*/
|
||||||
|
const BUY = 'buy';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возврат расхода (мы вернули предмет расчёта, нам вернули деньги)
|
||||||
|
*/
|
||||||
|
const BUY_REFUND = 'buy_refund';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Коррекция прихода
|
||||||
|
*/
|
||||||
|
const BUY_CORRECTION = 'buy_correction';
|
||||||
|
}
|
48
src/AtolOnline/Constants/SnoTypes.php
Normal file
48
src/AtolOnline/Constants/SnoTypes.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Константы, определяющие типы налогообложения
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Constants
|
||||||
|
*/
|
||||||
|
class SnoTypes
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Общая СН
|
||||||
|
*/
|
||||||
|
const OSN = 'osn';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Упрощенная СН (доходы)
|
||||||
|
*/
|
||||||
|
const USN_INCOME = 'usn_income';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Упрощенная СН (доходы минус расходы)
|
||||||
|
*/
|
||||||
|
const USN_INCOME_OUTCOME = 'usn_income_outcome';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Единый налог на вмененный доход
|
||||||
|
*/
|
||||||
|
const ENDV = 'envd';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Единый сельскохозяйственный налог
|
||||||
|
*/
|
||||||
|
const ESN = 'esn';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Патентная СН
|
||||||
|
*/
|
||||||
|
const PATENT = 'patent';
|
||||||
|
}
|
58
src/AtolOnline/Constants/VatTypes.php
Normal file
58
src/AtolOnline/Constants/VatTypes.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Константы, определяющие типы ставок НДС
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Constants
|
||||||
|
*/
|
||||||
|
class VatTypes
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Без НДС
|
||||||
|
*/
|
||||||
|
const NONE = 'none';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* НДС 0%
|
||||||
|
*/
|
||||||
|
const VAT0 = 'vat0';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* НДС 10%
|
||||||
|
*/
|
||||||
|
const VAT10 = 'vat10';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* НДС 18%
|
||||||
|
*/
|
||||||
|
const VAT18 = 'vat18';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* НДС 20%
|
||||||
|
*/
|
||||||
|
const VAT20 = 'vat20';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* НДС 10/110%
|
||||||
|
*/
|
||||||
|
const VAT110 = 'vat110';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* НДС 18/118%
|
||||||
|
*/
|
||||||
|
const VAT118 = 'vat118';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* НДС 20/120%
|
||||||
|
*/
|
||||||
|
const VAT120 = 'vat120';
|
||||||
|
}
|
28
src/AtolOnline/Entities/AtolEntity.php
Normal file
28
src/AtolOnline/Entities/AtolEntity.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
use JsonSerializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Абстрактное описание любой сущности, представляемой как JSON
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
abstract class AtolEntity implements JsonSerializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return json_encode($this->jsonSerialize(), JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
|
}
|
149
src/AtolOnline/Entities/Client.php
Normal file
149
src/AtolOnline/Entities/Client.php
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
use AtolOnline\{Exceptions\AtolNameTooLongException, Exceptions\AtolPhoneTooLongException, Traits\HasEmail, Traits\HasInn};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс Client, описывающий сущность покупателя
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
class Client extends AtolEntity
|
||||||
|
{
|
||||||
|
use
|
||||||
|
/**
|
||||||
|
* Покупатель может иметь почту. Тег ФФД - 1008.
|
||||||
|
*/
|
||||||
|
HasEmail,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Покупатель может иметь ИНН. Тег ФФД - 1228.
|
||||||
|
*/
|
||||||
|
HasInn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Телефон покупателя. Тег ФФД - 1008.
|
||||||
|
*/
|
||||||
|
protected $phone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Имя покупателя. Тег ФФД - 1227.
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client constructor.
|
||||||
|
*
|
||||||
|
* @param string|null $name Наименование
|
||||||
|
* @param string|null $phone Телефон
|
||||||
|
* @param string|null $email Email
|
||||||
|
* @param string|null $inn ИНН
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
|
||||||
|
*/
|
||||||
|
public function __construct(?string $name = null, ?string $phone = null, ?string $email = null, ?string $inn = null)
|
||||||
|
{
|
||||||
|
if ($name) {
|
||||||
|
$this->setName($name);
|
||||||
|
}
|
||||||
|
if ($email) {
|
||||||
|
$this->setEmail($email);
|
||||||
|
}
|
||||||
|
if ($phone) {
|
||||||
|
$this->setPhone($phone);
|
||||||
|
}
|
||||||
|
if ($inn) {
|
||||||
|
$this->setInn($inn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает имя покупателя. Тег ФФД - 1227.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает имя покупателя
|
||||||
|
* Тег ФФД - 1227.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolNameTooLongException
|
||||||
|
*/
|
||||||
|
public function setName(string $name)
|
||||||
|
{
|
||||||
|
$name = trim($name);
|
||||||
|
if (strlen($name) > 256) {
|
||||||
|
throw new AtolNameTooLongException($name, 256);
|
||||||
|
}
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает телефон покупателя.
|
||||||
|
* Тег ФФД - 1008.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPhone()
|
||||||
|
{
|
||||||
|
return $this->phone ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает телефон покупателя.
|
||||||
|
* Тег ФФД - 1008.
|
||||||
|
* Входная строка лишается всех знаков, кроме цифр и знака '+'.
|
||||||
|
*
|
||||||
|
* @param string $phone
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolPhoneTooLongException
|
||||||
|
*/
|
||||||
|
public function setPhone(string $phone)
|
||||||
|
{
|
||||||
|
$phone = preg_replace("/[^0-9+]/", '', $phone);
|
||||||
|
if (strlen($phone) > 64) {
|
||||||
|
throw new AtolPhoneTooLongException($phone, 64);
|
||||||
|
}
|
||||||
|
$this->phone = $phone;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
$json = [];
|
||||||
|
if ($this->getName()) {
|
||||||
|
$json['name'] = $this->getName() ?? '';
|
||||||
|
}
|
||||||
|
if ($this->getEmail()) {
|
||||||
|
$json['email'] = $this->getEmail() ?? '';
|
||||||
|
}
|
||||||
|
if ($this->getPhone()) {
|
||||||
|
$json['phone'] = $this->getPhone() ?? '';
|
||||||
|
}
|
||||||
|
if ($this->getInn()) {
|
||||||
|
$json['inn'] = $this->getInn() ?? '';
|
||||||
|
}
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
}
|
137
src/AtolOnline/Entities/Company.php
Normal file
137
src/AtolOnline/Entities/Company.php
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
use AtolOnline\{Exceptions\AtolEmailTooLongException,
|
||||||
|
Exceptions\AtolEmailValidateException,
|
||||||
|
Exceptions\AtolInnWrongLengthException,
|
||||||
|
Exceptions\AtolPaymentAddressTooLongException,
|
||||||
|
Traits\HasEmail,
|
||||||
|
Traits\HasInn
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс, описывающий сущность компании-продавца
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
class Company extends AtolEntity
|
||||||
|
{
|
||||||
|
use
|
||||||
|
/**
|
||||||
|
* Продавец должен иметь почту. Тег ФФД - 1117.
|
||||||
|
*/
|
||||||
|
HasEmail,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Продавец должен иметь ИНН. Тег ФФД - 1018.
|
||||||
|
*/
|
||||||
|
HasInn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Система налогообложения продавца. Тег ФФД - 1055.
|
||||||
|
*/
|
||||||
|
protected $sno;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Место расчётов (адрес интернет-магазина). Тег ФФД - 1187.
|
||||||
|
*/
|
||||||
|
protected $payment_address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Company constructor.
|
||||||
|
*
|
||||||
|
* @param string|null $sno
|
||||||
|
* @param string|null $inn
|
||||||
|
* @param string|null $paymentAddress
|
||||||
|
* @param string|null $email
|
||||||
|
* @throws AtolEmailTooLongException
|
||||||
|
* @throws AtolEmailValidateException
|
||||||
|
* @throws AtolInnWrongLengthException
|
||||||
|
* @throws AtolPaymentAddressTooLongException
|
||||||
|
*/
|
||||||
|
public function __construct(string $sno = null, string $inn = null, string $paymentAddress = null, string $email = null)
|
||||||
|
{
|
||||||
|
if ($sno) {
|
||||||
|
$this->setSno($sno);
|
||||||
|
}
|
||||||
|
if ($inn) {
|
||||||
|
$this->setInn($inn);
|
||||||
|
}
|
||||||
|
if ($paymentAddress) {
|
||||||
|
$this->setPaymentAddress($paymentAddress);
|
||||||
|
}
|
||||||
|
if ($email) {
|
||||||
|
$this->setEmail($email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает установленный тип налогообложения. Тег ФФД - 1055.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSno()
|
||||||
|
{
|
||||||
|
return $this->sno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает тип налогообложения. Тег ФФД - 1055.
|
||||||
|
*
|
||||||
|
* @param string $sno
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setSno(string $sno)
|
||||||
|
{
|
||||||
|
$this->sno = trim($sno);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает установленный адрес места расчётов. Тег ФФД - 1187.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPaymentAddress()
|
||||||
|
{
|
||||||
|
return $this->payment_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает адрес места расчётов. Тег ФФД - 1187.
|
||||||
|
*
|
||||||
|
* @param string $payment_address
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolPaymentAddressTooLongException
|
||||||
|
*/
|
||||||
|
public function setPaymentAddress(string $payment_address)
|
||||||
|
{
|
||||||
|
$payment_address = trim($payment_address);
|
||||||
|
if (strlen($payment_address) > 256) {
|
||||||
|
throw new AtolPaymentAddressTooLongException($payment_address, 256);
|
||||||
|
}
|
||||||
|
$this->payment_address = $payment_address;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email' => $this->getEmail(),
|
||||||
|
'sno' => $this->getSno(),
|
||||||
|
'inn' => $this->getInn(),
|
||||||
|
'payment_address' => $this->getPaymentAddress(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
171
src/AtolOnline/Entities/CorrectionInfo.php
Normal file
171
src/AtolOnline/Entities/CorrectionInfo.php
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс CorrectionInfo, описывающий данные коррекции
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
class CorrectionInfo extends AtolEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int Тип коррекции. Тег ФФД - 1173.
|
||||||
|
*/
|
||||||
|
protected $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Дата документа основания для коррекции. Тег ФФД - 1178.
|
||||||
|
*/
|
||||||
|
protected $base_date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Номер документа основания для коррекции. Тег ФФД - 1179.
|
||||||
|
*/
|
||||||
|
protected $base_number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Описание коррекции. Тег ФФД - 1177.
|
||||||
|
*/
|
||||||
|
protected $base_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CorrectionInfo constructor.
|
||||||
|
*
|
||||||
|
* @param string|null $type Тип коррекции
|
||||||
|
* @param string|null $base_date Дата документа
|
||||||
|
* @param string|null $base_number Номер документа
|
||||||
|
* @param string|null $base_name Описание коррекции
|
||||||
|
*/
|
||||||
|
public function __construct(?string $type = null, ?string $base_date = null, ?string $base_number = null, ?string $base_name = null)
|
||||||
|
{
|
||||||
|
if ($type) {
|
||||||
|
$this->setType($type);
|
||||||
|
}
|
||||||
|
if ($base_date) {
|
||||||
|
$this->setDate($base_date);
|
||||||
|
}
|
||||||
|
if ($base_number) {
|
||||||
|
$this->setNumber($base_number);
|
||||||
|
}
|
||||||
|
if ($base_name) {
|
||||||
|
$this->setName($base_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает номер документа основания для коррекции.
|
||||||
|
* Тег ФФД - 1179.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getNumber(): ?string
|
||||||
|
{
|
||||||
|
return $this->base_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает номер документа основания для коррекции.
|
||||||
|
* Тег ФФД - 1179.
|
||||||
|
*
|
||||||
|
* @param string $number
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setNumber(string $number)
|
||||||
|
{
|
||||||
|
$this->base_number = trim($number);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает описание коррекции.
|
||||||
|
* Тег ФФД - 1177.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getName(): ?string
|
||||||
|
{
|
||||||
|
return $this->base_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает описание коррекции.
|
||||||
|
* Тег ФФД - 1177.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setName(string $name)
|
||||||
|
{
|
||||||
|
$this->base_name = trim($name);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает дату документа основания для коррекции.
|
||||||
|
* Тег ФФД - 1178.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getDate(): ?string
|
||||||
|
{
|
||||||
|
return $this->base_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает дату документа основания для коррекции.
|
||||||
|
* Тег ФФД - 1178.
|
||||||
|
*
|
||||||
|
* @param string $date Строка в формате d.m.Y
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setDate(string $date)
|
||||||
|
{
|
||||||
|
$this->base_date = $date;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает тип коррекции.
|
||||||
|
* Тег ФФД - 1173.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getType(): ?string
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает тип коррекции.
|
||||||
|
* Тег ФФД - 1173.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setType(string $type)
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'type' => $this->getType() ?? '', // обязателен
|
||||||
|
'base_date' => $this->getDate() ?? '', // обязателен
|
||||||
|
'base_number' => $this->getNumber() ?? '', // обязателен
|
||||||
|
'base_name' => $this->getName() ?? '' // обязателен
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
354
src/AtolOnline/Entities/Document.php
Normal file
354
src/AtolOnline/Entities/Document.php
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
use AtolOnline\Exceptions\AtolCashierTooLongException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс, описывающий документ
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
class Document extends AtolEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \AtolOnline\Entities\ItemArray Массив предметов расчёта
|
||||||
|
*/
|
||||||
|
protected $items;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \AtolOnline\Entities\VatArray Массив ставок НДС
|
||||||
|
*/
|
||||||
|
protected $vats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \AtolOnline\Entities\PaymentArray Массив оплат
|
||||||
|
*/
|
||||||
|
protected $payments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \AtolOnline\Entities\Company Объект компании (продавца)
|
||||||
|
*/
|
||||||
|
protected $company;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \AtolOnline\Entities\Client Объект клиента (покупателя)
|
||||||
|
*/
|
||||||
|
protected $client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int Итоговая сумма чека. Тег ФФД - 1020.
|
||||||
|
*/
|
||||||
|
protected $total = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string ФИО кассира. Тег ФФД - 1021.
|
||||||
|
*/
|
||||||
|
protected $cashier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \AtolOnline\Entities\CorrectionInfo Данные коррекции
|
||||||
|
*/
|
||||||
|
protected $correction_info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Document constructor.
|
||||||
|
*
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyPaymentsException Слишком много оплат
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->vats = new VatArray();
|
||||||
|
$this->payments = new PaymentArray();
|
||||||
|
$this->items = new ItemArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Удаляет все налоги из документа и предметов расчёта
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException Слишком большая сумма
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||||
|
*/
|
||||||
|
public function clearVats()
|
||||||
|
{
|
||||||
|
$this->setVats([]);
|
||||||
|
foreach ($this->getItems() as &$item) {
|
||||||
|
$item->setVatType(null);
|
||||||
|
}
|
||||||
|
$this->calcTotal();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавляет новую ставку НДС в массив ставок НДС
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Vat $vat Объект ставки НДС
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||||
|
*/
|
||||||
|
public function addVat(Vat $vat)
|
||||||
|
{
|
||||||
|
if (count($this->getVats()) == 0 && !$vat->getSum()) {
|
||||||
|
$vat->setSum($this->calcTotal());
|
||||||
|
}
|
||||||
|
$this->vats->add($vat);
|
||||||
|
$this->calcTotal();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает массив ставок НДС
|
||||||
|
*
|
||||||
|
* @return \AtolOnline\Entities\Vat[]
|
||||||
|
*/
|
||||||
|
public function getVats(): array
|
||||||
|
{
|
||||||
|
return $this->vats->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает массив ставок НДС
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Vat[] $vats Массив ставок НДС
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function setVats(array $vats)
|
||||||
|
{
|
||||||
|
$this->vats->set($vats);
|
||||||
|
$this->calcTotal();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавляет новую оплату в массив оплат
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Payment $payment Объект оплаты
|
||||||
|
* @return $this
|
||||||
|
* @throws \Exception
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyPaymentsException Слишком много оплат
|
||||||
|
*/
|
||||||
|
public function addPayment(Payment $payment)
|
||||||
|
{
|
||||||
|
if (count($this->getPayments()) == 0 && !$payment->getSum()) {
|
||||||
|
$payment->setSum($this->calcTotal());
|
||||||
|
}
|
||||||
|
$this->payments->add($payment);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает массив оплат
|
||||||
|
*
|
||||||
|
* @return \AtolOnline\Entities\Payment[]
|
||||||
|
*/
|
||||||
|
public function getPayments(): array
|
||||||
|
{
|
||||||
|
return $this->payments->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает массив оплат
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Payment[] $payments Массив оплат
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyPaymentsException Слишком много оплат
|
||||||
|
*/
|
||||||
|
public function setPayments(array $payments)
|
||||||
|
{
|
||||||
|
$this->payments->set($payments);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавляет новый предмет расчёта в массив предметов расчёта
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Item $item Объект предмета расчёта
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||||
|
*/
|
||||||
|
public function addItem(Item $item)
|
||||||
|
{
|
||||||
|
$this->items->add($item);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает массив предметов расчёта
|
||||||
|
*
|
||||||
|
* @return \AtolOnline\Entities\Item[]
|
||||||
|
*/
|
||||||
|
public function getItems(): array
|
||||||
|
{
|
||||||
|
return $this->items->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает массив предметов расчёта
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Item[] $items Массив предметов расчёта
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||||
|
*/
|
||||||
|
public function setItems(array $items)
|
||||||
|
{
|
||||||
|
$this->items->set($items);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает заданного клиента (покупателя)
|
||||||
|
*
|
||||||
|
* @return Client
|
||||||
|
*/
|
||||||
|
public function getClient(): Client
|
||||||
|
{
|
||||||
|
return $this->client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает клиента (покупателя)
|
||||||
|
*
|
||||||
|
* @param Client|null $client
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setClient(?Client $client)
|
||||||
|
{
|
||||||
|
$this->client = $client;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает заданную компанию (продавца)
|
||||||
|
*
|
||||||
|
* @return Company
|
||||||
|
*/
|
||||||
|
public function getCompany(): Company
|
||||||
|
{
|
||||||
|
return $this->company;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает компанию (продавца)
|
||||||
|
*
|
||||||
|
* @param Company|null $company
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCompany(?Company $company)
|
||||||
|
{
|
||||||
|
$this->company = $company;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает ФИО кассира. Тег ФФД - 1021.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getCashier(): ?string
|
||||||
|
{
|
||||||
|
return $this->cashier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает ФИО кассира. Тег ФФД - 1021.
|
||||||
|
*
|
||||||
|
* @param string|null $cashier
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolCashierTooLongException
|
||||||
|
*/
|
||||||
|
public function setCashier(?string $cashier)
|
||||||
|
{
|
||||||
|
$cashier = trim($cashier);
|
||||||
|
if (strlen($cashier) > 64) {
|
||||||
|
throw new AtolCashierTooLongException($cashier);
|
||||||
|
}
|
||||||
|
$this->cashier = $cashier;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает данные коррекции
|
||||||
|
*
|
||||||
|
* @return \AtolOnline\Entities\CorrectionInfo|null
|
||||||
|
*/
|
||||||
|
public function getCorrectionInfo(): ?CorrectionInfo
|
||||||
|
{
|
||||||
|
return $this->correction_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает данные коррекции
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\CorrectionInfo|null $correction_info
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCorrectionInfo(?CorrectionInfo $correction_info)
|
||||||
|
{
|
||||||
|
$this->correction_info = $correction_info;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Пересчитывает, сохраняет и возвращает итоговую сумму чека по всем позициям (включая НДС). Тег ФФД - 1020.
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function calcTotal()
|
||||||
|
{
|
||||||
|
$sum = 0;
|
||||||
|
foreach ($this->items->get() as $item) {
|
||||||
|
$sum += $item->calcSum();
|
||||||
|
}
|
||||||
|
foreach ($this->vats->get() as $vat) {
|
||||||
|
$vat->setSum($sum);
|
||||||
|
}
|
||||||
|
return $this->total = round($sum, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает итоговую сумму чека. Тег ФФД - 1020.
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getTotal(): float
|
||||||
|
{
|
||||||
|
return $this->total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
$json = [
|
||||||
|
'company' => $this->getCompany()->jsonSerialize(), // обязательно
|
||||||
|
'payments' => $this->payments->jsonSerialize(), // обязательно
|
||||||
|
'cashier' => $this->getCashier() ?? '',
|
||||||
|
];
|
||||||
|
if ($this->getCorrectionInfo()) {
|
||||||
|
$json['correction_info'] = $this->getCorrectionInfo()->jsonSerialize(); // обязательно для коррекционных
|
||||||
|
} else {
|
||||||
|
$json['client'] = $this->getClient()->jsonSerialize(); // обязательно для некоррекционных
|
||||||
|
$json['items'] = $this->items->jsonSerialize(); // обязательно для некоррекционных
|
||||||
|
$json['total'] = $this->calcTotal(); // обязательно для некоррекционных
|
||||||
|
}
|
||||||
|
if ($this->getVats()) {
|
||||||
|
$json['vats'] = $this->vats->jsonSerialize();
|
||||||
|
}
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
}
|
396
src/AtolOnline/Entities/Item.php
Normal file
396
src/AtolOnline/Entities/Item.php
Normal file
@ -0,0 +1,396 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
use AtolOnline\{Exceptions\AtolNameTooLongException,
|
||||||
|
Exceptions\AtolPriceTooHighException,
|
||||||
|
Exceptions\AtolQuantityTooHighException,
|
||||||
|
Exceptions\AtolUnitTooLongException,
|
||||||
|
Exceptions\AtolUserdataTooLongException,
|
||||||
|
Traits\RublesKopeksConverter
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Предмет расчёта (товар, услуга)
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
class Item extends AtolEntity
|
||||||
|
{
|
||||||
|
use RublesKopeksConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Наименование. Тег ФФД - 1030.
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int Цена в копейках (с учётом скидок и наценок). Тег ФФД - 1079.
|
||||||
|
*/
|
||||||
|
protected $price = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var float Количество, вес. Тег ФФД - 1023.
|
||||||
|
*/
|
||||||
|
protected $quantity = 0.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var float Сумма в копейках. Тег ФФД - 1043.
|
||||||
|
*/
|
||||||
|
protected $sum = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Единица измерения количества. Тег ФФД - 1197.
|
||||||
|
*/
|
||||||
|
protected $measurement_unit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Vat Ставка НДС
|
||||||
|
*/
|
||||||
|
protected $vat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Признак способа расчёта. Тег ФФД - 1214.
|
||||||
|
*/
|
||||||
|
protected $payment_method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Признак объекта расчёта. Тег ФФД - 1212.
|
||||||
|
*/
|
||||||
|
protected $payment_object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Дополнительный реквизит. Тег ФФД - 1191.
|
||||||
|
*/
|
||||||
|
protected $user_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item constructor.
|
||||||
|
*
|
||||||
|
* @param string|null $name Наименование
|
||||||
|
* @param float|null $price Цена за одну единицу
|
||||||
|
* @param float|null $quantity Количество
|
||||||
|
* @param string|null $measurement_unit Единица измерения
|
||||||
|
* @param string|null $vat_type Ставка НДС
|
||||||
|
* @param string|null $payment_object Признак
|
||||||
|
* @param string|null $payment_method Способ расчёта
|
||||||
|
* @throws AtolNameTooLongException Слишком длинное наименование
|
||||||
|
* @throws AtolPriceTooHighException Слишком высокая цена за одну единицу
|
||||||
|
* @throws AtolQuantityTooHighException Слишком большое количество
|
||||||
|
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
?string $name = null,
|
||||||
|
?float $price = null,
|
||||||
|
?float $quantity = null,
|
||||||
|
?string $measurement_unit = null,
|
||||||
|
$vat_type = null,
|
||||||
|
?string $payment_object = null,
|
||||||
|
?string $payment_method = null
|
||||||
|
) {
|
||||||
|
if ($name) {
|
||||||
|
$this->setName($name);
|
||||||
|
}
|
||||||
|
if ($price) {
|
||||||
|
$this->setPrice($price);
|
||||||
|
}
|
||||||
|
if ($payment_object) {
|
||||||
|
$this->setPaymentObject($payment_object);
|
||||||
|
}
|
||||||
|
if ($quantity) {
|
||||||
|
$this->setQuantity($quantity);
|
||||||
|
}
|
||||||
|
if ($vat_type) {
|
||||||
|
$this->setVatType($vat_type);
|
||||||
|
}
|
||||||
|
if ($measurement_unit) {
|
||||||
|
$this->setMeasurementUnit($measurement_unit);
|
||||||
|
}
|
||||||
|
if ($payment_method) {
|
||||||
|
$this->setPaymentMethod($payment_method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает наименование. Тег ФФД - 1030.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устаналивает наименование. Тег ФФД - 1030.
|
||||||
|
*
|
||||||
|
* @param string $name Наименование
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolNameTooLongException Слишком длинное имя/наименование
|
||||||
|
*/
|
||||||
|
public function setName(string $name)
|
||||||
|
{
|
||||||
|
$name = trim($name);
|
||||||
|
if (strlen($name) > 128) {
|
||||||
|
throw new AtolNameTooLongException($name, 128);
|
||||||
|
}
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает цену в рублях. Тег ФФД - 1079.
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getPrice()
|
||||||
|
{
|
||||||
|
return self::toRub($this->price);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает цену в рублях. Тег ФФД - 1079.
|
||||||
|
*
|
||||||
|
* @param float $rubles Цена за одну единицу в рублях
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolPriceTooHighException Слишком высокая цена за одну единицу
|
||||||
|
*/
|
||||||
|
public function setPrice(float $rubles)
|
||||||
|
{
|
||||||
|
if ($rubles > 42949672.95) {
|
||||||
|
throw new AtolPriceTooHighException($rubles, 42949672.95);
|
||||||
|
}
|
||||||
|
$this->price = self::toKop($rubles);
|
||||||
|
$this->calcSum();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает количество. Тег ФФД - 1023.
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getQuantity(): float
|
||||||
|
{
|
||||||
|
return $this->quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает количество. Тег ФФД - 1023.
|
||||||
|
*
|
||||||
|
* @param float $quantity Количество
|
||||||
|
* @param string|null $measurement_unit Единица измерения количества
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolQuantityTooHighException Слишком большое количество
|
||||||
|
* @throws AtolPriceTooHighException Слишком высокая общая стоимость
|
||||||
|
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
|
||||||
|
*/
|
||||||
|
public function setQuantity(float $quantity, string $measurement_unit = null)
|
||||||
|
{
|
||||||
|
$quantity = round($quantity, 3);
|
||||||
|
if ($quantity > 99999.999) {
|
||||||
|
throw new AtolQuantityTooHighException($quantity, 99999.999);
|
||||||
|
}
|
||||||
|
$this->quantity = $quantity;
|
||||||
|
$this->calcSum();
|
||||||
|
if ($measurement_unit) {
|
||||||
|
$this->setMeasurementUnit($measurement_unit);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает заданную единицу измерения количества. Тег ФФД - 1197.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMeasurementUnit(): string
|
||||||
|
{
|
||||||
|
return $this->measurement_unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает единицу измерения количества. Тег ФФД - 1197.
|
||||||
|
*
|
||||||
|
* @param string $measurement_unit Единица измерения количества
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
|
||||||
|
*/
|
||||||
|
public function setMeasurementUnit(string $measurement_unit)
|
||||||
|
{
|
||||||
|
$measurement_unit = trim($measurement_unit);
|
||||||
|
if (strlen($measurement_unit) > 16) {
|
||||||
|
throw new AtolUnitTooLongException($measurement_unit, 16);
|
||||||
|
}
|
||||||
|
$this->measurement_unit = $measurement_unit;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает признак способа оплаты. Тег ФФД - 1214.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPaymentMethod(): string
|
||||||
|
{
|
||||||
|
return $this->payment_method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает признак способа оплаты. Тег ФФД - 1214.
|
||||||
|
*
|
||||||
|
* @param string $payment_method Признак способа оплаты
|
||||||
|
* @return $this
|
||||||
|
* @todo Проверка допустимых значений
|
||||||
|
*/
|
||||||
|
public function setPaymentMethod(string $payment_method)
|
||||||
|
{
|
||||||
|
$this->payment_method = trim($payment_method);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает признак предмета расчёта. Тег ФФД - 1212.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPaymentObject(): string
|
||||||
|
{
|
||||||
|
return $this->payment_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает признак предмета расчёта. Тег ФФД - 1212.
|
||||||
|
*
|
||||||
|
* @param string $payment_object Признак предмета расчёта
|
||||||
|
* @return $this
|
||||||
|
* @todo Проверка допустимых значений
|
||||||
|
*/
|
||||||
|
public function setPaymentObject(string $payment_object)
|
||||||
|
{
|
||||||
|
$this->payment_object = trim($payment_object);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает ставку НДС
|
||||||
|
*
|
||||||
|
* @return \AtolOnline\Entities\Vat|null
|
||||||
|
*/
|
||||||
|
public function getVat(): ?Vat
|
||||||
|
{
|
||||||
|
return $this->vat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает ставку НДС
|
||||||
|
*
|
||||||
|
* @param string|null $vat_type Тип ставки НДС. Передать null, чтобы удалить ставку.
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
|
||||||
|
*/
|
||||||
|
public function setVatType(?string $vat_type)
|
||||||
|
{
|
||||||
|
if ($vat_type) {
|
||||||
|
$this->vat
|
||||||
|
? $this->vat->setType($vat_type)
|
||||||
|
: $this->vat = new Vat($vat_type);
|
||||||
|
} else {
|
||||||
|
$this->vat = null;
|
||||||
|
}
|
||||||
|
$this->calcSum();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает дополнительный реквизит. Тег ФФД - 1191.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getUserData(): ?string
|
||||||
|
{
|
||||||
|
return $this->user_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает дополнительный реквизит. Тег ФФД - 1191.
|
||||||
|
*
|
||||||
|
* @param string $user_data Дополнительный реквизит. Тег ФФД - 1191.
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolUserdataTooLongException Слишком длинный дополнительный реквизит
|
||||||
|
*/
|
||||||
|
public function setUserData(string $user_data)
|
||||||
|
{
|
||||||
|
$user_data = trim($user_data);
|
||||||
|
if (strlen($user_data) > 64) {
|
||||||
|
throw new AtolUserdataTooLongException($user_data, 64);
|
||||||
|
}
|
||||||
|
$this->user_data = $user_data;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает стоимость. Тег ФФД - 1043.
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getSum(): float
|
||||||
|
{
|
||||||
|
return self::toRub($this->sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Расчитывает стоимость и размер НДС на неё
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
* @throws AtolPriceTooHighException Слишком большая сумма
|
||||||
|
*/
|
||||||
|
public function calcSum()
|
||||||
|
{
|
||||||
|
$sum = $this->quantity * $this->price;
|
||||||
|
if (self::toRub($sum) > 42949672.95) {
|
||||||
|
throw new AtolPriceTooHighException($sum, 42949672.95);
|
||||||
|
}
|
||||||
|
$this->sum = $sum;
|
||||||
|
if ($this->vat) {
|
||||||
|
$this->vat->setSum(self::toRub($sum));
|
||||||
|
}
|
||||||
|
return $this->getSum();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
$json = [
|
||||||
|
'name' => $this->getName(), // обязательно
|
||||||
|
'price' => $this->getPrice(), // обязательно
|
||||||
|
'quantity' => $this->getQuantity(), // обязательно
|
||||||
|
'sum' => $this->getSum(), // обязательно
|
||||||
|
'measurement_unit' => $this->getMeasurementUnit(),
|
||||||
|
'payment_method' => $this->getPaymentMethod(),
|
||||||
|
'payment_object' => $this->getPaymentObject()
|
||||||
|
//TODO nomenclature_code
|
||||||
|
//TODO agent_info
|
||||||
|
//TODO supplier_info
|
||||||
|
//TODO excise
|
||||||
|
//TODO country_code
|
||||||
|
//TODO declaration_number
|
||||||
|
];
|
||||||
|
if ($this->getVat()) {
|
||||||
|
$json['vat'] = $this->getVat()->jsonSerialize();
|
||||||
|
}
|
||||||
|
if ($this->getUserData()) {
|
||||||
|
$json['user_data'] = $this->getUserData();
|
||||||
|
}
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
}
|
111
src/AtolOnline/Entities/ItemArray.php
Normal file
111
src/AtolOnline/Entities/ItemArray.php
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
use AtolOnline\Exceptions\AtolTooManyItemsException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс, описывающий массив предметов расчёта
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
class ItemArray extends AtolEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Максимальное количество элементов в массиве
|
||||||
|
*/
|
||||||
|
const MAX_COUNT = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \AtolOnline\Entities\Item[] Массив предметов расчёта
|
||||||
|
*/
|
||||||
|
private $items = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ItemArray constructor.
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Item[]|null $items Массив предметов расчёта
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||||
|
*/
|
||||||
|
public function __construct(array $items = null)
|
||||||
|
{
|
||||||
|
if ($items) {
|
||||||
|
$this->set($items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает массив предметов расчёта
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Item[] $items Массив предметов расчёта
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||||
|
*/
|
||||||
|
public function set(array $items)
|
||||||
|
{
|
||||||
|
if ($this->validateCount($items)) {
|
||||||
|
$this->items = $items;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавляет предмет расчёта в массив
|
||||||
|
*
|
||||||
|
* @param \AtolOnline\Entities\Item $item Объект предмета расчёта
|
||||||
|
* @return $this
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||||
|
*/
|
||||||
|
public function add(Item $item)
|
||||||
|
{
|
||||||
|
if ($this->validateCount()) {
|
||||||
|
$this->items[] = $item;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает массив предметов расчёта
|
||||||
|
*
|
||||||
|
* @return \AtolOnline\Entities\Item[]
|
||||||
|
*/
|
||||||
|
public function get()
|
||||||
|
{
|
||||||
|
return $this->items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
foreach ($this->get() as $item) {
|
||||||
|
$result[] = $item->jsonSerialize();
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверяет количество элементов в массиве
|
||||||
|
*
|
||||||
|
* @param array|null $items Если передать массив, то проверит количество его элементов.
|
||||||
|
* Иначе проверит количество уже присвоенных элементов.
|
||||||
|
* @return bool
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||||
|
*/
|
||||||
|
protected function validateCount(array $items = null)
|
||||||
|
{
|
||||||
|
if (($items && is_array($items) && count($items) >= self::MAX_COUNT) || count($this->items) == self::MAX_COUNT) {
|
||||||
|
throw new AtolTooManyItemsException(self::MAX_COUNT);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
97
src/AtolOnline/Entities/Payment.php
Normal file
97
src/AtolOnline/Entities/Payment.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
use AtolOnline\Constants\PaymentTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс, описывающий оплату. Тег ФФД - 1031, 1081, 1215, 1216, 1217.
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
class Payment extends AtolEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int Тип оплаты
|
||||||
|
*/
|
||||||
|
protected $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var float Сумма оплаты
|
||||||
|
*/
|
||||||
|
protected $sum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payment constructor.
|
||||||
|
*
|
||||||
|
* @param int $payment_type Тип оплаты
|
||||||
|
* @param float $sum Сумма оплаты
|
||||||
|
*/
|
||||||
|
public function __construct(int $payment_type = PaymentTypes::ELECTRON, float $sum = 0.0)
|
||||||
|
{
|
||||||
|
$this->setType($payment_type);
|
||||||
|
$this->setSum($sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает тип оплаты. Тег ФФД - 1031, 1081, 1215, 1216, 1217.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getType(): int
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает тип оплаты. Тег ФФД - 1031, 1081, 1215, 1216, 1217.
|
||||||
|
*
|
||||||
|
* @param int $type
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setType(int $type)
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает сумму оплаты
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getSum(): float
|
||||||
|
{
|
||||||
|
return $this->sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает сумму оплаты
|
||||||
|
*
|
||||||
|
* @param float $sum
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setSum(float $sum)
|
||||||
|
{
|
||||||
|
$this->sum = $sum;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'type' => $this->getType(),
|
||||||
|
'sum' => $this->getSum(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
111
src/AtolOnline/Entities/PaymentArray.php
Normal file
111
src/AtolOnline/Entities/PaymentArray.php
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
use AtolOnline\Exceptions\AtolTooManyPaymentsException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс, описывающий массив оплат
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
class PaymentArray extends AtolEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Максимальное количество элементов в массиве
|
||||||
|
*/
|
||||||
|
const MAX_COUNT = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Payment[] Массив оплат
|
||||||
|
*/
|
||||||
|
private $payments = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ItemArray constructor.
|
||||||
|
*
|
||||||
|
* @param Payment[]|null $payments Массив оплат
|
||||||
|
* @throws AtolTooManyPaymentsException Слишком много оплат
|
||||||
|
*/
|
||||||
|
public function __construct(array $payments = null)
|
||||||
|
{
|
||||||
|
if ($payments) {
|
||||||
|
$this->set($payments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает массив оплат
|
||||||
|
*
|
||||||
|
* @param Payment[] $payments
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolTooManyPaymentsException Слишком много оплат
|
||||||
|
*/
|
||||||
|
public function set(array $payments)
|
||||||
|
{
|
||||||
|
if ($this->validateCount($payments)) {
|
||||||
|
$this->payments = $payments;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавляет новую оплату к заданным
|
||||||
|
*
|
||||||
|
* @param Payment $payment Объект оплаты
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolTooManyPaymentsException Слишком много оплат
|
||||||
|
*/
|
||||||
|
public function add(Payment $payment)
|
||||||
|
{
|
||||||
|
if ($this->validateCount()) {
|
||||||
|
$this->payments[] = $payment;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает массив оплат
|
||||||
|
*
|
||||||
|
* @return Payment[]
|
||||||
|
*/
|
||||||
|
public function get()
|
||||||
|
{
|
||||||
|
return $this->payments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
foreach ($this->get() as $payment) {
|
||||||
|
$result[] = $payment->jsonSerialize();
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверяет количество элементов в массиве
|
||||||
|
*
|
||||||
|
* @param Payment[]|null $payments Если передать массив, то проверит количество его элементов.
|
||||||
|
* Иначе проверит количество уже присвоенных элементов.
|
||||||
|
* @return bool
|
||||||
|
* @throws AtolTooManyPaymentsException Слишком много оплат
|
||||||
|
*/
|
||||||
|
protected function validateCount(array $payments = null)
|
||||||
|
{
|
||||||
|
if (($payments && is_array($payments) && count($payments) >= self::MAX_COUNT) || count($this->payments) == self::MAX_COUNT) {
|
||||||
|
throw new AtolTooManyPaymentsException(self::MAX_COUNT);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
186
src/AtolOnline/Entities/Vat.php
Normal file
186
src/AtolOnline/Entities/Vat.php
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
use AtolOnline\{Constants\VatTypes, Traits\RublesKopeksConverter};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс, описывающий ставку НДС
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
class Vat extends AtolEntity
|
||||||
|
{
|
||||||
|
use RublesKopeksConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Выбранный тип ставки НДС. Тег ФФД - 1199, 1105, 1104, 1103, 1102, 1107, 1106.
|
||||||
|
*/
|
||||||
|
private $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int Сумма в копейках, от которой пересчитывается размер налога
|
||||||
|
*/
|
||||||
|
private $sum_original = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int Сумма налога в копейках
|
||||||
|
*/
|
||||||
|
private $sum_final = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vat constructor.
|
||||||
|
*
|
||||||
|
* @param string $type Тип ставки НДС
|
||||||
|
* @param float|null $rubles Исходная сумма в рублях, от которой нужно расчитать размер НДС
|
||||||
|
*/
|
||||||
|
public function __construct(string $type = VatTypes::NONE, float $rubles = null)
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
if ($rubles) {
|
||||||
|
$this->setSum($rubles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает размер НДС от суммы в копейках
|
||||||
|
*
|
||||||
|
* @param string $type Тип ставки НДС
|
||||||
|
* @param int $kopeks Копейки
|
||||||
|
* @return float|int
|
||||||
|
* @see https://nalog-nalog.ru/nds/nalogovaya_baza_nds/kak-schitat-nds-pravilno-vychislyaem-20-ot-summy-primer-algoritm/
|
||||||
|
* @see https://glavkniga.ru/situations/k500734
|
||||||
|
* @see https://www.b-kontur.ru/nds-kalkuljator-online
|
||||||
|
*/
|
||||||
|
protected static function calculator(string $type, int $kopeks)
|
||||||
|
{
|
||||||
|
switch ($type) {
|
||||||
|
case VatTypes::NONE:
|
||||||
|
case VatTypes::VAT0:
|
||||||
|
return 0;
|
||||||
|
case VatTypes::VAT10:
|
||||||
|
return $kopeks * 10 / 100;
|
||||||
|
case VatTypes::VAT110:
|
||||||
|
return $kopeks * 10 / 110;
|
||||||
|
case VatTypes::VAT18:
|
||||||
|
return $kopeks * 18 / 100;
|
||||||
|
case VatTypes::VAT118:
|
||||||
|
return $kopeks * 18 / 118;
|
||||||
|
case VatTypes::VAT20:
|
||||||
|
return $kopeks * 20 / 100;
|
||||||
|
case VatTypes::VAT120:
|
||||||
|
return $kopeks * 20 / 120;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает тип ставки НДС. Тег ФФД - 1199, 1105, 1104, 1103, 1102, 1107, 1106.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType(): string
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает тип ставки НДС. Тег ФФД - 1199, 1105, 1104, 1103, 1102, 1107, 1106.
|
||||||
|
* Автоматически пересчитывает итоговый размер НДС от исходной суммы.
|
||||||
|
*
|
||||||
|
* @param string $type Тип ставки НДС
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setType(string $type)
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
$this->setFinal();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает расчитанный итоговый размер ставки НДС в рублях. Тег ФФД - 1200.
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getFinalSum()
|
||||||
|
{
|
||||||
|
return self::toRub($this->sum_final);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает исходную сумму, от которой будет расчитываться итоговый размер НДС.
|
||||||
|
* Автоматически пересчитывает итоговый размер НДС от исходной суммы.
|
||||||
|
*
|
||||||
|
* @param float $rubles Сумма в рублях за предмет расчёта, из которой высчитывается размер НДС
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setSum(float $rubles)
|
||||||
|
{
|
||||||
|
$this->sum_original = self::toKop($rubles);
|
||||||
|
$this->setFinal();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает исходную сумму, от которой расчитывается размер налога
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getSum(): float
|
||||||
|
{
|
||||||
|
return self::toRub($this->sum_original);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Прибавляет указанную сумму к общей исходной сумме.
|
||||||
|
* Автоматически пересчитывает итоговый размер НДС от новой исходной суммы.
|
||||||
|
*
|
||||||
|
* @param float $rubles
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function addSum(float $rubles)
|
||||||
|
{
|
||||||
|
$this->sum_original += self::toKop($rubles);
|
||||||
|
$this->setFinal();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Расчитывает и возвращает размер НДС от указанной суммы в рублях.
|
||||||
|
* Не изменяет итоговый размер НДС.
|
||||||
|
*
|
||||||
|
* @param float|null $rubles
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function calc(float $rubles): float
|
||||||
|
{
|
||||||
|
return self::toRub(self::calculator($this->type, self::toKop($rubles)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'type' => $this->getType(),
|
||||||
|
'sum' => $this->getFinalSum(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Расчитывает и устанавливает итоговый размер ставки от исходной суммы в копейках
|
||||||
|
*/
|
||||||
|
protected function setFinal()
|
||||||
|
{
|
||||||
|
$this->sum_final = self::calculator($this->type, $this->sum_original);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
111
src/AtolOnline/Entities/VatArray.php
Normal file
111
src/AtolOnline/Entities/VatArray.php
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Entities;
|
||||||
|
|
||||||
|
use AtolOnline\Exceptions\AtolTooManyVatsException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс, описывающий массив ставок НДС
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Entities
|
||||||
|
*/
|
||||||
|
class VatArray extends AtolEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Максимальное количество элементов в массиве
|
||||||
|
*/
|
||||||
|
public const MAX_COUNT = 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Vat[] Массив ставок НДС
|
||||||
|
*/
|
||||||
|
private $vats = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VatArray constructor.
|
||||||
|
*
|
||||||
|
* @param Vat[]|null $vats Массив ставок НДС
|
||||||
|
* @throws AtolTooManyVatsException Слишком много ставок НДС
|
||||||
|
*/
|
||||||
|
public function __construct(array $vats = null)
|
||||||
|
{
|
||||||
|
if ($vats) {
|
||||||
|
$this->set($vats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает массив ставок НДС
|
||||||
|
*
|
||||||
|
* @param Vat[] $vats Массив ставок НДС
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolTooManyVatsException Слишком много ставок НДС
|
||||||
|
*/
|
||||||
|
public function set(array $vats)
|
||||||
|
{
|
||||||
|
if ($this->validateCount($vats)) {
|
||||||
|
$this->vats = $vats;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавляет новую ставку НДС в массив
|
||||||
|
*
|
||||||
|
* @param Vat $vat Объект ставки НДС
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolTooManyVatsException Слишком много ставок НДС
|
||||||
|
*/
|
||||||
|
public function add(Vat $vat)
|
||||||
|
{
|
||||||
|
if ($this->validateCount()) {
|
||||||
|
$this->vats[] = $vat;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает массив ставок НДС
|
||||||
|
*
|
||||||
|
* @return Vat[]
|
||||||
|
*/
|
||||||
|
public function get()
|
||||||
|
{
|
||||||
|
return $this->vats;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
foreach ($this->get() as $vat) {
|
||||||
|
$result[] = $vat->jsonSerialize();
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверяет количество элементов в массиве
|
||||||
|
*
|
||||||
|
* @param array|null $vats Если передать массив, то проверит количество его элементов.
|
||||||
|
* Иначе проверит количество уже присвоенных элементов.
|
||||||
|
* @return bool
|
||||||
|
* @throws AtolTooManyVatsException Слишком много ставок НДС
|
||||||
|
*/
|
||||||
|
protected function validateCount(array $vats = null)
|
||||||
|
{
|
||||||
|
if (($vats && is_array($vats) && count($vats) >= self::MAX_COUNT) || count($this->vats) == self::MAX_COUNT) {
|
||||||
|
throw new AtolTooManyVatsException(self::MAX_COUNT);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
34
src/AtolOnline/Exceptions/AtolCashierTooLongException.php
Normal file
34
src/AtolOnline/Exceptions/AtolCashierTooLongException.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать слишком длинное имя кассира
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolCashierTooLongException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolCashierTooLongException constructor.
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($name, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком длинное имя кассира (макс. длина 64, фактически '.strlen($name).'): '.$name;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
33
src/AtolOnline/Exceptions/AtolCorrectionInfoException.php
Normal file
33
src/AtolOnline/Exceptions/AtolCorrectionInfoException.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке зарегистрировать документ без данных коррекции
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolCorrectionInfoException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolNoCorrectionInfoException constructor.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'В документе отсутствуют данные коррекции';
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
33
src/AtolOnline/Exceptions/AtolEmailEmptyException.php
Normal file
33
src/AtolOnline/Exceptions/AtolEmailEmptyException.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать пустой email
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolEmailEmptyException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolEmailEmptyException constructor.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Email не может быть пустым';
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
35
src/AtolOnline/Exceptions/AtolEmailTooLongException.php
Normal file
35
src/AtolOnline/Exceptions/AtolEmailTooLongException.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать слишком длинный email
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolEmailTooLongException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolEmailTooLongException constructor.
|
||||||
|
*
|
||||||
|
* @param $email
|
||||||
|
* @param $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($email, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком длинный email (макс. длина '.$max.', фактически '.strlen($email).'): '.$email;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
34
src/AtolOnline/Exceptions/AtolEmailValidateException.php
Normal file
34
src/AtolOnline/Exceptions/AtolEmailValidateException.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при ошибке валидации email
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolEmailValidateException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolEmailValidateException constructor.
|
||||||
|
*
|
||||||
|
* @param $email
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param \Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($email, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Некорректный email: '.$email;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
22
src/AtolOnline/Exceptions/AtolException.php
Normal file
22
src/AtolOnline/Exceptions/AtolException.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при работе с АТОЛ Онлайн
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
34
src/AtolOnline/Exceptions/AtolInnWrongLengthException.php
Normal file
34
src/AtolOnline/Exceptions/AtolInnWrongLengthException.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать ИНН некорректной длины
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolInnWrongLengthException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolInnWrongLengthException constructor.
|
||||||
|
*
|
||||||
|
* @param $inn
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($inn, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Длина ИНН должна быть 10 или 12 цифр, фактически '.strlen($inn).': '.$inn;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
33
src/AtolOnline/Exceptions/AtolKktLoginEmptyException.php
Normal file
33
src/AtolOnline/Exceptions/AtolKktLoginEmptyException.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать пустой логин ККТ
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolKktLoginEmptyException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolKktLoginEmptyException constructor.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Логин ККТ не может быть пустым';
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
35
src/AtolOnline/Exceptions/AtolKktLoginTooLongException.php
Normal file
35
src/AtolOnline/Exceptions/AtolKktLoginTooLongException.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать слишком длинный логин ККТ
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolKktLoginTooLongException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolKktLoginTooLongException constructor.
|
||||||
|
*
|
||||||
|
* @param $login
|
||||||
|
* @param $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($login, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком длинный логин ККТ (макс. длина '.$max.', фактически '.strlen($login).'): '.$login;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
33
src/AtolOnline/Exceptions/AtolKktPasswordEmptyException.php
Normal file
33
src/AtolOnline/Exceptions/AtolKktPasswordEmptyException.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать пустой пароль ККТ
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolKktPasswordEmptyException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolKktPasswordEmptyException constructor.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Пароль ККТ не может быть пустым';
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
35
src/AtolOnline/Exceptions/AtolNameTooLongException.php
Normal file
35
src/AtolOnline/Exceptions/AtolNameTooLongException.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать слишком длинное имя
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolNameTooLongException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolNameTooLongException constructor.
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
* @param $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($name, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком длинное имя/наименование (макс. длина '.$max.', фактически '.strlen($name).'): '.$name;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать слишком длинный платёжный адрес
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolPaymentAddressTooLongException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolPaymentAddressTooLongException constructor.
|
||||||
|
*
|
||||||
|
* @param $address
|
||||||
|
* @param $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($address, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком длинный адрес (макс. длина '.$max.', фактически '.strlen($address).'): '.$address;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
35
src/AtolOnline/Exceptions/AtolPhoneTooLongException.php
Normal file
35
src/AtolOnline/Exceptions/AtolPhoneTooLongException.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать слишком длинный телефон
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolPhoneTooLongException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolPhoneTooLongException constructor.
|
||||||
|
*
|
||||||
|
* @param $phone
|
||||||
|
* @param $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($phone, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком длинный телефон (макс. длина '.$max.', фактически '.strlen($phone).'): '.$phone;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
35
src/AtolOnline/Exceptions/AtolPriceTooHighException.php
Normal file
35
src/AtolOnline/Exceptions/AtolPriceTooHighException.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать слишком высокую цену (сумму)
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolPriceTooHighException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolPriceTooHighException constructor.
|
||||||
|
*
|
||||||
|
* @param $price
|
||||||
|
* @param $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($price, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком большая сумма (макс. '.$max.'): '.$price;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
35
src/AtolOnline/Exceptions/AtolQuantityTooHighException.php
Normal file
35
src/AtolOnline/Exceptions/AtolQuantityTooHighException.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать слишком большое количество
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolQuantityTooHighException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolQuantityTooHighException constructor.
|
||||||
|
*
|
||||||
|
* @param $quantity
|
||||||
|
* @param $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($quantity, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком большое количество (макс. '.$max.'): '.$quantity;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
34
src/AtolOnline/Exceptions/AtolTooManyItemsException.php
Normal file
34
src/AtolOnline/Exceptions/AtolTooManyItemsException.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке добавить слишком много предметов расчёта в массив
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolTooManyItemsException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolTooManyItemsException constructor.
|
||||||
|
*
|
||||||
|
* @param int $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком много предметов расчёта (макс. '.$max.')';
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
34
src/AtolOnline/Exceptions/AtolTooManyPaymentsException.php
Normal file
34
src/AtolOnline/Exceptions/AtolTooManyPaymentsException.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке добавить слишком много ставок НДС в массив
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolTooManyPaymentsException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolTooManyPaymentsException constructor.
|
||||||
|
*
|
||||||
|
* @param int $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком много платежей (макс. '.$max.')';
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
34
src/AtolOnline/Exceptions/AtolTooManyVatsException.php
Normal file
34
src/AtolOnline/Exceptions/AtolTooManyVatsException.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке добавить слишком много ставок НДС в массив
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolTooManyVatsException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolTooManyVatsException constructor.
|
||||||
|
*
|
||||||
|
* @param int $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком много ставок НДС (макс. '.$max.')';
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
35
src/AtolOnline/Exceptions/AtolUnitTooLongException.php
Normal file
35
src/AtolOnline/Exceptions/AtolUnitTooLongException.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать слишком длинный телефон
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolUnitTooLongException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolUnitTooLongException constructor.
|
||||||
|
*
|
||||||
|
* @param $unit
|
||||||
|
* @param $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($unit, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком длинное название единицы измерения (макс. длина '.$max.', фактически '.strlen($unit).'): '.$unit;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
35
src/AtolOnline/Exceptions/AtolUserdataTooLongException.php
Normal file
35
src/AtolOnline/Exceptions/AtolUserdataTooLongException.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать слишком длинный телефон
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolUserdataTooLongException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolUserdataTooLongException constructor.
|
||||||
|
*
|
||||||
|
* @param $data
|
||||||
|
* @param $max
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($data, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Слишком длинный дополнительный реквизит (макс. длина '.$max.', фактически '.strlen($data).'): '.$data;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
34
src/AtolOnline/Exceptions/AtolUuidValidateException.php
Normal file
34
src/AtolOnline/Exceptions/AtolUuidValidateException.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при ошибке валидации UUID
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolUuidValidateException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolUuidValidateException constructor.
|
||||||
|
*
|
||||||
|
* @param $uuid
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param \Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($uuid, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Некорректный UUID: '.$uuid;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
34
src/AtolOnline/Exceptions/AtolWrongDocumentTypeException.php
Normal file
34
src/AtolOnline/Exceptions/AtolWrongDocumentTypeException.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Exceptions;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение, возникающее при попытке указать некорректный тип документа
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Exceptions
|
||||||
|
*/
|
||||||
|
class AtolWrongDocumentTypeException extends AtolException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AtolWrongDocumentTypeException constructor.
|
||||||
|
*
|
||||||
|
* @param $type
|
||||||
|
* @param string $message
|
||||||
|
* @param int $code
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($type, $message = "", $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = $message ?: 'Некорректный тип документа: ожидался \'receipt\' или \'correction\', указан \''.$type.'\'';
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
56
src/AtolOnline/Traits/HasEmail.php
Normal file
56
src/AtolOnline/Traits/HasEmail.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Traits;
|
||||||
|
|
||||||
|
use AtolOnline\{Exceptions\AtolEmailTooLongException, Exceptions\AtolEmailValidateException};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавляет объекту функционал для работы с email
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Traits
|
||||||
|
*/
|
||||||
|
trait HasEmail
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string Почта
|
||||||
|
*/
|
||||||
|
protected $email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает установленную почту. Тег ФФД: 1008, 1117.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getEmail()
|
||||||
|
{
|
||||||
|
return $this->email;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает почту. Тег ФФД: 1008, 1117.
|
||||||
|
*
|
||||||
|
* @param string $email
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolEmailTooLongException
|
||||||
|
* @throws AtolEmailValidateException
|
||||||
|
*/
|
||||||
|
public function setEmail(string $email)
|
||||||
|
{
|
||||||
|
$email = trim($email);
|
||||||
|
if (strlen($email) > 64) {
|
||||||
|
throw new AtolEmailTooLongException($email, 64);
|
||||||
|
}
|
||||||
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
throw new AtolEmailValidateException($email);
|
||||||
|
}
|
||||||
|
$this->email = $email;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
53
src/AtolOnline/Traits/HasInn.php
Normal file
53
src/AtolOnline/Traits/HasInn.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Traits;
|
||||||
|
|
||||||
|
use AtolOnline\Exceptions\AtolInnWrongLengthException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавляет объекту функционал для работы с ИНН
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Traits
|
||||||
|
*/
|
||||||
|
trait HasInn
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string ИНН
|
||||||
|
*/
|
||||||
|
protected $inn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает установленный ИНН. Тег ФФД: 1228, 1018.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getInn()
|
||||||
|
{
|
||||||
|
return $this->inn ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает ИНН. Тег ФФД: 1228, 1018.
|
||||||
|
* Входная строка лишается всех знаков, кроме цифр.
|
||||||
|
*
|
||||||
|
* @param string $inn
|
||||||
|
* @return $this
|
||||||
|
* @throws AtolInnWrongLengthException
|
||||||
|
*/
|
||||||
|
public function setInn(string $inn)
|
||||||
|
{
|
||||||
|
$inn = preg_replace("/[^0-9]/", '', $inn);
|
||||||
|
if (preg_match_all("/(^[0-9]{10}$)|(^[0-9]{12}$)/", $inn) == 0) {
|
||||||
|
throw new AtolInnWrongLengthException($inn);
|
||||||
|
}
|
||||||
|
$this->inn = $inn;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
40
src/AtolOnline/Traits/RublesKopeksConverter.php
Normal file
40
src/AtolOnline/Traits/RublesKopeksConverter.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AtolOnline\Traits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Свойство класса, позволяющее конвертировать рубли <-> копейки
|
||||||
|
*
|
||||||
|
* @package AtolOnline\Traits
|
||||||
|
*/
|
||||||
|
trait RublesKopeksConverter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Конвертирует рубли в копейки, учитывая только 2 знака после запятой
|
||||||
|
*
|
||||||
|
* @param float|null $rubles Рубли
|
||||||
|
* @return int Копейки
|
||||||
|
*/
|
||||||
|
protected static function toKop(?float $rubles = null)
|
||||||
|
{
|
||||||
|
return $rubles === null ? null : (int)round($rubles * 100, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Конвертирует копейки в рубли, оставляя только 2 знака после запятой
|
||||||
|
*
|
||||||
|
* @param int|null $kopeks Копейки
|
||||||
|
* @return float Рубли
|
||||||
|
*/
|
||||||
|
protected static function toRub(?int $kopeks = null)
|
||||||
|
{
|
||||||
|
return $kopeks === null ? null : round($kopeks / 100, 2);
|
||||||
|
}
|
||||||
|
}
|
48
tests/BasicTestCase.php
Normal file
48
tests/BasicTestCase.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
use AtolOnline\Entities\AtolEntity;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BasicTestCase
|
||||||
|
*/
|
||||||
|
class BasicTestCase extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
//parent::setUp();
|
||||||
|
defined('ATOL_KKT_GROUP') ?: define('ATOL_KKT_GROUP', 'v4-online-atol-ru_4179');
|
||||||
|
defined('ATOL_KKT_LOGIN') ?: define('ATOL_KKT_LOGIN', 'v4-online-atol-ru');
|
||||||
|
defined('ATOL_KKT_PASS') ?: define('ATOL_KKT_PASS', 'iGFFuihss');
|
||||||
|
defined('ATOL_CALLBACK_URL') ?: define('ATOL_CALLBACK_URL', 'http://example.com/callback');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param AtolOnline\Entities\AtolEntity $entity
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function checkAtolEntity(AtolEntity $entity)
|
||||||
|
{
|
||||||
|
$this->assertJson((string)$entity);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function tearDown(): void
|
||||||
|
{
|
||||||
|
|
||||||
|
//parent::tearDown();
|
||||||
|
}
|
||||||
|
}
|
178
tests/Feature/ItemTest.php
Normal file
178
tests/Feature/ItemTest.php
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
use AtolOnline\{Constants\PaymentMethods,
|
||||||
|
Constants\PaymentObjects,
|
||||||
|
Constants\VatTypes,
|
||||||
|
Entities\Item,
|
||||||
|
Exceptions\AtolNameTooLongException,
|
||||||
|
Exceptions\AtolPriceTooHighException,
|
||||||
|
Exceptions\AtolQuantityTooHighException,
|
||||||
|
Exceptions\AtolUnitTooLongException,
|
||||||
|
Exceptions\AtolUserdataTooLongException
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ItemTest
|
||||||
|
*/
|
||||||
|
class ItemTest extends BasicTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Тестирует установку параметров через конструктор
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
|
||||||
|
*/
|
||||||
|
public function testConstructor()
|
||||||
|
{
|
||||||
|
$item = new Item(
|
||||||
|
'Банан',
|
||||||
|
65.99,
|
||||||
|
2.74,
|
||||||
|
'кг',
|
||||||
|
VatTypes::NONE,
|
||||||
|
PaymentObjects::COMMODITY,
|
||||||
|
PaymentMethods::FULL_PAYMENT
|
||||||
|
);
|
||||||
|
$this->checkAtolEntity($item);
|
||||||
|
$this->assertEquals('Банан', $item->getName());
|
||||||
|
$this->assertEquals(65.99, $item->getPrice());
|
||||||
|
$this->assertEquals(2.74, $item->getQuantity());
|
||||||
|
$this->assertEquals('кг', $item->getMeasurementUnit());
|
||||||
|
$this->assertEquals(VatTypes::NONE, $item->getVat()->getType());
|
||||||
|
$this->assertEquals(PaymentObjects::COMMODITY, $item->getPaymentObject());
|
||||||
|
$this->assertEquals(PaymentMethods::FULL_PAYMENT, $item->getPaymentMethod());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует установку параметров через сеттеры
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolUserdataTooLongException
|
||||||
|
*/
|
||||||
|
public function testSetters()
|
||||||
|
{
|
||||||
|
$item = new Item();
|
||||||
|
$item->setName('Банан');
|
||||||
|
$item->setPrice(65.99);
|
||||||
|
$item->setQuantity(2.74);
|
||||||
|
$item->setMeasurementUnit('кг');
|
||||||
|
$item->setVatType(VatTypes::NONE);
|
||||||
|
$item->setPaymentObject(PaymentObjects::COMMODITY);
|
||||||
|
$item->setPaymentMethod(PaymentMethods::FULL_PAYMENT);
|
||||||
|
$item->setUserData('Some user data');
|
||||||
|
$this->checkAtolEntity($item);
|
||||||
|
$this->assertEquals('Банан', $item->getName());
|
||||||
|
$this->assertEquals(65.99, $item->getPrice());
|
||||||
|
$this->assertEquals(2.74, $item->getQuantity());
|
||||||
|
$this->assertEquals('кг', $item->getMeasurementUnit());
|
||||||
|
$this->assertEquals(VatTypes::NONE, $item->getVat()->getType());
|
||||||
|
$this->assertEquals(PaymentObjects::COMMODITY, $item->getPaymentObject());
|
||||||
|
$this->assertEquals(PaymentMethods::FULL_PAYMENT, $item->getPaymentMethod());
|
||||||
|
$this->assertEquals('Some user data', $item->getUserData());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует установку ставки НДС разными путями
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
|
||||||
|
*/
|
||||||
|
public function testSetVat()
|
||||||
|
{
|
||||||
|
$item = new Item();
|
||||||
|
$item->setVatType(VatTypes::NONE);
|
||||||
|
$this->assertEquals(VatTypes::NONE, $item->getVat()->getType());
|
||||||
|
$item->setVatType(VatTypes::VAT20);
|
||||||
|
$this->assertEquals(VatTypes::VAT20, $item->getVat()->getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о слишком длинном наименовании
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
|
||||||
|
*/
|
||||||
|
public function testAtolNameTooLongException()
|
||||||
|
{
|
||||||
|
$item = new Item();
|
||||||
|
$this->expectException(AtolNameTooLongException::class);
|
||||||
|
$item->setName('Банан Банан Банан Банан Банан Банан Банан Банан Банан Банан Банан Банан');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о слишком высоком количестве
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
|
||||||
|
*/
|
||||||
|
public function testAtolQuantityTooHighException()
|
||||||
|
{
|
||||||
|
$item = new Item();
|
||||||
|
$this->expectException(AtolQuantityTooHighException::class);
|
||||||
|
$item->setQuantity(100000.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о слишком высокой цене
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
|
||||||
|
*/
|
||||||
|
public function testAtolPriceTooHighException()
|
||||||
|
{
|
||||||
|
$item = new Item();
|
||||||
|
$this->expectException(AtolPriceTooHighException::class);
|
||||||
|
$item->setPrice(42949673.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о слишком длинных польз. данных
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolUserdataTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
|
||||||
|
*/
|
||||||
|
public function testAtolUserdataTooLongException()
|
||||||
|
{
|
||||||
|
$item = new Item();
|
||||||
|
$this->expectException(AtolUserdataTooLongException::class);
|
||||||
|
$item->setUserData('User data User data User data User data User data User data User data');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о слишком длинной единице измерения
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
|
||||||
|
*/
|
||||||
|
public function testAtolUnitTooLongException()
|
||||||
|
{
|
||||||
|
$item = new Item();
|
||||||
|
$this->expectException(AtolUnitTooLongException::class);
|
||||||
|
$item->setMeasurementUnit('кг кг кг кг кг кг кг кг кг ');
|
||||||
|
}
|
||||||
|
}
|
131
tests/Unit/ClientTest.php
Normal file
131
tests/Unit/ClientTest.php
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
use AtolOnline\{Entities\Client,
|
||||||
|
Exceptions\AtolEmailTooLongException,
|
||||||
|
Exceptions\AtolEmailValidateException,
|
||||||
|
Exceptions\AtolInnWrongLengthException,
|
||||||
|
Exceptions\AtolNameTooLongException,
|
||||||
|
Exceptions\AtolPhoneTooLongException
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ClientTest
|
||||||
|
*/
|
||||||
|
class ClientTest extends BasicTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Тестирует установку параметров
|
||||||
|
*
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
*/
|
||||||
|
public function testConstructor()
|
||||||
|
{
|
||||||
|
$customer = new Client(
|
||||||
|
'John Doe',
|
||||||
|
'+1/22/99*73s dsdas654 5s6', // +122997365456
|
||||||
|
'john@example.com',
|
||||||
|
'+fasd3\qe3fs_=nac99013928czc' // 3399013928
|
||||||
|
);
|
||||||
|
$this->checkAtolEntity($customer);
|
||||||
|
$this->assertEquals('John Doe', $customer->getName());
|
||||||
|
$this->assertEquals('+122997365456', $customer->getPhone());
|
||||||
|
$this->assertEquals('john@example.com', $customer->getEmail());
|
||||||
|
$this->assertEquals('3399013928', $customer->getInn());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о слишком длинном имени
|
||||||
|
*
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
*/
|
||||||
|
public function testAtolNameTooLongException()
|
||||||
|
{
|
||||||
|
$customer = new Client();
|
||||||
|
$this->expectException(AtolNameTooLongException::class);
|
||||||
|
$customer->setName('John Doe John Doe John Doe John Doe John Doe '.
|
||||||
|
'John Doe John Doe John Doe John Doe John Doe John Doe John Doe John '.
|
||||||
|
'Doe John Doe John Doe John Doe John DoeJohn Doe John Doe John Doe '.
|
||||||
|
'John Doe John Doe John Doe John Doe John Doe John Doe John Doe John '.
|
||||||
|
'Doe John Doe John Doe John Doe John Doe John Doe John Doe');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о слишком длинном телефоне
|
||||||
|
*
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
*/
|
||||||
|
public function testAtolPhoneTooLongException()
|
||||||
|
{
|
||||||
|
$customer = new Client();
|
||||||
|
$this->expectException(AtolPhoneTooLongException::class);
|
||||||
|
$customer->setPhone('99999999999999999999999999999999999999999999999999999999999999999999999999');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о слишком длинной почте
|
||||||
|
*
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
*/
|
||||||
|
public function testAtolEmailTooLongException()
|
||||||
|
{
|
||||||
|
$customer = new Client();
|
||||||
|
$this->expectException(AtolEmailTooLongException::class);
|
||||||
|
$customer->setEmail('johnjohnjohnjohnjohnjohndoedoedoedoe@exampleexampleexampleexample.com');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о некорректной почте
|
||||||
|
*
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
*/
|
||||||
|
public function testAtolEmailValidateException()
|
||||||
|
{
|
||||||
|
$customer = new Client();
|
||||||
|
$this->expectException(AtolEmailValidateException::class);
|
||||||
|
$customer->setEmail('John Doe');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о некорректной длине ИНН
|
||||||
|
*
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||||
|
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
|
||||||
|
*/
|
||||||
|
public function testAtolInnWrongLengthException()
|
||||||
|
{
|
||||||
|
$company = new Client();
|
||||||
|
$this->expectException(AtolInnWrongLengthException::class);
|
||||||
|
$company->setInn('123456789');
|
||||||
|
$company->setInn('1234567890123');
|
||||||
|
}
|
||||||
|
}
|
110
tests/Unit/CompanyTest.php
Normal file
110
tests/Unit/CompanyTest.php
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
use AtolOnline\{Constants\SnoTypes,
|
||||||
|
Entities\Company,
|
||||||
|
Exceptions\AtolEmailTooLongException,
|
||||||
|
Exceptions\AtolEmailValidateException,
|
||||||
|
Exceptions\AtolInnWrongLengthException,
|
||||||
|
Exceptions\AtolPaymentAddressTooLongException
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CompanyTest
|
||||||
|
*/
|
||||||
|
class CompanyTest extends BasicTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Тестирует установку параметров через конструктор
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPaymentAddressTooLongException
|
||||||
|
*/
|
||||||
|
public function testConstructor()
|
||||||
|
{
|
||||||
|
$company = new Company(
|
||||||
|
SnoTypes::OSN,
|
||||||
|
'5544332219',
|
||||||
|
'https://v4.online.atol.ru',
|
||||||
|
'company@example.com'
|
||||||
|
);
|
||||||
|
$this->checkAtolEntity($company);
|
||||||
|
$this->assertEquals(SnoTypes::OSN, $company->getSno());
|
||||||
|
$this->assertEquals('5544332219', $company->getInn());
|
||||||
|
$this->assertEquals('https://v4.online.atol.ru', $company->getPaymentAddress());
|
||||||
|
$this->assertEquals('company@example.com', $company->getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о некорректной длине ИНН
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPaymentAddressTooLongException
|
||||||
|
*/
|
||||||
|
public function testAtolInnWrongLengthException()
|
||||||
|
{
|
||||||
|
$company = new Company();
|
||||||
|
$this->expectException(AtolInnWrongLengthException::class);
|
||||||
|
$company->setInn('321');
|
||||||
|
$company->setInn('1234567890123');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о слишком длинном платёжном адресе
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPaymentAddressTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
*/
|
||||||
|
public function testAtolPaymentAddressTooLongException()
|
||||||
|
{
|
||||||
|
$company = new Company();
|
||||||
|
$this->expectException(AtolPaymentAddressTooLongException::class);
|
||||||
|
$company->setPaymentAddress('John Doe John Doe John Doe John Doe '.
|
||||||
|
'John Doe John Doe John Doe John Doe John Doe John Doe John Doe John Doe John '.
|
||||||
|
'Doe John Doe John Doe John Doe John DoeJohn Doe John Doe John Doe John Doe '.
|
||||||
|
'John Doe John Doe John Doe John Doe John Doe John Doe John Doe John Doe John '.
|
||||||
|
'Doe John Doe John Doe John Doe John Doe');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о слишком длинной почте
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPaymentAddressTooLongException
|
||||||
|
*/
|
||||||
|
public function testAtolEmailTooLongException()
|
||||||
|
{
|
||||||
|
$company = new Company();
|
||||||
|
$this->expectException(AtolEmailTooLongException::class);
|
||||||
|
$company->setEmail('johnjohnjohnjohnjohnjohndoedoedoedoe@exampleexampleexampleexample.com');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тестирует исключение о некорректной почте
|
||||||
|
*
|
||||||
|
* @throws AtolOnline\Exceptions\AtolEmailValidateException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolEmailTooLongException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||||
|
* @throws AtolOnline\Exceptions\AtolPaymentAddressTooLongException
|
||||||
|
*/
|
||||||
|
public function testAtolEmailValidateException()
|
||||||
|
{
|
||||||
|
$company = new Company();
|
||||||
|
$this->expectException(AtolEmailValidateException::class);
|
||||||
|
$company->setEmail('John Doe');
|
||||||
|
}
|
||||||
|
}
|
51
tests/Unit/VatTest.php
Normal file
51
tests/Unit/VatTest.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||||
|
*
|
||||||
|
* This code is licensed under MIT.
|
||||||
|
* Этот код распространяется по лицензии MIT.
|
||||||
|
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
use AtolOnline\{Constants\VatTypes, Entities\Vat};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class VatTest
|
||||||
|
*/
|
||||||
|
class VatTest extends BasicTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Тестирует каждый тип ставки НДС
|
||||||
|
*
|
||||||
|
* @dataProvider vatProvider
|
||||||
|
* @param string $vat_type Тип НДС
|
||||||
|
* @param float $sum Исходная сумма
|
||||||
|
* @param float $expected_set Ожидаемый результат после установки суммы
|
||||||
|
* @param float $expected_add Ожидаемый результат после прибавления 20р
|
||||||
|
*/
|
||||||
|
public function testVat(string $vat_type, float $sum, float $expected_set, float $expected_add)
|
||||||
|
{
|
||||||
|
$vat = new Vat($vat_type);
|
||||||
|
$this->assertEquals(0, $vat->getFinalSum(), 'Test '.$vat_type.' | 1 step');
|
||||||
|
$vat->setSum($sum);
|
||||||
|
$this->assertEquals($expected_set, $vat->getFinalSum(), 'Test '.$vat_type.' | 2 step');
|
||||||
|
$vat->addSum(20);
|
||||||
|
$this->assertEquals($expected_add, $vat->getFinalSum(), 'Test '.$vat_type.' | 3 step');
|
||||||
|
$vat->addSum(-20);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Провайдер данных для тестирования разных типов ставок НДС
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function vatProvider()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[VatTypes::NONE, 100, 0, 0],
|
||||||
|
[VatTypes::VAT0, 100, 0, 0],
|
||||||
|
[VatTypes::VAT10, 100, 10, 12],
|
||||||
|
[VatTypes::VAT18, 100, 18, 21.6],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user