diff --git a/.DS_Store b/.DS_Store index 8b3e561..867c39e 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/Admin/HomeController.php similarity index 87% rename from app/Http/Controllers/HomeController.php rename to app/Http/Controllers/Admin/HomeController.php index cdde33d..7cc1ae3 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/Admin/HomeController.php @@ -1,8 +1,9 @@ update($request->user()->id, $request->all()); + $request->session()->flash('success', trans('app.profile.update_success')); return redirect()->route('profile.index'); } diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index a13071d..dd9a041 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -3,7 +3,11 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; +use App\User; use Illuminate\Foundation\Auth\AuthenticatesUsers; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Input; class LoginController extends Controller { diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index cf726ee..2c863aa 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -25,7 +25,7 @@ class ResetPasswordController extends Controller * * @var string */ - protected $redirectTo = '/home'; + protected $redirectTo = '/'; /** * Create a new controller instance. diff --git a/app/Http/Controllers/Employee/HomeController.php b/app/Http/Controllers/Employee/HomeController.php new file mode 100644 index 0000000..7db80af --- /dev/null +++ b/app/Http/Controllers/Employee/HomeController.php @@ -0,0 +1,18 @@ + \Illuminate\Routing\Middleware\ThrottleRequests::class, 'admin' => \App\Http\Middleware\RedirectIfNotAdmin::class, 'app_setup' => \App\Http\Middleware\AppSetupRegister::class, + 'employee' => \App\Http\Middleware\RedirectIfNotEmployee::class, ]; } diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index e27860e..5ff38e6 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -2,6 +2,7 @@ namespace App\Http\Middleware; +use App\User; use Closure; use Illuminate\Support\Facades\Auth; @@ -18,7 +19,11 @@ class RedirectIfAuthenticated public function handle($request, Closure $next, $guard = null) { if (Auth::guard($guard)->check()) { - return redirect('/'); + if (Auth::user()->role == User::USER_ROLE_EMPLOYEE) { + return redirect()->to('/employee'); + } else if (Auth::user()->role == User::USER_ROLE_ADMIN) { + return redirect()->to('/admin'); + } } return $next($request); diff --git a/app/Http/Middleware/RedirectIfNotAdmin.php b/app/Http/Middleware/RedirectIfNotAdmin.php index fd12661..effcd84 100644 --- a/app/Http/Middleware/RedirectIfNotAdmin.php +++ b/app/Http/Middleware/RedirectIfNotAdmin.php @@ -19,7 +19,7 @@ class RedirectIfNotAdmin public function handle($request, Closure $next, $guard = null) { if ($request->user()->role != User::USER_ROLE_ADMIN) { - return redirect('/'); + return redirect()->back(); } return $next($request); diff --git a/app/Http/Middleware/RedirectIfNotEmployee.php b/app/Http/Middleware/RedirectIfNotEmployee.php new file mode 100644 index 0000000..8b50a22 --- /dev/null +++ b/app/Http/Middleware/RedirectIfNotEmployee.php @@ -0,0 +1,26 @@ +user()->role != User::USER_ROLE_EMPLOYEE) { + return redirect()->back(); + } + + return $next($request); + } +} diff --git a/app/Http/Requests/ProfileRequest.php b/app/Http/Requests/ProfileRequest.php index fec540f..639cb2f 100644 --- a/app/Http/Requests/ProfileRequest.php +++ b/app/Http/Requests/ProfileRequest.php @@ -27,9 +27,10 @@ public function rules() $rules = [ 'first_name' => ['required'], 'last_name' => ['required'], - 'gender' => ['required'], - 'birth_date' => ['required'] + 'gender' => ['in:m,f'], + 'birth_date' => ['date'] ]; + $rules['email'] = [ 'required', 'email', diff --git a/app/Http/helpers.php b/app/Http/helpers.php index b80b683..4ed2a9c 100644 --- a/app/Http/helpers.php +++ b/app/Http/helpers.php @@ -169,4 +169,11 @@ function get_user_role($role) function get_current_date() { return Carbon\Carbon::now()->format('Y-m-d'); +} + +function checkValidity($id) +{ + if($id != Auth::user()->id) { + abort(403, 'Unauthorized action.'); + } } \ No newline at end of file diff --git a/app/Modules/Dashboard/Http/Controllers/DashboardDocumentsController.php b/app/Modules/Dashboard/Http/Controllers/DashboardDocumentsController.php new file mode 100644 index 0000000..db561dd --- /dev/null +++ b/app/Modules/Dashboard/Http/Controllers/DashboardDocumentsController.php @@ -0,0 +1,95 @@ +dashboardDocumentsRepository = $dashboardDocumentsRepository; + } + + public function index() + { + return view('dashboard::documents.index'); + } + + /** + * Returns data for the resource list + * + * @return \Illuminate\Http\Response + */ + public function getDatatable() + { + return Datatables::of($this->dashboardDocumentsRepository->getCollection([], ['id', 'name'])) + ->addColumn('actions', function($document){ + return view('includes._datatable_actions', [ + 'editUrl' => route('dashboard.documents.edit', $document->id), + 'deleteUrl' => route('dashboard.documents.destroy', $document->id), + 'downloadUrl' => route('dashboard.documents.download', $document->id) + ]); + }) + ->make(); + } + + public function create() + { + return view('dashboard::documents.create'); + } + + public function edit($id) + { + $document = $this->dashboardDocumentsRepository->getById($id); + $breadcrumb = [ + 'id' => $document->id, + 'title' => $document->name + ]; + return view('dashboard::documents.edit', compact('document', 'breadcrumb')); + } + + public function store(DashboardDocumentRequest $request) { + $documentData = $request->all(); + $attachment = $request->attachment->store('uploads/documents'); + $documentData['attachment'] = $attachment; + $documentData = $this->dashboardDocumentsRepository->create($documentData); + $request->session()->flash('success', trans('app.dashboard.documents.store_success')); + + return redirect()->route('dashboard.documents.edit', [$documentData->id]); + } + + public function update($id, DashboardDocumentRequest $request) + { + $documentData = $request->all(); + if($request->hasFile('attachment')) { + $attachment = $request->attachment->store('uploads/documents'); + $documentData['attachment'] = $attachment; + } + $documentData = $this->dashboardDocumentsRepository->update($id, $documentData); + $request->session()->flash('success', trans('app.dashboard.documents.update_success')); + + return redirect()->route('dashboard.documents.edit', [$documentData->id]); + } + + public function destroy($id, Request $request) { + $this->dashboardDocumentsRepository->delete($id); + $request->session()->flash('success', trans('app.dashboard.documents.delete_success')); + + return redirect()->route('dashboard.documents.index'); + } + + public function download($id) + { + $document = $this->dashboardDocumentsRepository->getById($id); + return response()->download(base_path('storage/app/' . $document->attachment)); + } + +} \ No newline at end of file diff --git a/app/Modules/Dashboard/Http/Requests/DashboardDocumentRequest.php b/app/Modules/Dashboard/Http/Requests/DashboardDocumentRequest.php new file mode 100644 index 0000000..7c51825 --- /dev/null +++ b/app/Modules/Dashboard/Http/Requests/DashboardDocumentRequest.php @@ -0,0 +1,38 @@ + ['required'], + // 'attachment' => ['mimes:png,jpg,pdf,xls,xlsx,csv,txt,doc,docx'] + ]; + + if(!preg_match('/update/', Route::currentRouteName())) { + $rules['attachment'][] = 'required'; + } + + return $rules; + } +} diff --git a/app/Modules/Dashboard/Models/DashboardDocument.php b/app/Modules/Dashboard/Models/DashboardDocument.php new file mode 100644 index 0000000..bbb2255 --- /dev/null +++ b/app/Modules/Dashboard/Models/DashboardDocument.php @@ -0,0 +1,12 @@ +model = $model; + } +} \ No newline at end of file diff --git a/app/Modules/Dashboard/Repositories/Interfaces/DashboardDocumentsRepositoryInterface.php b/app/Modules/Dashboard/Repositories/Interfaces/DashboardDocumentsRepositoryInterface.php new file mode 100644 index 0000000..e8e322d --- /dev/null +++ b/app/Modules/Dashboard/Repositories/Interfaces/DashboardDocumentsRepositoryInterface.php @@ -0,0 +1,7 @@ + + {!! Form::label('name', trans('app.dashboard.documents.name').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::text('name', null, ['class' => 'form-control']) !!} +
+ +
+ {!! Form::label('description', trans('app.dashboard.documents.description').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::textarea('description', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('attachment', trans('app.dashboard.documents.attachment').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::input('file', 'attachment', null, ['class' => 'form-control']) !!} +
+
+@if(@$document->attachment) +
+
+ {{trans('app.dashboard.documents.attachment')}} +
+
+@endif +@include('errors._form-errors') +
+
+
+ {{trans('app.cancel')}} + {!! Form::submit($submitName, ['class' => 'btn btn-primary']) !!} +
+
\ No newline at end of file diff --git a/app/Modules/Dashboard/resources/views/documents/create.blade.php b/app/Modules/Dashboard/resources/views/documents/create.blade.php new file mode 100644 index 0000000..cd4716d --- /dev/null +++ b/app/Modules/Dashboard/resources/views/documents/create.blade.php @@ -0,0 +1,13 @@ +@extends('layouts.main') +@section('content') +
+
+
+
{{trans('app.dashboard.documents.add_new')}}
+ {!! Form::open(['route' => 'dashboard.documents.store', 'files' => true, 'class' => 'form-horizontal']) !!} + @include('dashboard::documents._form', ['submitName' => trans('app.submit')]) + {!! Form::close() !!} +
+
+
+@endsection \ No newline at end of file diff --git a/app/Modules/Dashboard/resources/views/documents/edit.blade.php b/app/Modules/Dashboard/resources/views/documents/edit.blade.php new file mode 100644 index 0000000..a5178aa --- /dev/null +++ b/app/Modules/Dashboard/resources/views/documents/edit.blade.php @@ -0,0 +1,13 @@ +@extends('layouts.main') +@section('content') +
+
+
+
{{trans('app.dashboard.documents.edit_details')}}
+ {!! Form::model($document, ['method' => 'PUT', 'route' => ['dashboard.documents.update', $document->id], 'class' => 'form-horizontal', 'files' => true]) !!} + @include('dashboard::documents._form', ['submitName' => trans('app.submit')]) + {!! Form::close() !!} +
+
+
+@endsection \ No newline at end of file diff --git a/app/Modules/Dashboard/resources/views/documents/index.blade.php b/app/Modules/Dashboard/resources/views/documents/index.blade.php new file mode 100644 index 0000000..f3213b5 --- /dev/null +++ b/app/Modules/Dashboard/resources/views/documents/index.blade.php @@ -0,0 +1,68 @@ +@extends('layouts.main') +@section('content') +
+
+ {{trans('app.dashboard.documents.add_new')}} +
+
+
+
+
+
{{trans('app.dashboard.documents.main')}}
+ + + + + + + + + + + +
{{trans('app.id')}}{{trans('app.dashboard.documents.name')}}
+ + + +
+
+
+
+@endsection +@section('additionalCSS') + +@endsection +@section('additionalJS') + + +@endsection \ No newline at end of file diff --git a/app/Modules/Dashboard/resources/views/index.blade.php b/app/Modules/Dashboard/resources/views/index.blade.php new file mode 100644 index 0000000..58e3099 --- /dev/null +++ b/app/Modules/Dashboard/resources/views/index.blade.php @@ -0,0 +1,13 @@ +@extends('layouts.main') +@section('content') +
+
+ +

{{trans('app.dashboard.documents.main')}}

+
+
+
+@endsection +@section('additionalCSS') + +@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Dashboard/Http/Controllers/EmployeeDashboardDocumentsController.php b/app/Modules/Employee/Dashboard/Http/Controllers/EmployeeDashboardDocumentsController.php new file mode 100644 index 0000000..269b0ee --- /dev/null +++ b/app/Modules/Employee/Dashboard/Http/Controllers/EmployeeDashboardDocumentsController.php @@ -0,0 +1,48 @@ +dashboardDocumentsRepository = $dashboardDocumentsRepository; + } + + public function index() + { + return view('employee.dashboard_documents::index'); + } + + /** + * Returns data for the resource list + * + * @return \Illuminate\Http\Response + */ + public function getDatatable() + { + return Datatables::of($this->dashboardDocumentsRepository->getCollection([], ['id', 'name'])) + ->addColumn('actions', function($document){ + return view('includes._datatable_actions', [ + 'downloadUrl' => route('employee.dashboard_documents.download', $document->id) + ]); + }) + ->make(); + } + + public function download($id) + { + $document = $this->dashboardDocumentsRepository->getById($id); + return response()->download(base_path('storage/app/' . $document->attachment)); + } +} \ No newline at end of file diff --git a/app/Modules/Employee/Dashboard/resources/views/index.blade.php b/app/Modules/Employee/Dashboard/resources/views/index.blade.php new file mode 100644 index 0000000..cfe2b8f --- /dev/null +++ b/app/Modules/Employee/Dashboard/resources/views/index.blade.php @@ -0,0 +1,63 @@ +@extends('layouts.main_employee') +@section('content') +
+
+
+
{{trans('app.dashboard.documents.main')}}
+ + + + + + + + + + + +
{{trans('app.id')}}{{trans('app.dashboard.documents.name')}}
+ + + +
+
+
+
+@endsection +@section('additionalCSS') + +@endsection +@section('additionalJS') + + +@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Leaves/Http/Controllers/LeavesController.php b/app/Modules/Employee/Leaves/Http/Controllers/LeavesController.php new file mode 100644 index 0000000..f435c71 --- /dev/null +++ b/app/Modules/Employee/Leaves/Http/Controllers/LeavesController.php @@ -0,0 +1,167 @@ +employeeLeaveRepository = $employeeLeaveRepository; + } + + /** + * Display a listing of the resource. + * + * @param \App\Modules\Leave\Repositories\LeaveTypeRepository $leaveTypeRepository + * @param \App\Modules\Pim\Repositories\EmployeeRepository $employeeRepository + * @return \Illuminate\Http\Response + */ + public function index(LeaveTypeRepository $leaveTypeRepository, EmployeeRepository $employeeRepository) + { + $leaveTypes = $leaveTypeRepository->getAll()->pluck('name', 'id'); + $employees = $employeeRepository->getById(Auth::user()->id)->pluck('first_name', 'id'); + + return view('employee.leaves::index', compact('leaveTypes','employees')); + } + + /** + * Returns data for the resource list + * + * @return \Illuminate\Http\Response + */ + public function getDatatable(EmployeeRepository $employeeRepository) + { + return Datatables::of($this->employeeLeaveRepository->getCollection([[ + 'key' => 'user_id', + 'operator' => '=', + 'value' => Auth::user()->id + ]], ['id', 'leave_type_id', 'start_date', 'end_date', 'approved'])) + ->editColumn('leave_type_id', function($leave) { + return $leave->leave_type->name; + }) + ->editColumn('approved', function($leave) { + return $leave->approved ? trans('app.employee.leaves.approved') : trans('app.employee.leaves.pending'); + }) + ->addColumn('actions', function($leave){ + if($leave->approved) { + return view('includes._datatable_actions', [ + 'showUrl' => route('employee.leaves.show', $leave->id) + ]); + } else { + return view('includes._datatable_actions', [ + 'deleteUrl' => route('employee.leaves.destroy', $leave->id), + 'editUrl' => route('employee.leaves.edit', $leave->id) + ]); + } + }) + ->make(); + } + + /** + * Show the form for creating a new resource. + * + * @param \App\Modules\Leave\Repositories\LeaveTypeRepository $leaveTypeRepository + * @param \App\Modules\Pim\Repositories\EmployeeRepository $employeeRepository + * @return \Illuminate\Http\Response + */ + public function create(LeaveTypeRepository $leaveTypeRepository, EmployeeRepository $employeeRepository) + { + $leaveTypes = $leaveTypeRepository->getAll()->pluck('name', 'id'); + $employees = $employeeRepository->getById(Auth::user()->id)->pluck('first_name', 'id'); + + return view('employee.leaves::create', compact('leaveTypes', 'employees')); + } + + /** + * Store a newly created resource in storage. + * + * @param \App\Modules\Leave\Http\Requests\EmployeeLeaveRequest $request + * @return \Illuminate\Http\Response + */ + public function store(LeaveRequest $request) + { + $employeeLeaveData = $request->all()+['user_id' => Auth::user()->id, 'approved' => 0]; + $employeeLeaveData = $this->employeeLeaveRepository->create($employeeLeaveData); + $this->employeeLeaveRepository->updateStatus($employeeLeaveData->user_id, $employeeLeaveData->leave_type_id, $employeeLeaveData->start_date, $employeeLeaveData->end_date); + return redirect()->route('employee.leaves.edit', $employeeLeaveData->id)->with('success', trans('app.employee.leaves.store_success')); + } + + /** + * Display the specified resource. + * + * @param integer unique identifier for the resource + * @return \Illuminate\Http\Response + */ + public function show($id) + { + $leave = $this->employeeLeaveRepository->getById($id); + $breadcrumb = ['title' => '#'.$leave->id, 'id' => $leave->id]; + return view('employee.leaves::show', compact('leave', 'breadcrumb')); + } + + /** + * Show the form for editing the specified resource. + * + * @param integer unique identifier for the resource + * @param \App\Modules\Leave\Repositories\LeaveTypeRepository $leaveTypeRepository + * @param \App\Modules\Pim\Repositories\EmployeeRepository $employeeRepository + * @return \Illuminate\Http\Response + */ + public function edit($id, LeaveTypeRepository $leaveTypeRepository, EmployeeRepository $employeeRepository) + { + $employeeLeave = $this->employeeLeaveRepository->getById($id); + checkValidity($employeeLeave->user_id); + $leaveTypes = $leaveTypeRepository->getAll()->pluck('name', 'id'); + $breadcrumb = ['title' => '#'.$employeeLeave->id, 'id' => $employeeLeave->id]; + $employees = $employeeRepository->getById(Auth::user()->id)->pluck('first_name', 'id'); + return view('employee.leaves::edit', compact('employeeLeave', 'leaveTypes', 'breadcrumb','employees')); + } + + /** + * Update the specified resource in storage. + * + * @param integer unique identifier for the resource + * @param \App\Modules\Leave\Http\Requests\EmployeeLeaveRequest $request + * @return \Illuminate\Http\Response + */ + public function update($id, LeaveRequest $request) + { + $employeeLeaveData = $this->employeeLeaveRepository->getById($id); + checkValidity($employeeLeaveData->user_id); + $this->employeeLeaveRepository->deleteUsedDays($employeeLeaveData->user_id, $employeeLeaveData->leave_type_id, $employeeLeaveData->start_date, $employeeLeaveData->end_date); + $employeeLeaveData = $request->all(); + $employeeLeaveData = $this->employeeLeaveRepository->update($id, $employeeLeaveData); + $this->employeeLeaveRepository->updateStatus($employeeLeaveData->user_id, $employeeLeaveData->leave_type_id, $employeeLeaveData->start_date, $employeeLeaveData->end_date); + $request->session()->flash('success', trans('app.employee.leaves.update_success')); + return redirect()->route('employee.leaves.edit', $employeeLeaveData->id); + } + + /** + * Remove the specified resource from storage. + * + * @param integer unique identifier for the resource + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function destroy($id, Request $request) + { + $employeeLeaveData = $this->employeeLeaveRepository->getById($id); + checkValidity($employeeLeaveData->user_id); + $this->employeeLeaveRepository->deleteUsedDays($employeeLeaveData->user_id, $employeeLeaveData->leave_type_id, $employeeLeaveData->start_date, $employeeLeaveData->end_date); + $this->employeeLeaveRepository->delete($id); + $request->session()->flash('success', trans('app.employee.leaves.delete_success')); + return redirect()->route('employee.leaves.index'); + } +} \ No newline at end of file diff --git a/app/Modules/Employee/Leaves/Http/Requests/LeaveRequest.php b/app/Modules/Employee/Leaves/Http/Requests/LeaveRequest.php new file mode 100644 index 0000000..7af383b --- /dev/null +++ b/app/Modules/Employee/Leaves/Http/Requests/LeaveRequest.php @@ -0,0 +1,69 @@ +employeeLeaveRepository = $employeeLeaveRepository; + } + + /** + * Determine if the user is authorized to make this request. + * + * @return bool + */ + public function authorize() + { + return true; + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'leave_type_id' => ['required'], + 'start_date' => ['required', 'after:now'], + 'end_date' => ['required', 'after:start_date'] + ]; + } + + protected function getValidatorInstance() + { + $validator = parent::getValidatorInstance(); + + if($validator->errors()->any()) { + return $validator; + } + + $validator->after(function($validator) { + + $available = $this->employeeLeaveRepository->checkAvailableDays( + Auth::user()->id, + $this->get('leave_type_id'), + $this->get('start_date'), + $this->get('end_date'), + Route::input('employee_eeaf') + ); + + if(!$available['status']) { + $validator->errors()->add('end_date', trans('app.leave.employee_leaves.error_no_available_days', ['days' => $available['availableDays']])); + } + }); + + return $validator; + } +} diff --git a/app/Modules/Employee/Leaves/resources/views/_form.blade.php b/app/Modules/Employee/Leaves/resources/views/_form.blade.php new file mode 100644 index 0000000..9df1c7f --- /dev/null +++ b/app/Modules/Employee/Leaves/resources/views/_form.blade.php @@ -0,0 +1,35 @@ +
+ {!! Form::label('leave_type_id', trans('app.leave.employee_leaves.leave'), ['class' => 'col-sm-3']) !!} +
+ {!! Form::select('leave_type_id', $leaveTypes, null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('start_date', trans('app.leave.employee_leaves.start_date').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::input('date', 'start_date', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('end_date', trans('app.leave.employee_leaves.end_date').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::input('date', 'end_date', null, ['class' => 'form-control']) !!} +
+
+@include('errors._form-errors') +
+
+
+ {{trans('app.cancel')}} + {!! Form::submit($submitName, ['class' => 'btn btn-primary']) !!} +
+
+@section('additionalCSS') + +@endsection +@section('additionalJS') + + +@endsection diff --git a/app/Modules/Employee/Leaves/resources/views/create.blade.php b/app/Modules/Employee/Leaves/resources/views/create.blade.php new file mode 100644 index 0000000..4a3b19b --- /dev/null +++ b/app/Modules/Employee/Leaves/resources/views/create.blade.php @@ -0,0 +1,13 @@ +@extends('layouts.main_employee') +@section('content') +
+
+
+
{{trans('app.leave.employee_leaves.add_new')}}
+ {!! Form::open(['route' => 'employee.leaves.store', 'class' => 'form-horizontal', 'enctype' => 'multipart/form-data']) !!} + @include('employee.leaves::_form', ['submitName' => trans('app.submit')]) + {!! Form::close() !!} +
+
+
+@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Leaves/resources/views/edit.blade.php b/app/Modules/Employee/Leaves/resources/views/edit.blade.php new file mode 100644 index 0000000..069dbfe --- /dev/null +++ b/app/Modules/Employee/Leaves/resources/views/edit.blade.php @@ -0,0 +1,13 @@ +@extends('layouts.main_employee') +@section('content') +
+
+
+
{{trans('app.leave.employee_leaves.edit_details')}}
+ {!! Form::model($employeeLeave, ['method' => 'PUT', 'route' => ['employee.leaves.update', $employeeLeave->id], 'class' => 'form-horizontal', 'enctype' => 'multipart/form-data']) !!} + @include('employee.leaves::_form', ['submitName' => trans('app.submit')]) + {!! Form::close() !!} +
+
+
+@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Leaves/resources/views/index.blade.php b/app/Modules/Employee/Leaves/resources/views/index.blade.php new file mode 100644 index 0000000..c13e117 --- /dev/null +++ b/app/Modules/Employee/Leaves/resources/views/index.blade.php @@ -0,0 +1,77 @@ +@extends('layouts.main_employee') +@section('content') +
+
+ {{trans('app.employee.leaves.request')}} +
+
+
+
+
+
{{trans('app.leave.employee_leaves.main')}}
+ + + + + + + + + + + + + + + + + +
{{trans('app.id')}}{{trans('app.leave.employee_leaves.leave')}}{{trans('app.leave.employee_leaves.start_date')}}{{trans('app.leave.employee_leaves.end_date')}}{{trans('app.status')}}
+ + + {!! Form::select('leave_type_id', $leaveTypes, null, ['placeholder' => trans('app.leave.employee_leaves.leave')]) !!} + + + + +
+
+
+
+@endsection +@section('additionalCSS') + +@endsection +@section('additionalJS') + + +@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Leaves/resources/views/show.blade.php b/app/Modules/Employee/Leaves/resources/views/show.blade.php new file mode 100644 index 0000000..209d7fb --- /dev/null +++ b/app/Modules/Employee/Leaves/resources/views/show.blade.php @@ -0,0 +1,26 @@ +@extends('layouts.main') +@section('content') +
+
+
+
{{trans('app.employee.leaves.details')}}
+

+ {{trans('app.leave.employee_leaves.leave')}}: + {{$leave->leave_type->name}} +

+

+ {{trans('app.leave.employee_leaves.start_date')}}: + {{$leave->start_date}} +

+

+ {{trans('app.leave.employee_leaves.end_date')}}: + {{$leave->end_date}} +

+ @if(@$employeeLeave->attachment) +

{{trans('app.leave.employee_leaves.attachment')}}

+
+ @endif +
+
+ +@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Salary/Http/Controllers/SalaryController.php b/app/Modules/Employee/Salary/Http/Controllers/SalaryController.php new file mode 100644 index 0000000..d7be1bb --- /dev/null +++ b/app/Modules/Employee/Salary/Http/Controllers/SalaryController.php @@ -0,0 +1,92 @@ +employeeRepository = $employeeRepository; + $this->employeeSalaryRepository = $employeeSalaryRepository; + } + + /** + * Display a listing of the resource. + * + * @param integer unique identifier for the related employee resource + * @return \Illuminate\Http\Response + */ + public function index() + { + $employee = Auth::user(); + $breadcrumb = [ + 'parent_id' => $employee->id, + 'parent_title' => $employee->first_name.' '.$employee->last_name + ]; + return view('employee.salary::index', compact('breadcrumb')); + } + + /** + * Returns data for the resource list + * + * @param integer unique identifier for the related employee resource + * @return \Illuminate\Http\Response + */ + public function getDatatable() + { + return Datatables::of($this->employeeSalaryRepository->getCollection([[ + 'key' => 'user_id', + 'operator' => '=', + 'value' => Auth::user()->id + ]], ['id', 'gross_total', 'nett_total', 'payment_date', 'attachment', 'user_id'])) + ->addColumn('actions', function($record){ + return view('includes._datatable_actions', [ + 'showUrl' => route('employee.salary.show', $record->id), + 'downloadUrl' => ($record->attachment ? route('employee.salary.download', [$record->user_id, $record->id]) : '') + ]); + }) + ->removeColumn('attachment') + ->removeColumn('user_id') + ->make(); + } + + public function show($id, SalaryComponentsRepository $salaryComponentsRepository, SalariesSalaryComponentsRepository $salariesSalaryComponentsRepository) + { + $salary = $this->employeeSalaryRepository->getById($id); + checkValidity($salary->user_id); + $employee = Auth::user(); + $salaryComponents = $salaryComponentsRepository->getAllOrdered('type', 'asc'); + $components = []; + for($i = 0; $i < count($salary->components); $i++) { + $components[$i] = $salary->components[$i]->value; + } + $salary->components = $components; + $breadcrumb = [ + 'parent_id' => $employee->id, + 'parent_title' => $employee->first_name.' '.$employee->last_name, + 'id' => $salary->id, + 'title' => '#'.$salary->id + ]; + return view('employee.salary::show', compact('salary', 'breadcrumb', 'salaryComponents')); + } + + public function downloadReport(Request $request) + { + $salary = $this->employeeSalaryRepository->getById($request->salary_id); + checkValidity($salary->user_id); + return response()->download(base_path('storage/app/' . $salary->attachment)); + } +} \ No newline at end of file diff --git a/app/Modules/Employee/Salary/resources/views/index.blade.php b/app/Modules/Employee/Salary/resources/views/index.blade.php new file mode 100644 index 0000000..69a9dfb --- /dev/null +++ b/app/Modules/Employee/Salary/resources/views/index.blade.php @@ -0,0 +1,64 @@ +@extends('layouts.main_employee') +@section('content') +
+
+
+
{{trans('app.pim.employees.salaries.salary_history')}}
+ + + + + + + + + + + + + + + +
{{trans('app.id')}}{{trans('app.pim.employees.salaries.gross_total')}}{{trans('app.pim.employees.salaries.nett_total')}}{{trans('app.pim.employees.salaries.payment_date')}}
+ + + + + + + +
+
+
+
+@endsection +@section('additionalCSS') + +@endsection +@section('additionalJS') + + +@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Salary/resources/views/show.blade.php b/app/Modules/Employee/Salary/resources/views/show.blade.php new file mode 100644 index 0000000..4c5d72e --- /dev/null +++ b/app/Modules/Employee/Salary/resources/views/show.blade.php @@ -0,0 +1,22 @@ +@extends('layouts.main_employee') +@section('content') +
+@foreach($salaryComponents as $key => $component) +
+ {!! Form::label('components['.$component->id.']', $component->name.':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::text('components['.$component->id.']', $salary->components[$key++], ['class' => 'form-control', 'readonly']) !!} +
+
+@endforeach +
+ {!! Form::label('payment_date', trans('app.pim.employees.salaries.payment_date').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::input('date','payment_date', $salary->payment_date, ['class' => 'form-control', 'readonly']) !!} +
+
+
+@endsection +@section('additionalCSS') + +@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Time/Http/Controllers/TimeController.php b/app/Modules/Employee/Time/Http/Controllers/TimeController.php new file mode 100644 index 0000000..f0ec312 --- /dev/null +++ b/app/Modules/Employee/Time/Http/Controllers/TimeController.php @@ -0,0 +1,136 @@ +timeLogRepository = $timeLogRepository; + } + + /** + * Display a listing of the resource. + * + * @param \App\Modules\Time\Repositories\Interfaces\ProjectRepositoryInterface $projectRepository + * @param App\Modules\Pim\Repositories\Interfaces\EmployeeRepositoryInterface $employeeRepository + * @return \Illuminate\Http\Response + */ + public function index(ProjectRepository $projectRepository, EmployeeRepository $employeeRepository) + { + $projects = $projectRepository->getAll()->pluck('name', 'id'); + $employees = $employeeRepository->getById(Auth::user()->id)->pluck('first_name', 'id'); + return view('employee.time::index', compact('projects', 'employees')); + } + + /** + * Returns data for the resource list + * + * @return \Illuminate\Http\Response + */ + public function getDatatable() + { + return Datatables::of($this->timeLogRepository->getCollection([[ + 'key' => 'user_id', + 'operator' => '=', + 'value' => Auth::user()->id + ]], ['id', 'task_name', 'project_id', 'time', 'date'])) + ->editColumn('project_id', function($time) { + return $time->project->name; + }) + ->addColumn('actions', function($time){ + return view('includes._datatable_actions', [ + 'deleteUrl' => route('employee.time.destroy', $time->id), + 'editUrl' => route('employee.time.edit', $time->id) + ]); + }) + ->make(); + } + + /** + * Show the form for creating a new resource. + * + * @param \App\Modules\Time\Repositories\Interfaces\ProjectRepositoryInterface $projectRepository + * @param App\Modules\Pim\Repositories\Interfaces\EmployeeRepositoryInterface $employeeRepository + * @return \Illuminate\Http\Response + */ + public function create(ProjectRepository $projectRepository, EmployeeRepository $employeeRepository) + { + $projects = $projectRepository->getAll()->pluck('name', 'id'); + return view('employee.time::create', compact('projects')); + } + + /** + * Store a newly created resource in storage. + * + * @param \App\Modules\Employee\Time\Http\Requests\EmployeeTimeLogRequest $request + * @return \Illuminate\Http\Response + */ + public function store(EmployeeTimeLogRequest $request) + { + $companyData = $request->all()+['user_id' => Auth::user()->id]; + $companyData = $this->timeLogRepository->create($companyData); + $request->session()->flash('success', trans('app.time.time_logs.store_success')); + return redirect()->route('employee.time.edit', $companyData->id); + } + + /** + * Show the form for editing the specified resource. + * + * @param integer unique identifier for the resource + * @param \App\Modules\Time\Repositories\Interfaces\ProjectRepositoryInterface $projectRepository + * @param App\Modules\Pim\Repositories\Interfaces\EmployeeRepositoryInterface $employeeRepository + * @return \Illuminate\Http\Response + */ + public function edit($id, ProjectRepository $projectRepository, EmployeeRepository $employeeRepository) + { + $timeLog = $this->timeLogRepository->getById($id); + checkValidity($timeLog->user_id); + $projects = $projectRepository->getAll()->pluck('name', 'id'); + $breadcrumb = ['title' => $timeLog->task_name, 'id' => $timeLog->id]; + return view('employee.time::edit', compact('timeLog', 'projects', 'breadcrumb')); + } + + /** + * Update the specified resource in storage. + * + * @param integer unique identifier for the resource + * @param \App\Modules\Employee\Time\Http\Requests\TimeLogRequest $request + * @return \Illuminate\Http\Response + */ + public function update($id, EmployeeTimeLogRequest $request) + { + $timeLogData = $this->timeLogRepository->getById($id); + checkValidity($timeLogData->user_id); + $timeLogData = $request->all(); + $timeLogData = $this->timeLogRepository->update($id, $timeLogData); + $request->session()->flash('success', trans('app.time.time_logs.update_success')); + return redirect()->route('employee.time.edit', $timeLogData->id); + } + + /** + * Remove the specified resource from storage. + * + * @param integer unique identifier for the resource + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function destroy($id, Request $request) + { + $timeLogData = $this->timeLogRepository->getById($id); + checkValidity($timeLogData->user_id); + $this->timeLogRepository->delete($id); + $request->session()->flash('success', trans('app.time.time_logs.delete_success')); + return redirect()->route('employee.time.index'); + } +} \ No newline at end of file diff --git a/app/Modules/Employee/Time/Http/Requests/EmployeeTimeLogRequest.php b/app/Modules/Employee/Time/Http/Requests/EmployeeTimeLogRequest.php new file mode 100644 index 0000000..ec92fc3 --- /dev/null +++ b/app/Modules/Employee/Time/Http/Requests/EmployeeTimeLogRequest.php @@ -0,0 +1,34 @@ + ['required'], + 'task_description' => ['required'], + 'project_id' => ['required'], + 'time' => ['required'], + 'date' => ['required'] + ]; + } +} diff --git a/app/Modules/Employee/Time/resources/views/_form.blade.php b/app/Modules/Employee/Time/resources/views/_form.blade.php new file mode 100644 index 0000000..945f1f8 --- /dev/null +++ b/app/Modules/Employee/Time/resources/views/_form.blade.php @@ -0,0 +1,47 @@ +
+ {!! Form::label('task_name', trans('app.time.time_logs.task_name').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::text('task_name', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('task_description', trans('app.time.time_logs.task_description').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::textarea('task_description', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('project_id', trans('app.time.time_logs.project'), ['class' => 'col-sm-3']) !!} +
+ {!! Form::select('project_id', $projects, null, ['class' => 'form-control projects']) !!} +
+
+
+ {!! Form::label('time', trans('app.time.time_logs.time').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::text('time', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('date', trans('app.time.time_logs.date').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::input('date', 'date', null, ['class' => 'form-control']) !!} +
+
+@include('errors._form-errors') +
+
+
+ {{trans('app.cancel')}} + {!! Form::submit($submitName, ['class' => 'btn btn-primary']) !!} +
+
+@section('additionalCSS') + +@endsection +@section('additionalJS') + + +@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Time/resources/views/create.blade.php b/app/Modules/Employee/Time/resources/views/create.blade.php new file mode 100644 index 0000000..2a82df9 --- /dev/null +++ b/app/Modules/Employee/Time/resources/views/create.blade.php @@ -0,0 +1,13 @@ +@extends('layouts.main_employee') +@section('content') +
+
+
+
{{trans('app.time.time_logs.add_new')}}
+ {!! Form::open(['route' => 'employee.time.store', 'class' => 'form-horizontal']) !!} + @include('employee.time::_form', ['submitName' => trans('app.submit')]) + {!! Form::close() !!} +
+
+
+@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Time/resources/views/edit.blade.php b/app/Modules/Employee/Time/resources/views/edit.blade.php new file mode 100644 index 0000000..e38dc77 --- /dev/null +++ b/app/Modules/Employee/Time/resources/views/edit.blade.php @@ -0,0 +1,13 @@ +@extends('layouts.main_employee') +@section('content') +
+
+
+
{{trans('app.time.time_logs.edit_details')}}
+ {!! Form::model($timeLog, ['method' => 'PUT', 'route' => ['employee.time.update', $timeLog->id], 'class' => 'form-horizontal']) !!} + @include('employee.time::_form', ['submitName' => trans('app.submit')]) + {!! Form::close() !!} +
+
+
+@endsection \ No newline at end of file diff --git a/app/Modules/Employee/Time/resources/views/index.blade.php b/app/Modules/Employee/Time/resources/views/index.blade.php new file mode 100644 index 0000000..ebc3c6b --- /dev/null +++ b/app/Modules/Employee/Time/resources/views/index.blade.php @@ -0,0 +1,77 @@ +@extends('layouts.main_employee') +@section('content') +
+
+ {{trans('app.time.time_logs.add_new')}} +
+
+
+
+
+
{{trans('app.time.time_logs.main')}}
+ + + + + + + + + + + + + + + + + +
{{trans('app.id')}}{{trans('app.time.time_logs.task_name')}}{{trans('app.time.time_logs.project')}}{{trans('app.time.time_logs.time')}}{{trans('app.time.time_logs.date')}}
+ + + + + {!! Form::select('projects_id', $projects, null, ['placeholder' => trans('app.time.time_logs.project')]) !!} + + +
+
+
+
+@endsection +@section('additionalCSS') + +@endsection +@section('additionalJS') + + +@endsection \ No newline at end of file diff --git a/app/Modules/Leave/Http/Controllers/EmployeeLeaveController.php b/app/Modules/Leave/Http/Controllers/EmployeeLeaveController.php index 3bb5a79..1a6b453 100644 --- a/app/Modules/Leave/Http/Controllers/EmployeeLeaveController.php +++ b/app/Modules/Leave/Http/Controllers/EmployeeLeaveController.php @@ -40,7 +40,7 @@ public function index(LeaveTypeRepository $leaveTypeRepository, EmployeeReposito */ public function getDatatable() { - return Datatables::of($this->employeeLeaveRepository->getCollection([], ['id', 'user_id', 'leave_type_id', 'start_date', 'end_date'])) + return Datatables::of($this->employeeLeaveRepository->getCollection([], ['id', 'user_id', 'leave_type_id', 'start_date', 'end_date', 'approved'])) ->editColumn('user_id', function($leave) { return $leave->employee->first_name.' '.$leave->employee->last_name; }) @@ -50,7 +50,8 @@ public function getDatatable() ->addColumn('actions', function($leave){ return view('includes._datatable_actions', [ 'deleteUrl' => route('leave.employee_leaves.destroy', $leave->id), - 'editUrl' => route('leave.employee_leaves.edit', $leave->id) + 'editUrl' => route('leave.employee_leaves.edit', $leave->id), + 'approveUrl' => $leave->approved == 'pending' ? route('leave.employee_leaves.approve', $leave->id) : null ]); }) ->make(); @@ -79,6 +80,7 @@ public function create(LeaveTypeRepository $leaveTypeRepository, EmployeeReposit public function store(EmployeeLeaveRequest $request) { $employeeLeaveData = $request->all(); + $employeeLeaveData['approved'] = 'approved'; if($request->hasFile('attachment')) { $path = $request->attachment->store('uploads/leaves'); $employeeLeaveData['attachment'] = $path; @@ -153,4 +155,21 @@ public function destroy($id, Request $request) $request->session()->flash('success', trans('app.leave.employee_leaves.delete_success')); return redirect()->route('leave.employee_leaves.index'); } + + /** + * Approves an employee request for leave + * + * @param integer unique identifier for the resource + * @param \App\Modules\Leave\Repositories\LeaveTypeRepository $leaveTypeRepository + * @return \Illuminate\Http\Response + */ + public function approve($id, Request $request) + { + $employeeLeaveData = $this->employeeLeaveRepository->getById($id); + $employeeLeaveData['approved'] = 'approved'; + $this->employeeLeaveRepository->update($id, json_decode(json_encode($employeeLeaveData), TRUE)); + + $request->session()->flash('success', trans('app.leave.employee_leaves.approve_success')); + return redirect()->route('leave.employee_leaves.index'); + } } \ No newline at end of file diff --git a/app/Modules/Leave/Repositories/EmployeeLeaveRepository.php b/app/Modules/Leave/Repositories/EmployeeLeaveRepository.php index f7ffaa5..658dd15 100644 --- a/app/Modules/Leave/Repositories/EmployeeLeaveRepository.php +++ b/app/Modules/Leave/Repositories/EmployeeLeaveRepository.php @@ -20,6 +20,10 @@ public function __construct(EmployeeLeave $model, $this->leaveTypeRepository = $leaveTypeRepository; } + public function findBy($attribute, $value, $columns = array('*')) { + return $this->model->where($attribute, '=', $value)->get($columns); + } + public function getCalendarItems($date = false) { if(!$date) { diff --git a/app/Modules/Leave/resources/views/employee_leaves/index.blade.php b/app/Modules/Leave/resources/views/employee_leaves/index.blade.php index 616e2d7..f0eb68f 100644 --- a/app/Modules/Leave/resources/views/employee_leaves/index.blade.php +++ b/app/Modules/Leave/resources/views/employee_leaves/index.blade.php @@ -58,7 +58,7 @@ {data: 2, name: 'leave_type_id'}, {data: 3, name: 'start_date'}, {data: 4, name: 'end_date'}, - {data: 5, name: 'actions', sortable: false, searchable: false} + {data: 6, name: 'actions', sortable: false, searchable: false} ] }); table.columns().every(function () { diff --git a/app/Modules/Pim/Http/Controllers/EmployeesController.php b/app/Modules/Pim/Http/Controllers/EmployeesController.php index 5fa1cff..be3ad2e 100644 --- a/app/Modules/Pim/Http/Controllers/EmployeesController.php +++ b/app/Modules/Pim/Http/Controllers/EmployeesController.php @@ -3,10 +3,13 @@ namespace App\Modules\Pim\Http\Controllers; use App\Http\Controllers\Controller; -use App\Modules\Pim\Repositories\Interfaces\EmployeeRepositoryInterface as EmployeeRepository; use App\Modules\Pim\Http\Requests\EmployeeRequest; -use Illuminate\Http\Request; +use App\Modules\Pim\Repositories\Interfaces\EmployeeRepositoryInterface as EmployeeRepository; use Datatables; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Mail; +use Illuminate\Mail\Mailer; +use Illuminate\Support\Facades\Route; class EmployeesController extends Controller { @@ -40,17 +43,17 @@ public function birthdays(Request $request) /** * Return data for the resource list - * + * * @return \Illuminate\Http\Response */ public function getDatatable() { return Datatables::of($this->employeeRepository->getCollection( - [['key' => 'role', 'operator' => '=', 'value' => $this->employeeRepository->model::USER_ROLE_EMPLOYEE]], + [['key' => 'role', 'operator' => '=', 'value' => $this->employeeRepository->model::USER_ROLE_EMPLOYEE]], ['id', 'first_name', 'last_name', 'email'])) ->addColumn('actions', function($employee){ return view('includes._datatable_actions', [ - 'deleteUrl' => route('pim.employees.destroy', $employee->id), + 'deleteUrl' => route('pim.employees.destroy', $employee->id), 'editUrl' => route('pim.employees.edit', $employee->id) ]); }) @@ -59,7 +62,7 @@ public function getDatatable() /** * Returns all employee details for using with select2 - * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function getSelectJson(Request $request) @@ -97,7 +100,16 @@ public function store(EmployeeRequest $request) { $employeeData = $request->all(); $employeeData['role'] = $this->employeeRepository->model::USER_ROLE_EMPLOYEE; + $password = rand(); + $employeeData['password'] = bcrypt($password); $employeeData = $this->employeeRepository->create($employeeData); + $data = ['title' => trans('emails.employee-login.title'), 'password' => trans('emails.employee-login.password') . $password, 'route' => trans('emails.employee-login.change_password_url') . route('password/reset')]; + Mail::send('emails.employee-login-password', $data, function($message) use ($employeeData) + { + $message->from(env('MAIL_EMAIL_FROM')); + $message->to($employeeData['email']); + }); + $request->session()->flash('success', trans('app.pim.employees.store_success')); return redirect()->route('pim.employees.edit', $employeeData->id); } @@ -155,4 +167,4 @@ public function destroy($id, Request $request) $request->session()->flash('success', trans('app.pim.employees.delete_success')); return redirect()->route('pim.employees.index'); } -} \ No newline at end of file +} diff --git a/app/Modules/Pim/Http/Requests/EmployeeDocumentRequest.php b/app/Modules/Pim/Http/Requests/EmployeeDocumentRequest.php index a904f1f..1b01d3b 100644 --- a/app/Modules/Pim/Http/Requests/EmployeeDocumentRequest.php +++ b/app/Modules/Pim/Http/Requests/EmployeeDocumentRequest.php @@ -26,7 +26,7 @@ public function rules() { $rules = [ 'name' => ['required'], - 'attachment' => ['mimes:png,jpg,pdf,xls,xlsx,csv,txt,doc,docx'] + 'attachment' => ['mimes:png,jpg,pdf,xls,xlsx,csv,txt,doc,docx,zip'] ]; if(!preg_match('/update/', Route::currentRouteName())) { diff --git a/app/Modules/Pim/Http/Requests/EmployeeSalaryRequest.php b/app/Modules/Pim/Http/Requests/EmployeeSalaryRequest.php index c54d6a7..65bc8d8 100644 --- a/app/Modules/Pim/Http/Requests/EmployeeSalaryRequest.php +++ b/app/Modules/Pim/Http/Requests/EmployeeSalaryRequest.php @@ -7,6 +7,14 @@ class EmployeeSalaryRequest extends FormRequest { + private $salaryComponentRepository; + + public function __construct(SalaryComponentsRepository $salaryComponentRepository) + { + parent::__construct(); + $this->salaryComponentRepository = $salaryComponentRepository; + } + /** * Determine if the user is authorized to make this request. * @@ -22,15 +30,34 @@ public function authorize() * * @return array */ - public function rules(SalaryComponentsRepository $salaryComponentRepository) + public function rules() { - // $fields = $salaryComponentRepository->getAll(); $rules = [ - 'components' => ['required'], 'payment_date' => ['required'], 'attachment' => ['mimes:png,jpg,pdf,xls,xlsx,csv,txt'] ]; + $fields = $this->salaryComponentRepository->getAll(); + foreach ($fields as $key => $value) { + $rules['components.'.$value->id] = 'required'; + } + return $rules; } + + /** + * Get the error messages for the defined validation rules. + * + * @return array + */ + public function messages() + { + $fields = $this->salaryComponentRepository->getAll(); + + foreach ($fields as $key => $value) { + $messages['components.'.$value->id.'.required'] = $value->name.' is required.'; + } + + return $messages; + } } diff --git a/app/Modules/Pim/Repositories/EmployeeRepository.php b/app/Modules/Pim/Repositories/EmployeeRepository.php index c595678..aa41fbb 100644 --- a/app/Modules/Pim/Repositories/EmployeeRepository.php +++ b/app/Modules/Pim/Repositories/EmployeeRepository.php @@ -19,12 +19,13 @@ public function __construct(User $model) public function getAll() { - return $this->model->where('role', $this->model::USER_ROLE_EMPLOYEE)->get(); + return $this->model->where('role', $this->model->USER_ROLE_EMPLOYEE)->get(); } + public function getBirthdays($date = false) { - if(!$date) { + if (!$date) { $date = Carbon::now(); } else { $date = Carbon::createFromFormat('Y-m-d', $date); @@ -48,9 +49,8 @@ public function getBirthdays($date = false) public function pluckName() { return $this->model->select(DB::raw('CONCAT(first_name, " ", last_name) as name, id')) - ->where('role', $this->model::USER_ROLE_EMPLOYEE) - ->pluck('name','id'); - + ->where('role', $this->model->USER_ROLE_EMPLOYEE) + ->pluck('name', 'id'); } public function getSelect2Data($filter = '', $offset = 0, $limit = 10) diff --git a/app/Modules/Pim/resources/views/candidates/_form.blade.php b/app/Modules/Pim/resources/views/candidates/_form.blade.php index 3523ee1..0dd67c4 100644 --- a/app/Modules/Pim/resources/views/candidates/_form.blade.php +++ b/app/Modules/Pim/resources/views/candidates/_form.blade.php @@ -37,6 +37,12 @@ {!! Form::textarea('notes', null, ['class' => 'form-control']) !!} +
+ {!! Form::label('how_did_they_hear', trans('app.pim.employees.how_did_they_hear').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::text('how_did_they_hear', null, ['class' => 'form-control']) !!} +
+
@include('errors._form-errors')
diff --git a/app/Modules/Recruitment/Http/Controllers/.php_cs.cache b/app/Modules/Recruitment/Http/Controllers/.php_cs.cache new file mode 100644 index 0000000..829d4ec --- /dev/null +++ b/app/Modules/Recruitment/Http/Controllers/.php_cs.cache @@ -0,0 +1 @@ +{"php":"7.0.18-0ubuntu0.16.04.1","version":"2.3.1","rules":{"blank_line_after_namespace":true,"braces":true,"class_definition":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_constants":true,"lowercase_keywords":true,"method_argument_space":true,"no_closing_tag":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":true,"encoding":true,"full_opening_tag":true},"hashes":{"JobAdvertController.php":2300231351,"ReportsController.php":2338909593}} \ No newline at end of file diff --git a/app/Modules/Recruitment/Http/Controllers/JobAdvertController.php b/app/Modules/Recruitment/Http/Controllers/JobAdvertController.php new file mode 100644 index 0000000..a55db45 --- /dev/null +++ b/app/Modules/Recruitment/Http/Controllers/JobAdvertController.php @@ -0,0 +1,119 @@ +jobAdvertRepository = $jobAdvertRepository; + } + /** + * Show the Job Advert View. + * + * @return \Illuminate\Http\Response + */ + public function index() + { + return view('recruitment::job_advert.index'); + } + /** + * Return data for the resource list + * + * @return \Illuminate\Http\Response + */ + public function getDatatable() + { + return Datatables::of($this->jobAdvertRepository->getQry( + [], + ['id', 'title', 'description']))->addColumn('actions', function ($JobAdvert) { + return view('includes._datatable_actions', [ + 'deleteUrl' => route('recruitment.job_advert.destroy', $JobAdvert->id), + 'editUrl' => route('recruitment.job_advert.edit', $JobAdvert->id) + ]); + }) + ->make(); + } + + /** + * Show the form for creating a new resource. + * + * @return \Illuminate\Http\Response + */ + public function create() + { + return view('recruitment::job_advert.create'); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(JobAdvertRequest $request) + { + $jobData = $request->all(); + $jobData = $this->jobAdvertRepository->create($jobData); + $request->session()->flash('success', trans('app.recruitment.job_advert.store_success')); + return redirect()->route('recruitment.job_advert.edit', $jobData->id); + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function show($id) + { + // + } + + /** + * Show the form for editing the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function edit($id) + { + $jadvert = $this->jobAdvertRepository->getById($id); + return view('recruitment::job_advert.edit', ['jadvert' => $jadvert, 'breadcrumb' => ['title' => $jadvert->title, 'id' => $jadvert->id]]); + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { + $jadvert = $this->jobAdvertRepository->update($id, $request->all()); + $request->session()->flash('success', trans('app.recruitment.job_advert.update_success')); + return redirect()->route('recruitment.job_advert.edit', $jadvert->id); + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy($id, Request $request) + { + $this->jobAdvertRepository->delete($id); + $request->session()->flash('success', trans('app.recruitment.job_advert.delete_success')); + return redirect()->route('recruitment.job_advert.index'); + } +} diff --git a/app/Modules/Recruitment/Http/Controllers/ReportsController.php b/app/Modules/Recruitment/Http/Controllers/ReportsController.php index 68db8f1..da786f2 100644 --- a/app/Modules/Recruitment/Http/Controllers/ReportsController.php +++ b/app/Modules/Recruitment/Http/Controllers/ReportsController.php @@ -34,7 +34,7 @@ public function index(ContractTypeRepository $contractTypeRepository, SkillRepos /** * Return data for the resource list - * + * * @return \Illuminate\Http\Response */ public function getDatatable(Request $request) @@ -42,27 +42,27 @@ public function getDatatable(Request $request) $inputs = array_filter($request->only(['first_name', 'last_name', 'email', 'skills', 'salary_from', 'salary_to', 'contract_type_id', 'location'])); return Datatables::of($this->reportRepository->getQry( - $inputs, + $inputs, ['id', 'first_name', 'last_name', 'email'])) - ->addColumn('phone', function($candidate) { + ->addColumn('phone', function ($candidate) { return @$candidate->contact->phone; }) - ->addColumn('skills', function($candidate) { + ->addColumn('skills', function ($candidate) { return @implode(', ', $candidate->skills->pluck('name')->toArray()); }) - ->addColumn('salary', function($candidate) { + ->addColumn('salary', function ($candidate) { return @format_price($candidate->user_preferences->salary); }) - ->addColumn('contract_type', function($candidate) { + ->addColumn('contract_type', function ($candidate) { return @$candidate->user_preferences->contractType->name; }) - ->addColumn('location', function($candidate) { + ->addColumn('location', function ($candidate) { return @get_location_name($candidate->user_preferences->location); }) - ->addColumn('comments', function($candidate) { + ->addColumn('comments', function ($candidate) { return @$candidate->user_preferences->comments; }) - ->addColumn('actions', function($employee){ + ->addColumn('actions', function ($employee) { return view('includes._datatable_actions', [ 'showUrl' => route('recruitment.reports.show', $employee->id) ]); @@ -77,4 +77,4 @@ public function show($id) $breadcrumb = ['title' => $candidate->first_name.' '.$candidate->last_name, 'id' => $candidate->id]; return view('recruitment::reports.show', compact('candidate', 'breadcrumb')); } -} \ No newline at end of file +} diff --git a/app/Modules/Recruitment/Http/Requests/.php_cs.cache b/app/Modules/Recruitment/Http/Requests/.php_cs.cache new file mode 100644 index 0000000..f2d35dd --- /dev/null +++ b/app/Modules/Recruitment/Http/Requests/.php_cs.cache @@ -0,0 +1 @@ +{"php":"7.0.18-0ubuntu0.16.04.1","version":"2.3.1","rules":{"blank_line_after_namespace":true,"braces":true,"class_definition":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_constants":true,"lowercase_keywords":true,"method_argument_space":true,"no_closing_tag":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":true,"encoding":true,"full_opening_tag":true},"hashes":{"JobAdvertRequest.php":1586528411}} \ No newline at end of file diff --git a/app/Modules/Recruitment/Http/Requests/JobAdvertRequest.php b/app/Modules/Recruitment/Http/Requests/JobAdvertRequest.php new file mode 100644 index 0000000..10e5d3f --- /dev/null +++ b/app/Modules/Recruitment/Http/Requests/JobAdvertRequest.php @@ -0,0 +1,33 @@ + ['required'], + 'description' => ['required'] + ]; + + return $rules; + } +} diff --git a/app/Modules/Recruitment/Models/.php_cs.cache b/app/Modules/Recruitment/Models/.php_cs.cache new file mode 100644 index 0000000..950427a --- /dev/null +++ b/app/Modules/Recruitment/Models/.php_cs.cache @@ -0,0 +1 @@ +{"php":"7.0.18-0ubuntu0.16.04.1","version":"2.3.1","rules":{"blank_line_after_namespace":true,"braces":true,"class_definition":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_constants":true,"lowercase_keywords":true,"method_argument_space":true,"no_closing_tag":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":true,"encoding":true,"full_opening_tag":true},"hashes":{"JobAdvert.php":239084687}} \ No newline at end of file diff --git a/app/Modules/Recruitment/Models/JobAdvert.php b/app/Modules/Recruitment/Models/JobAdvert.php new file mode 100644 index 0000000..c62d3fd --- /dev/null +++ b/app/Modules/Recruitment/Models/JobAdvert.php @@ -0,0 +1,13 @@ +model = $model; + } +} diff --git a/app/Modules/Recruitment/Repositories/ReportRepository.php b/app/Modules/Recruitment/Repositories/ReportRepository.php index 9f6137d..9e9a86e 100644 --- a/app/Modules/Recruitment/Repositories/ReportRepository.php +++ b/app/Modules/Recruitment/Repositories/ReportRepository.php @@ -24,11 +24,11 @@ public function getQry($inputs = array(), $columns = []) ]; foreach ($inputs as $key => $value) { - if(in_array($key, ['first_name', 'last_name', 'email'])) { + if (in_array($key, ['first_name', 'last_name', 'email'])) { $operator = 'like'; - } elseif($key == 'salary_from') { + } elseif ($key == 'salary_from') { $operator = '>='; - } elseif($key == 'salary_to') { + } elseif ($key == 'salary_to') { $operator = '<='; } else { $operator = '='; @@ -47,28 +47,28 @@ public function getQry($inputs = array(), $columns = []) break; case 'skills': foreach ($value as $skill) { - $response->whereHas('skills', function($query) use ($skill) { + $response->whereHas('skills', function ($query) use ($skill) { $query->where('skill_id', $skill); }); } break; case 'salary_from': - $response->whereHas('user_preferences', function($query) use ($value) { + $response->whereHas('user_preferences', function ($query) use ($value) { $query->where('salary', '>=', $value); }); break; case 'salary_to': - $response->whereHas('user_preferences', function($query) use ($value) { + $response->whereHas('user_preferences', function ($query) use ($value) { $query->where('salary', '<=', $value); }); break; case 'contract_type_id': - $response->whereHas('user_preferences', function($query) use ($value) { + $response->whereHas('user_preferences', function ($query) use ($value) { $query->where('contract_type_id', '=', $value); }); break; case 'location': - $response->whereHas('user_preferences', function($query) use ($value) { + $response->whereHas('user_preferences', function ($query) use ($value) { $query->where('location', '=', $value); }); break; diff --git a/app/Modules/Recruitment/resources/views/.php_cs.cache b/app/Modules/Recruitment/resources/views/.php_cs.cache new file mode 100644 index 0000000..c93f5ee --- /dev/null +++ b/app/Modules/Recruitment/resources/views/.php_cs.cache @@ -0,0 +1 @@ +{"php":"7.0.18-0ubuntu0.16.04.1","version":"2.3.1","rules":{"blank_line_after_namespace":true,"braces":true,"class_definition":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_constants":true,"lowercase_keywords":true,"method_argument_space":true,"no_closing_tag":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":true,"encoding":true,"full_opening_tag":true},"hashes":{"index.blade.php":491633031}} \ No newline at end of file diff --git a/app/Modules/Recruitment/resources/views/index.blade.php b/app/Modules/Recruitment/resources/views/index.blade.php index a1f542e..12dff30 100644 --- a/app/Modules/Recruitment/resources/views/index.blade.php +++ b/app/Modules/Recruitment/resources/views/index.blade.php @@ -6,5 +6,10 @@

{{trans('app.recruitment.reports.main')}}

+
+ +

{{trans('app.recruitment.job_advert.main')}}

+
+
@endsection \ No newline at end of file diff --git a/app/Modules/Recruitment/resources/views/job_advert/.php_cs.cache b/app/Modules/Recruitment/resources/views/job_advert/.php_cs.cache new file mode 100644 index 0000000..03c7459 --- /dev/null +++ b/app/Modules/Recruitment/resources/views/job_advert/.php_cs.cache @@ -0,0 +1 @@ +{"php":"7.0.18-0ubuntu0.16.04.1","version":"2.3.1","rules":{"blank_line_after_namespace":true,"braces":true,"class_definition":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_constants":true,"lowercase_keywords":true,"method_argument_space":true,"no_closing_tag":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":true,"encoding":true,"full_opening_tag":true},"hashes":{"_form.blade.php":2988637721,"create.blade.php":924751384,"edit.blade.php":1816404516,"index.blade.php":3200190596}} \ No newline at end of file diff --git a/app/Modules/Recruitment/resources/views/job_advert/_form.blade.php b/app/Modules/Recruitment/resources/views/job_advert/_form.blade.php new file mode 100644 index 0000000..f63d278 --- /dev/null +++ b/app/Modules/Recruitment/resources/views/job_advert/_form.blade.php @@ -0,0 +1,51 @@ +
+ {!! Form::label('title', trans('app.recruitment.job_advert.title').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::text('title', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('description', trans('app.recruitment.job_advert.description').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::textarea('description', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('skills', trans('app.recruitment.job_advert.skills').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::textarea('skills', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('advantages', trans('app.recruitment.job_advert.advantages').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::textarea('advantages', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('responsibilities', trans('app.recruitment.job_advert.responsibilities').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::textarea('responsibilities', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('benefits', trans('app.recruitment.job_advert.benefits').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::textarea('benefits', null, ['class' => 'form-control']) !!} +
+
+
+ {!! Form::label('image', trans('app.recruitment.job_advert.image').':', ['class' => 'col-sm-3']) !!} +
+ {!! Form::file('image', null, ['class' => 'form-control']) !!} +
+
+ +@include('errors._form-errors') +
+
+
+ {{trans('app.cancel')}} + {!! Form::submit($submitName, ['class' => 'btn btn-primary']) !!} +
+
\ No newline at end of file diff --git a/app/Modules/Recruitment/resources/views/job_advert/create.blade.php b/app/Modules/Recruitment/resources/views/job_advert/create.blade.php new file mode 100644 index 0000000..2d1d702 --- /dev/null +++ b/app/Modules/Recruitment/resources/views/job_advert/create.blade.php @@ -0,0 +1,13 @@ +@extends('layouts.main') +@section('content') +
+
+
+
{{trans('app.recruitment.job_advert.add_new')}}
+ {!! Form::open(['route' => 'recruitment.job_advert.store', 'class' => 'form-horizontal', 'files'=>true, 'enctype' => 'multipart/form-data']) !!} + @include('recruitment::job_advert._form', ['submitName' => trans('app.submit')]) + {!! Form::close() !!} +
+
+
+@endsection \ No newline at end of file diff --git a/app/Modules/Recruitment/resources/views/job_advert/edit.blade.php b/app/Modules/Recruitment/resources/views/job_advert/edit.blade.php new file mode 100644 index 0000000..b4f910d --- /dev/null +++ b/app/Modules/Recruitment/resources/views/job_advert/edit.blade.php @@ -0,0 +1,13 @@ +@extends('layouts.main') +@section('content') +
+
+
+
{{trans('app.recruitment.job_advert.edit_details')}}
+ {!! Form::model($jadvert, ['method' => 'PUT', 'route' => ['recruitment.job_advert.update', $jadvert->id], 'class' => 'form-horizontal', 'enctype' => 'multipart/form-data']) !!} + @include('recruitment::job_advert._form', ['submitName' => trans('app.submit')]) + {!! Form::close() !!} +
+
+
+@endsection \ No newline at end of file diff --git a/app/Modules/Recruitment/resources/views/job_advert/index.blade.php b/app/Modules/Recruitment/resources/views/job_advert/index.blade.php new file mode 100644 index 0000000..ee57caa --- /dev/null +++ b/app/Modules/Recruitment/resources/views/job_advert/index.blade.php @@ -0,0 +1,65 @@ +@extends('layouts.main') +@section('content') +
+
+ {{trans('app.recruitment.job_advert.add_new')}} +
+
+
+
+
+
{{trans('app.recruitment.job_advert.main')}}
+ + + + + + + + + + + + + +
{{trans('app.id')}}{{trans('app.recruitment.job_advert.title')}}{{trans('app.recruitment.job_advert.description')}}
+ + + + + +
+
+
+
+@endsection +@section('additionalCSS') + +@endsection +@section('additionalJS') + + +@endsection \ No newline at end of file diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 66e01c7..656bb2e 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -20,6 +20,12 @@ public function boot() View::addNamespace('recruitment', base_path('app/Modules/Recruitment/resources/views')); View::addNamespace('discipline', base_path('app/Modules/Discipline/resources/views')); View::addNamespace('time', base_path('app/Modules/Time/resources/views')); + View::addNamespace('employee.salary', base_path('app/Modules/Employee/Salary/resources/views')); + View::addNamespace('employee.time', base_path('app/Modules/Employee/Time/resources/views')); + View::addNamespace('employee.leaves', base_path('app/Modules/Employee/Leaves/resources/views')); + View::addNamespace('employee.leaves', base_path('app/Modules/Employee/Leaves/resources/views')); + View::addNamespace('dashboard', base_path('app/Modules/Dashboard/resources/views')); + View::addNamespace('employee.dashboard_documents', base_path('app/Modules/Employee/Dashboard/resources/views')); } /** diff --git a/app/Providers/RepositoryServiceProvider.php b/app/Providers/RepositoryServiceProvider.php index 40551d5..4a16e4c 100644 --- a/app/Providers/RepositoryServiceProvider.php +++ b/app/Providers/RepositoryServiceProvider.php @@ -9,6 +9,7 @@ use App\Modules\Recruitment as Recruitment; use App\Modules\Discipline as Discipline; use App\Modules\Time as Time; +use App\Modules\Dashboard as Dashboard; class RepositoryServiceProvider extends ServiceProvider { @@ -40,10 +41,12 @@ public function register() Leave\Repositories\EmployeeLeaveRepository::class => [Leave\Repositories\Interfaces\EmployeeLeaveRepositoryInterface::class], Leave\Repositories\EmployeeLeaveStatusRepository::class => [Leave\Repositories\Interfaces\EmployeeLeaveStatusRepositoryInterface::class], Recruitment\Repositories\ReportRepository::class => [Recruitment\Repositories\Interfaces\ReportRepositoryInterface::class], + Recruitment\Repositories\JobAdvertRepository::class => [Recruitment\Repositories\Interfaces\JobAdvertRepositoryInterface::class], Discipline\Repositories\DisciplinaryCaseRepository::class => [Discipline\Repositories\Interfaces\DisciplinaryCaseRepositoryInterface::class], Time\Repositories\ClientRepository::class => [Time\Repositories\Interfaces\ClientRepositoryInterface::class], Time\Repositories\ProjectRepository::class => [Time\Repositories\Interfaces\ProjectRepositoryInterface::class], Time\Repositories\TimeLogRepository::class => [Time\Repositories\Interfaces\TimeLogRepositoryInterface::class], + Dashboard\Repositories\DashboardDocumentsRepository::class => [Dashboard\Repositories\Interfaces\DashboardDocumentsRepositoryInterface::class], ]; foreach ($bindings as $concrete => $interfaces) { diff --git a/app/Providers/ViewComposerServiceProvider.php b/app/Providers/ViewComposerServiceProvider.php index 6dfd76a..307d64b 100644 --- a/app/Providers/ViewComposerServiceProvider.php +++ b/app/Providers/ViewComposerServiceProvider.php @@ -27,5 +27,8 @@ public function register() view()->composer('includes.header', function($view) { $view->with('current', preg_replace('/\..*/', '', Route::currentRouteName())); }); + view()->composer('includes.header_employee', function($view) { + $view->with('current', preg_replace('/\..*/', '', Route::currentRouteName())); + }); } } diff --git a/app/User.php b/app/User.php index 2eba781..e986059 100644 --- a/app/User.php +++ b/app/User.php @@ -27,7 +27,7 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'first_name', 'last_name', 'email', 'gender', 'birth_date', 'password', 'role', 'notes' + 'first_name', 'last_name', 'email', 'gender', 'birth_date', 'password', 'role', 'notes', 'how_did_they_hear' ]; /** diff --git a/contributing.md b/contributing.md new file mode 100644 index 0000000..6d6c7e0 --- /dev/null +++ b/contributing.md @@ -0,0 +1,110 @@ +# Contributing to HRM + +Thank you for considering contributing to HRM! :octocat: :rocket: + +**Table of contents** + + + +- Code of conduct +- How can I contribute? + - Reporting bugs + - Suggesting Enhancements + + + +## Code of conduct + +This project and everyone participating in it is governed by the [Contributor Covenant](https://github.com/ContributorCovenant/contributor_covenant). By participating, you are expected to uphold this code. Please report unacceptable behavior to info@adevait.com. + +## How can I contribute? + +### Reporting bugs + +Bugs are reported as [Github issues](https://github.com/adevait/hrm/issues), with the label `bug`. Before reporting a bug, please make sure it's not already [reported](https://github.com/adevait/hrm/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3Abug%20) or [fixed](https://github.com/adevait/hrm/pulls?q=is%3Aopen+is%3Apr+label%3Abug). + +We welcome pull request for bug fixes so if you think you can tackle it, feel free to. Please make sure to label it `bug`, and link it to the related issue. + +Bug reports should have the following format. + +**Title** + +Use clear and descriptive title for the issue that identifies the problem. + +**Description** + +Make sure to explain the problem well and include all details you find necessary. + +**Details** + +1. Steps to reproduce + * Write down as many steps as you find necessary to explain how the bug occurred and help maintainers reproduce it. +2. Expected behavior + * What did you expect to happen? +3. Actual behavior + * What actually happened? +4. Testing environment + * Describe the testing environment including used browser, operating system and other details that can be helpful. + +**Additional information** + +This is the place for anything not included in the guide above that you find important. + +> Note: If you find a Closed issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. + +### Suggesting Enhancements + +Enhancements are also suggested in the form of [issues](https://github.com/adevait/hrm/issues), labeled `enhancement`. Before suggesting an enhancement, please make it's not already [suggested](https://github.com/adevait/hrm/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement) or [implemented](https://github.com/adevait/hrm/pulls?q=is%3Aopen+is%3Apr+label%3Abug+label%3Aenhancement). + +Before making a pull request for your suggestion, please get a feedback from some of the maintainers to see if such feature aligns with the general vision for the system. + +Pull requests for enhancements should follow these practices: + +**Code Format** + +1. Use [PSR-2](http://www.php-fig.org/psr/psr-2/) coding standard + * Make sure your code follows PSR-2 coding style guide. + * Some editors have packages that automatically build your code in PSR-2. If you don't want to think about your code structure while coding, you can easily automate it by installing such package. An example is Sublime's [Code Formatter](https://github.com/akalongman/sublimetext-codeformatter). +2. Document your code + * All of your code should be properly documented. A great package for generating code documentation is [DocBlockr](https://packagecontrol.io/packages/DocBlockr). + +**General Structure** + +1. Modules + * The system is organized in modules located in `app/Modules`. Every module has its own HTTP part, models, repositories and resources, and they follow Laravel's nesting and conventions. + * When adding a new module, check one of the existing ones as example for the code structure and practices. +2. Logic + * Controllers + - They are following the RESTful structure and are organized as resources. + - Controller methods should not do any complex operations or calculations. + - All database operations are handled in repositories (see point 3 below). + - Any function that is used more than once should be a helper function. + * Validation + - Every controller has its `FormRequest` class, located in `ModuleName/Http/Requests` where the request validation is done prior to executing the code in the controller method. + - Apart from the required rules, other validation rules should be added based on common sense. + * Routes + - All routes should be defined as resources and be properly nested (see existing routes as example). + - All routes should be named and used accordingly throughout the code. +3. Database + * Migrations + All database alterations should be done using migrations. + - Migrations used for creating a table in the database should follow this naming convention: `create_[table_name]_table`. + - Migrations used for altering a table in the database should follow this naming convention: `update_[table_name]_[altering_description]`. + - Every table should have timestamps and soft deletes. + - Every table should have an auto increment primary key. + - Every foreign key should be defined and cascade on delete and update. + * Models + - Tables representing many to many relations should not have separate model class. + - Every model should have the table name defined as a protected attribute. + - Every model should have the guarded attributes specified. + * Repositories + - All complex database operations should be handled in a repository rather than the model itself. + - Every model has its own repository that extends `App\Repositories\EloquentRepository`. + - Every repository should have its interface and binded through it to allow for higher abstraction. The repository bindings are done in `App\Providers\RepositoryServiceProvider`. + - Don't use model attributes or constants directly in external classes (e.g. `User::ACTIVE`). Instead, do it through the respective repository, like so: `$userRepository->model::ACTIVE`. To be able to use that, you should set the repository's `allowedAttributes` attribute to include the model - `$allowedAttributes = ['model']`. +4. Other + * Breadcrumbs + - Every page should have its breadcrumbs defined in `routes/breadcrumbs`. + * Localization + - Every text used throughout the system should be defined in `/resources/lang/en/app.php`, to make it easier for implementing localization eventually. + - Make sure to follow the existing nesting structure and naming for all texts added in the lang file. \ No newline at end of file diff --git a/database/migrations/2017_05_30_105051_create_job_advert_table.php b/database/migrations/2017_05_30_105051_create_job_advert_table.php new file mode 100644 index 0000000..96b6309 --- /dev/null +++ b/database/migrations/2017_05_30_105051_create_job_advert_table.php @@ -0,0 +1,38 @@ +increments('id'); + $table->string('title', 255); + $table->text('description'); + $table->text('skills')->nullable(); + $table->text('advantages')->nullable(); + $table->text('responsibilities')->nullable(); + $table->text('benefits')->nullable(); + $table->string('image', 255)->nullable(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('job_advert'); + } +} diff --git a/database/migrations/2017_06_15_114249_update_user_leaves_add_approved.php b/database/migrations/2017_06_15_114249_update_user_leaves_add_approved.php new file mode 100644 index 0000000..9bdad0f --- /dev/null +++ b/database/migrations/2017_06_15_114249_update_user_leaves_add_approved.php @@ -0,0 +1,32 @@ +boolean('approved')->nullable()->after('attachment'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('user_leaves', function (Blueprint $table) { + $table->dropColumn('approved'); + }); + } +} diff --git a/database/migrations/2017_07_05_121947_update_table_users_add_column_how_did_they_hear.php b/database/migrations/2017_07_05_121947_update_table_users_add_column_how_did_they_hear.php new file mode 100644 index 0000000..8cd4214 --- /dev/null +++ b/database/migrations/2017_07_05_121947_update_table_users_add_column_how_did_they_hear.php @@ -0,0 +1,32 @@ +string('how_did_they_hear')->after('notes'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('how_did_they_hear'); + }); + } +} diff --git a/database/migrations/2017_07_26_100942_create_dashboard_documents_table.php b/database/migrations/2017_07_26_100942_create_dashboard_documents_table.php new file mode 100644 index 0000000..20f5af0 --- /dev/null +++ b/database/migrations/2017_07_26_100942_create_dashboard_documents_table.php @@ -0,0 +1,35 @@ +increments('id'); + $table->string('name', 100); + $table->string('description')->nullable(); + $table->string('attachment', 100); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('dashboard_documents'); + } +} diff --git a/public/.DS_Store b/public/.DS_Store new file mode 100644 index 0000000..c096493 Binary files /dev/null and b/public/.DS_Store differ diff --git a/public/images/browserstack-logo.png b/public/images/browserstack-logo.png new file mode 100644 index 0000000..226c727 Binary files /dev/null and b/public/images/browserstack-logo.png differ diff --git a/readme.md b/readme.md index 5e0cf7d..ab838b6 100644 --- a/readme.md +++ b/readme.md @@ -28,10 +28,18 @@ The system is built on top of Laravel 5.3, so to proceed with the installation y * Check `/bootstrap/cache` permissions - this folder should also be writable. Make sure the permissions are set correctly. 8. At this point you should have the app up and running. Hit `yourdomain/register` to open the registration screen for creating an admin user. This is a one time setup and the credentials set here will be used for authenticating before using the system. +## Contributing + +We encourage you to contribute to HRM! Please check out the [Contributing guide](contributing.md) for guidelines about how to proceed. + ## License HRM is released under the GPL v3 (or later) license. ## Support -Please direct any feedback to trajchevska@adevait.com. \ No newline at end of file +Please direct any feedback to trajchevska@adevait.com. + +## Our supporters +#### [BrowserStack](https://www.browserstack.com/): Hassle free web-based browser testing +![Testing made easy with BrowserStack](https://raw.githubusercontent.com/adevait/hrm/master/public/images/browserstack-logo.png) \ No newline at end of file diff --git a/resources/lang/en/app.php b/resources/lang/en/app.php index 3ead3a2..029286c 100644 --- a/resources/lang/en/app.php +++ b/resources/lang/en/app.php @@ -33,6 +33,9 @@ 'login' => 'Login', 'logout' => 'Logout', 'home' => 'Home', + 'download' => 'Download', + 'status' => 'Status', + 'approve' => 'Approve', 'profile' => [ 'main' => 'Profile', @@ -140,6 +143,7 @@ 'gender_female' => 'Female', 'birth_date' => 'Birth date', 'notes' => 'Notes', + 'how_did_they_hear' => 'How did they hear about us?', 'store_success' => 'The employee was successfully added.', 'update_success' => 'The employee details were successfully updated.', 'delete_success' => 'The employee was successfully removed.', @@ -316,6 +320,7 @@ 'store_success' => 'Leave was successfully assigned.', 'update_success' => 'Leave was successfully updated.', 'delete_success' => 'Leave was successfully deleted.', + 'approve_success' => 'Leave was successfully approved.', 'attachment' => 'Attachment', 'error_no_available_days' => 'The leave request exceeds the total available days. There are :days days left.', ], @@ -335,6 +340,21 @@ ], 'recruitment' => [ 'main' => 'Recruitment', + 'job_advert' => [ + 'main' => 'Job Advertisement', + 'add_new' => 'Add job advertisement', + 'title' => 'Job title', + 'description' => 'Job description', + 'skills' => 'Required skills', + 'advantages' => 'Advantages', + 'responsibilities' => 'Responsibilities', + 'benefits' => 'Benefits', + 'image' => 'Image', + 'edit_details' => 'Edit job advertisement details', + 'store_success' => 'The job advertisement was successfully added.', + 'update_success' => 'The job advertisement details were successfully updated.', + 'delete_success' => 'The job advertisement was successfully removed.', + ], 'reports' => [ 'main' => 'Reports', 'first_name' => 'First name', @@ -408,5 +428,34 @@ 'update_success' => 'Time log was successfully updated.', 'delete_success' => 'Time log was successfully deleted.', ] + ], + 'dashboard' => [ + 'main' => 'Dashboard', + 'documents' => [ + 'main' => 'Documents', + 'name' => 'Name', + 'description' => 'Description', + 'attachment' => 'Attachment', + 'add_new' => 'Add new document', + 'edit_details' => 'Edit document details', + 'store_success' => 'Dashboard document was successfully added.', + 'update_success' => 'Dashboard document was successfully updated.', + 'delete_success' => 'Dashboard document was successfully deleted.', + ], + ], + 'employee' => [ + 'leaves' => [ + 'main' => 'Leaves', + 'details' => 'Leave Details', + 'approved' => 'Approved', + 'pending' => 'Pending', + 'request' => 'Request a leave', + 'store_success' => 'Leave request is successfully sent.', + 'update_success' => 'Leave request is successfully updated.', + 'delete_success' => 'Leave request is successfully deleted.', + ], + 'salary' => [ + 'main' => 'Salary' + ] ] ]; diff --git a/resources/lang/en/emails.php b/resources/lang/en/emails.php new file mode 100644 index 0000000..123676f --- /dev/null +++ b/resources/lang/en/emails.php @@ -0,0 +1,9 @@ + [ + 'title' => 'Welcome to HRM', + 'password' => 'Your temporary password is: ', + 'change_password_url' => ' Please log in with the temporary password and change it to a password of your choice as soon as possible, at the following link - ' + ] +]; \ No newline at end of file diff --git a/resources/views/emails/employee-login-password.blade.php b/resources/views/emails/employee-login-password.blade.php new file mode 100644 index 0000000..f40443b --- /dev/null +++ b/resources/views/emails/employee-login-password.blade.php @@ -0,0 +1,8 @@ + + + +

{{$title}}

+

{{$password}}

+

{{$route}}

+ + diff --git a/resources/views/includes/_datatable_actions.blade.php b/resources/views/includes/_datatable_actions.blade.php index b20d960..ec267d7 100644 --- a/resources/views/includes/_datatable_actions.blade.php +++ b/resources/views/includes/_datatable_actions.blade.php @@ -6,4 +6,16 @@ @endif @if(@$deleteUrl) {{trans('app.delete')}} -@endif \ No newline at end of file +@endif +@if(@$downloadUrl) +
+ {{ Form::token() }} + +
+@endif +@if(@$approveUrl) +
+ {{ Form::token() }} + +
+@endif diff --git a/resources/views/includes/header.blade.php b/resources/views/includes/header.blade.php index 498d403..bbe6d94 100644 --- a/resources/views/includes/header.blade.php +++ b/resources/views/includes/header.blade.php @@ -8,7 +8,7 @@ - {{ config('app.name', 'HRM') }} + {{ config('app.name', 'HRM') }} @@ -56,19 +56,26 @@ @endif +
  • + {{trans('app.dashboard.main')}} + @if($current == 'dashboard') + ({{trans('app.current')}}) + @endif + +