This commit is contained in:
@@ -47,6 +47,10 @@ class CreateSchoolYears extends Migration
|
||||
'type' => 'DATE',
|
||||
'null' => true,
|
||||
],
|
||||
'fall_makeup_exam_on' => [
|
||||
'type' => 'DATE',
|
||||
'null' => true,
|
||||
],
|
||||
'previous_school_year_id' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 11,
|
||||
@@ -144,6 +148,7 @@ class CreateSchoolYears extends Migration
|
||||
'description' => ['type' => 'TEXT', 'null' => true],
|
||||
'registration_starts_on' => ['type' => 'DATE', 'null' => true],
|
||||
'registration_ends_on' => ['type' => 'DATE', 'null' => true],
|
||||
'fall_makeup_exam_on' => ['type' => 'DATE', 'null' => true],
|
||||
'previous_school_year_id' => ['type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'null' => true],
|
||||
'next_school_year_id' => ['type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'null' => true],
|
||||
'activated_at' => ['type' => 'DATETIME', 'null' => true],
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class AddFallMakeupExamToSchoolYears extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (! $this->db->tableExists('school_years') || $this->db->fieldExists('fall_makeup_exam_on', 'school_years')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->forge->addColumn('school_years', [
|
||||
'fall_makeup_exam_on' => [
|
||||
'type' => 'DATE',
|
||||
'null' => true,
|
||||
'after' => 'registration_ends_on',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
if (! $this->db->tableExists('school_years') || ! $this->db->fieldExists('fall_makeup_exam_on', 'school_years')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->forge->dropColumn('school_years', 'fall_makeup_exam_on');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class CreateParentPolicyAcceptances extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if ($this->db->tableExists('parent_policy_acceptances')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->forge->addField([
|
||||
'id' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 11,
|
||||
'unsigned' => true,
|
||||
'auto_increment' => true,
|
||||
],
|
||||
'parent_id' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 11,
|
||||
'unsigned' => true,
|
||||
'null' => false,
|
||||
],
|
||||
'school_year' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 9,
|
||||
'null' => false,
|
||||
],
|
||||
'accepted_at' => [
|
||||
'type' => 'DATETIME',
|
||||
'null' => false,
|
||||
],
|
||||
'source' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 40,
|
||||
'null' => false,
|
||||
'default' => 'registration',
|
||||
],
|
||||
'ip_address' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 45,
|
||||
'null' => true,
|
||||
],
|
||||
'user_agent' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 255,
|
||||
'null' => true,
|
||||
],
|
||||
'created_at' => [
|
||||
'type' => 'DATETIME',
|
||||
'null' => true,
|
||||
],
|
||||
'updated_at' => [
|
||||
'type' => 'DATETIME',
|
||||
'null' => true,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey(['parent_id', 'school_year'], 'uq_parent_policy_year');
|
||||
$this->forge->addKey('school_year');
|
||||
$this->forge->createTable('parent_policy_acceptances');
|
||||
|
||||
$this->backfillExistingAcceptances();
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$this->forge->dropTable('parent_policy_acceptances', true);
|
||||
}
|
||||
|
||||
private function backfillExistingAcceptances(): void
|
||||
{
|
||||
if (! $this->db->tableExists('users')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$schoolYear = $this->configuredSchoolYear();
|
||||
if ($schoolYear === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$builder = $this->db->table('users u')
|
||||
->select('u.id')
|
||||
->where('u.accept_school_policy', 1);
|
||||
|
||||
$hasUserType = $this->db->fieldExists('user_type', 'users');
|
||||
$hasRoleTables = $this->db->tableExists('user_roles') && $this->db->tableExists('roles');
|
||||
|
||||
if ($hasUserType && $hasRoleTables) {
|
||||
$builder->groupStart()
|
||||
->where('u.user_type', 'primary')
|
||||
->orWhere(
|
||||
'EXISTS (SELECT 1 FROM user_roles ur INNER JOIN roles r ON r.id = ur.role_id WHERE ur.user_id = u.id AND LOWER(r.name) = ' . $this->db->escape('parent') . ')',
|
||||
null,
|
||||
false
|
||||
)
|
||||
->groupEnd();
|
||||
} elseif ($hasUserType) {
|
||||
$builder->where('u.user_type', 'primary');
|
||||
} elseif ($hasRoleTables) {
|
||||
$builder->where(
|
||||
'EXISTS (SELECT 1 FROM user_roles ur INNER JOIN roles r ON r.id = ur.role_id WHERE ur.user_id = u.id AND LOWER(r.name) = ' . $this->db->escape('parent') . ')',
|
||||
null,
|
||||
false
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
$rows = $builder->get()
|
||||
->getResultArray();
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$parentId = (int) ($row['id'] ?? 0);
|
||||
if ($parentId <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$existing = $this->db->table('parent_policy_acceptances')
|
||||
->where('parent_id', $parentId)
|
||||
->where('school_year', $schoolYear)
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
|
||||
if ($existing !== null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->db->table('parent_policy_acceptances')->insert([
|
||||
'parent_id' => $parentId,
|
||||
'school_year' => $schoolYear,
|
||||
'accepted_at' => date('Y-m-d H:i:s'),
|
||||
'source' => 'legacy_backfill',
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function configuredSchoolYear(): ?string
|
||||
{
|
||||
if ($this->db->tableExists('school_years')) {
|
||||
$row = $this->db->table('school_years')
|
||||
->select('name')
|
||||
->where('status', 'active')
|
||||
->orderBy('id', 'DESC')
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
|
||||
$name = trim((string) ($row['name'] ?? ''));
|
||||
if (preg_match('/^\d{4}-\d{4}$/', $name)) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $this->db->tableExists('configuration')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$row = $this->db->table('configuration')
|
||||
->select('config_value')
|
||||
->where('config_key', 'school_year')
|
||||
->orderBy('id', 'DESC')
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
|
||||
$name = trim((string) ($row['config_value'] ?? ''));
|
||||
|
||||
return preg_match('/^\d{4}-\d{4}$/', $name) ? $name : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class CreateRegistrationOpeningEmailTemplate extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (! $this->db->tableExists('email_templates')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fields = $this->db->getFieldNames('email_templates');
|
||||
$keyField = in_array('code', $fields, true) ? 'code' : 'template_key';
|
||||
$bodyField = in_array('body_html', $fields, true) ? 'body_html' : 'body';
|
||||
$nameField = in_array('name', $fields, true) ? 'name' : null;
|
||||
|
||||
$exists = $this->db->table('email_templates')
|
||||
->where($keyField, 'registration_opening')
|
||||
->countAllResults() > 0;
|
||||
|
||||
if ($exists) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = [
|
||||
$keyField => 'registration_opening',
|
||||
'subject' => 'Registration is now open for {{school_year}}',
|
||||
$bodyField => $this->bodyHtml(),
|
||||
'is_active' => 1,
|
||||
];
|
||||
|
||||
if ($nameField !== null) {
|
||||
$data[$nameField] = 'Registration Opening';
|
||||
}
|
||||
|
||||
$this->db->table('email_templates')->insert($data);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
if (! $this->db->tableExists('email_templates')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fields = $this->db->getFieldNames('email_templates');
|
||||
$keyField = in_array('code', $fields, true) ? 'code' : 'template_key';
|
||||
|
||||
$this->db->table('email_templates')
|
||||
->where($keyField, 'registration_opening')
|
||||
->delete();
|
||||
}
|
||||
|
||||
private function bodyHtml(): string
|
||||
{
|
||||
return <<<'HTML'
|
||||
<p>Dear {{name}},</p>
|
||||
<p>Registration is now open for the {{school_year}} school year.</p>
|
||||
<p>Please complete your registration through the school portal. The registration deadline is {{registration_deadline}}.</p>
|
||||
<p><a href="{{registration_url}}">Start registration</a></p>
|
||||
<p>If you already have an account, you can also log in here: <a href="{{login_url}}">{{login_url}}</a></p>
|
||||
<p>Regards,<br>{{school_name}}</p>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user