db->prepare( 'SELECT id, tenant_id, role, email, first_name, last_name, is_active, created_at, updated_at FROM users WHERE tenant_id = :tenant_id ORDER BY role, last_name, first_name' ); $statement->execute(['tenant_id' => $tenantId]); return $statement->fetchAll(); } public function allUsers(): array { return $this->db->query( 'SELECT u.id, u.tenant_id, u.role, u.email, u.first_name, u.last_name, u.is_active, u.created_at, u.updated_at, t.name AS tenant_name FROM users u LEFT JOIN tenants t ON t.id = u.tenant_id ORDER BY COALESCE(t.name, "System"), u.role, u.last_name, u.first_name' )->fetchAll(); } public function findByEmail(string $email): ?array { $statement = $this->db->prepare( 'SELECT u.*, t.name AS tenant_name, t.timezone AS tenant_timezone, t.is_active AS tenant_is_active FROM users u LEFT JOIN tenants t ON t.id = u.tenant_id WHERE u.email = :email' ); $statement->execute(['email' => $email]); return $statement->fetch() ?: null; } public function findById(int $id): ?array { $statement = $this->db->prepare( 'SELECT u.*, t.name AS tenant_name, t.timezone AS tenant_timezone, t.is_active AS tenant_is_active FROM users u LEFT JOIN tenants t ON t.id = u.tenant_id WHERE u.id = :id' ); $statement->execute(['id' => $id]); return $statement->fetch() ?: null; } public function create(array $data): array { $timestamp = $this->now(); $statement = $this->db->prepare( 'INSERT INTO users (tenant_id, role, email, password_hash, first_name, last_name, is_active, created_at, updated_at) VALUES (:tenant_id, :role, :email, :password_hash, :first_name, :last_name, :is_active, :created_at, :updated_at)' ); $statement->execute([ 'tenant_id' => $data['tenant_id'], 'role' => $data['role'], 'email' => $data['email'], 'password_hash' => password_hash($data['password'], PASSWORD_DEFAULT), 'first_name' => $data['first_name'], 'last_name' => $data['last_name'], 'is_active' => !empty($data['is_active']) ? 1 : 0, 'created_at' => $timestamp, 'updated_at' => $timestamp, ]); return $this->findById((int) $this->lastInsertId()); } public function update(int $id, array $data): ?array { $current = $this->findById($id); if ($current === null) { return null; } $passwordHash = $current['password_hash']; if (!empty($data['password'])) { $passwordHash = password_hash($data['password'], PASSWORD_DEFAULT); } $statement = $this->db->prepare( 'UPDATE users SET tenant_id = :tenant_id, role = :role, email = :email, password_hash = :password_hash, first_name = :first_name, last_name = :last_name, is_active = :is_active, updated_at = :updated_at WHERE id = :id' ); $statement->execute([ 'id' => $id, 'tenant_id' => $data['tenant_id'], 'role' => $data['role'], 'email' => $data['email'], 'password_hash' => $passwordHash, 'first_name' => $data['first_name'], 'last_name' => $data['last_name'], 'is_active' => !empty($data['is_active']) ? 1 : 0, 'updated_at' => $this->now(), ]); return $this->findById($id); } }