Merge branch 'master' into fix/tru-89-customer-portal-tilladelser-tab
This commit is contained in:
@@ -1421,7 +1421,49 @@ function GoalsProgressAlertsCron(): void
|
||||
case Dest::SLACK:
|
||||
$departments = (array)$goal->departments->value();
|
||||
$sentToDept = false;
|
||||
if (count($departments) > 0) {
|
||||
$internalDepartmentIds = [];
|
||||
try {
|
||||
$slackConfig = new Slack();
|
||||
if (method_exists($slackConfig, 'get_internal_department_ids')) {
|
||||
$internalDepartmentIds = array_map('intval', (array)$slackConfig->get_internal_department_ids());
|
||||
}
|
||||
} catch (Throwable $slackConfigError) {
|
||||
// Ignore - falls back to per-department webhooks
|
||||
$internalDepartmentIds = [];
|
||||
}
|
||||
$goalDeptIds = [];
|
||||
foreach ($departments as $deptId) {
|
||||
if (is_numeric($deptId)) {
|
||||
$goalDeptIds[] = (int)$deptId;
|
||||
}
|
||||
}
|
||||
$allInternal = count($goalDeptIds) > 0
|
||||
&& count(array_diff($goalDeptIds, $internalDepartmentIds)) === 0;
|
||||
|
||||
if ($allInternal) {
|
||||
// TRU-76: For internal departments (e.g. Taulov/Taastrup DHL daily
|
||||
// goal), post to the dedicated internal goal progress webhook
|
||||
// instead of per-department webhooks, which are typically empty
|
||||
// for internal locations.
|
||||
$internalWebhook = '';
|
||||
try {
|
||||
$slackInstance = new Slack();
|
||||
if (method_exists($slackInstance, 'get_internal_department_goal_progress_webhook_url')) {
|
||||
$internalWebhook = trim((string)$slackInstance->get_internal_department_goal_progress_webhook_url());
|
||||
}
|
||||
} catch (Throwable $internalWebhookError) {
|
||||
$internalWebhook = '';
|
||||
}
|
||||
if ($internalWebhook !== '') {
|
||||
(new Slack())->send_webhook_message((string)goals_progress_alert_renderer::render($criteria), $internalWebhook);
|
||||
$sentToDept = true;
|
||||
echo "[" . date('Y-m-d H:i:s') . "][CRON] GoalsProgressAlertsCron: goal #" . $goalId . " sent to internal goal progress webhook (departments: " . implode(',', $goalDeptIds) . ")\n";
|
||||
} else {
|
||||
echo "[" . date('Y-m-d H:i:s') . "][CRON] GoalsProgressAlertsCron: goal #" . $goalId . " has only internal departments but internal_department_goal_progress_webhook_url is empty; falling back to per-department webhooks\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!$sentToDept && count($departments) > 0) {
|
||||
foreach ($departments as $deptId) {
|
||||
if (!is_numeric($deptId)) { continue; }
|
||||
$dept = (new departments_o())->select((int)$deptId);
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* TRU-76: DHL daily goal for Taulov/Taastrup was not posting to Slack because
|
||||
* GoalsProgressAlertsCron only consulted the per-department `slack_webhook`
|
||||
* field. For "internal" departments (Taulov/Taastrup are configured as
|
||||
* internal) those per-department webhooks are intentionally empty — the
|
||||
* dedicated internal goal progress webhook is the right destination.
|
||||
*
|
||||
* These tests pin the new dispatch behavior:
|
||||
* 1. The cron reads internal_department_ids from the Slack config.
|
||||
* 2. When ALL goal departments are internal AND the dedicated
|
||||
* internal_department_goal_progress_webhook_url is configured, the cron
|
||||
* posts to that webhook (not the per-department one).
|
||||
* 3. When the dedicated webhook is empty, the cron logs a diagnostic
|
||||
* message and falls back to the per-department webhook loop.
|
||||
* 4. When the goal includes any non-internal department, the cron skips
|
||||
* the dedicated webhook entirely and uses the per-department loop.
|
||||
*/
|
||||
|
||||
it('loads internal department ids from the Slack config helper', function (): void {
|
||||
$content = file_get_contents(app_path('cron/Cron.php'));
|
||||
|
||||
expect($content)->not->toBeFalse();
|
||||
expect($content)->toContain("get_internal_department_ids");
|
||||
expect($content)->toContain("get_internal_department_goal_progress_webhook_url");
|
||||
});
|
||||
|
||||
it('posts to the dedicated internal goal progress webhook when all goal departments are internal', function (): void {
|
||||
$content = file_get_contents(app_path('cron/Cron.php'));
|
||||
|
||||
expect($content)->not->toBeFalse();
|
||||
// The new branch should be guarded by an "all internal" check.
|
||||
expect($content)->toContain('$allInternal');
|
||||
expect($content)->toContain('count(array_diff($goalDeptIds, $internalDepartmentIds)) === 0');
|
||||
// It should call send_webhook_message with the dedicated internal URL.
|
||||
expect($content)->toContain("send_webhook_message((string)goals_progress_alert_renderer::render(\$criteria), \$internalWebhook)");
|
||||
// It should log a confirmation line referencing the goal id and the
|
||||
// department list so an operator can verify the message actually went
|
||||
// somewhere.
|
||||
expect($content)->toContain('internal goal progress webhook');
|
||||
expect($content)->toContain('departments: ');
|
||||
});
|
||||
|
||||
it('logs a diagnostic and falls back to per-department webhooks when the internal goal progress webhook is empty', function (): void {
|
||||
$content = file_get_contents(app_path('cron/Cron.php'));
|
||||
|
||||
expect($content)->not->toBeFalse();
|
||||
expect($content)->toContain('internal_department_goal_progress_webhook_url is empty');
|
||||
expect($content)->toContain('falling back to per-department webhooks');
|
||||
// The per-department fallback should still run after the internal-webhook
|
||||
// branch is skipped.
|
||||
expect($content)->toContain('$dept->slack_webhook->value()');
|
||||
});
|
||||
|
||||
it('skips the internal goal progress webhook for goals that include any non-internal department', function (): void {
|
||||
$content = file_get_contents(app_path('cron/Cron.php'));
|
||||
|
||||
expect($content)->not->toBeFalse();
|
||||
// The internal-webhook branch must be guarded by the all-internal check;
|
||||
// otherwise external customers' goal alerts would be silently redirected
|
||||
// to the internal Slack channel.
|
||||
expect($content)->toContain('if ($allInternal) {');
|
||||
expect($content)->toContain('send_webhook_message((string)goals_progress_alert_renderer::render($criteria), $internalWebhook)');
|
||||
// The per-department loop must still be reachable for mixed/external goals.
|
||||
expect($content)->toContain('$sentToDept = false;');
|
||||
expect($content)->toContain('$dept->slack_webhook->value()');
|
||||
});
|
||||
Reference in New Issue
Block a user