nhance-enrollment/app/Models/ReminderMailConfigModel.php

343 lines
9.4 KiB
PHP

<?php
namespace App\Models;
use CodeIgniter\Model;
class ReminderMailConfigModel extends Model
{
public const FREQUENCY_DAILY = 'daily';
public const FREQUENCY_WEEKLY = 'weekly';
public const FREQUENCY_MONTHLY = 'monthly';
public const FREQUENCY_CUSTOM = 'custom';
public const FREQUENCY_WORKING_DAYS = 'working_days';
private const WORKING_DAY_NAMES = [
'mon' => 1,
'monday' => 1,
'tue' => 2,
'tuesday' => 2,
'wed' => 3,
'wednesday' => 3,
'thu' => 4,
'thursday' => 4,
'fri' => 5,
'friday' => 5,
'sat' => 6,
'saturday' => 6,
'sun' => 7,
'sunday' => 7,
];
private const WORKING_DAY_LABELS = [
1 => 'Mon',
2 => 'Tue',
3 => 'Wed',
4 => 'Thu',
5 => 'Fri',
6 => 'Sat',
7 => 'Sun',
];
protected $table = 'reminder_mail_config';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'array';
protected $useTimestamps = true;
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
protected $allowedFields = [
'client_policy_id',
'frequency',
'reminder_days',
'is_enabled',
'is_active',
'created_by',
'updated_by',
];
protected $allowCallbacks = true;
public function getByClientPolicyId(int $clientPolicyId): ?array
{
return $this->where('client_policy_id', $clientPolicyId)
->where('is_active', 1)
->first();
}
public function shouldSendTodayForPolicy(int $clientPolicyId, ?string $legacyReminderDate = null): bool
{
$config = $this->getByClientPolicyId($clientPolicyId);
if ($config) {
if (empty($config['is_enabled'])) {
return false;
}
return $this->shouldSendToday($config);
}
if (empty($legacyReminderDate)) {
return false;
}
$currentDate = date('d');
foreach (explode(',', $legacyReminderDate) as $date) {
if ($currentDate == trim($date)) {
return true;
}
}
return false;
}
public function shouldSendToday(array $config): bool
{
switch ($config['frequency']) {
case self::FREQUENCY_DAILY:
return true;
case self::FREQUENCY_WEEKLY:
return in_array((int) date('w'), $this->parseDays($config['reminder_days'] ?? ''), true);
case self::FREQUENCY_MONTHLY:
case self::FREQUENCY_CUSTOM:
return in_array((int) date('j'), $this->parseDays($config['reminder_days'] ?? ''), true);
case self::FREQUENCY_WORKING_DAYS:
return in_array((int) date('N'), $this->parseWorkingDays($config['reminder_days'] ?? ''), true);
default:
return false;
}
}
public function parseDays(?string $days): array
{
if ($days === null || trim($days) === '') {
return [];
}
return array_values(array_unique(array_map(
'intval',
array_filter(array_map('trim', explode(',', $days)), static fn ($day) => $day !== '')
)));
}
public function getWorkingDayOptions(): array
{
$options = [];
foreach (self::WORKING_DAY_LABELS as $value => $label) {
$options[] = [
'value' => $value,
'label' => $label,
'key' => strtolower($label),
];
}
return $options;
}
public function parseWorkingDays(?string $days): array
{
if ($days === null || trim($days) === '') {
return [];
}
$parsed = [];
foreach (explode(',', $days) as $day) {
$day = trim($day);
if ($day === '') {
continue;
}
if (is_numeric($day)) {
$num = (int) $day;
// Accept 0 as Sunday (same as 7 in ISO-8601 date('N'))
if ($num === 0) {
$num = 7;
}
$parsed[] = $num;
continue;
}
$key = strtolower($day);
if (isset(self::WORKING_DAY_NAMES[$key])) {
$parsed[] = self::WORKING_DAY_NAMES[$key];
}
}
return array_values(array_unique($parsed));
}
public function normalizeWorkingDays(?string $days): ?string
{
$parsed = $this->parseWorkingDays($days);
if (empty($parsed)) {
return null;
}
sort($parsed);
return implode(',', $parsed);
}
public function formatWorkingDayLabels(?string $days): array
{
$labels = [];
foreach ($this->parseWorkingDays($days) as $day) {
if (isset(self::WORKING_DAY_LABELS[$day])) {
$labels[] = self::WORKING_DAY_LABELS[$day];
}
}
return $labels;
}
public function enrichConfig(array $config): array
{
if (($config['frequency'] ?? '') === self::FREQUENCY_WORKING_DAYS) {
$config['working_day_labels'] = $this->formatWorkingDayLabels($config['reminder_days'] ?? null);
}
return $config;
}
public function normalizeReminderDays(string $frequency, ?string $reminderDays): ?string
{
if ($frequency === self::FREQUENCY_DAILY) {
return null;
}
if ($frequency === self::FREQUENCY_WORKING_DAYS) {
return $this->normalizeWorkingDays($reminderDays);
}
return $reminderDays !== null ? trim((string) $reminderDays) : null;
}
public function validateConfig(string $frequency, ?string $reminderDays): ?string
{
$allowedFrequencies = [
self::FREQUENCY_DAILY,
self::FREQUENCY_WEEKLY,
self::FREQUENCY_MONTHLY,
self::FREQUENCY_CUSTOM,
self::FREQUENCY_WORKING_DAYS,
];
if (!in_array($frequency, $allowedFrequencies, true)) {
return 'Invalid frequency. Allowed values: daily, weekly, monthly, custom, working_days.';
}
if ($frequency === self::FREQUENCY_DAILY) {
return null;
}
if ($frequency === self::FREQUENCY_WORKING_DAYS) {
$days = $this->parseWorkingDays($reminderDays);
if (empty($days)) {
return 'reminder_days is required. Use Mon-Sun or 1-7 (0 also accepted for Sunday).';
}
foreach ($days as $day) {
if ($day < 1 || $day > 7) {
return 'Working day reminder_days must be between 1 (Mon) and 7 (Sun).';
}
}
return null;
}
$days = $this->parseDays($reminderDays);
if (empty($days)) {
return 'reminder_days is required for the selected frequency.';
}
if ($frequency === self::FREQUENCY_WEEKLY) {
foreach ($days as $day) {
if ($day < 0 || $day > 6) {
return 'Weekly reminder_days must be between 0 (Sunday) and 6 (Saturday).';
}
}
return null;
}
foreach ($days as $day) {
if ($day < 1 || $day > 31) {
return 'Monthly/custom reminder_days must be between 1 and 31.';
}
}
return null;
}
/**
* @param array{id?: int|null, hr_id?: int|null} $options
*/
public function saveConfig(
int $clientPolicyId,
string $frequency,
?string $reminderDays,
int $isEnabled = 1,
array $options = []
): array {
$id = isset($options['id']) && $options['id'] !== '' ? (int) $options['id'] : null;
$hrId = isset($options['hr_id']) && $options['hr_id'] !== ''
? (int) $options['hr_id']
: null;
$validationError = $this->validateConfig($frequency, $reminderDays);
if ($validationError !== null) {
return ['status' => false, 'message' => $validationError];
}
$payload = [
'client_policy_id' => $clientPolicyId,
'frequency' => $frequency,
'reminder_days' => $this->normalizeReminderDays($frequency, $reminderDays),
'is_enabled' => $isEnabled,
'is_active' => 1,
];
if ($id) {
$existing = $this->where('id', $id)->where('is_active', 1)->first();
if (empty($existing)) {
return ['status' => false, 'message' => 'Reminder mail configuration not found'];
}
if ((int) $existing['client_policy_id'] !== $clientPolicyId) {
return ['status' => false, 'message' => 'client_policy_id does not match the configuration record'];
}
$payload['updated_by'] = $hrId;
$this->update($id, $payload);
$config = $this->find($id);
return ['status' => true, 'action' => 'updated', 'data' => $this->enrichConfig($config)];
}
$payload['created_by'] = $hrId;
$payload['updated_by'] = $hrId;
$this->insert($payload);
$config = $this->find($this->getInsertID());
return ['status' => true, 'action' => 'created', 'data' => $this->enrichConfig($config)];
}
}