159 lines
5.3 KiB
PHP
159 lines
5.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace MonetaPhpShop\host;
|
|
|
|
use Closure;
|
|
use MonetaPhpShop\callback\Logger;
|
|
use MonetaPhpShop\callback\ReceiptSource;
|
|
use MonetaPhpShop\order\Order;
|
|
use MonetaPhpShop\receipt\Receipt;
|
|
use MonetaPhpShop\receipt\ReceiptBuilder;
|
|
use MonetaPhpShop\receipt\Vat;
|
|
use MonetaPhpShop\receipt\VatRateWarnings;
|
|
use MonetaPhpShop\Settings;
|
|
|
|
/**
|
|
* ×åê çàêàçà äëÿ îòâåòîâ Check/Pay URL. Ñòàâêè ÍÄÑ — ôèêñèðîâàííûå èç íàñòðîåê ìîäóëÿ
|
|
* («ÍÄÑ íà òîâàðû», «ÍÄÑ íà äîñòàâêó»), à ïî óìîë÷àíèþ èç PHPShop: âûêëþ÷åí ÍÄÑ
|
|
* â íàñòðîéêàõ ìàãàçèíà — «áåç ÍÄÑ» íà âñåõ ñòðîêàõ; âêëþ÷¸í — ñèñòåìíàÿ ñòàâêà ó òîâàðîâ
|
|
* è ñòàâêà ñïîñîáà äîñòàâêè (`phpshop_delivery.ofd_nds`, ïóñòî — ñèñòåìíàÿ) ó äîñòàâêè.
|
|
*
|
|
* Ñòàâêó íå èç ïåðå÷íÿ êàññû (â PHPShop ýòî ñâîáîäíîå ÷èñëî, íàïðèìåð îïå÷àòêà `23`) ìîäóëü íå óãàäûâàåò:
|
|
* ïîçèöèÿ óõîäèò «áåç ÍÄÑ», à â æóðíàë PHP ïèøåòñÿ ïðåäóïðåæäåíèå — òî æå ïîêàçûâàþò íàñòðîéêè ìîäóëÿ
|
|
* ({@see VatRateWarnings}).
|
|
*
|
|
* Áåç ôèñêàëèçàöèè àòðèáóòû óðåçàíû, à «Email äëÿ ÷åêîâ» íå ïîäñòàâëÿåòñÿ: ÷åê íå ïðîáèâàåòñÿ,
|
|
* MONETA.RU òîëüêî ñîõðàíÿåò àòðèáóòû â îïåðàöèè.
|
|
*
|
|
* Ñáîé ñáîðêè ÷åêà íå äîëæåí ðîíÿòü ïîäòâåðæäåíèå îïëàòû: àòðèáóòû òîãäà ïóñòûå, JSON — null.
|
|
*/
|
|
final class HostReceiptSource implements ReceiptSource
|
|
{
|
|
/** @var Settings */
|
|
private $settings;
|
|
|
|
/** @var HostVatRates */
|
|
private $vatRates;
|
|
|
|
/** @var Logger */
|
|
private $logger;
|
|
|
|
/** @var array<int, Receipt> */
|
|
private $receipts = [];
|
|
|
|
public function __construct(Settings $settings, Database $database, Logger $logger)
|
|
{
|
|
$this->settings = $settings;
|
|
$this->vatRates = new HostVatRates($database);
|
|
$this->logger = $logger;
|
|
}
|
|
|
|
public function attributes(Order $order): array
|
|
{
|
|
$receipt = $this->receipt($order);
|
|
|
|
return ($receipt !== null)
|
|
? $receipt->toAttributes($this->settings->isFiscalization(), $this->settings->getTaxSystem())
|
|
: [];
|
|
}
|
|
|
|
public function jsonReceipt(Order $order): ?array
|
|
{
|
|
$receipt = $this->receipt($order);
|
|
|
|
return ($receipt !== null) ? $receipt->toJsonReceipt() : null;
|
|
}
|
|
|
|
private function receipt(Order $order): ?Receipt
|
|
{
|
|
if (isset($this->receipts[$order->getId()])) {
|
|
return $this->receipts[$order->getId()];
|
|
}
|
|
|
|
try {
|
|
$builder = new ReceiptBuilder(
|
|
Closure::fromCallable([HostCharset::class, 'toUtf8']),
|
|
$this->settings->getPaymentMethod(),
|
|
$this->settings->getPaymentObject(),
|
|
$this->settings->getGoodsVat()->getFixed(),
|
|
);
|
|
$receiptEmail = $this->settings->isFiscalization() ? $this->settings->getReceiptEmail() : '';
|
|
$receipt = $builder->build($order, $this->goodsVat($order), $this->deliveryVat($order), $receiptEmail);
|
|
} catch (\Throwable $exception) {
|
|
$this->logger->error(
|
|
sprintf(
|
|
'×åê çàêàçà %s íå ñîáðàí: %s: %s',
|
|
$order->getUid(),
|
|
get_class($exception),
|
|
$exception->getMessage(),
|
|
),
|
|
);
|
|
|
|
return null;
|
|
}
|
|
|
|
return $this->receipts[$order->getId()] = $receipt;
|
|
}
|
|
|
|
private function goodsVat(Order $order): Vat
|
|
{
|
|
$fixed = $this->settings->getGoodsVat()->getFixed();
|
|
if ($fixed !== null) {
|
|
return $fixed;
|
|
}
|
|
|
|
if (!$this->vatRates->isEnabled()) {
|
|
return Vat::none();
|
|
}
|
|
|
|
return $this->platformVat($order, $this->vatRates->systemPercent(), 'ñèñòåìíàÿ ñòàâêà PHPShop (òîâàðû)');
|
|
}
|
|
|
|
private function deliveryVat(Order $order): Vat
|
|
{
|
|
$fixed = $this->settings->getDeliveryVat()->getFixed();
|
|
if ($fixed !== null) {
|
|
return $fixed;
|
|
}
|
|
|
|
if (!$this->vatRates->isEnabled()) {
|
|
return Vat::none();
|
|
}
|
|
|
|
$percent = $this->vatRates->deliveryPercent($order->getDeliveryMethodId());
|
|
if ($percent !== '') {
|
|
return $this->platformVat($order, $percent, 'ñòàâêà ñïîñîáà äîñòàâêè');
|
|
}
|
|
|
|
return $this->platformVat($order, $this->vatRates->systemPercent(), 'ñèñòåìíàÿ ñòàâêà PHPShop (äîñòàâêà)');
|
|
}
|
|
|
|
/**
|
|
* Ñòàâêà èç PHPShop; íå èç ïåðå÷íÿ êàññû — «áåç ÍÄÑ» è ïðåäóïðåæäåíèå, åñëè ÷åê ïðîáèâàåòñÿ.
|
|
*/
|
|
private function platformVat(Order $order, string $percent, string $source): Vat
|
|
{
|
|
$vat = Vat::tryFromPercent($percent);
|
|
if ($vat !== null) {
|
|
return $vat;
|
|
}
|
|
|
|
if ($this->settings->isFiscalization()) {
|
|
$this->logger->error(
|
|
sprintf(
|
|
'Çàêàç %s: %s %s íå èç ïåðå÷íÿ êàññû — ïîçèöèÿ óõîäèò â ÷åê «áåç ÍÄÑ».'
|
|
. ' Èñïðàâüòå ñòàâêó â PHPShop èëè çàäàéòå ñòàâêó â íàñòðîéêàõ ìîäóëÿ.',
|
|
$order->getUid(),
|
|
$source,
|
|
//  æóðíàë — òîëüêî òî, ÷òî ïîõîæå íà ÷èñëî: çíà÷åíèå ââîäèò àäìèíèñòðàòîð.
|
|
VatRateWarnings::shown((string) preg_replace('/[^0-9.,%+\- ]/', '?', substr($percent, 0, 16))),
|
|
),
|
|
);
|
|
}
|
|
|
|
return Vat::none();
|
|
}
|
|
}
|