diff --git a/modules/helpdesk/pages/helpdesk/handovers/create().php b/modules/helpdesk/pages/helpdesk/handovers/create().php index 175b952..3e86ada 100644 --- a/modules/helpdesk/pages/helpdesk/handovers/create().php +++ b/modules/helpdesk/pages/helpdesk/handovers/create().php @@ -20,11 +20,6 @@ $returnTarget = requestResolveReturnTarget('helpdesk/handovers'); $closeTarget = requestResolveReturnTarget('helpdesk/handovers'); $createTarget = requestPathWithReturnTarget('helpdesk/handovers/create', $returnTarget); -$step = (int) $request->query('step', '1'); -if ($step < 1 || $step > 2) { - $step = 1; -} - $errorBag = formErrors(); $productService = app(SoftwareProductService::class); $handoverService = app(HandoverService::class); @@ -33,25 +28,84 @@ $appSession = $sessionStore->all(); $sessionKey = 'module.helpdesk.handover_create'; $authService = app(AuthorizationService::class); -$userId0 = (int) ($appSession['user']['id'] ?? 0); -$canManage = $authService->authorize(HelpdeskAuthorizationPolicy::ABILITY_HANDOVERS_MANAGE, ['actor_user_id' => $userId0])->isAllowed(); +$currentUserId = (int) ($appSession['user']['id'] ?? 0); +$currentTenantId = (int) ($appSession['current_tenant']['id'] ?? 0); +$canManage = $authService->authorize(HelpdeskAuthorizationPolicy::ABILITY_HANDOVERS_MANAGE, ['actor_user_id' => $currentUserId])->isAllowed(); -// ── Step 1: Select debitor + product ───────────────────────────────── +// For managers: step 1 = mode selection (self/assign), step 2 = form, step 3 = protocol (self mode only) +// For non-managers: step 1 = form, step 2 = protocol +$step = (int) $request->query('step', '1'); +$mode = $request->query('mode', ''); // 'self' or 'assign' -if ($step === 1) { +// ── Manager step 1: choose mode ────────────────────────────────────── + +if ($canManage && $step === 1) { + if ($request->isMethod('POST')) { + if (!Session::checkCsrfToken()) { + Flash::error(t('Form expired, please try again'), $createTarget, 'csrf_expired'); + Router::redirect($createTarget); + return; + } + + $chosenMode = (string) $request->body('mode', ''); + if (!in_array($chosenMode, ['self', 'assign'], true)) { + $errorBag->add('mode', t('Please select an option')); + } + + if (!$errorBag->hasAny()) { + $sessionStore->remove($sessionKey); + Router::redirect(lurl('helpdesk/handovers/create') . '?step=2&mode=' . $chosenMode . ($returnTarget ? '&return=' . rawurlencode($returnTarget) : '')); + return; + } + } + + $errors = $errorBag->toFlatList(); + $validationSummaryErrors = $errorBag->toArray(); + Buffer::set('title', t('New handover')); + Buffer::set('style_groups', json_encode(['helpdesk'])); + $breadcrumbs = [ + ['label' => t('Home'), 'path' => 'admin'], + ['label' => t('Helpdesk'), 'path' => 'helpdesk'], + ['label' => t('Handovers'), 'path' => 'helpdesk/handovers'], + ['label' => t('New handover')], + ]; + return; +} + +// ── Step for form (step 2 for managers, step 1 for non-managers) ────── + +$formStep = $canManage ? 2 : 1; +$protocolStep = $canManage ? 3 : 2; + +// Redirect non-managers who somehow get step > 2 +if (!$canManage && $step > 2) { + $step = 1; +} + +// For managers: validate mode param +if ($canManage && $step >= 2) { + $sessionData = $sessionStore->get($sessionKey); + $mode = $mode ?: (string) ($sessionData['mode'] ?? ''); + if (!in_array($mode, ['self', 'assign'], true)) { + Router::redirect($createTarget); + return; + } +} + +// ── Form step: select debitor + product (+ assignee for assign mode) ── + +if ($step === $formStep) { $productsWithSchema = $productService->listWithSchema(); $tenantUsers = []; - if ($canManage) { - $session = app(SessionStoreInterface::class)->all(); - $tenantId = (int) ($session['current_tenant']['id'] ?? 0); + if ($canManage && $mode === 'assign') { $rows = DB::select( 'SELECT u.id, u.display_name, u.email' . ' FROM users u' . ' JOIN user_tenants ut ON ut.user_id = u.id' . ' WHERE ut.tenant_id = ? AND u.active = 1' . ' ORDER BY u.display_name ASC', - (string) $tenantId + (string) $currentTenantId ); $tenantUsers = is_array($rows) ? $rows : []; } @@ -70,7 +124,6 @@ if ($step === 1) { if (!Session::checkCsrfToken()) { Flash::error(t('Form expired, please try again'), $createTarget, 'csrf_expired'); Router::redirect($createTarget); - return; } @@ -93,8 +146,13 @@ if ($step === 1) { } } + if ($canManage && $mode === 'assign' && $form['assigned_to'] <= 0) { + $errorBag->add('assigned_to', t('Please select an employee to assign')); + } + if (!$errorBag->hasAny()) { $sessionStore->set($sessionKey, [ + 'mode' => $mode, 'debitor_no' => trim($form['debitor_no']), 'debitor_name' => trim($form['debitor_name']), 'product_code' => trim($form['product_code']), @@ -104,9 +162,41 @@ if ($step === 1) { 'due_date' => trim($form['due_date']), ]); - Router::redirect(lurl('helpdesk/handovers/create') . '?step=2' . ($returnTarget ? '&return=' . rawurlencode($returnTarget) : '')); + // Assign mode: create record immediately and send invitation, skip protocol step + if ($canManage && $mode === 'assign') { + $result = $handoverService->create( + $currentTenantId, + trim($form['debitor_no']), + trim($form['debitor_name']), + trim($form['product_code']), + trim($form['domain_no']), + trim($form['domain_url']), + $currentUserId, + [] + ); - return; + if (!($result['ok'] ?? false)) { + foreach ($result['errors'] ?? [] as $key => $msg) { + $errorBag->add($key, $msg); + } + } else { + $handoverId = $result['id']; + $dueDate = trim($form['due_date']) ?: null; + $handoverService->assign($currentTenantId, $handoverId, $form['assigned_to'], $currentUserId, $dueDate, HandoverService::PERMISSION_MANAGE); + $sessionStore->remove($sessionKey); + + $editUrl = lurl('helpdesk/handovers/edit/' . $handoverId); + Flash::success(t('Handover created and assigned'), $editUrl, 'handover_created'); + Router::redirect($editUrl); + return; + } + } else { + // Self mode: continue to protocol step + $nextStep = $protocolStep; + $modeParam = $canManage ? '&mode=' . $mode : ''; + Router::redirect(lurl('helpdesk/handovers/create') . '?step=' . $nextStep . $modeParam . ($returnTarget ? '&return=' . rawurlencode($returnTarget) : '')); + return; + } } } @@ -114,14 +204,13 @@ if ($step === 1) { $validationSummaryErrors = $errorBag->toArray(); } -// ── Step 2: Fill protocol form ─────────────────────────────────────── +// ── Protocol step: fill protocol form ──────────────────────────────── -if ($step === 2) { +if ($step === $protocolStep) { $wizardData = $sessionStore->get($sessionKey); if (!is_array($wizardData) || empty($wizardData['debitor_no']) || empty($wizardData['product_code'])) { Flash::error(t('Please complete step 1 first'), $createTarget, 'wizard_step_missing'); Router::redirect($createTarget); - return; } @@ -129,7 +218,6 @@ if ($step === 2) { if ($product === null) { Flash::error(t('Software product not found'), $createTarget, 'product_not_found'); Router::redirect($createTarget); - return; } @@ -144,13 +232,12 @@ if ($step === 2) { if ($request->isMethod('POST')) { if (!Session::checkCsrfToken()) { - Flash::error(t('Form expired, please try again'), $createTarget . '?step=2', 'csrf_expired'); - Router::redirect($createTarget . '?step=2'); - + $modeParam = $canManage ? '&mode=' . ($wizardData['mode'] ?? 'self') : ''; + Flash::error(t('Form expired, please try again'), $createTarget . '?step=' . $protocolStep . $modeParam, 'csrf_expired'); + Router::redirect($createTarget . '?step=' . $protocolStep . $modeParam); return; } - // Collect field values from POST foreach ($schemaFields as $field) { $key = $field['key'] ?? null; if ($key === null) { @@ -164,17 +251,14 @@ if ($step === 2) { } } - $tenantId = (int) ($appSession['current_tenant']['id'] ?? 0); - $userId = (int) ($appSession['user']['id'] ?? 0); - $result = $handoverService->create( - $tenantId, + $currentTenantId, $wizardData['debitor_no'], $wizardData['debitor_name'], $wizardData['product_code'], $wizardData['domain_no'] ?? '', $wizardData['domain_url'] ?? '', - $userId, + $currentUserId, $fieldValues ); @@ -183,21 +267,11 @@ if ($step === 2) { $validationSummaryErrors = $result['errors'] ?? []; } else { $handoverId = $result['id']; - - // Auto-assign if an assignee was selected (managers only) - $assignedTo = (int) ($wizardData['assigned_to'] ?? 0); - if ($assignedTo > 0 && $canManage) { - $dueDate = trim((string) ($wizardData['due_date'] ?? '')) ?: null; - $handoverService->assign($tenantId, $handoverId, $assignedTo, $userId, $dueDate, HandoverService::PERMISSION_MANAGE); - } - - // Clear wizard session $sessionStore->remove($sessionKey); $editUrl = lurl('helpdesk/handovers/edit/' . $handoverId); Flash::success(t('Handover created'), $editUrl, 'handover_created'); Router::redirect($editUrl); - return; } } diff --git a/modules/helpdesk/pages/helpdesk/handovers/create(default).phtml b/modules/helpdesk/pages/helpdesk/handovers/create(default).phtml index 3feb6bd..3a2fc53 100644 --- a/modules/helpdesk/pages/helpdesk/handovers/create(default).phtml +++ b/modules/helpdesk/pages/helpdesk/handovers/create(default).phtml @@ -10,13 +10,38 @@ $schemaFields = is_array($schemaFields ?? null) ? $schemaFields : []; $fieldValues = is_array($fieldValues ?? null) ? $fieldValues : []; $wizardData = is_array($wizardData ?? null) ? $wizardData : []; $productDisplayName = $productDisplayName ?? ''; - -$steps = [ - ['label' => t('Customer & product'), 'number' => 1], - ['label' => t('Protocol'), 'number' => 2], -]; $canManage = $canManage ?? false; +$mode = $mode ?? ''; $tenantUsers = is_array($tenantUsers ?? null) ? $tenantUsers : []; +$formStep = $canManage ? 2 : 1; +$protocolStep = $canManage ? 3 : 2; + +// Build step indicator +if ($canManage) { + $steps = [ + ['label' => t('Type'), 'number' => 1], + ['label' => t('Customer & product'), 'number' => 2], + ['label' => t('Protocol'), 'number' => 3], + ]; + // For assign mode, step 3 is skipped — show only 2 steps + if ($mode === 'assign') { + $steps = [ + ['label' => t('Type'), 'number' => 1], + ['label' => t('Customer & product'), 'number' => 2], + ]; + } +} else { + $steps = [ + ['label' => t('Customer & product'), 'number' => 1], + ['label' => t('Protocol'), 'number' => 2], + ]; +} + +// Map actual step number to display step number for indicator +$displayStep = $step; +if ($canManage && $mode === 'assign' && $step === 2) { + $displayStep = 2; +} ?>
@@ -29,13 +54,13 @@ $tenantUsers = is_array($tenantUsers ?? null) ? $tenantUsers : []; @@ -44,12 +69,51 @@ $tenantUsers = is_array($tenantUsers ?? null) ? $tenantUsers : []; - - + +
-
-

-

+ +

+ +
+ + + +

+ +
+ + + +
+ + +
+
+
+ + + +
+
+ +

+ +

+

+
@@ -69,6 +133,9 @@ $tenantUsers = is_array($tenantUsers ?? null) ? $tenantUsers : [];
+ +

+
+ +

+
@@ -109,50 +179,66 @@ $tenantUsers = is_array($tenantUsers ?? null) ? $tenantUsers : []; + +

+
- +
- - + + +

+ + + +

+ +
-
+
- +
- - + + + + + + + + + +
- - + +
-
+ +

@@ -166,7 +252,7 @@ $tenantUsers = is_array($tenantUsers ?? null) ? $tenantUsers : [];

- +
diff --git a/modules/helpdesk/pages/helpdesk/handovers/index(default).phtml b/modules/helpdesk/pages/helpdesk/handovers/index(default).phtml index fecc259..1fb6c25 100644 --- a/modules/helpdesk/pages/helpdesk/handovers/index(default).phtml +++ b/modules/helpdesk/pages/helpdesk/handovers/index(default).phtml @@ -57,7 +57,7 @@ require templatePath('partials/app-list-filters.phtml');