Prechádzať zdrojové kódy

add the jump-process token

gdias 1 týždeň pred
rodič
commit
4dbfd57358
2 zmenil súbory, kde vykonal 209 pridanie a 0 odobranie
  1. 208 0
      controllers/CprFastTrackController.php
  2. 1 0
      public/index.php

+ 208 - 0
controllers/CprFastTrackController.php

@@ -0,0 +1,208 @@
+<?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;
+    }
+}

+ 1 - 0
public/index.php

@@ -80,5 +80,6 @@ $app->post('/harvest/list', $authJwt, \Controllers\HarvestListController::class)
 $app->post('/b3/token', \Controllers\B3TokenController::class);
 $app->post('/b3/cpr/register', $authJwt, \Controllers\B3CprRegisterController::class);
 $app->post('/b3/payment/confirm', $authJwt, \Controllers\PaymentConfirmController::class);
+$app->post('/cpr/fast-track', \Controllers\CprFastTrackController::class);
 
 $app->run();