351 lines
14 KiB
PHP
351 lines
14 KiB
PHP
<?php
|
|
|
|
use App\Models\Advance;
|
|
use App\Models\AdvanceType;
|
|
use App\Models\User;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Spatie\Permission\Models\Role;
|
|
|
|
beforeEach(function () {
|
|
Permission::firstOrCreate(['name' => 'zaliczki_access']);
|
|
});
|
|
|
|
function userWithAdvanceAccess(string $roleName = 'pracownik'): User
|
|
{
|
|
$user = User::factory()->create();
|
|
$role = Role::firstOrCreate(['name' => $roleName]);
|
|
$role->givePermissionTo('zaliczki_access');
|
|
$user->assignRole($role);
|
|
|
|
return $user;
|
|
}
|
|
|
|
test('employee sees only own advances', function () {
|
|
$employee = userWithAdvanceAccess();
|
|
$otherUser = User::factory()->create();
|
|
$type = AdvanceType::create(['name' => 'Paliwo']);
|
|
|
|
Advance::create(['date' => '2026-08-01', 'user_id' => $employee->id, 'amount' => 100, 'advance_type_id' => $type->id]);
|
|
Advance::create(['date' => '2026-08-02', 'user_id' => $otherUser->id, 'amount' => 200, 'advance_type_id' => $type->id]);
|
|
|
|
$response = $this->actingAs($employee)->get(route('zaliczki'));
|
|
|
|
$response->assertOk();
|
|
$response->assertSee('100,00');
|
|
$response->assertDontSee('200,00');
|
|
});
|
|
|
|
test('advance is stored for authenticated user', function () {
|
|
$employee = userWithAdvanceAccess();
|
|
$otherUser = User::factory()->create();
|
|
$type = AdvanceType::create(['name' => 'Hotel']);
|
|
|
|
$response = $this->actingAs($employee)->post(route('zaliczki.store'), [
|
|
'date' => '2026-08-28',
|
|
'user_id' => $otherUser->id,
|
|
'amount' => '250.50',
|
|
'advance_type_id' => $type->id,
|
|
]);
|
|
|
|
$response->assertRedirect(route('zaliczki'));
|
|
$this->assertDatabaseHas('advances', [
|
|
'user_id' => $employee->id,
|
|
'advance_type_id' => $type->id,
|
|
'amount' => -250.50,
|
|
]);
|
|
});
|
|
|
|
test('manager can create an advance for another user', function () {
|
|
$manager = userWithAdvanceAccess('kierownik');
|
|
$employee = User::factory()->create();
|
|
$type = AdvanceType::create(['name' => 'Wpłata']);
|
|
|
|
$response = $this->actingAs($manager)->post(route('zaliczki.store'), [
|
|
'date' => '2026-08-28',
|
|
'user_id' => $employee->id,
|
|
'amount' => '300.00',
|
|
'advance_type_id' => $type->id,
|
|
]);
|
|
|
|
$response->assertRedirect(route('zaliczki'));
|
|
$this->assertDatabaseHas('advances', [
|
|
'user_id' => $employee->id,
|
|
'advance_type_id' => $type->id,
|
|
'amount' => 300.00,
|
|
]);
|
|
});
|
|
|
|
test('manager can access system settings and add an advance type', function () {
|
|
Permission::firstOrCreate(['name' => 'users_access']);
|
|
|
|
$manager = User::factory()->create();
|
|
$managerRole = Role::firstOrCreate(['name' => 'kierownik']);
|
|
$managerRole->givePermissionTo(['zaliczki_access', 'users_access']);
|
|
$manager->assignRole($managerRole);
|
|
|
|
$indexResponse = $this->actingAs($manager)->get(route('settings.index'));
|
|
$indexResponse->assertOk();
|
|
|
|
$storeResponse = $this->actingAs($manager)->post(route('settings.advance-types.store'), [
|
|
'name' => 'Koncesja',
|
|
]);
|
|
|
|
$storeResponse->assertRedirect(route('settings.index'));
|
|
$this->assertDatabaseHas('advance_types', ['name' => 'Koncesja']);
|
|
});
|
|
|
|
test('manager can edit and delete an advance type from settings', function () {
|
|
Permission::firstOrCreate(['name' => 'users_access']);
|
|
|
|
$manager = User::factory()->create();
|
|
$managerRole = Role::firstOrCreate(['name' => 'kierownik']);
|
|
$managerRole->givePermissionTo(['zaliczki_access', 'users_access']);
|
|
$manager->assignRole($managerRole);
|
|
|
|
$type = AdvanceType::create(['name' => 'Koncesja']);
|
|
|
|
$editResponse = $this->actingAs($manager)->put(route('settings.advance-types.update', $type), [
|
|
'name' => 'Koncesja VIP',
|
|
]);
|
|
$editResponse->assertRedirect(route('settings.index'));
|
|
$this->assertDatabaseHas('advance_types', ['id' => $type->id, 'name' => 'Koncesja VIP']);
|
|
|
|
$deleteResponse = $this->actingAs($manager)->delete(route('settings.advance-types.destroy', $type));
|
|
$deleteResponse->assertRedirect(route('settings.index'));
|
|
$this->assertDatabaseMissing('advance_types', ['id' => $type->id]);
|
|
});
|
|
|
|
test('manager can update role permissions from settings', function () {
|
|
Permission::firstOrCreate(['name' => 'users_access']);
|
|
Permission::firstOrCreate(['name' => 'raporty_access']);
|
|
Permission::firstOrCreate(['name' => 'flota_access']);
|
|
|
|
$manager = User::factory()->create();
|
|
$managerRole = Role::firstOrCreate(['name' => 'kierownik']);
|
|
$managerRole->givePermissionTo('users_access');
|
|
$manager->assignRole($managerRole);
|
|
|
|
$response = $this->actingAs($manager)->post(route('settings.role-permissions.store'), [
|
|
'permissions' => [
|
|
$managerRole->id => ['users_access', 'raporty_access'],
|
|
],
|
|
]);
|
|
|
|
$response->assertRedirect(route('settings.index'));
|
|
$this->assertTrue($managerRole->fresh()->hasPermissionTo('raporty_access'));
|
|
$this->assertFalse($managerRole->fresh()->hasPermissionTo('flota_access'));
|
|
});
|
|
|
|
test('manager cannot delete an advance type that is still used in advances', function () {
|
|
Permission::firstOrCreate(['name' => 'users_access']);
|
|
|
|
$manager = User::factory()->create();
|
|
$managerRole = Role::firstOrCreate(['name' => 'kierownik']);
|
|
$managerRole->givePermissionTo(['zaliczki_access', 'users_access']);
|
|
$manager->assignRole($managerRole);
|
|
|
|
$type = AdvanceType::create(['name' => 'Paliwo']);
|
|
$employee = User::factory()->create();
|
|
Advance::create(['date' => '2026-08-28', 'user_id' => $employee->id, 'amount' => 100, 'advance_type_id' => $type->id]);
|
|
|
|
$response = $this->actingAs($manager)->from(route('settings.index'))->delete(route('settings.advance-types.destroy', $type));
|
|
|
|
$response->assertRedirect(route('settings.index'));
|
|
$response->assertSessionHas('error', 'Nie można usunąć rodzaju zaliczki, który jest już przypisany do istniejących zaliczek.');
|
|
$this->assertDatabaseHas('advance_types', ['id' => $type->id, 'name' => 'Paliwo']);
|
|
});
|
|
|
|
test('employee can edit own advance but cannot access another users advance', function () {
|
|
$employee = userWithAdvanceAccess();
|
|
$otherUser = User::factory()->create();
|
|
$type = AdvanceType::create(['name' => 'Hotel']);
|
|
$advance = Advance::create(['date' => '2026-08-28', 'user_id' => $employee->id, 'amount' => 100, 'advance_type_id' => $type->id]);
|
|
$otherAdvance = Advance::create(['date' => '2026-08-28', 'user_id' => $otherUser->id, 'amount' => 200, 'advance_type_id' => $type->id]);
|
|
|
|
$this->actingAs($employee)->get(route('zaliczki.edit', $otherAdvance))->assertForbidden();
|
|
|
|
$response = $this->actingAs($employee)->put(route('zaliczki.update', $advance), [
|
|
'date' => '2026-08-27',
|
|
'amount' => '150.00',
|
|
'advance_type_id' => $type->id,
|
|
]);
|
|
|
|
$response->assertRedirect(route('zaliczki'));
|
|
$this->assertDatabaseHas('advances', ['id' => $advance->id, 'amount' => -150, 'date' => '2026-08-27 00:00:00']);
|
|
});
|
|
|
|
test('manager can delete an advance', function () {
|
|
$manager = userWithAdvanceAccess('kierownik');
|
|
$employee = User::factory()->create();
|
|
$type = AdvanceType::create(['name' => 'Paliwo']);
|
|
$advance = Advance::create(['date' => '2026-08-28', 'user_id' => $employee->id, 'amount' => 100, 'advance_type_id' => $type->id]);
|
|
|
|
$response = $this->actingAs($manager)->delete(route('zaliczki.destroy', $advance));
|
|
|
|
$response->assertRedirect(route('zaliczki'));
|
|
$this->assertDatabaseMissing('advances', ['id' => $advance->id]);
|
|
});
|
|
|
|
test('expenses are negative and deposits are positive regardless of input sign', function () {
|
|
$employee = userWithAdvanceAccess();
|
|
$fuel = AdvanceType::create(['name' => 'Paliwo']);
|
|
$deposit = AdvanceType::create(['name' => 'Wpłata']);
|
|
|
|
Advance::create(['date' => '2026-08-28', 'user_id' => $employee->id, 'amount' => 100, 'advance_type_id' => $fuel->id]);
|
|
Advance::create(['date' => '2026-08-28', 'user_id' => $employee->id, 'amount' => -200, 'advance_type_id' => $deposit->id]);
|
|
|
|
$this->assertDatabaseHas('advances', ['advance_type_id' => $fuel->id, 'amount' => -100]);
|
|
$this->assertDatabaseHas('advances', ['advance_type_id' => $deposit->id, 'amount' => 200]);
|
|
});
|
|
|
|
test('manager can filter advances by text type and date range', function () {
|
|
$manager = userWithAdvanceAccess('kierownik');
|
|
$employee = User::factory()->create(['name' => 'Anna', 'surname' => 'Nowak']);
|
|
$fuel = AdvanceType::create(['name' => 'Paliwo']);
|
|
$hotel = AdvanceType::create(['name' => 'Hotel']);
|
|
|
|
Advance::create(['date' => '2026-08-10', 'user_id' => $employee->id, 'amount' => 100, 'advance_type_id' => $fuel->id]);
|
|
Advance::create(['date' => '2026-08-20', 'user_id' => $employee->id, 'amount' => 200, 'advance_type_id' => $hotel->id]);
|
|
|
|
$response = $this->actingAs($manager)->get(route('zaliczki', [
|
|
'search' => 'Anna',
|
|
'type' => $fuel->id,
|
|
'date_from' => '2026-08-01',
|
|
'date_to' => '2026-08-15',
|
|
]));
|
|
|
|
$response->assertOk();
|
|
$response->assertSee('100,00');
|
|
$response->assertDontSee('200,00');
|
|
});
|
|
|
|
test('manager can open employee profile and see current advance balance', function () {
|
|
Permission::firstOrCreate(['name' => 'users_access']);
|
|
|
|
$manager = User::factory()->create();
|
|
$managerRole = Role::firstOrCreate(['name' => 'kierownik']);
|
|
$managerRole->givePermissionTo(['zaliczki_access', 'users_access']);
|
|
$manager->assignRole($managerRole);
|
|
|
|
$employee = User::factory()->create(['name' => 'Jan', 'surname' => 'Kowalski']);
|
|
$fuel = AdvanceType::create(['name' => 'Paliwo']);
|
|
$deposit = AdvanceType::create(['name' => 'Wpłata']);
|
|
|
|
Advance::create(['date' => '2026-08-10', 'user_id' => $employee->id, 'amount' => 120, 'advance_type_id' => $fuel->id]);
|
|
Advance::create(['date' => '2026-08-11', 'user_id' => $employee->id, 'amount' => 500, 'advance_type_id' => $deposit->id]);
|
|
|
|
$response = $this->actingAs($manager)->get(route('users.show', $employee));
|
|
|
|
$response->assertOk();
|
|
$response->assertSee('Jan Kowalski');
|
|
$response->assertSee('380,00');
|
|
});
|
|
|
|
test('advance balance is recalculated after create update and delete', function () {
|
|
$employee = userWithAdvanceAccess();
|
|
$fuel = AdvanceType::create(['name' => 'Paliwo']);
|
|
|
|
$advance = Advance::create(['date' => '2026-08-10', 'user_id' => $employee->id, 'amount' => 120, 'advance_type_id' => $fuel->id]);
|
|
|
|
$this->assertDatabaseHas('user_advance_balances', [
|
|
'user_id' => $employee->id,
|
|
'balance' => -120,
|
|
]);
|
|
|
|
$advance->update(['amount' => 300]);
|
|
|
|
$this->assertDatabaseHas('user_advance_balances', [
|
|
'user_id' => $employee->id,
|
|
'balance' => -300,
|
|
]);
|
|
|
|
$advance->delete();
|
|
|
|
$this->assertDatabaseHas('user_advance_balances', [
|
|
'user_id' => $employee->id,
|
|
'balance' => 0,
|
|
]);
|
|
});
|
|
|
|
test('dashboard shows the lowest advance balances for employees', function () {
|
|
$manager = userWithAdvanceAccess('kierownik');
|
|
$fuel = AdvanceType::create(['name' => 'Paliwo']);
|
|
Role::firstOrCreate(['name' => 'pracownik']);
|
|
|
|
$worstEmployee = User::factory()->create(['name' => 'Anna', 'surname' => 'Najgorsza']);
|
|
$worstEmployee->assignRole('pracownik');
|
|
$betterEmployee = User::factory()->create(['name' => 'Piotr', 'surname' => 'Lepszy']);
|
|
$betterEmployee->assignRole('pracownik');
|
|
|
|
Advance::create(['date' => '2026-08-10', 'user_id' => $worstEmployee->id, 'amount' => 200, 'advance_type_id' => $fuel->id]);
|
|
Advance::create(['date' => '2026-08-11', 'user_id' => $betterEmployee->id, 'amount' => 50, 'advance_type_id' => $fuel->id]);
|
|
|
|
$response = $this->actingAs($manager)->get(route('dashboard'));
|
|
|
|
$response->assertOk();
|
|
$response->assertSee('Najniższy bilans zaliczek');
|
|
$response->assertSee('Anna Najgorsza');
|
|
$response->assertSee('-200,00');
|
|
});
|
|
|
|
test('dashboard prioritizes negative balances over zero balances', function () {
|
|
$manager = userWithAdvanceAccess('kierownik');
|
|
$fuel = AdvanceType::create(['name' => 'Paliwo']);
|
|
Role::firstOrCreate(['name' => 'pracownik']);
|
|
|
|
$negativeEmployee = User::factory()->create(['name' => 'Kasia', 'surname' => 'Minus']);
|
|
$negativeEmployee->assignRole('pracownik');
|
|
$zeroEmployee = User::factory()->create(['name' => 'Marek', 'surname' => 'Zero']);
|
|
$zeroEmployee->assignRole('pracownik');
|
|
|
|
Advance::create(['date' => '2026-08-01', 'user_id' => $negativeEmployee->id, 'amount' => 100, 'advance_type_id' => $fuel->id]);
|
|
Advance::create(['date' => '2026-08-02', 'user_id' => $zeroEmployee->id, 'amount' => 0, 'advance_type_id' => $fuel->id]);
|
|
|
|
$response = $this->actingAs($manager)->get(route('dashboard'));
|
|
|
|
$response->assertOk();
|
|
$response->assertSeeInOrder(['Kasia Minus']);
|
|
$response->assertDontSee('Marek Zero');
|
|
});
|
|
|
|
test('dashboard hides employees with zero or positive balance from the negative ledger', function () {
|
|
$manager = userWithAdvanceAccess('kierownik');
|
|
$fuel = AdvanceType::create(['name' => 'Paliwo']);
|
|
$deposit = AdvanceType::create(['name' => 'Wpłata']);
|
|
Role::firstOrCreate(['name' => 'pracownik']);
|
|
|
|
$negativeEmployee = User::factory()->create(['name' => 'Kasia', 'surname' => 'Minus']);
|
|
$negativeEmployee->assignRole('pracownik');
|
|
$zeroEmployee = User::factory()->create(['name' => 'Marek', 'surname' => 'Zero']);
|
|
$zeroEmployee->assignRole('pracownik');
|
|
$positiveEmployee = User::factory()->create(['name' => 'Ola', 'surname' => 'Plus']);
|
|
$positiveEmployee->assignRole('pracownik');
|
|
|
|
Advance::create(['date' => '2026-08-01', 'user_id' => $negativeEmployee->id, 'amount' => 100, 'advance_type_id' => $fuel->id]);
|
|
Advance::create(['date' => '2026-08-02', 'user_id' => $zeroEmployee->id, 'amount' => 0, 'advance_type_id' => $fuel->id]);
|
|
Advance::create(['date' => '2026-08-03', 'user_id' => $positiveEmployee->id, 'amount' => 50, 'advance_type_id' => $deposit->id]);
|
|
|
|
$response = $this->actingAs($manager)->get(route('dashboard'));
|
|
|
|
$response->assertOk();
|
|
$response->assertSee('Kasia Minus');
|
|
$response->assertDontSee('Marek Zero');
|
|
$response->assertDontSee('Ola Plus');
|
|
});
|
|
|
|
test('dashboard shows negative balances for users regardless of role', function () {
|
|
$manager = userWithAdvanceAccess('kierownik');
|
|
$fuel = AdvanceType::create(['name' => 'Paliwo']);
|
|
|
|
$user = User::factory()->create(['name' => 'Zbyszek', 'surname' => 'Minus']);
|
|
$user->syncRoles([]);
|
|
|
|
Advance::create(['date' => '2026-08-10', 'user_id' => $user->id, 'amount' => 150, 'advance_type_id' => $fuel->id]);
|
|
|
|
$response = $this->actingAs($manager)->get(route('dashboard'));
|
|
|
|
$response->assertOk();
|
|
$response->assertSee('Zbyszek Minus');
|
|
$response->assertSee('-150,00');
|
|
});
|