16 Commits

Author SHA1 Message Date
ca32fe5923 Повсюду улучшена проверка длин строк 2020-05-28 22:56:26 +08:00
9ea1c81666 Скорректирован Document::jsonSerialize() - не выдаёт пустого кассира 2020-05-28 22:55:53 +08:00
12b98dcdac Document::fromRaw() теперь парсит входящий json как массив, а не объект 2020-05-28 22:55:27 +08:00
1fec446ce0 Фикс тестов НДС 2020-05-28 01:31:37 +08:00
6256c14522 Обновления в composer.lock 2020-05-28 01:25:27 +08:00
7dff642f0a Бейджик в readme + фикс composer.json 2020-05-28 01:14:53 +08:00
670f440620 Github actions только на мастере 2020-05-28 01:13:08 +08:00
3385420005 Merge branch 'dev'. Мнда, я забыл слить изменения... 2020-05-28 00:56:31 +08:00
ff42eebb8c [RELEASE] v0.2.1-b 2020-05-28 00:53:18 +08:00
9121d44a26 Merge branch 'master' into dev 2020-05-28 00:43:28 +08:00
600a505c83 Генерация объекта документа по сырой json-строке 2020-05-28 00:41:58 +08:00
4fccf7809d Небольшие правки по Item (улучшена проверка длины ед. изм.) 2020-05-28 00:41:01 +08:00
2d29ff3994 Фикс исключения некорректного UUID в методе Kkt::getDocumentStatus() 2020-05-28 00:39:42 +08:00
954843e3ad Фикс исключения превышения количества ставок НДС в массиве 2020-05-28 00:38:48 +08:00
a619b06a48 Исправлен расчёт НДС для документа 2020-05-28 00:38:16 +08:00
0bb194b1f8 Улучшены исключения
- добавлены теги ФФД для удобства
- тексты исключений переведены на англ. язык во избежание проблем с кодировками
- новые исключения TooMany и TooLong для удобства, подходящие по смыслу исключения унаследованы от них
2020-05-27 23:10:30 +08:00
38 changed files with 632 additions and 343 deletions

View File

@@ -1,6 +1,9 @@
name: Composer and phpunit tests name: Build
on: [push] on:
push:
branches:
- master
jobs: jobs:
build: build:

View File

@@ -1,5 +1,7 @@
# АТОЛ Онлайн # АТОЛ Онлайн
![Build](https://github.com/anthonyaxenov/atol-online/workflows/Build/badge.svg?branch=master)
Библиотека для фискализации чеков по 54-ФЗ через [облачную ККТ АТОЛ](https://online.atol.ru/). Библиотека для фискализации чеков по 54-ФЗ через [облачную ККТ АТОЛ](https://online.atol.ru/).
Текущая поддерживаемая версия API: **5.1** Текущая поддерживаемая версия API: **5.1**

View File

@@ -3,9 +3,14 @@
"description": "Library to use cloud cash register in e-commerce according to Russian Federal Law #54", "description": "Library to use cloud cash register in e-commerce according to Russian Federal Law #54",
"license": "MIT", "license": "MIT",
"type": "library", "type": "library",
"version": "0.1.1-b",
"keywords": [ "keywords": [
"54-fz", "54-fz",
"kkt",
"e-commerce",
"cash",
"cash register",
"payment",
"payment system",
"atol", "atol",
"atol-online" "atol-online"
], ],

239
composer.lock generated
View File

@@ -4,27 +4,28 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "dae801b00d2c80c28d290f676970945b", "content-hash": "20b642fe60192cf1e67c9aa8dca27440",
"packages": [ "packages": [
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
"version": "6.5.2", "version": "6.5.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/guzzle.git", "url": "https://github.com/guzzle/guzzle.git",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82" "reference": "a4a1b6930528a8f7ee03518e6442ec7a44155d9d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a4a1b6930528a8f7ee03518e6442ec7a44155d9d",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82", "reference": "a4a1b6930528a8f7ee03518e6442ec7a44155d9d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"guzzlehttp/promises": "^1.0", "guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.6.1", "guzzlehttp/psr7": "^1.6.1",
"php": ">=5.5" "php": ">=5.5",
"symfony/polyfill-intl-idn": "1.17.0"
}, },
"require-dev": { "require-dev": {
"ext-curl": "*", "ext-curl": "*",
@@ -32,7 +33,6 @@
"psr/log": "^1.1" "psr/log": "^1.1"
}, },
"suggest": { "suggest": {
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware" "psr/log": "Required for using the Log middleware"
}, },
"type": "library", "type": "library",
@@ -71,7 +71,7 @@
"rest", "rest",
"web service" "web service"
], ],
"time": "2019-12-23T11:57:10+00:00" "time": "2020-05-25T19:35:05+00:00"
}, },
{ {
"name": "guzzlehttp/promises", "name": "guzzlehttp/promises",
@@ -466,16 +466,16 @@
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.15.0", "version": "v1.17.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git", "url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -487,7 +487,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.15-dev" "dev-master": "1.17-dev"
} }
}, },
"autoload": { "autoload": {
@@ -520,7 +520,183 @@
"polyfill", "polyfill",
"portable" "portable"
], ],
"time": "2020-02-27T09:26:54+00:00" "time": "2020-05-12T16:14:59+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "3bff59ea7047e925be6b7f2059d60af31bb46d6a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/3bff59ea7047e925be6b7f2059d60af31bb46d6a",
"reference": "3bff59ea7047e925be6b7f2059d60af31bb46d6a",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-php72": "^1.10"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.17-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Idn\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Laurent Bassin",
"email": "laurent@bassin.info"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"idn",
"intl",
"polyfill",
"portable",
"shim"
],
"time": "2020-05-12T16:47:27+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c",
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.17-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2020-05-12T16:47:27+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "f048e612a3905f34931127360bdd2def19a5e582"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/f048e612a3905f34931127360bdd2def19a5e582",
"reference": "f048e612a3905f34931127360bdd2def19a5e582",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.17-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"time": "2020-05-12T16:47:27+00:00"
} }
], ],
"packages-dev": [ "packages-dev": [
@@ -732,24 +908,21 @@
}, },
{ {
"name": "phpdocumentor/reflection-common", "name": "phpdocumentor/reflection-common",
"version": "2.0.0", "version": "2.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1" "php": ">=7.1"
}, },
"require-dev": {
"phpunit/phpunit": "~6"
},
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
@@ -780,7 +953,7 @@
"reflection", "reflection",
"static analysis" "static analysis"
], ],
"time": "2018-08-07T13:53:10+00:00" "time": "2020-04-27T09:25:28+00:00"
}, },
{ {
"name": "phpdocumentor/reflection-docblock", "name": "phpdocumentor/reflection-docblock",
@@ -1198,16 +1371,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "8.5.3", "version": "8.5.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "67750516bc02f300e2742fed2f50177f8f37bedf" "reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/67750516bc02f300e2742fed2f50177f8f37bedf", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/63dda3b212a0025d380a745f91bdb4d8c985adb7",
"reference": "67750516bc02f300e2742fed2f50177f8f37bedf", "reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1277,7 +1450,7 @@
"testing", "testing",
"xunit" "xunit"
], ],
"time": "2020-03-31T08:52:04+00:00" "time": "2020-05-22T13:51:52+00:00"
}, },
{ {
"name": "sebastian/code-unit-reverse-lookup", "name": "sebastian/code-unit-reverse-lookup",
@@ -1936,16 +2109,16 @@
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
"version": "1.7.0", "version": "1.8.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/webmozart/assert.git", "url": "https://github.com/webmozart/assert.git",
"reference": "aed98a490f9a8f78468232db345ab9cf606cf598" "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598", "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"reference": "aed98a490f9a8f78468232db345ab9cf606cf598", "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1953,7 +2126,7 @@
"symfony/polyfill-ctype": "^1.8" "symfony/polyfill-ctype": "^1.8"
}, },
"conflict": { "conflict": {
"vimeo/psalm": "<3.6.0" "vimeo/psalm": "<3.9.1"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.8.36 || ^7.5.13" "phpunit/phpunit": "^4.8.36 || ^7.5.13"
@@ -1980,7 +2153,7 @@
"check", "check",
"validate" "validate"
], ],
"time": "2020-02-14T12:15:55+00:00" "time": "2020-04-18T12:12:48+00:00"
} }
], ],
"aliases": [], "aliases": [],

View File

@@ -11,10 +11,10 @@ namespace AtolOnline\Api;
use AtolOnline\{Entities\Document, use AtolOnline\{Entities\Document,
Exceptions\AtolCorrectionInfoException, Exceptions\AtolCorrectionInfoException,
Exceptions\AtolInvalidUuidException,
Exceptions\AtolKktLoginEmptyException, Exceptions\AtolKktLoginEmptyException,
Exceptions\AtolKktLoginTooLongException, Exceptions\AtolKktLoginTooLongException,
Exceptions\AtolKktPasswordEmptyException, Exceptions\AtolKktPasswordEmptyException,
Exceptions\AtolUuidValidateException,
Exceptions\AtolWrongDocumentTypeException Exceptions\AtolWrongDocumentTypeException
}; };
use GuzzleHttp\Client; use GuzzleHttp\Client;
@@ -118,7 +118,7 @@ class Kkt extends Client
if (!$this->isTestMode()) { if (!$this->isTestMode()) {
if (empty($login)) { if (empty($login)) {
throw new AtolKktLoginEmptyException(); throw new AtolKktLoginEmptyException();
} elseif (strlen($login) > 100) { } elseif ((function_exists('mb_strlen') ? mb_strlen($login) : strlen($login)) > 100) {
throw new AtolKktLoginTooLongException($login, 100); throw new AtolKktLoginTooLongException($login, 100);
} }
} }
@@ -327,13 +327,13 @@ class Kkt extends Client
* *
* @param string $uuid UUID регистрации * @param string $uuid UUID регистрации
* @return \AtolOnline\Api\KktResponse * @return \AtolOnline\Api\KktResponse
* @throws \AtolOnline\Exceptions\AtolUuidValidateException Некорректный UUID документа * @throws \AtolOnline\Exceptions\AtolInvalidUuidException Некорректный UUID документа
*/ */
public function getDocumentStatus(string $uuid) public function getDocumentStatus(string $uuid)
{ {
$uuid = trim($uuid); $uuid = trim($uuid);
if (!Uuid::isValid($uuid)) { if (!Uuid::isValid($uuid)) {
throw new AtolUuidValidateException($uuid); throw new AtolInvalidUuidException($uuid);
} }
$this->auth(); $this->auth();
return $this->sendAtolRequest('GET', 'report/'.$uuid); return $this->sendAtolRequest('GET', 'report/'.$uuid);

View File

@@ -89,7 +89,7 @@ class Client extends Entity
public function setName(string $name) public function setName(string $name)
{ {
$name = trim($name); $name = trim($name);
if (strlen($name) > 256) { if ((function_exists('mb_strlen') ? mb_strlen($name) : strlen($name)) > 256) {
throw new AtolNameTooLongException($name, 256); throw new AtolNameTooLongException($name, 256);
} }
$this->name = $name; $this->name = $name;
@@ -119,7 +119,7 @@ class Client extends Entity
public function setPhone(string $phone) public function setPhone(string $phone)
{ {
$phone = preg_replace("/[^0-9+]/", '', $phone); $phone = preg_replace("/[^0-9+]/", '', $phone);
if (strlen($phone) > 64) { if ((function_exists('mb_strlen') ? mb_strlen($phone) : strlen($phone)) > 64) {
throw new AtolPhoneTooLongException($phone, 64); throw new AtolPhoneTooLongException($phone, 64);
} }
$this->phone = $phone; $this->phone = $phone;

View File

@@ -115,7 +115,7 @@ class Company extends Entity
public function setPaymentAddress(string $payment_address) public function setPaymentAddress(string $payment_address)
{ {
$payment_address = trim($payment_address); $payment_address = trim($payment_address);
if (strlen($payment_address) > 256) { if ((function_exists('mb_strlen') ? mb_strlen($payment_address) : strlen($payment_address)) > 256) {
throw new AtolPaymentAddressTooLongException($payment_address, 256); throw new AtolPaymentAddressTooLongException($payment_address, 256);
} }
$this->payment_address = $payment_address; $this->payment_address = $payment_address;

View File

@@ -10,6 +10,8 @@
namespace AtolOnline\Entities; namespace AtolOnline\Entities;
use AtolOnline\Exceptions\AtolCashierTooLongException; use AtolOnline\Exceptions\AtolCashierTooLongException;
use AtolOnline\Exceptions\AtolException;
use AtolOnline\Exceptions\AtolInvalidJsonException;
/** /**
* Класс, описывающий документ * Класс, описывающий документ
@@ -60,10 +62,6 @@ class Document extends Entity
/** /**
* Document constructor. * Document constructor.
*
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
* @throws \AtolOnline\Exceptions\AtolTooManyPaymentsException Слишком много оплат
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
*/ */
public function __construct() public function __construct()
{ {
@@ -82,10 +80,6 @@ class Document extends Entity
public function clearVats() public function clearVats()
{ {
$this->setVats([]); $this->setVats([]);
foreach ($this->getItems() as &$item) {
$item->setVatType(null);
}
$this->calcTotal();
return $this; return $this;
} }
@@ -98,11 +92,7 @@ class Document extends Entity
*/ */
public function addVat(Vat $vat) public function addVat(Vat $vat)
{ {
if (count($this->getVats()) == 0 && !$vat->getSum()) {
$vat->setSum($this->calcTotal());
}
$this->vats->add($vat); $this->vats->add($vat);
$this->calcTotal();
return $this; return $this;
} }
@@ -127,7 +117,6 @@ class Document extends Entity
public function setVats(array $vats) public function setVats(array $vats)
{ {
$this->vats->set($vats); $this->vats->set($vats);
$this->calcTotal();
return $this; return $this;
} }
@@ -271,8 +260,8 @@ class Document extends Entity
public function setCashier(?string $cashier) public function setCashier(?string $cashier)
{ {
$cashier = trim($cashier); $cashier = trim($cashier);
if (strlen($cashier) > 64) { if ((function_exists('mb_strlen') ? mb_strlen($cashier) : strlen($cashier)) > 64) {
throw new AtolCashierTooLongException($cashier); throw new AtolCashierTooLongException($cashier, 64);
} }
$this->cashier = $cashier; $this->cashier = $cashier;
return $this; return $this;
@@ -309,11 +298,10 @@ class Document extends Entity
public function calcTotal() public function calcTotal()
{ {
$sum = 0; $sum = 0;
$this->clearVats();
foreach ($this->items->get() as $item) { foreach ($this->items->get() as $item) {
$sum += $item->calcSum(); $sum += $item->calcSum();
} $this->addVat(new Vat($item->getVat()->getType(), $item->getSum()));
foreach ($this->vats->get() as $vat) {
$vat->setSum($sum);
} }
return $this->total = round($sum, 2); return $this->total = round($sum, 2);
} }
@@ -329,16 +317,95 @@ class Document extends Entity
} }
/** /**
* @inheritDoc * Собирает объект документа из сырой json-строки
*
* @param string $json
* @return \AtolOnline\Entities\Document
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
* @throws \AtolOnline\Exceptions\AtolException
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
* @throws \AtolOnline\Exceptions\AtolInvalidJsonException
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
* @throws \AtolOnline\Exceptions\AtolTooManyException
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException
* @throws \AtolOnline\Exceptions\AtolTooManyPaymentsException
* @throws \AtolOnline\Exceptions\AtolUnitTooLongException
* @throws \AtolOnline\Exceptions\AtolUserdataTooLongException
*/
public static function fromRaw(string $json)
{
$array = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new AtolInvalidJsonException();
}
$doc = new self();
if (isset($array['company'])) {
$doc->setCompany(new Company(
$array['company']['sno'] ?? null,
$array['company']['inn'] ?? null,
$array['company']['payment_address'] ?? null,
$array['company']['email'] ?? null
));
}
if (isset($array['client'])) {
$doc->setClient(new Client(
$array['client']['name'] ?? null,
$array['client']['phone'] ?? null,
$array['client']['email'] ?? null,
$array['client']['inn'] ?? null
));
}
if (isset($array['items'])) {
foreach ($array['items'] as $ar_item) {
$item = new Item(
$ar_item['name'] ?? null,
$ar_item['price'] ?? null,
$ar_item['quantity'] ?? null,
$ar_item['measurement_unit'] ?? null,
$ar_item['vat']['type'] ?? null,
$ar_item['payment_object'] ?? null,
$ar_item['payment_method'] ?? null
);
if (!empty($ar_item['user_data'])) {
$item->setUserData($ar_item['user_data'] ?? null);
}
$doc->addItem($item);
}
}
if (isset($array['payments'])) {
foreach ($array['payments'] as $ar_payment) {
$payment = new Payment();
if (isset($ar_payment['type'])) {
$payment->setType($ar_payment['type']);
}
if (isset($ar_payment['sum'])) {
$payment->setSum($ar_payment['sum']);
}
$doc->payments->add($payment);
}
}
if ($array['total'] != $doc->calcTotal()) {
throw new AtolException('Real total sum not equals to provided in JSON one');
}
return $doc;
}
/**
* Возвращает массив для кодирования в json
*
* @throws \Exception * @throws \Exception
*/ */
public function jsonSerialize() public function jsonSerialize()
{ {
$json = [ $json['company'] = $this->getCompany()->jsonSerialize();// обязательно
'company' => $this->getCompany()->jsonSerialize(), // обязательно $json['payments'] = $this->payments->jsonSerialize(); // обязательно
'payments' => $this->payments->jsonSerialize(), // обязательно if ($this->getCashier()) {
'cashier' => $this->getCashier() ?? '', $json['cashier'] = $this->getCashier();
]; }
if ($this->getCorrectionInfo()) { if ($this->getCorrectionInfo()) {
$json['correction_info'] = $this->getCorrectionInfo()->jsonSerialize(); // обязательно для коррекционных $json['correction_info'] = $this->getCorrectionInfo()->jsonSerialize(); // обязательно для коррекционных
} else { } else {

View File

@@ -11,11 +11,10 @@ namespace AtolOnline\Entities;
use AtolOnline\{Exceptions\AtolNameTooLongException, use AtolOnline\{Exceptions\AtolNameTooLongException,
Exceptions\AtolPriceTooHighException, Exceptions\AtolPriceTooHighException,
Exceptions\AtolQuantityTooHighException, Exceptions\AtolTooManyException,
Exceptions\AtolUnitTooLongException, Exceptions\AtolUnitTooLongException,
Exceptions\AtolUserdataTooLongException, Exceptions\AtolUserdataTooLongException,
Traits\RublesKopeksConverter Traits\RublesKopeksConverter};
};
/** /**
* Предмет расчёта (товар, услуга) * Предмет расчёта (товар, услуга)
@@ -83,7 +82,7 @@ class Item extends Entity
* @param string|null $payment_method Способ расчёта * @param string|null $payment_method Способ расчёта
* @throws AtolNameTooLongException Слишком длинное наименование * @throws AtolNameTooLongException Слишком длинное наименование
* @throws AtolPriceTooHighException Слишком высокая цена за одну единицу * @throws AtolPriceTooHighException Слишком высокая цена за одну единицу
* @throws AtolQuantityTooHighException Слишком большое количество * @throws AtolTooManyException Слишком большое количество
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения * @throws AtolUnitTooLongException Слишком длинное название единицы измерения
*/ */
public function __construct( public function __construct(
@@ -101,17 +100,17 @@ class Item extends Entity
if ($price) { if ($price) {
$this->setPrice($price); $this->setPrice($price);
} }
if ($payment_object) {
$this->setPaymentObject($payment_object);
}
if ($quantity) { if ($quantity) {
$this->setQuantity($quantity); $this->setQuantity($quantity);
} }
if ($measurement_unit) {
$this->setMeasurementUnit($measurement_unit);
}
if ($vat_type) { if ($vat_type) {
$this->setVatType($vat_type); $this->setVatType($vat_type);
} }
if ($measurement_unit) { if ($payment_object) {
$this->setMeasurementUnit($measurement_unit); $this->setPaymentObject($payment_object);
} }
if ($payment_method) { if ($payment_method) {
$this->setPaymentMethod($payment_method); $this->setPaymentMethod($payment_method);
@@ -138,7 +137,7 @@ class Item extends Entity
public function setName(string $name) public function setName(string $name)
{ {
$name = trim($name); $name = trim($name);
if (strlen($name) > 128) { if ((function_exists('mb_strlen') ? mb_strlen($name) : strlen($name)) > 128) {
throw new AtolNameTooLongException($name, 128); throw new AtolNameTooLongException($name, 128);
} }
$this->name = $name; $this->name = $name;
@@ -188,7 +187,7 @@ class Item extends Entity
* @param float $quantity Количество * @param float $quantity Количество
* @param string|null $measurement_unit Единица измерения количества * @param string|null $measurement_unit Единица измерения количества
* @return $this * @return $this
* @throws AtolQuantityTooHighException Слишком большое количество * @throws AtolTooManyException Слишком большое количество
* @throws AtolPriceTooHighException Слишком высокая общая стоимость * @throws AtolPriceTooHighException Слишком высокая общая стоимость
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения * @throws AtolUnitTooLongException Слишком длинное название единицы измерения
*/ */
@@ -196,7 +195,7 @@ class Item extends Entity
{ {
$quantity = round($quantity, 3); $quantity = round($quantity, 3);
if ($quantity > 99999.999) { if ($quantity > 99999.999) {
throw new AtolQuantityTooHighException($quantity, 99999.999); throw new AtolTooManyException($quantity, 99999.999);
} }
$this->quantity = $quantity; $this->quantity = $quantity;
$this->calcSum(); $this->calcSum();
@@ -226,7 +225,7 @@ class Item extends Entity
public function setMeasurementUnit(string $measurement_unit) public function setMeasurementUnit(string $measurement_unit)
{ {
$measurement_unit = trim($measurement_unit); $measurement_unit = trim($measurement_unit);
if (strlen($measurement_unit) > 16) { if ((function_exists('mb_strlen') ? mb_strlen($measurement_unit) : strlen($measurement_unit)) > 16) {
throw new AtolUnitTooLongException($measurement_unit, 16); throw new AtolUnitTooLongException($measurement_unit, 16);
} }
$this->measurement_unit = $measurement_unit; $this->measurement_unit = $measurement_unit;
@@ -329,7 +328,7 @@ class Item extends Entity
public function setUserData(string $user_data) public function setUserData(string $user_data)
{ {
$user_data = trim($user_data); $user_data = trim($user_data);
if (strlen($user_data) > 64) { if ((function_exists('mb_strlen') ? mb_strlen($user_data) : strlen($user_data)) > 64) {
throw new AtolUserdataTooLongException($user_data, 64); throw new AtolUserdataTooLongException($user_data, 64);
} }
$this->user_data = $user_data; $this->user_data = $user_data;

View File

@@ -26,12 +26,12 @@ class Vat extends Entity
private $type; private $type;
/** /**
* @var int Сумма в копейках, от которой пересчитывается размер налога * @var int Сумма в копейках, от которой пересчитывается размер НДС
*/ */
private $sum_original = 0; private $sum_original = 0;
/** /**
* @var int Сумма налога в копейках * @var int Сумма НДС в копейках
*/ */
private $sum_final = 0; private $sum_final = 0;
@@ -66,18 +66,19 @@ class Vat extends Entity
case VatTypes::VAT0: case VatTypes::VAT0:
return 0; return 0;
case VatTypes::VAT10: case VatTypes::VAT10:
return $kopeks * 10 / 100; //return $kopeks * 10 / 100;
case VatTypes::VAT110: case VatTypes::VAT110:
return $kopeks * 10 / 110; return $kopeks * 10 / 110;
case VatTypes::VAT18: case VatTypes::VAT18:
return $kopeks * 18 / 100; //return $kopeks * 18 / 100;
case VatTypes::VAT118: case VatTypes::VAT118:
return $kopeks * 18 / 118; return $kopeks * 18 / 118;
case VatTypes::VAT20: case VatTypes::VAT20:
return $kopeks * 20 / 100; //return $kopeks * 20 / 100;
case VatTypes::VAT120: case VatTypes::VAT120:
return $kopeks * 20 / 120; return $kopeks * 20 / 120;
} }
return 0;
} }
/** /**

View File

@@ -62,7 +62,11 @@ class VatArray extends Entity
public function add(Vat $vat) public function add(Vat $vat)
{ {
if ($this->validateCount()) { if ($this->validateCount()) {
$this->vats[] = $vat; if (isset($this->vats[$vat->getType()])) {
$this->vats[$vat->getType()]->addSum($vat->getSum());
} else {
$this->vats[$vat->getType()] = $vat;
}
} }
return $this; return $this;
} }
@@ -101,7 +105,7 @@ class VatArray extends Entity
{ {
$max_items = SellSchema::get()->properties->receipt->properties->vats->maxItems; $max_items = SellSchema::get()->properties->receipt->properties->vats->maxItems;
if ((!empty($vats) && count($vats) >= $max_items) || count($this->vats) >= $max_items) { if ((!empty($vats) && count($vats) >= $max_items) || count($this->vats) >= $max_items) {
throw new AtolTooManyVatsException($max_items); throw new AtolTooManyVatsException(count($vats), $max_items);
} }
return true; return true;
} }

View File

@@ -9,26 +9,22 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать слишком длинное имя кассира * Исключение, возникающее при попытке указать слишком длинное имя кассира
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolCashierTooLongException extends AtolException class AtolCashierTooLongException extends AtolTooLongException
{ {
/** /**
* AtolCashierTooLongException constructor. * @inheritDoc
*
* @param $name
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/ */
public function __construct($name, $message = "", $code = 0, Throwable $previous = null) protected $ffd_tags = [
{ 1021,
$message = $message ?: 'Слишком длинное имя кассира (макс. длина 64, фактически '.strlen($name).'): '.$name; ];
parent::__construct($message, $code, $previous);
} /**
* @var string Сообщение об ошибке
*/
protected $message = 'Cashier name is too long';
} }

View File

@@ -9,8 +9,6 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке зарегистрировать документ без данных коррекции * Исключение, возникающее при попытке зарегистрировать документ без данных коррекции
* *
@@ -19,15 +17,7 @@ use Throwable;
class AtolCorrectionInfoException extends AtolException class AtolCorrectionInfoException extends AtolException
{ {
/** /**
* AtolNoCorrectionInfoException constructor. * @var string Сообщение об ошибке
*
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/ */
public function __construct($message = "", $code = 0, Throwable $previous = null) protected $message = 'Document must have correction info';
{
$message = $message ?: 'В документе отсутствуют данные коррекции';
parent::__construct($message, $code, $previous);
}
} }

View File

@@ -9,8 +9,6 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать пустой email * Исключение, возникающее при попытке указать пустой email
* *
@@ -19,15 +17,15 @@ use Throwable;
class AtolEmailEmptyException extends AtolException class AtolEmailEmptyException extends AtolException
{ {
/** /**
* AtolEmailEmptyException constructor. * @inheritDoc
*
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/ */
public function __construct($message = "", $code = 0, Throwable $previous = null) protected $ffd_tags = [
{ 1008,
$message = $message ?: 'Email не может быть пустым'; 1117,
parent::__construct($message, $code, $previous); ];
}
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Email cannot be empty';
} }

View File

@@ -9,27 +9,23 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать слишком длинный email * Исключение, возникающее при попытке указать слишком длинный email
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolEmailTooLongException extends AtolException class AtolEmailTooLongException extends AtolTooLongException
{ {
/** /**
* AtolEmailTooLongException constructor. * @inheritDoc
*
* @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) protected $ffd_tags = [
{ 1008,
$message = $message ?: 'Слишком длинный email (макс. длина '.$max.', фактически '.strlen($email).'): '.$email; 1117,
parent::__construct($message, $code, $previous); ];
}
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Email is is too long';
} }

View File

@@ -18,6 +18,14 @@ use Throwable;
*/ */
class AtolEmailValidateException extends AtolException class AtolEmailValidateException extends AtolException
{ {
/**
* @inheritDoc
*/
protected $ffd_tags = [
1008,
1117,
];
/** /**
* AtolEmailValidateException constructor. * AtolEmailValidateException constructor.
* *
@@ -28,7 +36,6 @@ class AtolEmailValidateException extends AtolException
*/ */
public function __construct($email, $message = "", $code = 0, Throwable $previous = null) public function __construct($email, $message = "", $code = 0, Throwable $previous = null)
{ {
$message = $message ?: 'Некорректный email: '.$email; parent::__construct($message ?: 'Invalid email: '.$email, $code, $previous);
parent::__construct($message, $code, $previous);
} }
} }

View File

@@ -10,6 +10,7 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Exception; use Exception;
use Throwable;
/** /**
* Исключение, возникающее при работе с АТОЛ Онлайн * Исключение, возникающее при работе с АТОЛ Онлайн
@@ -18,5 +19,33 @@ use Exception;
*/ */
class AtolException extends Exception class AtolException extends Exception
{ {
/**
* @var int[] Теги ФФД
*/
protected $ffd_tags = null;
/**
* AtolException constructor.
*
* @param string $message
* @param int $code
* @param \Throwable|null $previous
*/
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
if ($this->getFfdTags()) {
$message .= ' [FFD tags: '.implode(', ', $this->getFfdTags()).']';
}
parent::__construct($message, $code, $previous);
}
/**
* Возвращает теги ФФД, с которыми связано исключение
*
* @return array|null
*/
protected function getFfdTags(): ?array
{
return $this->ffd_tags;
}
} }

View File

@@ -18,6 +18,16 @@ use Throwable;
*/ */
class AtolInnWrongLengthException extends AtolException class AtolInnWrongLengthException extends AtolException
{ {
/**
* @inheritDoc
*/
protected $ffd_tags = [
1016,
1018,
1226,
1228,
];
/** /**
* AtolInnWrongLengthException constructor. * AtolInnWrongLengthException constructor.
* *
@@ -28,7 +38,7 @@ class AtolInnWrongLengthException extends AtolException
*/ */
public function __construct($inn, $message = "", $code = 0, Throwable $previous = null) public function __construct($inn, $message = "", $code = 0, Throwable $previous = null)
{ {
$message = $message ?: 'Длина ИНН должна быть 10 или 12 цифр, фактически '.strlen($inn).': '.$inn; parent::__construct($message ?: 'INN length must be 10 or 12 digits only, but actual is '.
parent::__construct($message, $code, $previous); (function_exists('mb_strlen') ? mb_strlen($inn) : strlen($inn)).')', $code, $previous);
} }
} }

View File

@@ -0,0 +1,32 @@
<?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;
/**
* Исключение, возникающее при работе с невалидным JSON
*
* @package AtolOnline\Exceptions
*/
class AtolInvalidJsonException extends AtolException
{
/**
* AtolInnWrongLengthException constructor.
*
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
parent::__construct($message ?: 'Invalid JSON: ['.json_last_error().'] '.json_last_error_msg(), $code, $previous);
}
}

View File

@@ -16,10 +16,10 @@ use Throwable;
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolUuidValidateException extends AtolException class AtolInvalidUuidException extends AtolException
{ {
/** /**
* AtolUuidValidateException constructor. * AtolInvalidUuidException constructor.
* *
* @param $uuid * @param $uuid
* @param string $message * @param string $message
@@ -28,7 +28,6 @@ class AtolUuidValidateException extends AtolException
*/ */
public function __construct($uuid, $message = "", $code = 0, Throwable $previous = null) public function __construct($uuid, $message = "", $code = 0, Throwable $previous = null)
{ {
$message = $message ?: 'Некорректный UUID: '.$uuid; parent::__construct($message ?: 'Invalid UUID: '.$uuid, $code, $previous);
parent::__construct($message, $code, $previous);
} }
} }

View File

@@ -9,8 +9,6 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать пустой логин ККТ * Исключение, возникающее при попытке указать пустой логин ККТ
* *
@@ -19,15 +17,7 @@ use Throwable;
class AtolKktLoginEmptyException extends AtolException class AtolKktLoginEmptyException extends AtolException
{ {
/** /**
* AtolKktLoginEmptyException constructor. * @var string Сообщение об ошибке
*
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/ */
public function __construct($message = "", $code = 0, Throwable $previous = null) protected $message = 'KKT login cannot be empty';
{
$message = $message ?: 'Логин ККТ не может быть пустым';
parent::__construct($message, $code, $previous);
}
} }

View File

@@ -9,27 +9,15 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать слишком длинный логин ККТ * Исключение, возникающее при попытке указать слишком длинный логин ККТ
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolKktLoginTooLongException extends AtolException class AtolKktLoginTooLongException extends AtolTooLongException
{ {
/** /**
* AtolKktLoginTooLongException constructor. * @var string Сообщение об ошибке
*
* @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) protected $message = 'KKT login is too long';
{
$message = $message ?: 'Слишком длинный логин ККТ (макс. длина '.$max.', фактически '.strlen($login).'): '.$login;
parent::__construct($message, $code, $previous);
}
} }

View File

@@ -9,8 +9,6 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать пустой пароль ККТ * Исключение, возникающее при попытке указать пустой пароль ККТ
* *
@@ -19,15 +17,7 @@ use Throwable;
class AtolKktPasswordEmptyException extends AtolException class AtolKktPasswordEmptyException extends AtolException
{ {
/** /**
* AtolKktPasswordEmptyException constructor. * @var string Сообщение об ошибке
*
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/ */
public function __construct($message = "", $code = 0, Throwable $previous = null) protected $message = 'KKT password cannot be empty';
{
$message = $message ?: 'Пароль ККТ не может быть пустым';
parent::__construct($message, $code, $previous);
}
} }

View File

@@ -9,27 +9,26 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать слишком длинное имя * Исключение, возникающее при попытке указать слишком длинное имя
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolNameTooLongException extends AtolException class AtolNameTooLongException extends AtolTooLongException
{ {
/** /**
* AtolNameTooLongException constructor. * @inheritDoc
*
* @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) protected $ffd_tags = [
{ 1026,
$message = $message ?: 'Слишком длинное имя/наименование (макс. длина '.$max.', фактически '.strlen($name).'): '.$name; 1030,
parent::__construct($message, $code, $previous); 1085,
} 1225,
1227,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Name is too long';
} }

View File

@@ -9,8 +9,6 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать слишком длинный платёжный адрес * Исключение, возникающее при попытке указать слишком длинный платёжный адрес
* *
@@ -19,17 +17,14 @@ use Throwable;
class AtolPaymentAddressTooLongException extends AtolException class AtolPaymentAddressTooLongException extends AtolException
{ {
/** /**
* AtolPaymentAddressTooLongException constructor. * @inheritDoc
*
* @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) protected $ffd_tags = [
{ 1187,
$message = $message ?: 'Слишком длинный адрес (макс. длина '.$max.', фактически '.strlen($address).'): '.$address; ];
parent::__construct($message, $code, $previous);
} /**
* @var string Сообщение об ошибке
*/
protected $message = 'Payment address is too long';
} }

View File

@@ -9,27 +9,26 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать слишком длинный телефон * Исключение, возникающее при попытке указать слишком длинный телефон
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolPhoneTooLongException extends AtolException class AtolPhoneTooLongException extends AtolTooLongException
{ {
/** /**
* AtolPhoneTooLongException constructor. * @inheritDoc
*
* @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) protected $ffd_tags = [
{ 1008,
$message = $message ?: 'Слишком длинный телефон (макс. длина '.$max.', фактически '.strlen($phone).'): '.$phone; 1073,
parent::__construct($message, $code, $previous); 1074,
} 1075,
1171,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Phone is too long';
} }

View File

@@ -9,27 +9,22 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать слишком высокую цену (сумму) * Исключение, возникающее при попытке указать слишком высокую цену (сумму)
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolPriceTooHighException extends AtolException class AtolPriceTooHighException extends AtolTooManyException
{ {
/** /**
* AtolPriceTooHighException constructor. * @inheritDoc
*
* @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) protected $ffd_tags = [
{ 1079,
$message = $message ?: 'Слишком большая сумма (макс. '.$max.'): '.$price; ];
parent::__construct($message, $code, $previous);
} /**
* @var string Сообщение об ошибке
*/
protected $message = 'Price is too high';
} }

View 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\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком длинное что-либо
*
* @package AtolOnline\Exceptions
*/
class AtolTooLongException extends AtolException
{
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Parameter is too long';
/**
* AtolTooLongException constructor.
*
* @param $string
* @param $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
public function __construct($string, $max, $message = "", $code = 0, Throwable $previous = null)
{
parent::__construct($message ?: $this->message.' (max length - '.$max.', actual length - '.
(function_exists('mb_strlen') ? mb_strlen($string) : strlen($string)).')', $code, $previous);
}
}

View File

@@ -12,14 +12,19 @@ namespace AtolOnline\Exceptions;
use Throwable; use Throwable;
/** /**
* Исключение, возникающее при попытке указать слишком большое количество * Исключение, возникающее при попытке указать слишком большое количество чего-либо
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolQuantityTooHighException extends AtolException class AtolTooManyException extends AtolException
{ {
/** /**
* AtolQuantityTooHighException constructor. * @var string Сообщение об ошибке
*/
protected $message = 'Quantity is too high';
/**
* AtolTooManyException constructor.
* *
* @param $quantity * @param $quantity
* @param $max * @param $max
@@ -29,7 +34,7 @@ class AtolQuantityTooHighException extends AtolException
*/ */
public function __construct($quantity, $max, $message = "", $code = 0, Throwable $previous = null) public function __construct($quantity, $max, $message = "", $code = 0, Throwable $previous = null)
{ {
$message = $message ?: 'Слишком большое количество (макс. '.$max.'): '.$quantity; $message = $message ?: $this->message.' (max - '.$max.', actual - '.$quantity.')';
parent::__construct($message, $code, $previous); parent::__construct($message, $code, $previous);
} }
} }

View File

@@ -9,26 +9,15 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке добавить слишком много предметов расчёта в массив * Исключение, возникающее при попытке добавить слишком много предметов расчёта в массив
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolTooManyItemsException extends AtolException class AtolTooManyItemsException extends AtolTooManyException
{ {
/** /**
* AtolTooManyItemsException constructor. * @var string Сообщение об ошибке
*
* @param int $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/ */
public function __construct($max, $message = "", $code = 0, Throwable $previous = null) protected $message = 'Too many items';
{
$message = $message ?: 'Слишком много предметов расчёта (макс. '.$max.')';
parent::__construct($message, $code, $previous);
}
} }

View File

@@ -9,26 +9,25 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке добавить слишком много ставок НДС в массив * Исключение, возникающее при попытке добавить слишком много платежей в массив
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolTooManyPaymentsException extends AtolException class AtolTooManyPaymentsException extends AtolTooManyException
{ {
/** /**
* AtolTooManyPaymentsException constructor. * @inheritDoc
*
* @param int $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/ */
public function __construct($max, $message = "", $code = 0, Throwable $previous = null) protected $ffd_tags = [
{ 1031,
$message = $message ?: 'Слишком много платежей (макс. '.$max.')'; 1081,
parent::__construct($message, $code, $previous); 1215,
} 1217,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Too many payments';
} }

View File

@@ -9,26 +9,27 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке добавить слишком много ставок НДС в массив * Исключение, возникающее при попытке добавить слишком много ставок НДС в массив
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolTooManyVatsException extends AtolException class AtolTooManyVatsException extends AtolTooManyException
{ {
/** /**
* AtolTooManyVatsException constructor. * @inheritDoc
*
* @param int $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/ */
public function __construct($max, $message = "", $code = 0, Throwable $previous = null) protected $ffd_tags = [
{ 1102,
$message = $message ?: 'Слишком много ставок НДС (макс. '.$max.')'; 1103,
parent::__construct($message, $code, $previous); 1104,
} 1105,
1106,
1107,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Too many vats';
} }

View File

@@ -9,27 +9,22 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать слишком длинный телефон * Исключение, возникающее при попытке указать слишком длинный телефон
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolUnitTooLongException extends AtolException class AtolUnitTooLongException extends AtolTooLongException
{ {
/** /**
* AtolUnitTooLongException constructor. * @inheritDoc
*
* @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) protected $ffd_tags = [
{ 1197,
$message = $message ?: 'Слишком длинное название единицы измерения (макс. длина '.$max.', фактически '.strlen($unit).'): '.$unit; ];
parent::__construct($message, $code, $previous);
} /**
* @var string Сообщение об ошибке
*/
protected $message = 'Measurement unit is too long';
} }

View File

@@ -9,27 +9,22 @@
namespace AtolOnline\Exceptions; namespace AtolOnline\Exceptions;
use Throwable;
/** /**
* Исключение, возникающее при попытке указать слишком длинный телефон * Исключение, возникающее при попытке указать слишком длинный дополнительный реквизит
* *
* @package AtolOnline\Exceptions * @package AtolOnline\Exceptions
*/ */
class AtolUserdataTooLongException extends AtolException class AtolUserdataTooLongException extends AtolTooLongException
{ {
/** /**
* AtolUserdataTooLongException constructor. * @inheritDoc
*
* @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) protected $ffd_tags = [
{ 1191,
$message = $message ?: 'Слишком длинный дополнительный реквизит (макс. длина '.$max.', фактически '.strlen($data).'): '.$data; ];
parent::__construct($message, $code, $previous);
} /**
* @var string Сообщение об ошибке
*/
protected $message = 'User data is too long';
} }

View File

@@ -28,7 +28,6 @@ class AtolWrongDocumentTypeException extends AtolException
*/ */
public function __construct($type, $message = "", $code = 0, Throwable $previous = null) public function __construct($type, $message = "", $code = 0, Throwable $previous = null)
{ {
$message = $message ?: 'Некорректный тип документа: ожидался \'receipt\' или \'correction\', указан \''.$type.'\''; parent::__construct($message ?: "Wrong document type: 'receipt' or 'correction' expected, but '$type' provided", $code, $previous);
parent::__construct($message, $code, $previous);
} }
} }

View File

@@ -44,7 +44,7 @@ trait HasEmail
public function setEmail(string $email) public function setEmail(string $email)
{ {
$email = trim($email); $email = trim($email);
if (strlen($email) > 64) { if ((function_exists('mb_strlen') ? mb_strlen($email) : strlen($email)) > 64) {
throw new AtolEmailTooLongException($email, 64); throw new AtolEmailTooLongException($email, 64);
} }
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {

View File

@@ -13,10 +13,9 @@ use AtolOnline\{Constants\PaymentMethods,
Entities\Item, Entities\Item,
Exceptions\AtolNameTooLongException, Exceptions\AtolNameTooLongException,
Exceptions\AtolPriceTooHighException, Exceptions\AtolPriceTooHighException,
Exceptions\AtolQuantityTooHighException, Exceptions\AtolTooManyException,
Exceptions\AtolUnitTooLongException, Exceptions\AtolUnitTooLongException,
Exceptions\AtolUserdataTooLongException Exceptions\AtolUserdataTooLongException};
};
/** /**
* Class ItemTest * Class ItemTest
@@ -28,7 +27,7 @@ class ItemTest extends BasicTestCase
* *
* @throws AtolOnline\Exceptions\AtolNameTooLongException * @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException * @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException * @throws AtolOnline\Exceptions\AtolTooManyException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException * @throws AtolOnline\Exceptions\AtolUnitTooLongException
*/ */
public function testConstructor() public function testConstructor()
@@ -57,7 +56,7 @@ class ItemTest extends BasicTestCase
* *
* @throws AtolOnline\Exceptions\AtolNameTooLongException * @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException * @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException * @throws AtolOnline\Exceptions\AtolTooManyException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException * @throws AtolOnline\Exceptions\AtolUnitTooLongException
* @throws AtolOnline\Exceptions\AtolUserdataTooLongException * @throws AtolOnline\Exceptions\AtolUserdataTooLongException
*/ */
@@ -88,7 +87,7 @@ class ItemTest extends BasicTestCase
* *
* @throws AtolOnline\Exceptions\AtolNameTooLongException * @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException * @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException * @throws AtolOnline\Exceptions\AtolTooManyException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException * @throws AtolOnline\Exceptions\AtolUnitTooLongException
*/ */
public function testSetVat() public function testSetVat()
@@ -105,7 +104,7 @@ class ItemTest extends BasicTestCase
* *
* @throws AtolOnline\Exceptions\AtolNameTooLongException * @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException * @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException * @throws AtolOnline\Exceptions\AtolTooManyException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException * @throws AtolOnline\Exceptions\AtolUnitTooLongException
*/ */
public function testAtolNameTooLongException() public function testAtolNameTooLongException()
@@ -119,14 +118,14 @@ class ItemTest extends BasicTestCase
* Тестирует исключение о слишком высоком количестве * Тестирует исключение о слишком высоком количестве
* *
* @throws AtolOnline\Exceptions\AtolNameTooLongException * @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException * @throws AtolOnline\Exceptions\AtolTooManyException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException * @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException * @throws AtolOnline\Exceptions\AtolUnitTooLongException
*/ */
public function testAtolQuantityTooHighException() public function testAtolQuantityTooHighException()
{ {
$item = new Item(); $item = new Item();
$this->expectException(AtolQuantityTooHighException::class); $this->expectException(AtolTooManyException::class);
$item->setQuantity(100000.1); $item->setQuantity(100000.1);
} }
@@ -135,7 +134,7 @@ class ItemTest extends BasicTestCase
* *
* @throws AtolOnline\Exceptions\AtolPriceTooHighException * @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolNameTooLongException * @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException * @throws AtolOnline\Exceptions\AtolTooManyException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException * @throws AtolOnline\Exceptions\AtolUnitTooLongException
*/ */
public function testAtolPriceTooHighException() public function testAtolPriceTooHighException()
@@ -151,7 +150,7 @@ class ItemTest extends BasicTestCase
* @throws AtolOnline\Exceptions\AtolUserdataTooLongException * @throws AtolOnline\Exceptions\AtolUserdataTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException * @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolNameTooLongException * @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException * @throws AtolOnline\Exceptions\AtolTooManyException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException * @throws AtolOnline\Exceptions\AtolUnitTooLongException
*/ */
public function testAtolUserdataTooLongException() public function testAtolUserdataTooLongException()
@@ -166,7 +165,7 @@ class ItemTest extends BasicTestCase
* *
* @throws AtolOnline\Exceptions\AtolNameTooLongException * @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException * @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException * @throws AtolOnline\Exceptions\AtolTooManyException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException * @throws AtolOnline\Exceptions\AtolUnitTooLongException
*/ */
public function testAtolUnitTooLongException() public function testAtolUnitTooLongException()

View File

@@ -44,8 +44,8 @@ class VatTest extends BasicTestCase
return [ return [
[VatTypes::NONE, 100, 0, 0], [VatTypes::NONE, 100, 0, 0],
[VatTypes::VAT0, 100, 0, 0], [VatTypes::VAT0, 100, 0, 0],
[VatTypes::VAT10, 100, 10, 12], [VatTypes::VAT10, 100, 9.09, 10.9],
[VatTypes::VAT18, 100, 18, 21.6], [VatTypes::VAT18, 100, 15.25, 18.3],
]; ];
} }
} }