OpenXE/classes/Modules/FiskalyApi/Service/FiskalyTransferService.php
2021-05-21 08:49:41 +02:00

341 lines
12 KiB
PHP

<?php
declare(strict_types=1);
namespace Xentral\Modules\FiskalyApi\Service;
use Aura\SqlQuery\Exception;
use FiskalyClient\errors\exceptions\FiskalyClientException;
use FiskalyClient\errors\exceptions\FiskalyHttpException;
use FiskalyClient\errors\exceptions\FiskalyHttpTimeoutException;
use Xentral\Components\Database\Database;
use Xentral\Modules\FiskalyApi\Data\TechnicalSecuritySystem;
use Xentral\Modules\FiskalyApi\Data\Transaction\AmountsPerPaymentType;
use Xentral\Modules\FiskalyApi\Data\Transaction\AmountsPerPaymentTypeCollection;
use Xentral\Modules\FiskalyApi\Data\Transaction\AmountsPerVatType;
use Xentral\Modules\FiskalyApi\Data\Transaction\AmountsPerVatTypeCollection;
use Xentral\Modules\FiskalyApi\Data\Transaction\TransactionReponse;
use Xentral\Modules\FiskalyApi\Data\Transaction\TransactionReponseCollection;
use Xentral\Modules\FiskalyApi\Data\Transaction\TransactionRequest;
use Xentral\Modules\FiskalyApi\Factory\FiskalyApiFactory;
use Xentral\Modules\FiskalyApi\Factory\FiskalyTransactionFactory;
use Xentral\Modules\FiskalyApi\Transaction\Payment\CashPayment;
use Xentral\Modules\FiskalyApi\Transaction\Payment\NonCashPayment;
use Xentral\Modules\FiskalyApi\Transaction\Payment\OrderLineItem;
use Xentral\Modules\FiskalyApi\Transaction\Transaction;
use Xentral\Modules\FiskalyApi\Transaction\VatAmount\BaseVatAmount;
class FiskalyTransferService
{
/** @var FiskalyKassenSichVApi */
private $fiskalyApi;
/** @var FiskalyTransactionFactory $transactionFactory */
private $transactionFactory;
/** @var Database */
private $database;
/** @var FiskalyApiFactory $fiskalyApiFactory */
private $fiskalyApiFactory;
/**
* FiskalyTransferService constructor.
*
* @param FiskalyApiFactory $fiskalyApiFactory
* @param Database $database
*/
public function __construct(
FiskalyApiFactory $fiskalyApiFactory,
FiskalyTransactionFactory $transactionFactory,
Database $database
) {
$this->fiskalyApiFactory = $fiskalyApiFactory;
$this->transactionFactory = $transactionFactory;
$this->database = $database;
}
/**
* @param string $organizationId
*
* @throws \Exception
*/
public function loadOrganization(string $organizationId): self
{
$this->fiskalyApi = $this->fiskalyApiFactory->createFiskalyKassenSichVApiFromSystemSettings($organizationId);
return $this;
}
/**
* @param int $cashierId
* @param bool $incoming
* @param float $amount
* @param bool $isCash
*
* @throws Exception
* @return Transaction
*
* @depracated
*/
public function createTransactionFromSingleJournal(
int $cashierId,
bool $incoming,
float $amount,
bool $isCash
): Transaction {
$posProjectQuery = $this->database->select()
->from('pos_kassierer AS p')
->cols(['f.tss_uuid', 'f.client_uuid'])
->where('p.kassenkennung=:kennung')
->leftJoin('fiskaly_pos_mapping AS f', 'f.pos_id = p.projekt')
->bindValue('kennung', $cashierId);
$result = $this->database->fetchRow($posProjectQuery->getStatement(), $posProjectQuery->getBindValues());
$tssUuid = $result['tss_uuid'];
$clientId = $result['client_uuid'];
$tssDescription = $result['tss_description'];
if ($isCash) {
$paymentTypePayment = new CashPayment($amount);
} else {
$paymentTypePayment = new NonCashPayment($amount);
}
$vat = (float)0;
$sum = $amount * ($incoming ? 1 : -1);
$vatTypePayment = BaseVatAmount::fromPercentage($vat, $sum);
$transaction = new Transaction([$paymentTypePayment], [$vatTypePayment], [], $clientId);
$tss = new TechnicalSecuritySystem($tssUuid, $tssDescription);
return $this->fiskalyApi->uploadTransaction($transaction, $tss);
}
/**
* @param TransactionRequest $transactionRequest
*
* @throws FiskalyClientException
* @throws FiskalyHttpException
* @throws FiskalyHttpTimeoutException
* @return TransactionReponse
*/
public function startTransaction(TransactionRequest $transactionRequest): TransactionReponse
{
return $this->fiskalyApi->createTransaction($transactionRequest);
}
/**
* @param string|null $tssUuid
* @param int $offset
* @param int $limit
*
* @throws FiskalyClientException
* @throws FiskalyHttpException
* @throws FiskalyHttpTimeoutException
* @return TransactionReponseCollection
*/
public function getTransactions(
?string $tssUuid = null,
int $offset = 0,
int $limit = 100
): TransactionReponseCollection {
return $this->fiskalyApi->getTransactions($tssUuid, $offset, $limit);
}
/**
* @param TransactionRequest $transactionRequest
*
* @throws FiskalyClientException
* @throws FiskalyHttpException
* @throws FiskalyHttpTimeoutException
* @return TransactionReponse
*/
public function updateTransaction(TransactionRequest $transactionRequest): TransactionReponse
{
return $this->fiskalyApi->updateTransaction($transactionRequest);
}
/**
* @param TransactionReponse $transactionResponse
* @param bool $incoming
* @param float $value
* @param bool $isTraining
*
* @return TransactionRequest
*/
public function createTransactionRequestFromPosCounting(
TransactionReponse $transactionResponse,
bool $incoming,
float $value,
bool $isTraining = false
): TransactionRequest {
$negativeMultiplier = $incoming ? 1 : -1;
$vatTypePayment = BaseVatAmount::fromPercentage(0, $value);
$amountsPerVatTypeCollection = new AmountsPerVatTypeCollection(
[
new AmountsPerVatType(
$vatTypePayment->getVatType(), number_format($negativeMultiplier * $value, 2, '.', '')
),
]
);
$amountsPerPaymentTypeCollection = new AmountsPerPaymentTypeCollection(
[new AmountsPerPaymentType('CASH', number_format($negativeMultiplier * $value, 2, '.', ''), 'EUR')]
);
$receiptType = $isTraining ? 'TRAINING' : 'TRANSFER';
return $this->fiskalyApi->getFinishTransactionRequest(
$transactionResponse,
!empty($posSession['training']) ? 'TRAINING' : $receiptType,
$amountsPerVatTypeCollection,
$amountsPerPaymentTypeCollection
);
}
/**
* @param TransactionReponse $transactionResponse
* @param array $posSession
*
* @return TransactionRequest
*/
public function createFinishTransactionFromPosSession(
TransactionReponse $transactionResponse,
array $posSession
): TransactionRequest {
$amountsPerVatTypeCollection = new AmountsPerVatTypeCollection();
$amountsPerPaymentTypeCollection = new AmountsPerPaymentTypeCollection();
$paymentType = $posSession['ptype'];
$receiptType = 'RECEIPT';
$type = $posSession['rtype'];
if (in_array($type, ['einlage', 'entnahme'])) {
$type = 'TRANSFER';
}
$negativeMultiplier = 1;
if ($type === 'entnahme' || in_array($posSession['cmd'], ['stornieren', 'teilstornieren'])) {
$negativeMultiplier = -1;
}
$tip = isset($posSession['tip']) ? (float)round(str_replace(',', '.', $posSession['tip']), 2) : 0.;
$amount = (float)$posSession['soll'] * $negativeMultiplier;
if ($paymentType === 'bar') {
$amountsPerPaymentTypeCollection->addPaymentType(
new AmountsPerPaymentType('CASH', number_format($amount + $tip, 2, '.', ''), 'EUR')
);
} else {
$amountsPerPaymentTypeCollection->addPaymentType(
new AmountsPerPaymentType('NON_CASH', number_format($amount, 2, '.', ''), 'EUR')
);
if ($tip > 0) {
$amountsPerPaymentTypeCollection->addPaymentType(
new AmountsPerPaymentType('CASH', number_format($tip, 2, '.', ''), 'EUR')
);
}
}
foreach ($posSession['wk'] as $position) {
$vat = str_replace('%', '', $position['tax']);
$vat = (float)str_replace(',', '.', $vat);
$sum = (float)str_replace(',', '.', $position['preis']) * (float)str_replace(',', '.', $position['amount'])
* (1 - (float)str_replace(',', '.', $position['rabatt']) / 100);
$vatTypePayment = BaseVatAmount::fromPercentage($vat, $sum);
$amountsPerVatTypeCollection->combine(
new AmountsPerVatTypeCollection(
[
new AmountsPerVatType($vatTypePayment->getVatType(), number_format($sum, 2, '.', '')),
]
)
);
}
if ($tip > 0) {
$vatTypePayment = BaseVatAmount::fromPercentage(0, $tip);
$amountsPerVatTypeCollection->combine(
new AmountsPerVatTypeCollection(
[
new AmountsPerVatType($vatTypePayment->getVatType(), number_format($tip, 2, '.', '')),
]
)
);
}
return $this->fiskalyApi->getFinishTransactionRequest(
$transactionResponse,
!empty($posSession['training']) ? 'TRAINING' : $receiptType,
$amountsPerVatTypeCollection,
$amountsPerPaymentTypeCollection
);
}
/**
* @param $posSession
*
* @throws Exception
* @return Transaction
*
* @depracated
*/
public function transferPosSession($posSession): Transaction
{
$cashierId = $posSession['kassiererId'];
$result = $this->transactionFactory->getClientAndTssInfoFromCashierId((string)$cashierId);
$tssUuid = $result['tss_uuid'];
$clientId = $result['client_uuid'];
$tssDescription = $result['tss_description'];
$paymentType = $posSession['ptype'];
$negativeMultiplier = 1;
if (in_array($posSession['cmd'], ['stornieren', 'teilstornieren'])) {
$negativeMultiplier = -1;
}
$tip = isset($posSession['tip']) ? (float)round(str_replace(',', '.', $posSession['tip']), 2) : 0.;
$amount = (float)$posSession['soll'] * $negativeMultiplier;
$paymentTypePayments = [];
if ($paymentType === 'bar') {
$paymentTypePayments[] = new CashPayment($amount + $tip);
} else {
$paymentTypePayments[] = new NonCashPayment($amount);
if ($tip > 0) {
$paymentTypePayments[] = new CashPayment($tip);
}
}
$vatTypeAmounts = [];
$oderLineItems = [];
foreach ($posSession['wk'] as $position) {
$vat = str_replace('%', '', $position['tax']);
$vat = (float)str_replace(',', '.', $vat);
$sum = (float)str_replace(',', '.', $position['preis']);
$amount = (float)$position['amount'];
$oderLineItems[] = new OrderLineItem($amount, (string)$position['artikel'], $sum * $negativeMultiplier);
$sum *= $amount * $negativeMultiplier;
$vatTypePayment = BaseVatAmount::fromPercentage($vat, $sum);
$vatTypeClass = get_class($vatTypePayment);
/** @var BaseVatAmount $vatTypeAmount */
$cachedVatTypePayment = $vatTypeAmounts[$vatTypeClass] ?? null;
if (empty($cachedVatTypePayment)) {
$vatTypeAmounts[$vatTypeClass] = $vatTypePayment;
} else {
$cachedVatTypePayment->add($sum);
}
}
if ($tip > 0) {
$vatTypePayment = BaseVatAmount::fromPercentage(0., $tip);
$vatTypeClass = get_class($vatTypePayment);
/** @var BaseVatAmount $vatTypeAmount */
$cachedVatTypePayment = $vatTypeAmounts[$vatTypeClass] ?? null;
if ($cachedVatTypePayment === null) {
$vatTypeAmounts[$vatTypeClass] = $vatTypePayment;
} else {
$cachedVatTypePayment->add($tip);
}
$oderLineItems[] = new OrderLineItem(1, 'Trinkgeld', $tip);
}
$transaction = new Transaction($paymentTypePayments, array_values($vatTypeAmounts), $oderLineItems, $clientId);
$tss = new TechnicalSecuritySystem($tssUuid, $tssDescription);
return $this->fiskalyApi->uploadTransaction($transaction, $tss);
}
}