1
0

550 Commits

Author SHA1 Message Date
aminovfariz
0392043ee3 fix(helpdesk): fix user-select empty options — use nested row structure fallback
DB::select with JOIN returns rows as $u['u']['field'] ?? $u['field'].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 12:00:25 +02:00
aminovfariz
e3dfdef76f fix(helpdesk): always load tenant users, not only when schema has user-select
Schema snapshot on existing handovers may predate the field type change,
so the conditional check was false and tenantUsers was empty.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 11:57:02 +02:00
aminovfariz
40b94fa891 fix(helpdesk): user-select as multi-select, store as JSON array
- select multiple, no placeholder option (was causing two empty entries)
- value stored as JSON array string e.g. ["1","3"]
- on render decode JSON back to array for selected check
- both create and edit actions read field as array

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 11:51:50 +02:00
aminovfariz
0fabb0c478 fix(helpdesk): allow user-select in schema field type validation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 11:34:28 +02:00
aminovfariz
2968d5e386 feat(helpdesk): add user-select to schema editor field type dropdown
Adds 'user-select' to FIELD_TYPES so it appears in the schema editor
dropdown as 'Benutzerauswahl' / 'User selection'. Preview renders a
placeholder select. Translations added to both i18n files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 11:04:25 +02:00
aminovfariz
9bc8799b6b feat(helpdesk): add user-select field type to handover protocol schema
New schema field type 'user-select' renders a dropdown of active tenant
users. Action files (create + edit) load tenant users when the schema
contains at least one user-select field and pass them to _form.phtml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:46:15 +02:00
aminovfariz
e569e2d26c fix(helpdesk): fix manual domain value not submitted — use hidden input for domain_no
Select had name="domain_no" but JS was looking for input[name="domain_no"].
Moved name to a hidden input #wizard-domain-no; select syncs into it on
change; manual text input syncs into it on input event.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:22:19 +02:00
aminovfariz
57cb2f1017 ci: trigger GitHub Actions 2026-06-08 10:05:02 +02:00
aminovfariz
0fc2d3f2c3 feat(helpdesk): show manual domain input when customer has no domains
When the domain API returns an empty list for a selected customer, the
domain select is replaced with two text inputs: domain name (required)
and URL (optional). JS syncs the manual values into the existing hidden
domain_no/domain_url fields so the server-side validation and save logic
is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:04:27 +02:00
aminovfariz
2b230e756e fix(deploy): re-resolve php upstream on each request to survive container restarts
Using resolver 127.0.0.11 (Docker internal DNS) with set $php_upstream
forces nginx to re-resolve the php hostname dynamically instead of caching
the IP at startup — eliminates 502 after php container is recreated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:58:28 +02:00
aminovfariz
b049e2490b chore(deploy): add production deploy config (docker-compose + nginx)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:37:37 +02:00
aminovfariz
16fe1b0db3 fix(ci): skip codex skills sync on hosts without Codex installation
QG-009 was failing on GitHub Actions runner because ~/.codex does not
exist on ubuntu-latest and CODEX_HOME is not set. The check is a
local-developer tool only — CI runners do not have Codex installed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:29:00 +02:00
aminovfariz
322c9575f8 fix(css): wrap address-book-index.css in @layer pages block
css-contract-check.sh expects @layer pages { (block syntax),
not @layer pages; (statement syntax) — regex captures up to
the first whitespace or { so the semicolon was included in the
detected layer name.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:23:09 +02:00
aminovfariz
3ff302cc02 fix(css): add missing @layer pages declaration to address-book-index.css
Required by css-contract-check.sh — all files under pages/ must declare
their layer near the top of the file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:15:43 +02:00
aminovfariz
c6a919652f fix(ci): install ripgrep in deploy workflow qa step
Same fix as qa-required.yaml — css-contract-check.sh calls rg on
the host runner, not inside Docker.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:10:48 +02:00
aminovfariz
f4b08e4c73 fix(ci): install ripgrep on runner before qa-required scripts
CSS/docs/JS contract checks call rg directly on the host runner,
not inside Docker, so ripgrep must be present on the ubuntu runner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:06:12 +02:00
aminovfariz
db5c57ea5c fix(phpstan): remove unused Curl import from OidcHttpGateway 2026-06-05 15:01:49 +02:00
aminovfariz
0a56c741e8 fix(phpstan): simplify http_response_header check in OidcHttpGateway 2026-06-05 14:56:37 +02:00
aminovfariz
668a67c094 fix(tests): pass appTitle and appUrl to auth service constructors in tests 2026-06-05 14:51:47 +02:00
aminovfariz
acf3229f3f fix(tests): replace appLogoUrlAbsolute with resolveAppUrl in auth services 2026-06-05 14:43:52 +02:00
aminovfariz
5367449d80 fix(ci): run db:migrate before tests so settings table exists 2026-06-05 14:38:52 +02:00
aminovfariz
68407b944e fix(tests): remove appTitle/appUrl from AuthServicesFactory constructor calls 2026-06-05 14:27:28 +02:00
aminovfariz
c12d155e23 fix(tests): inject appTitle/appUrl into auth services to avoid DB calls in unit tests 2026-06-05 14:21:04 +02:00
aminovfariz
3f08f6189e fix(helpdesk): inject appTitle/appUrl into HandoverNotificationService to avoid DB calls in tests 2026-06-05 14:10:13 +02:00
aminovfariz
b8fc55bcc2 ci: start php container for QA gates 2026-06-05 14:02:57 +02:00
aminovfariz
6cfc8e7533 ci: use PHP 8.5 2026-06-05 14:00:55 +02:00
aminovfariz
2e26cce91f ci: run composer and QA gates directly on runner without Docker 2026-06-05 13:48:32 +02:00
aminovfariz
8e8ca4d5e7 ci: add GitHub Actions workflows 2026-06-05 13:41:19 +02:00
aminovfariz
c8cf2892c9 ci: trigger pipeline after runner fix with node on host
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 12:09:46 +02:00
aminovfariz
1ae3d5d984 ci: trigger pipeline after runner workspace mount fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 12:01:13 +02:00
aminovfariz
2e316b2901 ci: trigger pipeline after switching runner to host mode
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:59:33 +02:00
aminovfariz
925f8ec87e fix(ci): debug mounts via hostname inspect
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:54:12 +02:00
aminovfariz
0486ebf2a2 fix(ci): debug runner container mounts to find host workspace path
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:52:22 +02:00
aminovfariz
1d1f8479b6 fix(ci): set COMPOSE_PROJECT_NAME=breadcrumb-ci at job level for stable container names
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:50:01 +02:00
aminovfariz
70d431cff5 fix(ci): install composer directly in runner container, not via docker run
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:48:26 +02:00
aminovfariz
07cd2dd756 fix(ci): add path debug before composer install
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:46:58 +02:00
aminovfariz
9668a23797 fix(ci): use GITHUB_WORKSPACE instead of pwd for composer docker run volume
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:46:19 +02:00
aminovfariz
17ae333a39 fix(ci): install composer deps via docker run before compose up, force-recreate containers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:45:31 +02:00
aminovfariz
5df8abceaf fix(ci): force recreate containers with docker compose down before up
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:44:08 +02:00
aminovfariz
b0355791bb fix(ci): add container state diagnostics before composer install
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:43:16 +02:00
aminovfariz
a2ea9f385d fix(ci): debug - ls /var/www to find why composer.json not found
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:42:23 +02:00
aminovfariz
03cdfa7702 fix(ci): wait for php container and use explicit workdir for composer install
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:41:51 +02:00
aminovfariz
3dca38d1c2 fix(ci): run composer install inside php container before QA gates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:40:28 +02:00
aminovfariz
5e8273b952 fix(ci): start only php+db+memcached in CI, skip nginx (file mount fails in runner)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:39:45 +02:00
aminovfariz
d47e45e9f8 fix(ci): create .env from .env.example before docker compose up in CI
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:32:59 +02:00
aminovfariz
0e70e50abf feat(ci): add Gitea Actions deploy pipeline and fix prod image module assets
- Add .gitea/workflows/deploy.yaml: QA → build prod image → SCP to server → docker load + compose up + module:sync
- Fix Dockerfile prod stage: copy module web assets directly from modules/*/web/ instead of resolving symlinks (symlinks are excluded via .dockerignore and break on Windows/CI)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:22:47 +02:00
aminovfariz
9caa771a73 feat(helpdesk): add delete button on edit page, fix flash notifications
- Edit page: managers see 'Delete handover' button in aside with confirm dialog
- Delete handler: POST action=delete → deleteByIds → redirect to list
- Flash scope set to null (global) so toast shows reliably after redirect
  regardless of locale prefix or query string in URL
- i18n: added Delete handover / Delete this handover? / Handover deleted (de+en)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 15:51:36 +02:00
aminovfariz
1caa198286 feat(helpdesk): rework handover tabs and assign flow
Tabs: replace open/closed with active (draft+in_progress+under_review)
and done (completed+archived) — records now appear in the correct tab

Create wizard assign mode: redirect to list with flash message after
assigning instead of opening edit page

i18n: add In progress / Done tab labels and wizard strings (de + en)

Nikita Soldatov note: user does not exist in DB — needs to be created
via admin user management

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 15:23:31 +02:00
aminovfariz
47a26d0ca6 test(helpdesk): add tests for assign, submitForReview, resendNotification and HandoverNotificationService
HandoverServiceTest: 30 new cases covering:
- assign(): happy path, draft→in_progress transition, permission check,
  zero assignedTo, not found, email sent, due date passed to repo
- submitForReview(): assignee and manager paths, non-assignee denied,
  wrong status (under_review/completed), revision created, email sent
- resendNotification(): happy path, permission denied, no assignee
- statusLabel/Variant for under_review

HandoverNotificationServiceTest: 9 new cases covering:
- notifyAssigned: sends correct template+vars, skips on empty/null email,
  fallback dash for empty debitor and due_date
- notifyReviewRequested: sends to manager, skips on no email,
  fallback dash for empty assignee name

48 tests total, all passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 14:59:10 +02:00
aminovfariz
88bd7caae5 feat(helpdesk): rework handover create wizard with mode selection
- Managers now see step 1: choose 'Create myself' or 'Assign to employee'
- Assign mode: select customer+product+employee → creates record immediately,
  sends invitation email, skips protocol step
- Self mode: existing 2-step flow unchanged
- Fix open/closed tab: pass view param in dataUrl so grid filters correctly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 14:50:30 +02:00