diff --git a/app/Http/Controllers/Api/ApplianceController.php b/app/Http/Controllers/Api/ApplianceController.php
index 1af6366..0993744 100644
--- a/app/Http/Controllers/Api/ApplianceController.php
+++ b/app/Http/Controllers/Api/ApplianceController.php
@@ -73,6 +73,27 @@ public function editDate(Request $request, $id)
$user = auth()->user();
+ // Parse the start and end date
+ $startDate = Carbon::parse($request->start_date);
+ $endDate = Carbon::parse($request->end_date);
+
+ // Check if the start and end dates overlap with any other company's internship dates
+ $overlapCheck = $user->internDates()->where('company_id', '!=', $id)
+ ->where(function ($query) use ($startDate, $endDate) {
+ $query->whereBetween('start_date', [$startDate, $endDate])
+ ->orWhereBetween('end_date', [$startDate, $endDate])
+ ->orWhere(function ($query) use ($startDate, $endDate) {
+ $query->where('start_date', '<=', $startDate)
+ ->where('end_date', '>=', $endDate);
+ });
+ })->exists();
+
+ if ($overlapCheck) {
+ return response()->json([
+ 'message' => 'The selected dates overlap with another company\'s internship dates.',
+ ], 400);
+ }
+
try {
$user->internDates()->where('company_id', $id)->update($request->all());
diff --git a/app/Http/Controllers/Api/ExportController.php b/app/Http/Controllers/Api/ExportController.php
new file mode 100644
index 0000000..c5a361e
--- /dev/null
+++ b/app/Http/Controllers/Api/ExportController.php
@@ -0,0 +1,105 @@
+user();
+ $courseName = $user->courses->first()?->name;
+ $courseLevel = $courseName ? explode(' ', $courseName)[0] : 'N/A';
+
+ $formattedDateOfBirth = $user->date_of_birth
+ ? Carbon::parse($user->date_of_birth)->translatedFormat('j F Y')
+ : 'N/A';
+
+ $gender = match ($user->gender) {
+ 'male' => 'Laki-Laki',
+ 'female' => 'Perempuan'
+ };
+
+ $companyId = $id;
+ $company = $user->companies()->find($companyId);
+ if (!$company) {
+ return response()->json(['error' => 'Company not found!'], 404);
+ }
+ $companyName = $company?->name ?? 'N/A';
+
+ $presences = $user->presences()
+ ->where('company_id', $companyId)
+ ->whereDate('date', '<=', Carbon::now())
+ ->orderBy('date', 'asc')
+ ->get()
+ ->filter(fn($presence) => !is_null($presence->check_in))
+ ->values();
+
+ if ($presences->isEmpty()) {
+ return response()->json(['error' => 'No presences found!'], 404);
+ }
+
+ $journals = $user->journals()
+ ->where('company_id', $companyId)
+ ->whereDate('date', '<=', Carbon::now())
+ ->orderBy('date', 'asc')
+ ->get()
+ ->filter(fn($journal) => !is_null($journal->work_type))
+ ->values();
+
+ if ($journals->isEmpty()) {
+ return response()->json(['error' => 'No journals found!'], 404);
+ }
+
+ $formFields = [
+ 'namasiswa' => $user->name,
+ 'kelas' => $courseLevel,
+ 'alamat_siswa' => $user->address,
+ 'jurusan' => $user->departments->first()?->description,
+ 'instansi_nama' => $companyName,
+ 'kelasjurusan' => $courseName,
+ 'ttl' => $formattedDateOfBirth,
+ 'gender' => $gender,
+ ];
+
+ foreach ($presences as $index => $presence) {
+ $i = $index + 1;
+ $formFields["tanggal$i"] = Carbon::parse($presence->date)->translatedFormat('l, j F Y');
+ $formFields["checkin$i"] = $presence->check_in;
+ $formFields["checkout$i"] = $presence->check_out ?? 'N/A';
+ }
+
+ foreach ($journals as $index => $journal) {
+ $i = $index + 1;
+ $formFields["no$i"] = $i;
+ $formFields["bidang$i"] = $journal->work_type;
+ $formFields["uraian$i"] = $journal->description;
+ $formFields["tgl_jurnal$i"] = Carbon::parse($journal->date)->translatedFormat('l, j F Y');
+ }
+
+ $templatePath = '';
+ if (count($presences) <= 93 || count($journals) <= 93) {
+ $templatePath = public_path('template-pdf/template_3_month.pdf');
+ } else {
+ $templatePath = public_path('template-pdf/template_6_month.pdf');
+ }
+
+ if (!file_exists($templatePath)) {
+ return response()->json(['error' => 'PDF template not found!'], 404);
+ }
+
+ $fileName = $user->id . time() . '.pdf';
+ $tempPath = storage_path('storage/journals/' . $fileName);
+ $outputPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $fileName;
+ $pdf = new Pdf($templatePath);
+ $pdf->fillForm($formFields)->flatten()->saveAs($outputPath);
+
+ return response()->download($outputPath, $fileName)->deleteFileAfterSend(true);
+ }
+}
diff --git a/app/Http/Controllers/JournalController.php b/app/Http/Controllers/JournalController.php
index 9fc8cf3..7599e06 100644
--- a/app/Http/Controllers/JournalController.php
+++ b/app/Http/Controllers/JournalController.php
@@ -27,6 +27,8 @@ public function getData($userId, $companyId, $search = null, $status = null, $so
$sortType = 'asc';
}
$journals = $journals->orderBy($sort, $sortType);
+ } else {
+ $journals = $journals->orderBy('date', 'desc');
}
if ($paginate) {
$journals = $journals->paginate(10);
diff --git a/app/Http/Controllers/ScoreController.php b/app/Http/Controllers/ScoreController.php
index 9bd3ff2..85f0bad 100644
--- a/app/Http/Controllers/ScoreController.php
+++ b/app/Http/Controllers/ScoreController.php
@@ -89,6 +89,7 @@ public function store(Request $request)
'company_id' => 'required|exists:companies,id',
'name' => 'required',
'score' => 'required|integer',
+ 'type' => 'required|in:teknis,non-teknis'
]);
Score::create($request->all());
@@ -165,12 +166,14 @@ public function update(Request $request, $id)
$request->validate([
'name' => 'required',
'score' => 'required|integer',
+ 'type' => 'required|in:teknis,non-teknis'
]);
$score = Score::find($id);
$score->update([
'name' => $request->name,
'score' => $request->score,
+ 'type' => $request->type,
]);
return redirect()->route('scores.index', ['user' => encrypt($score->user_id), 'company' => encrypt($score->company_id)]);
diff --git a/app/Http/Controllers/StudentController.php b/app/Http/Controllers/StudentController.php
index 8acbd00..7fb127e 100644
--- a/app/Http/Controllers/StudentController.php
+++ b/app/Http/Controllers/StudentController.php
@@ -5,6 +5,7 @@
use Carbon\Carbon;
use App\Models\User;
use App\Models\Course;
+use App\Models\Company;
use Illuminate\Http\Request;
use App\Models\PresenceStatus;
@@ -18,7 +19,8 @@ public function getData($search=null, $status=null, $school=null, $department=nu
$isTeacher = auth()->user()->hasRole('teacher');
$isMentor = auth()->user()->hasRole('mentor');
- $users = User::whereRelation('roles', 'name', 'student');
+ $users = User::whereRelation('roles', 'name', 'student')
+ ->with(['companies', 'internDates', 'schools', 'departments']);
if ($search) {
$users = $users->where('name', 'like', '%' . $search . '%')
->orWhere('email', 'like', '%' . $search . '%');
@@ -121,24 +123,41 @@ public function edit(Request $request, $id)
if ($company) {
$user = User::whereRelation('roles', 'name', 'student')
->where('id', $id)
- ->whereHas('companies', function($query) use ($company) {
- $query->where('company_id', $company);
- })
- ->with(['companies' => function($query) use ($company) {
- $query->where('company_id', $company);
- }, 'courses' => function($query) use ($company) {
- $query->first();
- },'internDates' => function($query) use ($company) {
- $query->where('company_id', $company);
- }])
+ ->with(['companies', 'internDates'])
->first();
} else {
$user = User::whereRelation('roles', 'name', 'student')
->where('id', $id)
->first();
}
-
- $company = $company ? $user->companies()->first() : null;
+ if (auth()->user()->hasRole('mentor')) {
+ $mentorCompanyIds = auth()->user()->companies->pluck('id')->toArray();
+ $companiesData = $user->companies->filter(function ($company) use ($mentorCompanyIds) {
+ return in_array($company->id, $mentorCompanyIds);
+ })->map(function ($company) use ($user) {
+ $internDate = $user->internDates->where('company_id', $company->id)->first();
+ return [
+ 'id' => $company->id,
+ 'name' => $company->name,
+ 'start_date' => $internDate?->start_date,
+ 'end_date' => $internDate?->end_date,
+ 'extend' => $internDate?->extend,
+ 'finished' => $internDate?->finished,
+ ];
+ });
+ } else {
+ $companiesData = $user->companies->map(function ($company) use ($user) {
+ $internDate = $user->internDates->where('company_id', $company->id)->first();
+ return [
+ 'id' => $company->id,
+ 'name' => $company->name,
+ 'start_date' => $internDate?->start_date,
+ 'end_date' => $internDate?->end_date,
+ 'extend' => $internDate?->extend,
+ 'finished' => $internDate?->finished,
+ ];
+ });
+ }
if ($user) {
$courses = Course::where('department_id', $user->departments()->first()->id)->pluck('name', 'id');
@@ -147,7 +166,7 @@ public function edit(Request $request, $id)
'status' => true,
'message' => 'Data siswa ditemukan',
'student' => $user,
- 'company' => $company,
+ 'companiesData' => $companiesData,
'courses' => $courses,
];
} else {
@@ -155,24 +174,28 @@ public function edit(Request $request, $id)
'status' => false,
'message' => 'Data siswa tidak ditemukan',
'student' => null,
- 'company' => $company,
+ 'companiesData' => $companiesData,
'courses' => null
];
}
+ // dd($context);
+
return view('students.edit', $context);
}
public function update(Request $request, $id)
{
- $company = $request->query('company');
- $company = $company ? decrypt($company) : null;
$id = decrypt($id);
$request->validate([
'name' => 'required|string|max:255',
'skills' => 'nullable|string',
'course_id' => 'required|exists:courses,id',
+ 'companies.*.start_date' => 'nullable|date',
+ 'companies.*.end_date' => 'nullable|date',
+ 'companies.*.extend' => 'nullable|integer',
+ 'companies.*.finished' => 'nullable|boolean',
]);
$user = User::whereRelation('roles', 'name', 'student')
@@ -186,46 +209,59 @@ public function update(Request $request, $id)
]);
$user->courses()->sync($request->course_id);
- if ($company) {
-
- $request->validate([
- 'start_date' => 'required|date',
- 'end_date' => 'required|date',
- 'extend' => 'nullable|integer',
- 'finished' => 'required|boolean',
- ]);
-
- $user->internDates()->where('company_id', $company)->update([
- 'start_date' => $request->start_date,
- 'end_date' => $request->end_date,
- 'extend' => $request->extend,
- 'finished' => $request->finished,
- ]);
-
- $presencePending = PresenceStatus::where('name', 'Pending')->first('id')->id;
- $startDate = Carbon::parse($request->start_date);
- $endDate = Carbon::parse($request->end_date);
-
- for ($i = $startDate; $i <= $endDate; $i->addDay()) {
- $presence = $user->presences()->where('company_id', $company)->where('date', $i)->first();
- $journal = $user->journals()->where('company_id', $company)->where('date', $i)->first();
-
- if (! $presence) {
- $user->presences()->create([
- 'company_id' => $company,
- 'date' => $i,
- 'presence_status_id' => $presencePending,
- ]);
- }
- if (! $journal) {
- $user->journals()->create([
- 'company_id' => $company,
- 'date' => $i,
- ]);
+ if ($request->has('companies')) {
+ foreach ($request->companies as $companyId => $data) {
+ $company = Company::find($companyId);
+ if ($company) {
+ $startDate = Carbon::parse($data['start_date']);
+ $endDate = Carbon::parse($data['end_date']);
+
+ $overlapCheck = $user->internDates()->where('company_id', '!=', $companyId)
+ ->where(function ($query) use ($startDate, $endDate) {
+ $query->whereBetween('start_date', [$startDate, $endDate])
+ ->orWhereBetween('end_date', [$startDate, $endDate])
+ ->orWhere(function ($query) use ($startDate, $endDate) {
+ $query->where('start_date', '<=', $startDate)
+ ->where('end_date', '>=', $endDate);
+ });
+ })->exists();
+
+ if ($overlapCheck) {
+ return back()->with('error', 'Tanggal yang dipilih tidak sesuai.');
+ }
+ $user->internDates()->updateOrCreate(
+ ['company_id' => $companyId],
+ [
+ 'start_date' => $data['start_date'] ?? null,
+ 'end_date' => $data['end_date'] ?? null,
+ 'extend' => $data['extend'] ?? 0,
+ 'finished' => $data['finished'] ?? 0,
+ ]
+ );
+
+ $presencePending = PresenceStatus::where('name', 'Pending')->first('id')->id;
+
+ for ($i = $startDate; $i <= $endDate; $i->addDay()) {
+ $presence = $user->presences()->where('company_id', $companyId)->where('date', $i)->first();
+ if (!$presence) {
+ $user->presences()->create([
+ 'company_id' => $companyId,
+ 'date' => $i,
+ 'presence_status_id' => $presencePending,
+ ]);
+ }
+
+ $journal = $user->journals()->where('company_id', $companyId)->where('date', $i)->first();
+ if (!$journal) {
+ $user->journals()->create([
+ 'company_id' => $companyId,
+ 'date' => $i,
+ ]);
+ }
+ }
}
}
}
-
return redirect()->route('students.index')->with('success', 'Data siswa berhasil diperbarui');
} else {
return redirect()->route('students.index')->with('error', 'Data siswa tidak ditemukan');
diff --git a/app/Models/Score.php b/app/Models/Score.php
index 084479c..182b007 100644
--- a/app/Models/Score.php
+++ b/app/Models/Score.php
@@ -14,6 +14,7 @@ class Score extends Model
'company_id',
'name',
'score',
+ 'type',
];
protected $appends = [
diff --git a/composer.json b/composer.json
index d35f0cd..d20322f 100644
--- a/composer.json
+++ b/composer.json
@@ -18,6 +18,7 @@
"laravel/tinker": "^2.7",
"maatwebsite/excel": "^3.1",
"meilisearch/meilisearch-php": "^1.0",
+ "mikehaertl/php-pdftk": "^0.13.1",
"owen-it/laravel-auditing": "^13.0",
"spatie/laravel-permission": "^5.7"
},
diff --git a/composer.lock b/composer.lock
index 53c3141..9d04daa 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "24e4eb0d49ea1511e0ad0067e3d9788a",
+ "content-hash": "20003ba38720bb0f0b87ef46cf44787c",
"packages": [
{
"name": "bacon/bacon-qr-code",
@@ -2750,6 +2750,145 @@
},
"time": "2024-08-26T23:09:54+00:00"
},
+ {
+ "name": "mikehaertl/php-pdftk",
+ "version": "0.13.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/mikehaertl/php-pdftk.git",
+ "reference": "3851b08c1027489e48387d7c14c27bc295d98239"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/mikehaertl/php-pdftk/zipball/3851b08c1027489e48387d7c14c27bc295d98239",
+ "reference": "3851b08c1027489e48387d7c14c27bc295d98239",
+ "shasum": ""
+ },
+ "require": {
+ "mikehaertl/php-shellcommand": "^1.6.3",
+ "mikehaertl/php-tmpfile": "^1.1.0",
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": ">4.0 <9.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "mikehaertl\\pdftk\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Haertl",
+ "email": "haertl.mike@gmail.com"
+ }
+ ],
+ "description": "A PDF conversion and form utility based on pdftk.",
+ "keywords": [
+ "pdf",
+ "pdftk"
+ ],
+ "support": {
+ "issues": "https://github.com/mikehaertl/php-pdftk/issues",
+ "source": "https://github.com/mikehaertl/php-pdftk/tree/0.13.1"
+ },
+ "time": "2023-11-03T16:06:08+00:00"
+ },
+ {
+ "name": "mikehaertl/php-shellcommand",
+ "version": "1.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/mikehaertl/php-shellcommand.git",
+ "reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/mikehaertl/php-shellcommand/zipball/e79ea528be155ffdec6f3bf1a4a46307bb49e545",
+ "reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">= 5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": ">4.0 <=9.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "mikehaertl\\shellcommand\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Härtl",
+ "email": "haertl.mike@gmail.com"
+ }
+ ],
+ "description": "An object oriented interface to shell commands",
+ "keywords": [
+ "shell"
+ ],
+ "support": {
+ "issues": "https://github.com/mikehaertl/php-shellcommand/issues",
+ "source": "https://github.com/mikehaertl/php-shellcommand/tree/1.7.0"
+ },
+ "time": "2023-04-19T08:25:22+00:00"
+ },
+ {
+ "name": "mikehaertl/php-tmpfile",
+ "version": "1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/mikehaertl/php-tmpfile.git",
+ "reference": "a5392bed91f67e2849a7cb24075d346468e1b1a8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/mikehaertl/php-tmpfile/zipball/a5392bed91f67e2849a7cb24075d346468e1b1a8",
+ "reference": "a5392bed91f67e2849a7cb24075d346468e1b1a8",
+ "shasum": ""
+ },
+ "require-dev": {
+ "php": ">=5.3.0",
+ "phpunit/phpunit": ">4.0 <=9.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "mikehaertl\\tmp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Härtl",
+ "email": "haertl.mike@gmail.com"
+ }
+ ],
+ "description": "A convenience class for temporary files",
+ "keywords": [
+ "files"
+ ],
+ "support": {
+ "issues": "https://github.com/mikehaertl/php-tmpfile/issues",
+ "source": "https://github.com/mikehaertl/php-tmpfile/tree/1.3.0"
+ },
+ "time": "2024-10-14T16:12:48+00:00"
+ },
{
"name": "monolog/monolog",
"version": "3.7.0",
diff --git a/database/migrations/2025_01_30_135142_add_type_to_scores_table.php b/database/migrations/2025_01_30_135142_add_type_to_scores_table.php
new file mode 100644
index 0000000..18da51d
--- /dev/null
+++ b/database/migrations/2025_01_30_135142_add_type_to_scores_table.php
@@ -0,0 +1,28 @@
+enum('type', ['teknis', 'non-teknis'])->default('teknis');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('scores', function (Blueprint $table) {
+ $table->dropColumn('type');
+ });
+ }
+};
diff --git a/database/seeders/MenuSeeder.php b/database/seeders/MenuSeeder.php
index 4e2b4e5..68f74f6 100644
--- a/database/seeders/MenuSeeder.php
+++ b/database/seeders/MenuSeeder.php
@@ -69,7 +69,7 @@ public function run()
'url' => 'news?category=school&school=' . encrypt($school->id),
'status' => 1,
'order' => 31,
- 'parent_id' => 4,
+ 'parent_id' => 5,
'permission_id' => Permission::where('name', 'news-list')->first()->id,
],
[
@@ -78,7 +78,7 @@ public function run()
'url' => 'news?category=department&school=' . encrypt($school->id),
'status' => 1,
'order' => 32,
- 'parent_id' => 4,
+ 'parent_id' => 5,
'permission_id' => Permission::where('name', 'news-list')->first()->id,
],
[
diff --git a/resources/views/scores/create.blade.php b/resources/views/scores/create.blade.php
index 9012045..7ae8803 100644
--- a/resources/views/scores/create.blade.php
+++ b/resources/views/scores/create.blade.php
@@ -5,6 +5,13 @@
Belum Diisi
- @endif -Belum Diisi
- @endif -