atol-online/src/AtolOnline/Entities/Item.php

397 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
/**
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
*
* This code is licensed under MIT.
* Этот код распространяется по лицензии MIT.
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
*/
namespace AtolOnline\Entities;
use AtolOnline\{Exceptions\AtolNameTooLongException,
Exceptions\AtolPriceTooHighException,
Exceptions\AtolQuantityTooHighException,
Exceptions\AtolUnitTooLongException,
Exceptions\AtolUserdataTooLongException,
Traits\RublesKopeksConverter
};
/**
* Предмет расчёта (товар, услуга)
*
* @package AtolOnline\Entities
*/
class Item extends AtolEntity
{
use RublesKopeksConverter;
/**
* @var string Наименование. Тег ФФД - 1030.
*/
protected $name;
/**
* @var int Цена в копейках (с учётом скидок и наценок). Тег ФФД - 1079.
*/
protected $price = 0;
/**
* @var float Количество, вес. Тег ФФД - 1023.
*/
protected $quantity = 0.0;
/**
* @var float Сумма в копейках. Тег ФФД - 1043.
*/
protected $sum = 0;
/**
* @var string Единица измерения количества. Тег ФФД - 1197.
*/
protected $measurement_unit;
/**
* @var Vat Ставка НДС
*/
protected $vat;
/**
* @var string Признак способа расчёта. Тег ФФД - 1214.
*/
protected $payment_method;
/**
* @var string Признак объекта расчёта. Тег ФФД - 1212.
*/
protected $payment_object;
/**
* @var string Дополнительный реквизит. Тег ФФД - 1191.
*/
protected $user_data;
/**
* Item constructor.
*
* @param string|null $name Наименование
* @param float|null $price Цена за одну единицу
* @param float|null $quantity Количество
* @param string|null $measurement_unit Единица измерения
* @param string|null $vat_type Ставка НДС
* @param string|null $payment_object Признак
* @param string|null $payment_method Способ расчёта
* @throws AtolNameTooLongException Слишком длинное наименование
* @throws AtolPriceTooHighException Слишком высокая цена за одну единицу
* @throws AtolQuantityTooHighException Слишком большое количество
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
*/
public function __construct(
?string $name = null,
?float $price = null,
?float $quantity = null,
?string $measurement_unit = null,
$vat_type = null,
?string $payment_object = null,
?string $payment_method = null
) {
if ($name) {
$this->setName($name);
}
if ($price) {
$this->setPrice($price);
}
if ($payment_object) {
$this->setPaymentObject($payment_object);
}
if ($quantity) {
$this->setQuantity($quantity);
}
if ($vat_type) {
$this->setVatType($vat_type);
}
if ($measurement_unit) {
$this->setMeasurementUnit($measurement_unit);
}
if ($payment_method) {
$this->setPaymentMethod($payment_method);
}
}
/**
* Возвращает наименование. Тег ФФД - 1030.
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Устаналивает наименование. Тег ФФД - 1030.
*
* @param string $name Наименование
* @return $this
* @throws AtolNameTooLongException Слишком длинное имя/наименование
*/
public function setName(string $name)
{
$name = trim($name);
if (strlen($name) > 128) {
throw new AtolNameTooLongException($name, 128);
}
$this->name = $name;
return $this;
}
/**
* Возвращает цену в рублях. Тег ФФД - 1079.
*
* @return float
*/
public function getPrice()
{
return self::toRub($this->price);
}
/**
* Устанавливает цену в рублях. Тег ФФД - 1079.
*
* @param float $rubles Цена за одну единицу в рублях
* @return $this
* @throws AtolPriceTooHighException Слишком высокая цена за одну единицу
*/
public function setPrice(float $rubles)
{
if ($rubles > 42949672.95) {
throw new AtolPriceTooHighException($rubles, 42949672.95);
}
$this->price = self::toKop($rubles);
$this->calcSum();
return $this;
}
/**
* Возвращает количество. Тег ФФД - 1023.
*
* @return float
*/
public function getQuantity(): float
{
return $this->quantity;
}
/**
* Устанавливает количество. Тег ФФД - 1023.
*
* @param float $quantity Количество
* @param string|null $measurement_unit Единица измерения количества
* @return $this
* @throws AtolQuantityTooHighException Слишком большое количество
* @throws AtolPriceTooHighException Слишком высокая общая стоимость
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
*/
public function setQuantity(float $quantity, string $measurement_unit = null)
{
$quantity = round($quantity, 3);
if ($quantity > 99999.999) {
throw new AtolQuantityTooHighException($quantity, 99999.999);
}
$this->quantity = $quantity;
$this->calcSum();
if ($measurement_unit) {
$this->setMeasurementUnit($measurement_unit);
}
return $this;
}
/**
* Возвращает заданную единицу измерения количества. Тег ФФД - 1197.
*
* @return string
*/
public function getMeasurementUnit(): string
{
return $this->measurement_unit;
}
/**
* Устанавливает единицу измерения количества. Тег ФФД - 1197.
*
* @param string $measurement_unit Единица измерения количества
* @return $this
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
*/
public function setMeasurementUnit(string $measurement_unit)
{
$measurement_unit = trim($measurement_unit);
if (strlen($measurement_unit) > 16) {
throw new AtolUnitTooLongException($measurement_unit, 16);
}
$this->measurement_unit = $measurement_unit;
return $this;
}
/**
* Возвращает признак способа оплаты. Тег ФФД - 1214.
*
* @return string
*/
public function getPaymentMethod(): string
{
return $this->payment_method;
}
/**
* Устанавливает признак способа оплаты. Тег ФФД - 1214.
*
* @param string $payment_method Признак способа оплаты
* @return $this
* @todo Проверка допустимых значений
*/
public function setPaymentMethod(string $payment_method)
{
$this->payment_method = trim($payment_method);
return $this;
}
/**
* Возвращает признак предмета расчёта. Тег ФФД - 1212.
*
* @return string
*/
public function getPaymentObject(): string
{
return $this->payment_object;
}
/**
* Устанавливает признак предмета расчёта. Тег ФФД - 1212.
*
* @param string $payment_object Признак предмета расчёта
* @return $this
* @todo Проверка допустимых значений
*/
public function setPaymentObject(string $payment_object)
{
$this->payment_object = trim($payment_object);
return $this;
}
/**
* Возвращает ставку НДС
*
* @return \AtolOnline\Entities\Vat|null
*/
public function getVat(): ?Vat
{
return $this->vat;
}
/**
* Устанавливает ставку НДС
*
* @param string|null $vat_type Тип ставки НДС. Передать null, чтобы удалить ставку.
* @return $this
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
*/
public function setVatType(?string $vat_type)
{
if ($vat_type) {
$this->vat
? $this->vat->setType($vat_type)
: $this->vat = new Vat($vat_type);
} else {
$this->vat = null;
}
$this->calcSum();
return $this;
}
/**
* Возвращает дополнительный реквизит. Тег ФФД - 1191.
*
* @return string|null
*/
public function getUserData(): ?string
{
return $this->user_data;
}
/**
* Устанавливает дополнительный реквизит. Тег ФФД - 1191.
*
* @param string $user_data Дополнительный реквизит. Тег ФФД - 1191.
* @return $this
* @throws AtolUserdataTooLongException Слишком длинный дополнительный реквизит
*/
public function setUserData(string $user_data)
{
$user_data = trim($user_data);
if (strlen($user_data) > 64) {
throw new AtolUserdataTooLongException($user_data, 64);
}
$this->user_data = $user_data;
return $this;
}
/**
* Возвращает стоимость. Тег ФФД - 1043.
*
* @return float
*/
public function getSum(): float
{
return self::toRub($this->sum);
}
/**
* Расчитывает стоимость и размер НДС на неё
*
* @return float
* @throws AtolPriceTooHighException Слишком большая сумма
*/
public function calcSum()
{
$sum = $this->quantity * $this->price;
if (self::toRub($sum) > 42949672.95) {
throw new AtolPriceTooHighException($sum, 42949672.95);
}
$this->sum = $sum;
if ($this->vat) {
$this->vat->setSum(self::toRub($sum));
}
return $this->getSum();
}
/**
* @inheritDoc
*/
public function jsonSerialize()
{
$json = [
'name' => $this->getName(), // обязательно
'price' => $this->getPrice(), // обязательно
'quantity' => $this->getQuantity(), // обязательно
'sum' => $this->getSum(), // обязательно
'measurement_unit' => $this->getMeasurementUnit(),
'payment_method' => $this->getPaymentMethod(),
'payment_object' => $this->getPaymentObject()
//TODO nomenclature_code
//TODO agent_info
//TODO supplier_info
//TODO excise
//TODO country_code
//TODO declaration_number
];
if ($this->getVat()) {
$json['vat'] = $this->getVat()->jsonSerialize();
}
if ($this->getUserData()) {
$json['user_data'] = $this->getUserData();
}
return $json;
}
}