Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- declare(strict_types=1);
- namespace App\C1\Connector;
- use App\Application\Exceptions\Interfaces\ExceptionManagerAwareInterface;
- use App\Application\Exceptions\Manager\ExceptionManagerAwareTrait;
- use App\C1\Connector\Exceptions\ErrorGetBalance;
- use App\Finance\Balance\Exceptions\BalanceException;
- use App\Finance\Balance\Interfaces\Status;
- use App\Finance\Balance\Manager\BalanceManager;
- use App\Finance\Balance\Manager\Change;
- use App\Finance\Balance\Manager\ChangeResult;
- use App\Finance\Balance\Operation\Balance;
- use App\Finance\Balance\Operation\Block;
- use App\Finance\Balance\Status\Canceled;
- use App\Finance\Balance\Status\Executed;
- use App\InterServices\Billing\Data\BlockDepositParams;
- use App\InterServices\Billing\Data\BlockDepositResult;
- use App\InterServices\Billing\Data\GetBalanceParams;
- /**
- * Коннектор 1С.
- * Один из центральных классов для работы с 1С сервером
- */
- class Connector implements ExceptionManagerAwareInterface
- {
- use ExceptionManagerAwareTrait;
- /**
- * Клиент для связи с 1С сервером
- *
- * @var ApiClient
- */
- protected $apiClient;
- /**
- * Карта исключений для связи их со статусами операций
- *
- * @var ExceptionMapper
- */
- protected $exceptionMapper;
- /**
- * Конструктор класса
- *
- * @param ApiClient $apiClient
- * @param ExceptionMapper $exceptionMapper
- */
- public function __construct(ApiClient $apiClient, ExceptionMapper $exceptionMapper)
- {
- $this->apiClient = $apiClient;
- $this->exceptionMapper = $exceptionMapper;
- }
- /**
- * Получает баланс от 1С.
- * Текущий баланс не сравнивает
- *
- * @param string $accountNumber
- * @param bool $withNds
- * @throws ErrorGetBalance
- * @return array
- */
- public function getBalance(string $accountNumber, bool $withNds): Balance
- {
- try {
- $result = $this->apiClient->getBalance($accountNumber, $withNds);
- return $result;
- } catch (\Throwable $e) {
- $this->exceptionManager->log($e);
- $this->logger->debug('Error get balance', [
- 'accountNumber' => $accountNumber,
- 'withNds' => $withNds
- ]);
- throw new ErrorGetBalance($accountNumber, $withNds, $e);
- }
- }
- /**
- * Отсылает операцию в 1С и возвращает ответ от 1с
- *
- * @param Change $change
- * @return array
- */
- public function sendOperation(Change $change): Status
- {
- $result1C = $this->apiClient->operation($change);
- return $result1C;
- }
- }
- class BalanceGetter implements ExceptionManagerAwareInterface
- {
- use ExceptionManagerAwareTrait;
- /**
- * Коннектор 1С
- *
- * @varApp\Connector1C\Connector
- */
- protected $connector;
- /** @var BalanceManager $balanceManager
- * */
- protected $balanceManager;
- /**
- * Конструктор класса
- *
- * @param Connector $connector
- * @param BalanceManager $balanceManager
- */
- public function __construct(Connector $connector, BalanceManager $balanceManager)
- {
- $this->connector = $connector;
- $this->balanceManager = $balanceManager;
- }
- /**
- * Возвращает текущий баланс счета
- *
- * @param GetBalanceParams $params
- * @return GetBalanceResult
- */
- public function get(GetBalanceParams $params): Balance
- {
- $balance = $this->compareBalance($params->account, $params->nds);
- $result = new Balance();
- $result->account = $params->account;
- $result->nds = $params->nds;
- $result->available = $balance->getAvailable();
- $result->blocked = $balance->getBlocked();
- $result->total = $balance->getAvailable() + $balance->getBlocked();
- return $result;
- }
- /**
- * Получает баланс от 1С и сравнивает его с текущим балансом.
- * Если не совпадения, то это сваливается в сислог и все об этом узнают
- *
- * @param string $accountNumber
- * @param bool $withNds
- * @return Balance
- */
- public function compareBalance(string $accountNumber, bool $withNds): Balance
- {
- try {
- $balance = $this->balanceManager->getBalance($accountNumber, $withNds);
- $balance1cArray = $this->connector->getBalance($accountNumber, $withNds);
- $balance1c = new Balance($balance1cArray['available'], $balance1cArray['blocked']);
- if (($balance->getAvailable() != $balance1c->getAvailable()) || ($balance->getBlocked() != $balance1c->getBlocked())) {
- $this->exceptionManager->getLogger()->error('Balances not equals', [
- 'account' => $accountNumber,
- 'withNds' => $withNds,
- 'available' => $balance->getAvailable(),
- 'blocked' => $balance->getBlocked(),
- 'available1c' => $balance1c->getAvailable(),
- 'blocked1c' => $balance1c->getBlocked()
- ]);
- }
- } catch (\Throwable $e) {
- $this->exceptionManager->log($e);
- $this->exceptionManager->getLogger()->error('Error compare balances', [
- 'account' => $accountNumber,
- 'withNds' => $withNds
- ]);
- }
- return $balance;
- }
- }
- /**
- * Групповое исполнение операций
- */
- class ExecuteOperations implements ExceptionManagerAwareInterface
- {
- use ExceptionManagerAwareTrait;
- /**
- * Максимальное время исполнения скрипта в секундах
- *
- * @var integer
- */
- const TIME_LIMIT = 300;
- /**
- * Коннектор 1С
- *
- * @varApp\Connector1C\Connector
- */
- protected $connector;
- /**
- *
- * @var BalanceGetter
- */
- protected $balanceGetter;
- /**
- * Генератор - обертка над транзакциями БД
- *
- * @var App\Balance\Manager\TransIterator
- */
- protected $transIterator;
- /**
- * Конструктор класса
- *
- * @param Connector $connector
- * @param \App\InterServices\Billing\BalanceGetter $balanceGetter
- * @param TransIterator $transIterator
- */
- public function __construct(Connector $connector, \App\InterServices\Billing\BalanceGetter $balanceGetter, TransIterator $transIterator)
- {
- $this->connector = $connector;
- $this->balanceGetter = $balanceGetter;
- $this->transIterator = $transIterator;
- }
- /**
- * Выполнение операций
- *
- * @param Operation[] ...$operations
- * @return executeOperationResult
- */
- public function execute(Operation ...$operations): executeOperationResult
- {
- $result = new executeOperationResult();
- $result->status = $result::FAILURE;
- $this->logger->info('Execute method start');
- try {
- set_time_limit(self::TIME_LIMIT);
- ignore_user_abort(true);
- if (empty($operations)) {
- throw new EmptyOperationsArray();
- }
- $changes = $this->initOperations(...$operations);
- $changeResults = $this->addTransactions(...$changes);
- $this->sendRequestTo1C(...$changes);
- $this->setStatusForOperations(new Executed(), ...$changeResults);
- $result->status = $result::SUCCESS;
- $result->balances = $this->getBalances(...$operations);
- $this->logger->info('Execute method end success');
- } catch (\Throwable $e) {
- if (!empty($changeResults)) {
- $this->setStatusForOperations(new Canceled(), ...$changeResults);
- }
- $result->message = $this->exceptionManager->log($e);
- $this->logger->debug('Execute method end with errors: ' . $result->message);
- } finally {
- ignore_user_abort(false);
- }
- return $result;
- }
- /**
- *
- * @param Operation[] ...$operations
- * @return array
- */
- protected function initOperations(Operation ...$operations): array
- {
- $changes = [];
- foreach ($operations as $operation) {
- $currentOperation = null;
- /**
- *
- * @var Operation $operation
- */
- switch ($operation->type) {
- case OperationInterface::BLOCK:
- $currentOperation = new Block($operation->sum);
- break;
- case OperationInterface::DEBIT:
- $currentOperation = new Debit($operation->sum);
- break;
- case OperationInterface::UNBLOCK:
- $currentOperation = new Unblock($operation->sum);
- break;
- default:
- throw new UnknownOperation($operation->type);
- }
- $changes[] = new Change($operation->account, $operation->nds, $operation->basis, $currentOperation);
- }
- return $changes;
- }
- /**
- *
- * @param Operation[] ...$operations
- * @return array
- */
- protected function getBalances(Operation ...$operations): array
- {
- $balances = [];
- foreach ($operations as $operation) {
- $getBalanceParams = new GetBalanceParams();
- $getBalanceParams->nds = $operation->getNds();
- $getBalanceParams->account = $operation->getAccount();
- $balanceData = $this->balanceGetter->get($getBalanceParams);
- $balances[] = $balanceData;
- }
- return $balances;
- }
- /**
- *
- * @param Change[] ...$changes
- * @return array
- * @throws \Throwable
- */
- protected function addTransactions(Change ...$changes): array
- {
- $this->logger->info('AddTransactions method start');
- $changeResults = [];
- $items = $this->transIterator->get($changes);
- try {
- foreach ($items as $change) {
- $changeResults[] = $this->connector->addOperation($change);
- }
- } catch (\Throwable $e) {
- $items->throw($e);
- }
- $this->logger->info('AddTransactions method end success');
- return $changeResults;
- }
- /**
- *
- * @param Status $status
- * @param ChangeResult[] ...$changeResults
- * @throws \Throwable
- */
- protected function setStatusForOperations(Status $status, ChangeResult ...$changeResults)
- {
- $this->logger->info('SetStatusForOperations method start with status: ' . $status->getStatus());
- $items = $this->transIterator->get($changeResults);
- try {
- foreach ($items as $item) {
- $item->setStatus($status);
- }
- } catch (\Throwable $e) {
- $items->throw($e);
- }
- $this->logger->info('SetStatusForOperations method end success');
- }
- /**
- *
- * @param Change[] ...$changes
- * @throws \Throwable
- */
- protected function sendRequestTo1C(Change ...$changes)
- {
- $this->logger->info('SendRequestTo1C method start');
- try {
- foreach ($changes as $change) {
- $statusObject = $this->sendOperation($change);
- $status = $statusObject->getStatus();
- if ($status != Status::EXECUTED) {
- throw new OperationNotExecuted($status);
- }
- }
- $this->logger->info('SendRequestTo1C method end success');
- } catch (\Throwable $e) {
- $this->logger->info('SendRequestTo1C method end with errors');
- throw $e;
- }
- }
- /**
- * Добавляет новую операцию и отсылает ее в 1С
- *
- * @param Change $change
- * @return Status
- */
- public function operation(Change $change): Status
- {
- $changeResult = $this->addOperation($change);
- $result = $this->sendOperation($change);
- $changeResult->setStatus($result);
- return $result;
- }
- /**
- * Отсылает операцию в 1С и возвращает статус операции
- *
- * @param Change $change
- * @return Status
- */
- public function sendOperation(Change $change): Status
- {
- try {
- $result1C = $this->connector->sendOperation($change);
- if ($result1C['status'] === 'executed') {
- $result = new Executed();
- } else {
- $result = new Canceled();
- }
- } catch (\Throwable $e) {
- $this->exceptionManager->log($e);
- $result = $this->exceptionMapper->getStatus($e);
- }
- return $result;
- }
- /**
- * Добавляет новую операцию.
- * Если недостаточно денег для этой операции, то проверяет баланс в 1С
- *
- * @param Change $change
- * @throws BalanceException
- * @return ChangeResult
- */
- public function addOperation(Change $change): ChangeResult
- {
- $logger = $this->logger;
- try {
- //@toDo Вот тут осталась зависимость от менеджера, которую я выпилил из конструктора. Возможно, решением проблемы может стать переименоваине класса balanceGetter во что-то другое и добавление туда проброса этого метода
- $result = $this->balanceManager->add($change);
- } catch (BalanceException $e) {
- $this->exceptionManager->log($e);
- $logger->critical('Not enough money', $change->getContext());
- $this->balanceGetter->compareBalance($change->getAccountNumber(), $change->getWithNds());
- throw $e;
- }
- return $result;
- }
- }
- /**
- * Блокировка денег на счету
- */
- class BlockDeposit implements ExceptionManagerAwareInterface
- {
- use ExceptionManagerAwareTrait;
- /**
- * Коннектор 1С
- *
- * @var ExecuteOperations
- */
- protected $executeOperations;
- /**
- * Конструктор класса
- *
- * @param Connector $executeOperations
- */
- public function __construct(ExecuteOperations $executeOperations)
- {
- $this->executeOperations = $executeOperations;
- }
- /**
- * Блокировка средств
- *
- * @param BlockDepositParams $params
- * @return BlockDepositResult
- */
- public function block(BlockDepositParams $params): BlockDepositResult
- {
- $result = new BlockDepositResult();
- $this->logger->debug('Block method start');
- try {
- $blockOperation = new Block($params->sum);
- $change = new Change($params->account, $params->nds, $params->basis, $blockOperation);
- $status = $this->executeOperations->operation($change);
- if ($status instanceof Executed) {
- $result->status = $result::SUCCESS;
- } else {
- $result->status = $result::FAILURE;
- $result->message = $status->getStatus();
- }
- } catch (\Throwable $e) {
- $result->status = $result::FAILURE;
- $result->message = $this->exceptionManager->log($e);
- }
- $this->logger->debug('Block method end. Status:' . $result->status);
- return $result;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement