mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-09-01 21:00:58 +00:00
* refactor: stabilize model identities for domain migration * refactor: extract module platform context * refactor: assign models to domain contexts * refactor: extract ai platform context * refactor: extract storage platform context * refactor: extract mail platform context * refactor: extract pdf platform context * refactor: extract operations platform context * refactor: move installation into operations platform * refactor: extract money domain context * refactor: extract taxation domain context * refactor: extract catalog domain context * refactor: extract metadata domain context * refactor: extract reporting domain context * refactor: extract purchases domain context * refactor: extract receivables domain context * refactor: extract accounts domain context * refactor: complete reporting statement boundary * refactor: extract contacts domain context * refactor: extract sales domain context * refactor: remove legacy application layers * fix: migrate legacy bouncer role identities
125 lines
6.2 KiB
PHP
125 lines
6.2 KiB
PHP
<?php
|
|
|
|
use App\Adapters\Sales\LaravelEstimateEmailSender;
|
|
use App\Adapters\Sales\LaravelInvoiceEmailSender;
|
|
use App\Adapters\Sales\MoneyDocumentExchangeRateRecorder;
|
|
use App\Domains\Sales\Application\EstimateService;
|
|
use App\Domains\Sales\Application\InvoiceService;
|
|
use App\Domains\Sales\Contracts\DocumentExchangeRateRecorder;
|
|
use App\Domains\Sales\Contracts\EstimateEmailSender;
|
|
use App\Domains\Sales\Contracts\EstimatePdfDataProvider;
|
|
use App\Domains\Sales\Contracts\InvoiceEmailSender;
|
|
use App\Domains\Sales\Contracts\InvoicePdfDataProvider;
|
|
use App\Domains\Sales\Models\Estimate;
|
|
use App\Domains\Sales\Models\Invoice;
|
|
use App\Domains\Sales\Models\RecurringInvoice;
|
|
use App\Domains\Sales\Policies\EstimatePolicy;
|
|
use App\Domains\Sales\Policies\InvoicePolicy;
|
|
use App\Domains\Sales\Policies\RecurringInvoicePolicy;
|
|
use App\Domains\Sales\SalesServiceProvider;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
use Illuminate\Support\Facades\Gate;
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
test('the sales domain owns document behavior authorization and commands', function () {
|
|
expect(app()->getProviders(SalesServiceProvider::class))->toHaveCount(1)
|
|
->and(app(EstimatePdfDataProvider::class))->toBeInstanceOf(EstimateService::class)
|
|
->and(app(InvoicePdfDataProvider::class))->toBeInstanceOf(InvoiceService::class)
|
|
->and(app(DocumentExchangeRateRecorder::class))->toBeInstanceOf(MoneyDocumentExchangeRateRecorder::class)
|
|
->and(app(EstimateEmailSender::class))->toBeInstanceOf(LaravelEstimateEmailSender::class)
|
|
->and(app(InvoiceEmailSender::class))->toBeInstanceOf(LaravelInvoiceEmailSender::class)
|
|
->and(Gate::getPolicyFor(Estimate::class))->toBeInstanceOf(EstimatePolicy::class)
|
|
->and(Gate::getPolicyFor(Invoice::class))->toBeInstanceOf(InvoicePolicy::class)
|
|
->and(Gate::getPolicyFor(RecurringInvoice::class))->toBeInstanceOf(RecurringInvoicePolicy::class)
|
|
->and(Gate::has('send invoice'))->toBeTrue()
|
|
->and(Gate::has('create credit note'))->toBeTrue()
|
|
->and(Gate::has('send estimate'))->toBeTrue()
|
|
->and(Gate::has('delete multiple invoices'))->toBeTrue()
|
|
->and(Gate::has('delete multiple estimates'))->toBeTrue()
|
|
->and(Gate::has('delete multiple recurring invoices'))->toBeTrue()
|
|
->and(Artisan::all())->toHaveKeys(['check:estimates:status', 'check:invoices:status']);
|
|
|
|
foreach ([
|
|
'App\\Services\\Document\\CreditNoteService',
|
|
'App\\Services\\Document\\DocumentItemService',
|
|
'App\\Services\\Document\\EstimateService',
|
|
'App\\Services\\Document\\InvoiceBalanceService',
|
|
'App\\Services\\Document\\InvoiceService',
|
|
'App\\Services\\Document\\RecurringInvoiceService',
|
|
'App\\Services\\Document\\SerialNumberService',
|
|
'App\\Policies\\CreditNotePolicy',
|
|
'App\\Policies\\EstimatePolicy',
|
|
'App\\Policies\\InvoicePolicy',
|
|
'App\\Policies\\RecurringInvoicePolicy',
|
|
'App\\Jobs\\GenerateEstimatePdfJob',
|
|
'App\\Jobs\\GenerateInvoicePdfJob',
|
|
'App\\Mail\\EstimateViewedMail',
|
|
'App\\Mail\\InvoiceViewedMail',
|
|
'App\\Mail\\SendCreditNoteMail',
|
|
'App\\Mail\\SendEstimateMail',
|
|
'App\\Mail\\SendInvoiceMail',
|
|
'App\\Http\\Controllers\\Company\\Estimate\\EstimatesController',
|
|
'App\\Http\\Controllers\\Company\\Estimate\\EstimateTemplatesController',
|
|
'App\\Http\\Controllers\\Company\\Invoice\\InvoicesController',
|
|
'App\\Http\\Controllers\\Company\\Invoice\\InvoiceTemplatesController',
|
|
'App\\Http\\Controllers\\Company\\RecurringInvoice\\RecurringInvoiceController',
|
|
'App\\Http\\Controllers\\Company\\RecurringInvoice\\RecurringInvoiceFrequencyController',
|
|
'App\\Http\\Controllers\\Company\\General\\SerialNumberController',
|
|
'App\\Http\\Controllers\\CustomerPortal\\Estimate\\AcceptEstimateController',
|
|
'App\\Http\\Controllers\\CustomerPortal\\Estimate\\EstimatesController',
|
|
'App\\Http\\Controllers\\CustomerPortal\\Invoice\\InvoicesController',
|
|
'App\\Http\\Controllers\\CustomerPortal\\EstimatePdfController',
|
|
'App\\Http\\Controllers\\CustomerPortal\\InvoicePdfController',
|
|
'App\\Http\\Controllers\\Pdf\\DocumentPdfController',
|
|
] as $legacyClass) {
|
|
expect(class_exists($legacyClass))->toBeFalse();
|
|
}
|
|
});
|
|
|
|
test('the sales domain preserves company document routes and middleware', function () {
|
|
$routes = collect(Route::getRoutes()->getRoutes())
|
|
->filter(fn ($route): bool => preg_match(
|
|
'#^api/v1/(?:invoices|estimates|recurring-invoices|recurring-invoice-frequency|next-number|number-placeholders)(?:$|/)#',
|
|
$route->uri(),
|
|
) === 1);
|
|
|
|
expect($routes)->toHaveCount(34);
|
|
|
|
foreach ($routes as $route) {
|
|
expect($route->getActionName())
|
|
->toStartWith('App\\Domains\\Sales\\Http\\Controllers\\Company\\')
|
|
->and($route->gatherMiddleware())->toContain('auth:sanctum', 'company', 'bouncer');
|
|
}
|
|
});
|
|
|
|
test('the sales domain preserves customer and pdf routes', function () {
|
|
$customerRoutes = collect(Route::getRoutes()->getRoutes())
|
|
->filter(fn ($route): bool => str_starts_with($route->uri(), 'api/v1/{company}/customer/invoices')
|
|
|| str_starts_with($route->uri(), 'api/v1/{company}/customer/estimates')
|
|
|| $route->uri() === 'api/v1/{company}/customer/estimate/{estimate}/status');
|
|
|
|
expect($customerRoutes)->toHaveCount(5);
|
|
|
|
foreach ($customerRoutes as $route) {
|
|
expect($route->getActionName())
|
|
->toStartWith('App\\Domains\\Sales\\Http\\Controllers\\CustomerPortal\\')
|
|
->and($route->gatherMiddleware())->toContain('auth:customer', 'customer-portal');
|
|
}
|
|
|
|
$pdfRoutes = collect(Route::getRoutes()->getRoutes())
|
|
->filter(fn ($route): bool => in_array($route->uri(), [
|
|
'invoices/pdf/{invoice}',
|
|
'estimates/pdf/{estimate}',
|
|
'customer/invoices/{email_log}',
|
|
'customer/invoices/view/{email_log}',
|
|
'customer/estimates/{email_log}',
|
|
'customer/estimates/view/{email_log}',
|
|
], true));
|
|
|
|
expect($pdfRoutes)->toHaveCount(6);
|
|
|
|
foreach ($pdfRoutes as $route) {
|
|
expect($route->getActionName())->toStartWith('App\\Domains\\Sales\\Http\\Controllers\\');
|
|
}
|
|
});
|