diff --git a/app/Http/Controllers/ApiController.php b/app/Http/Controllers/ApiController.php index 933082e..41e2eeb 100755 --- a/app/Http/Controllers/ApiController.php +++ b/app/Http/Controllers/ApiController.php @@ -287,7 +287,11 @@ class ApiController extends Controller public function logout() { - Auth::user()->tokens()->delete(); + /** @var \App\Models\User $user */ + $user = auth('sanctum')->user(); + if ($user) { + $user->tokens()->delete(); + } return response()->json([ 'message' => 'Logout success', 'status' => true, diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index 60b186c..b228aca 100755 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -1060,7 +1060,6 @@ class TransactionController extends Controller 'users.name as mechanic_name' ]) ->where('transactions.dealer_id', $request->dealer_id) - ->where('users.role_id', 4) // Only transactions created by SA ->whereIn('transactions.status', [0, 1]) // Only pending and completed transactions ->orderBy('transactions.date', 'desc'); @@ -1091,6 +1090,7 @@ class TransactionController extends Controller $data = []; foreach ($transactions as $transaction) { $data[] = [ + 'id' => $transaction->id, 'date' => date('d/m/Y', strtotime($transaction->date)), 'spk' => $transaction->spk, 'police_number' => $transaction->police_number, @@ -1127,13 +1127,7 @@ class TransactionController extends Controller case 0: // pending return 'Menunggu'; case 1: // completed - return 'Selesai'; - case 2: // in_progress - return 'Sedang Dikerjakan'; - case 3: // claimed - return 'Diklaim'; - case 4: // cancelled - return 'Dibatalkan'; + return 'Closed'; default: return 'Tidak Diketahui'; } @@ -1234,6 +1228,25 @@ class TransactionController extends Controller $buttons .= 'Klaim'; $buttons .= ''; } else { + if($transaction->claimed_by == Auth::user()->id) { + // Check if precheck exists + $precheck = \App\Models\Precheck::where('transaction_id', $transaction->id)->first(); + if (!$precheck) { + $buttons .= ''; + $buttons .= 'Precheck'; + $buttons .= ''; + } else { + // Check if postcheck exists + $postcheck = \App\Models\Postcheck::where('transaction_id', $transaction->id)->first(); + if (!$postcheck) { + $buttons .= ''; + $buttons .= 'Postcheck'; + $buttons .= ''; + } else { + $buttons .= 'Selesai'; + } + } + } $buttons .= 'Sudah Diklaim'; } } diff --git a/app/Http/Controllers/Transactions/PostchecksController.php b/app/Http/Controllers/Transactions/PostchecksController.php new file mode 100644 index 0000000..f022fee --- /dev/null +++ b/app/Http/Controllers/Transactions/PostchecksController.php @@ -0,0 +1,72 @@ +validate([ + 'kilometer' => 'required|numeric|min:0', + 'pressure_high' => 'required|numeric|min:0', + 'pressure_low' => 'nullable|numeric|min:0', + 'cabin_temperature' => 'nullable|numeric', + 'cabin_temperature_image' => 'nullable|string', + 'ac_condition' => 'nullable|in:' . implode(',', Postcheck::getAcConditionOptions()), + 'ac_image' => 'nullable|string', + 'blower_condition' => 'nullable|in:' . implode(',', Postcheck::getBlowerConditionOptions()), + 'blower_image' => 'nullable|string', + 'evaporator_condition' => 'nullable|in:' . implode(',', Postcheck::getEvaporatorConditionOptions()), + 'evaporator_image' => 'nullable|string', + 'compressor_condition' => 'nullable|in:' . implode(',', Postcheck::getCompressorConditionOptions()), + 'postcheck_notes' => 'nullable|string', + 'front_image' => 'required|string', + ]); + + // Pastikan transaction_id sama dengan $transaction->id + $postcheck = Postcheck::create([ + 'transaction_id' => $transaction->id, + 'postcheck_by' => auth()->id(), + 'postcheck_at' => now(), + 'police_number' => $transaction->police_number, + 'spk_number' => $transaction->spk, + 'front_image' => $request->front_image, + 'kilometer' => $request->kilometer, + 'pressure_high' => $request->pressure_high, + 'pressure_low' => $request->pressure_low, + 'cabin_temperature' => $request->cabin_temperature, + 'cabin_temperature_image' => $request->cabin_temperature_image, + 'ac_condition' => $request->ac_condition, + 'ac_image' => $request->ac_image, + 'blower_condition' => $request->blower_condition, + 'blower_image' => $request->blower_image, + 'evaporator_condition' => $request->evaporator_condition, + 'evaporator_image' => $request->evaporator_image, + 'compressor_condition' => $request->compressor_condition, + 'postcheck_notes' => $request->postcheck_notes, + ]); + + return redirect()->route('transaction')->with('success', 'Postcheck berhasil disimpan'); + } +} diff --git a/app/Http/Controllers/Transactions/PrechecksController.php b/app/Http/Controllers/Transactions/PrechecksController.php new file mode 100644 index 0000000..21d121e --- /dev/null +++ b/app/Http/Controllers/Transactions/PrechecksController.php @@ -0,0 +1,72 @@ +validate([ + 'kilometer' => 'required|numeric|min:0', + 'pressure_high' => 'required|numeric|min:0', + 'pressure_low' => 'nullable|numeric|min:0', + 'cabin_temperature' => 'nullable|numeric', + 'cabin_temperature_image' => 'nullable|string', + 'ac_condition' => 'nullable|in:' . implode(',', Precheck::getAcConditionOptions()), + 'ac_image' => 'nullable|string', + 'blower_condition' => 'nullable|in:' . implode(',', Precheck::getBlowerConditionOptions()), + 'blower_image' => 'nullable|string', + 'evaporator_condition' => 'nullable|in:' . implode(',', Precheck::getEvaporatorConditionOptions()), + 'evaporator_image' => 'nullable|string', + 'compressor_condition' => 'nullable|in:' . implode(',', Precheck::getCompressorConditionOptions()), + 'precheck_notes' => 'nullable|string', + 'front_image' => 'required|string', + ]); + + // Pastikan transaction_id sama dengan $transaction->id + $precheck = Precheck::create([ + 'transaction_id' => $transaction->id, + 'precheck_by' => auth()->id(), + 'precheck_at' => now(), + 'police_number' => $transaction->police_number, + 'spk_number' => $transaction->spk, + 'front_image' => $request->front_image, + 'kilometer' => $request->kilometer, + 'pressure_high' => $request->pressure_high, + 'pressure_low' => $request->pressure_low, + 'cabin_temperature' => $request->cabin_temperature, + 'cabin_temperature_image' => $request->cabin_temperature_image, + 'ac_condition' => $request->ac_condition, + 'ac_image' => $request->ac_image, + 'blower_condition' => $request->blower_condition, + 'blower_image' => $request->blower_image, + 'evaporator_condition' => $request->evaporator_condition, + 'evaporator_image' => $request->evaporator_image, + 'compressor_condition' => $request->compressor_condition, + 'precheck_notes' => $request->precheck_notes, + ]); + + return redirect()->route('transaction')->with('success', 'Precheck berhasil disimpan'); + } +} diff --git a/app/Models/Postcheck.php b/app/Models/Postcheck.php new file mode 100644 index 0000000..5134376 --- /dev/null +++ b/app/Models/Postcheck.php @@ -0,0 +1,138 @@ + 'datetime', + 'kilometer' => 'decimal:2', + 'pressure_high' => 'decimal:2', + 'pressure_low' => 'decimal:2', + 'cabin_temperature' => 'decimal:2', + ]; + + /** + * Get the transaction associated with the Postcheck + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function transaction() + { + return $this->belongsTo(Transaction::class); + } + + /** + * Get the user who performed the postcheck + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function postcheckBy() + { + return $this->belongsTo(User::class, 'postcheck_by'); + } + + /** + * Get the AC condition options + * + * @return array + */ + public static function getAcConditionOptions() + { + return ['sudah dikerjakan', 'sudah diganti']; + } + + /** + * Get the blower condition options + * + * @return array + */ + public static function getBlowerConditionOptions() + { + return ['sudah dibersihkan atau dicuci', 'sudah diganti']; + } + + /** + * Get the evaporator condition options + * + * @return array + */ + public static function getEvaporatorConditionOptions() + { + return ['sudah dikerjakan', 'sudah diganti']; + } + + /** + * Get the compressor condition options + * + * @return array + */ + public static function getCompressorConditionOptions() + { + return ['sudah dikerjakan', 'sudah diganti']; + } + + /** + * Scope to filter by transaction + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param int $transactionId + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeByTransaction($query, $transactionId) + { + return $query->where('transaction_id', $transactionId); + } + + /** + * Scope to filter by user who performed postcheck + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param int $userId + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeByUser($query, $userId) + { + return $query->where('postcheck_by', $userId); + } + + /** + * Scope to filter by date range + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param string $startDate + * @param string $endDate + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeByDateRange($query, $startDate, $endDate) + { + return $query->whereBetween('postcheck_at', [$startDate, $endDate]); + } +} \ No newline at end of file diff --git a/app/Models/Precheck.php b/app/Models/Precheck.php new file mode 100644 index 0000000..104b63c --- /dev/null +++ b/app/Models/Precheck.php @@ -0,0 +1,138 @@ + 'datetime', + 'kilometer' => 'decimal:2', + 'pressure_high' => 'decimal:2', + 'pressure_low' => 'decimal:2', + 'cabin_temperature' => 'decimal:2', + ]; + + /** + * Get the transaction associated with the Precheck + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function transaction() + { + return $this->belongsTo(Transaction::class); + } + + /** + * Get the user who performed the precheck + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function precheckBy() + { + return $this->belongsTo(User::class, 'precheck_by'); + } + + /** + * Get the AC condition options + * + * @return array + */ + public static function getAcConditionOptions() + { + return ['kotor', 'rusak', 'baik', 'tidak ada']; + } + + /** + * Get the blower condition options + * + * @return array + */ + public static function getBlowerConditionOptions() + { + return ['kotor', 'rusak', 'baik', 'tidak ada']; + } + + /** + * Get the evaporator condition options + * + * @return array + */ + public static function getEvaporatorConditionOptions() + { + return ['kotor', 'berlendir', 'bocor', 'bersih']; + } + + /** + * Get the compressor condition options + * + * @return array + */ + public static function getCompressorConditionOptions() + { + return ['kotor', 'rusak', 'baik', 'tidak ada']; + } + + /** + * Scope to filter by transaction + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param int $transactionId + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeByTransaction($query, $transactionId) + { + return $query->where('transaction_id', $transactionId); + } + + /** + * Scope to filter by user who performed precheck + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param int $userId + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeByUser($query, $userId) + { + return $query->where('precheck_by', $userId); + } + + /** + * Scope to filter by date range + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param string $startDate + * @param string $endDate + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeByDateRange($query, $startDate, $endDate) + { + return $query->whereBetween('precheck_at', [$startDate, $endDate]); + } +} \ No newline at end of file diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 37c604a..a5782fa 100755 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -57,4 +57,24 @@ class Transaction extends Model { return $this->belongsTo(User::class, 'user_sa_id'); } + + /** + * Get the precheck associated with the transaction + * + * @return \Illuminate\Database\Eloquent\Relations\HasOne + */ + public function precheck() + { + return $this->hasOne(Precheck::class); + } + + /** + * Get the postcheck associated with the transaction + * + * @return \Illuminate\Database\Eloquent\Relations\HasOne + */ + public function postcheck() + { + return $this->hasOne(Postcheck::class); + } } diff --git a/app/Models/User.php b/app/Models/User.php index b957ad7..457cd31 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -301,4 +301,24 @@ class User extends Authenticatable ->where('privileges.view', 1) ->exists(); } + + /** + * Get all prechecks performed by this user + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function prechecks() + { + return $this->hasMany(Precheck::class, 'precheck_by'); + } + + /** + * Get all postchecks performed by this user + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function postchecks() + { + return $this->hasMany(Postcheck::class, 'postcheck_by'); + } } diff --git a/database/migrations/2025_07_10_140352_create_prechecks_table.php b/database/migrations/2025_07_10_140352_create_prechecks_table.php new file mode 100644 index 0000000..87a54dd --- /dev/null +++ b/database/migrations/2025_07_10_140352_create_prechecks_table.php @@ -0,0 +1,54 @@ +id(); + $table->foreignId('transaction_id')->constrained()->onDelete('cascade'); + $table->foreignId('precheck_by')->constrained('users')->onDelete('cascade'); + $table->timestamp('precheck_at')->nullable(); + $table->string('police_number'); + $table->string('spk_number'); + $table->string('front_image'); + $table->decimal('kilometer', 10, 2); + $table->decimal('pressure_high', 10, 2); + $table->decimal('pressure_low', 10, 2)->nullable(); + $table->decimal('cabin_temperature', 10, 2)->nullable(); + $table->string('cabin_temperature_image')->nullable(); + $table->enum('ac_condition', ['kotor', 'rusak', 'baik', 'tidak ada'])->nullable(); + $table->string('ac_image')->nullable(); + $table->enum('blower_condition', ['kotor', 'rusak', 'baik', 'tidak ada'])->nullable(); + $table->string('blower_image')->nullable(); + $table->enum('evaporator_condition', ['kotor', 'berlendir', 'bocor', 'bersih'])->nullable(); + $table->string('evaporator_image')->nullable(); + $table->enum('compressor_condition', ['kotor', 'rusak', 'baik', 'tidak ada'])->nullable(); + $table->text('precheck_notes')->nullable(); + $table->timestamps(); + + $table->index(['transaction_id']); + $table->index(['precheck_by']); + $table->index(['precheck_at']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('prechecks'); + } +} diff --git a/database/migrations/2025_07_10_140406_create_postchecks_table.php b/database/migrations/2025_07_10_140406_create_postchecks_table.php new file mode 100644 index 0000000..082d054 --- /dev/null +++ b/database/migrations/2025_07_10_140406_create_postchecks_table.php @@ -0,0 +1,54 @@ +id(); + $table->foreignId('transaction_id')->constrained()->onDelete('cascade'); + $table->foreignId('postcheck_by')->constrained('users')->onDelete('cascade'); + $table->timestamp('postcheck_at')->nullable(); + $table->string('police_number'); + $table->string('spk_number'); + $table->string('front_image'); + $table->decimal('kilometer', 10, 2); + $table->decimal('pressure_high', 10, 2); + $table->decimal('pressure_low', 10, 2)->nullable(); + $table->decimal('cabin_temperature', 10, 2)->nullable(); + $table->string('cabin_temperature_image')->nullable(); + $table->enum('ac_condition', ['sudah dikerjakan', 'sudah diganti'])->nullable(); + $table->string('ac_image')->nullable(); + $table->enum('blower_condition', ['sudah dibersihkan atau dicuci', 'sudah diganti'])->nullable(); + $table->string('blower_image')->nullable(); + $table->enum('evaporator_condition', ['sudah dikerjakan', 'sudah diganti'])->nullable(); + $table->string('evaporator_image')->nullable(); + $table->enum('compressor_condition', ['sudah dikerjakan', 'sudah diganti'])->nullable(); + $table->text('postcheck_notes')->nullable(); + $table->timestamps(); + + $table->index(['transaction_id']); + $table->index(['postcheck_by']); + $table->index(['postcheck_at']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('postchecks'); + } +} diff --git a/resources/views/transaction/postchecks.blade.php b/resources/views/transaction/postchecks.blade.php new file mode 100644 index 0000000..38c02bc --- /dev/null +++ b/resources/views/transaction/postchecks.blade.php @@ -0,0 +1,768 @@ +@extends('layouts.frontapp') + +@section('styles') + +@endsection + +@section('content') +