Initial commit
This commit is contained in:
393
database/seeders/FinancialWorkflowTestDataSeeder.php
Normal file
393
database/seeders/FinancialWorkflowTestDataSeeder.php
Normal file
@@ -0,0 +1,393 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\BankReconciliation;
|
||||
use App\Models\CashierLedgerEntry;
|
||||
use App\Models\FinanceDocument;
|
||||
use App\Models\PaymentOrder;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
/**
|
||||
* Financial Workflow Test Data Seeder
|
||||
*
|
||||
* Generates comprehensive test data for the financial workflow system
|
||||
*/
|
||||
class FinancialWorkflowTestDataSeeder extends Seeder
|
||||
{
|
||||
protected User $requester;
|
||||
protected User $cashier;
|
||||
protected User $accountant;
|
||||
protected User $chair;
|
||||
protected User $boardMember;
|
||||
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$this->command->info('🌱 Seeding financial workflow test data...');
|
||||
|
||||
// Create or get test users
|
||||
$this->createTestUsers();
|
||||
|
||||
// Seed finance documents at various stages
|
||||
$this->seedFinanceDocuments();
|
||||
|
||||
// Seed payment orders
|
||||
$this->seedPaymentOrders();
|
||||
|
||||
// Seed cashier ledger entries
|
||||
$this->seedCashierLedgerEntries();
|
||||
|
||||
// Seed bank reconciliations
|
||||
$this->seedBankReconciliations();
|
||||
|
||||
$this->command->info('✅ Financial workflow test data seeded successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create test users with appropriate roles
|
||||
*/
|
||||
protected function createTestUsers(): void
|
||||
{
|
||||
$this->command->info('Creating test users...');
|
||||
|
||||
$this->requester = User::firstOrCreate(
|
||||
['email' => 'requester@test.com'],
|
||||
[
|
||||
'name' => 'Test Requester',
|
||||
'password' => Hash::make('password'),
|
||||
]
|
||||
);
|
||||
$this->requester->assignRole('finance_requester');
|
||||
|
||||
$this->cashier = User::firstOrCreate(
|
||||
['email' => 'cashier@test.com'],
|
||||
[
|
||||
'name' => 'Test Cashier',
|
||||
'password' => Hash::make('password'),
|
||||
]
|
||||
);
|
||||
$this->cashier->assignRole('finance_cashier');
|
||||
|
||||
$this->accountant = User::firstOrCreate(
|
||||
['email' => 'accountant@test.com'],
|
||||
[
|
||||
'name' => 'Test Accountant',
|
||||
'password' => Hash::make('password'),
|
||||
]
|
||||
);
|
||||
$this->accountant->assignRole('finance_accountant');
|
||||
|
||||
$this->chair = User::firstOrCreate(
|
||||
['email' => 'chair@test.com'],
|
||||
[
|
||||
'name' => 'Test Chair',
|
||||
'password' => Hash::make('password'),
|
||||
]
|
||||
);
|
||||
$this->chair->assignRole('finance_chair');
|
||||
|
||||
$this->boardMember = User::firstOrCreate(
|
||||
['email' => 'board@test.com'],
|
||||
[
|
||||
'name' => 'Test Board Member',
|
||||
'password' => Hash::make('password'),
|
||||
]
|
||||
);
|
||||
$this->boardMember->assignRole('finance_board_member');
|
||||
|
||||
$this->command->info('✓ Test users created');
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed finance documents at various stages of the workflow
|
||||
*/
|
||||
protected function seedFinanceDocuments(): void
|
||||
{
|
||||
$this->command->info('Seeding finance documents...');
|
||||
|
||||
// Pending documents (Stage 1)
|
||||
FinanceDocument::factory()
|
||||
->count(3)
|
||||
->smallAmount()
|
||||
->pending()
|
||||
->create(['submitted_by_id' => $this->requester->id]);
|
||||
|
||||
FinanceDocument::factory()
|
||||
->count(2)
|
||||
->mediumAmount()
|
||||
->pending()
|
||||
->create(['submitted_by_id' => $this->requester->id]);
|
||||
|
||||
// Approved by cashier (Stage 1)
|
||||
FinanceDocument::factory()
|
||||
->count(2)
|
||||
->smallAmount()
|
||||
->approvedByCashier()
|
||||
->create([
|
||||
'submitted_by_id' => $this->requester->id,
|
||||
'cashier_approved_by_id' => $this->cashier->id,
|
||||
]);
|
||||
|
||||
// Approved by accountant - small amounts (Ready for payment)
|
||||
FinanceDocument::factory()
|
||||
->count(3)
|
||||
->smallAmount()
|
||||
->approvedByAccountant()
|
||||
->create([
|
||||
'submitted_by_id' => $this->requester->id,
|
||||
'cashier_approved_by_id' => $this->cashier->id,
|
||||
'accountant_approved_by_id' => $this->accountant->id,
|
||||
]);
|
||||
|
||||
// Approved by chair - medium amounts (Ready for payment)
|
||||
FinanceDocument::factory()
|
||||
->count(2)
|
||||
->mediumAmount()
|
||||
->approvedByChair()
|
||||
->create([
|
||||
'submitted_by_id' => $this->requester->id,
|
||||
'cashier_approved_by_id' => $this->cashier->id,
|
||||
'accountant_approved_by_id' => $this->accountant->id,
|
||||
'chair_approved_by_id' => $this->chair->id,
|
||||
]);
|
||||
|
||||
// Large amount with board approval (Ready for payment)
|
||||
FinanceDocument::factory()
|
||||
->count(1)
|
||||
->largeAmount()
|
||||
->approvedByChair()
|
||||
->create([
|
||||
'submitted_by_id' => $this->requester->id,
|
||||
'cashier_approved_by_id' => $this->cashier->id,
|
||||
'accountant_approved_by_id' => $this->accountant->id,
|
||||
'chair_approved_by_id' => $this->chair->id,
|
||||
'board_meeting_approved_at' => now(),
|
||||
'board_meeting_approved_by_id' => $this->boardMember->id,
|
||||
]);
|
||||
|
||||
// Completed workflow
|
||||
FinanceDocument::factory()
|
||||
->count(5)
|
||||
->smallAmount()
|
||||
->approvedByAccountant()
|
||||
->paymentExecuted()
|
||||
->create([
|
||||
'submitted_by_id' => $this->requester->id,
|
||||
'cashier_approved_by_id' => $this->cashier->id,
|
||||
'accountant_approved_by_id' => $this->accountant->id,
|
||||
'cashier_recorded_at' => now(),
|
||||
]);
|
||||
|
||||
// Rejected documents
|
||||
FinanceDocument::factory()
|
||||
->count(2)
|
||||
->rejected()
|
||||
->create([
|
||||
'submitted_by_id' => $this->requester->id,
|
||||
]);
|
||||
|
||||
$this->command->info('✓ Finance documents seeded');
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed payment orders
|
||||
*/
|
||||
protected function seedPaymentOrders(): void
|
||||
{
|
||||
$this->command->info('Seeding payment orders...');
|
||||
|
||||
// Get approved documents without payment orders
|
||||
$approvedDocs = FinanceDocument::whereIn('status', [
|
||||
FinanceDocument::STATUS_APPROVED_ACCOUNTANT,
|
||||
FinanceDocument::STATUS_APPROVED_CHAIR,
|
||||
])
|
||||
->whereNull('payment_order_created_at')
|
||||
->limit(5)
|
||||
->get();
|
||||
|
||||
foreach ($approvedDocs as $doc) {
|
||||
// Pending verification
|
||||
PaymentOrder::factory()
|
||||
->pendingVerification()
|
||||
->create([
|
||||
'finance_document_id' => $doc->id,
|
||||
'payment_amount' => $doc->amount,
|
||||
'created_by_accountant_id' => $this->accountant->id,
|
||||
]);
|
||||
|
||||
$doc->update([
|
||||
'payment_order_created_at' => now(),
|
||||
'payment_order_created_by_id' => $this->accountant->id,
|
||||
]);
|
||||
}
|
||||
|
||||
// Verified payment orders
|
||||
PaymentOrder::factory()
|
||||
->count(3)
|
||||
->verified()
|
||||
->create([
|
||||
'created_by_accountant_id' => $this->accountant->id,
|
||||
'verified_by_cashier_id' => $this->cashier->id,
|
||||
]);
|
||||
|
||||
// Executed payment orders
|
||||
PaymentOrder::factory()
|
||||
->count(5)
|
||||
->executed()
|
||||
->create([
|
||||
'created_by_accountant_id' => $this->accountant->id,
|
||||
'verified_by_cashier_id' => $this->cashier->id,
|
||||
'executed_by_cashier_id' => $this->cashier->id,
|
||||
]);
|
||||
|
||||
$this->command->info('✓ Payment orders seeded');
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed cashier ledger entries with running balances
|
||||
*/
|
||||
protected function seedCashierLedgerEntries(): void
|
||||
{
|
||||
$this->command->info('Seeding cashier ledger entries...');
|
||||
|
||||
$bankAccounts = [
|
||||
'First Bank - 1234567890',
|
||||
'Second Bank - 0987654321',
|
||||
'Petty Cash',
|
||||
];
|
||||
|
||||
foreach ($bankAccounts as $account) {
|
||||
$currentBalance = 100000; // Starting balance
|
||||
|
||||
// Create 10 entries for each account
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$isReceipt = $i % 3 !== 0; // 2/3 receipts, 1/3 payments
|
||||
$amount = rand(1000, 10000);
|
||||
|
||||
$entry = CashierLedgerEntry::create([
|
||||
'entry_type' => $isReceipt ? 'receipt' : 'payment',
|
||||
'entry_date' => now()->subDays(rand(1, 30)),
|
||||
'amount' => $amount,
|
||||
'payment_method' => $account === 'Petty Cash' ? 'cash' : 'bank_transfer',
|
||||
'bank_account' => $account,
|
||||
'balance_before' => $currentBalance,
|
||||
'balance_after' => $isReceipt
|
||||
? $currentBalance + $amount
|
||||
: $currentBalance - $amount,
|
||||
'receipt_number' => $isReceipt ? 'RCP' . str_pad($i + 1, 6, '0', STR_PAD_LEFT) : null,
|
||||
'notes' => $isReceipt ? 'Test receipt entry' : 'Test payment entry',
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now()->subDays(rand(1, 30)),
|
||||
]);
|
||||
|
||||
$currentBalance = $entry->balance_after;
|
||||
}
|
||||
}
|
||||
|
||||
$this->command->info('✓ Cashier ledger entries seeded');
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed bank reconciliations
|
||||
*/
|
||||
protected function seedBankReconciliations(): void
|
||||
{
|
||||
$this->command->info('Seeding bank reconciliations...');
|
||||
|
||||
// Pending reconciliation
|
||||
BankReconciliation::create([
|
||||
'reconciliation_month' => now()->startOfMonth(),
|
||||
'bank_statement_date' => now(),
|
||||
'bank_statement_balance' => 100000,
|
||||
'system_book_balance' => 95000,
|
||||
'outstanding_checks' => [
|
||||
['check_number' => 'CHK001', 'amount' => 3000, 'description' => 'Vendor A payment'],
|
||||
['check_number' => 'CHK002', 'amount' => 2000, 'description' => 'Service fee'],
|
||||
],
|
||||
'deposits_in_transit' => [
|
||||
['date' => now()->format('Y-m-d'), 'amount' => 5000, 'description' => 'Member dues'],
|
||||
],
|
||||
'bank_charges' => [
|
||||
['amount' => 500, 'description' => 'Monthly service charge'],
|
||||
],
|
||||
'discrepancy_amount' => 4500,
|
||||
'notes' => 'Pending review',
|
||||
'prepared_by_cashier_id' => $this->cashier->id,
|
||||
'prepared_at' => now(),
|
||||
'reconciliation_status' => 'pending',
|
||||
]);
|
||||
|
||||
// Reviewed reconciliation
|
||||
BankReconciliation::create([
|
||||
'reconciliation_month' => now()->subMonth()->startOfMonth(),
|
||||
'bank_statement_date' => now()->subMonth(),
|
||||
'bank_statement_balance' => 95000,
|
||||
'system_book_balance' => 93000,
|
||||
'outstanding_checks' => [
|
||||
['check_number' => 'CHK003', 'amount' => 1500, 'description' => 'Supplies'],
|
||||
],
|
||||
'deposits_in_transit' => [
|
||||
['date' => now()->subMonth()->format('Y-m-d'), 'amount' => 3000, 'description' => 'Donation'],
|
||||
],
|
||||
'bank_charges' => [
|
||||
['amount' => 500, 'description' => 'Service charge'],
|
||||
],
|
||||
'discrepancy_amount' => 0,
|
||||
'notes' => 'All items reconciled',
|
||||
'prepared_by_cashier_id' => $this->cashier->id,
|
||||
'prepared_at' => now()->subMonth(),
|
||||
'reviewed_by_accountant_id' => $this->accountant->id,
|
||||
'reviewed_at' => now()->subMonth()->addDays(2),
|
||||
'reconciliation_status' => 'pending',
|
||||
]);
|
||||
|
||||
// Completed reconciliation
|
||||
BankReconciliation::create([
|
||||
'reconciliation_month' => now()->subMonths(2)->startOfMonth(),
|
||||
'bank_statement_date' => now()->subMonths(2),
|
||||
'bank_statement_balance' => 90000,
|
||||
'system_book_balance' => 90000,
|
||||
'outstanding_checks' => [],
|
||||
'deposits_in_transit' => [],
|
||||
'bank_charges' => [
|
||||
['amount' => 500, 'description' => 'Service charge'],
|
||||
],
|
||||
'discrepancy_amount' => 0,
|
||||
'notes' => 'Perfect match',
|
||||
'prepared_by_cashier_id' => $this->cashier->id,
|
||||
'prepared_at' => now()->subMonths(2),
|
||||
'reviewed_by_accountant_id' => $this->accountant->id,
|
||||
'reviewed_at' => now()->subMonths(2)->addDays(2),
|
||||
'approved_by_manager_id' => $this->chair->id,
|
||||
'approved_at' => now()->subMonths(2)->addDays(3),
|
||||
'reconciliation_status' => 'completed',
|
||||
]);
|
||||
|
||||
// Reconciliation with discrepancy
|
||||
BankReconciliation::create([
|
||||
'reconciliation_month' => now()->subMonths(3)->startOfMonth(),
|
||||
'bank_statement_date' => now()->subMonths(3),
|
||||
'bank_statement_balance' => 85000,
|
||||
'system_book_balance' => 75000,
|
||||
'outstanding_checks' => [
|
||||
['check_number' => 'CHK004', 'amount' => 2000, 'description' => 'Payment'],
|
||||
],
|
||||
'deposits_in_transit' => [],
|
||||
'bank_charges' => [
|
||||
['amount' => 500, 'description' => 'Service charge'],
|
||||
],
|
||||
'discrepancy_amount' => 7500,
|
||||
'notes' => 'Large discrepancy - needs investigation',
|
||||
'prepared_by_cashier_id' => $this->cashier->id,
|
||||
'prepared_at' => now()->subMonths(3),
|
||||
'reconciliation_status' => 'discrepancy',
|
||||
]);
|
||||
|
||||
$this->command->info('✓ Bank reconciliations seeded');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user