parfum/tests/Feature/Studio/Finance/PayrollTest.php

190 lines
6.0 KiB
PHP

<?php
use App\Enums\IsPaid;
use App\Enums\SalaryAdjustmentType;
use App\Livewire\Studio\Finance\Payroll;
use App\Models\Employee;
use App\Models\Payroll as PayrollModel;
use App\Models\PayrollAdjustment;
use App\Models\User;
use Carbon\Carbon;
use Livewire\Livewire;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
beforeEach(function () {
$this->setupUser();
$role = Role::firstOrCreate(['name' => 'Owner']);
Permission::firstOrCreate(['name' => 'view payroll']);
Permission::firstOrCreate(['name' => 'manage adjustment']);
$role->givePermissionTo(['view payroll', 'manage adjustment']);
$this->user->assignRole($role);
});
it('renders the payroll page correctly', function () {
PayrollModel::factory()->create([
'user_id' => $this->user->id,
'period_month' => Carbon::now()->format('Y-m'),
'is_paid' => \App\Enums\IsPaid::NOT_PAID,
]);
$this->actingAs($this->user)
->get(route('studio.finance.payroll.index'))
->assertOk()
->assertSeeLivewire(Payroll::class);
});
it('can open modal for adjustment', function () {
Livewire::actingAs($this->user)
->test(Payroll::class)
->call('openModal', 'create', 'Tambah Penyesuaian')
->assertSet('method', 'create')
->assertSet('modalTitle', 'Tambah Penyesuaian');
});
it('shows validation errors on adjustment form', function () {
Livewire::actingAs($this->user)
->test(Payroll::class)
->call('create')
->assertHasErrors([
'form.user_ids' => 'required',
'form.type' => 'required',
'form.amount' => 'required',
'form.description' => 'required',
]);
});
it('can add a bonus adjustment', function () {
$employeeUser = User::factory()->active()->create();
Employee::factory()->create(['user_id' => $employeeUser->id, 'base_salary' => 5000000]);
// Create payroll for the current month
$payroll = PayrollModel::factory()->create([
'user_id' => $employeeUser->id,
'period_month' => Carbon::now()->format('Y-m'),
'base_salary' => 5000000,
'bonus' => 0,
'deduction' => 0,
'total_salary' => 5000000,
]);
Livewire::actingAs($this->user)
->test(Payroll::class)
->set('form.user_ids', [$employeeUser->id])
->set('form.type', SalaryAdjustmentType::BONUS->value)
->set('form.amount', '500000')
->set('form.description', 'Bonus Performance')
->call('create')
->assertHasNoErrors()
->assertDispatched('refreshDatatable');
$payroll->refresh();
expect($payroll->bonus)->toBe(500000);
expect($payroll->total_salary)->toBe(5500000);
$this->assertDatabaseHas('payroll_adjustments', [
'payroll_id' => $payroll->id,
'type' => SalaryAdjustmentType::BONUS->value,
'amount' => 500000,
'description' => 'Bonus Performance',
]);
});
it('can add a deduction adjustment', function () {
$employeeUser = User::factory()->active()->create();
Employee::factory()->create(['user_id' => $employeeUser->id, 'base_salary' => 5000000]);
// Create payroll for the current month
$payroll = PayrollModel::factory()->create([
'user_id' => $employeeUser->id,
'period_month' => Carbon::now()->format('Y-m'),
'base_salary' => 5000000,
'bonus' => 0,
'deduction' => 0,
'total_salary' => 5000000,
]);
Livewire::actingAs($this->user)
->test(Payroll::class)
->set('form.user_ids', [$employeeUser->id])
->set('form.type', SalaryAdjustmentType::DEDUCTION->value)
->set('form.amount', '200000')
->set('form.description', 'Potongan Keterlambatan')
->call('create')
->assertHasNoErrors()
->assertDispatched('refreshDatatable');
$payroll->refresh();
expect($payroll->deduction)->toBe(200000);
expect($payroll->total_salary)->toBe(4800000);
});
it('can delete an adjustment', function () {
$employeeUser = User::factory()->active()->create();
Employee::factory()->create(['user_id' => $employeeUser->id, 'base_salary' => 5000000]);
$payroll = PayrollModel::factory()->create([
'user_id' => $employeeUser->id,
'period_month' => Carbon::now()->format('Y-m'),
'base_salary' => 5000000,
'bonus' => 500000,
'deduction' => 0,
'total_salary' => 5500000,
]);
$adjustment = PayrollAdjustment::factory()->create([
'payroll_id' => $payroll->id,
'type' => SalaryAdjustmentType::BONUS,
'amount' => 500000,
]);
Livewire::actingAs($this->user)
->test(Payroll::class)
->call('delete', $adjustment->id)
->assertHasNoErrors()
->assertDispatched('refreshDatatable');
$payroll->refresh();
expect($payroll->bonus)->toBe(0);
expect($payroll->total_salary)->toBe(5000000);
$this->assertSoftDeleted('payroll_adjustments', ['id' => $adjustment->id]);
});
it('can export payroll as pdf', function () {
$employeeUser = User::factory()->active()->create();
Employee::factory()->create(['user_id' => $employeeUser->id, 'base_salary' => 5000000]);
$payroll = PayrollModel::factory()->create([
'user_id' => $employeeUser->id,
'period_month' => Carbon::now()->format('Y-m'),
'base_salary' => 5000000,
'is_paid' => IsPaid::NOT_PAID,
]);
Livewire::actingAs($this->user)
->test(Payroll::class)
->call('exportPdf', $payroll)
->assertFileDownloaded();
});
it('cannot manage adjustment without permission', function () {
$this->user->roles()->detach();
$this->user->permissions()->detach();
Livewire::actingAs($this->user)
->test(Payroll::class)
->call('create')
->assertForbidden();
});
it('cannot access payroll page without permission', function () {
$this->user->roles()->detach();
$this->user->permissions()->detach();
$this->actingAs($this->user)
->get(route('studio.finance.payroll.index'))
->assertForbidden();
});