Bläddra i källkod

fix the most features

gdias 1 vecka sedan
förälder
incheckning
2017457ddb

+ 14 - 5
controllers/CprQueryController.php

@@ -23,13 +23,17 @@ class CprQueryController
             return ResponseLib::sendFail('Invalid JSON body', [], 'E_VALIDATE')->withStatus(400);
         }
 
-        $bodyCompanyId = (int)($body['company_id'] ?? 0);
+        $authCompanyId = (int)($request->getAttribute('api_company_id') ?? 0);
+        if ($authCompanyId <= 0) {
+            return ResponseLib::sendFail('Authenticated company not found', [], 'E_VALIDATE')->withStatus(401);
+        }
+
+        $bodyCompanyId = (int)($body['company_id'] ?? $authCompanyId);
         if ($bodyCompanyId <= 0) {
             return ResponseLib::sendFail('company_id is required', [], 'E_VALIDATE')->withStatus(400);
         }
 
-        $authCompanyId = (int)$request->getAttribute('api_company_id');
-        if ($authCompanyId !== $bodyCompanyId) {
+        if ($authCompanyId !== 1 && $authCompanyId !== $bodyCompanyId) {
             return ResponseLib::sendFail(
                 'Unauthorized company access',
                 [],
@@ -37,11 +41,14 @@ class CprQueryController
             )->withStatus(403);
         }
 
+        $hasGlobalAccess = $authCompanyId === 1;
         $cprId = isset($body['cpr_id']) ? (int)$body['cpr_id'] : null;
 
         try {
             if ($cprId) {
-                $record = $this->model->getByIdAndCompany($cprId, $authCompanyId);
+                $record = $hasGlobalAccess
+                    ? $this->model->getById($cprId)
+                    : $this->model->getByIdAndCompany($cprId, $authCompanyId);
                 if (!$record) {
                     return ResponseLib::sendFail(
                         'CPR not found',
@@ -53,7 +60,9 @@ class CprQueryController
                 return Response::json($record)->withStatus(200);
             }
 
-            $list = $this->model->listByCompany($authCompanyId);
+            $list = $hasGlobalAccess
+                ? $this->model->listAll()
+                : $this->model->listByCompany($authCompanyId);
             return Response::json($list)->withStatus(200);
 
         } catch (\Throwable $e) {

+ 25 - 9
controllers/OrderbookTransferController.php

@@ -22,6 +22,7 @@ class OrderbookTransferController
     private TokenTransferService $tokenTransferService;
     private TokenModel $tokenModel;
     private CprModel $cprModel;
+    private OrderbookModel $orderbookModel;
 
     public function __construct()
     {
@@ -31,6 +32,7 @@ class OrderbookTransferController
         $this->tokenTransferService = new TokenTransferService();
         $this->tokenModel = new TokenModel();
         $this->cprModel = new CprModel();
+        $this->orderbookModel = new OrderbookModel();
     }
 
     public function __invoke(ServerRequestInterface $request)
@@ -97,8 +99,14 @@ class OrderbookTransferController
             return ResponseLib::sendFail('Token não está vinculado a uma CPR', ['token_id' => $tokenId], 'E_CPR_NOT_FOUND')->withStatus(409);
         }
 
-        if ((int)$orderbook['company_id'] !== $companyId) {
-            return ResponseLib::sendFail('Orderbook não pertence à empresa autenticada', [], 'E_FORBIDDEN')->withStatus(403);
+        try {
+            $wallet = $this->walletModel->getPrimaryWalletByCompanyId($companyId);
+        } catch (\Throwable $e) {
+            return ResponseLib::sendFail('Falha ao consultar carteira da empresa: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
+        }
+
+        if (!$wallet || empty($wallet['wallet_address'])) {
+            return ResponseLib::sendFail('Carteira da empresa não encontrada', [], 'E_WALLET_NOT_FOUND')->withStatus(404);
         }
 
         if ((int)$orderbook['status_id'] === OrderbookModel::STATUS_COMPLETED) {
@@ -109,24 +117,31 @@ class OrderbookTransferController
             ], 'S_TOKEN_ALREADY_TRANSFERRED');
         }
 
+        $serverAddress = $this->resolveServerAddress();
+
         try {
-            $wallet = $this->walletModel->getPrimaryWalletByCompanyId($companyId);
+            $transferResult = $this->tokenTransferService->transferFrom($serverAddress, (string)$wallet['wallet_address'], $tokenExternalId);
         } catch (\Throwable $e) {
-            return ResponseLib::sendFail('Falha ao consultar carteira da empresa: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
+            return ResponseLib::sendFail('Falha ao transferir token: ' . $e->getMessage(), [], 'E_TRANSFER')->withStatus(500);
         }
 
-        if (!$wallet || empty($wallet['wallet_address'])) {
-            return ResponseLib::sendFail('Carteira da empresa não encontrada', [], 'E_WALLET_NOT_FOUND')->withStatus(404);
+        $txHash = $transferResult['tx_hash'] ?? null;
+        if (!$txHash) {
+            return ResponseLib::sendFail('Transferência não retornou hash válido', [], 'E_TRANSFER_HASH')->withStatus(502);
         }
 
-        $serverAddress = $this->resolveServerAddress();
+        try {
+            $this->orderbookModel->updateWalletId((int)$orderbook['orderbook_id'], (int)$wallet['wallet_id']);
+        } catch (\Throwable $e) {
+            return ResponseLib::sendFail('Falha ao registrar comprador no orderbook: ' . $e->getMessage(), [], 'E_ORDERBOOK_UPDATE')->withStatus(500);
+        }
 
         try {
-            $transferResult = $this->tokenTransferService->transferFrom($serverAddress, (string)$wallet['wallet_address'], $tokenExternalId);
             $this->orderbookTransferModel->markCompleted((int)$orderbook['orderbook_id']);
+            $this->tokenModel->updateWalletId($tokenId, (int)$wallet['wallet_id']);
             $this->cprModel->updateCompanyId($cprId, $companyId);
         } catch (\Throwable $e) {
-            return ResponseLib::sendFail('Falha ao transferir token: ' . $e->getMessage(), [], 'E_TRANSFER')->withStatus(500);
+            return ResponseLib::sendFail('Falha ao atualizar registros após transferência: ' . $e->getMessage(), [], 'E_TRANSFER_PERSIST')->withStatus(500);
         }
 
         return ResponseLib::sendOk([
@@ -135,6 +150,7 @@ class OrderbookTransferController
             'destination_address' => (string)$wallet['wallet_address'],
             'transfer_output' => $transferResult['output'] ?? '',
             'transfer_error' => $transferResult['error'] ?? '',
+            'transaction_hash' => $txHash,
         ], 'S_TOKEN_TRANSFERRED');
     }
 

+ 2 - 5
controllers/PaymentConfirmController.php

@@ -180,12 +180,9 @@ class PaymentConfirmController
             throw new \InvalidArgumentException('CPR sem usuário associado.');
         }
 
-        $companyId = (int)($cpr['company_id'] ?? 0);
-        if ($companyId <= 0) {
-            throw new \InvalidArgumentException('CPR sem empresa associada.');
-        }
-
+        $companyId = 1;
         $wallet = $this->findWalletByCompanyId($companyId);
+
         $commoditiesName = $this->requireStringField($cpr, ['cpr_product_name'], 'cpr_product_name');
         $commoditiesId = $this->resolveCommodityId($commoditiesName);
 

+ 29 - 0
models/CprQueryModel.php

@@ -38,6 +38,22 @@ class CprQueryModel
         return $stmt->fetchAll(\PDO::FETCH_ASSOC);
     }
 
+    public function listAll(): array
+    {
+        $sql = '
+            SELECT
+                cpr_id,
+                cpr_product_class_name,
+                cpr_issue_date,
+                cpr_issuer_name,
+                cpr_issue_financial_value
+            FROM cpr
+            ORDER BY cpr_issue_date DESC
+        ';
+
+        return $this->pdo->query($sql)->fetchAll(\PDO::FETCH_ASSOC);
+    }
+
     /**
      * Detalhe completo
      */
@@ -65,6 +81,19 @@ class CprQueryModel
         return $this->filterEmptyFields($row);
     }
 
+    public function getById(int $cprId): ?array
+    {
+        $stmt = $this->pdo->prepare('SELECT * FROM cpr WHERE cpr_id = :cpr_id LIMIT 1');
+        $stmt->execute(['cpr_id' => $cprId]);
+        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
+
+        if (!$row) {
+            return null;
+        }
+
+        return $this->filterEmptyFields($row);
+    }
+
     /**
      * Remove NULL e "na"
      */

+ 26 - 0
models/OrderbookModel.php

@@ -195,4 +195,30 @@ class OrderbookModel
             'orderbook_id' => $orderbookId,
         ]);
     }
+
+    public function updateWalletId(int $orderbookId, int $walletId): void
+    {
+        if ($orderbookId <= 0) {
+            throw new \InvalidArgumentException('Invalid orderbook id provided');
+        }
+
+        if ($walletId <= 0) {
+            throw new \InvalidArgumentException('Invalid wallet id provided');
+        }
+
+        $stmt = $this->pdo->prepare(
+            'UPDATE "orderbook"
+             SET wallet_id = :wallet_id
+             WHERE orderbook_id = :orderbook_id'
+        );
+
+        $stmt->execute([
+            'wallet_id' => $walletId,
+            'orderbook_id' => $orderbookId,
+        ]);
+
+        if ($stmt->rowCount() === 0) {
+            throw new \RuntimeException('Orderbook record not found for wallet update');
+        }
+    }
 }

+ 26 - 0
models/TokenModel.php

@@ -141,5 +141,31 @@ class TokenModel
             'token_id' => $tokenId,
         ]);
     }
+
+    public function updateWalletId(int $tokenId, int $walletId): void
+    {
+        if ($tokenId <= 0) {
+            throw new \InvalidArgumentException('Invalid token id provided');
+        }
+
+        if ($walletId <= 0) {
+            throw new \InvalidArgumentException('Invalid wallet id provided');
+        }
+
+        $stmt = $this->pdo->prepare(
+            'UPDATE "token"
+             SET wallet_id = :wallet_id
+             WHERE token_id = :token_id'
+        );
+
+        $stmt->execute([
+            'wallet_id' => $walletId,
+            'token_id' => $tokenId,
+        ]);
+
+        if ($stmt->rowCount() === 0) {
+            throw new \RuntimeException('Token record not found for wallet update');
+        }
+    }
 }
 

+ 20 - 4
services/TokenTransferService.php

@@ -28,9 +28,8 @@ class TokenTransferService
         }
 
         $command = sprintf(
-            '%s token transferFrom %s %s %s',
+            '%s token transfer --to %s --token-id %s',
             escapeshellarg($this->easyCliPath),
-            escapeshellarg($from),
             escapeshellarg($to),
             escapeshellarg($token)
         );
@@ -38,12 +37,29 @@ class TokenTransferService
         $result = BashExecutor::run($command, 120);
         if (($result['exitCode'] ?? 1) !== 0) {
             $message = $result['error'] ?: $result['output'] ?: 'Unknown easycli error';
-            throw new \RuntimeException('easycli transferFrom failed: ' . $message);
+            throw new \RuntimeException('easycli transfer failed: ' . $message);
         }
 
+        $output = trim((string)($result['output'] ?? ''));
+        $txHash = $this->extractHashFromOutput($output);
+
         return [
-            'output' => trim((string)($result['output'] ?? '')),
+            'output' => $output,
             'error' => trim((string)($result['error'] ?? '')),
+            'tx_hash' => $txHash,
         ];
     }
+
+    private function extractHashFromOutput(string $output): ?string
+    {
+        if ($output === '') {
+            return null;
+        }
+
+        if (preg_match('/0x[a-fA-F0-9]{64}/', $output, $matches)) {
+            return $matches[0];
+        }
+
+        return null;
+    }
 }