diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 569a22f..80256f5 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -511,7 +511,6 @@ $routes->group("employeeRest", ['filter' => [ 'GlobalPostFileUploadGuard', 'appS $routes->get("getExcelFileErrors/(:any)", "EmployeeController::getExcelFileErrors/$1"); $routes->post("sendReminderMail", "EmployeeRestController::sendReminderMail"); - $routes->get("sendReminderMail", "EmployeeRestController::sendReminderMail"); $routes->get("getReminderMailConfig", "EmployeeRestController::getReminderMailConfig"); $routes->post("saveReminderMailConfig", "EmployeeRestController::saveReminderMailConfig"); diff --git a/app/Controllers/DashboardController.php b/app/Controllers/DashboardController.php index 1739b54..0a62204 100755 --- a/app/Controllers/DashboardController.php +++ b/app/Controllers/DashboardController.php @@ -350,7 +350,13 @@ class DashboardController extends AdminController ->where('template_name', 'member_reminder_mail') ->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 if (empty($send_mail_for_manual_or_crone)) { diff --git a/app/Controllers/EmployeeController.php b/app/Controllers/EmployeeController.php index 3aba419..1616f34 100755 --- a/app/Controllers/EmployeeController.php +++ b/app/Controllers/EmployeeController.php @@ -3267,7 +3267,10 @@ class EmployeeController extends AdminController $sentCount = 0; try { $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'] ?? ''; if(empty($acm_Mails)){ @@ -3282,6 +3285,11 @@ class EmployeeController extends AdminController : 'N/A'; $subject = 'Enrollment Closed - Enrolled Employee List | ' . ($clientData['client_name'] ?? ''); + $statusTilesHtml = $this->renderEnrollmentStatusTilesForMail( + $fileClientId, + (int) $file['client_branch_id'], + $filePolicyId + ); foreach ($hrRecipients as $hrRecipient) { $hrEmail = trim($hrRecipient['email'] ?? ''); @@ -3291,7 +3299,7 @@ class EmployeeController extends AdminController continue; } - $mailContent = $this->buildEnrollmentClosedHrMailContent([ + $mailContent = $statusTilesHtml . $this->buildEnrollmentClosedHrMailContent([ 'hr_name' => $hrName, 'client_name' => $clientData['client_name'] ?? '', '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 { $hrName = htmlspecialchars($data['hr_name'] ?? 'HR Team', ENT_QUOTES, 'UTF-8'); @@ -3368,19 +3387,19 @@ class EmployeeController extends AdminController
|
- Dear ' . $hrName . ', -The enrollment window for ' . $clientName . ' has closed. -+ |
+ Dear ' . $hrName . ',
+ The enrollment window for ' . $clientName . ' has closed.
+
Policy No: ' . $policyNo . '
+ Enrollment Open Date: ' . $openDate . ' Enrollment Close Date: ' . $closeDate . ' - - +
Please find the attached Excel file with the enrolled employee list
(' . $employeeCount . ' record' . ($employeeCount === 1 ? '' : 's') . ').
-
-
+ Regards, Regards,
Nhance Team |
| + Enrollment Summary + | +||||
+
|
+
|
- ');
- background-size:contain;
- background-repeat:no-repeat;
- background-position: center;
- ">
-
-
+
+ |
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);
+ }
+}
diff --git a/tests/unit/GetReminderMailConfigTest.php b/tests/unit/GetReminderMailConfigTest.php
new file mode 100644
index 0000000..e86e8b2
--- /dev/null
+++ b/tests/unit/GetReminderMailConfigTest.php
@@ -0,0 +1,317 @@
+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' => 'Please enroll ', + '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' => 'Custom body ', + ]; + + $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('Custom body ', $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' => 'Default body ', + ]); + + $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('Default body ', $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']); + } +} diff --git a/tests/unit/ReminderMailConfigModelTest.php b/tests/unit/ReminderMailConfigModelTest.php new file mode 100644 index 0000000..47bc728 --- /dev/null +++ b/tests/unit/ReminderMailConfigModelTest.php @@ -0,0 +1,161 @@ +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' => 'Body ', + ])); + $this->assertTrue($this->model->hasCustomTemplate([ + 'email_subject' => 'Reminder', + 'email_body' => 'Body ', + ])); + } + + public function testResolveNotificationTemplateUsesCustomTemplateWhenConfigured() + { + $config = [ + 'email_subject' => 'Custom subject', + 'email_body' => 'Custom body ', + ]; + + $notification = [ + 'id' => 5, + 'enabled' => 0, + 'subject' => 'Default subject', + 'mail_content' => 'Default body ', + ]; + + $resolved = $this->model->resolveNotificationTemplate($config, $notification); + + $this->assertSame('Custom subject', $resolved['subject']); + $this->assertSame('Custom body ', $resolved['mail_content']); + $this->assertSame(1, $resolved['enabled']); + $this->assertSame(5, $resolved['id']); + } + + public function testResolveNotificationTemplateReturnsDefaultWhenCustomTemplateMissing() + { + $notification = [ + 'subject' => 'Default subject', + 'mail_content' => 'Default body ', + ]; + + $resolved = $this->model->resolveNotificationTemplate( + ['email_subject' => 'Only subject'], + $notification + ); + + $this->assertSame($notification, $resolved); + } + + public function testCanSendReminderMailAllowsCustomTemplateEvenWhenNotificationDisabled() + { + $config = [ + 'email_subject' => 'Custom subject', + 'email_body' => 'Custom body ', + ]; + + $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' => 'Body ', + ])); + $this->assertFalse($this->model->canSendReminderMail(null, [ + 'enabled' => 1, + 'mail_content' => '', + ])); + $this->assertTrue($this->model->canSendReminderMail(null, [ + 'enabled' => 1, + 'mail_content' => 'Body ', + ])); + } + + 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' => 'Please enroll ', + ]); + + $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')); + } +} diff --git a/tests/unit/SaveReminderMailConfigTest.php b/tests/unit/SaveReminderMailConfigTest.php new file mode 100644 index 0000000..abac9a8 --- /dev/null +++ b/tests/unit/SaveReminderMailConfigTest.php @@ -0,0 +1,173 @@ +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' => 'Reminder body ', + '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) === 'Reminder body ' + && ($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' => 'Reminder body ', + '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('Reminder body ', $body['data']['email_body']); + } +} diff --git a/tests/unit/SendReminderMailTest.php b/tests/unit/SendReminderMailTest.php new file mode 100644 index 0000000..3e95071 --- /dev/null +++ b/tests/unit/SendReminderMailTest.php @@ -0,0 +1,181 @@ +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', + 'Hi [[member_name]] ', + 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' => 'Hi [[member_name]] ', + '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']); + } +} diff --git a/writable/venbaehn_nhance b/writable/venbaehn_nhance new file mode 100644 index 0000000..e69de29 |