343 lines
9.4 KiB
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)];
|
|
}
|
|
}
|