Add a new "Domains" page to the helpdesk module that fetches domain data
from the FS_Contract_Domains OData endpoint and enriches each domain with
its contract type (PI_Header_Type) by joining with FS_Contract_Lines_Test
where Type = 'Domain'.
New files:
- domains/index().php, index(default).phtml, filter-schema.php — list page
- domains-data().php — data endpoint with PHP-side filtering/sorting
- helpdesk-domains-index.js — Grid.js via initStandardListPage()
Gateway additions:
- listDomains() — fetch all contract domains
- listDomainContractLines() — fetch domain-type contract lines for type lookup
Sidebar restructured into three collapsible groups (Lookup, Monitoring,
Administration) with per-group icons and color coding, matching the core
admin panel pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move HelpdeskTenantSettingsRepository and HelpdeskTokenRepository from
Service/ to Repository/ directory (GR-SEC-003: SQL only in repositories)
- Make AccessControl constructor require IntendedUrlService explicitly
instead of falling back to `new IntendedUrlService()` (GR-TEST-002:
no service instantiation outside factories)
- Update all imports and tests accordingly
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a meetings section to the debitor detail page, fetching meeting data from BC OData API with cache control support. Includes timeline UI for upcoming and past meetings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restructure helpdesk tenant settings into per-connection config with
improved token handling. Update risk radar data endpoint and UI.
Clean up ImageUploadTrait and update architecture contract tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce per-tenant override for helpdesk BC connection config.
New table helpdesk_tenant_settings stores tenant-specific credentials
with encrypted secrets (AES-256-GCM). EffectiveHelpdeskSettingsService
resolves global vs tenant config per request. Settings UI extended with
tenant override tab, toggle, and dual editing mode.
All runtime consumers (OData, SOAP, OAuth) read through the new
resolver. Token cache flushed on any config change. Default behavior
unchanged — tenants use global config until override explicitly enabled.
Also includes risk radar UI refinements: Stripe-style card redesign
with accent borders and score pills, removal of redundant KPI tiles
and search, and filtering of zero-score entries.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cards now show plain-language reasons instead of abstract progress bars:
'8 open, 3 critical', '↑4 more than resolved', '2 SLA breaches',
'Oldest ticket 12d'. Instantly understandable without knowing the
scoring formula. Driver bars remain in the detail dialog for the
full dimension breakdown.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Search input now comes first (left), period segment control after.
Both in a horizontal flex row on the same line.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New portfolio view scoring customers 0-100 across five dimensions:
- Open pressure (30%): open + critical ticket count
- Trend (25%): net ticket flow (created - closed) in period
- SLA overdue (20%): tickets exceeding escalation targets
- Resolution time (15%): median hours to close (null = neutral)
- Inactivity (10%): age of oldest open ticket
Card grid with score badges (color-coded high/medium/low), metric
pills, driver bars. Click opens detail dialog with all dimensions
and open ticket list. Clientside search filter.
PBI_LV_Tickets with client-driven paging ($skip/$top, hardcap 5000).
Escalation definitions cached separately (30min TTL). Truncated
banner when data is capped.
New: RiskRadarService, getTicketsForRiskRadar(), 13 PHPUnit tests,
permission helpdesk.risk-radar.view, 2 routes, i18n de+en.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Proxy endpoint supports ?inline=1 parameter that serves images with
correct Content-Type and Content-Disposition: inline. Uses fpassthru
via php://memory stream to bypass MintyPHP Analyzer restrictions.
Frontend always attempts image preview via <img> tag. Non-image files
gracefully hide the preview via onerror handler. Download link shown
for all file types regardless.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
OData TicketLog doesn't expose the original filename (DataText field).
When the derived filename has no extension, detect the file type from
magic bytes (PNG, JPEG, GIF, PDF, ZIP) and append the correct extension.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BC's GetTicketFile requires a valid contactNo for authorization.
The endpoint now accepts ticketNo, loads the ticket via OData to get
Current_Contact_Name, looks up the contact's No, and passes it to
the SOAP call. Frontend includes ticketNo in the file download URL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use Router::download() instead of die() to avoid Analyzer rejection
- Add 5 PHPUnit tests for BcSoapGateway::getTicketFile() (F-001)
- Add test for file metadata on communication entries (F-002)
- Add rel=noopener noreferrer on target=_blank links (F-003)
- Add aria-hidden on download icon, aria-label on image link (F-003)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MintyPHP Analyzer rejects echo in action files. Use die() which is
the same pattern as Router::download() internally.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New SOAP method getTicketFile() on BcSoapGateway calls BC's
GetTicketFile to retrieve file attachments as Base64, decodes in
memory and returns binary data without writing to disk.
New proxy endpoint helpdesk/ticket-file-data streams files directly
to the browser with correct MIME type. Images served inline, other
files as download attachment.
TicketCommunicationService now attaches file_entry_no and file_name
to file-type events. Frontend renders download links with bi-download
icon and inline image previews for jpg/png/gif attachments.
Works in both ticket detail and debitor detail communication feeds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds 'Refresh data' button that re-fetches the communication feed
with ?refresh=1 to bypass the session cache. Shows loading skeleton
during reload.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the heading and the CSS override — communication feed starts
directly without a title in the ticket detail view.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the Status and Age KPI metric tiles from the ticket aside.
Merge all information into a single definition list: Status, Description,
Company, Contact, Category, Support, Created, Last activity, Age.
Consistent with the label/value pattern used across all detail views.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Contracts & products KPI tiles (active contracts, monthly volume,
support hours, next invoicing) distract from the ticket-focused support
view. Contract data remains available in the dedicated Sales tab.
Removes: section HTML, skeleton placeholder, JS render function + call.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change default period from 90 to 30 days for a more current snapshot.
Add legend footnote: '↑↓ Trend basiert auf den letzten 30 Tagen'
so the user knows what the arrows refer to.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hover over ↑/↓ shows a data-tooltip explaining the delta in plain
language: 'More tickets received than resolved — backlog is growing.'
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Revert queue detection, wait time summary, and visual separation.
All members are treated equally again — queue appears as a normal
agent entry sorted by the existing criteria.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Queue detection: any member with 'warteschlange' in support_user name
(or empty) is treated as queue, not as a regular agent.
Current tab: queue cards shown at top with a wait time summary
(Ø/Min/Max from open ticket ages). Agents listed below.
Historical tab: queue cards shown before agents, same performance
widget pattern.
No backend changes — purely client-side separation using existing data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Skeleton loading now mirrors the actual agent card layout: bordered card
with header (avatar circle + name bar + badge) and three table-like rows.
Removes aria-busy toggle from JS. Three skeleton cards shown during load.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each agent gets a card with three insight columns:
- Resolution time: Ø / Min / Max (formatted as hours or days)
- Top 3 customers by resolved ticket count (ranked list)
- Top 3 categories by resolved ticket count (ranked list)
Backend collects resolved ticket details per agent: customer names,
categories, and resolution hours. Aggregates top-3 and min/max/avg.
Replaces the old compact single-row layout with rich widget cards
matching the Current tab pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PBI_LV_Tickets exposes Description and Cust_Name (not Company_Contact_Name
which is FP-only). Add both to select. Table now shows 5 columns:
Ticket (link) | Customer name (link) | Description (ellipsis) |
Category | Last activity.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Description is not available on PBI_LV_Tickets. Show Category_1_Code
as its own 'Category' column instead of misusing it as description.
Remove unused ticket-desc CSS class.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Switch gateway from PBI_LV_Tickets to PBI_FP_Tickets to get
Description and Company_Contact_Name fields
- Ticket number links to ticket detail page
- Customer column shows Company_Contact_Name with link to debitor detail
- Description column with text-overflow ellipsis
- Last activity column shows formatted date (was: age in hours)
- Backend provides last_activity ISO string and customer_name per ticket
- Table headers use i18n labels via data attributes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Count badge in section title is always neutral (no warning color)
- Critical highlighting only on ticket number, not entire row
- Ticket tables have border + border-radius + subtle header background
matching the existing table widget pattern
- Legend at bottom explains the warning color when critical tickets exist
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace KPI tiles + table with visual agent cards showing workload at a
glance. Each card has the agent name, ticket count badge (warning-colored
when critical), a proportional load bar, and the actual open tickets
listed underneath (number, description, age). Critical tickets are
highlighted with warning color. Queue (unassigned) shown as dashed card
at top. Performance tab uses compact cards with success-colored bars.
Backend now returns open_ticket_details per member (sorted: critical
first, then by age descending).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Filter out agents with 0 open tickets from Current tab and 0 resolved
from Performance tab to reduce noise. Add margin between period selector
and KPI card in the Performance panel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Current tab: snapshot KPIs (open, unassigned, avg age) and per-agent
table with open/critical/age columns. No period filter needed.
Performance tab: period-filtered KPI (resolved) with segment control
(30/90/180/365d) and per-agent table sorted by resolved count.
Separates the two core questions: "Who needs help now?" vs.
"How did the team perform over time?"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All dashboard content (period selector, states, KPIs, table) now sits
inside one wrapper div as a direct child of section, so Core's
padding-inline rule applies consistently.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace custom button-based period selector with the existing
helpdesk-segment-control radio+label pattern used in the controlling
dashboard. Removes duplicate CSS and ensures visual consistency.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New standalone page (helpdesk/team) showing support agent workload
aggregated from BC tickets. KPI bar (open, unassigned, avg age, resolved),
per-agent table sorted by open tickets, period selector (30/90/180/365d).
Global OData query via getTicketsForTeam() without customer filter.
New permission helpdesk.team-workload.view with admin role assignment.
Includes 6 PHPUnit tests for buildTeamWorkloadDashboard().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace border-bottom on rule items and border-top on advanced disclosure
with native <hr> elements that inherit Core's muted-border styling.
Module CSS now only handles layout, not border presentation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merge 'System recommendations' (5 rules × 3-4 fields) and 'Controlling'
(4 rules × 2 fields) into a single 'Automation' tab with two sections:
Recommendations and Risk monitoring. Each rule now shows only a toggle and
help text; priority fields removed (hardcoded in action). Advanced disclosure
for recommendation thresholds. Fix nav highlighting bug where 'Kunden' was
also highlighted when Settings was active.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move breadcrumb rendering from individual page templates into the core
topbar. Each page now sets $breadcrumbs in its action .php file; the
topbar renders it automatically via the shared partial.
- Remove global back/forward buttons and app-nav-history.js component
- Remove Alt+Arrow keyboard shortcuts for history navigation
- Render breadcrumb in topbar-left section (replaces button area)
- Clean up breadcrumb CSS: context-neutral base (flex, no margin)
- Recalculate sticky titlebar offset in details container
- Migrate all 41 pages (core + helpdesk, audit, addressbook, api-docs)
- Add missing breadcrumbs to addressbook detail view
- Update architecture contract tests (nav-history references removed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 3 new ticket list filters: Support User (dynamic select), Contact (dynamic
select), and Period (30/90/180/365 days). Extend categories endpoint to also
return support_users and contacts arrays from the same cached ticket data.
Add server-side filtering for all three in the data endpoint.
Resolve support user abbreviation codes to full names in the communication chat
widget. For single-ticket view, infer code-to-name from Support_User_Name when
only one support code appears. For debitor view, build map from already-fetched
entries across tickets with no additional API calls.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Swap layout: communication feed becomes the primary main content area (full width),
ticket metadata moves to aside panel with 2 stacked KPI tiles (Status, Age) and
a Stripe-style key-value definition list (Description, Company link, Contact,
Category, Support, Debtor No.). Remove activity timeline entirely — communication
feed already includes activity fallback when SOAP is unavailable. Add skeleton
bubble loading for async communication. Simplify JS from 211 to 89 lines. Remove
unused ticketLogUrl data attribute and i18n keys.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restructure Support dashboard into 2 KPI groups (Tickets + Contracts) with
section dividers, merge escalations and recommendations into "Attention needed".
Redesign Sales dashboard with clickable contract timeline and dialog.
Add CSS shimmer skeleton loading for all dashboard tabs and aside.
Unify vertical rhythm via * + * sibling combinator on tab content containers.
Remove ~265 lines of dead CSS (contract cards, escalation styles) and unused JS
functions. Refactor hydrateTicketCategoryFilter into generic hydrateSelectFilter.
Fix role="button" CSS bleed from shell and remove extra future year from timeline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add support/sales/controlling dashboards with KPIs, trend charts and
risk indicators. Add debitor communication timeline, contact filters,
system recommendations engine, and configurable controlling risk rules.
Rename search→index to fix query-string preservation on back navigation.
Remove fake escalation rate metric, add KPI info tooltips, and switch
trend chart colors to red (created) / green (closed) for clarity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>