190 lines
6.0 KiB
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();
|
|
});
|