|
|
|
@@ -21,8 +21,10 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
protected $schoolYear;
|
|
|
|
|
protected $semester;
|
|
|
|
|
protected $adjustmentModel;
|
|
|
|
|
/** cache for roster presence per term */
|
|
|
|
|
/** Cache for roster presence per school year. */
|
|
|
|
|
private array $rosterPresenceCache = [];
|
|
|
|
|
/** Cache table-column checks to avoid repeated schema queries. */
|
|
|
|
|
private array $columnExistsCache = [];
|
|
|
|
|
// Inside ClassPreparationController (class scope, not inside a method)
|
|
|
|
|
private array $allowedPrepCategories = [
|
|
|
|
|
'Grade Box',
|
|
|
|
@@ -57,7 +59,7 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
$semParam = $this->request->getGet('semester');
|
|
|
|
|
$semester = (is_string($semParam) && $semParam !== '') ? (string)$semParam : (string)$this->semester;
|
|
|
|
|
$allowed = $this->allowedPrepCategories;
|
|
|
|
|
$limitToSemester = $this->hasRosterForSemester($schoolYear, $semester);
|
|
|
|
|
$hasRoster = $this->hasRosterForSchoolYear($schoolYear);
|
|
|
|
|
|
|
|
|
|
// 1) Get student count per class-section (distinct students, correct semester)
|
|
|
|
|
$scQ = $this->db->table('student_class sc')
|
|
|
|
@@ -65,13 +67,12 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
->join('students s', 's.id = sc.student_id', 'inner')
|
|
|
|
|
->where('s.is_active', 1)
|
|
|
|
|
->where('sc.school_year', $schoolYear);
|
|
|
|
|
if ($limitToSemester && $semester !== '') {
|
|
|
|
|
$scQ->where('sc.semester', $semester);
|
|
|
|
|
}
|
|
|
|
|
$classSections = $scQ->groupBy('sc.class_section_id')->get()->getResultArray();
|
|
|
|
|
$classSections = $hasRoster
|
|
|
|
|
? $scQ->groupBy('sc.class_section_id')->get()->getResultArray()
|
|
|
|
|
: [];
|
|
|
|
|
|
|
|
|
|
// 2) Inventory availability — prefer good_qty when present, else condition='good' quantity.
|
|
|
|
|
$inventoryMap = $this->buildInventoryAvailability($schoolYear, $semester, $limitToSemester, $allowed);
|
|
|
|
|
$inventoryMap = $this->buildInventoryAvailability($schoolYear, $semester, $allowed);
|
|
|
|
|
|
|
|
|
|
// Seed totals with allowed categories for stable ordering
|
|
|
|
|
$requiredTotals = array_fill_keys($allowed, 0);
|
|
|
|
@@ -85,14 +86,10 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
$className = $this->classSectionModel->getClassSectionNameBySectionId($classSectionId);
|
|
|
|
|
|
|
|
|
|
// Calculate required items (whitelist inside)
|
|
|
|
|
$baseItems = $this->calculatePrepItems($studentCount, $classLevel, $classSectionId);
|
|
|
|
|
$baseItems = $this->calculatePrepItems($studentCount, $classLevel, $classSectionId, $schoolYear);
|
|
|
|
|
|
|
|
|
|
// --- Apply adjustments (only Small/Large Table), clamp >= 0 ---
|
|
|
|
|
$rawAdjustments = $this->adjustmentModel
|
|
|
|
|
->where('class_section_id', $classSectionId)
|
|
|
|
|
->where('school_year', $schoolYear)
|
|
|
|
|
->where('adjustable', 1)
|
|
|
|
|
->findAll();
|
|
|
|
|
$rawAdjustments = $this->getAdjustments((string) $classSectionId, (string) $schoolYear);
|
|
|
|
|
|
|
|
|
|
$adjMap = ['Large Table' => 0, 'Small Table' => 0];
|
|
|
|
|
|
|
|
|
@@ -117,11 +114,7 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5) Compare with last snapshot; do not save here — only on print or explicit API
|
|
|
|
|
$oldSnap = $this->prepLogModel
|
|
|
|
|
->where('class_section_id', $classSectionId)
|
|
|
|
|
->where('school_year', $schoolYear)
|
|
|
|
|
->orderBy('created_at', 'DESC')
|
|
|
|
|
->first();
|
|
|
|
|
$oldSnap = $this->getLatestPrepSnapshot((string) $classSectionId, (string) $schoolYear);
|
|
|
|
|
|
|
|
|
|
$oldPrep = $oldSnap ? json_decode($oldSnap['prep_data'], true) : [];
|
|
|
|
|
$hasChanged = $this->hasPrepChanged($baseItems, $oldPrep);
|
|
|
|
@@ -175,7 +168,7 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
return (int)($row['cnt'] ?? 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function calculatePrepItems(int $students, int $classLevel, string $classSectionId): array
|
|
|
|
|
private function calculatePrepItems(int $students, int $classLevel, string $classSectionId, ?string $schoolYear = null): array
|
|
|
|
|
{
|
|
|
|
|
// 1) Stable keys: your whitelist, all zero to start
|
|
|
|
|
$allowed = $this->allowedPrepCategories;
|
|
|
|
@@ -192,7 +185,7 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
|
|
|
|
|
// 3) Rules
|
|
|
|
|
$isLowerGrades = in_array($classLevel, [1, 2], true);
|
|
|
|
|
$teacherCount = $this->getTeacherCountForSection($classSectionId, $this->schoolYear);
|
|
|
|
|
$teacherCount = $this->getTeacherCountForSection($classSectionId, $schoolYear ?? $this->schoolYear);
|
|
|
|
|
|
|
|
|
|
foreach ($categories as $cat) {
|
|
|
|
|
$name = $cat['name']; // e.g., 'Small Table'
|
|
|
|
@@ -253,24 +246,35 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
$adjustments = $data['adjustments'] ?? [];
|
|
|
|
|
|
|
|
|
|
foreach ($adjustments as $itemName => $adjustment) {
|
|
|
|
|
$row = $this->adjustmentModel
|
|
|
|
|
$adjustmentQuery = $this->adjustmentModel
|
|
|
|
|
->where('class_section_id', $sectionId)
|
|
|
|
|
->where('school_year', $schoolYear)
|
|
|
|
|
->where('item_name', $itemName)
|
|
|
|
|
->first();
|
|
|
|
|
->where('item_name', $itemName);
|
|
|
|
|
|
|
|
|
|
$adjustmentTable = $this->adjustmentModel->getTable();
|
|
|
|
|
|
|
|
|
|
if ($schoolYear !== '' && $this->tableHasColumn($adjustmentTable, 'school_year')) {
|
|
|
|
|
$adjustmentQuery->where('school_year', $schoolYear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$row = $adjustmentQuery->first();
|
|
|
|
|
|
|
|
|
|
if ($row) {
|
|
|
|
|
// Update
|
|
|
|
|
$this->adjustmentModel->update($row['id'], ['adjustment' => (int)$adjustment, 'adjustable' => 1]);
|
|
|
|
|
} else {
|
|
|
|
|
// Insert
|
|
|
|
|
$this->adjustmentModel->insert([
|
|
|
|
|
$insertData = [
|
|
|
|
|
'class_section_id' => $sectionId,
|
|
|
|
|
'item_name' => $itemName,
|
|
|
|
|
'adjustment' => (int)$adjustment,
|
|
|
|
|
'school_year' => $schoolYear,
|
|
|
|
|
'adjustment' => (int) $adjustment,
|
|
|
|
|
'adjustable' => 1,
|
|
|
|
|
]);
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if ($schoolYear !== '' && $this->tableHasColumn($adjustmentTable, 'school_year')) {
|
|
|
|
|
$insertData['school_year'] = $schoolYear;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->adjustmentModel->insert($insertData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -292,10 +296,6 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
|
|
|
|
|
public function print($classSectionId, $schoolYear)
|
|
|
|
|
{
|
|
|
|
|
$semParam = $this->request->getGet('semester');
|
|
|
|
|
$semester = (is_string($semParam) && $semParam !== '') ? (string) $semParam : (string) $this->semester;
|
|
|
|
|
$limitToSemester = $this->hasRosterForSemester((string) $schoolYear, $semester);
|
|
|
|
|
|
|
|
|
|
// Friendly label (if you have this helper)
|
|
|
|
|
$className = $this->classSectionModel->getClassSectionNameBySectionId($classSectionId) ?? $classSectionId;
|
|
|
|
|
|
|
|
|
@@ -306,15 +306,12 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
->where('s.is_active', 1)
|
|
|
|
|
->where('sc.class_section_id', $classSectionId)
|
|
|
|
|
->where('sc.school_year', $schoolYear);
|
|
|
|
|
if ($limitToSemester && $semester !== '') {
|
|
|
|
|
$studentQ->where('sc.semester', $semester);
|
|
|
|
|
}
|
|
|
|
|
$studentRow = $studentQ->get()->getRowArray();
|
|
|
|
|
$studentCount = (int)($studentRow['cnt'] ?? 0);
|
|
|
|
|
|
|
|
|
|
// Live calc + adjustments
|
|
|
|
|
$classLevel = $this->getClassLevelBySection((string)$classSectionId);
|
|
|
|
|
$items = $this->calculatePrepItems($studentCount, $classLevel, (string)$classSectionId);
|
|
|
|
|
$items = $this->calculatePrepItems($studentCount, $classLevel, (string)$classSectionId, (string)$schoolYear);
|
|
|
|
|
|
|
|
|
|
$rawAdjustments = $this->adjustmentModel
|
|
|
|
|
->where('class_section_id', $classSectionId)
|
|
|
|
@@ -328,13 +325,15 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Record a snapshot at print time as the new baseline
|
|
|
|
|
$this->prepLogModel->insert([
|
|
|
|
|
'class_section_id' => (string)$classSectionId,
|
|
|
|
|
'class_section' => $className,
|
|
|
|
|
'school_year' => $schoolYear,
|
|
|
|
|
'prep_data' => json_encode($items),
|
|
|
|
|
'created_at' => utc_now(),
|
|
|
|
|
]);
|
|
|
|
|
$this->prepLogModel->insert(
|
|
|
|
|
$this->buildPrepLogData(
|
|
|
|
|
(string) $classSectionId,
|
|
|
|
|
(string) $className,
|
|
|
|
|
(string) $schoolYear,
|
|
|
|
|
$items,
|
|
|
|
|
utc_now()
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Return PRINT view (HTML) that auto-opens the print dialog
|
|
|
|
|
return view('class_prep/print', [
|
|
|
|
@@ -356,7 +355,7 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
$semParam = $this->request->getGet('semester');
|
|
|
|
|
$semester = (is_string($semParam) && $semParam !== '') ? (string)$semParam : (string)$this->semester;
|
|
|
|
|
$allowed = $this->allowedPrepCategories;
|
|
|
|
|
$limitToSemester = $this->hasRosterForSemester($schoolYear, $semester);
|
|
|
|
|
$hasRoster = $this->hasRosterForSchoolYear($schoolYear);
|
|
|
|
|
|
|
|
|
|
// Student counts
|
|
|
|
|
$scQ = $this->db->table('student_class sc')
|
|
|
|
@@ -364,13 +363,12 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
->join('students s', 's.id = sc.student_id', 'inner')
|
|
|
|
|
->where('s.is_active', 1)
|
|
|
|
|
->where('sc.school_year', $schoolYear);
|
|
|
|
|
if ($limitToSemester && $semester !== '') {
|
|
|
|
|
$scQ->where('sc.semester', $semester);
|
|
|
|
|
}
|
|
|
|
|
$classSections = $scQ->groupBy('sc.class_section_id')->get()->getResultArray();
|
|
|
|
|
$classSections = $hasRoster
|
|
|
|
|
? $scQ->groupBy('sc.class_section_id')->get()->getResultArray()
|
|
|
|
|
: [];
|
|
|
|
|
|
|
|
|
|
// Build inventory availability maps
|
|
|
|
|
$inventoryMap = $this->buildInventoryAvailability($schoolYear, $semester, $limitToSemester, $allowed);
|
|
|
|
|
$inventoryMap = $this->buildInventoryAvailability($schoolYear, $semester, $allowed);
|
|
|
|
|
|
|
|
|
|
$requiredTotals = array_fill_keys($allowed, 0);
|
|
|
|
|
$results = [];
|
|
|
|
@@ -381,12 +379,8 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
$classLevel = $this->getClassLevelBySection($classSectionId);
|
|
|
|
|
$className = $this->classSectionModel->getClassSectionNameBySectionId($classSectionId);
|
|
|
|
|
|
|
|
|
|
$baseItems = $this->calculatePrepItems($studentCount, $classLevel, $classSectionId);
|
|
|
|
|
$rawAdjustments = $this->adjustmentModel
|
|
|
|
|
->where('class_section_id', $classSectionId)
|
|
|
|
|
->where('school_year', $schoolYear)
|
|
|
|
|
->where('adjustable', 1)
|
|
|
|
|
->findAll();
|
|
|
|
|
$baseItems = $this->calculatePrepItems($studentCount, $classLevel, $classSectionId, $schoolYear);
|
|
|
|
|
$rawAdjustments = $this->getAdjustments((string) $classSectionId, (string) $schoolYear);
|
|
|
|
|
$adjMap = ['Large Table' => 0, 'Small Table' => 0];
|
|
|
|
|
foreach ($rawAdjustments as $a) {
|
|
|
|
|
$item = $a['item_name'];
|
|
|
|
@@ -399,11 +393,7 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
$requiredTotals[$cat] += (int)($baseItems[$cat] ?? 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$oldSnap = $this->prepLogModel
|
|
|
|
|
->where('class_section_id', $classSectionId)
|
|
|
|
|
->where('school_year', $schoolYear)
|
|
|
|
|
->orderBy('created_at', 'DESC')
|
|
|
|
|
->first();
|
|
|
|
|
$oldSnap = $this->getLatestPrepSnapshot((string) $classSectionId, (string) $schoolYear);
|
|
|
|
|
$oldPrep = $oldSnap ? json_decode($oldSnap['prep_data'], true) : [];
|
|
|
|
|
$hasChanged = $this->hasPrepChanged($baseItems, $oldPrep);
|
|
|
|
|
|
|
|
|
@@ -446,7 +436,6 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
$schoolYear = (string)($this->request->getPost('school_year') ?? $this->schoolYear);
|
|
|
|
|
$semParam = $this->request->getPost('semester');
|
|
|
|
|
$semester = (is_string($semParam) && $semParam !== '') ? (string)$semParam : (string)$this->semester;
|
|
|
|
|
$limitToSemester = $this->hasRosterForSemester($schoolYear, $semester);
|
|
|
|
|
$ids = $this->request->getPost('class_section_ids') ?? [];
|
|
|
|
|
if (!is_array($ids)) $ids = $ids ? [$ids] : [];
|
|
|
|
|
$ids = array_values(array_unique(array_filter(array_map('strval', $ids))));
|
|
|
|
@@ -460,21 +449,14 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
->where('s.is_active', 1)
|
|
|
|
|
->where('sc.class_section_id', $classSectionId)
|
|
|
|
|
->where('sc.school_year', $schoolYear);
|
|
|
|
|
if ($limitToSemester && $semester !== '') {
|
|
|
|
|
$studentQ->where('sc.semester', $semester);
|
|
|
|
|
}
|
|
|
|
|
$studentRow = $studentQ->get()->getRowArray();
|
|
|
|
|
$studentCount = (int)($studentRow['cnt'] ?? 0);
|
|
|
|
|
$classLevel = $this->getClassLevelBySection((string)$classSectionId);
|
|
|
|
|
$className = $this->classSectionModel->getClassSectionNameBySectionId($classSectionId) ?? $classSectionId;
|
|
|
|
|
|
|
|
|
|
$items = $this->calculatePrepItems($studentCount, $classLevel, (string)$classSectionId);
|
|
|
|
|
$items = $this->calculatePrepItems($studentCount, $classLevel, (string)$classSectionId, (string)$schoolYear);
|
|
|
|
|
|
|
|
|
|
$rawAdjustments = $this->adjustmentModel
|
|
|
|
|
->where('class_section_id', $classSectionId)
|
|
|
|
|
->where('school_year', $schoolYear)
|
|
|
|
|
->where('adjustable', 1)
|
|
|
|
|
->findAll();
|
|
|
|
|
$rawAdjustments = $this->getAdjustments((string) $classSectionId, (string) $schoolYear);
|
|
|
|
|
foreach ($rawAdjustments as $a) {
|
|
|
|
|
$item = $a['item_name'];
|
|
|
|
|
$delta = (int)$a['adjustment'];
|
|
|
|
@@ -482,13 +464,15 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$this->prepLogModel->insert([
|
|
|
|
|
'class_section_id' => (string)$classSectionId,
|
|
|
|
|
'class_section' => $className,
|
|
|
|
|
'school_year' => $schoolYear,
|
|
|
|
|
'prep_data' => json_encode($items),
|
|
|
|
|
'created_at' => $now,
|
|
|
|
|
]);
|
|
|
|
|
$this->prepLogModel->insert(
|
|
|
|
|
$this->buildPrepLogData(
|
|
|
|
|
(string) $classSectionId,
|
|
|
|
|
(string) $className,
|
|
|
|
|
(string) $schoolYear,
|
|
|
|
|
$items,
|
|
|
|
|
$now
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
$count++;
|
|
|
|
|
} catch (\Throwable $e) {
|
|
|
|
|
// ignore and continue
|
|
|
|
@@ -528,12 +512,12 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if student_class has any rows for the given school year.
|
|
|
|
|
* The semester argument is ignored because assignments are tracked per year.
|
|
|
|
|
* Returns true when student_class contains at least one assignment
|
|
|
|
|
* for the selected school year.
|
|
|
|
|
*/
|
|
|
|
|
private function hasRosterForTerm(string $schoolYear, string $semester): bool
|
|
|
|
|
private function hasRosterForSchoolYear(string $schoolYear): bool
|
|
|
|
|
{
|
|
|
|
|
$year = trim((string)$schoolYear);
|
|
|
|
|
$year = trim($schoolYear);
|
|
|
|
|
if ($year === '') {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@@ -542,75 +526,154 @@ class ClassPreparationController extends BaseController
|
|
|
|
|
return $this->rosterPresenceCache[$year];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$cnt = $this->db->table('student_class')
|
|
|
|
|
$exists = $this->db->table('student_class')
|
|
|
|
|
->where('school_year', $year)
|
|
|
|
|
->countAllResults();
|
|
|
|
|
->limit(1)
|
|
|
|
|
->countAllResults() > 0;
|
|
|
|
|
|
|
|
|
|
$this->rosterPresenceCache[$year] = $cnt > 0;
|
|
|
|
|
return $this->rosterPresenceCache[$year];
|
|
|
|
|
$this->rosterPresenceCache[$year] = $exists;
|
|
|
|
|
|
|
|
|
|
return $exists;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function hasRosterForSemester(string $schoolYear, string $semester): bool
|
|
|
|
|
private function tableHasColumn(string $table, string $column): bool
|
|
|
|
|
{
|
|
|
|
|
$year = trim((string)$schoolYear);
|
|
|
|
|
$sem = trim((string)$semester);
|
|
|
|
|
if ($year === '' || $sem === '') {
|
|
|
|
|
return false;
|
|
|
|
|
$key = $table . '.' . $column;
|
|
|
|
|
|
|
|
|
|
if (!array_key_exists($key, $this->columnExistsCache)) {
|
|
|
|
|
$this->columnExistsCache[$key] = $this->db->fieldExists($column, $table);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$key = sprintf('sem:%s:%s', $year, $sem);
|
|
|
|
|
if (array_key_exists($key, $this->rosterPresenceCache)) {
|
|
|
|
|
return $this->rosterPresenceCache[$key];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$cnt = $this->db->table('student_class')
|
|
|
|
|
->where('school_year', $year)
|
|
|
|
|
->where('semester', $sem)
|
|
|
|
|
->countAllResults();
|
|
|
|
|
|
|
|
|
|
$this->rosterPresenceCache[$key] = $cnt > 0;
|
|
|
|
|
return $this->rosterPresenceCache[$key];
|
|
|
|
|
return $this->columnExistsCache[$key];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function buildInventoryAvailability(string $schoolYear, string $semester, bool $limitToSemester, array $allowed): array
|
|
|
|
|
private function getAdjustments(string $classSectionId, string $schoolYear): array
|
|
|
|
|
{
|
|
|
|
|
$query = $this->adjustmentModel
|
|
|
|
|
->where('class_section_id', $classSectionId)
|
|
|
|
|
->where('adjustable', 1);
|
|
|
|
|
|
|
|
|
|
$table = $this->adjustmentModel->getTable();
|
|
|
|
|
|
|
|
|
|
if ($schoolYear !== '' && $this->tableHasColumn($table, 'school_year')) {
|
|
|
|
|
$query->where('school_year', $schoolYear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $query->findAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function getLatestPrepSnapshot(string $classSectionId, string $schoolYear): ?array
|
|
|
|
|
{
|
|
|
|
|
$query = $this->prepLogModel
|
|
|
|
|
->where('class_section_id', $classSectionId);
|
|
|
|
|
|
|
|
|
|
$table = $this->prepLogModel->getTable();
|
|
|
|
|
|
|
|
|
|
if ($schoolYear !== '' && $this->tableHasColumn($table, 'school_year')) {
|
|
|
|
|
$query->where('school_year', $schoolYear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $query
|
|
|
|
|
->orderBy('created_at', 'DESC')
|
|
|
|
|
->first();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function buildPrepLogData(
|
|
|
|
|
string $classSectionId,
|
|
|
|
|
string $className,
|
|
|
|
|
string $schoolYear,
|
|
|
|
|
array $items,
|
|
|
|
|
string $createdAt
|
|
|
|
|
): array {
|
|
|
|
|
$data = [
|
|
|
|
|
'class_section_id' => $classSectionId,
|
|
|
|
|
'class_section' => $className,
|
|
|
|
|
'prep_data' => json_encode($items),
|
|
|
|
|
'created_at' => $createdAt,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$table = $this->prepLogModel->getTable();
|
|
|
|
|
|
|
|
|
|
if ($schoolYear !== '' && $this->tableHasColumn($table, 'school_year')) {
|
|
|
|
|
$data['school_year'] = $schoolYear;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function buildInventoryAvailability(string $schoolYear, string $semester, array $allowed): array
|
|
|
|
|
{
|
|
|
|
|
$inventoryMap = array_fill_keys($allowed, 0);
|
|
|
|
|
|
|
|
|
|
$hasSchoolYear = $this->tableHasColumn('inventory_items', 'school_year');
|
|
|
|
|
$hasSemester = $this->tableHasColumn('inventory_items', 'semester');
|
|
|
|
|
$hasName = $this->tableHasColumn('inventory_items', 'name');
|
|
|
|
|
|
|
|
|
|
$joinRows = $this->db->table('inventory_items ii')
|
|
|
|
|
->select('ic.name AS item_name, COALESCE(SUM(CASE WHEN ii.good_qty IS NOT NULL THEN ii.good_qty WHEN ii.`condition`="good" THEN ii.quantity ELSE 0 END),0) AS available')
|
|
|
|
|
->select('ic.name AS item_name, COALESCE(SUM(CASE WHEN ii.good_qty IS NOT NULL THEN ii.good_qty WHEN ii.`condition` = "good" THEN ii.quantity ELSE 0 END), 0) AS available', false)
|
|
|
|
|
->join('inventory_categories ic', 'ic.id = ii.category_id', 'left')
|
|
|
|
|
->where('ii.type', 'classroom')
|
|
|
|
|
->where('ii.school_year', $schoolYear)
|
|
|
|
|
->whereIn('ic.name', $allowed);
|
|
|
|
|
if ($limitToSemester && $semester !== '') {
|
|
|
|
|
|
|
|
|
|
if ($hasSchoolYear && $schoolYear !== '') {
|
|
|
|
|
$joinRows->where('ii.school_year', $schoolYear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($hasSemester && $semester !== '') {
|
|
|
|
|
$joinRows->where('ii.semester', $semester);
|
|
|
|
|
}
|
|
|
|
|
$joinRows = $joinRows->groupBy('ic.name')->get()->getResultArray();
|
|
|
|
|
|
|
|
|
|
foreach ($joinRows as $r) {
|
|
|
|
|
$name = (string)($r['item_name'] ?? '');
|
|
|
|
|
if ($name !== '' && isset($inventoryMap[$name])) {
|
|
|
|
|
$inventoryMap[$name] = max($inventoryMap[$name], (int)($r['available'] ?? 0));
|
|
|
|
|
$joinRows = $joinRows
|
|
|
|
|
->groupBy('ic.name')
|
|
|
|
|
->get()
|
|
|
|
|
->getResultArray();
|
|
|
|
|
|
|
|
|
|
foreach ($joinRows as $row) {
|
|
|
|
|
$name = (string) ($row['item_name'] ?? '');
|
|
|
|
|
|
|
|
|
|
if ($name !== '' && array_key_exists($name, $inventoryMap)) {
|
|
|
|
|
$inventoryMap[$name] = max(
|
|
|
|
|
$inventoryMap[$name],
|
|
|
|
|
(int) ($row['available'] ?? 0)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$nameRows = $this->db->table('inventory_items')
|
|
|
|
|
->select('name AS item_name, COALESCE(SUM(CASE WHEN good_qty IS NOT NULL THEN good_qty WHEN `condition`="good" THEN quantity ELSE 0 END),0) AS available')
|
|
|
|
|
->where('type', 'classroom')
|
|
|
|
|
->where('school_year', $schoolYear)
|
|
|
|
|
->whereIn('name', $allowed);
|
|
|
|
|
if ($limitToSemester && $semester !== '') {
|
|
|
|
|
$nameRows->where('semester', $semester);
|
|
|
|
|
}
|
|
|
|
|
$nameRows = $nameRows->groupBy('name')->get()->getResultArray();
|
|
|
|
|
/*
|
|
|
|
|
* Some older schemas store the item name directly on inventory_items.
|
|
|
|
|
* Only run this fallback when that column actually exists.
|
|
|
|
|
*/
|
|
|
|
|
if ($hasName) {
|
|
|
|
|
$nameRows = $this->db->table('inventory_items')
|
|
|
|
|
->select('name AS item_name, COALESCE(SUM(CASE WHEN good_qty IS NOT NULL THEN good_qty WHEN `condition` = "good" THEN quantity ELSE 0 END), 0) AS available', false)
|
|
|
|
|
->where('type', 'classroom')
|
|
|
|
|
->whereIn('name', $allowed);
|
|
|
|
|
|
|
|
|
|
foreach ($nameRows as $r) {
|
|
|
|
|
$name = (string)($r['item_name'] ?? '');
|
|
|
|
|
if ($name !== '' && isset($inventoryMap[$name])) {
|
|
|
|
|
$inventoryMap[$name] = max($inventoryMap[$name], (int)($r['available'] ?? 0));
|
|
|
|
|
if ($hasSchoolYear && $schoolYear !== '') {
|
|
|
|
|
$nameRows->where('school_year', $schoolYear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($hasSemester && $semester !== '') {
|
|
|
|
|
$nameRows->where('semester', $semester);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$nameRows = $nameRows
|
|
|
|
|
->groupBy('name')
|
|
|
|
|
->get()
|
|
|
|
|
->getResultArray();
|
|
|
|
|
|
|
|
|
|
foreach ($nameRows as $row) {
|
|
|
|
|
$name = (string) ($row['item_name'] ?? '');
|
|
|
|
|
|
|
|
|
|
if ($name !== '' && array_key_exists($name, $inventoryMap)) {
|
|
|
|
|
$inventoryMap[$name] = max(
|
|
|
|
|
$inventoryMap[$name],
|
|
|
|
|
(int) ($row['available'] ?? 0)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $inventoryMap;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|