connection->executeStatement( 'INSERT INTO student_averages (id, tenant_id, student_id, subject_id, period_id, average, grade_count, updated_at) VALUES (gen_random_uuid(), :tenant_id, :student_id, :subject_id, :period_id, :average, :grade_count, NOW()) ON CONFLICT (student_id, subject_id, period_id) DO UPDATE SET average = EXCLUDED.average, grade_count = EXCLUDED.grade_count, updated_at = NOW()', [ 'tenant_id' => (string) $tenantId, 'student_id' => (string) $studentId, 'subject_id' => (string) $subjectId, 'period_id' => $periodId, 'average' => $average, 'grade_count' => $gradeCount, ], ); } #[Override] public function saveGeneralAverage( TenantId $tenantId, UserId $studentId, string $periodId, float $average, ): void { $this->connection->executeStatement( 'INSERT INTO student_general_averages (id, tenant_id, student_id, period_id, average, updated_at) VALUES (gen_random_uuid(), :tenant_id, :student_id, :period_id, :average, NOW()) ON CONFLICT (student_id, period_id) DO UPDATE SET average = EXCLUDED.average, updated_at = NOW()', [ 'tenant_id' => (string) $tenantId, 'student_id' => (string) $studentId, 'period_id' => $periodId, 'average' => $average, ], ); } #[Override] public function findSubjectAveragesForStudent( UserId $studentId, string $periodId, TenantId $tenantId, ): array { $rows = $this->connection->fetchAllAssociative( 'SELECT average FROM student_averages WHERE student_id = :student_id AND period_id = :period_id AND tenant_id = :tenant_id', [ 'student_id' => (string) $studentId, 'period_id' => $periodId, 'tenant_id' => (string) $tenantId, ], ); return array_map( /** @param array $row */ static function (array $row): float { /** @var string|float $avg */ $avg = $row['average']; return (float) $avg; }, $rows, ); } #[Override] public function findDetailedSubjectAveragesForStudent( UserId $studentId, string $periodId, TenantId $tenantId, ): array { $rows = $this->connection->fetchAllAssociative( 'SELECT sa.subject_id, sa.average, sa.grade_count, s.name as subject_name FROM student_averages sa LEFT JOIN subjects s ON s.id = sa.subject_id WHERE sa.student_id = :student_id AND sa.period_id = :period_id AND sa.tenant_id = :tenant_id ORDER BY s.name ASC', [ 'student_id' => (string) $studentId, 'period_id' => $periodId, 'tenant_id' => (string) $tenantId, ], ); return array_map( /** @param array $row */ static function (array $row): array { /** @var string $subjectId */ $subjectId = $row['subject_id']; /** @var string|null $subjectName */ $subjectName = $row['subject_name']; /** @var string|float $average */ $average = $row['average']; /** @var string|int $gradeCount */ $gradeCount = $row['grade_count']; return [ 'subjectId' => $subjectId, 'subjectName' => $subjectName, 'average' => (float) $average, 'gradeCount' => (int) $gradeCount, ]; }, $rows, ); } #[Override] public function findGeneralAverageForStudent( UserId $studentId, string $periodId, TenantId $tenantId, ): ?float { $row = $this->connection->fetchAssociative( 'SELECT average FROM student_general_averages WHERE student_id = :student_id AND period_id = :period_id AND tenant_id = :tenant_id', [ 'student_id' => (string) $studentId, 'period_id' => $periodId, 'tenant_id' => (string) $tenantId, ], ); if ($row === false) { return null; } /** @var string|float $average */ $average = $row['average']; return (float) $average; } #[Override] public function deleteSubjectAverage( UserId $studentId, SubjectId $subjectId, string $periodId, TenantId $tenantId, ): void { $this->connection->executeStatement( 'DELETE FROM student_averages WHERE student_id = :student_id AND subject_id = :subject_id AND period_id = :period_id AND tenant_id = :tenant_id', [ 'student_id' => (string) $studentId, 'subject_id' => (string) $subjectId, 'period_id' => $periodId, 'tenant_id' => (string) $tenantId, ], ); } #[Override] public function deleteGeneralAverage( UserId $studentId, string $periodId, TenantId $tenantId, ): void { $this->connection->executeStatement( 'DELETE FROM student_general_averages WHERE student_id = :student_id AND period_id = :period_id AND tenant_id = :tenant_id', [ 'student_id' => (string) $studentId, 'period_id' => $periodId, 'tenant_id' => (string) $tenantId, ], ); } }