169 lines
5.2 KiB
PHP
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(),
|
|
];
|
|
}
|
|
}
|