From 5085f22a1da7dbb48e999103b2850f695cd28330 Mon Sep 17 00:00:00 2001 From: amirghasempoor Date: Sun, 3 Aug 2025 08:54:19 +0330 Subject: [PATCH] create operator dialogue cartable --- .../OperatorDialogues/OperatorController.php | 43 +++++ .../PeopleMessages/SupervisorController.php | 37 +---- .../ProvinceDashboard/ReportController.php | 36 ++++ ...ialogueRating.php => OperatorDialogue.php} | 6 +- .../OperatorDialogues/DataTableService.php | 29 ++++ .../Dashboard/Province/ReportService.php | 157 ++++++++++++++++++ ...actory.php => OperatorDialogueFactory.php} | 4 +- ...10555_create_operator_dialogues_table.php} | 6 +- ...gSeeder.php => OperatorDialogueSeeder.php} | 2 +- 9 files changed, 280 insertions(+), 40 deletions(-) create mode 100644 app/Http/Controllers/ProvinceDashboard/OperatorDialogues/OperatorController.php create mode 100644 app/Http/Controllers/ProvinceDashboard/ReportController.php rename app/Models/{OperatorDialogueRating.php => OperatorDialogue.php} (53%) create mode 100644 app/Services/Dashboard/Province/OperatorDialogues/DataTableService.php create mode 100644 app/Services/Dashboard/Province/ReportService.php rename database/factories/{OperatorDialogueRatingFactory.php => OperatorDialogueFactory.php} (81%) rename database/migrations/{2025_07_29_072224_create_operator_dialogue_ratings_table.php => 2025_08_02_110555_create_operator_dialogues_table.php} (76%) rename database/seeders/{OperatorDialogueRatingSeeder.php => OperatorDialogueSeeder.php} (82%) diff --git a/app/Http/Controllers/ProvinceDashboard/OperatorDialogues/OperatorController.php b/app/Http/Controllers/ProvinceDashboard/OperatorDialogues/OperatorController.php new file mode 100644 index 0000000..614733a --- /dev/null +++ b/app/Http/Controllers/ProvinceDashboard/OperatorDialogues/OperatorController.php @@ -0,0 +1,43 @@ +json($dataTableService->index($request)); + } + + /** + * Display the specified resource. + */ + public function show(string $id) + { + // + } + + /** + * Update the specified resource in storage. + */ + public function download(Request $request, string $id) + { + // + } + + /** + * Remove the specified resource from storage. + */ + public function excel(string $id) + { + // + } +} diff --git a/app/Http/Controllers/ProvinceDashboard/PeopleMessages/SupervisorController.php b/app/Http/Controllers/ProvinceDashboard/PeopleMessages/SupervisorController.php index 49d7365..6028dcf 100644 --- a/app/Http/Controllers/ProvinceDashboard/PeopleMessages/SupervisorController.php +++ b/app/Http/Controllers/ProvinceDashboard/PeopleMessages/SupervisorController.php @@ -3,6 +3,8 @@ namespace App\Http\Controllers\ProvinceDashboard\PeopleMessages; use App\Http\Controllers\Controller; +use App\Services\Dashboard\Province\PeopleMessages\DataTableService; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; class SupervisorController extends Controller @@ -10,17 +12,14 @@ class SupervisorController extends Controller /** * Display a listing of the resource. */ - public function index() + public function index(Request $request, DataTableService $dataTableService): JsonResponse { - // + return response()->json($dataTableService->index($request)); } - /** - * Store a newly created resource in storage. - */ - public function store(Request $request) + public function excel() { - // + } /** @@ -30,28 +29,4 @@ class SupervisorController extends Controller { // } - - /** - * Show the form for editing the specified resource. - */ - public function edit(string $id) - { - // - } - - /** - * Update the specified resource in storage. - */ - public function update(Request $request, string $id) - { - // - } - - /** - * Remove the specified resource from storage. - */ - public function destroy(string $id) - { - // - } } diff --git a/app/Http/Controllers/ProvinceDashboard/ReportController.php b/app/Http/Controllers/ProvinceDashboard/ReportController.php new file mode 100644 index 0000000..35d75d4 --- /dev/null +++ b/app/Http/Controllers/ProvinceDashboard/ReportController.php @@ -0,0 +1,36 @@ +json($reportService->cumulative($request)); + } + + public function peopleMessages(Request $request, ReportService $reportService): JsonResponse + { + return response()->json($reportService->peopleMessages($request)); + } + + public function detailedLogs(Request $request, ReportService $reportService): JsonResponse + { + return response()->json($reportService->detailedLogs($request)); + } + + public function operatorPerformanceDaily(Request $request, ReportService $reportService): JsonResponse + { + return response()->json($reportService->operatorPerformanceDaily($request)); + } + + public function operatorPerformanceTotal(Request $request, ReportService $reportService): JsonResponse + { + return response()->json($reportService->operatorPerformanceTotal($request)); + } +} diff --git a/app/Models/OperatorDialogueRating.php b/app/Models/OperatorDialogue.php similarity index 53% rename from app/Models/OperatorDialogueRating.php rename to app/Models/OperatorDialogue.php index 73b3651..2188499 100644 --- a/app/Models/OperatorDialogueRating.php +++ b/app/Models/OperatorDialogue.php @@ -2,13 +2,13 @@ namespace App\Models; -use Database\Factories\OperatorDialogueRatingFactory; +use Database\Factories\OperatorDialogueFactory; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -class OperatorDialogueRating extends Model +class OperatorDialogue extends Model { - /** @use HasFactory */ + /** @use HasFactory */ use HasFactory; protected $guarded = []; diff --git a/app/Services/Dashboard/Province/OperatorDialogues/DataTableService.php b/app/Services/Dashboard/Province/OperatorDialogues/DataTableService.php new file mode 100644 index 0000000..0a0fc65 --- /dev/null +++ b/app/Services/Dashboard/Province/OperatorDialogues/DataTableService.php @@ -0,0 +1,29 @@ +leftJoin('crm_db.voice_experts', 'asteriskcdrdb.cdr.uniqueid', '=', 'crm_db.operator_dialogues.cdr_unique_id') + ->where('dst', '<>', '') + ->where('lastapp', '=', 'Dial') + ->where('duration', '>', 0) + ->where('recordingfile', '<>', '') + ->select('*'); + + return DataTableFacade::run( + $query, + $request, + allowedFilters: ['*'], + allowedSortings: ['*'], + ); + } +} diff --git a/app/Services/Dashboard/Province/ReportService.php b/app/Services/Dashboard/Province/ReportService.php new file mode 100644 index 0000000..18bef68 --- /dev/null +++ b/app/Services/Dashboard/Province/ReportService.php @@ -0,0 +1,157 @@ +selectRaw(" + DATE(calldate) AS d, + COUNT(CASE WHEN (recordingfile = '' OR recordingfile LIKE 'q-%') THEN 1 END) AS c_all, + COUNT(CASE WHEN lastdata = 'IAX2/serverpeer/100' THEN 1 END) AS c_teh4, + COUNT(CASE WHEN lastdata = 'IAX2/242serverpeer/200' THEN 1 END) AS c_teh5, + COUNT(CASE WHEN dst = '500' THEN 1 END) AS c_os4, + COUNT(CASE WHEN dst = '600' THEN 1 END) AS c_os5, + COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'ANSWERED' AND dst BETWEEN 101 AND 104 THEN 1 END) AS c_ok, + COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'NO ANSWER' AND dst BETWEEN 101 AND 104 AND duration > 14 THEN 1 END) AS c_nok, + COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'ANSWERED' AND dst BETWEEN 101 AND 104 AND billsec > 9 THEN 1 END) AS c_b10, + COUNT(CASE WHEN lastapp = 'Busy' THEN 1 END) AS c_dnd, + COUNT(CASE WHEN dst BETWEEN 502 AND 599 THEN 1 END) AS c_trans, + COUNT(CASE WHEN disposition <> 'BUSY' AND dst BETWEEN 101 AND 105 THEN 1 END) AS ch_all, + AVG(CASE WHEN dcontext = 'from-internal' AND disposition = 'ANSWERED' THEN billsec END) AS c_avg + "); +// ->whereBetween('calldate', [$from, $to]) // use Carbon or date strings +// ->groupBy(DB::raw('DATE(calldate)')) +// ->orderByDesc(DB::raw('DATE(calldate)')) +// ->get(); + + return DataTableFacade::run( + $query, + $request, + allowedFilters: ['*'], + allowedSortings: ['*'], + allowedGroupBy: ['d'] + ); + } + + public function peopleMessages(Request $request) + { + $query = DB::table('people_messages') + ->selectRaw(' + COUNT(CASE WHEN is_listen = 1 THEN 1 END) AS c_l, + COUNT(CASE WHEN is_listen = 0 THEN 1 END) AS c_nl + '); +// ->whereBetween('date', [$date_from, $date_to]) +// ->first(); + + return DataTableFacade::run( + $query, + $request, + allowedFilters: ['*'], + allowedSortings: ['*'], + ); + } + + public function detailedLogs(Request $request) + { + $query = DB::table('asteriskcdrdb.cdr') + ->where('recordingfile', '<>', ''); +// ->whereBetween('calldate', ["$date_from $time_from", "$date_to $time_to"]) +// ->when($cid, function ($query, $cid) { +// return $query->where('src', 'like', "%{$cid}%"); +// }) +// ->when($c_op, function ($query, $c_op) { +// return $query->where('dst', $c_op); +// }, function ($query) { +// return $query->whereBetween('dst', [100, 110]); +// }) +// ->orderByDesc('calldate'); + + return DataTableFacade::run( + $query, + $request, + allowedFilters: ['*'], + allowedSortings: ['*'], + ); + } + + public function operatorPerformanceDaily(Request $request) + { + $query = DB::table('asteriskcdrdb.cdr') + ->selectRaw(" + SELECT + * + (ch_all - (c_ok + c_nok)) AS c_fail + FROM ( + SELECT + DATE(calldate) AS d, + dst, + COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'ANSWERED' AND dst BETWEEN 101 AND 104 THEN 1 END) AS c_ok, + COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'NO ANSWER' AND dst BETWEEN 101 AND 104 AND duration > 14 THEN 1 END) AS c_nok, + COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'ANSWERED' AND dst BETWEEN 101 AND 104 AND billsec > 9 THEN 1 END) AS c_b10, + COUNT(CASE WHEN lastapp = 'Busy' THEN 1 END) AS c_dnd, + COUNT(CASE WHEN dst BETWEEN 502 AND 599 THEN 1 END) AS c_trans, + COUNT(CASE WHEN disposition <> 'BUSY' AND dst BETWEEN 101 AND 105 THEN 1 END) AS ch_all + FROM asteriskcdrdb.cdr + WHERE dst BETWEEN 101 AND 105 AND calldate BETWEEN ? AND ? + GROUP BY d, dst + ORDER BY d, dst + ); + "); +// ->whereBetween('calldate', ["$date_from $time_from", "$date_to $time_to"]) +// ->when($cid, function ($query, $cid) { +// return $query->where('src', 'like', "%{$cid}%"); +// }) +// ->when($c_op, function ($query, $c_op) { +// return $query->where('dst', $c_op); +// }, function ($query) { +// return $query->whereBetween('dst', [100, 110]); +// }) +// ->orderByDesc('calldate'); + + return DataTableFacade::run( + $query, + $request, + allowedFilters: ['*'], + allowedSortings: ['*'], + ); + } + + public function operatorPerformanceTotal(Request $request) + { + $query = DB::table('asteriskcdrdb.cdr') + ->selectRaw(" + SELECT + * + (ch_all - (c_ok + c_nok)) AS c_fail + FROM ( + SELECT + DATE(calldate) AS d, + dst, + COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'ANSWERED' AND dst BETWEEN 101 AND 104 THEN 1 END) AS c_ok, + COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'NO ANSWER' AND dst BETWEEN 101 AND 104 AND duration > 14 THEN 1 END) AS c_nok, + COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'ANSWERED' AND dst BETWEEN 101 AND 104 AND billsec > 9 THEN 1 END) AS c_b10, + COUNT(CASE WHEN lastapp = 'Busy' THEN 1 END) AS c_dnd, + COUNT(CASE WHEN dst BETWEEN 502 AND 599 THEN 1 END) AS c_trans, + COUNT(CASE WHEN disposition <> 'BUSY' AND dst BETWEEN 101 AND 105 THEN 1 END) AS ch_all + FROM asteriskcdrdb.cdr + WHERE dst BETWEEN 101 AND 105 AND calldate BETWEEN ? AND ? + GROUP dst + ORDER dst + ); + "); + + return DataTableFacade::run( + $query, + $request, + allowedFilters: ['*'], + allowedSortings: ['*'], + ); + } +} diff --git a/database/factories/OperatorDialogueRatingFactory.php b/database/factories/OperatorDialogueFactory.php similarity index 81% rename from database/factories/OperatorDialogueRatingFactory.php rename to database/factories/OperatorDialogueFactory.php index 1d80042..f405551 100644 --- a/database/factories/OperatorDialogueRatingFactory.php +++ b/database/factories/OperatorDialogueFactory.php @@ -5,9 +5,9 @@ namespace Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\OperatorDialogueRating> + * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\OperatorDialogue> */ -class OperatorDialogueRatingFactory extends Factory +class OperatorDialogueFactory extends Factory { /** * Define the model's default state. diff --git a/database/migrations/2025_07_29_072224_create_operator_dialogue_ratings_table.php b/database/migrations/2025_08_02_110555_create_operator_dialogues_table.php similarity index 76% rename from database/migrations/2025_07_29_072224_create_operator_dialogue_ratings_table.php rename to database/migrations/2025_08_02_110555_create_operator_dialogues_table.php index ca6c42c..2a37667 100644 --- a/database/migrations/2025_07_29_072224_create_operator_dialogue_ratings_table.php +++ b/database/migrations/2025_08_02_110555_create_operator_dialogues_table.php @@ -11,11 +11,11 @@ return new class extends Migration */ public function up(): void { - Schema::create('operator_dialogue_ratings', function (Blueprint $table) { + Schema::create('operator_dialogues', function (Blueprint $table) { $table->id(); $table->string('cdr_unique_id'); $table->dateTime('date'); - $table->foreignId('expert_id')->constrained('users'); + $table->foreignId('supervisor_id')->constrained('users'); $table->boolean('is_listen')->default(false); $table->boolean('is_good'); $table->string('description')->nullable(); @@ -28,6 +28,6 @@ return new class extends Migration */ public function down(): void { - Schema::dropIfExists('operator_dialogue_ratings'); + Schema::dropIfExists('operator_dialogues'); } }; diff --git a/database/seeders/OperatorDialogueRatingSeeder.php b/database/seeders/OperatorDialogueSeeder.php similarity index 82% rename from database/seeders/OperatorDialogueRatingSeeder.php rename to database/seeders/OperatorDialogueSeeder.php index 27a7eff..e604a1f 100644 --- a/database/seeders/OperatorDialogueRatingSeeder.php +++ b/database/seeders/OperatorDialogueSeeder.php @@ -5,7 +5,7 @@ namespace Database\Seeders; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; -class OperatorDialogueRatingSeeder extends Seeder +class OperatorDialogueSeeder extends Seeder { /** * Run the database seeds.