context = $context; $this->roster = $roster; $this->inventory = $inventory; $this->calculator = $calculator; $this->adjustments = $adjustments; $this->logs = $logs; } public function listPrep(?string $schoolYear = null, ?string $semester = null): array { $schoolYear = $schoolYear ?: $this->context->getSchoolYear(); $semester = $semester ?: $this->context->getSemester(); $allowed = $this->calculator->getAllowedCategories(); $limitToSemester = $this->context->hasRosterForSemester($schoolYear, $semester); $classSections = $this->roster->getClassSectionStudentCounts($schoolYear, $semester, $limitToSemester); $inventoryMap = $this->inventory->buildAvailability($schoolYear, $semester, $limitToSemester, $allowed); $requiredTotals = array_fill_keys($allowed, 0); $results = []; foreach ($classSections as $row) { $classSectionId = (string) $row->class_section_id; $studentCount = (int) $row->student_count; $classLevel = $this->calculator->getClassLevelBySection($classSectionId); $className = ClassSection::getClassSectionNameBySectionId($classSectionId); $baseItems = $this->calculator->calculatePrepItems($studentCount, $classLevel, $classSectionId); [$baseItems, $adjMap] = $this->adjustments->applyAdjustments($baseItems, $classSectionId, $schoolYear); foreach ($allowed as $cat) { $requiredTotals[$cat] += (int) ($baseItems[$cat] ?? 0); } $oldSnap = $this->logs->getLatestLog($classSectionId, $schoolYear); $oldPrep = $oldSnap ? (array) ($oldSnap->prep_data ?? []) : []; $hasChanged = $this->logs->hasPrepChanged($baseItems, $oldPrep); $results[] = [ 'class_section' => $className, 'class_section_id' => $classSectionId, 'student_count' => $studentCount, 'class_level' => $classLevel, 'prep_items' => $baseItems, 'needs_print' => $hasChanged, 'last_printed_at' => $oldSnap?->created_at, 'adjustments' => $adjMap, ]; } $shortages = []; foreach ($requiredTotals as $item => $reqQty) { $have = (int) ($inventoryMap[$item] ?? 0); if ($have < (int) $reqQty) { $shortages[$item] = (int) $reqQty - $have; } } return [ 'schoolYear' => $schoolYear, 'semester' => $semester, 'results' => $results, 'totals' => $requiredTotals, 'shortages' => $shortages, ]; } public function markPrinted(string $schoolYear, string $semester, array $classSectionIds): int { $limitToSemester = $this->context->hasRosterForSemester($schoolYear, $semester); $ids = array_values(array_unique(array_filter(array_map('strval', $classSectionIds)))); $now = $this->utcNow(); $count = 0; foreach ($ids as $classSectionId) { $studentCount = $this->roster->getStudentCountForSection($schoolYear, $semester, $limitToSemester, $classSectionId); $classLevel = $this->calculator->getClassLevelBySection($classSectionId); $className = ClassSection::getClassSectionNameBySectionId($classSectionId) ?? $classSectionId; $items = $this->calculator->calculatePrepItems($studentCount, $classLevel, $classSectionId); [$items] = $this->adjustments->applyAdjustments($items, $classSectionId, $schoolYear); if ($this->logs->createLog($classSectionId, $className, $schoolYear, $items, $now)) { $count++; } } return $count; } private function utcNow(): string { if (function_exists('utc_now')) { return (string) utc_now(); } return now('UTC')->toDateTimeString(); } }