@@ -570,21 +570,21 @@ class AdministratorController extends BaseController
|
||||
// USERS (phone col: cellphone)
|
||||
$uCols = ['firstname', 'lastname', 'email', 'cellphone', 'school_id', 'city', 'state'];
|
||||
$uQB = $db->table('users')
|
||||
->select('id, firstname, lastname, email, cellphone, school_id, city, state, school_year, semester');
|
||||
->select('id, firstname, lastname, email, cellphone, school_id, city, state, semester');
|
||||
$applyMultiTokenLike($uQB, $uCols, $tokens, ['cellphone']);
|
||||
$users = $uQB->limit(150)->get()->getResultArray();
|
||||
|
||||
// STUDENTS (no phone column to search)
|
||||
$sCols = ['firstname', 'lastname', 'school_id', 'rfid_tag', 'dob', 'gender'];
|
||||
$sQB = $db->table('students')
|
||||
->select('id, parent_id, school_id, firstname, lastname, dob, gender, school_year, semester, rfid_tag');
|
||||
->select('id, parent_id, school_id, firstname, lastname, dob, gender, semester, rfid_tag');
|
||||
$applyMultiTokenLike($sQB, $sCols, $tokens, []);
|
||||
$students = $sQB->limit(150)->get()->getResultArray();
|
||||
|
||||
// PARENTS (phone col: secondparent_phone)
|
||||
$pCols = ['secondparent_firstname', 'secondparent_lastname', 'secondparent_email', 'secondparent_phone'];
|
||||
$pQB = $db->table('parents')
|
||||
->select('id, firstparent_id, secondparent_firstname, secondparent_lastname, secondparent_email, secondparent_phone, school_year, semester');
|
||||
->select('id, firstparent_id, secondparent_firstname, secondparent_lastname, secondparent_email, secondparent_phone');
|
||||
$applyMultiTokenLike($pQB, $pCols, $tokens, ['secondparent_phone']);
|
||||
foreach ($tokens as $t) {
|
||||
if (ctype_digit($t)) {
|
||||
@@ -596,14 +596,14 @@ class AdministratorController extends BaseController
|
||||
// STAFF (phone col: phone)
|
||||
$stCols = ['firstname', 'lastname', 'email', 'role_name', 'phone'];
|
||||
$stQB = $db->table('staff')
|
||||
->select('id, user_id, firstname, lastname, email, phone, role_name, school_year, active_role');
|
||||
->select('id, user_id, firstname, lastname, email, phone, role_name, active_role');
|
||||
$applyMultiTokenLike($stQB, $stCols, $tokens, ['phone']);
|
||||
$staff = $stQB->limit(150)->get()->getResultArray();
|
||||
|
||||
// EMERGENCY CONTACTS (phone col: cellphone)
|
||||
$ecCols = ['emergency_contact_name', 'relation', 'email', 'cellphone'];
|
||||
$ecQB = $db->table('emergency_contacts')
|
||||
->select('id, parent_id, emergency_contact_name, relation, cellphone, email, school_year, semester');
|
||||
->select('id, parent_id, emergency_contact_name, relation, cellphone, email');
|
||||
$applyMultiTokenLike($ecQB, $ecCols, $tokens, ['cellphone']);
|
||||
$emergency = $ecQB->limit(150)->get()->getResultArray();
|
||||
|
||||
@@ -2202,7 +2202,6 @@ class AdministratorController extends BaseController
|
||||
'cellphone' => $user['cellphone'],
|
||||
'gender' => $user['gender'],
|
||||
'created_at' => $user['created_at'],
|
||||
'school_year' => $user['school_year'],
|
||||
'paid_amount' => $paidAmount,
|
||||
'balance' => $balance,
|
||||
'students' => $students,
|
||||
|
||||
@@ -605,8 +605,6 @@ class ClassPreparationController extends BaseController
|
||||
{
|
||||
$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')
|
||||
@@ -615,12 +613,19 @@ class ClassPreparationController extends BaseController
|
||||
->where('ii.type', 'classroom')
|
||||
->whereIn('ic.name', $allowed);
|
||||
|
||||
if ($hasSchoolYear && $schoolYear !== '') {
|
||||
$joinRows->where('ii.school_year', $schoolYear);
|
||||
$periodClauses = ['im.item_id = ii.id'];
|
||||
if ($schoolYear !== '') {
|
||||
$periodClauses[] = 'im.school_year = ' . $this->db->escape($schoolYear);
|
||||
}
|
||||
|
||||
if ($hasSemester && $semester !== '') {
|
||||
$joinRows->where('ii.semester', $semester);
|
||||
if ($semester !== '') {
|
||||
$periodClauses[] = 'im.semester = ' . $this->db->escape($semester);
|
||||
}
|
||||
if (count($periodClauses) > 1) {
|
||||
$joinRows->where(
|
||||
'EXISTS (SELECT 1 FROM inventory_movements im WHERE ' . implode(' AND ', $periodClauses) . ')',
|
||||
null,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
$joinRows = $joinRows
|
||||
@@ -644,21 +649,28 @@ class ClassPreparationController extends BaseController
|
||||
* 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);
|
||||
$nameRows = $this->db->table('inventory_items ii_name')
|
||||
->select('ii_name.name AS item_name, COALESCE(SUM(CASE WHEN ii_name.good_qty IS NOT NULL THEN ii_name.good_qty WHEN ii_name.`condition` = "good" THEN ii_name.quantity ELSE 0 END), 0) AS available', false)
|
||||
->where('ii_name.type', 'classroom')
|
||||
->whereIn('ii_name.name', $allowed);
|
||||
|
||||
if ($hasSchoolYear && $schoolYear !== '') {
|
||||
$nameRows->where('school_year', $schoolYear);
|
||||
$fallbackPeriodClauses = ['im.item_id = ii_name.id'];
|
||||
if ($schoolYear !== '') {
|
||||
$fallbackPeriodClauses[] = 'im.school_year = ' . $this->db->escape($schoolYear);
|
||||
}
|
||||
|
||||
if ($hasSemester && $semester !== '') {
|
||||
$nameRows->where('semester', $semester);
|
||||
if ($semester !== '') {
|
||||
$fallbackPeriodClauses[] = 'im.semester = ' . $this->db->escape($semester);
|
||||
}
|
||||
if (count($fallbackPeriodClauses) > 1) {
|
||||
$nameRows->where(
|
||||
'EXISTS (SELECT 1 FROM inventory_movements im WHERE ' . implode(' AND ', $fallbackPeriodClauses) . ')',
|
||||
null,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
$nameRows = $nameRows
|
||||
->groupBy('name')
|
||||
->groupBy('ii_name.name')
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
@@ -676,4 +688,4 @@ class ClassPreparationController extends BaseController
|
||||
|
||||
return $inventoryMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ class FamilyAdminController extends BaseController
|
||||
if ($gid > 0) $gmap[$gid] = trim(($g['firstname'] ?? '') . ' ' . ($g['lastname'] ?? ''));
|
||||
}
|
||||
$ecRows = $db->table('emergency_contacts')
|
||||
->select('id, parent_id, emergency_contact_name, relation, cellphone, email, school_year, semester, created_at, updated_at')
|
||||
->select('id, parent_id, emergency_contact_name, relation, cellphone, email, created_at, updated_at')
|
||||
->whereIn('parent_id', $parentIds)
|
||||
->orderBy('updated_at', 'DESC')
|
||||
->get()->getResultArray();
|
||||
|
||||
@@ -706,7 +706,6 @@ class GradingController extends Controller
|
||||
|
||||
$existing = $this->placementLevelModel
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $schoolYear)
|
||||
->first();
|
||||
|
||||
if ($level === null) {
|
||||
@@ -718,7 +717,6 @@ class GradingController extends Controller
|
||||
|
||||
$payload = [
|
||||
'student_id' => $studentId,
|
||||
'school_year' => $schoolYear,
|
||||
'level' => $level,
|
||||
'updated_by' => session()->get('user_id'),
|
||||
];
|
||||
@@ -768,7 +766,6 @@ class GradingController extends Controller
|
||||
if (!empty($studentIds)) {
|
||||
$rows = $this->placementLevelModel
|
||||
->whereIn('student_id', $studentIds)
|
||||
->where('school_year', $schoolYear)
|
||||
->findAll();
|
||||
foreach ($rows as $row) {
|
||||
$levels[(int) $row['student_id']] = $row['level'] ?? null;
|
||||
@@ -806,7 +803,6 @@ class GradingController extends Controller
|
||||
if (!empty($validIds)) {
|
||||
$rows = $this->placementLevelModel
|
||||
->whereIn('student_id', $validIds)
|
||||
->where('school_year', $schoolYear)
|
||||
->findAll();
|
||||
foreach ($rows as $row) {
|
||||
$existingRows[(int) $row['student_id']] = $row;
|
||||
@@ -834,7 +830,6 @@ class GradingController extends Controller
|
||||
|
||||
$payload = [
|
||||
'student_id' => $studentId,
|
||||
'school_year' => $schoolYear,
|
||||
'level' => $level,
|
||||
'updated_by' => $userId,
|
||||
];
|
||||
@@ -1648,7 +1643,7 @@ public function belowSixty()
|
||||
->join('students s', 's.id = sc.student_id', 'inner')
|
||||
->join(
|
||||
'placement_levels pl',
|
||||
"pl.student_id = s.id AND pl.school_year = {$yrEsc}",
|
||||
'pl.student_id = s.id',
|
||||
'left'
|
||||
)
|
||||
|
||||
|
||||
@@ -75,12 +75,7 @@ class InventoryController extends BaseController
|
||||
$selectedSem = $selectedSemRaw === null ? (string) $this->semester : trim((string) $selectedSemRaw);
|
||||
|
||||
$builder = $this->itemModel->where('type', $type);
|
||||
if (strtolower($selectedYear) !== 'all') {
|
||||
$builder->where('school_year', $selectedYear);
|
||||
}
|
||||
if ($selectedSem !== '') {
|
||||
$builder->where('semester', $selectedSem);
|
||||
}
|
||||
$this->applyInventoryMovementPeriodFilter($builder, 'inventory_items', $selectedYear, $selectedSem);
|
||||
|
||||
$items = $builder->orderBy('name', 'ASC')->findAll();
|
||||
$categories = $this->catModel->optionsForType($type);
|
||||
@@ -474,17 +469,26 @@ class InventoryController extends BaseController
|
||||
// Distinct school years for a given inventory type (newest first).
|
||||
private function getSchoolYearsForType(string $type): array
|
||||
{
|
||||
// Pull distinct non-null school_year values for this type
|
||||
$years = $this->itemModel
|
||||
->select('school_year')
|
||||
->where('type', $type)
|
||||
->where('school_year IS NOT NULL', null, false)
|
||||
->groupBy('school_year')
|
||||
->orderBy('school_year', 'DESC')
|
||||
->findColumn('school_year') ?? [];
|
||||
$rows = $this->db->table('inventory_movements m')
|
||||
->distinct()
|
||||
->select('m.school_year')
|
||||
->join('inventory_items i', 'i.id = m.item_id', 'inner')
|
||||
->where('m.school_year IS NOT NULL', null, false)
|
||||
->where("TRIM(m.school_year) <>", '')
|
||||
->orderBy('m.school_year', 'DESC');
|
||||
|
||||
if (strtolower($type) !== 'all') {
|
||||
$rows->where('i.type', $type);
|
||||
}
|
||||
|
||||
$rows = $rows->get()
|
||||
->getResultArray();
|
||||
|
||||
// Normalize & de-dup
|
||||
$years = array_values(array_unique(array_filter(array_map('trim', $years))));
|
||||
$years = array_values(array_unique(array_filter(array_map(
|
||||
static fn(array $row): string => trim((string)($row['school_year'] ?? '')),
|
||||
$rows
|
||||
))));
|
||||
|
||||
// Ensure the current year (from config) appears as an option, even if no rows yet
|
||||
$currentYear = $this->schoolYear;
|
||||
@@ -496,6 +500,31 @@ class InventoryController extends BaseController
|
||||
return $years;
|
||||
}
|
||||
|
||||
private function applyInventoryMovementPeriodFilter($builder, string $itemAlias, ?string $schoolYear, ?string $semester = null): void
|
||||
{
|
||||
$schoolYear = trim((string) $schoolYear);
|
||||
$semester = trim((string) $semester);
|
||||
$clauses = ["m.item_id = {$itemAlias}.id"];
|
||||
|
||||
if ($schoolYear !== '' && strtolower($schoolYear) !== 'all') {
|
||||
$clauses[] = 'm.school_year = ' . $this->db->escape($schoolYear);
|
||||
}
|
||||
|
||||
if ($semester !== '') {
|
||||
$clauses[] = 'm.semester = ' . $this->db->escape($semester);
|
||||
}
|
||||
|
||||
if (count($clauses) <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$builder->where(
|
||||
'EXISTS (SELECT 1 FROM inventory_movements m WHERE ' . implode(' AND ', $clauses) . ')',
|
||||
null,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
private function recordMovement(
|
||||
int $itemId,
|
||||
int $qtyChange,
|
||||
@@ -1095,7 +1124,7 @@ class InventoryController extends BaseController
|
||||
|
||||
// Filter by school year unless "all"
|
||||
if (!$isAllYears) {
|
||||
$qbItems->where('i.school_year', $selectedYear);
|
||||
$this->applyInventoryMovementPeriodFilter($qbItems, 'i', $selectedYear);
|
||||
}
|
||||
|
||||
// Optional: filter by type if provided
|
||||
@@ -1123,7 +1152,7 @@ class InventoryController extends BaseController
|
||||
return view('inventory/summary', [
|
||||
'selectedYear' => $selectedYear,
|
||||
'currentYear' => $this->schoolYear,
|
||||
'schoolYears' => $this->getSchoolYearsForType('book') ?: [$this->schoolYear, 'All'],
|
||||
'schoolYears' => $this->getSchoolYearsForType($selectedType) ?: [$this->schoolYear, 'All'],
|
||||
'rows' => $rows,
|
||||
'totals' => $totals,
|
||||
// optionally pass the selected type if your view supports it
|
||||
@@ -1202,7 +1231,7 @@ class InventoryController extends BaseController
|
||||
}
|
||||
|
||||
// -------- Year dropdown options --------
|
||||
$schoolYears = $this->getSchoolYearsForType('book') ?: [$this->schoolYear, 'All'];
|
||||
$schoolYears = $this->getSchoolYearsForType($selectedType) ?: [$this->schoolYear, 'All'];
|
||||
|
||||
return view('inventory/summary', [
|
||||
'selectedYear' => $selectedYear,
|
||||
|
||||
@@ -1487,8 +1487,6 @@ $existing = $this->studentModel
|
||||
'cellphone' => $phone,
|
||||
'email' => $email,
|
||||
'relation' => $relation,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'updated_at' => utc_now(),
|
||||
];
|
||||
|
||||
@@ -1568,8 +1566,6 @@ $existing = $this->studentModel
|
||||
'cellphone' => $phone,
|
||||
'email' => $email,
|
||||
'relation' => $relation,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user