createCompany(); $user = $this->createUserForCompany($company); $ticket = $this->createTicketForCompany($company, [ 'created_by_id' => $user->id, 'assigned_to_id' => $user->id, ]); $this->actingAs($user) ->post(route('helpdesk.tickets.time-logs.store', $ticket), [ 'minutes' => 45, 'description' => 'Investigated the issue and updated the ticket.', ]) ->assertRedirect(); $this->assertDatabaseHas('helpdesk_time_logs', [ 'ticket_id' => $ticket->id, 'user_id' => $user->id, 'minutes' => 45, 'description' => 'Investigated the issue and updated the ticket.', ]); } /** * It rejects invalid logged minutes. */ public function test_ticket_time_log_requires_valid_minutes(): void { $company = $this->createCompany(); $user = $this->createUserForCompany($company); $ticket = $this->createTicketForCompany($company, [ 'created_by_id' => $user->id, 'assigned_to_id' => $user->id, ]); $this->actingAs($user) ->from(route('helpdesk.tickets.show', $ticket)) ->post(route('helpdesk.tickets.time-logs.store', $ticket), [ 'minutes' => 0, ]) ->assertRedirect(route('helpdesk.tickets.show', $ticket)) ->assertSessionHasErrors('minutes'); } /** * Create a company for ticket time-log feature tests without requiring a CompanyFactory. */ private function createCompany(): Company { return Company::query()->create([ 'name' => 'Helpdesk Test Company '.Str::random(8), 'slug' => 'helpdesk-test-company-'.Str::lower(Str::random(8)), 'status' => 'active', 'timezone' => 'Europe/London', 'billing_email' => 'helpdesk-test-'.Str::lower(Str::random(8)).'@example.test', 'is_system_company' => false, ]); } /** * Create a company-scoped user for ticket time-log feature tests. */ private function createUserForCompany(Company $company): User { return User::factory()->create([ 'company_id' => $company->getKey(), ]); } /** * Create a company-scoped ticket using only columns present in the schema. * * @param array $attributes */ private function createTicketForCompany(Company $company, array $attributes = []): Ticket { $ticket = new Ticket(); $table = $ticket->getTable(); $data = []; $put = static function (string $column, mixed $value) use (&$data, $table): void { if (Schema::hasColumn($table, $column)) { $data[$column] = $value; } }; $status = Status::query()->firstOrCreate( ['slug' => 'open'], [ 'name' => 'Open', 'color' => 'blue', 'sort_order' => 10, 'is_closed' => false, ], ); $priority = Priority::query()->firstOrCreate( ['slug' => 'normal'], [ 'name' => 'Normal', 'color' => 'blue', 'sort_order' => 20, ], ); $userId = $attributes['created_by_id'] ?? $attributes['user_id'] ?? $attributes['owner_id'] ?? $attributes['assigned_to_id'] ?? User::factory()->create(['company_id' => $company->getKey()])->getKey(); $put('company_id', $company->getKey()); $put('user_id', $userId); $put('owner_id', $userId); $put('created_by_id', $userId); $put('assigned_to_id', $attributes['assigned_to_id'] ?? $userId); $put('agent_id', $attributes['assigned_to_id'] ?? $userId); $put('status_id', $attributes['status_id'] ?? $status->getKey()); $put('priority_id', $attributes['priority_id'] ?? $priority->getKey()); $put('reference', 'HD-'.now()->format('Y').'-'.str_pad((string) random_int(1, 9999), 4, '0', STR_PAD_LEFT)); $put('subject', 'Time log test ticket'); $put('title', 'Time log test ticket'); $put('body', '

Time log test ticket body.

'); $put('details', '

Time log test ticket body.

'); $put('description', '

Time log test ticket body.

'); $put('search_text', 'time log test ticket body'); $put('last_activity_at', now()); $unid = strtoupper(str_replace('-', '', (string) Str::uuid())); $put('guid', (string) Str::uuid()); $put('uuid', (string) Str::uuid()); $put('unid', $unid); $put('root_unid', $unid); $put('sync_sequence', 1); $put('source_system', 'phpunit'); foreach ($attributes as $column => $value) { $put((string) $column, $value); } return Ticket::query()->create($data); } }