IntegrationsModel.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <?php
  2. namespace Models;
  3. use Libs\Database;
  4. class IntegrationsModel
  5. {
  6. private \PDO $pdo;
  7. public function __construct()
  8. {
  9. $this->pdo = Database::pdo();
  10. }
  11. public function getOperatorIdByUserEmail(int $companyId, string $email): int
  12. {
  13. $normalizedEmail = mb_strtolower(trim($email));
  14. if ($normalizedEmail === '') {
  15. return 0;
  16. }
  17. $stmt = $this->pdo->prepare(
  18. "SELECT operator_id
  19. FROM operator
  20. WHERE company_id = :company_id
  21. AND lower(operator_email) = :email
  22. AND operator_deleted_at = 'infinity'
  23. LIMIT 1"
  24. );
  25. $stmt->execute([
  26. 'company_id' => $companyId,
  27. 'email' => $normalizedEmail,
  28. ]);
  29. $operatorId = $stmt->fetchColumn();
  30. return $operatorId === false ? 0 : (int) $operatorId;
  31. }
  32. public function listByCompany(int $companyId): array
  33. {
  34. $stmt = $this->pdo->prepare(
  35. "SELECT integration_id, company_id, user_id, operator_id, integration_provider,
  36. integration_account_id, integration_external_account_id, integration_account_name,
  37. integration_status, integration_is_connected, integration_last_sync_at,
  38. integration_last_error, integration_created_at, integration_updated_at
  39. FROM integration
  40. WHERE company_id = :company_id
  41. AND integration_provider = 'whatsapp'
  42. AND integration_deleted_at = 'infinity'
  43. ORDER BY integration_created_at DESC, integration_id DESC"
  44. );
  45. $stmt->execute(['company_id' => $companyId]);
  46. $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC) ?: [];
  47. return array_map([$this, 'formatIntegration'], $rows);
  48. }
  49. public function findById(int $companyId, int $integrationId): ?array
  50. {
  51. $stmt = $this->pdo->prepare(
  52. "SELECT *
  53. FROM integration
  54. WHERE company_id = :company_id
  55. AND integration_id = :integration_id
  56. AND integration_deleted_at = 'infinity'
  57. LIMIT 1"
  58. );
  59. $stmt->execute([
  60. 'company_id' => $companyId,
  61. 'integration_id' => $integrationId,
  62. ]);
  63. $row = $stmt->fetch(\PDO::FETCH_ASSOC);
  64. return $row === false ? null : $row;
  65. }
  66. public function findByAccountId(string $accountId): ?array
  67. {
  68. $stmt = $this->pdo->prepare(
  69. "SELECT *
  70. FROM integration
  71. WHERE integration_account_id = :account_id
  72. AND integration_deleted_at = 'infinity'
  73. LIMIT 1"
  74. );
  75. $stmt->execute(['account_id' => $accountId]);
  76. $row = $stmt->fetch(\PDO::FETCH_ASSOC);
  77. return $row === false ? null : $row;
  78. }
  79. public function upsertWhatsappIntegration(int $companyId, int $userId, int $operatorId, string $accountId, string $status, array $metadata = []): array
  80. {
  81. $externalAccountId = $this->extractExternalAccountId($metadata);
  82. $accountName = $this->extractAccountName($metadata, $accountId);
  83. $isConnected = in_array($status, ['OK', 'CREATION_SUCCESS', 'RECONNECTED', 'SYNC_SUCCESS', 'CONNECTING'], true);
  84. $metadataJson = json_encode($metadata, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
  85. if ($metadataJson === false) {
  86. $metadataJson = '{}';
  87. }
  88. $existing = $this->findByAccountId($accountId);
  89. if ($existing !== null) {
  90. $stmt = $this->pdo->prepare(
  91. "UPDATE integration
  92. SET company_id = :company_id,
  93. user_id = :user_id,
  94. operator_id = :operator_id,
  95. integration_external_account_id = :external_account_id,
  96. integration_account_name = :account_name,
  97. integration_status = :status,
  98. integration_is_connected = :is_connected,
  99. integration_last_sync_at = NOW(),
  100. integration_last_error = '',
  101. integration_metadata = CAST(:metadata AS jsonb),
  102. integration_updated_at = NOW()
  103. WHERE integration_id = :integration_id
  104. RETURNING *"
  105. );
  106. $stmt->execute([
  107. 'company_id' => $companyId,
  108. 'user_id' => $userId,
  109. 'operator_id' => $operatorId,
  110. 'external_account_id' => $externalAccountId,
  111. 'account_name' => $accountName,
  112. 'status' => $status,
  113. 'is_connected' => $isConnected,
  114. 'metadata' => $metadataJson,
  115. 'integration_id' => (int) $existing['integration_id'],
  116. ]);
  117. return $stmt->fetch(\PDO::FETCH_ASSOC) ?: $existing;
  118. }
  119. $stmt = $this->pdo->prepare(
  120. "INSERT INTO integration (
  121. company_id, user_id, operator_id, integration_provider, integration_account_id,
  122. integration_external_account_id, integration_account_name, integration_status,
  123. integration_access_token, integration_refresh_token, integration_is_connected,
  124. integration_last_sync_at, integration_last_error, integration_metadata
  125. ) VALUES (
  126. :company_id, :user_id, :operator_id, 'whatsapp', :account_id,
  127. :external_account_id, :account_name, :status,
  128. '', '', :is_connected,
  129. NOW(), '', CAST(:metadata AS jsonb)
  130. ) RETURNING *"
  131. );
  132. $stmt->execute([
  133. 'company_id' => $companyId,
  134. 'user_id' => $userId,
  135. 'operator_id' => $operatorId,
  136. 'account_id' => $accountId,
  137. 'external_account_id' => $externalAccountId,
  138. 'account_name' => $accountName,
  139. 'status' => $status,
  140. 'is_connected' => $isConnected,
  141. 'metadata' => $metadataJson,
  142. ]);
  143. return $stmt->fetch(\PDO::FETCH_ASSOC) ?: [];
  144. }
  145. public function updateStatusByAccountId(string $accountId, string $status, array $metadata = []): ?array
  146. {
  147. $isConnected = in_array($status, ['OK', 'CREATION_SUCCESS', 'RECONNECTED', 'SYNC_SUCCESS', 'CONNECTING'], true);
  148. $metadataJson = json_encode($metadata, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
  149. if ($metadataJson === false) {
  150. $metadataJson = '{}';
  151. }
  152. $stmt = $this->pdo->prepare(
  153. "UPDATE integration
  154. SET integration_status = :status,
  155. integration_is_connected = :is_connected,
  156. integration_last_sync_at = NOW(),
  157. integration_last_error = CASE WHEN :is_connected THEN '' ELSE integration_last_error END,
  158. integration_metadata = integration_metadata || CAST(:metadata AS jsonb),
  159. integration_updated_at = NOW()
  160. WHERE integration_account_id = :account_id
  161. AND integration_deleted_at = 'infinity'
  162. RETURNING *"
  163. );
  164. $stmt->execute([
  165. 'status' => $status,
  166. 'is_connected' => $isConnected,
  167. 'metadata' => $metadataJson,
  168. 'account_id' => $accountId,
  169. ]);
  170. $row = $stmt->fetch(\PDO::FETCH_ASSOC);
  171. return $row === false ? null : $row;
  172. }
  173. public function formatIntegration(array $row): array
  174. {
  175. return [
  176. 'id' => (int) ($row['integration_id'] ?? 0),
  177. 'companyId' => (int) ($row['company_id'] ?? 0),
  178. 'userId' => (int) ($row['user_id'] ?? 0),
  179. 'operatorId' => (int) ($row['operator_id'] ?? 0),
  180. 'provider' => $row['integration_provider'] ?? '',
  181. 'accountId' => $row['integration_account_id'] ?? '',
  182. 'externalAccountId' => $row['integration_external_account_id'] ?? '',
  183. 'accountName' => $row['integration_account_name'] ?? '',
  184. 'status' => $row['integration_status'] ?? '',
  185. 'isConnected' => (bool) ($row['integration_is_connected'] ?? false),
  186. 'lastSyncAt' => $row['integration_last_sync_at'] ?? '',
  187. 'lastError' => $row['integration_last_error'] ?? '',
  188. 'createdAt' => $row['integration_created_at'] ?? '',
  189. 'updatedAt' => $row['integration_updated_at'] ?? '',
  190. ];
  191. }
  192. private function extractExternalAccountId(array $metadata): string
  193. {
  194. $accountInfo = is_array($metadata['account_info'] ?? null) ? $metadata['account_info'] : [];
  195. return (string) ($accountInfo['user_id'] ?? $metadata['external_account_id'] ?? '');
  196. }
  197. private function extractAccountName(array $metadata, string $accountId): string
  198. {
  199. $accountInfo = is_array($metadata['account_info'] ?? null) ? $metadata['account_info'] : [];
  200. $name = trim((string) ($accountInfo['name'] ?? $metadata['account_name'] ?? $metadata['name'] ?? ''));
  201. return $name !== '' ? mb_substr($name, 0, 100) : mb_substr($accountId, 0, 100);
  202. }
  203. }