1
0
Files
breadcrumb-the-shire/modules/helpdesk/lib/Module/Helpdesk/Service/DebitorCacheControl.php
fs 42efdb8102 feat(helpdesk): add debitor meetings tab with upcoming/past meeting display
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>
2026-04-13 14:13:29 +02:00

138 lines
4.7 KiB
PHP

<?php
namespace MintyPHP\Module\Helpdesk\Service;
use MintyPHP\Http\SessionStoreInterface;
final class DebitorCacheControl
{
public const TTL_STANDARD_SECONDS = 300;
public const TTL_ESCALATION_DEFINITIONS_SECONDS = 1800;
private const REFRESH_TRUE_VALUES = ['1', 'true', 'yes'];
private function __construct()
{
}
/**
* @param mixed $value
*/
public static function parseRefreshFlag(mixed $value): bool
{
if (is_bool($value)) {
return $value;
}
$normalized = strtolower(trim((string) ($value ?? '')));
if ($normalized === '') {
return false;
}
return in_array($normalized, self::REFRESH_TRUE_VALUES, true);
}
/**
* @param array<string, mixed> $session
*/
public static function resolveTenantScope(array $session): string
{
$tenantId = (int) (($session['current_tenant']['id'] ?? 0));
return $tenantId > 0 ? (string) $tenantId : 'global';
}
public static function ticketsKey(string $tenantScope, string $customerNo): string
{
return 'module.helpdesk.debitor.v2.tickets.' . $tenantScope . '.' . trim($customerNo);
}
public static function contactsKey(string $tenantScope, string $customerNo): string
{
return 'module.helpdesk.debitor.v2.contacts.' . $tenantScope . '.' . trim($customerNo);
}
public static function communicationKey(string $tenantScope, string $customerNo): string
{
return 'module.helpdesk.debitor.v2.communication.' . $tenantScope . '.' . trim($customerNo);
}
public static function escalationKey(string $tenantScope, string $customerNo): string
{
return 'module.helpdesk.debitor.v2.escalation.' . $tenantScope . '.' . trim($customerNo);
}
public static function contractsKey(string $tenantScope, string $customerNo): string
{
return 'module.helpdesk.debitor.v2.contracts.' . $tenantScope . '.' . trim($customerNo);
}
public static function contractLinesKey(string $tenantScope, string $customerNo): string
{
return 'module.helpdesk.debitor.v2.contract-lines.' . $tenantScope . '.' . trim($customerNo);
}
public static function controllingTicketsKey(string $tenantScope, string $customerNo): string
{
return 'module.helpdesk.debitor.v2.controlling-tickets.' . $tenantScope . '.' . trim($customerNo);
}
public static function meetingsKey(string $tenantScope, string $customerNo): string
{
return 'module.helpdesk.debitor.v2.meetings.' . $tenantScope . '.' . trim($customerNo);
}
public static function escalationDefinitionsKey(string $tenantScope): string
{
return 'module.helpdesk.debitor.v1.escalation-definitions.' . $tenantScope;
}
public static function teamWorkloadKey(string $tenantScope): string
{
return 'module.helpdesk.team.v1.workload.' . $tenantScope;
}
public static function riskRadarKey(string $tenantScope, int $periodDays): string
{
return 'module.helpdesk.risk-radar.v1.' . $tenantScope . '.' . $periodDays;
}
/**
* @return array<int, string>
*/
public static function allDebitorCacheKeys(string $tenantScope, string $customerNo): array
{
return [
self::ticketsKey($tenantScope, $customerNo),
self::contactsKey($tenantScope, $customerNo),
self::communicationKey($tenantScope, $customerNo),
self::escalationKey($tenantScope, $customerNo),
self::contractsKey($tenantScope, $customerNo),
self::contractLinesKey($tenantScope, $customerNo),
self::controllingTicketsKey($tenantScope, $customerNo),
self::meetingsKey($tenantScope, $customerNo),
// Legacy keys kept for hard refresh compatibility
'module.helpdesk.tickets_cache.' . $tenantScope . '.' . trim($customerNo),
'module.helpdesk.contacts_cache.v1.' . $tenantScope . '.' . trim($customerNo),
'module.helpdesk.debitor_comm_cache.v3.' . $tenantScope . '.' . trim($customerNo),
'module.helpdesk.escalation_cache.v1.' . $tenantScope . '.' . trim($customerNo),
'module.helpdesk.contracts_cache.v2.' . $tenantScope . '.' . trim($customerNo),
];
}
public static function invalidateDebitorCaches(
SessionStoreInterface $sessionStore,
string $tenantScope,
string $customerNo,
bool $includeTenantShared = true
): void {
foreach (self::allDebitorCacheKeys($tenantScope, $customerNo) as $key) {
$sessionStore->remove($key);
}
if ($includeTenantShared) {
$sessionStore->remove(self::escalationDefinitionsKey($tenantScope));
}
}
}