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>
103 lines
2.9 KiB
PHP
103 lines
2.9 KiB
PHP
<?php
|
|
|
|
namespace MintyPHP\Module\Helpdesk\Service;
|
|
|
|
/**
|
|
* Service for searching BC debtors via OData.
|
|
*/
|
|
class DebitorSearchService
|
|
{
|
|
public const MIN_QUERY_LENGTH = 2;
|
|
|
|
public function __construct(
|
|
private readonly BcODataGateway $bcODataGateway,
|
|
private readonly EffectiveHelpdeskSettingsService $settingsGateway
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Search debtors by name or number.
|
|
*
|
|
* @return array{status: string, results: array<int, array<string, mixed>>, error?: string}
|
|
*/
|
|
public function search(string $query): array
|
|
{
|
|
$query = trim($query);
|
|
|
|
if ($query === '') {
|
|
return ['status' => 'empty', 'results' => []];
|
|
}
|
|
|
|
if (mb_strlen($query) < self::MIN_QUERY_LENGTH) {
|
|
return ['status' => 'too_short', 'results' => []];
|
|
}
|
|
|
|
if (!$this->settingsGateway->isConfigured()) {
|
|
return ['status' => 'not_configured', 'results' => [], 'error' => 'BC connection not configured'];
|
|
}
|
|
|
|
try {
|
|
$results = $this->bcODataGateway->searchCustomers($query);
|
|
} catch (\Throwable $e) {
|
|
return ['status' => 'error', 'results' => [], 'error' => 'BC connection failed'];
|
|
}
|
|
|
|
if ($results === []) {
|
|
return ['status' => 'no_results', 'results' => []];
|
|
}
|
|
|
|
return ['status' => 'success', 'results' => $results];
|
|
}
|
|
|
|
/**
|
|
* Build grid data for the helpdesk debtor list.
|
|
*
|
|
* @param array<string,mixed> $filters
|
|
* @return array{status: string, rows: array<int, array<string, mixed>>, total: int, error?: string}
|
|
*/
|
|
public function listForGrid(array $filters): array
|
|
{
|
|
if (!$this->settingsGateway->isConfigured()) {
|
|
return [
|
|
'status' => 'not_configured',
|
|
'rows' => [],
|
|
'total' => 0,
|
|
'error' => 'BC connection not configured',
|
|
];
|
|
}
|
|
|
|
$search = trim((string) ($filters['search'] ?? ''));
|
|
$city = trim((string) ($filters['city'] ?? ''));
|
|
$limit = (int) ($filters['limit'] ?? 10);
|
|
$offset = (int) ($filters['offset'] ?? 0);
|
|
$order = (string) ($filters['order'] ?? 'Name');
|
|
$dir = (string) ($filters['dir'] ?? 'asc');
|
|
|
|
if ($limit < 1) {
|
|
$limit = 1;
|
|
} elseif ($limit > 100) {
|
|
$limit = 100;
|
|
}
|
|
if ($offset < 0) {
|
|
$offset = 0;
|
|
}
|
|
|
|
try {
|
|
$result = $this->bcODataGateway->listCustomers($search, $city, $limit, $offset, $order, $dir);
|
|
} catch (\Throwable) {
|
|
return [
|
|
'status' => 'error',
|
|
'rows' => [],
|
|
'total' => 0,
|
|
'error' => 'BC connection failed',
|
|
];
|
|
}
|
|
|
|
return [
|
|
'status' => 'success',
|
|
'rows' => (array) $result['rows'],
|
|
'total' => max(0, (int) $result['total']),
|
|
];
|
|
}
|
|
}
|