Add phone login support and member import functionality
Features: - Support login via phone number or email (LoginRequest) - Add members:import-roster command for Excel roster import - Merge survey emails with roster data Code Quality (Phase 1-4): - Add database locking for balance calculation - Add self-approval checks for finance workflow - Create service layer (FinanceDocumentApprovalService, PaymentVerificationService) - Add HasAccountingEntries and HasApprovalWorkflow traits - Create FormRequest classes for validation - Add status-badge component - Define authorization gates in AuthServiceProvider - Add accounting config file Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ use App\Models\FinanceDocument;
|
||||
use App\Models\PaymentOrder;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
trait CreatesFinanceData
|
||||
{
|
||||
@@ -34,6 +34,7 @@ trait CreatesFinanceData
|
||||
|
||||
// Verify it's small amount
|
||||
assert($doc->determineAmountTier() === FinanceDocument::AMOUNT_TIER_SMALL);
|
||||
|
||||
return $doc;
|
||||
}
|
||||
|
||||
@@ -48,6 +49,7 @@ trait CreatesFinanceData
|
||||
|
||||
// Verify it's medium amount
|
||||
assert($doc->determineAmountTier() === FinanceDocument::AMOUNT_TIER_MEDIUM);
|
||||
|
||||
return $doc;
|
||||
}
|
||||
|
||||
@@ -62,19 +64,20 @@ trait CreatesFinanceData
|
||||
|
||||
// Verify it's large amount
|
||||
assert($doc->determineAmountTier() === FinanceDocument::AMOUNT_TIER_LARGE);
|
||||
|
||||
return $doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a finance document at specific approval stage
|
||||
* Create a finance document at specific approval stage (new workflow)
|
||||
*/
|
||||
protected function createDocumentAtStage(string $stage, array $attributes = []): FinanceDocument
|
||||
{
|
||||
$statusMap = [
|
||||
'pending' => FinanceDocument::STATUS_PENDING,
|
||||
'cashier_approved' => FinanceDocument::STATUS_APPROVED_CASHIER,
|
||||
'accountant_approved' => FinanceDocument::STATUS_APPROVED_ACCOUNTANT,
|
||||
'secretary_approved' => FinanceDocument::STATUS_APPROVED_SECRETARY,
|
||||
'chair_approved' => FinanceDocument::STATUS_APPROVED_CHAIR,
|
||||
'board_approved' => FinanceDocument::STATUS_APPROVED_BOARD,
|
||||
'rejected' => FinanceDocument::STATUS_REJECTED,
|
||||
];
|
||||
|
||||
@@ -88,8 +91,8 @@ trait CreatesFinanceData
|
||||
*/
|
||||
protected function createPaymentOrder(array $attributes = []): PaymentOrder
|
||||
{
|
||||
if (!isset($attributes['finance_document_id'])) {
|
||||
$document = $this->createDocumentAtStage('chair_approved');
|
||||
if (! isset($attributes['finance_document_id'])) {
|
||||
$document = $this->createDocumentAtStage('secretary_approved', ['amount' => 3000]);
|
||||
$attributes['finance_document_id'] = $document->id;
|
||||
}
|
||||
|
||||
@@ -121,17 +124,19 @@ trait CreatesFinanceData
|
||||
{
|
||||
$cashier = $attributes['recorded_by_cashier_id'] ?? User::factory()->create()->id;
|
||||
|
||||
return CashierLedgerEntry::create(array_merge([
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now(),
|
||||
'amount' => 10000,
|
||||
'payment_method' => 'bank_transfer',
|
||||
'bank_account' => 'Test Bank Account',
|
||||
'balance_before' => 0,
|
||||
'balance_after' => 10000,
|
||||
'recorded_by_cashier_id' => $cashier,
|
||||
'recorded_at' => now(),
|
||||
], $attributes));
|
||||
return DB::transaction(function () use ($attributes, $cashier) {
|
||||
return CashierLedgerEntry::create(array_merge([
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now(),
|
||||
'amount' => 10000,
|
||||
'payment_method' => 'bank_transfer',
|
||||
'bank_account' => 'Test Bank Account',
|
||||
'balance_before' => 0,
|
||||
'balance_after' => 10000,
|
||||
'recorded_by_cashier_id' => $cashier,
|
||||
'recorded_at' => now(),
|
||||
], $attributes));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,15 +144,17 @@ trait CreatesFinanceData
|
||||
*/
|
||||
protected function createReceiptEntry(int $amount, string $bankAccount = 'Test Account', array $attributes = []): CashierLedgerEntry
|
||||
{
|
||||
$latestBalance = CashierLedgerEntry::getLatestBalance($bankAccount);
|
||||
return DB::transaction(function () use ($amount, $bankAccount, $attributes) {
|
||||
$latestBalance = CashierLedgerEntry::getLatestBalance($bankAccount);
|
||||
|
||||
return $this->createCashierLedgerEntry(array_merge([
|
||||
'entry_type' => 'receipt',
|
||||
'amount' => $amount,
|
||||
'bank_account' => $bankAccount,
|
||||
'balance_before' => $latestBalance,
|
||||
'balance_after' => $latestBalance + $amount,
|
||||
], $attributes));
|
||||
return $this->createCashierLedgerEntry(array_merge([
|
||||
'entry_type' => 'receipt',
|
||||
'amount' => $amount,
|
||||
'bank_account' => $bankAccount,
|
||||
'balance_before' => $latestBalance,
|
||||
'balance_after' => $latestBalance + $amount,
|
||||
], $attributes));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,15 +162,17 @@ trait CreatesFinanceData
|
||||
*/
|
||||
protected function createPaymentEntry(int $amount, string $bankAccount = 'Test Account', array $attributes = []): CashierLedgerEntry
|
||||
{
|
||||
$latestBalance = CashierLedgerEntry::getLatestBalance($bankAccount);
|
||||
return DB::transaction(function () use ($amount, $bankAccount, $attributes) {
|
||||
$latestBalance = CashierLedgerEntry::getLatestBalance($bankAccount);
|
||||
|
||||
return $this->createCashierLedgerEntry(array_merge([
|
||||
'entry_type' => 'payment',
|
||||
'amount' => $amount,
|
||||
'bank_account' => $bankAccount,
|
||||
'balance_before' => $latestBalance,
|
||||
'balance_after' => $latestBalance - $amount,
|
||||
], $attributes));
|
||||
return $this->createCashierLedgerEntry(array_merge([
|
||||
'entry_type' => 'payment',
|
||||
'amount' => $amount,
|
||||
'bank_account' => $bankAccount,
|
||||
'balance_before' => $latestBalance,
|
||||
'balance_after' => $latestBalance - $amount,
|
||||
], $attributes));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,7 +274,6 @@ trait CreatesFinanceData
|
||||
'title' => 'Test Finance Document',
|
||||
'description' => 'Test description',
|
||||
'amount' => 10000,
|
||||
'request_type' => FinanceDocument::REQUEST_TYPE_EXPENSE_REIMBURSEMENT,
|
||||
'payee_name' => 'Test Payee',
|
||||
'notes' => 'Test notes',
|
||||
], $overrides);
|
||||
|
||||
Reference in New Issue
Block a user