*/ 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(); } }