diff --git a/WorkflowEngine.php b/WorkflowEngine.php index 30f25d0..bfeebda 100644 --- a/WorkflowEngine.php +++ b/WorkflowEngine.php @@ -791,10 +791,10 @@ class WorkflowEngine { return $attendance; } - public function updateMeetingAttendance(int $meetingId, int $personId, string $status, int $userId, ?string $guestSurvey = null): void { - $sql = "INSERT INTO meeting_attendance (meeting_id, person_id, attendance_status, guest_survey, updated_by) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE attendance_status = VALUES(attendance_status), guest_survey = VALUES(guest_survey), updated_by = VALUES(updated_by)"; + public function updateMeetingAttendance(int $meetingId, int $personId, int $bniGroupId, string $status, int $userId, ?string $guestSurvey = null): void { + $sql = "INSERT INTO meeting_attendance (meeting_id, person_id, bni_group_id, attendance_status, guest_survey, updated_by) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE attendance_status = VALUES(attendance_status), guest_survey = VALUES(guest_survey), updated_by = VALUES(updated_by), bni_group_id = VALUES(bni_group_id)"; $stmt = $this->pdo->prepare($sql); - $stmt->execute([$meetingId, $personId, $status, $guestSurvey, $userId]); + $stmt->execute([$meetingId, $personId, $bniGroupId, $status, $guestSurvey, $userId]); } public function getMeetingAttendanceByGroupAndDate(int $groupId, string $meetingDatetime): array { diff --git a/_update_meeting_attendance.php b/_update_meeting_attendance.php index 2e4dedf..de787bf 100644 --- a/_update_meeting_attendance.php +++ b/_update_meeting_attendance.php @@ -35,7 +35,7 @@ if (!$personId || !$groupId || !$meetingDate || !$status) { try { $workflowEngine = new WorkflowEngine(); $meetingId = $workflowEngine->getOrCreateMeeting((int)$groupId, $meetingDate); - $workflowEngine->updateMeetingAttendance($meetingId, (int)$personId, $status, (int)$userId, $guestSurvey); + $workflowEngine->updateMeetingAttendance($meetingId, (int)$personId, (int)$groupId, $status, (int)$userId, $guestSurvey); $response['success'] = true; $response['message'] = 'Attendance updated successfully.'; diff --git a/db/migrations/032_add_meeting_key_to_meetings.php b/db/migrations/032_add_meeting_key_to_meetings.php new file mode 100644 index 0000000..9a331ff --- /dev/null +++ b/db/migrations/032_add_meeting_key_to_meetings.php @@ -0,0 +1,73 @@ +exec("ALTER TABLE meetings ADD COLUMN bni_group_id INT(11) UNSIGNED NULL;"); + echo "SUCCESS: Added nullable bni_group_id column.\n"; + } catch (PDOException $e) { + if (strpos($e->getMessage(), 'Duplicate column name') !== false) { + echo "INFO: bni_group_id column already exists.\n"; + } else { + throw $e; + } + } + + // Step 2: Add meeting_datetime column + try { + echo "Step 2: Adding meeting_datetime column...\n"; + $db->exec("ALTER TABLE meetings ADD COLUMN meeting_datetime DATETIME NULL;"); + echo "SUCCESS: Added nullable meeting_datetime column.\n"; + } catch (PDOException $e) { + if (strpos($e->getMessage(), 'Duplicate column name') !== false) { + echo "INFO: meeting_datetime column already exists.\n"; + } else { + throw $e; + } + } + + // Step 3: Add meeting_key column + try { + echo "Step 3: Adding meeting_key column...\n"; + $db->exec("ALTER TABLE meetings ADD COLUMN meeting_key VARCHAR(255) NULL;"); + echo "SUCCESS: Added nullable meeting_key column.\n"; + } catch (PDOException $e) { + if (strpos($e->getMessage(), 'Duplicate column name') !== false) { + echo "INFO: meeting_key column already exists.\n"; + } else { + throw $e; + } + } + + // Step 4: Populate meeting_key + echo "Step 4: Populating meeting_key...\n"; + $updateStmt = $db->prepare("UPDATE meetings SET meeting_key = CONCAT(bni_group_id, '_', meeting_datetime) WHERE (meeting_key IS NULL OR meeting_key = '') AND bni_group_id IS NOT NULL AND meeting_datetime IS NOT NULL"); + $updateStmt->execute(); + echo "SUCCESS: Populated meeting_key for " . $updateStmt->rowCount() . " rows.\n"; + + // Step 5: Add unique index on meeting_key + try { + echo "Step 5: Adding unique index on meeting_key...\n"; + $db->exec("ALTER TABLE meetings ADD UNIQUE (meeting_key);"); + echo "SUCCESS: Added unique index on meeting_key.\n"; + } catch (PDOException $e) { + if (strpos($e->getMessage(), 'Duplicate entry') !== false) { + echo "WARNING: Could not add UNIQUE index because duplicate meeting_key values exist.\n"; + } elseif (strpos($e->getMessage(), 'already exists') !== false) { + echo "INFO: Unique index on meeting_key already exists.\n"; + } else { + throw $e; + } + } + + echo "Migration 032 completed successfully.\n"; + +} catch (Exception $e) { + error_log("Migration 032 failed: " . $e->getMessage()); + die("FATAL: Migration 032 failed: " . $e->getMessage() . "\n"); +} \ No newline at end of file diff --git a/db/migrations/033_standardize_bni_group_id.php b/db/migrations/033_standardize_bni_group_id.php new file mode 100644 index 0000000..0120d0c --- /dev/null +++ b/db/migrations/033_standardize_bni_group_id.php @@ -0,0 +1,71 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + echo "Starting migration 033: Standardize bni_group_id in meeting_attendance. +"; + + // Ensure bni_group_id column exists and is nullable for now + $stmt_bni = $db->query("SHOW COLUMNS FROM meeting_attendance LIKE 'bni_group_id'"); + $result_bni = $stmt_bni->fetch(PDO::FETCH_ASSOC); + if (!$result_bni) { + $db->exec("ALTER TABLE meeting_attendance ADD COLUMN bni_group_id INT(11) NULL;"); + echo "SUCCESS: Added nullable 'bni_group_id' column. +"; + } else { + $db->exec("ALTER TABLE meeting_attendance MODIFY bni_group_id INT(11) NULL;"); + echo "SUCCESS: Modified 'bni_group_id' to be nullable. +"; + } + + // Check for orphaned bni_group_ids + $orphan_check = $db->query("SELECT ma.bni_group_id, COUNT(*) as count FROM meeting_attendance ma LEFT JOIN bni_groups bg ON ma.bni_group_id = bg.id WHERE bg.id IS NULL AND ma.bni_group_id IS NOT NULL GROUP BY ma.bni_group_id;"); + $orphans = $orphan_check->fetchAll(PDO::FETCH_ASSOC); + + if (count($orphans) > 0) { + echo "WARNING: Found orphaned bni_group_ids in meeting_attendance table. +"; + foreach ($orphans as $orphan) { + echo " - bni_group_id: " . $orphan['bni_group_id'] . " (" . $orphan['count'] . " rows) +"; + } + // For now, we will set them to NULL to allow FK creation + foreach ($orphans as $orphan) { + if ($orphan['bni_group_id'] !== 0) { // we don't want to update rows that have 0 as this is default + $update_stmt = $db->prepare("UPDATE meeting_attendance SET bni_group_id = NULL WHERE bni_group_id = :orphan_id;"); + $update_stmt->execute(['orphan_id' => $orphan['bni_group_id']]); + echo "Set " . $update_stmt->rowCount() . " rows with orphaned bni_group_id " . $orphan['bni_group_id'] . " to NULL. +"; + } + } + } else { + echo "INFO: No orphaned bni_group_ids found. +"; + } + + // Add foreign key if it doesn't exist + $fk_check = $db->query("SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting_attendance' AND COLUMN_NAME = 'bni_group_id' AND REFERENCED_TABLE_NAME = 'bni_groups';")->fetch(); + if (!$fk_check) { + echo "Adding foreign key on 'bni_group_id' to 'bni_groups.id'. +"; + $db->exec("ALTER TABLE meeting_attendance ADD CONSTRAINT fk_meeting_attendance_bni_group FOREIGN KEY (bni_group_id) REFERENCES bni_groups(id) ON DELETE CASCADE;"); + echo "SUCCESS: Foreign key added. +"; + } else { + echo "INFO: Foreign key on 'bni_group_id' already exists. +"; + } + + // Now, alter the column to be NOT NULL. This will fail if there are any NULLs left. + // I will not do this for now, as the user might want to check the orphaned data first. + // I will let the column be nullable for now. + + echo "Migration 033 completed successfully (bni_group_id is currently nullable). +"; + +} catch (Exception $e) { + error_log("Migration 033 failed: " . $e->getMessage()); + die("FATAL: Migration 033 failed: " . $e->getMessage() . "\n"); +} diff --git a/db/migrations/034_set_bni_group_id_not_null.php b/db/migrations/034_set_bni_group_id_not_null.php new file mode 100644 index 0000000..56168b2 --- /dev/null +++ b/db/migrations/034_set_bni_group_id_not_null.php @@ -0,0 +1,37 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + echo "Starting migration 034: Set bni_group_id in meeting_attendance to NOT NULL.\n"; + + // First, check if there are any NULL values in the bni_group_id column. + $null_check = $db->query("SELECT COUNT(*) FROM meeting_attendance WHERE bni_group_id IS NULL;")->fetchColumn(); + + if ($null_check > 0) { + echo "WARNING: Found $null_check rows with NULL bni_group_id. Attempting to populate them.\n"; + + // Try to populate from the corresponding meeting record + $update_sql = "UPDATE meeting_attendance ma JOIN meetings m ON ma.meeting_id = m.id SET ma.bni_group_id = m.bni_group_id WHERE ma.bni_group_id IS NULL AND m.bni_group_id IS NOT NULL;"; + $stmt = $db->exec($update_sql); + echo "Populated $stmt rows based on meeting ID.\n"; + + // Re-check for NULLs + $null_check_after = $db->query("SELECT COUNT(*) FROM meeting_attendance WHERE bni_group_id IS NULL;")->fetchColumn(); + if($null_check_after > 0) { + // If still NULLs, we have to fail. + throw new Exception("$null_check_after rows still have NULL bni_group_id after population attempt. Cannot proceed."); + } + } + + echo "No NULL values found in bni_group_id. Altering column to NOT NULL.\n"; + $db->exec("ALTER TABLE meeting_attendance MODIFY bni_group_id INT(11) NOT NULL;"); + echo "SUCCESS: Column bni_group_id in meeting_attendance is now NOT NULL.\n"; + + echo "Migration 034 completed successfully.\n"; + +} catch (Exception $e) { + error_log("Migration 034 failed: " . $e->getMessage()); + die("FATAL: Migration 034 failed: " . $e->getMessage() . "\n"); +} diff --git a/index.php b/index.php index 9d5b96e..76f8e29 100644 --- a/index.php +++ b/index.php @@ -42,6 +42,9 @@ $status_colors = [ 'negative' => 'danger', 'in_progress' => 'warning', 'positive' => 'success', + 'present' => 'success', + 'absent' => 'danger', + 'substitute' => 'warning', ];