Compare commits

...

12 Commits

Author SHA1 Message Date
379f0b7daa remove redundant packages 2026-02-22 09:27:07 +03:30
de6630dfc5 Merge branch 'feature/Teleport' into 'develop'
add select

See merge request witel-back-end/crm!35
2026-02-14 12:06:18 +00:00
342cd8cb51 add select 2026-02-14 15:34:55 +03:30
530e23d1e1 Merge branch 'feature/Teleport' into 'develop'
logout

See merge request witel-back-end/crm!33
2025-08-17 12:15:25 +00:00
e90d3775e2 logout 2025-08-17 15:43:12 +03:30
d4be4f557f Merge branch 'feature/Teleport' into 'develop'
create roles and permissions

See merge request witel-back-end/crm!32
2025-08-16 12:11:20 +00:00
1b88fb0f0a create roles and permissions 2025-08-16 15:38:38 +03:30
efd93816a0 Merge branch 'feature/TokenLogin' into 'develop'
fix route names

See merge request witel-back-end/crm!31
2025-08-16 05:56:26 +00:00
3ac70b0076 fix route names 2025-08-16 09:24:50 +03:30
07a7355f7f Merge branch 'feature/TokenLogin' into 'develop'
Feature/token login

See merge request witel-back-end/crm!30
2025-08-13 13:26:20 +00:00
dd2e016ad2 debug 2025-08-13 16:47:11 +03:30
0902b4864c Merge branch 'feature/TokenLogin' into 'develop'
Feature/token login

See merge request witel-back-end/crm!29
2025-08-13 11:00:56 +00:00
17 changed files with 215 additions and 95 deletions

View File

@@ -27,13 +27,6 @@ DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
ASTERISK_DB_CONNECTION=asterisk
ASTERISK_DB_HOST=127.0.0.1
ASTERISK_DB_PORT=3306
ASTERISK_DB_DATABASE=laravel
ASTERISK_DB_USERNAME=root
ASTERISK_DB_PASSWORD=
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false

View File

@@ -2,9 +2,7 @@ FROM docker.arvancloud.ir/php:8.3-fpm-alpine3.21
# Install common PHP extension dependencies
RUN apk update && apk add --no-cache \
git \
bash \
nano \
curl \
libpng \
libpng-dev \
@@ -29,8 +27,8 @@ COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER=1
# Default command
CMD composer install \
&& php artisan key:generate \
&& php artisan migrate \
&& php artisan db:seed \
&& php-fpm
CMD composer install ;\
php artisan key:generate ;\
php artisan migrate ;\
php artisan db:seed ;\
php-fpm

View File

@@ -25,8 +25,8 @@ class RoleManagementController extends Controller
Role::query(),
$request,
allowedFilters: array('id', 'name', 'name_fa'),
allowedSortings: array('id', 'name', 'name_fa'),
allowedRelations: array('permissions:id,name_fa')
allowedRelations: array('permissions:id,name_fa'),
allowedSortings: array('id', 'name', 'name_fa')
);
return response()->json($data);

View File

@@ -20,11 +20,13 @@ class LoginToProvinceController extends Controller
->value('ip');
$data = [
'user_id' => auth()->user()->id,
'user_id' => auth()->user()->username,
'token' => Hash::make(config('globalVariables.LOGIN_HASH_VALUE')),
'ip' => $province_ip,
];
auth()->user()->currentAccessToken()->delete();
return $this->successResponse($data);
}
}

View File

@@ -26,7 +26,7 @@ class SupervisorController extends Controller
{
OperatorDialogue::query()->updateOrCreate(
[
$request->cdr_unique_id
'cdr_unique_id' => $request->cdr_unique_id,
],
[
'cdr_unique_id' => $request->cdr_unique_id,

View File

@@ -19,10 +19,13 @@ class VerifyAuthenticationController extends Controller
return $this->errorResponse('Invalid token');
}
$user = User::query()->findOrFail($request->user_id);
$user = User::query()->firstWhere('username', '=', $request->user_id);
Auth::login($user);
$token = $user->createToken("{$user->username}", ['*'], now()->addWeek())->plainTextToken;
return $this->successResponse();
return $this->successResponse([
'message' => __('messages.successful'),
'token' => $token
]);
}
}

View File

@@ -1,24 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class VerifySetadIp
{
/**
* Handle an incoming request.
*
* @param Closure(Request): (Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if ($request->ip() == config('globalVariables.SETAD_IP')) {
return $next($request);
}
abort(Response::HTTP_FORBIDDEN);
}
}

View File

@@ -25,6 +25,7 @@ class RateRequest extends FormRequest
'cdr_unique_id' => 'required|string',
'is_good' => 'required|in:0,1',
'description' => 'string',
'date' => 'required|date'
];
}
}

View File

@@ -2,9 +2,18 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class Cdr extends Model
{
protected $table = 'cdr';
protected $table = 'asteriskcdrdb.cdr';
protected function recordingfile(): Attribute
{
return Attribute::make(
get: fn($value) => $value == null ? null : url('/') . 'recordingfiles/' . $value
);
}
}

View File

@@ -13,6 +13,10 @@ class DataTableService
{
$query = DB::table('asteriskcdrdb.cdr')
->leftJoin('roaddb.operator_dialogues', 'asteriskcdrdb.cdr.uniqueid', '=', 'roaddb.operator_dialogues.cdr_unique_id')
->select(
'asteriskcdrdb.cdr.*',
DB::raw("CONCAT('" . url('recordings') . "/', DATE_FORMAT(calldate, '%Y/%m/%d/'), recordingfile) AS recording_url")
)
->where('dst', '<>', '')
->where('lastapp', '=', 'Dial')
->where('duration', '>', 0)

View File

@@ -25,14 +25,14 @@ class ReportService
COUNT(CASE WHEN lastapp = 'Busy' THEN 1 END) AS dnd,
COUNT(CASE WHEN dst BETWEEN 502 AND 599 THEN 1 END) AS trans,
COUNT(CASE WHEN disposition <> 'BUSY' AND dst BETWEEN 101 AND 105 THEN 1 END) AS all_calls,
AVG(CASE WHEN dcontext = 'from-internal' AND disposition = 'ANSWERED' THEN billsec END) AS avg
AVG(CASE WHEN dcontext = 'from-internal' AND disposition = 'ANSWERED' THEN billsec END) AS avg,
(
COUNT(CASE WHEN disposition <> 'BUSY' AND dst BETWEEN 101 AND 105 THEN 1 END)
- (
COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'ANSWERED' AND dst BETWEEN 101 AND 104 THEN 1 END)
+ COUNT(CASE WHEN dcontext = 'from-internal' AND disposition = 'NO ANSWER' AND dst BETWEEN 101 AND 104 AND duration > 14 THEN 1 END)
)
) AS fail,
) AS fail
")->groupByRaw('DATE(calldate)');
$data = DataTableFacade::run(

View File

@@ -19,7 +19,6 @@ return Application::configure(basePath: dirname(__DIR__))
$middleware->statefulApi()->alias([
'role' => \Spatie\Permission\Middleware\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class,
'setadIp' => \App\Http\Middleware\VerifySetadIp::class,
]);
})
->withExceptions(function (Exceptions $exceptions) {

View File

@@ -4,5 +4,4 @@ return [
'TRUSTED_IP' => explode(',', env("TRUSTED_IP", '127.0.0.1')),
'NOTIFICATION_SERVER_URL' => env('NOTIFICATION_SERVER_URL', '127.0.0.1'),
'LOGIN_HASH_VALUE' => env('LOGIN_HASH_VALUE'),
'SETAD_IP' => env('SETAD_IP'),
];

View File

@@ -45,7 +45,103 @@ class PermissionSeeder extends Seeder
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
]
],
[
'id' => 5,
'name' => 'country_calls_report',
'name_fa' => 'تجمعی تمام مراکز',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 6,
'name' => 'country_voice_rating',
'name_fa' => 'تجمعی کیفی تمام مراکز',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 7,
'name' => 'country_message_rating',
'name_fa' => 'تجمعی پیام های مردمی',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 8,
'name' => 'country_keypress_report',
'name_fa' => 'گزارش تماس ها',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 9,
'name' => 'supervise_operator_dialogue',
'name_fa' => 'ارزیابی مکالمات اپراتور',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 10,
'name' => 'supervise_system_message',
'name_fa' => 'ارزیابی پیام های سیستمی',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 11,
'name' => 'supervise_people_message',
'name_fa' => 'ارزیابی پیام های مردمی',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 12,
'name' => 'province_reports',
'name_fa' => 'گزارشات استان',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 13,
'name' => 'province_operator_dialogue',
'name_fa' => 'مکالمات اپراتور',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 14,
'name' => 'province_system_message',
'name_fa' => 'پیام های سیستمی',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 15,
'name' => 'province_people_message',
'name_fa' => 'پیام های مردمی',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
[
'id' => 16,
'name' => 'supervisor_performance',
'name_fa' => 'عملکرد کارشناس ستاد',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
],
]);
}
}

View File

@@ -16,16 +16,56 @@ class RoleSeeder extends Seeder
*/
public function run(): void
{
$role = Role::query()->create([
$superAdmin = Role::query()->create([
'id' => 1,
'name' => 'super-admin',
'name_fa' => 'ادمین',
'name_fa' => 'سوپر ادمین',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
]);
$role->givePermissionTo(Permission::all());
$superAdmin->givePermissionTo(Permission::all());
User::query()->where('username', '=', 'witel')->first()->assignRole('super-admin');
$setadAdmin = Role::query()->create([
'id' => 2,
'name' => 'setad-admin',
'name_fa' => 'ادمین ستاد',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
]);
$setadAdmin->givePermissionTo([1, 3, 4, 5, 6, 7, 8, 16]);
$setadExpert = Role::query()->create([
'id' => 3,
'name' => 'setad-expert',
'name_fa' => 'کارشناس ستاد',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
]);
$setadExpert->givePermissionTo([3, 4, 5, 6, 7, 8]);
$provinceSupervisor = Role::query()->create([
'id' => 4,
'name' => 'province-supervisor',
'name_fa' => 'ارزیاب استان',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
]);
$provinceSupervisor->givePermissionTo([3, 4, 9, 10, 11, 12]);
$province = Role::query()->create([
'id' => 5,
'name' => 'province',
'name_fa' => 'استان',
'guard_name' => 'api',
'created_at' => now(),
'updated_at' => now()
]);
$province->givePermissionTo([3, 12, 13, 14, 15]);
}
}

View File

@@ -153,7 +153,7 @@ Route::middleware('auth')
->group(function () {
Route::get('/', 'index')->name('index');
Route::get('/excel', 'excel')->name('excel');
Route::post('/rate/{operatorDialogue}', 'rate')->name('rate');
Route::post('/rate', 'rate')->name('rate');
Route::get('/{operatorDialogue}', 'show')->name('show');
});
});
@@ -187,7 +187,7 @@ Route::middleware('auth')
->name('peopleMessages.')
->group(function () {
Route::prefix('operator')
->name('peopleMessages.')
->name('operator.')
->controller(\App\Http\Controllers\ProvinceDashboard\PeopleMessages\OperatorController::class)
->group(function () {
Route::get('/', 'index')->name('index');
@@ -197,7 +197,7 @@ Route::middleware('auth')
});
Route::prefix('supervisor')
->name('peopleMessages.')
->name('supervisor.')
->controller(\App\Http\Controllers\ProvinceDashboard\PeopleMessages\SupervisorController::class)
->group(function () {
Route::get('/', 'index')->name('index');
@@ -214,8 +214,7 @@ Route::middleware(['auth', 'permission:teleport_to_province'])
Route::post('/', 'authenticate')->name('authenticate');
});
Route::middleware(['auth', 'setadIp'])
->prefix('verify_authentication')
Route::prefix('verify_authentication')
->name('verifyAuthentication.')
->controller(VerifyAuthenticationController::class)
->group(function () {

View File

@@ -1,36 +1,37 @@
insert into provinces (id, name, lat, lon) values
('1','آذربایجان شرقی','38.0742000000','46.2962000000'),
('2','آذربایجان غربی','37.5495000000','45.0683000000'),
('3','اردبیل','38.2419000000','48.2887000000'),
('4','اصفهان','32.6709000000','51.6650000000'),
('5','البرز','35.8124000000','51.0074000000'),
('6','ایرانشهر','27.2069903000','60.6882515000'),
('7','ایلام','33.6381000000','46.4203000000'),
('8','بوشهر','28.9312000000','50.8458000000'),
('9','تهران','35.7065000000','51.3477000000'),
('10','چهارمحال و بختیاری','32.3259000000','50.8497000000'),
('11','خراسان جنوبی','32.8635000000','59.2177000000'),
('12','خراسان رضوی','36.2977000000','59.6059000000'),
('13','خراسان شمالی','37.4761000000','57.3320000000'),
('14','خوزستان','31.3231000000','48.6793000000'),
('15','زنجان','36.6782000000','48.5079000000'),
('16','سمنان شرق','36.4056260000','54.9670738726'),
('17','سمنان غرب','35.5834074000','53.3882906000'),
('18','سیستان و بلوچستان','29.4912000000','60.8674000000'),
('19','فارس','29.6061000000','52.5378000000'),
('20','قزوین','36.2816000000','50.0153000000'),
('21','قم','34.6425000000','50.8801000000'),
('22','کردستان','35.3128000000','46.9979000000'),
('23','کرمان','30.2924085000','57.0645647000'),
('24','کرمان جنوب','28.6697367000','57.7373382000'),
('25','کرمانشاه','34.3241000000','47.0736000000'),
('26','کهگیلویه و بویراحمد','30.6678000000','51.5803000000'),
('27','گلستان','36.8305000000','54.4242000000'),
('28','گیلان','37.2795000000','49.5846000000'),
('29','لارستان','27.6619203000','54.3229561000'),
('30','لرستان','33.4844000000','48.3538000000'),
('31','مازندران','36.5505000000','53.0708000000'),
('32','مرکزی','34.0883000000','49.7132000000'),
('33','هرمزگان','27.1795000000','56.2781000000'),
('34','همدان','34.7992000000','48.5148000000'),
('35','یزد','31.8888000000','54.3641000000');
insert into provinces (id, name, lat, lon, ip) values
('1','آذربایجان شرقی','38.0742000000','46.2962000000', '172.30.5.1'),
('2','آذربایجان غربی','37.5495000000','45.0683000000', '172.30.5.1'),
('3','اردبیل','38.2419000000','48.2887000000', '172.30.5.1'),
('4','اصفهان','32.6709000000','51.6650000000', '172.30.5.1'),
('5','البرز','35.8124000000','51.0074000000', '172.30.5.1'),
('6','ایرانشهر','27.2069903000','60.6882515000', '172.30.5.1'),
('7','ایلام','33.6381000000','46.4203000000', '172.30.5.1'),
('8','بوشهر','28.9312000000','50.8458000000', '172.30.5.1'),
('9','تهران','35.7065000000','51.3477000000', '172.30.5.1'),
('10','چهارمحال و بختیاری','32.3259000000','50.8497000000', '172.30.5.1'),
('11','خراسان جنوبی','32.8635000000','59.2177000000', '172.30.5.1'),
('12','خراسان رضوی','36.2977000000','59.6059000000', '172.30.5.1'),
('13','خراسان شمالی','37.4761000000','57.3320000000', '172.30.5.1'),
('14','خوزستان','31.3231000000','48.6793000000', '172.30.5.1'),
('15','زنجان','36.6782000000','48.5079000000', '172.30.5.1'),
('16','سمنان شرق','36.4056260000','54.9670738726', '172.30.5.1'),
('17','سمنان غرب','35.5834074000','53.3882906000', '172.30.5.1'),
('18','سیستان و بلوچستان','29.4912000000','60.8674000000', '172.30.5.1'),
('19','فارس','29.6061000000','52.5378000000', '172.30.5.1'),
('20','قزوین','36.2816000000','50.0153000000', '172.30.5.1'),
('21','قم','34.6425000000','50.8801000000', '172.30.5.1'),
('22','کردستان','35.3128000000','46.9979000000', '172.30.5.1'),
('23','کرمان','30.2924085000','57.0645647000', '172.30.5.1'),
('24','کرمان جنوب','28.6697367000','57.7373382000', '172.30.5.1'),
('25','کرمانشاه','34.3241000000','47.0736000000', '172.30.5.1'),
('26','کهگیلویه و بویراحمد','30.6678000000','51.5803000000', '172.30.5.1'),
('27','گلستان','36.8305000000','54.4242000000', '172.30.5.1'),
('28','گیلان','37.2795000000','49.5846000000', '172.30.5.1'),
('29','لارستان','27.6619203000','54.3229561000', '172.30.5.1'),
('30','لرستان','33.4844000000','48.3538000000', '172.30.5.1'),
('31','مازندران','36.5505000000','53.0708000000', '172.30.5.1'),
('32','مرکزی','34.0883000000','49.7132000000', '172.30.5.1'),
('33','هرمزگان','27.1795000000','56.2781000000', '172.30.5.1'),
('34','همدان','34.7992000000','48.5148000000', '172.30.5.1'),
('35','یزد','31.8888000000','54.3641000000', '172.30.5.1'),
('36','ستاد','35.7065000000','51.3477000000', '172.30.5.1');