From ad7789dd3f2768cb9c72d0d444aa43a0586bab06 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Mon, 19 Jan 2026 08:23:56 +0700 Subject: [PATCH] feat: Add a console command to simulate cooperation time, improve date validation, and refine UI texts and report creation conditions. --- .../Commands/SimulateCooperationTime.php | 130 ++++++++++++++++++ .../Actions/Proposal/RejectAction.php | 2 +- .../Actions/Report/RejectAction.php | 2 +- .../CooperationProposalRelationManager.php | 19 ++- .../ReportRelationManager.php | 2 + .../TaskAssignmentRelationManager.php | 5 - .../Cooperations/Schemas/CooperationForm.php | 10 +- app/Models/CooperationPayment.php | 2 +- ...0256_create_cooperation_payments_table.php | 2 +- database/seeders/CooperationSeeder.php | 2 +- 10 files changed, 161 insertions(+), 15 deletions(-) create mode 100644 app/Console/Commands/SimulateCooperationTime.php diff --git a/app/Console/Commands/SimulateCooperationTime.php b/app/Console/Commands/SimulateCooperationTime.php new file mode 100644 index 0000000..21c5f02 --- /dev/null +++ b/app/Console/Commands/SimulateCooperationTime.php @@ -0,0 +1,130 @@ +isLocal()) { + $this->error('This command can only be run in local environment.'); + + return Command::FAILURE; + } + + $cooperationId = $this->argument('id'); + + // Interactive Selection if ID not provided + if (! $cooperationId) { + $cooperations = Cooperation::whereIn('status', [ + CooperationStatus::PENDING, + CooperationStatus::ASSIGNMENT, + ])->get(); + + if ($cooperations->isEmpty()) { + $this->warn('No active cooperations (PENDING or ASSIGNMENT) found to simulate.'); + + return Command::SUCCESS; + } + + $choices = []; + foreach ($cooperations as $c) { + // Handle enum value safely + $status = $c->status instanceof \UnitEnum ? $c->status->value : $c->status; + $choices[$c->id] = "[ID: {$c->id}] {$c->title} ({$status})"; + } + + $choice = $this->choice( + 'Which cooperation do you want to fast-forward?', + $choices + ); + + // Retrieve the ID associated with the choice + $cooperationId = array_search($choice, $choices); + } + + $cooperation = Cooperation::find($cooperationId); + + if (! $cooperation) { + $this->error("Cooperation with ID {$cooperationId} not found."); + + return Command::FAILURE; + } + + $this->info("Simulating time passage for: {$cooperation->title}"); + + if ($cooperation->status === CooperationStatus::PENDING) { + // 1. Move dates to past + $cooperation->update([ + 'initial_submission_date' => now()->subDays(8), + 'final_submission_date' => now()->subDay(), + ]); + $this->info('Moved dates to the past (Final Submission: Yesterday).'); + + // 2. Reject unresponsive media + $rejectedCount = CooperationMedia::where('cooperation_id', $cooperation->id) + ->pending() + ->update(['status' => ApprovalStatus::REJECTED]); + + if ($rejectedCount > 0) { + $this->info("Rejected {$rejectedCount} media that didn't respond."); + } + + // 3. Update Status + $cooperation->update(['status' => CooperationStatus::ASSIGNMENT]); + $this->info('Status transitioned to ASSIGNMENT.'); + } elseif ($cooperation->status === CooperationStatus::ASSIGNMENT) { + if ($cooperation->taskAssignment) { + // 1. Move task dates to past + $cooperation->taskAssignment->update([ + 'start_date' => now()->subDays(8), + 'end_date' => now()->subDay(), + ]); + $this->info('Moved task dates to the past (Task End: Yesterday).'); + + // 2. Reject unresponsive media (assignments) + $rejectedCount = CooperationMedia::where('cooperation_id', $cooperation->id) + ->pending() + ->update(['status' => ApprovalStatus::REJECTED]); + + if ($rejectedCount > 0) { + $this->info("Rejected {$rejectedCount} media that didn't respond to assignment."); + } + + // 3. Update Status + $cooperation->update(['status' => CooperationStatus::VERIFICATION]); + $this->info('Status transitioned to VERIFICATION.'); + } else { + $this->error('This ASSIGNMENT cooperation has no Task Assignment yet.'); + } + } else { + $status = $cooperation->status instanceof \UnitEnum ? $cooperation->status->value : $cooperation->status; + $this->warn("Cooperation status '{$status}' is not supported for simulation. Only PENDING and ASSIGNMENT are supported."); + } + + return Command::SUCCESS; + } +} diff --git a/app/Filament/Resources/Manage/Cooperations/Actions/Proposal/RejectAction.php b/app/Filament/Resources/Manage/Cooperations/Actions/Proposal/RejectAction.php index 0bfbc00..b661979 100644 --- a/app/Filament/Resources/Manage/Cooperations/Actions/Proposal/RejectAction.php +++ b/app/Filament/Resources/Manage/Cooperations/Actions/Proposal/RejectAction.php @@ -25,7 +25,7 @@ protected function setUp(): void ->schema([ Textarea::make('reason') ->label('Alasan Penolakan') - ->placeholder('...') + ->placeholder('Jelaskan alasan pengajuan ditolak...') ->required(), ]) ->action(function (CooperationProposal $record, array $data): void { diff --git a/app/Filament/Resources/Manage/Cooperations/Actions/Report/RejectAction.php b/app/Filament/Resources/Manage/Cooperations/Actions/Report/RejectAction.php index 12ceefc..90a7c76 100644 --- a/app/Filament/Resources/Manage/Cooperations/Actions/Report/RejectAction.php +++ b/app/Filament/Resources/Manage/Cooperations/Actions/Report/RejectAction.php @@ -26,7 +26,7 @@ protected function setUp(): void ->schema([ Textarea::make('reason') ->label('Alasan Penolakan') - ->placeholder('Jelaskan apa yang perlu diperbaiki...') + ->placeholder('Jelaskan alasan pengajuan ditolak...') ->required(), ]) ->action(function (Report $record, array $data): void { diff --git a/app/Filament/Resources/Manage/Cooperations/RelationManagers/CooperationProposalRelationManager.php b/app/Filament/Resources/Manage/Cooperations/RelationManagers/CooperationProposalRelationManager.php index 5c41a7c..d06cb91 100644 --- a/app/Filament/Resources/Manage/Cooperations/RelationManagers/CooperationProposalRelationManager.php +++ b/app/Filament/Resources/Manage/Cooperations/RelationManagers/CooperationProposalRelationManager.php @@ -44,7 +44,11 @@ public static function canViewForRecord(Model $ownerRecord, string $pageClass): public static function getBadge(Model $ownerRecord, string $pageClass): ?string { - return $ownerRecord->proposal()->count(); + if (auth()->user()->hasRole('Perusahaan')) { + return null; + } + + return (string) $ownerRecord->proposal()->count(); } public function table(Table $table): Table @@ -103,7 +107,18 @@ public function table(Table $table): Table ->success() ), ]), - ]); + ]) + ->modifyQueryUsing(function ($query) { + $user = auth()->user(); + + if (! $user->hasRole('Perusahaan')) { + return $query; + } + + return $query->whereHas('partnerMedia.company', function ($q) use ($user) { + $q->where('user_id', $user->id); + }); + }); } public function infolist(Schema $infolist): Schema diff --git a/app/Filament/Resources/Manage/Cooperations/RelationManagers/ReportRelationManager.php b/app/Filament/Resources/Manage/Cooperations/RelationManagers/ReportRelationManager.php index c76099c..9992f47 100644 --- a/app/Filament/Resources/Manage/Cooperations/RelationManagers/ReportRelationManager.php +++ b/app/Filament/Resources/Manage/Cooperations/RelationManagers/ReportRelationManager.php @@ -182,6 +182,8 @@ public function table(Table $table): Table } return $this->getOwnerRecord()->status === CooperationStatus::ASSIGNMENT + && $taskAssignment->start_date->toDateString() <= now()->toDateString() + && $taskAssignment->end_date->toDateString() >= now()->toDateString() && $taskAssignment->reports() ->where('status', '!=', ApprovalStatus::REJECTED) ->count() < $taskAssignment->report_amount; diff --git a/app/Filament/Resources/Manage/Cooperations/RelationManagers/TaskAssignmentRelationManager.php b/app/Filament/Resources/Manage/Cooperations/RelationManagers/TaskAssignmentRelationManager.php index 99623a5..e245561 100644 --- a/app/Filament/Resources/Manage/Cooperations/RelationManagers/TaskAssignmentRelationManager.php +++ b/app/Filament/Resources/Manage/Cooperations/RelationManagers/TaskAssignmentRelationManager.php @@ -37,11 +37,6 @@ public static function canViewForRecord(Model $ownerRecord, string $pageClass): return true; } - public static function getBadge(Model $ownerRecord, string $pageClass): ?string - { - return $ownerRecord->taskAssignment()->count(); - } - public function table(Table $table): Table { return $table diff --git a/app/Filament/Resources/Manage/Cooperations/Schemas/CooperationForm.php b/app/Filament/Resources/Manage/Cooperations/Schemas/CooperationForm.php index f03cb66..155b0fb 100644 --- a/app/Filament/Resources/Manage/Cooperations/Schemas/CooperationForm.php +++ b/app/Filament/Resources/Manage/Cooperations/Schemas/CooperationForm.php @@ -12,6 +12,7 @@ use Filament\Forms\Components\TextInput; use Filament\Schemas\Components\Grid; use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\Utilities\Get; use Filament\Schemas\Components\Utilities\Set; use Filament\Schemas\Schema; use Filament\Support\Icons\Heroicon; @@ -39,15 +40,18 @@ public static function configure(Schema $schema): Schema ->placeholder(fn (): string => now()->translatedFormat('l, d F Y')) ->native(false) ->displayFormat('l, d F Y') - ->required(), + ->required() + ->minDate(today()) + ->reactive(), DatePicker::make('final_submission_date') ->label('Tanggal Pengajuan Akhir') - ->placeholder(fn (): string => now()->addDays(30)->translatedFormat('l, d F Y')) + ->placeholder(fn (): string => now()->addDays(7)->translatedFormat('l, d F Y')) ->native(false) ->displayFormat('l, d F Y') ->required() - ->after('initial_submission_date'), + ->afterOrEqual('initial_submission_date') + ->minDate(fn (Get $get) => $get('initial_submission_date')), ]), Select::make('partner_media_ids') diff --git a/app/Models/CooperationPayment.php b/app/Models/CooperationPayment.php index 9db1a0e..966c594 100644 --- a/app/Models/CooperationPayment.php +++ b/app/Models/CooperationPayment.php @@ -18,7 +18,7 @@ protected function casts(): array { return [ 'amount' => 'integer', - 'payment_date' => 'datetime', + 'payment_date' => 'date', ]; } diff --git a/database/migrations/2026_01_14_140256_create_cooperation_payments_table.php b/database/migrations/2026_01_14_140256_create_cooperation_payments_table.php index b42bec3..6bd0dff 100644 --- a/database/migrations/2026_01_14_140256_create_cooperation_payments_table.php +++ b/database/migrations/2026_01_14_140256_create_cooperation_payments_table.php @@ -14,7 +14,7 @@ public function up(): void { Schema::create('cooperation_payments', function (Blueprint $table) { $table->id(); - $table->foreignIdFor(CooperationMedia::class)->constrained()->cascadeOnDelete(); + $table->foreignIdFor(CooperationMedia::class, 'cooperation_media_id')->constrained()->cascadeOnDelete(); $table->unsignedInteger('amount'); $table->text('description')->nullable(); $table->date('payment_date')->useCurrent(); diff --git a/database/seeders/CooperationSeeder.php b/database/seeders/CooperationSeeder.php index f69aed6..967d165 100644 --- a/database/seeders/CooperationSeeder.php +++ b/database/seeders/CooperationSeeder.php @@ -19,7 +19,7 @@ public function run(): void 'title' => 'Kerja Sama Media '.now()->format('Y'), 'description' => 'Kerja sama media untuk penyebarluasan informasi publik.', 'initial_submission_date' => now()->subDay(), - 'final_submission_date' => now(), + 'final_submission_date' => now()->addDay(), 'status' => CooperationStatus::PENDING, ]);