| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- <?php
- namespace Controllers;
- use Libs\ResponseLib;
- use Models\CprModel;
- use Models\CommodityModel;
- use Models\StatusModel;
- use Models\PaymentModel;
- use Psr\Http\Message\ServerRequestInterface;
- use Services\TokenCreateService;
- class CprFastTrackController
- {
- private \PDO $pdo;
- private CprModel $cprModel;
- private CommodityModel $commodityModel;
- private StatusModel $statusModel;
- private PaymentModel $paymentModel;
- private TokenCreateService $tokenCreateService;
- public function __construct()
- {
- if (!isset($GLOBALS['pdo']) || !$GLOBALS['pdo'] instanceof \PDO) {
- throw new \RuntimeException('Global PDO connection not initialized');
- }
- $this->pdo = $GLOBALS['pdo'];
- $this->cprModel = new CprModel();
- $this->commodityModel = new CommodityModel();
- $this->statusModel = new StatusModel();
- $this->paymentModel = new PaymentModel();
- $this->tokenCreateService = new TokenCreateService();
- }
- public function __invoke(ServerRequestInterface $request)
- {
- $body = json_decode((string)$request->getBody(), true) ?? [];
- $cprPayload = isset($body['cpr']) && is_array($body['cpr']) ? $body['cpr'] : $body;
- $userId = isset($body['user_id']) ? (int)$body['user_id'] : 0;
- $companyId = isset($body['company_id']) ? (int)$body['company_id'] : 0;
- if ($userId <= 0 || $companyId <= 0) {
- $pair = $this->findAnyActiveUser();
- $userId = $pair['user_id'];
- $companyId = $pair['company_id'];
- }
- try {
- $statusId = $this->statusModel->getIdByStatus('pending');
- if ($statusId === null) {
- throw new \RuntimeException('Pending status not found');
- }
- $paymentExternal = 'FAST_' . bin2hex(random_bytes(6));
- $paymentId = $this->paymentModel->create(
- $paymentExternal,
- PaymentModel::STATUS_COMPLETED,
- $userId,
- time(),
- '',
- 'fast-track'
- );
- $cpr = $this->cprModel->create($cprPayload, $statusId, $paymentId, $userId, $companyId);
- $inputs = $this->prepareTokenInputs($cpr, $companyId, $userId);
- $token = $this->tokenCreateService->createToken(
- $inputs['token_commodities_amount'],
- $inputs['token_commodities_value'],
- $inputs['token_uf'],
- $inputs['token_city'],
- (string)$cpr['cpr_id'],
- '',
- $inputs['wallet_id'],
- $inputs['chain_id'],
- $inputs['commodities_id'],
- (int)$cpr['cpr_id'],
- $userId
- );
- $this->cprModel->updateTokenId((int)$cpr['cpr_id'], (int)$token['token_id']);
- return ResponseLib::sendOk([
- 'message' => 'CPR registrada e token mintado (fast-track)',
- 'cpr_id' => (int)$cpr['cpr_id'],
- 'payment_id' => $paymentId,
- 'token_id' => (int)$token['token_id'],
- 'token_external_id' => $token['token_external_id'],
- 'tx_hash' => $token['tx_hash'],
- ], 'S_CPR_FAST');
- } catch (\Throwable $e) {
- return ResponseLib::sendFail('Falha no fast-track: ' . $e->getMessage(), [], 'E_FAST_TRACK')->withStatus(500);
- }
- }
- private function findAnyActiveUser(): array
- {
- $stmt = $this->pdo->query("SELECT user_id, company_id FROM \"user\" WHERE user_flag = 'a' ORDER BY user_id LIMIT 1");
- $row = $stmt->fetch(\PDO::FETCH_ASSOC);
- if (!$row) {
- throw new \RuntimeException('Nenhum usuário ativo encontrado');
- }
- return ['user_id' => (int)$row['user_id'], 'company_id' => (int)$row['company_id']];
- }
- private function prepareTokenInputs(array $cpr, int $companyId, int $userId): array
- {
- $wallet = $this->findWalletByCompanyId($companyId);
- $commoditiesName = $this->requireStringField($cpr, ['cpr_product_name'], 'cpr_product_name');
- $commoditiesId = $this->resolveCommodityId($commoditiesName);
- $amount = $this->requireNumericField($cpr, ['cpr_product_quantity', 'cpr_issue_quantity'], 'quantidade do produto');
- $value = $this->requireNumericField($cpr, ['cpr_issue_value', 'cpr_issue_financial_value'], 'valor do produto');
- $uf = $this->requireStringField($cpr, ['cpr_deliveryPlace_state_acronym', 'cpr_issuers_state_acronym'], 'UF');
- $city = $this->requireStringField($cpr, ['cpr_deliveryPlace_city_name', 'cpr_issuers_city_name'], 'cidade');
- return [
- 'token_commodities_amount' => $amount,
- 'token_commodities_value' => $value,
- 'token_uf' => $uf,
- 'token_city' => $city,
- 'wallet_id' => $wallet['wallet_id'],
- 'chain_id' => $wallet['chain_id'],
- 'commodities_id' => $commoditiesId,
- 'user_id' => $userId,
- ];
- }
- private function findWalletByCompanyId(int $companyId): array
- {
- $stmt = $this->pdo->prepare('SELECT wallet_id, chain_id FROM "wallet" WHERE company_id = :company_id ORDER BY wallet_id ASC LIMIT 1');
- $stmt->execute(['company_id' => $companyId]);
- $wallet = $stmt->fetch(\PDO::FETCH_ASSOC);
- if (!$wallet) {
- throw new \RuntimeException('Nenhuma carteira encontrada para a empresa informada');
- }
- return ['wallet_id' => (int)$wallet['wallet_id'], 'chain_id' => (int)$wallet['chain_id']];
- }
- private function resolveCommodityId(string $name): int
- {
- $id = $this->commodityModel->getIdByName($name);
- if ($id === null) {
- throw new \RuntimeException('Commodity não encontrada para o produto: ' . $name);
- }
- return $id;
- }
- private function requireStringField(array $cpr, array $candidates, string $label): string
- {
- foreach ($candidates as $field) {
- if (array_key_exists($field, $cpr)) {
- $v = $this->normalizeStringValue($cpr[$field]);
- if ($v !== '') {
- return $v;
- }
- }
- }
- throw new \InvalidArgumentException("Campo {$label} ausente ou inválido na CPR.");
- }
- private function requireNumericField(array $cpr, array $candidates, string $label): int
- {
- foreach ($candidates as $field) {
- if (array_key_exists($field, $cpr)) {
- $v = $this->normalizeNumericValue($cpr[$field]);
- if ($v !== null) {
- return $v;
- }
- }
- }
- throw new \InvalidArgumentException("Campo {$label} ausente ou inválido na CPR.");
- }
- private function normalizeStringValue($value): string
- {
- if (is_array($value)) {
- $value = reset($value);
- }
- if (!is_scalar($value)) {
- return '';
- }
- $s = trim((string)$value);
- if ($s === '') {
- return '';
- }
- $parts = preg_split('/\s*;\s*/', $s) ?: [];
- $first = $parts[0] ?? $s;
- return trim((string)$first);
- }
- private function normalizeNumericValue($value): ?int
- {
- if (is_array($value)) {
- $value = reset($value);
- }
- if (is_string($value)) {
- $value = str_replace([' ', ','], ['', '.'], $value);
- }
- if (is_numeric($value)) {
- return (int)round((float)$value);
- }
- return null;
- }
- }
|