MERGE_TEST_BUG_FIXES
This commit is contained in:
commit
debefacdec
@ -511,7 +511,6 @@ $routes->group("employeeRest", ['filter' => [ 'GlobalPostFileUploadGuard', 'appS
|
|||||||
$routes->get("getExcelFileErrors/(:any)", "EmployeeController::getExcelFileErrors/$1");
|
$routes->get("getExcelFileErrors/(:any)", "EmployeeController::getExcelFileErrors/$1");
|
||||||
|
|
||||||
$routes->post("sendReminderMail", "EmployeeRestController::sendReminderMail");
|
$routes->post("sendReminderMail", "EmployeeRestController::sendReminderMail");
|
||||||
$routes->get("sendReminderMail", "EmployeeRestController::sendReminderMail");
|
|
||||||
|
|
||||||
$routes->get("getReminderMailConfig", "EmployeeRestController::getReminderMailConfig");
|
$routes->get("getReminderMailConfig", "EmployeeRestController::getReminderMailConfig");
|
||||||
$routes->post("saveReminderMailConfig", "EmployeeRestController::saveReminderMailConfig");
|
$routes->post("saveReminderMailConfig", "EmployeeRestController::saveReminderMailConfig");
|
||||||
|
|||||||
@ -350,7 +350,13 @@ class DashboardController extends AdminController
|
|||||||
->where('template_name', 'member_reminder_mail')
|
->where('template_name', 'member_reminder_mail')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($notification_data && $notification_data['enabled'] == 1 && !empty($notification_data['mail_content'])) {
|
$reminderConfig = $this->reminderMailConfigModel->getByClientPolicyId((int) $client_policy['id']);
|
||||||
|
$notification_data = $this->reminderMailConfigModel->resolveNotificationTemplate(
|
||||||
|
$reminderConfig,
|
||||||
|
$notification_data
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->reminderMailConfigModel->canSendReminderMail($reminderConfig, $notification_data)) {
|
||||||
|
|
||||||
//manaual
|
//manaual
|
||||||
if (empty($send_mail_for_manual_or_crone)) {
|
if (empty($send_mail_for_manual_or_crone)) {
|
||||||
|
|||||||
@ -3267,7 +3267,10 @@ class EmployeeController extends AdminController
|
|||||||
$sentCount = 0;
|
$sentCount = 0;
|
||||||
try {
|
try {
|
||||||
$clientPolicy = $this->clientPolicyModel->find($filePolicyId);
|
$clientPolicy = $this->clientPolicyModel->find($filePolicyId);
|
||||||
$clientLogo = base_url() . 'public/uploads/logo/' . ($clientData['client_logo'] ?? '');
|
$clientLogo = '';
|
||||||
|
if (!empty($clientData['client_logo'])) {
|
||||||
|
$clientLogo = base_url() . 'public/uploads/logo/' . $clientData['client_logo'];
|
||||||
|
}
|
||||||
|
|
||||||
$acm_Mails = $clientData['common_mails'] ?? '';
|
$acm_Mails = $clientData['common_mails'] ?? '';
|
||||||
if(empty($acm_Mails)){
|
if(empty($acm_Mails)){
|
||||||
@ -3282,6 +3285,11 @@ class EmployeeController extends AdminController
|
|||||||
: 'N/A';
|
: 'N/A';
|
||||||
|
|
||||||
$subject = 'Enrollment Closed - Enrolled Employee List | ' . ($clientData['client_name'] ?? '');
|
$subject = 'Enrollment Closed - Enrolled Employee List | ' . ($clientData['client_name'] ?? '');
|
||||||
|
$statusTilesHtml = $this->renderEnrollmentStatusTilesForMail(
|
||||||
|
$fileClientId,
|
||||||
|
(int) $file['client_branch_id'],
|
||||||
|
$filePolicyId
|
||||||
|
);
|
||||||
|
|
||||||
foreach ($hrRecipients as $hrRecipient) {
|
foreach ($hrRecipients as $hrRecipient) {
|
||||||
$hrEmail = trim($hrRecipient['email'] ?? '');
|
$hrEmail = trim($hrRecipient['email'] ?? '');
|
||||||
@ -3291,7 +3299,7 @@ class EmployeeController extends AdminController
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$mailContent = $this->buildEnrollmentClosedHrMailContent([
|
$mailContent = $statusTilesHtml . $this->buildEnrollmentClosedHrMailContent([
|
||||||
'hr_name' => $hrName,
|
'hr_name' => $hrName,
|
||||||
'client_name' => $clientData['client_name'] ?? '',
|
'client_name' => $clientData['client_name'] ?? '',
|
||||||
'policy_no' => $clientPolicy['policy_no'] ?? 'N/A',
|
'policy_no' => $clientPolicy['policy_no'] ?? 'N/A',
|
||||||
@ -3355,6 +3363,17 @@ class EmployeeController extends AdminController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function renderEnrollmentStatusTilesForMail(int $client_id, int $branch_id, int $policy_id): string
|
||||||
|
{
|
||||||
|
$counts = $this->employeePolicyModel->getEnrollmentStatusTileCounts(
|
||||||
|
$client_id,
|
||||||
|
$branch_id,
|
||||||
|
$policy_id
|
||||||
|
);
|
||||||
|
|
||||||
|
return view('mail/enrollment_status_tiles', ['counts' => $counts]);
|
||||||
|
}
|
||||||
|
|
||||||
private function buildEnrollmentClosedHrMailContent(array $data): string
|
private function buildEnrollmentClosedHrMailContent(array $data): string
|
||||||
{
|
{
|
||||||
$hrName = htmlspecialchars($data['hr_name'] ?? 'HR Team', ENT_QUOTES, 'UTF-8');
|
$hrName = htmlspecialchars($data['hr_name'] ?? 'HR Team', ENT_QUOTES, 'UTF-8');
|
||||||
@ -3368,19 +3387,19 @@ class EmployeeController extends AdminController
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="max-width:600px;">
|
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="max-width:600px;">
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left" style="padding:15px; font-family:arial, sans-serif; font-size:14px; line-height:22px; color:#333333;">
|
<td align="left" style="padding:10px 15px 20px; font-family:arial, sans-serif; font-size:14px; line-height:24px; color:#333333;">
|
||||||
<p>Dear ' . $hrName . ',</p>
|
<div style="margin-bottom:16px;">Dear ' . $hrName . ',</div>
|
||||||
<p>The enrollment window for <strong>' . $clientName . '</strong> has closed.</p>
|
<div style="margin-bottom:16px;">The enrollment window for <strong>' . $clientName . '</strong> has closed.</div>
|
||||||
<p>
|
<div style="margin-bottom:16px;">
|
||||||
<strong>Policy No:</strong> ' . $policyNo . '<br>
|
<strong>Policy No:</strong> ' . $policyNo . '<br>
|
||||||
<strong>Enrollment Open Date:</strong> ' . $openDate . '<br>
|
<strong>Enrollment Open Date:</strong> ' . $openDate . '<br>
|
||||||
<strong>Enrollment Close Date:</strong> ' . $closeDate . '
|
<strong>Enrollment Close Date:</strong> ' . $closeDate . '
|
||||||
</p>
|
</div>
|
||||||
<p>
|
<div style="margin-bottom:16px;">
|
||||||
Please find the attached Excel file with the enrolled employee list
|
Please find the attached Excel file with the enrolled employee list
|
||||||
(' . $employeeCount . ' record' . ($employeeCount === 1 ? '' : 's') . ').
|
(' . $employeeCount . ' record' . ($employeeCount === 1 ? '' : 's') . ').
|
||||||
</p>
|
</div>
|
||||||
<p>Regards,<br>Nhance Team</p>
|
<div>Regards,<br>Nhance Team</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@ -3187,25 +3187,26 @@ class EmployeeRestController extends AdminController
|
|||||||
return $this->respond(['status' => 'failed','code' => 200,'data' => [] ], 200);
|
return $this->respond(['status' => 'failed','code' => 200,'data' => [] ], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
$openEnrollmentPolicies = $this->employeePolicyModel
|
// $openEnrollmentPolicies = $this->employeePolicyModel
|
||||||
->select('employee_polices.client_policy_id')
|
// ->select('employee_polices.client_policy_id')
|
||||||
->join('employees', 'employee_polices.employee_id = employees.id')
|
// ->join('employees', 'employee_polices.employee_id = employees.id')
|
||||||
->whereIn('employee_polices.client_policy_id', $allowedPolicyIds)
|
// ->whereIn('employee_polices.client_policy_id', $allowedPolicyIds)
|
||||||
->where('md5(employees.client_id)', $client_id)
|
// ->where('md5(employees.client_id)', $client_id)
|
||||||
->where('employees.client_branch_id', $client_branch_id)
|
// ->where('employees.client_branch_id', $client_branch_id)
|
||||||
->where('employee_polices.enrollment_open_date <= CURDATE()', null, false)
|
// ->where('employee_polices.enrollment_open_date <= CURDATE()', null, false)
|
||||||
->where('employee_polices.enrollment_close_date >= CURDATE()', null, false)
|
// ->where('employee_polices.enrollment_close_date >= CURDATE()', null, false)
|
||||||
->where('employee_polices.enrollment_open_date IS NOT NULL', null, false)
|
// ->where('employee_polices.enrollment_open_date IS NOT NULL', null, false)
|
||||||
->where('employee_polices.enrollment_close_date IS NOT NULL', null, false)
|
// ->where('employee_polices.enrollment_close_date IS NOT NULL', null, false)
|
||||||
->where('employees.is_active', 1)
|
// ->where('employees.is_active', 1)
|
||||||
->where('employee_polices.is_active', 1)
|
// ->where('employee_polices.is_active', 1)
|
||||||
->whereIn('employee_polices.status', ['draft', 'enrolled'])
|
// ->whereIn('employee_polices.status', ['draft', 'enrolled'])
|
||||||
->whereIn('employees.emp_status', ['draft', 'enrolled'])
|
// ->whereIn('employees.emp_status', ['draft', 'enrolled'])
|
||||||
->groupBy('employee_polices.client_policy_id')
|
// ->groupBy('employee_polices.client_policy_id')
|
||||||
->findAll();
|
// ->findAll();
|
||||||
|
|
||||||
$policyId = array_column($openEnrollmentPolicies, 'client_policy_id');
|
// $policyId = array_column($openEnrollmentPolicies, 'client_policy_id');
|
||||||
|
|
||||||
|
$policyId = $allowedPolicyIds;
|
||||||
if(empty($policyId)){
|
if(empty($policyId)){
|
||||||
return $this->respond(['status' => 'failed','code' => 200,'data' => [] ], 200);
|
return $this->respond(['status' => 'failed','code' => 200,'data' => [] ], 200);
|
||||||
}
|
}
|
||||||
@ -4683,8 +4684,9 @@ class EmployeeRestController extends AdminController
|
|||||||
public function getReminderMailConfig()
|
public function getReminderMailConfig()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$clientPolicyId = $this->request->getGet('client_policy_id')
|
|
||||||
?? $this->request->getPost('client_policy_id');
|
$clientPolicyId = $this->request->getGet('client_policy_id');
|
||||||
|
$is_email_template = $this->request->getGet('is_email_template') ?? false;
|
||||||
|
|
||||||
if (empty($clientPolicyId)) {
|
if (empty($clientPolicyId)) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
@ -4706,6 +4708,27 @@ class EmployeeRestController extends AdminController
|
|||||||
|
|
||||||
$config = $this->reminderMailConfigModel->getByClientPolicyId((int) $clientPolicyId);
|
$config = $this->reminderMailConfigModel->getByClientPolicyId((int) $clientPolicyId);
|
||||||
|
|
||||||
|
if ($is_email_template) {
|
||||||
|
if (empty($config)) {
|
||||||
|
|
||||||
|
$notification = $this->notificationModel->where('client_id', $clientPolicy['client_id'])->where('template_name', 'member_reminder_mail')->first();
|
||||||
|
if (empty($notification)) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => false,
|
||||||
|
'code' => 404,
|
||||||
|
'message' => 'Member reminder mail notification not found',
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respond(['status' => true, 'code' => 200, 'data' => ['email_subject' => $notification['subject'], 'email_body' => $notification['mail_content']]], 200);
|
||||||
|
}
|
||||||
|
return $this->respond([
|
||||||
|
'status' => true,
|
||||||
|
'code' => 200,
|
||||||
|
'data' => ['email_subject' => $config['email_subject'], 'email_body' => $config['email_body']],
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($config) && !empty($clientPolicy['reminder_date'])) {
|
if (empty($config) && !empty($clientPolicy['reminder_date'])) {
|
||||||
$config = [
|
$config = [
|
||||||
'client_policy_id' => (int) $clientPolicyId,
|
'client_policy_id' => (int) $clientPolicyId,
|
||||||
@ -4749,6 +4772,8 @@ class EmployeeRestController extends AdminController
|
|||||||
?? null;
|
?? null;
|
||||||
$isEnabled = $requestData['is_enabled'] ?? null;
|
$isEnabled = $requestData['is_enabled'] ?? null;
|
||||||
$hrId = $requestData['hr_id'] ?? null;
|
$hrId = $requestData['hr_id'] ?? null;
|
||||||
|
$emailSubject = $requestData['email_subject'] ?? null;
|
||||||
|
$emailBody = $requestData['email_body'] ?? null;
|
||||||
|
|
||||||
if (empty($clientPolicyId)) {
|
if (empty($clientPolicyId)) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
@ -4776,15 +4801,25 @@ class EmployeeRestController extends AdminController
|
|||||||
], 200);
|
], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$saveOptions = [
|
||||||
|
'id' => $configId !== null && $configId !== '' ? (int) $configId : null,
|
||||||
|
'hr_id' => $hrId !== null && $hrId !== '' ? (int) $hrId : null,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (array_key_exists('email_subject', $requestData)) {
|
||||||
|
$saveOptions['email_subject'] = $emailSubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('email_body', $requestData)) {
|
||||||
|
$saveOptions['email_body'] = $emailBody;
|
||||||
|
}
|
||||||
|
|
||||||
$result = $this->reminderMailConfigModel->saveConfig(
|
$result = $this->reminderMailConfigModel->saveConfig(
|
||||||
(int) $clientPolicyId,
|
(int) $clientPolicyId,
|
||||||
$frequency,
|
$frequency,
|
||||||
$reminderDays !== null ? (string) $reminderDays : null,
|
$reminderDays !== null ? (string) $reminderDays : null,
|
||||||
$isEnabled === null ? 1 : (int) $isEnabled,
|
$isEnabled === null ? 1 : (int) $isEnabled,
|
||||||
[
|
$saveOptions
|
||||||
'id' => $configId !== null && $configId !== '' ? (int) $configId : null,
|
|
||||||
'hr_id' => $hrId !== null && $hrId !== '' ? (int) $hrId : null,
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!$result['status']) {
|
if (!$result['status']) {
|
||||||
@ -4825,6 +4860,8 @@ class EmployeeRestController extends AdminController
|
|||||||
'frequency' => $this->request->getVar('frequency'),
|
'frequency' => $this->request->getVar('frequency'),
|
||||||
'reminder_days' => $this->request->getVar('reminder_days'),
|
'reminder_days' => $this->request->getVar('reminder_days'),
|
||||||
'working_days' => $this->request->getVar('working_days'),
|
'working_days' => $this->request->getVar('working_days'),
|
||||||
|
'email_subject' => $this->request->getVar('email_subject'),
|
||||||
|
'email_body' => $this->request->getVar('email_body'),
|
||||||
'is_enabled' => $this->request->getVar('is_enabled'),
|
'is_enabled' => $this->request->getVar('is_enabled'),
|
||||||
'hr_id' => $this->request->getVar('hr_id'),
|
'hr_id' => $this->request->getVar('hr_id'),
|
||||||
], static fn ($value) => $value !== null && $value !== '');
|
], static fn ($value) => $value !== null && $value !== '');
|
||||||
@ -4833,8 +4870,34 @@ class EmployeeRestController extends AdminController
|
|||||||
public function sendReminderMail()
|
public function sendReminderMail()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$clientPolicyId = $this->request->getGet('client_policy_id')
|
|
||||||
?? $this->request->getPost('client_policy_id');
|
if (!$this->request->is('post')) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => false,
|
||||||
|
'code' => 405,
|
||||||
|
'message' => 'Only POST method is allowed',
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$requestData = $this->request->getJSON(true);
|
||||||
|
} catch (\CodeIgniter\HTTP\Exceptions\HTTPException $e) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => false,
|
||||||
|
'code' => 400,
|
||||||
|
'message' => 'Invalid JSON request body',
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($requestData) || empty($requestData)) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => false,
|
||||||
|
'code' => 400,
|
||||||
|
'message' => 'JSON request body is required',
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
$clientPolicyId = $requestData['client_policy_id'] ?? null;
|
||||||
|
|
||||||
if (empty($clientPolicyId)) {
|
if (empty($clientPolicyId)) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
@ -4854,9 +4917,20 @@ class EmployeeRestController extends AdminController
|
|||||||
], 200);
|
], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
$dashboardController = new DashboardController();
|
$emailSubject = $requestData['email_subject'] ?? null;
|
||||||
|
$emailBody = $requestData['email_body'] ?? null;
|
||||||
|
$hrId = $requestData['hr_id'] ?? null;
|
||||||
|
|
||||||
return $dashboardController->sendManualReminder(
|
if (array_key_exists('email_subject', $requestData) || array_key_exists('email_body', $requestData)) {
|
||||||
|
$this->reminderMailConfigModel->saveEmailTemplate(
|
||||||
|
(int) $clientPolicyId,
|
||||||
|
$emailSubject,
|
||||||
|
$emailBody,
|
||||||
|
$hrId !== null && $hrId !== '' ? (int) $hrId : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->dispatchManualReminder(
|
||||||
$clientPolicy['client_id'],
|
$clientPolicy['client_id'],
|
||||||
$clientPolicy['client_branch_id'],
|
$clientPolicy['client_branch_id'],
|
||||||
$clientPolicyId
|
$clientPolicyId
|
||||||
@ -4870,4 +4944,15 @@ class EmployeeRestController extends AdminController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function dispatchManualReminder($clientId, $clientBranchId, $clientPolicyId)
|
||||||
|
{
|
||||||
|
$dashboardController = new DashboardController();
|
||||||
|
|
||||||
|
return $dashboardController->sendManualReminder(
|
||||||
|
$clientId,
|
||||||
|
$clientBranchId,
|
||||||
|
$clientPolicyId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -5,6 +5,8 @@ CREATE TABLE IF NOT EXISTS `reminder_mail_config` (
|
|||||||
`client_policy_id` INT UNSIGNED NOT NULL,
|
`client_policy_id` INT UNSIGNED NOT NULL,
|
||||||
`frequency` ENUM('daily', 'weekly', 'monthly', 'custom', 'working_days') NOT NULL DEFAULT 'custom',
|
`frequency` ENUM('daily', 'weekly', 'monthly', 'custom', 'working_days') NOT NULL DEFAULT 'custom',
|
||||||
`reminder_days` VARCHAR(255) DEFAULT NULL COMMENT 'weekly: 0-6 (Sun-Sat); working_days: 1-7 (Mon-Sun) or Mon,Tue,...; monthly/custom: 1-31; daily: NULL',
|
`reminder_days` VARCHAR(255) DEFAULT NULL COMMENT 'weekly: 0-6 (Sun-Sat); working_days: 1-7 (Mon-Sun) or Mon,Tue,...; monthly/custom: 1-31; daily: NULL',
|
||||||
|
`email_subject` VARCHAR(500) DEFAULT NULL COMMENT 'Custom reminder mail subject; falls back to notification template when NULL',
|
||||||
|
`email_body` TEXT DEFAULT NULL COMMENT 'Custom reminder mail body; falls back to notification template when NULL',
|
||||||
`is_enabled` TINYINT(1) NOT NULL DEFAULT 1,
|
`is_enabled` TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
`created_by` INT UNSIGNED DEFAULT NULL,
|
`created_by` INT UNSIGNED DEFAULT NULL,
|
||||||
@ -16,3 +18,10 @@ CREATE TABLE IF NOT EXISTS `reminder_mail_config` (
|
|||||||
KEY `idx_reminder_mail_config_frequency` (`frequency`),
|
KEY `idx_reminder_mail_config_frequency` (`frequency`),
|
||||||
KEY `idx_reminder_mail_config_is_enabled` (`is_enabled`)
|
KEY `idx_reminder_mail_config_is_enabled` (`is_enabled`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Upgrade existing installations (ignore duplicate-column errors if already applied)
|
||||||
|
ALTER TABLE `reminder_mail_config`
|
||||||
|
ADD COLUMN `email_subject` VARCHAR(500) DEFAULT NULL COMMENT 'Custom reminder mail subject; falls back to notification template when NULL' AFTER `reminder_days`;
|
||||||
|
|
||||||
|
ALTER TABLE `reminder_mail_config`
|
||||||
|
ADD COLUMN `email_body` TEXT DEFAULT NULL COMMENT 'Custom reminder mail body; falls back to notification template when NULL' AFTER `email_subject`;
|
||||||
|
|||||||
@ -1987,7 +1987,9 @@ class EmployeePolicyModel extends Model
|
|||||||
|
|
||||||
|
|
||||||
// Conditionally add where clauses
|
// Conditionally add where clauses
|
||||||
if ($client_id != 0 && !empty(trim($client_id))) {
|
if (is_string($client_id) && preg_match('/^[a-f0-9]{32}$/i', $client_id)) {
|
||||||
|
$result->where('MD5(emp.client_id)', $client_id);
|
||||||
|
} elseif ($client_id != 0 && !empty($client_id)) {
|
||||||
$result->where('emp.client_id', $client_id);
|
$result->where('emp.client_id', $client_id);
|
||||||
}
|
}
|
||||||
if ($branch_id != 0 && !empty(trim($branch_id))) {
|
if ($branch_id != 0 && !empty(trim($branch_id))) {
|
||||||
@ -2124,5 +2126,65 @@ class EmployeePolicyModel extends Model
|
|||||||
->getRowArray();
|
->getRowArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enrollment status tile counts (same logic as enrollment_list.php).
|
||||||
|
*/
|
||||||
|
public function getEnrollmentStatusTileCounts(int $client_id, int $branch_id, int $client_policy_id): array
|
||||||
|
{
|
||||||
|
$authSubQuery = '(SELECT user_id FROM auth_history WHERE user_type = "employee" GROUP BY user_id) auth_history';
|
||||||
|
|
||||||
|
$rows = $this->db->table('employees')
|
||||||
|
->select('employees.id, employees.relationship, employees.emp_status, auth_history.user_id as logged_in_user_id')
|
||||||
|
->join('employee_polices', 'employees.id = employee_polices.employee_id')
|
||||||
|
->join($authSubQuery, 'employees.id = auth_history.user_id', 'left', false)
|
||||||
|
->where('employees.client_id', $client_id)
|
||||||
|
->where('employees.client_branch_id', $branch_id)
|
||||||
|
->where('employees.is_active', 1)
|
||||||
|
->where('employees.emp_status !=', 'truncated')
|
||||||
|
->where('employee_polices.client_policy_id', $client_policy_id)
|
||||||
|
->where('employee_polices.is_active', 1)
|
||||||
|
->where('employee_polices.status !=', 'truncated')
|
||||||
|
->groupBy('employees.id, employees.relationship, employees.emp_status, auth_history.user_id')
|
||||||
|
->get()
|
||||||
|
->getResultArray();
|
||||||
|
|
||||||
|
$counts = [
|
||||||
|
'emp_count' => 0,
|
||||||
|
'enrolled' => 0,
|
||||||
|
'not_enrolled' => 0,
|
||||||
|
'logged_in' => 0,
|
||||||
|
'not_logged_in' => 0,
|
||||||
|
'draft' => 0,
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
if (strtolower(trim($row['relationship'] ?? '')) !== 'self') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$counts['emp_count']++;
|
||||||
|
|
||||||
|
$isEnrolled = ($row['emp_status'] ?? '') === 'enrolled';
|
||||||
|
if ($isEnrolled) {
|
||||||
|
$counts['enrolled']++;
|
||||||
|
} else {
|
||||||
|
$counts['not_enrolled']++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$isLoggedIn = !empty($row['logged_in_user_id']);
|
||||||
|
if ($isLoggedIn) {
|
||||||
|
$counts['logged_in']++;
|
||||||
|
} else {
|
||||||
|
$counts['not_logged_in']++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$isEnrolled && $isLoggedIn) {
|
||||||
|
$counts['draft']++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $counts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -50,6 +50,8 @@ class ReminderMailConfigModel extends Model
|
|||||||
'client_policy_id',
|
'client_policy_id',
|
||||||
'frequency',
|
'frequency',
|
||||||
'reminder_days',
|
'reminder_days',
|
||||||
|
'email_subject',
|
||||||
|
'email_body',
|
||||||
'is_enabled',
|
'is_enabled',
|
||||||
'is_active',
|
'is_active',
|
||||||
'created_by',
|
'created_by',
|
||||||
@ -209,9 +211,90 @@ class ReminderMailConfigModel extends Model
|
|||||||
$config['working_day_labels'] = $this->formatWorkingDayLabels($config['reminder_days'] ?? null);
|
$config['working_day_labels'] = $this->formatWorkingDayLabels($config['reminder_days'] ?? null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$config['has_custom_template'] = $this->hasCustomTemplate($config);
|
||||||
|
|
||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasCustomTemplate(?array $config): bool
|
||||||
|
{
|
||||||
|
if (empty($config)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim((string) ($config['email_subject'] ?? '')) !== ''
|
||||||
|
&& trim((string) ($config['email_body'] ?? '')) !== '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply reminder_mail_config template to notification data when configured.
|
||||||
|
*/
|
||||||
|
public function resolveNotificationTemplate(?array $config, ?array $notificationData): ?array
|
||||||
|
{
|
||||||
|
if (!$this->hasCustomTemplate($config)) {
|
||||||
|
return $notificationData;
|
||||||
|
}
|
||||||
|
|
||||||
|
$notificationData = is_array($notificationData) ? $notificationData : [];
|
||||||
|
$notificationData['subject'] = $config['email_subject'];
|
||||||
|
$notificationData['mail_content'] = $config['email_body'];
|
||||||
|
$notificationData['enabled'] = 1;
|
||||||
|
|
||||||
|
return $notificationData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canSendReminderMail(?array $config, ?array $notificationData): bool
|
||||||
|
{
|
||||||
|
if ($this->hasCustomTemplate($config)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !empty($notificationData)
|
||||||
|
&& (int) ($notificationData['enabled'] ?? 0) === 1
|
||||||
|
&& trim((string) ($notificationData['mail_content'] ?? '')) !== '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveEmailTemplate(
|
||||||
|
int $clientPolicyId,
|
||||||
|
?string $emailSubject,
|
||||||
|
?string $emailBody,
|
||||||
|
?int $hrId = null
|
||||||
|
): void {
|
||||||
|
if ($emailSubject === null && $emailBody === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$existing = $this->getByClientPolicyId($clientPolicyId);
|
||||||
|
|
||||||
|
if ($existing) {
|
||||||
|
$payload = ['updated_by' => $hrId];
|
||||||
|
|
||||||
|
if ($emailSubject !== null) {
|
||||||
|
$payload['email_subject'] = $emailSubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($emailBody !== null) {
|
||||||
|
$payload['email_body'] = $emailBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->update((int) $existing['id'], $payload);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->insert([
|
||||||
|
'client_policy_id' => $clientPolicyId,
|
||||||
|
'frequency' => self::FREQUENCY_CUSTOM,
|
||||||
|
'reminder_days' => null,
|
||||||
|
'email_subject' => $emailSubject,
|
||||||
|
'email_body' => $emailBody,
|
||||||
|
'is_enabled' => 1,
|
||||||
|
'is_active' => 1,
|
||||||
|
'created_by' => $hrId,
|
||||||
|
'updated_by' => $hrId,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function normalizeReminderDays(string $frequency, ?string $reminderDays): ?string
|
public function normalizeReminderDays(string $frequency, ?string $reminderDays): ?string
|
||||||
{
|
{
|
||||||
if ($frequency === self::FREQUENCY_DAILY) {
|
if ($frequency === self::FREQUENCY_DAILY) {
|
||||||
@ -313,6 +396,14 @@ class ReminderMailConfigModel extends Model
|
|||||||
'is_active' => 1,
|
'is_active' => 1,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (array_key_exists('email_subject', $options)) {
|
||||||
|
$payload['email_subject'] = $options['email_subject'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('email_body', $options)) {
|
||||||
|
$payload['email_body'] = $options['email_body'];
|
||||||
|
}
|
||||||
|
|
||||||
if ($id) {
|
if ($id) {
|
||||||
$existing = $this->where('id', $id)->where('is_active', 1)->first();
|
$existing = $this->where('id', $id)->where('is_active', 1)->first();
|
||||||
|
|
||||||
|
|||||||
57
app/Views/mail/enrollment_status_tiles.php
Normal file
57
app/Views/mail/enrollment_status_tiles.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
$counts = $counts ?? [];
|
||||||
|
$tiles = [
|
||||||
|
['label' => 'Emp Count', 'value' => (int) ($counts['emp_count'] ?? 0), 'accent' => '#00999E'],
|
||||||
|
['label' => 'Enroled', 'value' => (int) ($counts['enrolled'] ?? 0), 'accent' => '#0ab39c'],
|
||||||
|
['label' => 'Not Enroled', 'value' => (int) ($counts['not_enrolled'] ?? 0), 'accent' => '#f06548'],
|
||||||
|
['label' => 'Logged-In', 'value' => (int) ($counts['logged_in'] ?? 0), 'accent' => '#299cdb'],
|
||||||
|
['label' => 'Not Logged-In', 'value' => (int) ($counts['not_logged_in'] ?? 0), 'accent' => '#878a99'],
|
||||||
|
['label' => 'Draft', 'value' => (int) ($counts['draft'] ?? 0), 'accent' => '#f7b84b'],
|
||||||
|
];
|
||||||
|
$tileRows = array_chunk($tiles, 3);
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div align="center" style="width:100%; margin:24px 0;">
|
||||||
|
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="max-width:600px; border-collapse:collapse;">
|
||||||
|
<tr>
|
||||||
|
<td style="padding:0 12px 12px; font-family:arial, sans-serif; font-size:15px; font-weight:600; color:#343a40; text-align:left;">
|
||||||
|
Enrollment Summary
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding:0 8px;">
|
||||||
|
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="border-collapse:collapse;">
|
||||||
|
<?php foreach ($tileRows as $rowTiles): ?>
|
||||||
|
<tr>
|
||||||
|
<?php foreach ($rowTiles as $tile): ?>
|
||||||
|
<td width="33%" align="center" valign="top" style="padding:6px;">
|
||||||
|
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="border-collapse:collapse; background-color:#ffffff; border:1px solid #e9ecef; border-radius:8px;">
|
||||||
|
<tr>
|
||||||
|
<td height="4" style="background-color:<?= esc($tile['accent']) ?>; font-size:0; line-height:0; border-radius:8px 8px 0 0;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding:18px 10px 20px;">
|
||||||
|
<div style="font-family:arial, sans-serif; font-size:26px; font-weight:700; color:#212529; line-height:1.1; margin:0 0 6px 0;">
|
||||||
|
<?= $tile['value'] ?>
|
||||||
|
</div>
|
||||||
|
<div style="font-family:arial, sans-serif; font-size:12px; font-weight:500; color:#6c757d; line-height:1.3; letter-spacing:0.2px;">
|
||||||
|
<?= esc($tile['label']) ?>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php
|
||||||
|
$missingCells = 3 - count($rowTiles);
|
||||||
|
for ($i = 0; $i < $missingCells; $i++):
|
||||||
|
?>
|
||||||
|
<td width="33%" style="padding:6px; font-size:0; line-height:0;"> </td>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
@ -89,16 +89,11 @@ p{
|
|||||||
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="mail-template-header">
|
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="mail-template-header">
|
||||||
<tr style="height:90px; background-color: #ffffff !important;">
|
<tr style="height:90px; background-color: #ffffff !important;">
|
||||||
<td align="left" class="client_logo" style="padding:5px;" width="50%">
|
<td align="left" class="client_logo" style="padding:5px;" width="50%">
|
||||||
<div style="
|
<?php if (!empty($client_logo)): ?>
|
||||||
width:160px;
|
<img src="<?= esc($client_logo) ?>"
|
||||||
height:80px;
|
alt="Client Logo"
|
||||||
background-image:url('<?= $client_logo ?? "" ?>');
|
style="height:auto; max-width:160px; max-height:80px; display:block;">
|
||||||
background-size:contain;
|
<?php endif; ?>
|
||||||
background-repeat:no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td align="right" class="nhance_logo" style="padding:5px;" width="50%">
|
<td align="right" class="nhance_logo" style="padding:5px;" width="50%">
|
||||||
<img src="<?= base_url('/public/assets/images/Nhance-Logo-Final.png'); ?>"
|
<img src="<?= base_url('/public/assets/images/Nhance-Logo-Final.png'); ?>"
|
||||||
|
|||||||
120
tests/_support/Traits/ReminderMailControllerTestTrait.php
Normal file
120
tests/_support/Traits/ReminderMailControllerTestTrait.php
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Support\Traits;
|
||||||
|
|
||||||
|
use App\Controllers\EmployeeRestController;
|
||||||
|
use CodeIgniter\HTTP\IncomingRequest;
|
||||||
|
use Config\Services;
|
||||||
|
use ReflectionClass;
|
||||||
|
|
||||||
|
trait ReminderMailControllerTestTrait
|
||||||
|
{
|
||||||
|
private function createNotificationModelStub(?array $result): object
|
||||||
|
{
|
||||||
|
return new class($result) {
|
||||||
|
private ?array $result;
|
||||||
|
|
||||||
|
public function __construct(?array $result)
|
||||||
|
{
|
||||||
|
$this->result = $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function where(...$args)
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function first(): ?array
|
||||||
|
{
|
||||||
|
return $this->result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildGetController(
|
||||||
|
array $getParams,
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel,
|
||||||
|
?object $notificationModel = null
|
||||||
|
): EmployeeRestController {
|
||||||
|
$request = $this->createMock(IncomingRequest::class);
|
||||||
|
$request->method('getGet')
|
||||||
|
->willReturnCallback(function ($key = null) use ($getParams) {
|
||||||
|
if ($key === null) {
|
||||||
|
return $getParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_key_exists($key, $getParams) ? $getParams[$key] : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $this->injectReminderMailControllerDependencies(
|
||||||
|
$request,
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel,
|
||||||
|
$notificationModel
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildJsonPostController(
|
||||||
|
array $jsonData,
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel,
|
||||||
|
bool $isPost = true,
|
||||||
|
?object $notificationModel = null,
|
||||||
|
?EmployeeRestController $controller = null
|
||||||
|
): EmployeeRestController {
|
||||||
|
$request = $this->createMock(IncomingRequest::class);
|
||||||
|
$request->method('is')
|
||||||
|
->with('post')
|
||||||
|
->willReturn($isPost);
|
||||||
|
$request->method('getJSON')
|
||||||
|
->with(true)
|
||||||
|
->willReturn($jsonData);
|
||||||
|
$request->method('getVar')
|
||||||
|
->willReturn(null);
|
||||||
|
|
||||||
|
$controller = $controller ?? new EmployeeRestController();
|
||||||
|
|
||||||
|
return $this->injectReminderMailControllerDependencies(
|
||||||
|
$request,
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel,
|
||||||
|
$notificationModel,
|
||||||
|
$controller
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function injectReminderMailControllerDependencies(
|
||||||
|
IncomingRequest $request,
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel,
|
||||||
|
?object $notificationModel = null,
|
||||||
|
?EmployeeRestController $controller = null
|
||||||
|
): EmployeeRestController {
|
||||||
|
$controller = $controller ?? new EmployeeRestController();
|
||||||
|
$controller->initController($request, Services::response(), Services::logger());
|
||||||
|
|
||||||
|
$reflection = new ReflectionClass($controller);
|
||||||
|
|
||||||
|
foreach ([
|
||||||
|
'clientPolicyModel' => $clientPolicyModel,
|
||||||
|
'reminderMailConfigModel' => $reminderMailConfigModel,
|
||||||
|
'notificationModel' => $notificationModel,
|
||||||
|
] as $property => $value) {
|
||||||
|
if ($value === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$prop = $reflection->getProperty($property);
|
||||||
|
$prop->setAccessible(true);
|
||||||
|
$prop->setValue($controller, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function decodeResponse($response): array
|
||||||
|
{
|
||||||
|
return json_decode($response->getBody(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
317
tests/unit/GetReminderMailConfigTest.php
Normal file
317
tests/unit/GetReminderMailConfigTest.php
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Controllers\EmployeeRestController;
|
||||||
|
use App\Models\ClientPolicyModel;
|
||||||
|
use App\Models\ReminderMailConfigModel;
|
||||||
|
use CodeIgniter\HTTP\IncomingRequest;
|
||||||
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
|
use Config\Services;
|
||||||
|
use ReflectionClass;
|
||||||
|
|
||||||
|
class GetReminderMailConfigTest extends CIUnitTestCase
|
||||||
|
{
|
||||||
|
private function createNotificationModelStub(?array $result): object
|
||||||
|
{
|
||||||
|
return new class($result) {
|
||||||
|
private ?array $result;
|
||||||
|
|
||||||
|
public function __construct(?array $result)
|
||||||
|
{
|
||||||
|
$this->result = $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function where(...$args)
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function first(): ?array
|
||||||
|
{
|
||||||
|
return $this->result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildController(
|
||||||
|
array $getParams,
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel,
|
||||||
|
?object $notificationModel = null
|
||||||
|
): EmployeeRestController {
|
||||||
|
$controller = new EmployeeRestController();
|
||||||
|
|
||||||
|
$request = $this->createMock(IncomingRequest::class);
|
||||||
|
$request->method('getGet')
|
||||||
|
->willReturnCallback(function ($key = null) use ($getParams) {
|
||||||
|
if ($key === null) {
|
||||||
|
return $getParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_key_exists($key, $getParams) ? $getParams[$key] : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
$controller->initController($request, Services::response(), Services::logger());
|
||||||
|
|
||||||
|
$reflection = new ReflectionClass($controller);
|
||||||
|
|
||||||
|
foreach ([
|
||||||
|
'clientPolicyModel' => $clientPolicyModel,
|
||||||
|
'reminderMailConfigModel' => $reminderMailConfigModel,
|
||||||
|
'notificationModel' => $notificationModel,
|
||||||
|
] as $property => $value) {
|
||||||
|
if ($value === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$prop = $reflection->getProperty($property);
|
||||||
|
$prop->setAccessible(true);
|
||||||
|
$prop->setValue($controller, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function decodeResponse($response): array
|
||||||
|
{
|
||||||
|
return json_decode($response->getBody(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function mockReminderMailConfigModel(array $methods): ReminderMailConfigModel
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder(ReminderMailConfigModel::class)
|
||||||
|
->onlyMethods(array_keys($methods))
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMissingClientPolicyIdReturns400()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel([]);
|
||||||
|
|
||||||
|
$controller = $this->buildController([], $clientPolicyModel, $reminderMailConfigModel);
|
||||||
|
$body = $this->decodeResponse($controller->getReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(400, $body['code']);
|
||||||
|
$this->assertSame('client_policy_id is required', $body['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClientPolicyNotFoundReturns404()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(999)->willReturn(null);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel([]);
|
||||||
|
|
||||||
|
$controller = $this->buildController(
|
||||||
|
['client_policy_id' => '999'],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel
|
||||||
|
);
|
||||||
|
$body = $this->decodeResponse($controller->getReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(404, $body['code']);
|
||||||
|
$this->assertSame('Client policy not found', $body['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testExistingConfigReturnsEnrichedDataAndWorkingDayOptions()
|
||||||
|
{
|
||||||
|
$config = [
|
||||||
|
'id' => 10,
|
||||||
|
'client_policy_id' => 123,
|
||||||
|
'frequency' => ReminderMailConfigModel::FREQUENCY_WORKING_DAYS,
|
||||||
|
'reminder_days' => '1,3,5',
|
||||||
|
'email_subject' => 'Reminder',
|
||||||
|
'email_body' => '<p>Please enroll</p>',
|
||||||
|
'is_enabled' => 1,
|
||||||
|
'is_active' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn([
|
||||||
|
'id' => 123,
|
||||||
|
'client_id' => 42,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel([
|
||||||
|
'getByClientPolicyId' => null,
|
||||||
|
]);
|
||||||
|
$reminderMailConfigModel->method('getByClientPolicyId')->with(123)->willReturn($config);
|
||||||
|
|
||||||
|
$controller = $this->buildController(
|
||||||
|
['client_policy_id' => '123'],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel
|
||||||
|
);
|
||||||
|
$body = $this->decodeResponse($controller->getReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertTrue($body['status']);
|
||||||
|
$this->assertSame(200, $body['code']);
|
||||||
|
$this->assertSame(123, $body['data']['client_policy_id']);
|
||||||
|
$this->assertSame(['Mon', 'Wed', 'Fri'], $body['data']['working_day_labels']);
|
||||||
|
$this->assertTrue($body['data']['has_custom_template']);
|
||||||
|
$this->assertCount(7, $body['working_day_options']);
|
||||||
|
$this->assertSame('Mon', $body['working_day_options'][0]['label']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLegacyFallbackWhenNoConfigButPolicyHasReminderDate()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn([
|
||||||
|
'id' => 123,
|
||||||
|
'client_id' => 42,
|
||||||
|
'reminder_date' => '1,15,28',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel([
|
||||||
|
'getByClientPolicyId' => null,
|
||||||
|
]);
|
||||||
|
$reminderMailConfigModel->method('getByClientPolicyId')->with(123)->willReturn(null);
|
||||||
|
|
||||||
|
$controller = $this->buildController(
|
||||||
|
['client_policy_id' => '123'],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel
|
||||||
|
);
|
||||||
|
$body = $this->decodeResponse($controller->getReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertTrue($body['status']);
|
||||||
|
$this->assertSame(200, $body['code']);
|
||||||
|
$this->assertSame(123, $body['data']['client_policy_id']);
|
||||||
|
$this->assertSame(ReminderMailConfigModel::FREQUENCY_CUSTOM, $body['data']['frequency']);
|
||||||
|
$this->assertSame('1,15,28', $body['data']['reminder_days']);
|
||||||
|
$this->assertSame('legacy_client_policy', $body['data']['source']);
|
||||||
|
$this->assertArrayHasKey('working_day_options', $body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNoConfigAndNoLegacyReminderDateReturnsNullData()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn([
|
||||||
|
'id' => 123,
|
||||||
|
'client_id' => 42,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel([
|
||||||
|
'getByClientPolicyId' => null,
|
||||||
|
]);
|
||||||
|
$reminderMailConfigModel->method('getByClientPolicyId')->with(123)->willReturn(null);
|
||||||
|
|
||||||
|
$controller = $this->buildController(
|
||||||
|
['client_policy_id' => '123'],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel
|
||||||
|
);
|
||||||
|
$body = $this->decodeResponse($controller->getReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertTrue($body['status']);
|
||||||
|
$this->assertSame(200, $body['code']);
|
||||||
|
$this->assertNull($body['data']);
|
||||||
|
$this->assertCount(7, $body['working_day_options']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmailTemplateModeReturnsConfigTemplate()
|
||||||
|
{
|
||||||
|
$config = [
|
||||||
|
'client_policy_id' => 123,
|
||||||
|
'email_subject' => 'Custom subject',
|
||||||
|
'email_body' => '<p>Custom body</p>',
|
||||||
|
];
|
||||||
|
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn([
|
||||||
|
'id' => 123,
|
||||||
|
'client_id' => 42,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel([
|
||||||
|
'getByClientPolicyId' => null,
|
||||||
|
]);
|
||||||
|
$reminderMailConfigModel->method('getByClientPolicyId')->with(123)->willReturn($config);
|
||||||
|
|
||||||
|
$controller = $this->buildController(
|
||||||
|
[
|
||||||
|
'client_policy_id' => '123',
|
||||||
|
'is_email_template' => '1',
|
||||||
|
],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel
|
||||||
|
);
|
||||||
|
$body = $this->decodeResponse($controller->getReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertTrue($body['status']);
|
||||||
|
$this->assertSame(200, $body['code']);
|
||||||
|
$this->assertSame('Custom subject', $body['data']['email_subject']);
|
||||||
|
$this->assertSame('<p>Custom body</p>', $body['data']['email_body']);
|
||||||
|
$this->assertArrayNotHasKey('working_day_options', $body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmailTemplateModeFallsBackToNotificationWhenNoConfig()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn([
|
||||||
|
'id' => 123,
|
||||||
|
'client_id' => 42,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel([
|
||||||
|
'getByClientPolicyId' => null,
|
||||||
|
]);
|
||||||
|
$reminderMailConfigModel->method('getByClientPolicyId')->with(123)->willReturn(null);
|
||||||
|
|
||||||
|
$notificationModel = $this->createNotificationModelStub([
|
||||||
|
'subject' => 'Default subject',
|
||||||
|
'mail_content' => '<p>Default body</p>',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$controller = $this->buildController(
|
||||||
|
[
|
||||||
|
'client_policy_id' => '123',
|
||||||
|
'is_email_template' => '1',
|
||||||
|
],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel,
|
||||||
|
$notificationModel
|
||||||
|
);
|
||||||
|
$body = $this->decodeResponse($controller->getReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertTrue($body['status']);
|
||||||
|
$this->assertSame(200, $body['code']);
|
||||||
|
$this->assertSame('Default subject', $body['data']['email_subject']);
|
||||||
|
$this->assertSame('<p>Default body</p>', $body['data']['email_body']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmailTemplateModeReturns404WhenNotificationMissing()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn([
|
||||||
|
'id' => 123,
|
||||||
|
'client_id' => 42,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel([
|
||||||
|
'getByClientPolicyId' => null,
|
||||||
|
]);
|
||||||
|
$reminderMailConfigModel->method('getByClientPolicyId')->with(123)->willReturn(null);
|
||||||
|
|
||||||
|
$notificationModel = $this->createNotificationModelStub(null);
|
||||||
|
|
||||||
|
$controller = $this->buildController(
|
||||||
|
[
|
||||||
|
'client_policy_id' => '123',
|
||||||
|
'is_email_template' => '1',
|
||||||
|
],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel,
|
||||||
|
$notificationModel
|
||||||
|
);
|
||||||
|
$body = $this->decodeResponse($controller->getReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(404, $body['code']);
|
||||||
|
$this->assertSame('Member reminder mail notification not found', $body['message']);
|
||||||
|
}
|
||||||
|
}
|
||||||
161
tests/unit/ReminderMailConfigModelTest.php
Normal file
161
tests/unit/ReminderMailConfigModelTest.php
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Models\ReminderMailConfigModel;
|
||||||
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
|
|
||||||
|
class ReminderMailConfigModelTest extends CIUnitTestCase
|
||||||
|
{
|
||||||
|
private ReminderMailConfigModel $model;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->model = new ReminderMailConfigModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHasCustomTemplateRequiresBothSubjectAndBody()
|
||||||
|
{
|
||||||
|
$this->assertFalse($this->model->hasCustomTemplate(null));
|
||||||
|
$this->assertFalse($this->model->hasCustomTemplate([]));
|
||||||
|
$this->assertFalse($this->model->hasCustomTemplate([
|
||||||
|
'email_subject' => 'Reminder',
|
||||||
|
'email_body' => '',
|
||||||
|
]));
|
||||||
|
$this->assertFalse($this->model->hasCustomTemplate([
|
||||||
|
'email_subject' => ' ',
|
||||||
|
'email_body' => '<p>Body</p>',
|
||||||
|
]));
|
||||||
|
$this->assertTrue($this->model->hasCustomTemplate([
|
||||||
|
'email_subject' => 'Reminder',
|
||||||
|
'email_body' => '<p>Body</p>',
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResolveNotificationTemplateUsesCustomTemplateWhenConfigured()
|
||||||
|
{
|
||||||
|
$config = [
|
||||||
|
'email_subject' => 'Custom subject',
|
||||||
|
'email_body' => '<p>Custom body</p>',
|
||||||
|
];
|
||||||
|
|
||||||
|
$notification = [
|
||||||
|
'id' => 5,
|
||||||
|
'enabled' => 0,
|
||||||
|
'subject' => 'Default subject',
|
||||||
|
'mail_content' => '<p>Default body</p>',
|
||||||
|
];
|
||||||
|
|
||||||
|
$resolved = $this->model->resolveNotificationTemplate($config, $notification);
|
||||||
|
|
||||||
|
$this->assertSame('Custom subject', $resolved['subject']);
|
||||||
|
$this->assertSame('<p>Custom body</p>', $resolved['mail_content']);
|
||||||
|
$this->assertSame(1, $resolved['enabled']);
|
||||||
|
$this->assertSame(5, $resolved['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResolveNotificationTemplateReturnsDefaultWhenCustomTemplateMissing()
|
||||||
|
{
|
||||||
|
$notification = [
|
||||||
|
'subject' => 'Default subject',
|
||||||
|
'mail_content' => '<p>Default body</p>',
|
||||||
|
];
|
||||||
|
|
||||||
|
$resolved = $this->model->resolveNotificationTemplate(
|
||||||
|
['email_subject' => 'Only subject'],
|
||||||
|
$notification
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertSame($notification, $resolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanSendReminderMailAllowsCustomTemplateEvenWhenNotificationDisabled()
|
||||||
|
{
|
||||||
|
$config = [
|
||||||
|
'email_subject' => 'Custom subject',
|
||||||
|
'email_body' => '<p>Custom body</p>',
|
||||||
|
];
|
||||||
|
|
||||||
|
$notification = [
|
||||||
|
'enabled' => 0,
|
||||||
|
'mail_content' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->assertTrue($this->model->canSendReminderMail($config, $notification));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanSendReminderMailRequiresEnabledDefaultNotification()
|
||||||
|
{
|
||||||
|
$this->assertFalse($this->model->canSendReminderMail(null, null));
|
||||||
|
$this->assertFalse($this->model->canSendReminderMail(null, [
|
||||||
|
'enabled' => 0,
|
||||||
|
'mail_content' => '<p>Body</p>',
|
||||||
|
]));
|
||||||
|
$this->assertFalse($this->model->canSendReminderMail(null, [
|
||||||
|
'enabled' => 1,
|
||||||
|
'mail_content' => '',
|
||||||
|
]));
|
||||||
|
$this->assertTrue($this->model->canSendReminderMail(null, [
|
||||||
|
'enabled' => 1,
|
||||||
|
'mail_content' => '<p>Body</p>',
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidateConfigRejectsInvalidFrequency()
|
||||||
|
{
|
||||||
|
$error = $this->model->validateConfig('hourly', '1');
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
'Invalid frequency. Allowed values: daily, weekly, monthly, custom, working_days.',
|
||||||
|
$error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidateConfigDailyDoesNotRequireReminderDays()
|
||||||
|
{
|
||||||
|
$this->assertNull($this->model->validateConfig(
|
||||||
|
ReminderMailConfigModel::FREQUENCY_DAILY,
|
||||||
|
null
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidateConfigWorkingDaysAcceptsDayNames()
|
||||||
|
{
|
||||||
|
$this->assertNull($this->model->validateConfig(
|
||||||
|
ReminderMailConfigModel::FREQUENCY_WORKING_DAYS,
|
||||||
|
'Mon,Wed,Fri'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidateConfigWeeklyRejectsInvalidDay()
|
||||||
|
{
|
||||||
|
$error = $this->model->validateConfig(
|
||||||
|
ReminderMailConfigModel::FREQUENCY_WEEKLY,
|
||||||
|
'0,8'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
'Weekly reminder_days must be between 0 (Sunday) and 6 (Saturday).',
|
||||||
|
$error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEnrichConfigAddsCustomTemplateFlagAndWorkingDayLabels()
|
||||||
|
{
|
||||||
|
$config = $this->model->enrichConfig([
|
||||||
|
'frequency' => ReminderMailConfigModel::FREQUENCY_WORKING_DAYS,
|
||||||
|
'reminder_days' => '1,3,5',
|
||||||
|
'email_subject' => 'Reminder',
|
||||||
|
'email_body' => '<p>Please enroll</p>',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertTrue($config['has_custom_template']);
|
||||||
|
$this->assertSame(['Mon', 'Wed', 'Fri'], $config['working_day_labels']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNormalizeWorkingDaysSortsAndDeduplicates()
|
||||||
|
{
|
||||||
|
$this->assertSame('1,3,5', $this->model->normalizeWorkingDays('Fri,Mon,Wed,Mon'));
|
||||||
|
}
|
||||||
|
}
|
||||||
173
tests/unit/SaveReminderMailConfigTest.php
Normal file
173
tests/unit/SaveReminderMailConfigTest.php
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Controllers\EmployeeRestController;
|
||||||
|
use App\Models\ClientPolicyModel;
|
||||||
|
use App\Models\ReminderMailConfigModel;
|
||||||
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
|
use Tests\Support\Traits\ReminderMailControllerTestTrait;
|
||||||
|
|
||||||
|
class SaveReminderMailConfigTest extends CIUnitTestCase
|
||||||
|
{
|
||||||
|
use ReminderMailControllerTestTrait;
|
||||||
|
|
||||||
|
private function mockReminderMailConfigModel(array $methods): ReminderMailConfigModel
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder(ReminderMailConfigModel::class)
|
||||||
|
->onlyMethods(array_keys($methods))
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMissingClientPolicyIdReturns400()
|
||||||
|
{
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
['frequency' => 'daily'],
|
||||||
|
$this->createMock(ClientPolicyModel::class),
|
||||||
|
$this->mockReminderMailConfigModel([])
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->saveReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(400, $body['code']);
|
||||||
|
$this->assertSame('client_policy_id is required', $body['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMissingFrequencyReturns400()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
['client_policy_id' => 123],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$this->mockReminderMailConfigModel([])
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->saveReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(400, $body['code']);
|
||||||
|
$this->assertSame('frequency is required', $body['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClientPolicyNotFoundReturns404()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn(null);
|
||||||
|
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
[
|
||||||
|
'client_policy_id' => 123,
|
||||||
|
'frequency' => 'daily',
|
||||||
|
],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$this->mockReminderMailConfigModel([])
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->saveReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(404, $body['code']);
|
||||||
|
$this->assertSame('Client policy not found', $body['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSaveConfigValidationErrorReturns400()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn(['id' => 123]);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel(['saveConfig' => null]);
|
||||||
|
$reminderMailConfigModel->expects($this->once())
|
||||||
|
->method('saveConfig')
|
||||||
|
->with(
|
||||||
|
123,
|
||||||
|
'weekly',
|
||||||
|
'9',
|
||||||
|
1,
|
||||||
|
$this->callback(function (array $options): bool {
|
||||||
|
return !array_key_exists('email_subject', $options)
|
||||||
|
&& !array_key_exists('email_body', $options);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
->willReturn([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Weekly reminder_days must be between 0 (Sunday) and 6 (Saturday).',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
[
|
||||||
|
'client_policy_id' => 123,
|
||||||
|
'frequency' => 'weekly',
|
||||||
|
'reminder_days' => '9',
|
||||||
|
],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->saveReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(400, $body['code']);
|
||||||
|
$this->assertSame(
|
||||||
|
'Weekly reminder_days must be between 0 (Sunday) and 6 (Saturday).',
|
||||||
|
$body['message']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSuccessfulSaveIncludesEmailTemplateFields()
|
||||||
|
{
|
||||||
|
$savedConfig = [
|
||||||
|
'id' => 10,
|
||||||
|
'client_policy_id' => 123,
|
||||||
|
'frequency' => ReminderMailConfigModel::FREQUENCY_DAILY,
|
||||||
|
'email_subject' => 'Reminder subject',
|
||||||
|
'email_body' => '<p>Reminder body</p>',
|
||||||
|
'is_enabled' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn(['id' => 123]);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel(['saveConfig' => null]);
|
||||||
|
$reminderMailConfigModel->expects($this->once())
|
||||||
|
->method('saveConfig')
|
||||||
|
->with(
|
||||||
|
123,
|
||||||
|
'daily',
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
$this->callback(function (array $options): bool {
|
||||||
|
return ($options['email_subject'] ?? null) === 'Reminder subject'
|
||||||
|
&& ($options['email_body'] ?? null) === '<p>Reminder body</p>'
|
||||||
|
&& ($options['hr_id'] ?? null) === 45;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
->willReturn([
|
||||||
|
'status' => true,
|
||||||
|
'action' => 'updated',
|
||||||
|
'data' => $savedConfig,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
[
|
||||||
|
'client_policy_id' => 123,
|
||||||
|
'frequency' => 'daily',
|
||||||
|
'email_subject' => 'Reminder subject',
|
||||||
|
'email_body' => '<p>Reminder body</p>',
|
||||||
|
'hr_id' => 45,
|
||||||
|
],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->saveReminderMailConfig());
|
||||||
|
|
||||||
|
$this->assertTrue($body['status']);
|
||||||
|
$this->assertSame(200, $body['code']);
|
||||||
|
$this->assertSame('updated', $body['action']);
|
||||||
|
$this->assertSame('Reminder mail configuration saved successfully', $body['message']);
|
||||||
|
$this->assertSame('Reminder subject', $body['data']['email_subject']);
|
||||||
|
$this->assertSame('<p>Reminder body</p>', $body['data']['email_body']);
|
||||||
|
}
|
||||||
|
}
|
||||||
181
tests/unit/SendReminderMailTest.php
Normal file
181
tests/unit/SendReminderMailTest.php
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Controllers\EmployeeRestController;
|
||||||
|
use App\Models\ClientPolicyModel;
|
||||||
|
use App\Models\ReminderMailConfigModel;
|
||||||
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
|
use Config\Services;
|
||||||
|
use Tests\Support\Traits\ReminderMailControllerTestTrait;
|
||||||
|
|
||||||
|
class SendReminderMailTest extends CIUnitTestCase
|
||||||
|
{
|
||||||
|
use ReminderMailControllerTestTrait;
|
||||||
|
|
||||||
|
private function mockReminderMailConfigModel(array $methods): ReminderMailConfigModel
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder(ReminderMailConfigModel::class)
|
||||||
|
->onlyMethods(array_keys($methods))
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNonPostRequestReturns405()
|
||||||
|
{
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
['client_policy_id' => 123],
|
||||||
|
$this->createMock(ClientPolicyModel::class),
|
||||||
|
$this->mockReminderMailConfigModel([]),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->sendReminderMail());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(405, $body['code']);
|
||||||
|
$this->assertSame('Only POST method is allowed', $body['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyJsonBodyReturns400()
|
||||||
|
{
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
[],
|
||||||
|
$this->createMock(ClientPolicyModel::class),
|
||||||
|
$this->mockReminderMailConfigModel([])
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->sendReminderMail());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(400, $body['code']);
|
||||||
|
$this->assertSame('JSON request body is required', $body['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMissingClientPolicyIdReturns400()
|
||||||
|
{
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
['email_subject' => 'Reminder'],
|
||||||
|
$this->createMock(ClientPolicyModel::class),
|
||||||
|
$this->mockReminderMailConfigModel([])
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->sendReminderMail());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(400, $body['code']);
|
||||||
|
$this->assertSame('client_policy_id is required', $body['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClientPolicyNotFoundReturns404()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn(null);
|
||||||
|
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
['client_policy_id' => 123],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$this->mockReminderMailConfigModel([])
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->sendReminderMail());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame(404, $body['code']);
|
||||||
|
$this->assertSame('Client policy not found', $body['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSavesEmailTemplateBeforeSendingMail()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn([
|
||||||
|
'id' => 123,
|
||||||
|
'client_id' => 42,
|
||||||
|
'client_branch_id' => 7,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel(['saveEmailTemplate' => null]);
|
||||||
|
$reminderMailConfigModel->expects($this->once())
|
||||||
|
->method('saveEmailTemplate')
|
||||||
|
->with(
|
||||||
|
123,
|
||||||
|
'Enrollment reminder',
|
||||||
|
'<p>Hi [[member_name]]</p>',
|
||||||
|
45
|
||||||
|
);
|
||||||
|
|
||||||
|
$controller = $this->getMockBuilder(EmployeeRestController::class)
|
||||||
|
->onlyMethods(['dispatchManualReminder'])
|
||||||
|
->getMock();
|
||||||
|
$controller->expects($this->once())
|
||||||
|
->method('dispatchManualReminder')
|
||||||
|
->with(42, 7, 123)
|
||||||
|
->willReturn(
|
||||||
|
Services::response()->setJSON([
|
||||||
|
'status' => true,
|
||||||
|
'code' => 200,
|
||||||
|
'message' => 'Mail sent successfully',
|
||||||
|
])->setStatusCode(200)
|
||||||
|
);
|
||||||
|
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
[
|
||||||
|
'client_policy_id' => 123,
|
||||||
|
'email_subject' => 'Enrollment reminder',
|
||||||
|
'email_body' => '<p>Hi [[member_name]]</p>',
|
||||||
|
'hr_id' => 45,
|
||||||
|
],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
$controller
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->sendReminderMail());
|
||||||
|
|
||||||
|
$this->assertTrue($body['status']);
|
||||||
|
$this->assertSame(200, $body['code']);
|
||||||
|
$this->assertSame('Mail sent successfully', $body['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSkipsTemplateSaveWhenEmailFieldsNotProvided()
|
||||||
|
{
|
||||||
|
$clientPolicyModel = $this->createMock(ClientPolicyModel::class);
|
||||||
|
$clientPolicyModel->method('find')->with(123)->willReturn([
|
||||||
|
'id' => 123,
|
||||||
|
'client_id' => 42,
|
||||||
|
'client_branch_id' => 7,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$reminderMailConfigModel = $this->mockReminderMailConfigModel(['saveEmailTemplate' => null]);
|
||||||
|
$reminderMailConfigModel->expects($this->never())->method('saveEmailTemplate');
|
||||||
|
|
||||||
|
$controller = $this->getMockBuilder(EmployeeRestController::class)
|
||||||
|
->onlyMethods(['dispatchManualReminder'])
|
||||||
|
->getMock();
|
||||||
|
$controller->expects($this->once())
|
||||||
|
->method('dispatchManualReminder')
|
||||||
|
->with(42, 7, 123)
|
||||||
|
->willReturn(
|
||||||
|
Services::response()->setJSON([
|
||||||
|
'status' => false,
|
||||||
|
'code' => 200,
|
||||||
|
'message' => 'There is no data to send',
|
||||||
|
])->setStatusCode(200)
|
||||||
|
);
|
||||||
|
|
||||||
|
$controller = $this->buildJsonPostController(
|
||||||
|
['client_policy_id' => 123],
|
||||||
|
$clientPolicyModel,
|
||||||
|
$reminderMailConfigModel,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
$controller
|
||||||
|
);
|
||||||
|
|
||||||
|
$body = $this->decodeResponse($controller->sendReminderMail());
|
||||||
|
|
||||||
|
$this->assertFalse($body['status']);
|
||||||
|
$this->assertSame('There is no data to send', $body['message']);
|
||||||
|
}
|
||||||
|
}
|
||||||
0
writable/venbaehn_nhance
Normal file
0
writable/venbaehn_nhance
Normal file
Loading…
Reference in New Issue
Block a user