Files
PHPShop/moneta/class/receipt/ReceiptItem.php
T

169 lines
5.2 KiB
PHP

<?php
declare(strict_types=1);
namespace MonetaPhpShop\receipt;
use InvalidArgumentException;
use MonetaPhpShop\Money;
use MonetaPhpShop\protocol\JsonNumber;
/**
* Ïîçèöèÿ ÷åêà: `inventPositions` (`kassaspecification.pdf`) è ýëåìåíò `items` JSON Check URL
* (`cmsspecification.pdf`). Êîëè÷åñòâî — äî òð¸õ çíàêîâ ïîñëå òî÷êè ({@see Quantity});
* åäèíèöà èçìåðåíèÿ (`measure`) — èç ïåðå÷íÿ êàññû ({@see Measure}).
* Ïðèçíàê ïðåäìåòà ðàñ÷¸òà (`po` / `paymentObject`) — ÿâíî: ó òîâàðîâ èç íàñòðîéêè, ó äîñòàâêè
* `service` (áåç íåãî êàññà ñòàâèò `commodity` âñåì, è «Äîñòàâêà» óõîäèëà áû òîâàðîì). Ñïîñîá
* ðàñ÷¸òà (`pm` / `paymentMethod`) — ÿâíî: `kassaspecification.pdf` òðåáóåò ïîëå.
* Çíà÷åíèÿ — íàñòðîéêè «Ïðèçíàê ïðåäìåòà ðàñ÷¸òà» ({@see PaymentObject}) è
* «Ïðèçíàê ñïîñîáà ðàñ÷¸òà» ({@see PaymentMethod}). Îáà ïðèçíàêà — òîëüêî â ÷åêå äëÿ êàññû:
* áåç ôèñêàëèçàöèè `INVENTORY` èõ íå íåñ¸ò ({@see self::toInventoryPosition()}).
*/
final class ReceiptItem
{
public const NAME_MAX_LENGTH = 128;
/** Ïîòîëîê êàññû äëÿ öåíû è äëÿ `price * quantity`. */
public const PRICE_MAX = '42949672.95';
/** @var string */
private $name;
/** @var Money */
private $price;
/** @var Quantity */
private $quantity;
/** @var string */
private $measure;
/** @var Vat */
private $vat;
/** @var PaymentObject */
private $paymentObject;
/** @var PaymentMethod */
private $paymentMethod;
/**
* @param string $name â UTF-8; ïóñòîå ïîñëå ÷èñòêè êàññà íå ïðèìåò — çàïàñíîå íàçâàíèå
* ïîäñòàâëÿåò {@see ReceiptBuilder} (ëèòåðàëû ìîäóëÿ ïîñëå ñáîðêè â cp1251)
* @param PaymentObject|null $paymentObject null — òîâàð
* @param PaymentMethod|null $paymentMethod null — ïîëíûé ðàñ÷¸ò
* @param string $measure êîä åäèíèöû èçìåðåíèÿ êàññû ({@see Measure})
*/
public function __construct(
string $name,
Money $price,
Quantity $quantity,
Vat $vat,
?PaymentObject $paymentObject = null,
?PaymentMethod $paymentMethod = null,
string $measure = Measure::UNIT
) {
$this->name = ReceiptText::clean($name, self::NAME_MAX_LENGTH);
if ($this->name === '') {
throw new InvalidArgumentException('Ïóñòîå íàçâàíèå ïîçèöèè ÷åêà.');
}
$this->price = $price;
$this->quantity = $quantity;
$this->measure = $measure;
$this->vat = $vat;
$this->paymentObject = $paymentObject ?? PaymentObject::commodity();
$this->paymentMethod = $paymentMethod ?? PaymentMethod::fullPayment();
$max = Money::fromDecimal(self::PRICE_MAX)->toMinorUnits();
if (($price->toMinorUnits() > $max) || ($this->total()->toMinorUnits() > $max)) {
throw new InvalidArgumentException('Ñóììà ïîçèöèè ÷åêà âûøå ïîòîëêà êàññû.');
}
}
public function getName(): string
{
return $this->name;
}
public function getPrice(): Money
{
return $this->price;
}
public function getQuantity(): Quantity
{
return $this->quantity;
}
public function getMeasure(): string
{
return $this->measure;
}
public function getVat(): Vat
{
return $this->vat;
}
public function getPaymentObject(): PaymentObject
{
return $this->paymentObject;
}
public function getPaymentMethod(): PaymentMethod
{
return $this->paymentMethod;
}
/**
* Ñóììà ïîçèöèè òàê, êàê å¸ ïîñ÷èòàåò êàññà: öåíà x êîëè÷åñòâî äî êîïåéêè.
*/
public function total(): Money
{
return $this->quantity->totalOf($this->price);
}
/**
* Ýëåìåíò `items` JSON-îòâåòà Check URL; öåíà — ìåòêîé {@see JsonNumber}.
*
* @return array<string, mixed>
*/
public function toCheckItem(): array
{
return [
'name' => $this->name,
'price' => JsonNumber::placeholder($this->price),
'quantity' => JsonNumber::quantity($this->quantity),
'measure' => $this->measure,
'paymentMethod' => $this->paymentMethod->getValue(),
'paymentObject' => $this->paymentObject->getValue(),
'vat' => $this->vat->getCode(),
];
}
/**
* Îáúåêò `inventPositions` äëÿ àòðèáóòà `INVENTORY`. Áåç ôèñêàëèçàöèè — òîëüêî òî, ÷òî
* MONETA.RU ñîõðàíèò â îïåðàöèè: áåç `vatTag`, `pm`, `po`.
*
* @return array<string, mixed>
*/
public function toInventoryPosition(bool $fiscalization = true): array
{
$position = [
'name' => $this->name,
'price' => JsonNumber::placeholder($this->price),
'quantity' => JsonNumber::quantity($this->quantity),
'measure' => $this->measure,
];
if (!$fiscalization) {
return $position;
}
return $position + [
'vatTag' => $this->vat->getTag(),
'pm' => $this->paymentMethod->getValue(),
'po' => $this->paymentObject->getValue(),
];
}
}