Files
breadcrumb-the-shire/modules/helpdesk/CLAUDE.md
2026-05-26 11:04:57 +02:00

180 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md — Helpdesk Module
Self-contained MintyPHP module. Namespace: `MintyPHP\Module\Helpdesk\*`. All changes stay inside `modules/helpdesk/` — never touch core templates or global layout.
After any manifest change (new route, permission, slot): `docker compose exec php php bin/console module:sync`
---
## Architecture
```
lib/Module/Helpdesk/
HelpdeskAuthorizationPolicy.php — all ability/permission constants + authorize()
HelpdeskContainerRegistrar.php — all DI bindings (add new services here)
Handler/ — scheduled job handlers
Providers/HelpdeskLayoutProvider.php — resolves can_* flags for sidebar nav
Repository/ — SQL only, no HTTP
Service/ — business logic, no HTML
pages/helpdesk/ — actions (*.php) + views (*.phtml)
templates/
aside-helpdesk-panel.phtml — sidebar navigation
helpdesk-ticket-detail.phtml — shared ticket detail body
i18n/default_de.json + default_en.json — 551 keys each, always add both
migrations/ — 011 SQL files applied via module:migrate
tests/Module/Helpdesk/Service/ — 20 test files, happy path + edge case required
web/css/helpdesk.css
web/js/ — 16 JS files, components + page scripts
```
---
## Page File Naming
| URL | Action file | View file |
|-----|-------------|-----------|
| `helpdesk/team` | `pages/helpdesk/team/index().php` | `team/index(default).phtml` |
| `helpdesk/handovers/edit/{id}` | `pages/helpdesk/handovers/edit($id).php` | `handovers/edit(default).phtml` |
| `helpdesk/dashboard` | `pages/helpdesk/dashboard/index().php` | `dashboard/index(default).phtml` |
| data endpoint | `pages/helpdesk/foo-data().php` | — |
| drawer fragment | `pages/helpdesk/foo-fragment($id).php` | `foo-fragment(none).phtml` |
**View structure pattern** (always):
```php
<div class="app-details-container">
<section>
<?php
$titlebar = ['title' => t('Page title')];
require templatePath('partials/app-details-titlebar.phtml');
?>
<!-- content -->
</section>
</div>
```
---
## Permissions (10 total)
All constants in `HelpdeskAuthorizationPolicy`:
| Constant | Permission key |
|----------|---------------|
| `ABILITY_ACCESS` | `helpdesk.access` — base access, customer search + detail views |
| `ABILITY_SETTINGS_MANAGE` | `helpdesk.settings.manage` |
| `ABILITY_TEAM_WORKLOAD` | `helpdesk.team-workload.view` |
| `ABILITY_RISK_RADAR` | `helpdesk.risk-radar.view` |
| `ABILITY_SOFTWARE_PRODUCTS_MANAGE` | `helpdesk.software-products.manage` |
| `ABILITY_HANDOVERS_VIEW` | `helpdesk.handovers.view` |
| `ABILITY_HANDOVERS_CREATE` | `helpdesk.handovers.create` |
| `ABILITY_HANDOVERS_MANAGE` | `helpdesk.handovers.manage` |
| `ABILITY_UPDATES_VIEW` | `helpdesk.updates.view` |
| `ABILITY_UPDATES_MANAGE` | `helpdesk.updates.manage` |
New pages reuse existing permissions — no new permission keys without product decision.
**Action file boilerplate:**
```php
Guard::requireLogin();
Guard::requireAbilityOrForbidden(HelpdeskAuthorizationPolicy::ABILITY_ACCESS);
$session = app(SessionStoreInterface::class)->all();
$tenantId = (int) ($session['current_tenant']['id'] ?? 0);
```
---
## Services & Repositories
**Gateways (external BC API):**
- `BcODataGateway` — OData V4 queries (customers, domains, tickets, contacts)
- `BcSoapGateway` — SOAP (ticket communication feed, file downloads)
**Core services:**
- `EffectiveHelpdeskSettingsService` — resolves BC config per tenant (global + override)
- `HelpdeskOAuthTokenService` — OAuth2 token acquisition + cache
- `DebitorSearchService` — debtor search by name/number
- `DebitorDetailService` — debtor master data + contacts + tickets
- `DomainDetailService` — domain/contract data + handover/update enrichment
- `DomainListService` — domain list with security level enrichment
- `HandoverService` — handover protocol CRUD + status transitions
- `HandoverRevisionService` — revision snapshots for audit trail
- `UpdateService` — software update tracking + assignment
- `SoftwareProductService` — product catalog + handover schema
- `SoftwareProductSyncService` — BC sync (scheduled daily 02:00 CET)
- `RiskRadarService` — risk scoring engine (5 dimensions, 0100 score)
- `DomainSecurityLevelService` — security level get/set (niedrig/normal/hoch/kritisch)
- `SystemRecommendationEngine` — rule-based recommendation engine (no constructor)
**Repositories:**
- `HandoverRepository` — insert, findById, listPaged, updateFieldValues, updateStatus, deleteByIds, findByDomainNo, transactions
- `UpdateRepository` — insert, findByTicketNo, findByDomainNo, findAllByTenant, updateAssignment
- `SoftwareProductRepository` — upsertByCode, listPaged, updateHandoverSchema, softDeleteNotInCodes
- `HandoverRevisionRepository` — insert, getLatestRevisionNumber, listByHandover
- `DomainSecurityLevelRepository` — findByTenantAndDomainNo, listLevelsByDomainNos, upsert
- `HelpdeskTenantSettingsRepository` — findByTenantId, upsert, deleteByTenantId
- `HelpdeskTokenRepository` — findValidToken, storeToken, deleteByTenantId (encrypted)
New service → register in `HelpdeskContainerRegistrar::register()` + add `@api` annotation if called from pages.
---
## Sidebar Navigation
**`HelpdeskLayoutProvider`** resolves these flags → passed as `$layoutNav['helpdesk.nav']`:
`can_view_dashboard`, `can_manage_settings`, `can_view_team`, `can_view_risk_radar`,
`can_manage_software_products`, `can_view_handovers`, `can_create_handovers`,
`can_manage_handovers`, `can_view_updates`
**`aside-helpdesk-panel.phtml`** — 5 collapsible groups:
1. **Overview** (`bi-speedometer2`) — Dashboard
2. **Lookup** (`bi-search`) — Customers, Domains
3. **Monitoring** (`bi-bar-chart-line`) — Team workload, Risk radar
4. **Operations** (`bi-clipboard-check`) — Handovers, Updates
5. **Administration** (`bi-sliders`) — Software products, Settings
Adding a nav item = 3 steps: (1) add `can_*` flag to `HelpdeskLayoutProvider`, (2) add `$dashboardActive = navActive(...)` + item to group in `aside-helpdesk-panel.phtml`, (3) add condition to `$customersActive` override if needed.
---
## DB Schema (relevant tables)
| Table | Key columns |
|-------|-------------|
| `helpdesk_handovers` | id, tenant_id, status (draft/in_progress/completed/archived), debitor_no, domain_no |
| `helpdesk_handover_revisions` | handover_id, revision_number, snapshot_json |
| `helpdesk_updates` | id, tenant_id, status (open/assigned/done/resolved/closed), ticket_no, domain_no |
| `helpdesk_software_products` | code, name, handover_schema_json |
| `helpdesk_domain_security_levels` | tenant_id, domain_no, level, note |
| `helpdesk_tenant_settings` | tenant_id, encrypted BC connection overrides |
| `helpdesk_oauth_token_cache` | tenant_id, token (encrypted), expires_at |
Tenant scope enforced on every query — always pass `$tenantId` to repository methods.
---
## Tests
Location: `tests/Module/Helpdesk/Service/`
Pattern: `->method('foo')->willReturn([...])` — no `->with()` (PHPUnit 12 incompatible with PHPStan).
Every new/changed Service or Gateway needs happy path + at least one edge case test.
Run: `docker compose exec php vendor/bin/phpunit modules/helpdesk/tests/`
---
## JS Components
Registered via `data-app-component="<name>"` on the container div:
- `helpdesk-detail` — customer search detail
- `helpdesk-domain-detail` — domain detail
- `helpdesk-ticket` — ticket view
- `helpdesk-team` — team workload
- `helpdesk-risk-radar` — risk radar
- `helpdesk-settings` — settings config
- `helpdesk-communication` — ticket communication feed
- `helpdesk-handover-domain-select` — domain picker in handover wizard
- `helpdesk-handover-schema-editor` — handover schema JSON editor
CSS class prefix: `helpdesk-` for module-specific styles in `web/css/helpdesk.css`.