155 lines
5.7 KiB
PHP
155 lines
5.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\ChiamataPostIt;
|
|
use App\Models\RubricaUniversale;
|
|
use App\Support\PhoneNumber;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class PanasonicCstaController extends Controller
|
|
{
|
|
public function incoming(Request $request): JsonResponse
|
|
{
|
|
if (! $this->isAuthorized($request)) {
|
|
return response()->json(['ok' => false, 'message' => 'Unauthorized'], 401);
|
|
}
|
|
|
|
$payload = $request->validate([
|
|
'phone' => ['required', 'string', 'max:64'],
|
|
'name' => ['nullable', 'string', 'max:255'],
|
|
'direction' => ['nullable', 'in:in_arrivo,in_uscita,persa'],
|
|
'outcome' => ['nullable', 'string', 'max:255'],
|
|
'event_id' => ['nullable', 'string', 'max:100'],
|
|
'called_extension' => ['nullable', 'string', 'max:30'],
|
|
'note' => ['nullable', 'string'],
|
|
'called_at' => ['nullable', 'date'],
|
|
]);
|
|
|
|
$normalized = PhoneNumber::normalizeForMatch((string) $payload['phone']);
|
|
$rubrica = $this->findRubricaByPhone($normalized);
|
|
|
|
$postIt = null;
|
|
if (Schema::hasTable('chiamate_post_it')) {
|
|
$postIt = ChiamataPostIt::query()->create([
|
|
'stabile_id' => null,
|
|
'rubrica_id' => $rubrica?->id,
|
|
'ticket_id' => null,
|
|
'creato_da_user_id' => null,
|
|
'telefono' => $normalized !== '' ? $normalized : (string) $payload['phone'],
|
|
'nome_chiamante' => $rubrica?->nome_completo ?: ($payload['name'] ?? null),
|
|
'direzione' => $payload['direction'] ?? 'in_arrivo',
|
|
'esito' => $payload['outcome'] ?? null,
|
|
'origine' => 'panasonic_ns1000',
|
|
'origine_id' => $payload['event_id'] ?? null,
|
|
'oggetto' => 'Chiamata ' . (($payload['direction'] ?? 'in_arrivo') === 'in_arrivo' ? 'in arrivo' : 'telefonica'),
|
|
'nota' => $this->buildNote($payload),
|
|
'priorita' => 'Media',
|
|
'stato' => 'post_it',
|
|
'chiamata_il' => $payload['called_at'] ?? now(),
|
|
]);
|
|
}
|
|
|
|
return response()->json([
|
|
'ok' => true,
|
|
'source' => 'panasonic_ns1000',
|
|
'phone_normalized' => $normalized,
|
|
'matched' => (bool) $rubrica,
|
|
'rubrica' => $rubrica ? [
|
|
'id' => $rubrica->id,
|
|
'nome_completo' => $rubrica->nome_completo,
|
|
'categoria' => $rubrica->categoria,
|
|
] : null,
|
|
'post_it_id' => $postIt?->id,
|
|
'called_extension' => $payload['called_extension'] ?? null,
|
|
]);
|
|
}
|
|
|
|
public function lookup(Request $request): JsonResponse
|
|
{
|
|
if (! $this->isAuthorized($request)) {
|
|
return response()->json(['ok' => false, 'message' => 'Unauthorized'], 401);
|
|
}
|
|
|
|
$data = $request->validate([
|
|
'phone' => ['required', 'string', 'max:64'],
|
|
]);
|
|
|
|
$normalized = PhoneNumber::normalizeForMatch((string) $data['phone']);
|
|
$rubrica = $this->findRubricaByPhone($normalized);
|
|
|
|
return response()->json([
|
|
'ok' => true,
|
|
'phone_normalized' => $normalized,
|
|
'matched' => (bool) $rubrica,
|
|
'rubrica' => $rubrica ? [
|
|
'id' => $rubrica->id,
|
|
'nome_completo' => $rubrica->nome_completo,
|
|
'telefono_ufficio' => $rubrica->telefono_ufficio,
|
|
'telefono_cellulare' => $rubrica->telefono_cellulare,
|
|
'telefono_casa' => $rubrica->telefono_casa,
|
|
'categoria' => $rubrica->categoria,
|
|
] : null,
|
|
]);
|
|
}
|
|
|
|
private function isAuthorized(Request $request): bool
|
|
{
|
|
$configured = (string) env('NETGESCON_CTI_SHARED_TOKEN', '');
|
|
if ($configured === '') {
|
|
return false;
|
|
}
|
|
|
|
$token = (string) ($request->header('X-CTI-Token') ?: $request->input('token', ''));
|
|
|
|
return hash_equals($configured, $token);
|
|
}
|
|
|
|
private function findRubricaByPhone(string $phone): ?RubricaUniversale
|
|
{
|
|
$digits = PhoneNumber::normalizeDigits($phone);
|
|
if ($digits === '') {
|
|
return null;
|
|
}
|
|
|
|
$tail = substr($digits, -7);
|
|
if ($tail === false || $tail === '') {
|
|
return null;
|
|
}
|
|
|
|
return RubricaUniversale::query()
|
|
->where(function ($q) use ($tail) {
|
|
$q->orWhere('telefono_cellulare', 'like', '%' . $tail . '%')
|
|
->orWhere('telefono_ufficio', 'like', '%' . $tail . '%')
|
|
->orWhere('telefono_casa', 'like', '%' . $tail . '%')
|
|
->orWhere('telefono_cellulare_nazionale', 'like', '%' . $tail . '%');
|
|
})
|
|
->orderByDesc('updated_at')
|
|
->first();
|
|
}
|
|
|
|
private function buildNote(array $payload): string
|
|
{
|
|
$lines = [
|
|
'Origine: Panasonic NS1000 (CSTA)',
|
|
];
|
|
|
|
if (! empty($payload['called_extension'])) {
|
|
$lines[] = 'Interno chiamato: ' . $payload['called_extension'];
|
|
}
|
|
|
|
if (! empty($payload['event_id'])) {
|
|
$lines[] = 'Event ID: ' . $payload['event_id'];
|
|
}
|
|
|
|
if (! empty($payload['note'])) {
|
|
$lines[] = 'Note PBX: ' . $payload['note'];
|
|
}
|
|
|
|
return implode("\n", $lines);
|
|
}
|
|
}
|