- Updated CustomerService to simplify getAll method. - Refactored ProductService to utilize HasRoleChecks trait and improved role verification logic. - Enhanced ProductVariantService with new methods for fetching data for restocking and transactions. - Cleaned up RawMaterialService by removing unused methods and improving data retrieval. - Adjusted SupplierService to streamline getAll method. - Refactored RoleService to use Spatie's Role model and improved role filtering logic. - Updated NotificationService to handle role labels more effectively. - Improved StockMutationService by removing redundant paginated method. - Cleaned up various frontend components to directly accept necessary props instead of nested data objects. - Updated tests to reflect changes in service method names and ensure proper notification handling.
889 lines
28 KiB
PHP
889 lines
28 KiB
PHP
<?php
|
|
|
|
use App\Models\Attendance;
|
|
use App\Models\CashAccount;
|
|
use App\Models\Employee;
|
|
use App\Models\Expense;
|
|
use App\Models\Payroll;
|
|
use App\Models\PayrollPeriod;
|
|
use App\Models\Product;
|
|
use App\Models\User;
|
|
use App\Notifications\WebPushNotification;
|
|
use App\Services\Admin\Finance\Cash\CashTransactionService;
|
|
use App\Services\Admin\Finance\EmployeeAdvanceService;
|
|
use App\Services\Admin\Finance\ExpenseService;
|
|
use App\Services\Admin\Finance\Payroll\PayrollPeriodService;
|
|
use App\Services\Admin\HR\AttendanceService;
|
|
use App\Services\Admin\HR\LeaveRequestService;
|
|
use App\Services\Admin\Master\Product\ProductService;
|
|
use App\Services\NotificationService;
|
|
use Database\Seeders\RolePermissionSeeder;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Notification;
|
|
use Spatie\Permission\PermissionRegistrar;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
app()[PermissionRegistrar::class]->forgetCachedPermissions();
|
|
$this->seed(RolePermissionSeeder::class);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| HELPERS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
function notifUserWithRole(string $role, bool $active = true): User
|
|
{
|
|
$user = User::factory()->create(['is_active' => $active]);
|
|
$user->assignRole($role);
|
|
|
|
return $user;
|
|
}
|
|
|
|
function notifEmployeeWithRole(string $role = 'Kasir'): array
|
|
{
|
|
$user = notifUserWithRole($role);
|
|
$employee = Employee::factory()->create(['user_id' => $user->id]);
|
|
|
|
return ['user' => $user, 'employee' => $employee];
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| NOTIFICATION SERVICE — UNIT TESTS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('NotificationService creates in-app notification for users with matching role', function () {
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
notifUserWithRole('Kasir'); // should NOT receive
|
|
|
|
NotificationService::notify(
|
|
roles: ['Owner', 'Developer'],
|
|
title: 'Test Title',
|
|
body: 'Test Body.',
|
|
url: '/test-url'
|
|
);
|
|
|
|
expect($developer->notifications()->count())->toBe(1);
|
|
expect($owner->notifications()->count())->toBe(1);
|
|
|
|
$notification = $developer->notifications()->first();
|
|
expect($notification->title)->toBe('Test Title')
|
|
->and($notification->body)->toBe('Test Body.')
|
|
->and($notification->url)->toBe('/test-url')
|
|
->and($notification->is_read)->toBeFalse();
|
|
});
|
|
|
|
test('NotificationService does not notify inactive users', function () {
|
|
notifUserWithRole('Developer', active: false);
|
|
$active = notifUserWithRole('Developer');
|
|
|
|
NotificationService::notify(
|
|
roles: ['Developer'],
|
|
title: 'Test',
|
|
body: 'Body.',
|
|
url: '/test'
|
|
);
|
|
|
|
expect($active->notifications()->count())->toBe(1);
|
|
expect(User::where('is_active', false)->first()->notifications()->count())->toBe(0);
|
|
});
|
|
|
|
test('NotificationService dispatches WebPushNotification to each user', function () {
|
|
Notification::fake();
|
|
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
|
|
NotificationService::notify(
|
|
roles: ['Developer', 'Owner'],
|
|
title: 'Push Title',
|
|
body: 'Push Body.',
|
|
url: '/push'
|
|
);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
});
|
|
|
|
test('NotificationService includes additionalUser when not already in role-based list', function () {
|
|
$kasir = notifUserWithRole('Kasir');
|
|
$developer = notifUserWithRole('Developer');
|
|
|
|
NotificationService::notify(
|
|
roles: ['Developer'],
|
|
title: 'Title',
|
|
body: 'Body.',
|
|
url: '/url',
|
|
additionalUser: $kasir
|
|
);
|
|
|
|
expect($kasir->notifications()->count())->toBe(1);
|
|
expect($developer->notifications()->count())->toBe(1);
|
|
});
|
|
|
|
test('NotificationService does not duplicate additionalUser already in role list', function () {
|
|
$developer = notifUserWithRole('Developer');
|
|
|
|
NotificationService::notify(
|
|
roles: ['Developer'],
|
|
title: 'Title',
|
|
body: 'Body.',
|
|
url: '/url',
|
|
additionalUser: $developer
|
|
);
|
|
|
|
expect($developer->notifications()->count())->toBe(1);
|
|
});
|
|
|
|
test('NotificationService handles null additionalUser', function () {
|
|
$developer = notifUserWithRole('Developer');
|
|
|
|
NotificationService::notify(
|
|
roles: ['Developer'],
|
|
title: 'Title',
|
|
body: 'Body.',
|
|
url: '/url',
|
|
additionalUser: null
|
|
);
|
|
|
|
expect($developer->notifications()->count())->toBe(1);
|
|
});
|
|
|
|
test('NotificationService notifies multiple users across multiple roles', function () {
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
$direktur = notifUserWithRole('Direktur');
|
|
$adminToko = notifUserWithRole('Admin Toko');
|
|
notifUserWithRole('Kasir'); // should NOT receive
|
|
|
|
NotificationService::notify(
|
|
roles: ['Owner', 'Developer', 'Direktur', 'Admin Toko'],
|
|
title: 'Multi Role',
|
|
body: 'Body.',
|
|
url: '/multi'
|
|
);
|
|
|
|
expect($developer->notifications()->count())->toBe(1);
|
|
expect($owner->notifications()->count())->toBe(1);
|
|
expect($direktur->notifications()->count())->toBe(1);
|
|
expect($adminToko->notifications()->count())->toBe(1);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| PRODUCT NOTIFICATIONS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('ProductService create sends notification to correct roles', function () {
|
|
Notification::fake();
|
|
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
$kasir = notifUserWithRole('Kasir');
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new ProductService;
|
|
$product = $service->create([
|
|
'name' => 'Test Product',
|
|
'description' => 'A test product',
|
|
'status' => 'active',
|
|
'category_ids' => [],
|
|
'use_same_price' => false,
|
|
'variants' => [
|
|
[
|
|
'name' => 'Default',
|
|
'stock' => 10,
|
|
'reject_stock' => 0,
|
|
'retail_stock' => 5,
|
|
'prices' => [
|
|
['type' => 'retail', 'price' => 50000],
|
|
],
|
|
],
|
|
],
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
Notification::assertNothingSentTo($kasir);
|
|
|
|
expect($developer->notifications()->count())->toBe(1);
|
|
expect($developer->notifications()->first()->title)->toBe('Produk Baru');
|
|
});
|
|
|
|
test('ProductService update sends notification to correct roles', function () {
|
|
Notification::fake();
|
|
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
$adminToko = notifUserWithRole('Admin Toko');
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new ProductService;
|
|
$product = $service->create([
|
|
'name' => 'Original Product',
|
|
'description' => 'Desc',
|
|
'status' => 'active',
|
|
'category_ids' => [],
|
|
'use_same_price' => false,
|
|
'variants' => [
|
|
[
|
|
'name' => 'Var 1',
|
|
'stock' => 10,
|
|
'reject_stock' => 0,
|
|
'retail_stock' => 5,
|
|
'prices' => [
|
|
['type' => 'retail', 'price' => 50000],
|
|
],
|
|
],
|
|
],
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
|
|
Notification::fake();
|
|
|
|
$product = $service->update($product, [
|
|
'name' => 'Updated Product',
|
|
'description' => 'Desc updated',
|
|
'status' => 'active',
|
|
'category_ids' => [],
|
|
'use_same_price' => false,
|
|
'variants' => [
|
|
[
|
|
'id' => $product->productVariants->first()->id,
|
|
'name' => 'Var 1',
|
|
'stock' => 20,
|
|
'reject_stock' => 0,
|
|
'retail_stock' => 10,
|
|
'prices' => [
|
|
['type' => 'retail', 'price' => 60000],
|
|
],
|
|
],
|
|
],
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
Notification::assertSentTo($adminToko, WebPushNotification::class);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| CASH ACCOUNT NOTIFICATIONS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('CashTransactionService deposit sends notification to correct roles', function () {
|
|
Notification::fake();
|
|
|
|
$cashAccount = CashAccount::factory()->create(['balance' => 1000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
$kasir = notifUserWithRole('Kasir');
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new CashTransactionService;
|
|
$service->deposit([
|
|
'amount' => 500000,
|
|
'description' => 'Setoran modal',
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
Notification::assertNothingSentTo($kasir);
|
|
|
|
expect($developer->notifications()->first()->title)->toBe('Setoran Kas Toko');
|
|
});
|
|
|
|
test('CashTransactionService withdrawal sends notification to correct roles', function () {
|
|
Notification::fake();
|
|
|
|
$cashAccount = CashAccount::factory()->create(['balance' => 1000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$direktur = notifUserWithRole('Direktur');
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new CashTransactionService;
|
|
$service->withdrawal([
|
|
'amount' => 200000,
|
|
'description' => 'Penarikan kas',
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($direktur, WebPushNotification::class);
|
|
|
|
expect($developer->notifications()->first()->title)->toBe('Penarikan Kas Toko');
|
|
});
|
|
|
|
test('CashTransactionService update sends notification to correct roles', function () {
|
|
Notification::fake();
|
|
|
|
$cashAccount = CashAccount::factory()->create(['balance' => 1000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new CashTransactionService;
|
|
$transaction = $service->deposit([
|
|
'amount' => 500000,
|
|
'description' => 'Initial deposit',
|
|
]);
|
|
|
|
Notification::fake();
|
|
|
|
$service->update($transaction, [
|
|
'amount' => 600000,
|
|
'description' => 'Updated deposit',
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
|
|
expect($developer->notifications()->where('title', 'Transaksi Kas Diperbarui')->count())->toBe(1);
|
|
});
|
|
|
|
test('CashTransactionService destroy sends notification to correct roles', function () {
|
|
Notification::fake();
|
|
|
|
$cashAccount = CashAccount::factory()->create(['balance' => 1000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new CashTransactionService;
|
|
$transaction = $service->deposit([
|
|
'amount' => 500000,
|
|
'description' => 'To be deleted',
|
|
]);
|
|
|
|
Notification::fake();
|
|
|
|
$service->destroy($transaction);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
|
|
expect($developer->notifications()->where('title', 'Transaksi Kas Dihapus')->count())->toBe(1);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| EXPENSE NOTIFICATIONS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('ExpenseService create sends notification to correct roles', function () {
|
|
Notification::fake();
|
|
|
|
CashAccount::factory()->create(['balance' => 5000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
$kasir = notifUserWithRole('Kasir');
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new ExpenseService;
|
|
$expense = $service->create([
|
|
'amount' => 100000,
|
|
'description' => 'Office supplies',
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
Notification::assertNothingSentTo($kasir);
|
|
|
|
expect($developer->notifications()->first()->title)->toBe('Pengeluaran Baru');
|
|
});
|
|
|
|
test('ExpenseService update sends notification to correct roles', function () {
|
|
Notification::fake();
|
|
|
|
CashAccount::factory()->create(['balance' => 5000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$adminToko = notifUserWithRole('Admin Toko');
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new ExpenseService;
|
|
$expense = $service->create([
|
|
'amount' => 100000,
|
|
'description' => 'Original',
|
|
]);
|
|
|
|
Notification::fake();
|
|
|
|
$service->update($expense, [
|
|
'amount' => 150000,
|
|
'description' => 'Updated expense',
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($adminToko, WebPushNotification::class);
|
|
|
|
expect($developer->notifications()->where('title', 'Pengeluaran Diperbarui')->count())->toBe(1);
|
|
});
|
|
|
|
test('ExpenseService delete sends notification to correct roles', function () {
|
|
Notification::fake();
|
|
|
|
CashAccount::factory()->create(['balance' => 5000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$direktur = notifUserWithRole('Direktur');
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new ExpenseService;
|
|
$expense = $service->create([
|
|
'amount' => 100000,
|
|
'description' => 'To delete',
|
|
]);
|
|
|
|
Notification::fake();
|
|
|
|
$service->delete($expense);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($direktur, WebPushNotification::class);
|
|
|
|
expect($developer->notifications()->where('title', 'Pengeluaran Dihapus')->count())->toBe(1);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| EMPLOYEE ADVANCE (KASBON) NOTIFICATIONS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('EmployeeAdvanceService create sends notification including the requesting employee', function () {
|
|
Notification::fake();
|
|
|
|
CashAccount::factory()->create(['balance' => 5000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
$kasbonData = notifEmployeeWithRole('Kasir');
|
|
$employee = $kasbonData['employee'];
|
|
$kasbonUser = $kasbonData['user'];
|
|
|
|
$this->actingAs($kasbonUser);
|
|
|
|
$service = new EmployeeAdvanceService;
|
|
$advance = $service->create([
|
|
'amount' => 500000,
|
|
'description' => 'Emergency need',
|
|
'due_date' => now()->addDays(30)->toDateString(),
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
Notification::assertSentTo($kasbonUser, WebPushNotification::class);
|
|
|
|
expect($kasbonUser->notifications()->first()->title)->toBe('Kasbon Baru');
|
|
});
|
|
|
|
test('EmployeeAdvanceService approve sends notification including the employee', function () {
|
|
Notification::fake();
|
|
|
|
CashAccount::factory()->create(['balance' => 5000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$kasbonData = notifEmployeeWithRole('Kasir');
|
|
$employee = $kasbonData['employee'];
|
|
$kasbonUser = $kasbonData['user'];
|
|
|
|
$this->actingAs($kasbonUser);
|
|
|
|
$service = new EmployeeAdvanceService;
|
|
$advance = $service->create([
|
|
'amount' => 300000,
|
|
'description' => 'Advance',
|
|
'due_date' => now()->addDays(14)->toDateString(),
|
|
]);
|
|
|
|
Notification::fake();
|
|
|
|
$admin = notifUserWithRole('Admin Toko');
|
|
$this->actingAs($admin);
|
|
|
|
$service->approve($advance);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($kasbonUser, WebPushNotification::class);
|
|
|
|
expect($kasbonUser->notifications()->where('title', 'Kasbon Disetujui')->count())->toBe(1);
|
|
});
|
|
|
|
test('EmployeeAdvanceService pay sends notification including the employee', function () {
|
|
Notification::fake();
|
|
|
|
CashAccount::factory()->create(['balance' => 5000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$kasbonData = notifEmployeeWithRole('Kasir');
|
|
$employee = $kasbonData['employee'];
|
|
$kasbonUser = $kasbonData['user'];
|
|
|
|
$this->actingAs($kasbonUser);
|
|
|
|
$service = new EmployeeAdvanceService;
|
|
$advance = $service->create([
|
|
'amount' => 200000,
|
|
'description' => 'To pay',
|
|
'due_date' => now()->addDays(7)->toDateString(),
|
|
]);
|
|
|
|
$admin = notifUserWithRole('Admin Toko');
|
|
$this->actingAs($admin);
|
|
|
|
$service->approve($advance);
|
|
|
|
Notification::fake();
|
|
|
|
$service->pay($advance);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($kasbonUser, WebPushNotification::class);
|
|
|
|
expect($kasbonUser->notifications()->where('title', 'Kasbon Dibayar')->count())->toBe(1);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| PAYROLL NOTIFICATIONS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('PayrollPeriodService pay sends notification including the employee', function () {
|
|
Notification::fake();
|
|
|
|
CashAccount::factory()->create(['balance' => 50000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
$employeeData = notifEmployeeWithRole('Kasir');
|
|
$employee = $employeeData['employee'];
|
|
$employeeUser = $employeeData['user'];
|
|
|
|
$period = PayrollPeriod::factory()->create(['year' => 2026, 'month' => 7, 'status' => 'open']);
|
|
$payroll = Payroll::factory()->create([
|
|
'payroll_period_id' => $period->id,
|
|
'employee_id' => $employee->id,
|
|
'base_salary' => 3000000,
|
|
'bonus_amount' => 0,
|
|
'deduction_amount' => 0,
|
|
'total_amount' => 3000000,
|
|
'status' => 'unpaid',
|
|
]);
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new PayrollPeriodService;
|
|
$service->pay($payroll);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
Notification::assertSentTo($employeeUser, WebPushNotification::class);
|
|
|
|
expect($employeeUser->notifications()->where('title', 'Gaji Dibayar')->count())->toBe(1);
|
|
});
|
|
|
|
test('PayrollPeriodService cancel sends notification including the employee', function () {
|
|
Notification::fake();
|
|
|
|
$developer = notifUserWithRole('Developer');
|
|
$direktur = notifUserWithRole('Direktur');
|
|
$employeeData = notifEmployeeWithRole('Kasir');
|
|
$employee = $employeeData['employee'];
|
|
$employeeUser = $employeeData['user'];
|
|
|
|
$period = PayrollPeriod::factory()->create(['year' => 2026, 'month' => 8, 'status' => 'open']);
|
|
$payroll = Payroll::factory()->create([
|
|
'payroll_period_id' => $period->id,
|
|
'employee_id' => $employee->id,
|
|
'base_salary' => 3000000,
|
|
'bonus_amount' => 0,
|
|
'deduction_amount' => 0,
|
|
'total_amount' => 3000000,
|
|
'status' => 'unpaid',
|
|
]);
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new PayrollPeriodService;
|
|
$service->cancel($payroll);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($direktur, WebPushNotification::class);
|
|
Notification::assertSentTo($employeeUser, WebPushNotification::class);
|
|
|
|
expect($employeeUser->notifications()->where('title', 'Gaji Dibatalkan')->count())->toBe(1);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| LEAVE REQUEST NOTIFICATIONS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('LeaveRequestService create sends notification including the requesting employee', function () {
|
|
Notification::fake();
|
|
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
$leaveData = notifEmployeeWithRole('Kasir');
|
|
$employee = $leaveData['employee'];
|
|
$leaveUser = $leaveData['user'];
|
|
|
|
$this->actingAs($leaveUser);
|
|
|
|
$service = new LeaveRequestService;
|
|
$leaveRequest = $service->create([
|
|
'start_date' => now()->addDays(5)->toDateString(),
|
|
'end_date' => now()->addDays(7)->toDateString(),
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
Notification::assertSentTo($leaveUser, WebPushNotification::class);
|
|
|
|
expect($leaveUser->notifications()->first()->title)->toBe('Pengajuan Cuti Baru');
|
|
});
|
|
|
|
test('LeaveRequestService approve sends notification including the employee', function () {
|
|
Notification::fake();
|
|
|
|
$developer = notifUserWithRole('Developer');
|
|
$leaveData = notifEmployeeWithRole('Kasir');
|
|
$employee = $leaveData['employee'];
|
|
$leaveUser = $leaveData['user'];
|
|
|
|
$this->actingAs($leaveUser);
|
|
|
|
$service = new LeaveRequestService;
|
|
$leaveRequest = $service->create([
|
|
'start_date' => now()->addDays(10)->toDateString(),
|
|
'end_date' => now()->addDays(12)->toDateString(),
|
|
]);
|
|
|
|
Notification::fake();
|
|
|
|
$admin = notifUserWithRole('Admin Toko');
|
|
$this->actingAs($admin);
|
|
|
|
$service->approve($leaveRequest);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($leaveUser, WebPushNotification::class);
|
|
|
|
expect($leaveUser->notifications()->where('title', 'Cuti Disetujui')->count())->toBe(1);
|
|
});
|
|
|
|
test('LeaveRequestService reject sends notification including the employee', function () {
|
|
Notification::fake();
|
|
|
|
$developer = notifUserWithRole('Developer');
|
|
$leaveData = notifEmployeeWithRole('Kasir');
|
|
$employee = $leaveData['employee'];
|
|
$leaveUser = $leaveData['user'];
|
|
|
|
$this->actingAs($leaveUser);
|
|
|
|
$service = new LeaveRequestService;
|
|
$leaveRequest = $service->create([
|
|
'start_date' => now()->addDays(15)->toDateString(),
|
|
'end_date' => now()->addDays(17)->toDateString(),
|
|
]);
|
|
|
|
Notification::fake();
|
|
|
|
$admin = notifUserWithRole('Admin Toko');
|
|
$this->actingAs($admin);
|
|
|
|
$service->reject($leaveRequest);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($leaveUser, WebPushNotification::class);
|
|
|
|
expect($leaveUser->notifications()->where('title', 'Cuti Ditolak')->count())->toBe(1);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| ATTENDANCE NOTIFICATIONS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('AttendanceService checkIn sends notification to Developer, Owner, Direktur', function () {
|
|
Notification::fake();
|
|
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
$direktur = notifUserWithRole('Direktur');
|
|
$adminToko = notifUserWithRole('Admin Toko');
|
|
|
|
$attData = notifEmployeeWithRole('Kasir');
|
|
$employee = $attData['employee'];
|
|
$attendant = $attData['user'];
|
|
|
|
$this->actingAs($attendant);
|
|
|
|
$service = new AttendanceService;
|
|
$attendance = $service->checkIn([
|
|
'latitude' => -6.200000,
|
|
'longitude' => 106.816666,
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
Notification::assertSentTo($direktur, WebPushNotification::class);
|
|
Notification::assertNothingSentTo($adminToko);
|
|
|
|
expect($developer->notifications()->first()->title)->toBe('Presensi Masuk');
|
|
});
|
|
|
|
test('AttendanceService checkOut sends notification to Developer, Owner, Direktur', function () {
|
|
Notification::fake();
|
|
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
$direktur = notifUserWithRole('Direktur');
|
|
$adminToko = notifUserWithRole('Admin Toko');
|
|
|
|
$attData = notifEmployeeWithRole('Kasir');
|
|
$employee = $attData['employee'];
|
|
$attendant = $attData['user'];
|
|
|
|
$this->actingAs($attendant);
|
|
|
|
$service = new AttendanceService;
|
|
$attendance = $service->checkIn([
|
|
'latitude' => -6.200000,
|
|
'longitude' => 106.816666,
|
|
]);
|
|
|
|
Notification::fake();
|
|
|
|
$attendance = $service->checkOut($attendance, [
|
|
'latitude' => -6.200100,
|
|
'longitude' => 106.816700,
|
|
]);
|
|
|
|
Notification::assertSentTo($developer, WebPushNotification::class);
|
|
Notification::assertSentTo($owner, WebPushNotification::class);
|
|
Notification::assertSentTo($direktur, WebPushNotification::class);
|
|
Notification::assertNothingSentTo($adminToko);
|
|
|
|
expect($developer->notifications()->where('title', 'Presensi Pulang')->count())->toBe(1);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| IN-APP NOTIFICATION RECORDS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('services create in-app notification records in database', function () {
|
|
$developer = notifUserWithRole('Developer');
|
|
$owner = notifUserWithRole('Owner');
|
|
|
|
NotificationService::notify(
|
|
roles: ['Developer', 'Owner'],
|
|
title: 'DB Test',
|
|
body: 'Body here.',
|
|
url: '/db-test'
|
|
);
|
|
|
|
$this->assertDatabaseHas('notifications', [
|
|
'user_id' => $developer->id,
|
|
'title' => 'DB Test',
|
|
'body' => 'Body here.',
|
|
'url' => '/db-test',
|
|
'is_read' => false,
|
|
]);
|
|
|
|
$this->assertDatabaseHas('notifications', [
|
|
'user_id' => $owner->id,
|
|
'title' => 'DB Test',
|
|
]);
|
|
});
|
|
|
|
test('ProductService create creates in-app notification record', function () {
|
|
CashAccount::factory()->create(['balance' => 1000000]);
|
|
$developer = notifUserWithRole('Developer');
|
|
|
|
$this->actingAs($developer);
|
|
|
|
$service = new ProductService;
|
|
$product = $service->create([
|
|
'name' => 'DB Notification Product',
|
|
'description' => 'Test',
|
|
'status' => 'active',
|
|
'category_ids' => [],
|
|
'use_same_price' => false,
|
|
'variants' => [
|
|
[
|
|
'name' => 'Var',
|
|
'stock' => 10,
|
|
'reject_stock' => 0,
|
|
'retail_stock' => 5,
|
|
'prices' => [
|
|
['type' => 'retail', 'price' => 50000],
|
|
],
|
|
],
|
|
],
|
|
]);
|
|
|
|
$this->assertDatabaseHas('notifications', [
|
|
'user_id' => $developer->id,
|
|
'title' => 'Produk Baru',
|
|
]);
|
|
});
|
|
|
|
test('CashTransactionService deposit creates in-app notification record', function () {
|
|
CashAccount::factory()->create(['balance' => 5000000]);
|
|
$owner = notifUserWithRole('Owner');
|
|
|
|
$this->actingAs($owner);
|
|
|
|
$service = new CashTransactionService;
|
|
$service->deposit([
|
|
'amount' => 250000,
|
|
'description' => 'Test deposit',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('notifications', [
|
|
'user_id' => $owner->id,
|
|
'title' => 'Setoran Kas Toko',
|
|
]);
|
|
});
|
|
|
|
test('AttendanceService checkIn creates in-app notification record', function () {
|
|
$developer = notifUserWithRole('Developer');
|
|
$attData = notifEmployeeWithRole('Kasir');
|
|
$employee = $attData['employee'];
|
|
$attendant = $attData['user'];
|
|
|
|
$this->actingAs($attendant);
|
|
|
|
$service = new AttendanceService;
|
|
$service->checkIn([
|
|
'latitude' => -6.2,
|
|
'longitude' => 106.8,
|
|
]);
|
|
|
|
$this->assertDatabaseHas('notifications', [
|
|
'user_id' => $developer->id,
|
|
'title' => 'Presensi Masuk',
|
|
]);
|
|
});
|