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>
When a ticket was reassigned (multiple support codes), all codes were
mapped to the current Support_User_Name — replacing the previous
agent's name with the new one on older entries.
Now: if multiple support codes exist, only the code from the most
recent entry is mapped to the current name. Older codes remain as
abbreviations, preserving the actual history of who worked on what.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the SOAP message map is applied to OData entries, the message text
is already embedded in the OData entries. The separate SOAP message
entries then cause duplicates with different actor/timestamp metadata.
Now: when soapMessageMap was used, filter out SOAP entries with
type_variant 'message' since they are already represented in OData.
Non-message SOAP entries (status, activity) are kept.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SOAP entries often have an empty actor while OData entries have a code
like 'NKS'. After name resolution, one becomes 'Nikita Soldatov' and
the other stays empty — producing different signatures and causing
duplicates. The actor is not a reliable dedup field since the same
event can have different actor representations across sources.
Dedup now uses: ticket_no + timestamp_iso + type + message_hash.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous logic only resolved support user codes to full names when
exactly one unique support code existed per ticket. Tickets with multiple
support codes (e.g. after reassignment) left all codes unresolved,
showing abbreviations like 'NKS' or 'FA' instead of full names.
Now: every support-role actor code in a ticket is mapped to that ticket's
Support_User_Name. For the debitor feed, codes are mapped on first
encounter to avoid conflicts from reassigned tickets.
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>
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>