├── public ├── favicon.ico ├── robots.txt ├── example │ ├── attendance_format_1.txt │ └── attendance_format_2.txt ├── web.config ├── index.php └── svg │ ├── 404.svg │ ├── 503.svg │ ├── 403.svg │ └── 500.svg ├── screenshot ├── home.png ├── id-2.png ├── id1.png ├── list.png ├── ce │ ├── menu.png │ ├── dashboard.png │ └── profile-st.png ├── grade.png ├── rules.png ├── marksheet.jpg ├── attendance.jpg └── site-dashboard.png ├── tests ├── TestCase.php ├── Unit │ └── ExampleTest.php ├── Feature │ └── ExampleTest.php └── CreatesApplication.php ├── app ├── AboutSlider.php ├── AppMeta.php ├── Grade.php ├── AcademicCalendar.php ├── AcademicYear.php ├── AttendanceFileQueue.php ├── ClassProfile.php ├── Event.php ├── AboutContent.php ├── Exam.php ├── Console │ ├── Kernel.php │ └── Commands │ │ ├── SeedEmployeeAttendance.php │ │ └── SeedStudentAttendance.php ├── ExamRule.php ├── EmployeeAttendance.php ├── Exceptions │ └── Handler.php ├── Employee.php └── Http │ └── Controllers │ └── Backend │ └── AcademicController.php ├── bin └── cloudschool-worker.conf ├── .gitignore ├── database ├── factories │ ├── WorkousideFactory.php │ ├── UserFactory.php │ ├── LeaveFactory.php │ ├── ExamFactory.php │ ├── SectionFactory.php │ ├── SubjectFactory.php │ ├── StudentFactory.php │ └── TeacherFactory.php └── migrations │ ├── 2018_03_05_000005_create_password_resets_table.php │ ├── 2018_03_04_000000_create_roles_table.php │ ├── 2018_07_08_110923_create_site_metas_table.php │ ├── 2018_08_11_092832_create_app_metas_table.php │ ├── 2018_03_05_000002_create_permissions_table.php │ ├── 2018_07_11_035714_create_testimonials_table.php │ ├── 2018_08_11_121754_create_academic_years_table.php │ ├── 2018_06_09_065945_create_sliders_table.php │ ├── 2018_03_05_000001_create_user_roles_table.php │ ├── 2018_07_14_155755_create_teacher_profiles_table.php │ ├── 2018_03_05_000003_create_users_permissions_table.php │ ├── 2018_03_05_000004_create_roles_permissions_table.php │ ├── 2018_03_05_000000_create_users_table.php │ ├── 2018_07_14_180514_create_events_table.php │ ├── 2018_07_14_115139_create_class_profiles_table.php │ └── 2018_07_06_103920_create_about_content_tables.php ├── routes ├── channels.php ├── api.php ├── console.php ├── website.php └── web.php ├── server.php ├── phpunit.xml ├── .env.example ├── webpack.frontend.mix.js ├── config ├── hashing.php ├── broadcasting.php ├── filesystems.php ├── cache.php ├── logging.php ├── auth.php ├── database.php └── app.php ├── bootstrap └── app.php ├── artisan ├── package.json ├── webpack.backend.mix.js ├── composer.json └── readme.md /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /screenshot/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/home.png -------------------------------------------------------------------------------- /screenshot/id-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/id-2.png -------------------------------------------------------------------------------- /screenshot/id1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/id1.png -------------------------------------------------------------------------------- /screenshot/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/list.png -------------------------------------------------------------------------------- /screenshot/ce/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/ce/menu.png -------------------------------------------------------------------------------- /screenshot/grade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/grade.png -------------------------------------------------------------------------------- /screenshot/rules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/rules.png -------------------------------------------------------------------------------- /screenshot/marksheet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/marksheet.jpg -------------------------------------------------------------------------------- /screenshot/attendance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/attendance.jpg -------------------------------------------------------------------------------- /screenshot/ce/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/ce/dashboard.png -------------------------------------------------------------------------------- /screenshot/ce/profile-st.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/ce/profile-st.png -------------------------------------------------------------------------------- /screenshot/site-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hindhuja-V/school-management/HEAD/screenshot/site-dashboard.png -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /bin/cloudschool-worker.conf: -------------------------------------------------------------------------------- 1 | [program:cloudschool-worker] 2 | process_name=%(program_name)s_%(process_num)02d 3 | command=php /home/hbot/www/public_html/sms/artisan queue:work --tries=3 --sleep=3 --queue=default,commands,absent,sms,email 4 | autostart=true 5 | autorestart=true 6 | user=www-data 7 | numprocs=3 8 | redirect_stderr=true 9 | stdout_logfile=/home/hbot/www/public_html/sms/storage/logs/cloudschool-worker.log -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /public/hot 3 | /public/storage 4 | /public/css 5 | /public/js 6 | /public/fonts 7 | /public/images 8 | /public/frontend 9 | /public/mix-manifest.json 10 | /storage/*.key 11 | /vendor 12 | /.idea 13 | /.vscode 14 | /.vagrant 15 | Homestead.json 16 | Homestead.yaml 17 | npm-debug.log 18 | yarn-error.log 19 | yarn.lock 20 | .env 21 | storage/debugbar 22 | database/seeds/DevPermissionTableSeeder.php 23 | -------------------------------------------------------------------------------- /tests/Feature/ExampleTest.php: -------------------------------------------------------------------------------- 1 | get('/'); 18 | 19 | $response->assertStatus(200); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/AppMeta.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 19 | 20 | return $app; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/AcademicCalendar.php: -------------------------------------------------------------------------------- 1 | define(App\WorkOutside::class, function (Faker $faker) { 6 | return [ 7 | 'employee_id' => function () { 8 | // Get random teacher id 9 | return App\Employee::inRandomOrder()->first()->id; 10 | }, 11 | 'work_date' => $faker->dateTimeThisMonth($max = 'now', $timezone = "Asia/Dhaka")->format('d/m/Y'), 12 | 'document' => null, 13 | 'description' => $faker->sentence, 14 | ]; 15 | }); 16 | -------------------------------------------------------------------------------- /database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | define(App\User::class, function (Faker $faker) { 7 | return [ 8 | 'name' => $faker->name, 9 | 'username' => $faker->unique()->userName, 10 | 'email' => $faker->unique()->safeEmail, 11 | 'password' => bcrypt('demo123'), 12 | 'status' => '1', 13 | 'force_logout' => 0, 14 | 'remember_token' => Str::random(10), 15 | 'created_by' => 1, 16 | 'created_at' => now() 17 | ]; 18 | }); 19 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 16 | }); 17 | -------------------------------------------------------------------------------- /app/AcademicYear.php: -------------------------------------------------------------------------------- 1 | get('/user', function (Request $request) { 17 | return $request->user(); 18 | }); 19 | -------------------------------------------------------------------------------- /database/factories/LeaveFactory.php: -------------------------------------------------------------------------------- 1 | define(App\Leave::class, function (Faker $faker) { 6 | return [ 7 | 'employee_id' => function () { 8 | // Get random teacher id 9 | return App\Employee::inRandomOrder()->first()->id; 10 | }, 11 | 'leave_type' => rand(1,2), 12 | 'leave_date' => $faker->dateTimeThisMonth($max = 'now', $timezone = "Asia/Dhaka")->format('d/m/Y'), 13 | 'document' => null, 14 | 'description' => $faker->sentence, 15 | 'status' => rand(1,3) 16 | ]; 17 | }); 18 | -------------------------------------------------------------------------------- /app/AttendanceFileQueue.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 18 | })->describe('Display an inspiring quote'); 19 | -------------------------------------------------------------------------------- /database/factories/ExamFactory.php: -------------------------------------------------------------------------------- 1 | define(App\Exam::class, function (Faker $faker) { 6 | return [ 7 | 'name' => $faker->sentence($nbWords = 3, $variableNbWords = true), 8 | 'elective_subject_point_addition' => rand(0,2), 9 | 'marks_distribution_types' => json_encode(array_rand(\App\Http\Helpers\AppHelper::MARKS_DISTRIBUTION_TYPES, 3)), 10 | 'class_id' => function () { 11 | // Get random class id 12 | return App\IClass::where('id','!=',1)->inRandomOrder()->first()->id; 13 | }, 14 | 'status' => '1', 15 | ]; 16 | }); 17 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | $uri = urldecode( 11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 12 | ); 13 | 14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 15 | // built-in PHP web server. This provides a convenient way to test a Laravel 16 | // application without having installed a "real" web server software here. 17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 18 | return false; 19 | } 20 | 21 | require_once __DIR__.'/public/index.php'; 22 | -------------------------------------------------------------------------------- /database/factories/SectionFactory.php: -------------------------------------------------------------------------------- 1 | define(App\Section::class, function (Faker $faker) { 6 | 7 | return [ 8 | 'name' => strtoupper($faker->unique()->randomLetter), 9 | 'capacity' => rand(20,40), 10 | 'class_id' => function(){ 11 | return App\IClass::where('id','!=',1)->inRandomOrder()->first()->id; 12 | }, 13 | 'teacher_id' => function () { 14 | // Get random teacher id 15 | return App\Employee::where('role_id', \App\Http\Helpers\AppHelper::USER_TEACHER)->inRandomOrder()->first()->id; 16 | }, 17 | 'note' => $faker->sentence, 18 | 'status' => '1', 19 | ]; 20 | }); 21 | -------------------------------------------------------------------------------- /app/ClassProfile.php: -------------------------------------------------------------------------------- 1 | define(App\Subject::class, function (Faker $faker) { 6 | return [ 7 | 'name' => $faker->sentence($nbWords = 3, $variableNbWords = true), 8 | 'code' => $faker->unique()->numberBetween($min = 100, $max = 200), 9 | 'type' => rand(1,2), 10 | 'class_id' => function () { 11 | // Get random class id 12 | return App\IClass::where('id','!=',1)->inRandomOrder()->first()->id; 13 | }, 14 | 'teacher_id' => function () { 15 | // Get random teacher id 16 | return App\Employee::where('role_id', \App\Http\Helpers\AppHelper::USER_TEACHER)->inRandomOrder()->first()->id; 17 | }, 18 | 'status' => '1', 19 | ]; 20 | }); 21 | -------------------------------------------------------------------------------- /app/AboutContent.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Exam.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\IClass', 'class_id'); 32 | } 33 | 34 | public function scopeIclass($query, $classId) 35 | { 36 | if($classId){ 37 | return $query->where('class_id', $classId); 38 | } 39 | 40 | return $query; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /database/migrations/2018_03_04_000000_create_roles_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name')->unique(); 19 | $table->boolean('deletable')->default(true); 20 | $table->timestamps(); 21 | $table->softDeletes(); 22 | $table->userstamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('roles'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2018_07_08_110923_create_site_metas_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('meta_key'); 19 | $table->longText('meta_value'); 20 | $table->timestamps(); 21 | $table->softDeletes(); 22 | $table->userstamps(); 23 | 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('site_metas'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2018_08_11_092832_create_app_metas_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('meta_key'); 19 | $table->longText('meta_value')->nullable(); 20 | $table->timestamps(); 21 | $table->softDeletes(); 22 | $table->userstamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('app_metas'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /public/example/attendance_format_2.txt: -------------------------------------------------------------------------------- 1 | 197001 2019-01-18 07:38:22 102 4 197001 I 0 1 2 | 197002 2019-01-18 07:44:17 102 4 197002 I 0 1 3 | 197003 2019-01-18 07:44:34 102 4 197003 I 0 1 4 | 197004 2019-01-18 07:45:02 102 4 197004 I 0 1 5 | 197005 2019-01-18 07:45:57 102 4 197005 I 0 1 6 | 197006 2019-01-18 07:56:48 102 4 197006 I 0 1 7 | 197007 2019-01-18 08:06:34 102 4 197007 I 0 1 8 | 197008 2019-01-18 08:06:44 102 4 197008 I 0 1 9 | 197009 2019-01-18 09:11:45 102 4 197009 I 0 1 10 | 197010 2019-01-18 09:12:22 102 4 197010 I 0 1 -------------------------------------------------------------------------------- /public/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire') 28 | // ->hourly(); 29 | } 30 | 31 | /** 32 | * Register the commands for the application. 33 | * 34 | * @return void 35 | */ 36 | protected function commands() 37 | { 38 | $this->load(__DIR__.'/Commands'); 39 | 40 | require base_path('routes/console.php'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /database/migrations/2018_03_05_000002_create_permissions_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('slug'); //route name [user.create] 19 | $table->string('name'); // Readable Name [User Create] 20 | $table->string('group')->nullable(); // Group name [site, user, system user] 21 | $table->timestamp("created_at")->useCurrent(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('permissions'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2018_07_11_035714_create_testimonials_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('writer'); 19 | $table->text('comments'); 20 | $table->string('avatar')->nullable(); 21 | $table->integer('order')->default(0); 22 | $table->timestamps(); 23 | $table->softDeletes(); 24 | $table->userstamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('testimonials'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2018_08_11_121754_create_academic_years_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('title'); 19 | $table->date('start_date'); 20 | $table->date('end_date'); 21 | $table->enum('status', [0,1])->default(0); 22 | $table->timestamps(); 23 | $table->softDeletes(); 24 | $table->userstamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('academic_years'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2018_06_09_065945_create_sliders_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 19 | $table->string('title'); 20 | $table->string('subtitle'); 21 | $table->string('image'); 22 | $table->integer('order')->default(0); 23 | $table->timestamps(); 24 | $table->softDeletes(); 25 | $table->userstamps(); 26 | } 27 | ); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::dropIfExists('sliders'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /database/migrations/2018_03_05_000001_create_user_roles_table.php: -------------------------------------------------------------------------------- 1 | unsignedInteger('user_id'); 18 | $table->unsignedInteger('role_id'); 19 | $table->timestamps(); 20 | $table->softDeletes(); 21 | $table->userstamps(); 22 | 23 | //FOREIGN KEY CONSTRAINTS 24 | $table->foreign('user_id')->references('id')->on('users'); 25 | $table->foreign('role_id')->references('id')->on('roles'); 26 | 27 | 28 | //SETTING THE PRIMARY KEYS 29 | $table->primary(['user_id','role_id']); 30 | 31 | }); 32 | } 33 | 34 | /** 35 | * Reverse the migrations. 36 | * 37 | * @return void 38 | */ 39 | public function down() 40 | { 41 | Schema::dropIfExists('user_roles'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /database/factories/StudentFactory.php: -------------------------------------------------------------------------------- 1 | define(App\Student::class, function (Faker $faker) { 6 | 7 | $user = factory(App\User::class)->create(); 8 | return [ 9 | 'user_id' => $user->id, 10 | 'name' => $faker->name($gender = 'male'|'female'), 11 | 'dob' => $faker->dateTimeBetween($startDate = '-20 years', $endDate = 'now', $timezone = "Asia/Dhaka")->format('d/m/Y'), 12 | 'gender' => rand(1,2), 13 | 'religion' => rand(1,5), 14 | 'blood_group' => rand(1,8), 15 | 'nationality' => substr($faker->country, 0 , 48), 16 | 'photo' => null, 17 | 'email' => $user->email, 18 | 'phone_no' => $faker->e164PhoneNumber, 19 | 'extra_activity' => '', 20 | 'note' => '', 21 | 'father_name' => $faker->name($gender = 'male'), 22 | 'father_phone_no' => $faker->e164PhoneNumber, 23 | 'mother_name' => $faker->name($gender = 'female'), 24 | 'mother_phone_no' => $faker->e164PhoneNumber, 25 | 'guardian' => null, 26 | 'guardian_phone_no' => null, 27 | 'present_address' => $faker->address, 28 | 'permanent_address' => $faker->address, 29 | 'status' => '1', 30 | ]; 31 | }); 32 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./tests/Feature 14 | 15 | 16 | 17 | ./tests/Unit 18 | 19 | 20 | 21 | 22 | ./app 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /database/factories/TeacherFactory.php: -------------------------------------------------------------------------------- 1 | define(App\Employee::class, function (Faker $faker) { 6 | $user = factory(App\User::class)->create(); 7 | return [ 8 | 'user_id' => $user->id, 9 | 'role_id' => \App\Http\Helpers\AppHelper::USER_TEACHER, 10 | 'id_card' => str_pad($faker->unique()->numberBetween($min = 1, $max = 99),10,'0',STR_PAD_LEFT), 11 | 'name' => $faker->name($gender = 'male'|'female'), 12 | 'designation' => $faker->jobTitle, 13 | 'qualification' => $faker->word, 14 | 'dob' => $faker->dateTimeBetween($startDate = '-20 years', $endDate = 'now', $timezone = "Asia/Dhaka")->format('d/m/Y'), 15 | 'gender' => rand(1,2), 16 | 'religion' => rand(1,5), 17 | 'email' => $user->email, 18 | 'phone_no' => $faker->e164PhoneNumber, 19 | 'address' => $faker->address, 20 | 'joining_date' => $faker->dateTimeBetween($startDate = '-5 years', $endDate = 'now', $timezone = "Asia/Dhaka")->format('d/m/Y'), 21 | 'photo' => null, 22 | 'signature' => null, 23 | 'shift' => rand(1,2), 24 | 'duty_start' => '09:00 am', 25 | 'duty_end' => '05:00 pm', 26 | 'status' => '1' 27 | ]; 28 | }); 29 | 30 | -------------------------------------------------------------------------------- /database/migrations/2018_07_14_155755_create_teacher_profiles_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('designation'); 20 | $table->string('image')->nullable(); 21 | $table->longText('description')->nullable(); 22 | $table->longText('qualification')->nullable(); 23 | $table->string('facebook')->nullable(); 24 | $table->string('google')->nullable(); 25 | $table->string('twitter')->nullable(); 26 | $table->timestamps(); 27 | $table->softDeletes(); 28 | $table->userstamps(); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::dropIfExists('teacher_profiles'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /database/migrations/2018_03_05_000003_create_users_permissions_table.php: -------------------------------------------------------------------------------- 1 | integer('user_id')->unsigned(); 18 | $table->integer('permission_id')->unsigned(); 19 | $table->timestamps(); 20 | $table->softDeletes(); 21 | $table->userstamps(); 22 | 23 | //FOREIGN KEY CONSTRAINTS 24 | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 25 | $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade'); 26 | 27 | //SETTING THE PRIMARY KEYS 28 | // $table->primary(['user_id','permission_id']); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::dropIfExists('users_permissions'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /database/migrations/2018_03_05_000004_create_roles_permissions_table.php: -------------------------------------------------------------------------------- 1 | integer('role_id')->unsigned(); 18 | $table->integer('permission_id')->unsigned(); 19 | $table->timestamps(); 20 | $table->softDeletes(); 21 | $table->userstamps(); 22 | 23 | //FOREIGN KEY CONSTRAINTS 24 | $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); 25 | $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade'); 26 | 27 | // //SETTING THE PRIMARY KEYS 28 | // $table->primary(['role_id','permission_id']); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::dropIfExists('roles_permissions'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /database/migrations/2018_03_05_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 19 | $table->string('name'); 20 | $table->string('username')->unique(); 21 | $table->string('email')->unique(); 22 | $table->string('phone_no',15)->nullable(); 23 | $table->string('password'); 24 | $table->rememberToken(); 25 | $table->boolean('force_logout')->default(0); 26 | $table->enum('status', [0,1])->default(1); 27 | $table->timestamps(); 28 | $table->softDeletes(); 29 | $table->userstamps(); 30 | } 31 | ); 32 | } 33 | 34 | /** 35 | * Reverse the migrations. 36 | * 37 | * @return void 38 | */ 39 | public function down() 40 | { 41 | Schema::dropIfExists('users'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/ExamRule.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\IClass', 'class_id'); 35 | } 36 | public function exam() 37 | { 38 | return $this->belongsTo('App\Exam', 'exam_id'); 39 | } 40 | 41 | public function combineSubject() 42 | { 43 | return $this->belongsTo('App\Subject', 'combine_subject_id'); 44 | } 45 | 46 | public function subject() 47 | { 48 | return $this->belongsTo('App\Subject', 'subject_id'); 49 | } 50 | 51 | public function grade() 52 | { 53 | return $this->belongsTo('App\Grade', 'grade_id'); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /database/migrations/2018_07_14_180514_create_events_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->dateTime('event_time'); 19 | $table->string('title'); 20 | $table->string('slug',500); 21 | $table->string('cover_photo')->nullable(); 22 | $table->string('cover_video')->nullable(); 23 | $table->string('tags')->nullable(); 24 | $table->longText('description'); 25 | $table->string('slider_1')->nullable(); 26 | $table->string('slider_2')->nullable(); 27 | $table->string('slider_3')->nullable(); 28 | $table->timestamps(); 29 | $table->softDeletes(); 30 | $table->userstamps(); 31 | }); 32 | 33 | } 34 | 35 | /** 36 | * Reverse the migrations. 37 | * 38 | * @return void 39 | */ 40 | public function down() 41 | { 42 | Schema::dropIfExists('events'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /database/migrations/2018_07_14_115139_create_class_profiles_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('slug',500); 20 | $table->string('image_sm'); 21 | $table->string('image_lg'); 22 | $table->string('teacher'); 23 | $table->string('room_no',50); 24 | $table->integer('capacity'); 25 | $table->string('shift'); 26 | $table->longText('short_description'); 27 | $table->longText('description')->nullable(); 28 | $table->longText('outline')->nullable(); 29 | $table->timestamps(); 30 | $table->softDeletes(); 31 | $table->userstamps(); 32 | }); 33 | } 34 | 35 | /** 36 | * Reverse the migrations. 37 | * 38 | * @return void 39 | */ 40 | public function down() 41 | { 42 | Schema::dropIfExists('class_profiles'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # Application Settings 2 | 3 | APP_NAME=CloudSchool 4 | APP_ENV=production 5 | APP_KEY=base64:+m0h+ObGNu26eF4MVCgqX1ua0IukSUn7lRYInflNt8A= 6 | APP_DEBUG=false 7 | APP_URL=http://localhost 8 | APP_TIMEZONE=Asia/Dhaka 9 | APP_LOCALE=en 10 | MAX_RECORD_PER_PAGE= 25 11 | INSTITUTE_CATEGORY=school 12 | CURRENCY_SYMBOL="tk." 13 | DASHBOARD_SECTION_STUDENT_CLASS_CODE=90,91,92,100,101,102 14 | 15 | # Its only for college. value will the the title of the year 16 | DASHBOARD_STUDENT_COUNT_DEFAULT_ACADEMIC_YEAR=2018 17 | 18 | # Website frontend Settings 19 | MAX_RECORD_PER_PAGE_FRONT= 10 20 | GA_TRACK_ID= 21 | 22 | 23 | # DB Settings 24 | 25 | DB_CONNECTION=mysql 26 | DB_HOST=127.0.0.1 27 | DB_PORT=3306 28 | DB_DATABASE=sms_2_0 29 | DB_USERNAME=root 30 | DB_PASSWORD=root 31 | 32 | # Log, Session, Job Queue Settings 33 | 34 | BROADCAST_DRIVER=log 35 | LOG_CHANNEL=stack 36 | CACHE_DRIVER=file 37 | SESSION_DRIVER=file 38 | SESSION_LIFETIME=120 39 | QUEUE_CONNECTION=database 40 | 41 | # Storage Settings 42 | 43 | FILESYSTEM_DRIVER=local 44 | 45 | # Pusher Settings 46 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 47 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 48 | 49 | 50 | # Email Server Settings 51 | 52 | MAIL_DRIVER=smtp 53 | MAIL_HOST=smtp.mailtrap.io 54 | MAIL_PORT=2525 55 | MAIL_USERNAME= 56 | MAIL_PASSWORD= 57 | MAIL_ENCRYPTION=tls 58 | 59 | # website admin email address for recieve contact email 60 | 61 | MAIL_RECEIVER=dev@hrshadhin.me 62 | MAIL_NO_REPLY_ADDRESS= 63 | 64 | 65 | # Deployment settings 66 | 67 | DEVELOPER_MODE_ENABLED=false -------------------------------------------------------------------------------- /webpack.frontend.mix.js: -------------------------------------------------------------------------------- 1 | let mixFrontend = require('laravel-mix'); 2 | 3 | const fullPublicPath = "public/frontend"; 4 | const mixManifest = fullPublicPath + '/mix-manifest.json'; 5 | /* 6 | |-------------------------------------------------------------------------- 7 | | Mix Frontend Asset Management 8 | |-------------------------------------------------------------------------- 9 | | 10 | | Mix provides a clean, fluent API for defining some Webpack build steps 11 | | for your Laravel application. By default, we are compiling the Sass 12 | | file for the application as well as bundling up all the JS files. 13 | | 14 | */ 15 | 16 | mixFrontend.setPublicPath(fullPublicPath); 17 | 18 | mixFrontend.js('resources/assets/frontend/js/libs.js', 'public/frontend/js') 19 | .sass('resources/assets/frontend/sass/libs.scss', 'public/frontend/css'); 20 | 21 | 22 | mixFrontend.options({ 23 | processCssUrls: false, 24 | // uglify: {}, 25 | purifyCss: false, 26 | // purifyCss: {}, 27 | clearConsole: false 28 | }); 29 | 30 | 31 | // copy non processing files to public path 32 | mixFrontend.copyDirectory('resources/assets/frontend/libs/jquery.min.js', 'public/frontend/js/jquery.min.js'); 33 | mixFrontend.copyDirectory('resources/assets/frontend/img', 'public/frontend/img'); 34 | mixFrontend.copyDirectory('resources/assets/frontend/fonts', 'public/frontend/fonts'); 35 | mixFrontend.copyDirectory('resources/assets/frontend/flags', 'public/frontend/flags'); 36 | mixFrontend.copyDirectory('resources/assets/frontend/rs-plugin', 'public/frontend/rs-plugin'); 37 | 38 | if (mixFrontend.inProduction()) { 39 | mixFrontend.version(); 40 | mixFrontend.sourceMaps(); 41 | } 42 | 43 | mixFrontend.browserSync({ 44 | proxy: 'l5.school.test' 45 | }); -------------------------------------------------------------------------------- /config/hashing.php: -------------------------------------------------------------------------------- 1 | 'bcrypt', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Bcrypt Options 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may specify the configuration options that should be used when 26 | | passwords are hashed using the Bcrypt algorithm. This will allow you 27 | | to control the amount of time it takes to hash the given password. 28 | | 29 | */ 30 | 31 | 'bcrypt' => [ 32 | 'rounds' => env('BCRYPT_ROUNDS', 10), 33 | ], 34 | 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | Argon Options 38 | |-------------------------------------------------------------------------- 39 | | 40 | | Here you may specify the configuration options that should be used when 41 | | passwords are hashed using the Argon algorithm. These will allow you 42 | | to control the amount of time it takes to hash the given password. 43 | | 44 | */ 45 | 46 | 'argon' => [ 47 | 'memory' => 1024, 48 | 'threads' => 2, 49 | 'time' => 2, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | App\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | App\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | App\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /config/broadcasting.php: -------------------------------------------------------------------------------- 1 | env('BROADCAST_DRIVER', 'null'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Broadcast Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the broadcast connections that will be used 26 | | to broadcast events to other systems or over websockets. Samples of 27 | | each available type of connection are provided inside this array. 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'pusher' => [ 34 | 'driver' => 'pusher', 35 | 'key' => env('PUSHER_APP_KEY'), 36 | 'secret' => env('PUSHER_APP_SECRET'), 37 | 'app_id' => env('PUSHER_APP_ID'), 38 | 'options' => [ 39 | 'cluster' => env('PUSHER_APP_CLUSTER'), 40 | 'encrypted' => true, 41 | ], 42 | ], 43 | 44 | 'redis' => [ 45 | 'driver' => 'redis', 46 | 'connection' => 'default', 47 | ], 48 | 49 | 'log' => [ 50 | 'driver' => 'log', 51 | ], 52 | 53 | 'null' => [ 54 | 'driver' => 'null', 55 | ], 56 | 57 | ], 58 | 59 | ]; 60 | -------------------------------------------------------------------------------- /app/EmployeeAttendance.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\Employee', 'employee_id'); 39 | } 40 | 41 | public function setAttendanceDateAttribute($value) 42 | { 43 | $this->attributes['attendance_date'] = Carbon::createFromFormat('d/m/Y', $value)->format('Y-m-d'); 44 | } 45 | 46 | public function getAttendanceDateAttribute($value) 47 | { 48 | return Carbon::parse($value)->format('d/m/Y'); 49 | } 50 | 51 | 52 | public function getPresentAttribute($value) 53 | { 54 | return Arr::get(AppHelper::ATTENDANCE_TYPE, $value); 55 | } 56 | 57 | public function scopeEmployee($query, $employee) 58 | { 59 | if($employee){ 60 | return $query->where('employee_id', $employee); 61 | } 62 | 63 | return $query; 64 | } 65 | 66 | public function scopeCountOrGet($query, $isCount) 67 | { 68 | if($isCount){ 69 | return $query->count(); 70 | } 71 | 72 | return $query->get(); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | make(Illuminate\Contracts\Console\Kernel::class); 34 | 35 | $status = $kernel->handle( 36 | $input = new Symfony\Component\Console\Input\ArgvInput, 37 | new Symfony\Component\Console\Output\ConsoleOutput 38 | ); 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Shutdown The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once Artisan has finished running, we will fire off the shutdown events 46 | | so that any final work may be done by the application before we shut 47 | | down the process. This is the last thing to happen to the request. 48 | | 49 | */ 50 | 51 | $kernel->terminate($input, $status); 52 | 53 | exit($status); 54 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | define('LARAVEL_START', microtime(true)); 11 | 12 | /* 13 | |-------------------------------------------------------------------------- 14 | | Register The Auto Loader 15 | |-------------------------------------------------------------------------- 16 | | 17 | | Composer provides a convenient, automatically generated class loader for 18 | | our application. We just need to utilize it! We'll simply require it 19 | | into the script here so that we don't have to worry about manual 20 | | loading any of our classes later on. It feels great to relax. 21 | | 22 | */ 23 | 24 | require __DIR__.'/../vendor/autoload.php'; 25 | 26 | /* 27 | |-------------------------------------------------------------------------- 28 | | Turn On The Lights 29 | |-------------------------------------------------------------------------- 30 | | 31 | | We need to illuminate PHP development, so let us turn on the lights. 32 | | This bootstraps the framework and gets it ready for use, then it 33 | | will load up this application so that we can run it and send 34 | | the responses back to the browser and delight our users. 35 | | 36 | */ 37 | 38 | $app = require_once __DIR__.'/../bootstrap/app.php'; 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Run The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once we have the application, we can handle the incoming request 46 | | through the kernel, and send the associated response back to 47 | | the client's browser allowing them to enjoy the creative 48 | | and wonderful application we have prepared for them. 49 | | 50 | */ 51 | 52 | $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); 53 | 54 | $response = $kernel->handle( 55 | $request = Illuminate\Http\Request::capture() 56 | ); 57 | 58 | $response->send(); 59 | 60 | $kernel->terminate($request, $response); 61 | -------------------------------------------------------------------------------- /database/migrations/2018_07_06_103920_create_about_content_tables.php: -------------------------------------------------------------------------------- 1 | increments('id'); 19 | $table->string('why_content',500); 20 | $table->string('key_point_1_title',100); 21 | $table->longText('key_point_1_content'); 22 | $table->string('key_point_2_title',100)->nullable(); 23 | $table->longText('key_point_2_content')->nullable(); 24 | $table->string('key_point_3_title',100)->nullable(); 25 | $table->longText('key_point_3_content')->nullable(); 26 | $table->string('key_point_4_title',100)->nullable(); 27 | $table->longText('key_point_4_content')->nullable(); 28 | $table->string('key_point_5_title',100)->nullable(); 29 | $table->longText('key_point_5_content')->nullable(); 30 | $table->string('about_us',500); 31 | $table->string('who_we_are',1000); 32 | $table->text('intro_video_embed_code'); 33 | $table->string('video_site_link',500)->nullable(); 34 | $table->timestamps(); 35 | $table->userstamps(); 36 | } 37 | ); 38 | Schema::create( 39 | 'about_sliders', function (Blueprint $table) { 40 | $table->increments('id'); 41 | $table->string('image'); 42 | $table->integer('order')->default(0); 43 | $table->timestamps(); 44 | $table->userstamps(); 45 | } 46 | ); 47 | } 48 | 49 | /** 50 | * Reverse the migrations. 51 | * 52 | * @return void 53 | */ 54 | public function down() 55 | { 56 | Schema::dropIfExists('about_contents'); 57 | Schema::dropIfExists('about_sliders'); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DRIVER', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Default Cloud Filesystem Disk 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Many applications store files both locally and in the cloud. For this 24 | | reason, you may specify a default "cloud" driver here. This driver 25 | | will be bound as the Cloud disk implementation in the container. 26 | | 27 | */ 28 | 29 | 'cloud' => env('FILESYSTEM_CLOUD', 's3'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Filesystem Disks 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here you may configure as many filesystem "disks" as you wish, and you 37 | | may even configure multiple disks of the same driver. Defaults have 38 | | been setup for each driver as an example of the required options. 39 | | 40 | | Supported Drivers: "local", "ftp", "sftp", "s3", "rackspace" 41 | | 42 | */ 43 | 44 | 'disks' => [ 45 | 46 | 'local' => [ 47 | 'driver' => 'local', 48 | 'root' => storage_path('app'), 49 | ], 50 | 51 | 'public' => [ 52 | 'driver' => 'local', 53 | 'root' => storage_path('app/public'), 54 | 'url' => env('APP_URL').'/storage', 55 | 'visibility' => 'public', 56 | ], 57 | 58 | 's3' => [ 59 | 'driver' => 's3', 60 | 'key' => env('AWS_ACCESS_KEY_ID'), 61 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 62 | 'region' => env('AWS_DEFAULT_REGION'), 63 | 'bucket' => env('AWS_BUCKET'), 64 | 'url' => env('AWS_URL'), 65 | ], 66 | 67 | ], 68 | 69 | ]; 70 | -------------------------------------------------------------------------------- /app/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | getStatusCode(); 58 | 59 | if(!env('APP_DEBUG', false)) { 60 | if (!$request->user() && AppHelper::isFrontendEnabled()) { 61 | $locale = Session::get('user_locale'); 62 | App::setLocale($locale); 63 | 64 | if ($statusCode == 404) { 65 | return response()->view('errors.front_404', [], 404); 66 | } 67 | 68 | if ($statusCode == 500) { 69 | 70 | return response()->view('errors.front_500', [], 500); 71 | } 72 | 73 | } 74 | } 75 | 76 | if ($request->user()) { 77 | if ($statusCode == 404) { 78 | return response()->view('errors.back_404', [], 404); 79 | } 80 | 81 | if ($statusCode == 401) { 82 | return response()->view('errors.back_401', [], 404); 83 | } 84 | } 85 | 86 | 87 | 88 | } 89 | 90 | 91 | 92 | return parent::render($request, $exception); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "prefrontend-dev": "rm -rf public/frontend", 5 | "frontend-dev": "npm run frontend-development", 6 | "frontend-development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js --env.mixfile=webpack.frontend.mix.js", 7 | "frontend-watch": "npm run frontend-development -- --watch", 8 | "frontend-prod": "npm run frontend-production", 9 | "frontend-production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js --env.mixfile=webpack.frontend.mix.js", 10 | "prebackend-dev": "rm -rf public/css public/js public/fonts public/images", 11 | "backend-dev": "npm run backend-development", 12 | "backend-development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js --env.mixfile=webpack.backend.mix.js", 13 | "backend-watch": "npm run backend-development -- --watch", 14 | "backend-prod": "npm run backend-production", 15 | "backend-production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js --env.mixfile=webpack.backend.mix.js" 16 | }, 17 | "devDependencies": { 18 | "axios": "^0.19.0", 19 | "browser-sync": "^2.26.7", 20 | "browser-sync-webpack-plugin": "^2.2.2", 21 | "cross-env": "^5.2.0", 22 | "laravel-mix": "^4.1.2", 23 | "purify-css": "^1.2.5", 24 | "purifycss-webpack": "^0.7.0", 25 | "resolve-url-loader": "2.3.1", 26 | "sass": "^1.22.7", 27 | "sass-loader": "^7.2.0", 28 | "script-loader": "^0.7.2", 29 | "vue-template-compiler": "^2.6.10" 30 | }, 31 | "dependencies": { 32 | "bootstrap": "^3.4.0", 33 | "bootstrap-colorpicker": "^2.5.3", 34 | "chart.js": "^2.7.3", 35 | "datatables.net": "^1.10.15", 36 | "datatables.net-bs": "^1.10.15", 37 | "datatables.net-responsive-bs": "^2.2.1", 38 | "fastclick": "^1.0.6", 39 | "font-awesome": "^4.7.0", 40 | "fs": "0.0.1-security", 41 | "icheck": "^1.0.2", 42 | "install": "^0.11.0", 43 | "jquery": "^3.4.1", 44 | "jquery-slimscroll": "^1.3.8", 45 | "jquery-ui": "^1.12.1", 46 | "jquery-validation": "^1.19.1", 47 | "moment": "^2.23.0", 48 | "popper.js": "^1.14.6", 49 | "remove": "^0.1.5", 50 | "select2": "^4.0.8", 51 | "sweetalert2": "^7.33.1", 52 | "toastr": "^2.1.4" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/Employee.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\User', 'user_id'); 51 | } 52 | 53 | 54 | public function getGenderAttribute($value) 55 | { 56 | return Arr::get(AppHelper::GENDER, $value); 57 | } 58 | 59 | public function getShiftAttribute($value) 60 | { 61 | return Arr::get(AppHelper::EMP_SHIFTS, $value); 62 | } 63 | public function setDutyStartAttribute($value) 64 | { 65 | if(strlen($value)){ 66 | $this->attributes['duty_start'] = Carbon::createFromFormat('h:i a', $value)->format('H:i:s'); 67 | } 68 | 69 | } 70 | 71 | public function getDutyStartAttribute($value) 72 | { 73 | if(!strlen($value)){ 74 | return null; 75 | } 76 | 77 | return Carbon::parse($value); 78 | 79 | } 80 | 81 | public function setDutyEndAttribute($value) 82 | { 83 | if(strlen($value)){ 84 | $this->attributes['duty_end'] = Carbon::createFromFormat('h:i a', $value)->format('H:i:s'); 85 | } 86 | 87 | } 88 | 89 | public function getDutyEndAttribute($value) 90 | { 91 | if(!strlen($value)){ 92 | return null; 93 | } 94 | return Carbon::parse($value); 95 | 96 | } 97 | 98 | 99 | public function getReligionAttribute($value) 100 | { 101 | return Arr::get(AppHelper::RELIGION, $value); 102 | } 103 | 104 | public function class() 105 | { 106 | return $this->hasMany('App\IClass', 'teacher_id'); 107 | } 108 | 109 | public function section() 110 | { 111 | return $this->hasMany('App\Section', 'teacher_id'); 112 | } 113 | 114 | public function role() 115 | { 116 | return $this->belongsTo('App\Role', 'role_id'); 117 | } 118 | 119 | 120 | } 121 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Cache Stores 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the cache "stores" for your application as 26 | | well as their drivers. You may even define multiple stores for the 27 | | same cache driver to group types of items stored in your caches. 28 | | 29 | */ 30 | 31 | 'stores' => [ 32 | 33 | 'apc' => [ 34 | 'driver' => 'apc', 35 | ], 36 | 37 | 'array' => [ 38 | 'driver' => 'array', 39 | ], 40 | 41 | 'database' => [ 42 | 'driver' => 'database', 43 | 'table' => 'cache', 44 | 'connection' => null, 45 | ], 46 | 47 | 'file' => [ 48 | 'driver' => 'file', 49 | 'path' => storage_path('framework/cache/data'), 50 | ], 51 | 52 | 'memcached' => [ 53 | 'driver' => 'memcached', 54 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 55 | 'sasl' => [ 56 | env('MEMCACHED_USERNAME'), 57 | env('MEMCACHED_PASSWORD'), 58 | ], 59 | 'options' => [ 60 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 61 | ], 62 | 'servers' => [ 63 | [ 64 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 65 | 'port' => env('MEMCACHED_PORT', 11211), 66 | 'weight' => 100, 67 | ], 68 | ], 69 | ], 70 | 71 | 'redis' => [ 72 | 'driver' => 'redis', 73 | 'connection' => 'default', 74 | ], 75 | 76 | ], 77 | 78 | /* 79 | |-------------------------------------------------------------------------- 80 | | Cache Key Prefix 81 | |-------------------------------------------------------------------------- 82 | | 83 | | When utilizing a RAM based store such as APC or Memcached, there might 84 | | be other applications utilizing the same cache. So, we'll specify a 85 | | value to get prefixed to all our keys so we can avoid collisions. 86 | | 87 | */ 88 | 89 | 'prefix' => env( 90 | 'CACHE_PREFIX', 91 | str_slug(env('APP_NAME', 'laravel'), '_').'_cache' 92 | ), 93 | 94 | ]; 95 | -------------------------------------------------------------------------------- /config/logging.php: -------------------------------------------------------------------------------- 1 | env('LOG_CHANNEL', 'stack'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Log Channels 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may configure the log channels for your application. Out of 26 | | the box, Laravel uses the Monolog PHP logging library. This gives 27 | | you a variety of powerful log handlers / formatters to utilize. 28 | | 29 | | Available Drivers: "single", "daily", "slack", "syslog", 30 | | "errorlog", "monolog", 31 | | "custom", "stack" 32 | | 33 | */ 34 | 35 | 'channels' => [ 36 | 'stack' => [ 37 | 'driver' => 'stack', 38 | 'channels' => ['single'], 39 | ], 40 | 41 | 'single' => [ 42 | 'driver' => 'single', 43 | 'path' => storage_path('logs/laravel.log'), 44 | 'level' => 'debug', 45 | ], 46 | 'smsLog' => [ 47 | 'driver' => 'single', 48 | 'path' => storage_path('logs/sms.log'), 49 | 'level' => 'debug', 50 | ], 51 | 'studentabsentlog' => [ 52 | 'driver' => 'single', 53 | 'path' => storage_path('logs/student-absent-job.log'), 54 | 'level' => 'debug', 55 | ], 56 | 'employeeabsentlog' => [ 57 | 'driver' => 'single', 58 | 'path' => storage_path('logs/employee-absent-job.log'), 59 | 'level' => 'debug', 60 | ], 61 | 'studentattendancelog' => [ 62 | 'driver' => 'single', 63 | 'path' => storage_path('logs/student-attendance-upload.log'), 64 | 'level' => 'debug', 65 | ], 66 | 'employeeattendancelog' => [ 67 | 'driver' => 'single', 68 | 'path' => storage_path('logs/employee-attendance-upload.log'), 69 | 'level' => 'debug', 70 | ], 71 | 'daily' => [ 72 | 'driver' => 'daily', 73 | 'path' => storage_path('logs/laravel.log'), 74 | 'level' => 'debug', 75 | 'days' => 7, 76 | ], 77 | 78 | 'slack' => [ 79 | 'driver' => 'slack', 80 | 'url' => env('LOG_SLACK_WEBHOOK_URL'), 81 | 'username' => 'Laravel Log', 82 | 'emoji' => ':boom:', 83 | 'level' => 'critical', 84 | ], 85 | 86 | 'stderr' => [ 87 | 'driver' => 'monolog', 88 | 'handler' => StreamHandler::class, 89 | 'with' => [ 90 | 'stream' => 'php://stderr', 91 | ], 92 | ], 93 | 94 | 'syslog' => [ 95 | 'driver' => 'syslog', 96 | 'level' => 'debug', 97 | ], 98 | 99 | 'errorlog' => [ 100 | 'driver' => 'errorlog', 101 | 'level' => 'debug', 102 | ], 103 | ], 104 | 105 | ]; 106 | -------------------------------------------------------------------------------- /webpack.backend.mix.js: -------------------------------------------------------------------------------- 1 | let mix = require('laravel-mix'); 2 | const webpack = require('webpack'); 3 | 4 | /* 5 | |-------------------------------------------------------------------------- 6 | | Mix Back Panel Asset Management 7 | |-------------------------------------------------------------------------- 8 | | 9 | | Mix provides a clean, fluent API for defining some Webpack build steps 10 | | for your Laravel application. By default, we are compiling the Sass 11 | | file for the application as well as bundling up all the JS files. 12 | | 13 | */ 14 | 15 | mix.webpackConfig({ 16 | plugins: [ 17 | // Ignore all locale files of moment.js 18 | // new webpack.IgnorePlugin( 19 | // /^\.\/locale$/, /moment$/, 20 | // ) 21 | new webpack.ContextReplacementPlugin( 22 | // The path to directory which should be handled by this plugin 23 | /moment[\/\\]locale/, 24 | /select2[\/\\]dist[\/\\]js[\/\\]i18n/, 25 | ) 26 | ] 27 | }); 28 | 29 | mix.js('resources/assets/backend/js/app.js', 'public/js') 30 | .js([ 31 | 'resources/assets/backend/js/site-dashboard.js', 32 | ], 'public/js/site-dashboard.js') 33 | .js([ 34 | 'resources/assets/backend/js/dashboard.js', 35 | ], 'public/js/dashboard.js') 36 | .js([ 37 | 'resources/assets/backend/js/adminlte.js', 38 | 'resources/assets/backend/js/theme_settings.js', 39 | 'resources/assets/backend/js/bootstrap-datetimepicker.min.js', 40 | 'resources/assets/backend/js/bootstrap-toggle.min.js', 41 | ], 'public/js/theme.js') 42 | .extract([ 43 | 'jquery', 'bootstrap', 'icheck', 'jquery-validation', 'jquery-slimscroll', 'fastclick', 44 | 'datatables.net', 'datatables.net-bs', 'datatables.net-responsive-bs' 45 | ]) 46 | .sass('resources/assets/backend/sass/app.scss', 'public/css') 47 | .sass('resources/assets/backend/sass/print.scss', 'public/css') 48 | .sass('resources/assets/backend/sass/vendor.scss', 'public/css') 49 | .sass('resources/assets/backend/sass/colorpicker.scss', 'public/css') 50 | .sass('resources/assets/backend/sass/report.scss', 'public/css') 51 | .js([ 52 | 'resources/assets/backend/js/colorpicker.js', 53 | ], 'public/js/colorpicker.js') 54 | .styles([ 55 | 'resources/assets/backend/css/AdminLTE.css', 56 | 'resources/assets/backend/css/_all-skins.css', 57 | 'resources/assets/backend/css/bootstrap3-wysihtml5.min.css', 58 | 'resources/assets/backend/css/bootstrap-datetimepicker.min.css', 59 | 'resources/assets/backend/css/bootstrap-toggle.min.css' 60 | ], 'public/css/theme.css') 61 | .styles('resources/assets/backend/css/site-dashboard.css', 'public/css/site-dashboard.css') 62 | .styles('resources/assets/backend/css/pace.css', 'public/css/pace.css') 63 | .autoload({ 64 | jquery: ['$', 'window.jQuery', 'jQuery', 'jquery'], 65 | moment: ['window.moment', 'moment'], 66 | }); 67 | 68 | 69 | mix.options({ 70 | processCssUrls: true, 71 | // uglify: {}, 72 | purifyCss: false, 73 | // purifyCss: {}, 74 | clearConsole: false 75 | }); 76 | 77 | 78 | // copy non processing files to public path 79 | mix.copy('resources/assets/backend/js/bootstrap3-wysihtml5.all.min.js', 'public/js/editor.js'); 80 | mix.copy('resources/assets/backend/js/pace.js', 'public/js/pace.js'); 81 | mix.copyDirectory('resources/assets/backend/images', 'public/images'); 82 | 83 | 84 | 85 | if (mix.inProduction()) { 86 | mix.version(); 87 | mix.sourceMaps(); 88 | } 89 | 90 | mix.browserSync({ 91 | proxy: 'l5.school.test' 92 | }); 93 | -------------------------------------------------------------------------------- /config/auth.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'guard' => 'web', 18 | 'passwords' => 'users', 19 | ], 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Authentication Guards 24 | |-------------------------------------------------------------------------- 25 | | 26 | | Next, you may define every authentication guard for your application. 27 | | Of course, a great default configuration has been defined for you 28 | | here which uses session storage and the Eloquent user provider. 29 | | 30 | | All authentication drivers have a user provider. This defines how the 31 | | users are actually retrieved out of your database or other storage 32 | | mechanisms used by this application to persist your user's data. 33 | | 34 | | Supported: "session", "token" 35 | | 36 | */ 37 | 38 | 'guards' => [ 39 | 'web' => [ 40 | 'driver' => 'session', 41 | 'provider' => 'users', 42 | ], 43 | 44 | 'api' => [ 45 | 'driver' => 'token', 46 | 'provider' => 'users', 47 | ], 48 | ], 49 | 50 | /* 51 | |-------------------------------------------------------------------------- 52 | | User Providers 53 | |-------------------------------------------------------------------------- 54 | | 55 | | All authentication drivers have a user provider. This defines how the 56 | | users are actually retrieved out of your database or other storage 57 | | mechanisms used by this application to persist your user's data. 58 | | 59 | | If you have multiple user tables or models you may configure multiple 60 | | sources which represent each model / table. These sources may then 61 | | be assigned to any extra authentication guards you have defined. 62 | | 63 | | Supported: "database", "eloquent" 64 | | 65 | */ 66 | 67 | 'providers' => [ 68 | 'users' => [ 69 | 'driver' => 'cache-user', 70 | 'model' => App\User::class, 71 | ], 72 | 73 | // 'users' => [ 74 | // 'driver' => 'database', 75 | // 'table' => 'users', 76 | // ], 77 | ], 78 | 79 | /* 80 | |-------------------------------------------------------------------------- 81 | | Resetting Passwords 82 | |-------------------------------------------------------------------------- 83 | | 84 | | You may specify multiple password reset configurations if you have more 85 | | than one user table or model in the application and you want to have 86 | | separate password reset settings based on the specific user types. 87 | | 88 | | The expire time is the number of minutes that the reset token should be 89 | | considered valid. This security feature keeps tokens short-lived so 90 | | they have less time to be guessed. You may change this as needed. 91 | | 92 | */ 93 | 94 | 'passwords' => [ 95 | 'users' => [ 96 | 'provider' => 'users', 97 | 'table' => 'password_resets', 98 | 'expire' => 60, 99 | ], 100 | ], 101 | 102 | ]; 103 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hrshadhin/school-management-system", 3 | "version": "2.0", 4 | "description": "Another School Management System build with laravel", 5 | "keywords": [ 6 | "School", 7 | "Management", 8 | "Web", 9 | "Application", 10 | "Admission", 11 | "Attendance", 12 | "Exam", 13 | "Result", 14 | "Fees", 15 | "Accounting", 16 | "Library", 17 | "Hostel", 18 | "Employees" 19 | ], 20 | "type": "project", 21 | "license": "AGPL-3.0-or-later", 22 | "authors": [ 23 | { 24 | "name": "H.R.Shadhin", 25 | "email": "dev@hrshadhin.me", 26 | "homepage": "http://hrshadhin.me", 27 | "role": "Developer" 28 | } 29 | ], 30 | "homepage": "http://school.hrshadhin.me", 31 | "readme": "./readme.xml", 32 | "time": "2018-05-20", 33 | "support": { 34 | "email": "hello@hrshadhin.me", 35 | "issues": "https://github.com/hrshadhin/school-management-system/issues", 36 | "wiki": "https://github.com/hrshadhin/school-management-system/wiki", 37 | "source": "https://github.com/hrshadhin/school-management-system" 38 | }, 39 | "repositories": [ 40 | { 41 | "url": "https://github.com/hrshadhin/laravel-userstamps.git", 42 | "type": "git" 43 | } 44 | ], 45 | "require": { 46 | "php": "^7.1.3", 47 | "barryvdh/laravel-dompdf": "^0.8.4", 48 | "bonecms/laravel-captcha": "^2.1", 49 | "fideloper/proxy": "^4.0", 50 | "guzzlehttp/guzzle": "^6.3", 51 | "hrshadhin/laravel-userstamps": "dev-master", 52 | "laravel/framework": "5.8.*", 53 | "laravel/tinker": "^1.0", 54 | "laravelcollective/html": "^5.4.0", 55 | "maatwebsite/excel": "^3.1", 56 | "picqer/php-barcode-generator": "^0.3.0", 57 | "rap2hpoutre/laravel-log-viewer": "^1.2", 58 | "twilio/sdk": "^5.28" 59 | }, 60 | "require-dev": { 61 | "barryvdh/laravel-debugbar": "^3.2", 62 | "filp/whoops": "^2.0", 63 | "fzaninotto/faker": "^1.4", 64 | "mockery/mockery": "^1.0", 65 | "nunomaduro/collision": "^2.0", 66 | "phpunit/phpunit": "^7.0" 67 | }, 68 | "autoload": { 69 | "classmap": [ 70 | "database/seeds", 71 | "database/factories" 72 | ], 73 | "psr-4": { 74 | "App\\": "app/" 75 | } 76 | }, 77 | "autoload-dev": { 78 | "psr-4": { 79 | "Tests\\": "tests/" 80 | } 81 | }, 82 | "extra": { 83 | "laravel": { 84 | "dont-discover": [] 85 | } 86 | }, 87 | "scripts": { 88 | "post-install-cmd": [ 89 | "php artisan config:clear", 90 | "php artisan cache:clear", 91 | "php artisan route:clear", 92 | "php artisan view:clear", 93 | "php artisan clear-compiled", 94 | "php artisan package:discover" 95 | ], 96 | "post-update-cmd": [ 97 | "php artisan config:clear", 98 | "php artisan cache:clear", 99 | "php artisan route:clear", 100 | "php artisan view:clear", 101 | "php artisan clear-compiled", 102 | "php artisan package:discover" 103 | ], 104 | "post-create-project-cmd": [ 105 | "php -r \"copy('.env.example', '.env');\"", 106 | "php artisan key:generate" 107 | ] 108 | }, 109 | "config": { 110 | "preferred-install": "dist", 111 | "sort-packages": true, 112 | "optimize-autoloader": true 113 | }, 114 | "minimum-stability": "dev", 115 | "prefer-stable": true 116 | } 117 | -------------------------------------------------------------------------------- /public/svg/404.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config/database.php: -------------------------------------------------------------------------------- 1 | env('DB_CONNECTION', 'mysql'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Database Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here are each of the database connections setup for your application. 24 | | Of course, examples of configuring each database platform that is 25 | | supported by Laravel is shown below to make development simple. 26 | | 27 | | 28 | | All database work in Laravel is done through the PHP PDO facilities 29 | | so make sure you have the driver for your particular database of 30 | | choice installed on your machine before you begin development. 31 | | For long key size replace utf8mb4 to utf8 for both charset and collation 32 | | 33 | */ 34 | 35 | 'connections' => [ 36 | 37 | 'sqlite' => [ 38 | 'driver' => 'sqlite', 39 | 'database' => env('DB_DATABASE', database_path('database.sqlite')), 40 | 'prefix' => '', 41 | ], 42 | 43 | 'mysql' => [ 44 | 'driver' => 'mysql', 45 | 'host' => env('DB_HOST', '127.0.0.1'), 46 | 'port' => env('DB_PORT', '3306'), 47 | 'database' => env('DB_DATABASE', 'forge'), 48 | 'username' => env('DB_USERNAME', 'forge'), 49 | 'password' => env('DB_PASSWORD', ''), 50 | 'unix_socket' => env('DB_SOCKET', ''), 51 | 'charset' => 'utf8', 52 | 'collation' => 'utf8_unicode_ci', 53 | 'prefix' => '', 54 | 'strict' => true, 55 | 'engine' => null, 56 | ], 57 | 58 | 'pgsql' => [ 59 | 'driver' => 'pgsql', 60 | 'host' => env('DB_HOST', '127.0.0.1'), 61 | 'port' => env('DB_PORT', '5432'), 62 | 'database' => env('DB_DATABASE', 'forge'), 63 | 'username' => env('DB_USERNAME', 'forge'), 64 | 'password' => env('DB_PASSWORD', ''), 65 | 'charset' => 'utf8', 66 | 'prefix' => '', 67 | 'schema' => 'public', 68 | 'sslmode' => 'prefer', 69 | ], 70 | 71 | 'sqlsrv' => [ 72 | 'driver' => 'sqlsrv', 73 | 'host' => env('DB_HOST', 'localhost'), 74 | 'port' => env('DB_PORT', '1433'), 75 | 'database' => env('DB_DATABASE', 'forge'), 76 | 'username' => env('DB_USERNAME', 'forge'), 77 | 'password' => env('DB_PASSWORD', ''), 78 | 'charset' => 'utf8', 79 | 'prefix' => '', 80 | ], 81 | 82 | ], 83 | 84 | /* 85 | |-------------------------------------------------------------------------- 86 | | Migration Repository Table 87 | |-------------------------------------------------------------------------- 88 | | 89 | | This table keeps track of all the migrations that have already run for 90 | | your application. Using this information, we can determine which of 91 | | the migrations on disk haven't actually been run in the database. 92 | | 93 | */ 94 | 95 | 'migrations' => 'migrations', 96 | 97 | /* 98 | |-------------------------------------------------------------------------- 99 | | Redis Databases 100 | |-------------------------------------------------------------------------- 101 | | 102 | | Redis is an open source, fast, and advanced key-value store that also 103 | | provides a richer set of commands than a typical key-value systems 104 | | such as APC or Memcached. Laravel makes it easy to dig right in. 105 | | 106 | */ 107 | 108 | 'redis' => [ 109 | 110 | 'client' => 'predis', 111 | 112 | 'default' => [ 113 | 'host' => env('REDIS_HOST', '127.0.0.1'), 114 | 'password' => env('REDIS_PASSWORD', null), 115 | 'port' => env('REDIS_PORT', 6379), 116 | 'database' => 0, 117 | ], 118 | 119 | ], 120 | 121 | ]; 122 | -------------------------------------------------------------------------------- /public/svg/503.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /routes/website.php: -------------------------------------------------------------------------------- 1 | 'Frontend', 'middleware' => ['frontend']], function () { 17 | Route::get('/', 'HomeController@home')->name('home'); 18 | Route::post('site/subscribe','HomeController@subscribe') 19 | ->name('site.subscribe'); 20 | Route::get('/class', 'HomeController@classProfile')->name('site.class_profile'); 21 | Route::get('/class-details/{name}', 'HomeController@classDetails')->name('site.class_details'); 22 | Route::get('/teachers', 'HomeController@teacherProfile')->name('site.teacher_profile'); 23 | Route::get('/events', 'HomeController@event')->name('site.event'); 24 | Route::get('/events-details/{slug}', 'HomeController@eventDetails')->name('site.event_details'); 25 | Route::get('/gallery', 'HomeController@gallery')->name('site.gallery_view'); 26 | Route::get('/contact-us', 'HomeController@contactUs')->name('site.contact_us_view'); 27 | Route::post('/contact-us', 'HomeController@contactUs')->name('site.contact_us_form'); 28 | Route::get('/faq', 'HomeController@faq')->name('site.faq_view'); 29 | Route::get('/timeline', 'HomeController@timeline')->name('site.timeline_view'); 30 | 31 | }); 32 | 33 | //change website locale 34 | Route::get( 35 | '/set-locale/{lang}', function ($lang) { 36 | //set user wanted locale to session 37 | Session::put('user_locale', $lang); 38 | return redirect()->back(); 39 | } 40 | )->name('setLocale'); 41 | 42 | Route::group( 43 | ['namespace' => 'Backend', 'middleware' => ['auth','permission']], function () { 44 | 45 | /** 46 | * Website contents routes 47 | */ 48 | 49 | Route::get('/site/dashboard', 'SiteController@dashboard') 50 | ->name('site.dashboard'); 51 | Route::resource('slider','SliderController'); 52 | Route::get('/site/about-content', 'SiteController@aboutContent') 53 | ->name('site.about_content'); 54 | Route::post('/site/about-content', 'SiteController@aboutContent') 55 | ->name('site.about_content'); 56 | Route::get('site/about-content/images','SiteController@aboutContentImage') 57 | ->name('site.about_content_image'); 58 | Route::post('site/about-content/images','SiteController@aboutContentImage') 59 | ->name('site.about_content_image'); 60 | Route::post('site/about-content/images/{id}','SiteController@aboutContentImageDelete') 61 | ->name('site.about_content_image_delete'); 62 | Route::get('site/service','SiteController@serviceContent') 63 | ->name('site.service'); 64 | Route::post('site/service','SiteController@serviceContent') 65 | ->name('site.service'); 66 | Route::get('site/statistic','SiteController@statisticContent') 67 | ->name('site.statistic'); 68 | Route::post('site/statistic','SiteController@statisticContent') 69 | ->name('site.statistic'); 70 | 71 | Route::get('site/testimonial','SiteController@testimonialIndex') 72 | ->name('site.testimonial'); 73 | Route::post('site/testimonial','SiteController@testimonialIndex') 74 | ->name('site.testimonial_delete'); 75 | Route::get('site/testimonial/create','SiteController@testimonialCreate') 76 | ->name('site.testimonial_create'); 77 | Route::post('site/testimonial/create','SiteController@testimonialCreate') 78 | ->name('site.testimonial_create'); 79 | 80 | Route::get('site/subscribe','SiteController@subscribe') 81 | ->name('site.subscribe'); 82 | 83 | Route::resource('class_profile','ClassProfileController'); 84 | Route::resource('teacher_profile','TeacherProfileController'); 85 | Route::resource('event','EventController'); 86 | Route::get('site/gallery','SiteController@gallery') 87 | ->name('site.gallery'); 88 | Route::get('site/gallery/add-image','SiteController@galleryAdd') 89 | ->name('site.gallery_image'); 90 | Route::post('site/gallery/add-image','SiteController@galleryAdd') 91 | ->name('site.gallery_image'); 92 | Route::post('site/gallery/delete-images/{id}','SiteController@galleryDelete') 93 | ->name('site.gallery_image_delete'); 94 | Route::get('site/contact-us','SiteController@contactUs') 95 | ->name('site.contact_us'); 96 | Route::post('site/contact-us','SiteController@contactUs') 97 | ->name('site.contact_us'); 98 | Route::get('site/fqa','SiteController@faq') 99 | ->name('site.faq'); 100 | Route::post('site/fqa','SiteController@faq') 101 | ->name('site.faq'); 102 | Route::post('site/faq/{id}','SiteController@faqDelete') 103 | ->name('site.faq_delete'); 104 | Route::get('site/timeline','SiteController@timeline') 105 | ->name('site.timeline'); 106 | Route::post('site/timeline','SiteController@timeline') 107 | ->name('site.timeline'); 108 | Route::post('site/timeline/{id}','SiteController@timelineDelete') 109 | ->name('site.timeline_delete'); 110 | Route::get('site/settings','SiteController@settings') 111 | ->name('site.settings'); 112 | Route::post('site/settings','SiteController@settings') 113 | ->name('site.settings'); 114 | Route::get('site/analytics','SiteController@analytics') 115 | ->name('site.analytics'); 116 | Route::post('site/analytics','SiteController@analytics') 117 | ->name('site.analytics'); 118 | }); 119 | 120 | 121 | -------------------------------------------------------------------------------- /public/svg/403.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # school Management System (SMS) 2 | Another School Management System build with laravel and PHP 7. 3 | 4 | [![Codeship Status for hrshadhin/school-management-system](https://app.codeship.com/projects/09010350-b97f-0136-1477-5a7589b245e6/status?branch=master)](https://app.codeship.com/projects/312233) 5 | [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) 6 | [![Known Vulnerabilities](https://snyk.io/test/github/hrshadhin/school-management-system/badge.svg?targetFile=package.json)](https://snyk.io/test/github/hrshadhin/school-management-system?targetFile=package.json) 7 | 8 | 9 | :loudspeaker: 10 | **Notic:** Now its version [v2.0](https://github.com/hrshadhin/school-management-system/releases/tag/v2.0) (community edition) 11 | . If you need PHP 5 support then use version [v1.0](https://github.com/hrshadhin/school-management-system/releases/tag/v1.0). 12 | For Enterprise edition checkout here [EE](https://github.com/hrshadhin/school-management-system/tree/empty) 13 | 14 | # Join Our Discord Server 15 | :mega:[CloudSchool](https://discord.gg/7rXyuu8):mega: 16 | 17 | # Features 18 | | Community Edition | Enterprise Edition | 19 | |-----------------------|:-------------------------:| 20 | | Academic Year manage | Academic Year manage | 21 | | Academic Calendar Setup | Academic Calendar Setup | 22 | | Institute Setup | Institute Setup | 23 | | Class & Section Manage | Class & Section Manage | 24 | | Subject & Teacher Manage | Subject & Teacher Manage | 25 | | Student Admission | Student Admission | 26 | | Student Attendance | Student Attendance | 27 | | Exam & Grading Rules | Exam & Grading Rules | 28 | | Makrs & Result | Easy Makrs Entry & Result Manage | 29 | | Employees Manage | Employees Manage | 30 | | Employees Attendance | Employees Attendance | 31 | | Employees Leave | Employees Leave | 32 | | Employees Work Outside | Employees Work Outside | 33 | | SMS Gateway Setup | SMS Gateway Setup | 34 | | Email & SMS Templating | Email & SMS Templating | 35 | | Attendance notification email/sms | Attendance notification email/sms | 36 | | Id Card templates Manage | Id Card templates Manage | 37 | | Employee & Student id card print | Employee & Student id card print | 38 | | User & Role manage with permision grid(ACL) | User & Role manage with permision grid(ACL) | 39 | | User wise Dashboard | User wise Dashboard 40 | | Report Settings | Report Settings | 41 | | Only 5 Reports | **40+** Reports | 42 | | Dynamic Front Website | Dynamic Front Website | 43 | | Website Management Panel | Website Management Panel 44 | | Photo Gallery | Photo Gallery | 45 | | Event Manage | Event Manage | 46 | | Google Analytics | Google Analytics | 47 | | User Notification | User Notification | 48 | | | Online Admission | 49 | | | Online Admit Card & Payslip | 50 | | | Student Promotion | 51 | | | Notice Board | 52 | | | Student & Employee Id card bulk/mass print | 53 | | | Account Manage | 54 | | | Budget Manage | 55 | | | Account Heads | 56 | | | Student Invoice | 57 | | | Income / Expense Manage | 58 | | | Payroll | 59 | | | Salary Template | 60 | | | Employee Salary Payment | 61 | | | Hostel & Collection Manage | 62 | | | Library Manage | 63 | | | Issue book and fine collection | 64 | | | Academic Calendar Print | 65 | | | Bulk SMS and Email Sending | 66 | | | **40+** Reports | 67 | 68 | # Installation and use 69 | 70 | **Dependency** 71 | - PHP >= 7.1.3 72 | - OpenSSL PHP Extension 73 | - PDO PHP Extension 74 | - Mbstring PHP Extension 75 | - Tokenizer PHP Extension 76 | - XML PHP Extension 77 | - Ctype PHP Extension 78 | - JSON PHP Extension 79 | - [hrshadhin/laravel-userstamps](https://github.com/hrshadhin/laravel-userstamps.git) 80 | - NodeJS, npm, webpack 81 | 82 | 83 | ``` 84 | $ git clone https://github.com/hrshadhin/school-management-system.git 85 | 86 | ``` 87 | ``` 88 | $ cd school-management-system 89 | ``` 90 | ``` 91 | $ cp .env.example .env 92 | ``` 93 | **Change configuration according to your need in ".env" file and create Database** 94 | ``` 95 | $ composer install 96 | ``` 97 | ``` 98 | $ php artisan migrate 99 | ``` 100 | ``` 101 | $ php artisan db:seed 102 | ``` 103 | **Load demo data** 104 | ``` 105 | $ php artisan db:seed --class DemoSiteDataSeeder 106 | ``` 107 | ``` 108 | $ php artisan db:seed --class DemoAppDataSeeder 109 | ``` 110 | **Clear cache** 111 | ``` 112 | $ sudo php artisan cache:clear 113 | ``` 114 | ``` 115 | $ npm install 116 | ``` 117 | ``` 118 | $ npm run backend-prod 119 | ``` 120 | ``` 121 | $ npm run frontend-prod 122 | ``` 123 | ``` 124 | $ php artisan storage:link 125 | ``` 126 | ``` 127 | $ php artisan serve 128 | ``` 129 | Now visit and login: [http://localhost:8000](http://localhost:8000) \ 130 | username: admin\ 131 | password: demo123 132 | 133 | **Demo(Community Edition)**\ 134 | website url: http://sms.hrshadhin.me \ 135 | app login: http://sms.hrshadhin.me/login \ 136 | username: admin\ 137 | password: demo123 138 | 139 | **Demo(Enterprise Edition)**\ 140 | website url: http://cloudschoolbd.com \ 141 | app login: http://cloudschoolbd.com/login \ 142 | username: admin\ 143 | password: demo123 144 | 145 | **N.B:** 146 | - For sms and email processing you need to run laravel queue worker. `bin` folder has supervisor config for start queue worker with supervisor. 147 | 148 | # Screenshot 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | # Security Vulnerabilities 162 | 163 | If you discover a security vulnerability within SMS, please send an e-mail to H.R. Shadhin via [dev@hrshadhin.me](mailto:dev@hrshadhin.me). All security vulnerabilities will be promptly addressed. 164 | 165 | # License 166 | 167 | SMS is open-sourced software licensed under the AGPL-3.0 license. Frameworks and libraries has it own licensed. 168 | -------------------------------------------------------------------------------- /config/app.php: -------------------------------------------------------------------------------- 1 | env('APP_NAME', 'sms'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Application Environment 21 | |-------------------------------------------------------------------------- 22 | | 23 | | This value determines the "environment" your application is currently 24 | | running in. This may determine how you prefer to configure various 25 | | services your application utilizes. Set this in your ".env" file. 26 | | 27 | */ 28 | 29 | 'env' => env('APP_ENV', 'production'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Application Debug Mode 34 | |-------------------------------------------------------------------------- 35 | | 36 | | When your application is in debug mode, detailed error messages with 37 | | stack traces will be shown on every error that occurs within your 38 | | application. If disabled, a simple generic error page is shown. 39 | | 40 | */ 41 | 42 | 'debug' => env('APP_DEBUG', false), 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Application URL 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This URL is used by the console to properly generate URLs when using 50 | | the Artisan command line tool. You should set this to the root of 51 | | your application so that it is used when running Artisan tasks. 52 | | 53 | */ 54 | 55 | 'url' => env('APP_URL', 'http://school.hrshadhin.me'), 56 | 57 | /* 58 | |-------------------------------------------------------------------------- 59 | | Application Timezone 60 | |-------------------------------------------------------------------------- 61 | | 62 | | Here you may specify the default timezone for your application, which 63 | | will be used by the PHP date and date-time functions. We have gone 64 | | ahead and set this to a sensible default for you out of the box. 65 | | 66 | */ 67 | 68 | 'timezone' => env('APP_TIMEZONE', 'Asia/Dhaka'), 69 | 70 | /* 71 | |-------------------------------------------------------------------------- 72 | | Application Locale Configuration 73 | |-------------------------------------------------------------------------- 74 | | 75 | | The application locale determines the default locale that will be used 76 | | by the translation service provider. You are free to set this value 77 | | to any of the locales which will be supported by the application. 78 | | 79 | */ 80 | 81 | 'locale' => env('APP_LOCALE', 'en'), 82 | 83 | /* 84 | |-------------------------------------------------------------------------- 85 | | Application Fallback Locale 86 | |-------------------------------------------------------------------------- 87 | | 88 | | The fallback locale determines the locale to use when the current one 89 | | is not available. You may change the value to correspond to any of 90 | | the language folders that are provided through your application. 91 | | 92 | */ 93 | 94 | 'fallback_locale' => 'en', 95 | 96 | /* 97 | |-------------------------------------------------------------------------- 98 | | Encryption Key 99 | |-------------------------------------------------------------------------- 100 | | 101 | | This key is used by the Illuminate encrypter service and should be set 102 | | to a random, 32 character string, otherwise these encrypted strings 103 | | will not be safe. Please do this before deploying an application! 104 | | 105 | */ 106 | 107 | 'key' => env('APP_KEY'), 108 | 109 | 'cipher' => 'AES-256-CBC', 110 | 111 | /* 112 | |-------------------------------------------------------------------------- 113 | | Autoloaded Service Providers 114 | |-------------------------------------------------------------------------- 115 | | 116 | | The service providers listed here will be automatically loaded on the 117 | | request to your application. Feel free to add your own services to 118 | | this array to grant expanded functionality to your applications. 119 | | 120 | */ 121 | 122 | 'providers' => [ 123 | 124 | /* 125 | * Laravel Framework Service Providers... 126 | */ 127 | Illuminate\Auth\AuthServiceProvider::class, 128 | Illuminate\Broadcasting\BroadcastServiceProvider::class, 129 | Illuminate\Bus\BusServiceProvider::class, 130 | Illuminate\Cache\CacheServiceProvider::class, 131 | Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, 132 | Illuminate\Cookie\CookieServiceProvider::class, 133 | Illuminate\Database\DatabaseServiceProvider::class, 134 | Illuminate\Encryption\EncryptionServiceProvider::class, 135 | Illuminate\Filesystem\FilesystemServiceProvider::class, 136 | Illuminate\Foundation\Providers\FoundationServiceProvider::class, 137 | Illuminate\Hashing\HashServiceProvider::class, 138 | Illuminate\Mail\MailServiceProvider::class, 139 | Illuminate\Notifications\NotificationServiceProvider::class, 140 | Illuminate\Pagination\PaginationServiceProvider::class, 141 | Illuminate\Pipeline\PipelineServiceProvider::class, 142 | Illuminate\Queue\QueueServiceProvider::class, 143 | Illuminate\Redis\RedisServiceProvider::class, 144 | Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, 145 | Illuminate\Session\SessionServiceProvider::class, 146 | Illuminate\Translation\TranslationServiceProvider::class, 147 | Illuminate\Validation\ValidationServiceProvider::class, 148 | Illuminate\View\ViewServiceProvider::class, 149 | 150 | /* 151 | * Package Service Providers... 152 | */ 153 | 154 | /* 155 | * Application Service Providers... 156 | */ 157 | App\Providers\AppServiceProvider::class, 158 | App\Providers\AuthServiceProvider::class, 159 | // App\Providers\BroadcastServiceProvider::class, 160 | App\Providers\EventServiceProvider::class, 161 | App\Providers\RouteServiceProvider::class, 162 | App\Providers\ComposerServiceProvider::class, 163 | App\Providers\PermissionsServiceProvider::class, 164 | // Hrshadhin\Userstamps\UserstampsServiceProvider::class, 165 | Collective\Html\HtmlServiceProvider::class, 166 | 167 | 168 | ], 169 | 170 | /* 171 | |-------------------------------------------------------------------------- 172 | | Class Aliases 173 | |-------------------------------------------------------------------------- 174 | | 175 | | This array of class aliases will be registered when this application 176 | | is started. However, feel free to register as many as you wish as 177 | | the aliases are "lazy" loaded so they don't hinder performance. 178 | | 179 | */ 180 | 181 | 'aliases' => [ 182 | 183 | 'App' => Illuminate\Support\Facades\App::class, 184 | 'Artisan' => Illuminate\Support\Facades\Artisan::class, 185 | 'Auth' => Illuminate\Support\Facades\Auth::class, 186 | 'Blade' => Illuminate\Support\Facades\Blade::class, 187 | 'Broadcast' => Illuminate\Support\Facades\Broadcast::class, 188 | 'Bus' => Illuminate\Support\Facades\Bus::class, 189 | 'Cache' => Illuminate\Support\Facades\Cache::class, 190 | 'Config' => Illuminate\Support\Facades\Config::class, 191 | 'Cookie' => Illuminate\Support\Facades\Cookie::class, 192 | 'Crypt' => Illuminate\Support\Facades\Crypt::class, 193 | 'DB' => Illuminate\Support\Facades\DB::class, 194 | 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 195 | 'Event' => Illuminate\Support\Facades\Event::class, 196 | 'File' => Illuminate\Support\Facades\File::class, 197 | 'Gate' => Illuminate\Support\Facades\Gate::class, 198 | 'Hash' => Illuminate\Support\Facades\Hash::class, 199 | 'Lang' => Illuminate\Support\Facades\Lang::class, 200 | 'Log' => Illuminate\Support\Facades\Log::class, 201 | 'Mail' => Illuminate\Support\Facades\Mail::class, 202 | 'Notification' => Illuminate\Support\Facades\Notification::class, 203 | 'Password' => Illuminate\Support\Facades\Password::class, 204 | 'Queue' => Illuminate\Support\Facades\Queue::class, 205 | 'Redirect' => Illuminate\Support\Facades\Redirect::class, 206 | 'Redis' => Illuminate\Support\Facades\Redis::class, 207 | 'Request' => Illuminate\Support\Facades\Request::class, 208 | 'Response' => Illuminate\Support\Facades\Response::class, 209 | 'Route' => Illuminate\Support\Facades\Route::class, 210 | 'Schema' => Illuminate\Support\Facades\Schema::class, 211 | 'Session' => Illuminate\Support\Facades\Session::class, 212 | 'Storage' => Illuminate\Support\Facades\Storage::class, 213 | 'URL' => Illuminate\Support\Facades\URL::class, 214 | 'Validator' => Illuminate\Support\Facades\Validator::class, 215 | 'View' => Illuminate\Support\Facades\View::class, 216 | 'AppHelper' => App\Http\Helpers\AppHelper::class, 217 | 'Form' => Collective\Html\FormFacade::class, 218 | 'Html' => Collective\Html\HtmlFacade::class, 219 | 220 | ], 221 | 222 | ]; 223 | -------------------------------------------------------------------------------- /app/Console/Commands/SeedEmployeeAttendance.php: -------------------------------------------------------------------------------- 1 | where('is_imported','=',0) 60 | ->orderBy('created_at', 'DESC') 61 | ->first(); 62 | 63 | if(!$pendingFile){ 64 | Log::channel('employeeattendancelog')->info('No pending task!'); 65 | return false; 66 | } 67 | 68 | //set file format 69 | $this->fileFormatType = intval($pendingFile->file_format); 70 | $this->createdBy = $pendingFile->created_by; 71 | 72 | $filePath = storage_path('app/employee-attendance/').$pendingFile->file_name; 73 | if(!file_exists($filePath)){ 74 | Log::channel('employeeattendancelog')->critical('File not found! '.$pendingFile->file_name); 75 | return false; 76 | } 77 | 78 | //data imported class 79 | $presentStudentsByClass = []; 80 | 81 | //process present attendance student 82 | try{ 83 | 84 | $dateWiseData = []; 85 | $totalValidRows = 0; 86 | //open the file and get line and process it 87 | $linecount = 0; 88 | $handle = fopen($filePath, "r"); 89 | while(!feof($handle)){ 90 | $line = fgets($handle, 4096); 91 | $linecount = $linecount + substr_count($line, PHP_EOL); 92 | 93 | if(!$linecount){ 94 | throw new Exception("File is empty."); 95 | } 96 | 97 | $valid = AppHelper::isLineValid($line); 98 | if(!$valid){ 99 | Log::channel('employeeattendancelog')->critical("Contain invalid data at line number ".$linecount); 100 | } 101 | 102 | $row = AppHelper::parseRowForEmployee($line, $this->fileFormatType); 103 | 104 | if(count($row)){ 105 | $dateWiseData[$row['date']][] = [ 106 | 'empId' => $row['id'], 107 | 'time' => $row['time'] 108 | ]; 109 | 110 | } 111 | } 112 | fclose($handle); 113 | 114 | 115 | 116 | $isFail = false; 117 | 118 | //now process data for one day 119 | foreach ($dateWiseData as $key => $oneDayData) { 120 | //build employee wise data 121 | $empWiseData = []; 122 | foreach ($oneDayData as $data) { 123 | $empWiseData[$data['empId']][] = $data['time']; 124 | } 125 | 126 | $atndDate = $key; 127 | 128 | //now clean employee multiple entry 129 | $cleanEmpWiseData = []; 130 | foreach ($empWiseData as $empId => $entries) { 131 | sort($entries); 132 | $entryCount = count($entries); 133 | $inTime = $entries[0]; 134 | $outTime = $entryCount > 1 ? $entries[$entryCount - 1] : $inTime; 135 | 136 | $inTimeObject = Carbon::createFromFormat('YmdHis', $atndDate.$inTime); 137 | $outTimeObject = Carbon::createFromFormat('YmdHis', $atndDate.$outTime); 138 | $workTime = $inTimeObject->diff($outTimeObject)->format('%H:%I'); 139 | 140 | 141 | $cleanEmpWiseData[$empId] = [ 142 | 'inTime' => $inTimeObject, 143 | 'outTime' => $outTimeObject, 144 | 'workingHours' => $workTime 145 | ]; 146 | 147 | $totalValidRows++; 148 | 149 | } 150 | 151 | //now push back one day data to $dateWiseDate array 152 | $dateWiseData[$atndDate] = $cleanEmpWiseData; 153 | } 154 | 155 | $pendingFile->total_rows = $totalValidRows; 156 | $pendingFile->imported_rows = 0; 157 | if(!$totalValidRows){ 158 | $pendingFile->is_imported = -1; 159 | $pendingFile->save(); 160 | throw new Exception('There are no valid data in this file.'); 161 | } 162 | 163 | $pendingFile->updated_by = $this->createdBy; 164 | $pendingFile->save(); 165 | 166 | 167 | //fetch all employees 168 | $employeesData = Employee::where('status', AppHelper::ACTIVE)->get()->reduce(function ($employeesData, $employee) { 169 | $employeesData[$employee->id_card] = [ 170 | 'id' => $employee->id, 171 | 'in_time' => $employee->getOriginal('duty_start'), 172 | 'out_time' => $employee->getOriginal('duty_end'), 173 | ]; 174 | return $employeesData; 175 | }); 176 | 177 | $totalEmployee = count(array_keys($employeesData)); 178 | $absentIds = []; 179 | 180 | if($totalEmployee){ 181 | //ready to insert data to db 182 | $dateTimeNow = Carbon::now(env('APP_TIMEZONE','Asia/Dhaka')); 183 | 184 | foreach ($dateWiseData as $date => $employees) { 185 | $atd = new \DateTime(date('Ymd', strtotime($date))); 186 | $attendance_date = $atd->format('Y-m-d'); 187 | $attendances = []; 188 | 189 | //check if this date data exists on db or not 190 | $entryExists = $this->isAttendanceExists($attendance_date); 191 | if ($entryExists) { 192 | $msg = "Date '".$atd->format('d/m/Y')."' > attendance override by multiple upload."; 193 | Log::channel('employeeattendancelog')->warning($msg); 194 | DB::table('employee_attendances')->whereDate('attendance_date', '=', $attendance_date)->delete(); 195 | } 196 | 197 | DB::beginTransaction(); 198 | try { 199 | //now build data array for insert into db table 200 | foreach ($employeesData as $employee => $employeeData) { 201 | $isPresent = "0"; 202 | $status = []; 203 | 204 | $inTimeObject = Carbon::createFromFormat('Y-m-dH:i:s', $attendance_date."00:00:00"); 205 | $outTimeObject = Carbon::createFromFormat('Y-m-dH:i:s', $attendance_date."00:00:00"); 206 | $workingHours = $inTimeObject->diff($outTimeObject)->format('%H:%I'); 207 | 208 | //check is this employee present 209 | if (array_key_exists($employee, $employees)) { 210 | $isPresent = "1"; 211 | $inTimeObject = $employees[$employee]['inTime']; 212 | $outTimeObject = $employees[$employee]['outTime']; 213 | $workingHours = $employees[$employee]['workingHours']; 214 | 215 | //late or early out find 216 | if($employeeData['in_time'] && $employeeData['out_time']) { 217 | $empIntime = Carbon::createFromFormat('Y-m-d H:i:s',$attendance_date.' '.$employeeData['in_time']); 218 | if ($inTimeObject->greaterThan($empIntime)) { 219 | $status[] = 1; 220 | } 221 | 222 | $empOuttime = Carbon::createFromFormat('Y-m-d H:i:s',$attendance_date.' '.$employeeData['out_time']); 223 | if ($outTimeObject->lessThan($empOuttime)) { 224 | $status[] = 2; 225 | } 226 | } 227 | 228 | } 229 | 230 | $attendances[] = [ 231 | "employee_id" => $employeeData['id'], 232 | "attendance_date" => $attendance_date, 233 | "in_time" => $inTimeObject, 234 | "out_time" => $outTimeObject, 235 | "working_hour" => $workingHours, 236 | "status" => implode(',',$status), 237 | "present" => $isPresent, 238 | "created_at" => $dateTimeNow, 239 | "created_by" => $this->createdBy, 240 | ]; 241 | 242 | if(!$isPresent){ 243 | $absentIds[$attendance_date][] = $employeeData['id']; 244 | } 245 | 246 | } 247 | EmployeeAttendance::insert($attendances); 248 | DB::commit(); 249 | $msg = "Date '".$atd->format('d/m/Y')."' Total ".$totalEmployee." entry successfully stored."; 250 | Log::channel('employeeattendancelog')->info($msg); 251 | 252 | 253 | } 254 | catch (\Exception $e) { 255 | DB::rollback(); 256 | $msg = "Date '".$atd->format('d/m/Y')."' data insert problem. ".$e->getMessage(); 257 | Log::channel('employeeattendancelog')->error($msg); 258 | } 259 | 260 | 261 | 262 | $totalEmployeeInFile = count($employees); 263 | $pendingFile->imported_rows += $totalEmployeeInFile; 264 | $pendingFile->save(); 265 | 266 | //write log in more entry found rather than db employee list 267 | if($totalEmployee<$totalEmployeeInFile){ 268 | $msg = "Date '".$atd->format('d/m/Y')."' > ".($totalEmployeeInFile-$totalEmployee)." employee not found in db but found in attendance file!"; 269 | Log::channel('employeeattendancelog')->warning($msg); 270 | } 271 | 272 | 273 | } 274 | } 275 | else{ 276 | $isFail = true; 277 | Log::channel('employeeattendancelog')->critical("Employee not found on Database!"); 278 | } 279 | 280 | 281 | if($isFail) { 282 | $pendingFile->is_imported = - 1; 283 | $pendingFile->updated_by = $this->createdBy; 284 | $pendingFile->save(); 285 | } 286 | 287 | } 288 | catch (\Exception $e){ 289 | $pendingFile->is_imported = -1; 290 | $pendingFile->updated_by = $this->createdBy; 291 | $pendingFile->save(); 292 | $errorMSG = $e->getMessage(); 293 | Log::channel('employeeattendancelog')->critical($errorMSG); 294 | return false; 295 | } 296 | 297 | //send notification for absent 298 | try { 299 | $sendNotification = AppHelper::getAppSettings('student_attendance_notification', true); 300 | if ($sendNotification != "0" && $pendingFile->send_notification) { 301 | foreach ($absentIds as $attendance_date => $employeeIds) { 302 | PushEmployeeAbsentJob::dispatch($employeeIds, $attendance_date) 303 | ->onQueue('absent'); 304 | } 305 | } 306 | $pendingFile->is_imported = 1; 307 | $pendingFile->updated_by = $this->createdBy; 308 | $pendingFile->save(); 309 | } 310 | catch (\Exception $e){ 311 | 312 | $pendingFile->is_imported = -1; 313 | $pendingFile->updated_by = $this->createdBy; 314 | $pendingFile->save(); 315 | 316 | $errorMSG = $e->getMessage(); 317 | Log::channel('employeeattendancelog')->critical($errorMSG); 318 | return false; 319 | } 320 | 321 | 322 | $msg = "========File Queue Command Complete========"; 323 | Log::channel('employeeattendancelog')->info($msg); 324 | 325 | 326 | } 327 | 328 | private function isAttendanceExists($attendance_date) { 329 | return $attendances = EmployeeAttendance::whereDate('attendance_date', $attendance_date) 330 | ->CountOrGet(true); 331 | } 332 | } 333 | -------------------------------------------------------------------------------- /app/Http/Controllers/Backend/AcademicController.php: -------------------------------------------------------------------------------- 1 | isMethod('post')) {// 29 | $this->validate($request, [ 30 | 'hiddenId' => 'required|integer', 31 | ]); 32 | $iclass = IClass::findOrFail($request->get('hiddenId')); 33 | 34 | $haveSection = Section::where('class_id', $iclass->id)->count(); 35 | $haveStudent = Registration::where('class_id', $iclass->id)->count(); 36 | if($haveStudent || $haveSection){ 37 | return redirect()->route('academic.class')->with('error', 'Can not delete! Class used in section or have student.'); 38 | } 39 | 40 | $iclass->delete(); 41 | 42 | //now notify the admins about this record 43 | $msg = $iclass->name." class deleted by ".auth()->user()->name; 44 | $nothing = AppHelper::sendNotificationToAdmins('info', $msg); 45 | // Notification end 46 | 47 | //invalid cache 48 | Cache::forget('selected_classes_4_dashboard'); 49 | 50 | return redirect()->route('academic.class')->with('success', 'Record deleted!'); 51 | } 52 | 53 | //for get request 54 | $iclasses = IClass::select('id','name','numeric_value','order','status','note','group')->orderBy('order', 'asc')->get(); 55 | 56 | return view('backend.academic.iclass.list', compact('iclasses')); 57 | } 58 | 59 | /** 60 | * class create, read, update manage 61 | * @return \Illuminate\Http\Response 62 | */ 63 | public function classCru(Request $request, $id=0) 64 | { 65 | //for save on POST request 66 | if ($request->isMethod('post')) { 67 | ; 68 | $this->validate($request, [ 69 | 'name' => 'required|min:2|max:255', 70 | 'numeric_value' => 'required|integer', 71 | 'order' => 'required|integer', 72 | 'group' => 'nullable|max:20', 73 | 'note' => 'max:500', 74 | ]); 75 | 76 | $data = $request->all(); 77 | if(!$id){ 78 | $data['status'] = AppHelper::ACTIVE; 79 | 80 | } 81 | else{ 82 | unset($data['numeric_value']); 83 | } 84 | 85 | IClass::updateOrCreate( 86 | ['id' => $id], 87 | $data 88 | ); 89 | 90 | if(!$id){ 91 | //now notify the admins about this record 92 | $msg = $data['name']." class added by ".auth()->user()->name; 93 | $nothing = AppHelper::sendNotificationToAdmins('info', $msg); 94 | // Notification end 95 | 96 | //invalid cache 97 | Cache::forget('selected_classes_4_dashboard'); 98 | } 99 | 100 | 101 | $msg = "Class "; 102 | $msg .= $id ? 'updated.' : 'added.'; 103 | 104 | return redirect()->route('academic.class')->with('success', $msg); 105 | } 106 | 107 | //for get request 108 | $iclass = IClass::find($id); 109 | $group = 'None'; 110 | 111 | if($iclass){ 112 | $group = $iclass->group; 113 | } 114 | 115 | return view('backend.academic.iclass.add', compact('iclass','group')); 116 | } 117 | 118 | /** 119 | * class status change 120 | * @return mixed 121 | */ 122 | public function classStatus(Request $request, $id=0) 123 | { 124 | 125 | $iclass = IClass::findOrFail($id); 126 | if(!$iclass){ 127 | return [ 128 | 'success' => false, 129 | 'message' => 'Record not found!' 130 | ]; 131 | } 132 | 133 | $iclass->status = (string)$request->get('status'); 134 | 135 | $iclass->save(); 136 | 137 | return [ 138 | 'success' => true, 139 | 'message' => 'Status updated.' 140 | ]; 141 | 142 | } 143 | 144 | 145 | /** 146 | * section manage 147 | * @return \Illuminate\Http\Response 148 | */ 149 | public function sectionIndex(Request $request) 150 | { 151 | 152 | //for save on POST request 153 | if ($request->isMethod('post')) {// 154 | $this->validate($request, [ 155 | 'hiddenId' => 'required|integer', 156 | ]); 157 | $section = Section::findOrFail($request->get('hiddenId')); 158 | 159 | $haveStudent = Registration::where('section_id', $section->id)->count(); 160 | if($haveStudent){ 161 | return redirect()->route('academic.section')->with('error', 'Can not delete! Section have student.'); 162 | } 163 | 164 | $section->delete(); 165 | 166 | //now notify the admins about this record 167 | $msg = $section->name." section deleted by ".auth()->user()->name; 168 | $nothing = AppHelper::sendNotificationToAdmins('info', $msg); 169 | // Notification end 170 | 171 | return redirect()->route('academic.section')->with('success', 'Record deleted!'); 172 | } 173 | 174 | 175 | // check for ajax request here 176 | if($request->ajax()){ 177 | $class_id = $request->query->get('class', 0); 178 | $sections = Section::select('id', 'name as text')->where('class_id',$class_id)->where('status', AppHelper::ACTIVE)->orderBy('name', 'asc')->get(); 179 | return $sections; 180 | } 181 | 182 | $sections = Section::with('teacher')->with('class')->orderBy('name', 'asc')->get(); 183 | 184 | return view('backend.academic.section.list', compact('sections')); 185 | } 186 | 187 | /** 188 | * section create, read, update manage 189 | * @return \Illuminate\Http\Response 190 | */ 191 | public function sectionCru(Request $request, $id=0) 192 | { 193 | //for save on POST request 194 | if ($request->isMethod('post')) { 195 | ; 196 | $this->validate($request, [ 197 | 'name' => 'required|min:1|max:255', 198 | 'capacity' => 'required|numeric', 199 | 'class_id' => 'required|integer', 200 | 'teacher_id' => 'required|integer', 201 | 'note' => 'max:500', 202 | ]); 203 | 204 | $data = $request->all(); 205 | 206 | Section::updateOrCreate( 207 | ['id' => $id], 208 | $data 209 | ); 210 | 211 | 212 | if(!$id){ 213 | //now notify the admins about this record 214 | $msg = $data['name']." section added by ".auth()->user()->name; 215 | $nothing = AppHelper::sendNotificationToAdmins('info', $msg); 216 | // Notification end 217 | } 218 | 219 | $msg = "section "; 220 | $msg .= $id ? 'updated.' : 'added.'; 221 | 222 | return redirect()->route('academic.section')->with('success', $msg); 223 | } 224 | 225 | //for get request 226 | $section = Section::find($id); 227 | 228 | $teachers = Employee::where('role_id', AppHelper::EMP_TEACHER) 229 | ->where('status', AppHelper::ACTIVE) 230 | ->pluck('name', 'id'); 231 | $teacher = null; 232 | 233 | $classes = IClass::where('status', AppHelper::ACTIVE) 234 | ->pluck('name', 'id'); 235 | $iclass = null; 236 | 237 | if($section){ 238 | $teacher = $section->teacher_id; 239 | $iclass = $section->class_id; 240 | } 241 | 242 | return view('backend.academic.section.add', compact('section', 'iclass', 'classes', 'teachers', 'teacher')); 243 | } 244 | 245 | /** 246 | * section status change 247 | * @return mixed 248 | */ 249 | public function sectionStatus(Request $request, $id=0) 250 | { 251 | 252 | $section = Section::findOrFail($id); 253 | if(!$section){ 254 | return [ 255 | 'success' => false, 256 | 'message' => 'Record not found!' 257 | ]; 258 | } 259 | 260 | $section->status = (string)$request->get('status'); 261 | 262 | $section->save(); 263 | 264 | return [ 265 | 'success' => true, 266 | 'message' => 'Status updated.' 267 | ]; 268 | 269 | } 270 | 271 | 272 | /** 273 | * subject manage 274 | * @return \Illuminate\Http\Response 275 | */ 276 | public function subjectIndex(Request $request) 277 | { 278 | 279 | //for save on POST request 280 | if ($request->isMethod('post')) {// 281 | $this->validate($request, [ 282 | 'hiddenId' => 'required|integer', 283 | ]); 284 | $subject = Subject::findOrFail($request->get('hiddenId')); 285 | 286 | //todo: add delete protection here 287 | // $haveExam = Exam::where('section_id', $subject->id)->count(); 288 | // if($haveExam){ 289 | // return redirect()->route('academic.section')->with('error', 'Can not delete! Section have student.'); 290 | // } 291 | 292 | $subject->delete(); 293 | 294 | //now notify the admins about this record 295 | $msg = $subject->name." subject deleted by ".auth()->user()->name; 296 | $nothing = AppHelper::sendNotificationToAdmins('info', $msg); 297 | // Notification end 298 | 299 | //invalid dashboard cache 300 | Cache::forget('SubjectCount'); 301 | 302 | return redirect()->route('academic.subject')->with('success', 'Record deleted!'); 303 | } 304 | 305 | 306 | // check for ajax request here 307 | if($request->ajax()){ 308 | $class_id = $request->query->get('class', 0); 309 | $subjectType = $request->query->get('type', 0); 310 | $teacherId = 0; 311 | if(session('user_role_id',0) == AppHelper::USER_TEACHER){ 312 | $teacherId = auth()->user()->teacher->id; 313 | } 314 | $subjects = Subject::select('id', 'name as text') 315 | ->where('class_id',$class_id) 316 | ->sType($subjectType) 317 | ->when($teacherId, function ($query) use($teacherId){ 318 | $query->where('teacher_id', $teacherId); 319 | }) 320 | ->where('status', AppHelper::ACTIVE) 321 | ->orderBy('name', 'asc') 322 | ->get(); 323 | return $subjects; 324 | } 325 | 326 | 327 | $class_id = $request->query->get('class',0); 328 | $subjects = Subject::iclass($class_id)->with('teacher')->with('class')->orderBy('name', 'asc')->get(); 329 | $classes = IClass::where('status', AppHelper::ACTIVE) 330 | ->pluck('name', 'id'); 331 | $iclass = $class_id; 332 | 333 | 334 | return view('backend.academic.subject.list', compact('subjects','classes', 'iclass')); 335 | } 336 | 337 | /** 338 | * subject create, read, update manage 339 | * @return \Illuminate\Http\Response 340 | */ 341 | public function subjectCru(Request $request, $id=0) 342 | { 343 | //for save on POST request 344 | if ($request->isMethod('post')) { 345 | ; 346 | $this->validate($request, [ 347 | 'name' => 'required|min:1|max:255', 348 | 'code' => 'required|min:1|max:255', 349 | 'type' => 'required|numeric', 350 | 'class_id' => 'required|integer', 351 | 'teacher_id' => 'required|integer', 352 | ]); 353 | 354 | $data = $request->all(); 355 | 356 | Subject::updateOrCreate( 357 | ['id' => $id], 358 | $data 359 | ); 360 | 361 | 362 | if(!$id){ 363 | //now notify the admins about this record 364 | $msg = $data['name']." subject added by ".auth()->user()->name; 365 | $nothing = AppHelper::sendNotificationToAdmins('info', $msg); 366 | // Notification end 367 | 368 | //invalid dashboard cache 369 | Cache::forget('SubjectCount'); 370 | } 371 | 372 | $msg = "subject "; 373 | $msg .= $id ? 'updated.' : 'added.'; 374 | 375 | return redirect()->route('academic.subject')->with('success', $msg); 376 | } 377 | 378 | //for get request 379 | $subject = Subject::find($id); 380 | 381 | $teachers = Employee::where('role_id', AppHelper::EMP_TEACHER) 382 | ->where('status', AppHelper::ACTIVE) 383 | ->pluck('name', 'id'); 384 | $teacher = null; 385 | 386 | $classes = IClass::where('status', AppHelper::ACTIVE) 387 | ->pluck('name', 'id'); 388 | $iclass = null; 389 | $subjectType = null; 390 | 391 | if($subject){ 392 | $teacher = $subject->teacher_id; 393 | $iclass = $subject->class_id; 394 | $subjectType = $subject->getOriginal('type'); 395 | } 396 | 397 | return view('backend.academic.subject.add', compact('subject', 'iclass', 'classes', 'teachers', 'teacher', 'subjectType')); 398 | } 399 | 400 | /** 401 | * subject status change 402 | * @return mixed 403 | */ 404 | public function subjectStatus(Request $request, $id=0) 405 | { 406 | 407 | $subject = Subject::findOrFail($id); 408 | if(!$subject){ 409 | return [ 410 | 'success' => false, 411 | 'message' => 'Record not found!' 412 | ]; 413 | } 414 | 415 | $subject->status = (string)$request->get('status'); 416 | 417 | $subject->save(); 418 | 419 | return [ 420 | 'success' => true, 421 | 'message' => 'Status updated.' 422 | ]; 423 | 424 | } 425 | 426 | 427 | 428 | } 429 | -------------------------------------------------------------------------------- /public/svg/500.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Console/Commands/SeedStudentAttendance.php: -------------------------------------------------------------------------------- 1 | where('is_imported','=',0) 57 | ->orderBy('created_at', 'DESC') 58 | ->first(); 59 | 60 | if(!$pendingFile){ 61 | Log::channel('studentattendancelog')->info('No pending task!'); 62 | return false; 63 | } 64 | 65 | //set file format 66 | $this->fileFormatType = intval($pendingFile->file_format); 67 | $this->createdBy = $pendingFile->created_by; 68 | 69 | $filePath = storage_path('app/student-attendance/').$pendingFile->file_name; 70 | if(!file_exists($filePath)){ 71 | Log::channel('studentattendancelog')->critical('File not found! '.$pendingFile->file_name); 72 | return false; 73 | } 74 | 75 | //data imported class 76 | $presentStudentsByClass = []; 77 | 78 | //process present attendance student 79 | try{ 80 | 81 | $attendanceData = []; 82 | $totalValidRows = 0; 83 | //open the file and get line and process it 84 | $linecount = 0; 85 | $handle = fopen($filePath, "r"); 86 | while(!feof($handle)){ 87 | $line = fgets($handle, 4096); 88 | $linecount = $linecount + substr_count($line, PHP_EOL); 89 | 90 | if(!$linecount){ 91 | throw new Exception("File is empty."); 92 | } 93 | 94 | $valid = AppHelper::isLineValid($line); 95 | if(!$valid){ 96 | Log::channel('studentattendancelog')->critical("Contain invalid data at line number ".$linecount); 97 | } 98 | 99 | $row = AppHelper::parseRow($line, $this->fileFormatType); 100 | if(count($row)){ 101 | 102 | $attendanceData[$row['date']][] = [ 103 | 'studentId' => $row['id'], 104 | 'time' => $row['time'] 105 | ]; 106 | 107 | } 108 | } 109 | fclose($handle); 110 | 111 | //now process data for one day 112 | foreach ($attendanceData as $key => $oneDayData) { 113 | //build student wise data 114 | $studentWiseData = []; 115 | foreach ($oneDayData as $data) { 116 | $studentWiseData[$data['studentId']][] = $data['time']; 117 | } 118 | 119 | $atndDate = $key; 120 | //now clean student multiple entry 121 | $cleanstudentWiseData = []; 122 | foreach ($studentWiseData as $studentId => $entries) { 123 | sort($entries); 124 | $entryCount = count($entries); 125 | $inTime = $entries[0]; 126 | $outTime = $entryCount > 1 ? $entries[$entryCount - 1] : $inTime; 127 | 128 | $inTimeObject = Carbon::createFromFormat('YmdHis', $atndDate.$inTime); 129 | $outTimeObject = Carbon::createFromFormat('YmdHis', $atndDate.$outTime); 130 | $stayingTime = $inTimeObject->diff($outTimeObject)->format('%H:%I'); 131 | 132 | 133 | $cleanstudentWiseData[$studentId] = [ 134 | 'inTime' => $inTimeObject, 135 | 'outTime' => $outTimeObject, 136 | 'stayingHours' => $stayingTime 137 | ]; 138 | 139 | $totalValidRows++; 140 | 141 | } 142 | //now push back one day data to $dateWiseDate array 143 | $attendanceData[$atndDate] = $cleanstudentWiseData; 144 | } 145 | 146 | 147 | $pendingFile->total_rows = $totalValidRows; 148 | if(!$totalValidRows){ 149 | $pendingFile->is_imported = -1; 150 | $pendingFile->save(); 151 | throw new Exception('There are no valid data in this file.'); 152 | } 153 | 154 | $pendingFile->updated_by = $this->createdBy; 155 | $pendingFile->save(); 156 | 157 | 158 | $dateTimeNow = Carbon::now(env('APP_TIMEZONE','Asia/Dhaka')); 159 | $isFail = false; 160 | 161 | //pull shift running time 162 | //fetch institute shift running times 163 | $shiftData = AppHelper::getAppSettings('shift_data', true); 164 | if($shiftData){ 165 | $shiftData = json_decode($shiftData, true); 166 | } 167 | $shiftRuningTimes = []; 168 | 169 | foreach ($shiftData as $shift => $times){ 170 | $shiftRuningTimes[$shift] = [ 171 | 'start' => $times['start'], 172 | 'end' => $times['end'] 173 | ]; 174 | } 175 | 176 | //now insert those data to db and 177 | foreach ($attendanceData as $kdate => $studentData) { 178 | try 179 | { 180 | $atd = new \DateTime(date('Ymd', strtotime($kdate))); 181 | $attendance_date = $atd->format('Y-m-d'); 182 | 183 | // now fetch student id and class info 184 | $regiNumbers = array_keys($studentData); 185 | $presentStudents = Registration::select('id','class_id','regi_no','academic_year_id','shift') 186 | ->where('status', AppHelper::ACTIVE) 187 | ->whereIn('regi_no', $regiNumbers) 188 | ->get(); 189 | 190 | $insertCounter = 0; 191 | foreach ($presentStudents as $student){ 192 | 193 | //extract class id from here 194 | $presentStudentsByClass[$attendance_date][$student->class_id] = $student->academic_year_id; 195 | 196 | $entryExists = StudentAttendance::whereDate('attendance_date', '=', $attendance_date) 197 | ->where('registration_id', '=', $student->id) 198 | ->where('academic_year_id', $student->academic_year_id) 199 | ->where('class_id', $student->class_id) 200 | ->count(); 201 | 202 | if(!$entryExists) { 203 | 204 | //find is late or early out 205 | $inTime = $studentData[$student->regi_no]['inTime']; 206 | $outTime = $studentData[$student->regi_no]['outTime']; 207 | $timeDiff = $inTime->diff($outTime)->format('%H:%I'); 208 | $status = []; 209 | //late or early out find 210 | if($timeDiff != "00:00" && strlen($student->shift) && isset($shiftRuningTimes[$student->shift])){ 211 | 212 | $shiftStart = Carbon::createFromFormat('Y-m-dh:i a', $attendance_date.$shiftRuningTimes[$student->shift]['start']); 213 | $shiftEnd = Carbon::createFromFormat('Y-m-dh:i a', $attendance_date.$shiftRuningTimes[$student->shift]['end']); 214 | 215 | if($inTime->greaterThan($shiftStart)){ 216 | $status[] = 1; 217 | } 218 | 219 | if($outTime->lessThan($shiftEnd)){ 220 | $status[] = 2; 221 | } 222 | 223 | 224 | 225 | } 226 | 227 | $singleAttendance = [ 228 | "academic_year_id" => $student->academic_year_id, 229 | "class_id" => $student->class_id, 230 | "registration_id" => $student->id, 231 | "attendance_date" => $kdate, 232 | "in_time" => $inTime, 233 | "out_time" => $outTime, 234 | "staying_hour" => $timeDiff, 235 | "status" => implode(',',$status), 236 | "present" => "1", 237 | "created_at" => $dateTimeNow, 238 | "created_by" => $this->createdBy, 239 | ]; 240 | 241 | StudentAttendance::insert($singleAttendance); 242 | 243 | $pendingFile->imported_rows = $pendingFile->imported_rows + 1; 244 | $pendingFile->save(); 245 | 246 | $insertCounter++; 247 | } 248 | else{ 249 | Log::channel('studentattendancelog')->warning('Attendance already exists for '.$student->regi_no.' and '.$kdate); 250 | } 251 | 252 | } 253 | 254 | Log::channel('studentattendancelog')->info('Total '.$insertCounter.' student attendance insert for '.$kdate); 255 | 256 | }catch (\Exception $e) { 257 | $isFail = true; 258 | $msg = "Date '".$kdate."' data insert problem. ".$e->getMessage(); 259 | Log::channel('studentattendancelog')->critical($msg); 260 | 261 | } 262 | 263 | } 264 | 265 | 266 | if($isFail) { 267 | $pendingFile->is_imported = - 1; 268 | $pendingFile->updated_by = $this->createdBy; 269 | $pendingFile->save(); 270 | } 271 | 272 | } 273 | catch (Exception $e){ 274 | $pendingFile->is_imported = -1; 275 | $pendingFile->updated_by = $this->createdBy; 276 | $pendingFile->save(); 277 | $errorMSG = $e->getMessage(); 278 | Log::channel('studentattendancelog')->critical($errorMSG); 279 | return false; 280 | } 281 | 282 | //process absent attendance student 283 | $absentStudentIdsByDate = []; 284 | try { 285 | //find absent students 286 | foreach ($presentStudentsByClass as $pDate => $stClasses){ 287 | $absentAttendances = []; 288 | $dateTimeNow = Carbon::now(env('APP_TIMEZONE','Asia/Dhaka')); 289 | 290 | foreach ($stClasses as $class_id => $academicYear){ 291 | $absentStudents = Registration::where('status', AppHelper::ACTIVE) 292 | ->where('academic_year_id', $academicYear) 293 | ->where('class_id', $class_id) 294 | ->whereDoesntHave('attendance' , function ($query) use($pDate, $academicYear, $class_id) { 295 | $query->select('registration_id') 296 | ->where('academic_year_id', $academicYear) 297 | ->where('class_id', $class_id) 298 | ->whereDate('attendance_date', $pDate); 299 | }) 300 | ->select('id','regi_no','roll_no','class_id','academic_year_id') 301 | ->get(); 302 | 303 | //find is late or early out 304 | $inTime = Carbon::createFromFormat('Y-m-dHis', $pDate.'000000'); 305 | $outTime = $inTime; 306 | $timeDiff = $inTime->diff($outTime)->format('%H:%I'); 307 | $status = []; 308 | 309 | foreach ($absentStudents as $student){ 310 | $absentAttendances[] = [ 311 | "academic_year_id" => $student->academic_year_id, 312 | "class_id" => $student->class_id, 313 | "registration_id" => $student->id, 314 | "attendance_date" => $pDate, 315 | "in_time" => $inTime, 316 | "out_time" => $outTime, 317 | "staying_hour" => $timeDiff, 318 | "status" => implode(',',$status), 319 | "present" => "0", 320 | "created_at" => $dateTimeNow, 321 | "created_by" => $this->createdBy, 322 | ]; 323 | 324 | $absentStudentIdsByDate[$pDate][] = $student->id; 325 | } 326 | } 327 | 328 | StudentAttendance::insert($absentAttendances); 329 | Log::channel('studentattendancelog')->info('Total '.count($absentAttendances).' absent student attendance insert for '.$pDate); 330 | } 331 | } 332 | catch (Exception $e){ 333 | $pendingFile->is_imported = -1; 334 | $pendingFile->updated_by = $this->createdBy; 335 | $pendingFile->save(); 336 | $errorMSG = $e->getMessage(); 337 | Log::channel('studentattendancelog')->critical($errorMSG); 338 | return false; 339 | } 340 | 341 | //now invalid cache 342 | Cache::forget('student_attendance_count'); 343 | 344 | //send notification for absent 345 | try { 346 | $sendNotification = AppHelper::getAppSettings('student_attendance_notification', true); 347 | if ($sendNotification != "0" && $pendingFile->send_notification) { 348 | foreach ($absentStudentIdsByDate as $attendance_date => $absentIds) { 349 | PushStudentAbsentJob::dispatch($absentIds, $attendance_date) 350 | ->onQueue('absent'); 351 | } 352 | } 353 | $pendingFile->is_imported = 1; 354 | $pendingFile->updated_by = $this->createdBy; 355 | $pendingFile->save(); 356 | } 357 | catch (Exception $e){ 358 | 359 | $pendingFile->is_imported = -1; 360 | $pendingFile->updated_by = $this->createdBy; 361 | $pendingFile->save(); 362 | 363 | $errorMSG = $e->getMessage(); 364 | Log::channel('studentattendancelog')->critical($errorMSG); 365 | return false; 366 | } 367 | 368 | 369 | $msg = "========File Queue Command Complete========"; 370 | Log::channel('studentattendancelog')->info($msg); 371 | 372 | 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | 'role:admin'], function() { 17 | // Route::get('/admin', function() { 18 | // return 'Welcome Admin'; 19 | // }); 20 | //}); 21 | 22 | 23 | /** 24 | * Admin panel routes goes below 25 | */ 26 | Route::group( 27 | ['namespace' => 'Backend', 'middleware' => ['guest']], function () { 28 | Route::get('/login', 'UserController@login')->name('login'); 29 | Route::post('/login', 'UserController@authenticate'); 30 | Route::get('/forgot', 'UserController@forgot')->name('forgot'); 31 | Route::post('/forgot', 'UserController@forgot') 32 | ->name('forgot'); 33 | Route::get('/reset/{token}', 'UserController@reset') 34 | ->name('reset'); 35 | Route::post('/reset/{token}', 'UserController@reset') 36 | ->name('reset'); 37 | 38 | } 39 | ); 40 | 41 | Route::get('/public/exam', 'Backend\ExamController@indexPublic')->name('public.exam_list'); 42 | Route::any('/online-result', 'Backend\ReportController@marksheetPublic')->name('report.marksheet_pub'); 43 | 44 | Route::group( 45 | ['namespace' => 'Backend', 'middleware' => ['auth', 'permission']], function () { 46 | Route::get('/logout', 'UserController@logout')->name('logout'); 47 | Route::get('/lock', 'UserController@lock')->name('lockscreen'); 48 | Route::get('/dashboard', 'UserController@dashboard')->name('user.dashboard'); 49 | 50 | //user management 51 | Route::resource('user', 'UserController'); 52 | Route::get('/profile', 'UserController@profile') 53 | ->name('profile'); 54 | Route::post('/profile', 'UserController@profile') 55 | ->name('profile'); 56 | Route::get('/change-password', 'UserController@changePassword') 57 | ->name('change_password'); 58 | Route::post('/change-password', 'UserController@changePassword') 59 | ->name('change_password'); 60 | Route::post('user/status/{id}', 'UserController@changeStatus') 61 | ->name('user.status'); 62 | Route::any('user/{id}/permission', 'UserController@updatePermission') 63 | ->name('user.permission'); 64 | 65 | //user notification 66 | Route::get('/notification/unread', 'NotificationController@getUnReadNotification') 67 | ->name('user.notification_unread'); 68 | Route::get('/notification/read', 'NotificationController@getReadNotification') 69 | ->name('user.notification_read'); 70 | Route::get('/notification/all', 'NotificationController@getAllNotification') 71 | ->name('user.notification_all'); 72 | 73 | //system user management 74 | Route::get('/administrator/user', 'AdministratorController@userIndex') 75 | ->name('administrator.user_index'); 76 | Route::get('/administrator/user/create', 'AdministratorController@userCreate') 77 | ->name('administrator.user_create'); 78 | Route::post('/administrator/user/store', 'AdministratorController@userStore') 79 | ->name('administrator.user_store'); 80 | Route::get('/administrator/user/{id}/edit', 'AdministratorController@userEdit') 81 | ->name('administrator.user_edit'); 82 | Route::post('/administrator/user/{id}/update', 'AdministratorController@userUpdate') 83 | ->name('administrator.user_update'); 84 | Route::post('/administrator/user/{id}/delete', 'AdministratorController@userDestroy') 85 | ->name('administrator.user_destroy'); 86 | Route::post('administrator/user/status/{id}', 'AdministratorController@userChangeStatus') 87 | ->name('administrator.user_status'); 88 | 89 | Route::any('/administrator/user/reset-password', 'AdministratorController@userResetPassword') 90 | ->name('administrator.user_password_reset'); 91 | 92 | 93 | 94 | //user role manage 95 | Route::get('/role', 'UserController@roles') 96 | ->name('user.role_index'); 97 | Route::post('/role', 'UserController@roles') 98 | ->name('user.role_destroy'); 99 | Route::get('/role/create', 'UserController@roleCreate') 100 | ->name('user.role_create'); 101 | Route::post('/role/store', 'UserController@roleCreate') 102 | ->name('user.role_store'); 103 | Route::any('/role/update/{id}', 'UserController@roleUpdate') 104 | ->name('user.role_update'); 105 | 106 | 107 | // application settings routes 108 | Route::get('settings/institute', 'SettingsController@institute') 109 | ->name('settings.institute'); 110 | Route::post('settings/institute', 'SettingsController@institute') 111 | ->name('settings.institute'); 112 | 113 | // academic calendar 114 | Route::get('settings/academic-calendar', 'SettingsController@academicCalendarIndex') 115 | ->name('settings.academic_calendar.index'); 116 | Route::post('settings/academic-calendar', 'SettingsController@academicCalendarIndex') 117 | ->name('settings.academic_calendar.destroy'); 118 | Route::get('settings/academic-calendar/create', 'SettingsController@academicCalendarCru') 119 | ->name('settings.academic_calendar.create'); 120 | Route::post('settings/academic-calendar/create', 'SettingsController@academicCalendarCru') 121 | ->name('settings.academic_calendar.store'); 122 | Route::get('settings/academic-calendar/edit/{id}', 'SettingsController@academicCalendarCru') 123 | ->name('settings.academic_calendar.edit'); 124 | Route::post('settings/academic-calendar/update/{id}', 'SettingsController@academicCalendarCru') 125 | ->name('settings.academic_calendar.update'); 126 | 127 | //sms gateways 128 | Route::get('settings/sms-gateway', 'SettingsController@smsGatewayIndex') 129 | ->name('settings.sms_gateway.index'); 130 | Route::post('settings/sms-gateway', 'SettingsController@smsGatewayIndex') 131 | ->name('settings.sms_gateway.destroy'); 132 | Route::get('settings/sms-gateway/create', 'SettingsController@smsGatewayCru') 133 | ->name('settings.sms_gateway.create'); 134 | Route::post('settings/sms-gateway/create', 'SettingsController@smsGatewayCru') 135 | ->name('settings.sms_gateway.store'); 136 | Route::get('settings/sms-gateway/edit/{id}', 'SettingsController@smsGatewayCru') 137 | ->name('settings.sms_gateway.edit'); 138 | Route::post('settings/sms-gateway/update/{id}', 'SettingsController@smsGatewayCru') 139 | ->name('settings.sms_gateway.update'); 140 | 141 | //report settings 142 | Route::get('settings/report', 'SettingsController@report') 143 | ->name('settings.report'); 144 | Route::post('settings/report', 'SettingsController@report') 145 | ->name('settings.report'); 146 | 147 | 148 | // administrator routes 149 | //academic year 150 | Route::get('administrator/academic_year', 'AdministratorController@academicYearIndex') 151 | ->name('administrator.academic_year'); 152 | Route::post('administrator/academic_year', 'AdministratorController@academicYearIndex') 153 | ->name('administrator.academic_year_destroy'); 154 | Route::get('administrator/academic_year/create', 'AdministratorController@academicYearCru') 155 | ->name('administrator.academic_year_create'); 156 | Route::post('administrator/academic_year/create', 'AdministratorController@academicYearCru') 157 | ->name('administrator.academic_year_store'); 158 | Route::get('administrator/academic_year/edit/{id}', 'AdministratorController@academicYearCru') 159 | ->name('administrator.academic_year_edit'); 160 | Route::post('administrator/academic_year/update/{id}', 'AdministratorController@academicYearCru') 161 | ->name('administrator.academic_year_update'); 162 | Route::post('administrator/academic_year/status/{id}', 'AdministratorController@academicYearChangeStatus') 163 | ->name('administrator.academic_year_status'); 164 | 165 | // template 166 | //mail and sms 167 | Route::get('administrator/template-mailandsms', 'AdministratorController@templateMailAndSmsIndex') 168 | ->name('administrator.template.mailsms.index'); 169 | Route::post('administrator/template-mailandsms', 'AdministratorController@templateMailAndSmsIndex') 170 | ->name('administrator.template.mailsms.destroy'); 171 | Route::get('administrator/template-mailandsms/create', 'AdministratorController@templateMailAndSmsCru') 172 | ->name('administrator.template.mailsms.create'); 173 | Route::post('administrator/template-mailandsms/create', 'AdministratorController@templateMailAndSmsCru') 174 | ->name('administrator.template.mailsms.store'); 175 | Route::get('administrator/template-mailandsms/edit/{id}', 'AdministratorController@templateMailAndSmsCru') 176 | ->name('administrator.template.mailsms.edit'); 177 | Route::post('administrator/template-mailandsms/update/{id}', 'AdministratorController@templateMailAndSmsCru') 178 | ->name('administrator.template.mailsms.update'); 179 | // id card 180 | Route::get('administrator/template-idcard', 'AdministratorController@templateIdcardIndex') 181 | ->name('administrator.template.idcard.index'); 182 | Route::post('administrator/template-idcard', 'AdministratorController@templateIdcardIndex') 183 | ->name('administrator.template.idcard.destroy'); 184 | Route::get('administrator/template-idcard/create', 'AdministratorController@templateIdcardCru') 185 | ->name('administrator.template.idcard.create'); 186 | Route::post('administrator/template-idcard/create', 'AdministratorController@templateIdcardCru') 187 | ->name('administrator.template.idcard.store'); 188 | Route::get('administrator/template-idcard/edit/{id}', 'AdministratorController@templateIdcardCru') 189 | ->name('administrator.template.idcard.edit'); 190 | Route::post('administrator/template-idcard/update/{id}', 'AdministratorController@templateIdcardCru') 191 | ->name('administrator.template.idcard.update'); 192 | 193 | 194 | // academic routes 195 | // class 196 | Route::get('academic/class', 'AcademicController@classIndex') 197 | ->name('academic.class'); 198 | Route::post('academic/class', 'AcademicController@classIndex') 199 | ->name('academic.class_destroy'); 200 | Route::get('academic/class/create', 'AcademicController@classCru') 201 | ->name('academic.class_create'); 202 | Route::post('academic/class/create', 'AcademicController@classCru') 203 | ->name('academic.class_store'); 204 | Route::get('academic/class/edit/{id}', 'AcademicController@classCru') 205 | ->name('academic.class_edit'); 206 | Route::post('academic/class/update/{id}', 'AcademicController@classCru') 207 | ->name('academic.class_update'); 208 | Route::post('academic/class/status/{id}', 'AcademicController@classStatus') 209 | ->name('academic.class_status'); 210 | 211 | // section 212 | Route::get('academic/section', 'AcademicController@sectionIndex') 213 | ->name('academic.section'); 214 | Route::post('academic/section', 'AcademicController@sectionIndex') 215 | ->name('academic.section_destroy'); 216 | Route::get('academic/section/create', 'AcademicController@sectionCru') 217 | ->name('academic.section_create'); 218 | Route::post('academic/section/create', 'AcademicController@sectionCru') 219 | ->name('academic.section_store'); 220 | Route::get('academic/section/edit/{id}', 'AcademicController@sectionCru') 221 | ->name('academic.section_edit'); 222 | Route::post('academic/section/update/{id}', 'AcademicController@sectionCru') 223 | ->name('academic.section_update'); 224 | Route::post('academic/section/status/{id}', 'AcademicController@sectionStatus') 225 | ->name('academic.section_status'); 226 | 227 | // subject 228 | Route::get('academic/subject', 'AcademicController@subjectIndex') 229 | ->name('academic.subject'); 230 | Route::post('academic/subject', 'AcademicController@subjectIndex') 231 | ->name('academic.subject_destroy'); 232 | Route::get('academic/subject/create', 'AcademicController@subjectCru') 233 | ->name('academic.subject_create'); 234 | Route::post('academic/subject/create', 'AcademicController@subjectCru') 235 | ->name('academic.subject_store'); 236 | Route::get('academic/subject/edit/{id}', 'AcademicController@subjectCru') 237 | ->name('academic.subject_edit'); 238 | Route::post('academic/subject/update/{id}', 'AcademicController@subjectCru') 239 | ->name('academic.subject_update'); 240 | Route::post('academic/subject/status/{id}', 'AcademicController@subjectStatus') 241 | ->name('academic.subject_status'); 242 | 243 | 244 | // teacher routes 245 | Route::resource('teacher', 'TeacherController'); 246 | Route::post('teacher/status/{id}', 'TeacherController@changeStatus') 247 | ->name('teacher.status'); 248 | 249 | // student routes 250 | Route::resource('student', 'StudentController'); 251 | Route::post('student/status/{id}', 'StudentController@changeStatus') 252 | ->name('student.status'); 253 | Route::get('student-list-by-filter', 'StudentController@studentListByFitler') 254 | ->name('student.list_by_fitler'); 255 | 256 | // student attendance routes 257 | Route::get('student-attendance', 'StudentAttendanceController@index')->name('student_attendance.index'); 258 | Route::any('student-attendance/create', 'StudentAttendanceController@create')->name('student_attendance.create'); 259 | Route::post('student-attendance/store', 'StudentAttendanceController@store')->name('student_attendance.store'); 260 | Route::post('student-attendance/status/{id}', 'StudentAttendanceController@changeStatus') 261 | ->name('student_attendance.status'); 262 | Route::any('student-attendance/file-upload', 'StudentAttendanceController@createFromFile') 263 | ->name('student_attendance.create_file'); 264 | Route::get('student-attendance/file-queue-status', 'StudentAttendanceController@fileQueueStatus') 265 | ->name('student_attendance.file_queue_status'); 266 | 267 | // HRM 268 | //Employee 269 | Route::resource('hrm/employee', 'EmployeeController', ['as' => 'hrm']); 270 | Route::post('hrm/employee/status/{id}', 'EmployeeController@changeStatus') 271 | ->name('hrm.employee.status'); 272 | // Leave 273 | Route::resource('hrm/leave', 'LeaveController', ['as' => 'hrm']); 274 | Route::resource('hrm/work_outside', 'WorkOutsideController', ['as' => 'hrm']); 275 | // policy 276 | Route::get('hrm/policy', 'EmployeeController@hrmPolicy') 277 | ->name('hrm.policy'); 278 | Route::post('hrm/policy', 'EmployeeController@hrmPolicy') 279 | ->name('hrm.policy'); 280 | 281 | // employee attendance routes 282 | Route::get('employee-attendance', 'EmployeeAttendanceController@index')->name('employee_attendance.index'); 283 | Route::get('employee-attendance/create', 'EmployeeAttendanceController@create')->name('employee_attendance.create'); 284 | Route::post('employee-attendance/create', 'EmployeeAttendanceController@store')->name('employee_attendance.store'); 285 | Route::post('employee-attendance/status/{id}', 'EmployeeAttendanceController@changeStatus') 286 | ->name('employee_attendance.status'); 287 | Route::any('employee-attendance/file-upload', 'EmployeeAttendanceController@createFromFile') 288 | ->name('employee_attendance.create_file'); 289 | Route::get('employee-attendance/file-queue-status', 'EmployeeAttendanceController@fileQueueStatus') 290 | ->name('employee_attendance.file_queue_status'); 291 | 292 | 293 | //exam 294 | Route::get('exam', 'ExamController@index') 295 | ->name('exam.index'); 296 | Route::get('exam/create', 'ExamController@create') 297 | ->name('exam.create'); 298 | Route::post('exam/store', 'ExamController@store') 299 | ->name('exam.store'); 300 | Route::get('exam/edit/{id}', 'ExamController@edit') 301 | ->name('exam.edit'); 302 | Route::post('exam/update/{id}', 'ExamController@update') 303 | ->name('exam.update'); 304 | Route::post('exam/status/{id}', 'ExamController@changeStatus') 305 | ->name('exam.status'); 306 | Route::post('exam/delete/{id}', 'ExamController@destroy') 307 | ->name('exam.destroy'); 308 | //grade 309 | Route::get('exam/grade', 'ExamController@gradeIndex') 310 | ->name('exam.grade.index'); 311 | Route::post('exam/grade', 'ExamController@gradeIndex') 312 | ->name('exam.grade.destroy'); 313 | Route::get('exam/grade/create', 'ExamController@gradeCru') 314 | ->name('exam.grade.create'); 315 | Route::post('exam/grade/create', 'ExamController@gradeCru') 316 | ->name('exam.grade.store'); 317 | Route::get('exam/grade/edit/{id}', 'ExamController@gradeCru') 318 | ->name('exam.grade.edit'); 319 | Route::post('exam/grade/update/{id}', 'ExamController@gradeCru') 320 | ->name('exam.grade.update'); 321 | //exam rules 322 | Route::get('exam/rule', 'ExamController@ruleIndex') 323 | ->name('exam.rule.index'); 324 | Route::post('exam/rule', 'ExamController@ruleIndex') 325 | ->name('exam.rule.destroy'); 326 | Route::get('exam/rule/create', 'ExamController@ruleCreate') 327 | ->name('exam.rule.create'); 328 | Route::post('exam/rule/create', 'ExamController@ruleCreate') 329 | ->name('exam.rule.store'); 330 | Route::get('exam/rule/edit/{id}', 'ExamController@ruleEdit') 331 | ->name('exam.rule.edit'); 332 | Route::post('exam/rule/update/{id}', 'ExamController@ruleEdit') 333 | ->name('exam.rule.update'); 334 | 335 | //Marks 336 | Route::any('marks', 'MarkController@index') 337 | ->name('marks.index'); 338 | Route::any('marks/create', 'MarkController@create') 339 | ->name('marks.create'); 340 | Route::post('marks/store', 'MarkController@store') 341 | ->name('marks.store'); 342 | Route::get('marks/edit/{id}', 'MarkController@edit') 343 | ->name('marks.edit'); 344 | Route::post('marks/update/{id}', 'MarkController@update') 345 | ->name('marks.update'); 346 | //result 347 | Route::any('result', 'MarkController@resultIndex') 348 | ->name('result.index'); 349 | Route::any('result/generate', 'MarkController@resultGenerate') 350 | ->name('result.create'); 351 | Route::any('result/delete', 'MarkController@resultDelete') 352 | ->name('result.delete'); 353 | 354 | // Reporting 355 | 356 | Route::any('report/student-monthly-attendance', 'ReportController@studentMonthlyAttendance') 357 | ->name('report.student_monthly_attendance'); 358 | Route::any('report/student-list', 'ReportController@studentList') 359 | ->name('report.student_list'); 360 | Route::any('report/employee-list', 'ReportController@employeeList') 361 | ->name('report.employee_list'); 362 | Route::any('report/employee-monthly-attendance', 'ReportController@employeeMonthlyAttendance') 363 | ->name('report.employee_monthly_attendance'); 364 | 365 | }); 366 | 367 | //web artisan routes 368 | Route::get( 369 | '/student-attendance-file-queue-start/{code}', function ($code) { 370 | if($code == "hr799"){ 371 | try { 372 | echo '
Started student attendance processing...
'; 373 | Artisan::call('attendance:seedStudent'); 374 | echo '
Student attendance processing completed.
You will be redirect in 5 seconds.
'; 375 | sleep(5); 376 | 377 | return redirect()->route('student_attendance.create_file')->with("success", "Students attendance saved and send sms successfully."); 378 | 379 | } catch (Exception $e) { 380 | Response::make($e->getMessage(), 500); 381 | } 382 | }else{ 383 | App::abort(404); 384 | } 385 | } 386 | )->name('student_attendance_seeder'); 387 | Route::get( 388 | '/employee-attendance-file-queue-start/{code}', function ($code) { 389 | if($code == "hr799"){ 390 | try { 391 | echo '
Started employee attendance processing...
'; 392 | Artisan::call('attendance:seedEmployee'); 393 | echo '
Employee attendance processing completed.
You will be redirect in 5 seconds.
'; 394 | sleep(5); 395 | 396 | return redirect()->route('employee_attendance.create_file')->with("success", "Employee attendance saved and notify successfully."); 397 | 398 | } catch (Exception $e) { 399 | Response::make($e->getMessage(), 500); 400 | } 401 | }else{ 402 | App::abort(404); 403 | } 404 | } 405 | )->name('employee_attendance_seeder'); 406 | 407 | //dev routes 408 | Route::get( 409 | '/make-link/{code}', function ($code) { 410 | if($code !== '007') { 411 | return 'Wrong code!'; 412 | } 413 | 414 | //check if developer mode enabled? 415 | if(!env('DEVELOPER_MODE_ENABLED', false)) { 416 | return "Please enable developer mode in '.env' file.".PHP_EOL."set 'DEVELOPER_MODE_ENABLED=true'"; 417 | } 418 | //remove first 419 | if(is_link(public_path('storage'))){ 420 | unlink(public_path('storage')); 421 | } 422 | 423 | 424 | //create symbolic link for public image storage 425 | App::make('files')->link(storage_path('app/public'), public_path('storage')); 426 | return 'Done link'; 427 | } 428 | ); 429 | Route::get( 430 | '/cache-clear/{code}', function ($code) { 431 | if($code !== '007') { 432 | return 'Wrong code!'; 433 | } 434 | 435 | //check if developer mode enabled? 436 | if(!env('DEVELOPER_MODE_ENABLED', false)) { 437 | return "Please enable developer mode in '.env' file.".PHP_EOL."set 'DEVELOPER_MODE_ENABLED=true'"; 438 | } 439 | 440 | $exitCode = Artisan::call('cache:clear'); 441 | $exitCode = Artisan::call('config:clear'); 442 | $exitCode = Artisan::call('view:clear'); 443 | $exitCode = Artisan::call('route:clear'); 444 | return 'clear cache'; 445 | } 446 | ); 447 | //create tiggers 448 | Route::get( 449 | '/create-triggers/{code}', function ($code) { 450 | if($code !== '007') { 451 | return 'Wrong code!'; 452 | } 453 | 454 | //check if developer mode enabled? 455 | if(!env('DEVELOPER_MODE_ENABLED', false)) { 456 | return "Please enable developer mode in '.env' file.".PHP_EOL."set 'DEVELOPER_MODE_ENABLED=true'"; 457 | } 458 | 459 | AppHelper::createTriggers(); 460 | 461 | return 'Triggers created :)'; 462 | } 463 | ); 464 | //test sms send 465 | Route::get( 466 | '/test-sms/{code}', function ($code) { 467 | if($code !== '007') { 468 | return 'Wrong code!'; 469 | } 470 | //check if developer mode enabled? 471 | if(!env('DEVELOPER_MODE_ENABLED', false)) { 472 | return "Please enable developer mode in '.env' file.".PHP_EOL."set 'DEVELOPER_MODE_ENABLED=true'"; 473 | } 474 | 475 | $gateway = \App\AppMeta::where('id', AppHelper::getAppSettings('student_attendance_gateway'))->first(); 476 | $gateway = json_decode($gateway->meta_value); 477 | $smsHelper = new \App\Http\Helpers\SmsHelper($gateway); 478 | $res = $smsHelper->sendSms('8801722813644','test sms vai'); 479 | dd($res); 480 | } 481 | ); 482 | --------------------------------------------------------------------------------