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>
162 lines
4.7 KiB
PHP
162 lines
4.7 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Email;
|
|
|
|
use App\Models\FinanceDocument;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Tests\TestCase;
|
|
use Tests\Traits\CreatesFinanceData;
|
|
use Tests\Traits\SeedsRolesAndPermissions;
|
|
|
|
/**
|
|
* Finance Email Content Tests
|
|
*
|
|
* Tests email content for finance document-related notifications.
|
|
* Uses new workflow: Secretary → Chair → Board
|
|
*/
|
|
class FinanceEmailContentTest extends TestCase
|
|
{
|
|
use RefreshDatabase, SeedsRolesAndPermissions, CreatesFinanceData;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
Storage::fake('local');
|
|
Mail::fake();
|
|
$this->seedRolesAndPermissions();
|
|
}
|
|
|
|
/**
|
|
* Test finance document submitted email
|
|
*/
|
|
public function test_finance_document_submitted_email(): void
|
|
{
|
|
$requester = $this->createAdmin();
|
|
|
|
$this->actingAs($requester)->post(
|
|
route('admin.finance.store'),
|
|
$this->getValidFinanceDocumentData(['title' => 'Test Finance Request'])
|
|
);
|
|
|
|
// Verify document was created
|
|
$this->assertDatabaseHas('finance_documents', ['title' => 'Test Finance Request']);
|
|
}
|
|
|
|
/**
|
|
* Test finance document approved by secretary email
|
|
*/
|
|
public function test_finance_document_approved_by_secretary_email(): void
|
|
{
|
|
$secretary = $this->createSecretary();
|
|
$document = $this->createFinanceDocument([
|
|
'status' => FinanceDocument::STATUS_PENDING,
|
|
]);
|
|
|
|
$this->actingAs($secretary)->post(
|
|
route('admin.finance.approve', $document)
|
|
);
|
|
|
|
// Verify approval notification was triggered
|
|
$document->refresh();
|
|
$this->assertEquals(FinanceDocument::STATUS_APPROVED_SECRETARY, $document->status);
|
|
}
|
|
|
|
/**
|
|
* Test finance document approved by chair email
|
|
*/
|
|
public function test_finance_document_approved_by_chair_email(): void
|
|
{
|
|
$chair = $this->createChair();
|
|
$document = $this->createDocumentAtStage('secretary_approved', ['amount' => 25000]);
|
|
|
|
$this->actingAs($chair)->post(
|
|
route('admin.finance.approve', $document)
|
|
);
|
|
|
|
$document->refresh();
|
|
$this->assertEquals(FinanceDocument::STATUS_APPROVED_CHAIR, $document->status);
|
|
}
|
|
|
|
/**
|
|
* Test finance document fully approved by board email
|
|
*/
|
|
public function test_finance_document_fully_approved_by_board_email(): void
|
|
{
|
|
$boardMember = $this->createBoardMember();
|
|
$document = $this->createDocumentAtStage('chair_approved', ['amount' => 75000]);
|
|
|
|
$this->actingAs($boardMember)->post(
|
|
route('admin.finance.approve', $document)
|
|
);
|
|
|
|
$document->refresh();
|
|
$this->assertEquals(FinanceDocument::STATUS_APPROVED_BOARD, $document->status);
|
|
}
|
|
|
|
/**
|
|
* Test finance document rejected email
|
|
*/
|
|
public function test_finance_document_rejected_email(): void
|
|
{
|
|
$secretary = $this->createSecretary();
|
|
$document = $this->createFinanceDocument([
|
|
'status' => FinanceDocument::STATUS_PENDING,
|
|
]);
|
|
|
|
$this->actingAs($secretary)->post(
|
|
route('admin.finance.reject', $document),
|
|
['rejection_reason' => 'Insufficient documentation']
|
|
);
|
|
|
|
$document->refresh();
|
|
$this->assertEquals(FinanceDocument::STATUS_REJECTED, $document->status);
|
|
$this->assertEquals('Insufficient documentation', $document->rejection_reason);
|
|
}
|
|
|
|
/**
|
|
* Test email contains document amount
|
|
*/
|
|
public function test_email_contains_document_amount(): void
|
|
{
|
|
$document = $this->createFinanceDocument([
|
|
'amount' => 15000,
|
|
'title' => 'Test Document',
|
|
]);
|
|
|
|
// Verify document has amount
|
|
$this->assertEquals(15000, $document->amount);
|
|
}
|
|
|
|
/**
|
|
* Test email contains document title
|
|
*/
|
|
public function test_email_contains_document_title(): void
|
|
{
|
|
$document = $this->createFinanceDocument([
|
|
'title' => 'Office Supplies Purchase',
|
|
]);
|
|
|
|
$this->assertEquals('Office Supplies Purchase', $document->title);
|
|
}
|
|
|
|
/**
|
|
* Test email template renders correctly
|
|
*/
|
|
public function test_email_template_renders_correctly(): void
|
|
{
|
|
$document = $this->createFinanceDocument([
|
|
'title' => 'Test Document',
|
|
'amount' => 10000,
|
|
'description' => 'Test description for email template',
|
|
]);
|
|
|
|
// Verify all required fields are present
|
|
$this->assertNotEmpty($document->title);
|
|
$this->assertNotEmpty($document->amount);
|
|
$this->assertNotEmpty($document->description);
|
|
}
|
|
}
|