pdo = Database::pdo(); } /** * Cria a empresa + usuário admin numa única transação. * * @param array $company ['name', 'cnpj', 'logo'] * @param array $admin ['name', 'email', 'phone', 'password'] * @return array{status:string, company?:array, user?:array} * status: 'created' | 'cnpj_exists' | 'email_exists' | 'error' */ public function createCompanyWithAdmin(array $company, array $admin): array { $companyName = trim((string) ($company['name'] ?? '')); $cnpj = preg_replace('/\D/', '', (string) ($company['cnpj'] ?? '')); $logo = trim((string) ($company['logo'] ?? '')); $userName = trim((string) ($admin['name'] ?? '')); $email = mb_strtolower(trim((string) ($admin['email'] ?? ''))); $phone = trim((string) ($admin['phone'] ?? '')); $password = (string) ($admin['password'] ?? ''); if ($this->cnpjExists($cnpj)) { return ['status' => 'cnpj_exists']; } if ($this->emailExists($email)) { return ['status' => 'email_exists']; } $secret = Hmac::generateSecret(); $passwordHash = password_hash($password, PASSWORD_DEFAULT); $this->pdo->beginTransaction(); try { $companyStmt = $this->pdo->prepare( "INSERT INTO company (company_name, company_cnpj, company_logo, company_hmac_secret) VALUES (:name, :cnpj, :logo, :secret) RETURNING company_id, company_name, company_cnpj, company_logo, company_hmac_secret, company_created_at" ); $companyStmt->execute([ 'name' => $companyName, 'cnpj' => $cnpj, 'logo' => $logo, 'secret' => $secret, ]); $createdCompany = $companyStmt->fetch(\PDO::FETCH_ASSOC); $companyId = (int) $createdCompany['company_id']; $userStmt = $this->pdo->prepare( "INSERT INTO \"user\" (company_id, user_name, user_phone, user_email, user_role, user_password) VALUES (:company_id, :user_name, :user_phone, :user_email, 'admin', :user_password) RETURNING user_id, company_id, user_name, user_phone, user_email, user_role, user_created_at" ); $userStmt->execute([ 'company_id' => $companyId, 'user_name' => $userName, 'user_phone' => $phone, 'user_email' => $email, 'user_password' => $passwordHash, ]); $createdUser = $userStmt->fetch(\PDO::FETCH_ASSOC); $this->pdo->commit(); } catch (\Throwable $e) { $this->pdo->rollBack(); Logger::error('Failed to create company with admin', [ 'cnpj' => $cnpj, 'email' => $email, 'error' => $e->getMessage(), ]); return ['status' => 'error']; } return [ 'status' => 'created', 'company' => [ 'company_id' => $companyId, 'company_name' => $createdCompany['company_name'], 'company_cnpj' => $createdCompany['company_cnpj'], 'company_logo' => $createdCompany['company_logo'], 'company_hmac_secret' => $createdCompany['company_hmac_secret'], 'company_created_at' => $createdCompany['company_created_at'], ], 'user' => [ 'user_id' => (int) $createdUser['user_id'], 'company_id' => (int) $createdUser['company_id'], 'user_name' => $createdUser['user_name'], 'user_phone' => $createdUser['user_phone'], 'user_email' => $createdUser['user_email'], 'user_role' => $createdUser['user_role'], 'user_created_at' => $createdUser['user_created_at'], ], ]; } private function cnpjExists(string $cnpj): bool { $stmt = $this->pdo->prepare( "SELECT 1 FROM company WHERE company_cnpj = :cnpj AND company_deleted_at = 'infinity' LIMIT 1" ); $stmt->execute(['cnpj' => $cnpj]); return $stmt->fetchColumn() !== false; } private function emailExists(string $email): bool { // user_email é UNIQUE global (não filtra por empresa). $stmt = $this->pdo->prepare('SELECT 1 FROM "user" WHERE user_email = :email LIMIT 1'); $stmt->execute(['email' => $email]); return $stmt->fetchColumn() !== false; } }