From cba7e7b2bd5e63e5d34ccd25949c0b312e9cd413 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 09:37:21 +1000 Subject: [PATCH 01/14] Fixes for tests --- app/Models/Client.php | 2 +- app/Providers/StaticServiceProvider.php | 1 + .../Export/ReportCsvGenerationTest.php | 20 ++++ tests/Feature/ProjectApiTest.php | 2 +- tests/MockAccountData.php | 107 +++++++++++------- tests/TestCase.php | 1 - tests/Unit/AutoBillInvoiceTest.php | 5 +- tests/Unit/Chart/ChartCurrencyTest.php | 47 ++++++-- tests/Unit/CompanyDocumentsTest.php | 2 +- tests/Unit/EInvoiceTest.php | 2 +- tests/Unit/EntityTest.php | 2 +- tests/Unit/FactoryCreationTest.php | 2 +- tests/Unit/GeneratesCounterTest.php | 2 +- tests/_bootstrap.php | 11 -- 14 files changed, 138 insertions(+), 68 deletions(-) diff --git a/app/Models/Client.php b/app/Models/Client.php index cc204188df..8ba23516f6 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -495,7 +495,7 @@ class Client extends BaseModel implements HasLocalePreference return $item->id == $currency_id; }); - }); + }) ?? \App\Models\Currency::find($this->getSetting('currency_id')); } diff --git a/app/Providers/StaticServiceProvider.php b/app/Providers/StaticServiceProvider.php index 07677af7d4..d82675fcaa 100644 --- a/app/Providers/StaticServiceProvider.php +++ b/app/Providers/StaticServiceProvider.php @@ -263,6 +263,7 @@ class StaticServiceProvider extends ServiceProvider }); + nlog("static service provider registered"); } public function boot() diff --git a/tests/Feature/Export/ReportCsvGenerationTest.php b/tests/Feature/Export/ReportCsvGenerationTest.php index 3c159d968f..b403498121 100644 --- a/tests/Feature/Export/ReportCsvGenerationTest.php +++ b/tests/Feature/Export/ReportCsvGenerationTest.php @@ -27,6 +27,7 @@ use App\Models\Credit; use App\Models\Expense; use App\Models\Invoice; use App\Models\User; +use App\Repositories\InvoiceRepository; use App\Utils\Traits\MakesHash; use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Support\Facades\Http; @@ -652,6 +653,9 @@ $this->account->forceDelete(); ]); + $repo = new InvoiceRepository(); + $invoice = $repo->save([], $invoice); + $log = '[[1689547165,1689550765,"sumtin",true]]'; \App\Models\Task::factory()->create([ @@ -912,6 +916,11 @@ $this->account->forceDelete(); $invoice->client->paid_to_date = 0; $invoice->push(); + +$repo = new InvoiceRepository(); +$invoice = $repo->save([], $invoice); + + $invoice->service()->markPaid()->save(); $data = [ @@ -1262,6 +1271,10 @@ $this->account->forceDelete(); 'terms' => 'Terms', ]); + $repo = new InvoiceRepository(); + $invoice = $repo->save([], $invoice); + + $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","invoice.number","invoice.amount","payment.date", "payment.amount","invoice.user"], @@ -1452,6 +1465,9 @@ $this->account->forceDelete(); ] ]); +$repo = new InvoiceRepository(); +$invoice = $repo->save([], $invoice); + $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","invoice.number","invoice.amount","payment.date", "payment.amount", "item.quantity", "item.cost", "item.line_total", "item.discount", "item.notes", "item.product_key", "item.custom_value1", "item.tax_name1", "item.tax_rate1",], @@ -1844,6 +1860,10 @@ $this->account->forceDelete(); 'terms' => 'Terms', ]); + $repo = new InvoiceRepository(); + $invoice = $repo->save([], $invoice); + + $invoice->service()->markPaid()->save(); $data = [ diff --git a/tests/Feature/ProjectApiTest.php b/tests/Feature/ProjectApiTest.php index d1c064b232..afda82037a 100644 --- a/tests/Feature/ProjectApiTest.php +++ b/tests/Feature/ProjectApiTest.php @@ -32,7 +32,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class ProjectApiTest extends TestCase { use MakesHash; - use DatabaseTransactions; + // use DatabaseTransactions; use MockAccountData; protected $faker; diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index 9099959d39..b2cf963e09 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -11,59 +11,62 @@ namespace Tests; -use App\DataMapper\ClientRegistrationFields; -use App\DataMapper\ClientSettings; -use App\DataMapper\CompanySettings; -use App\Factory\CompanyUserFactory; -use App\Factory\CreditFactory; -use App\Factory\InvoiceFactory; -use App\Factory\InvoiceInvitationFactory; -use App\Factory\InvoiceItemFactory; -use App\Factory\InvoiceToRecurringInvoiceFactory; -use App\Factory\PurchaseOrderFactory; -use App\Helpers\Invoice\InvoiceSum; -use App\Jobs\Company\CreateCompanyTaskStatuses; -use App\Models\Account; -use App\Models\BankIntegration; -use App\Models\BankTransaction; -use App\Models\BankTransactionRule; +use App\Models\Task; +use App\Models\User; +use App\Models\Quote; use App\Models\Client; -use App\Models\ClientContact; -use App\Models\Company; -use App\Models\CompanyGateway; -use App\Models\CompanyToken; -use App\Models\Country; use App\Models\Credit; -use App\Models\CreditInvitation; +use App\Models\Vendor; +use App\Models\Account; +use App\Models\Company; +use App\Models\Country; use App\Models\Expense; -use App\Models\ExpenseCategory; -use App\Models\GroupSetting; -use App\Models\InvoiceInvitation; use App\Models\Payment; use App\Models\Product; use App\Models\Project; -use App\Models\PurchaseOrderInvitation; -use App\Models\Quote; +use App\Models\TaxRate; +use App\Models\Currency; +use App\Models\Scheduler; +use App\Models\TaskStatus; +use App\Utils\TruthSource; +use App\Models\CompanyToken; +use App\Models\GroupSetting; +use App\Models\ClientContact; +use App\Models\VendorContact; +use App\Factory\CreditFactory; +use App\Models\CompanyGateway; +use App\Models\RecurringQuote; +use Illuminate\Support\Carbon; +use App\Factory\InvoiceFactory; +use App\Models\BankIntegration; +use App\Models\BankTransaction; +use App\Models\ExpenseCategory; use App\Models\QuoteInvitation; +use App\Utils\Traits\MakesHash; +use App\Models\CreditInvitation; use App\Models\RecurringExpense; use App\Models\RecurringInvoice; -use App\Models\RecurringQuote; -use App\Models\Scheduler; -use App\Models\Task; -use App\Models\TaskStatus; -use App\Models\TaxRate; -use App\Models\User; -use App\Models\Vendor; -use App\Models\VendorContact; -use App\Utils\Traits\GeneratesCounter; -use App\Utils\Traits\MakesHash; -use App\Utils\TruthSource; -use Illuminate\Support\Carbon; -use Illuminate\Support\Facades\Artisan; -use Illuminate\Support\Facades\Cache; +use App\Models\InvoiceInvitation; +use App\DataMapper\ClientSettings; +use App\DataMapper\CompanySettings; +use App\Factory\CompanyUserFactory; +use App\Factory\InvoiceItemFactory; +use App\Helpers\Invoice\InvoiceSum; +use App\Models\BankTransactionRule; use Illuminate\Support\Facades\Hash; +use App\Factory\PurchaseOrderFactory; +use Illuminate\Support\Facades\Cache; +use App\Utils\Traits\GeneratesCounter; use Illuminate\Support\Facades\Schema; +use App\Models\PurchaseOrderInvitation; +use App\Repositories\InvoiceRepository; +use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Storage; +use App\Factory\InvoiceInvitationFactory; +use App\DataMapper\ClientRegistrationFields; +use App\Jobs\Company\CreateCompanyTaskStatuses; +use App\Repositories\RecurringInvoiceRepository; +use App\Factory\InvoiceToRecurringInvoiceFactory; /** * Class MockAccountData. @@ -208,6 +211,18 @@ trait MockAccountData Artisan::call('db:seed', ['--force' => true]); } + + app()->singleton('currencies', function ($app) { + + $resource = Currency::query()->orderBy('name')->get(); + + Cache::forever('currencies', $resource); + + return $resource; + + }); + + $this->faker = \Faker\Factory::create(); $fake_email = $this->faker->email(); @@ -309,9 +324,13 @@ trait MockAccountData 'company_id' => $this->company->id, ]); + // $client_settings = ClientSettings::defaults(); + // $client_settings->currency_id = '1'; + $this->client = Client::factory()->create([ 'user_id' => $user_id, 'company_id' => $this->company->id, + // 'settings' => $client_settings, ]); Storage::makeDirectory($this->company->company_key.'/'.$this->client->client_hash.'/invoices', 0755, true); @@ -439,6 +458,9 @@ trait MockAccountData 'uses_inclusive_taxes' => false, ]); + $repo = new RecurringInvoiceRepository(); + $this->recurring_invoice = $repo->save([], $this->recurring_invoice); + $this->recurring_invoice_calc = new InvoiceSum($this->recurring_invoice); $this->recurring_invoice_calc->build(); $this->recurring_invoice = $this->recurring_invoice_calc->getRecurringInvoice(); @@ -480,6 +502,9 @@ trait MockAccountData $this->invoice->fresh()->service()->markSent(); // $this->invoice->service()->markSent(); + $repo = new InvoiceRepository(); + $this->invoice = $repo->save([], $this->invoice); + $this->quote = Quote::factory()->create([ 'user_id' => $user_id, 'client_id' => $this->client->id, diff --git a/tests/TestCase.php b/tests/TestCase.php index a9c24851b4..b889dd12c8 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -14,7 +14,6 @@ abstract class TestCase extends BaseTestCase protected function setUp(): void { parent::setUp(); - } } diff --git a/tests/Unit/AutoBillInvoiceTest.php b/tests/Unit/AutoBillInvoiceTest.php index 77ed0b65de..96c27c88ce 100644 --- a/tests/Unit/AutoBillInvoiceTest.php +++ b/tests/Unit/AutoBillInvoiceTest.php @@ -14,6 +14,7 @@ namespace Tests\Unit; use Illuminate\Foundation\Testing\DatabaseTransactions; use Tests\MockAccountData; use Tests\TestCase; +use Illuminate\Support\Facades\Artisan; /** * @@ -21,7 +22,7 @@ use Tests\TestCase; */ class AutoBillInvoiceTest extends TestCase { - use DatabaseTransactions; + // use DatabaseTransactions; use MockAccountData; protected function setUp(): void @@ -29,10 +30,12 @@ class AutoBillInvoiceTest extends TestCase parent::setUp(); $this->makeTestData(); + } public function testAutoBillFunctionality() { + $this->assertEquals('1', $this->client->settings->currency_id); $this->assertEquals($this->client->balance, 10); $this->assertEquals($this->client->paid_to_date, 0); $this->assertEquals($this->client->credit_balance, 10); diff --git a/tests/Unit/Chart/ChartCurrencyTest.php b/tests/Unit/Chart/ChartCurrencyTest.php index e50db739e3..359b790ce7 100644 --- a/tests/Unit/Chart/ChartCurrencyTest.php +++ b/tests/Unit/Chart/ChartCurrencyTest.php @@ -14,13 +14,14 @@ namespace Tests\Unit\Chart; use Tests\TestCase; use App\Models\Client; use App\Models\Company; +use App\Models\Expense; use App\Models\Invoice; use App\Models\Currency; use Tests\MockAccountData; use App\DataMapper\ClientSettings; use App\DataMapper\CompanySettings; -use App\Models\Expense; use App\Services\Chart\ChartService; +use App\Repositories\InvoiceRepository; use Illuminate\Foundation\Testing\DatabaseTransactions; /** @@ -30,7 +31,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class ChartCurrencyTest extends TestCase { use MockAccountData; - use DatabaseTransactions; + // use DatabaseTransactions; protected function setUp(): void { @@ -72,6 +73,8 @@ class ChartCurrencyTest extends TestCase 'user_id' => $this->user->id, 'company_id' => $company->id, 'settings' => $settings, + 'balance' => 0, + 'paid_to_date' => 0, ]); Currency::query()->where('id', 1)->update(['exchange_rate' => 1]); @@ -84,9 +87,10 @@ class ChartCurrencyTest extends TestCase 'user_id' => $this->user->id, 'company_id' => $company->id, 'settings' => $settings, + 'balance' => 0, + 'paid_to_date' => 0, ]); - $i1 = Invoice::factory()->create([ 'client_id' => $usd->id, 'user_id' => $this->user->id, @@ -96,7 +100,18 @@ class ChartCurrencyTest extends TestCase 'paid_to_date' => 0, 'status_id' => 2, 'date' => now(), - 'due_date' => now() + 'due_date' => now(), + 'line_items' => [ + [ + 'product_key' => 'product_1', + 'quantity' => 1, + 'cost' => 100, + ] + ], + 'tax_rate1' => 0, + 'tax_rate2' => 0, + 'tax_rate3' => 0, +'discount' => 0, ]); $i2 = Invoice::factory()->create([ @@ -108,19 +123,37 @@ class ChartCurrencyTest extends TestCase 'paid_to_date' => 0, 'status_id' => 2, 'date' => now(), - 'due_date' => now() + 'due_date' => now(), + 'line_items' => [ + [ + 'product_key' => 'product_1', + 'quantity' => 1, + 'cost' => 100, + ] + ], + 'tax_rate1' => 0, + 'tax_rate2' => 0, + 'tax_rate3' => 0, +'discount' => 0, ]); + $repo = new InvoiceRepository(); + $i1 = $repo->save([], $i1); + $i2 = $repo->save([], $i2); + $i1->service()->markPaid()->save(); $i2->service()->markPaid()->save(); + +$this->assertEquals(100, $i1->amount); +$this->assertEquals(100, $i2->amount); + $cs = new ChartService($company, $this->user, true); $results = $cs->totals('1970-01-01', '2050-01-01'); + nlog($results); $this->assertCount(2, $results['currencies']); - // nlog($results); - $this->assertEquals('USD', $results['currencies'][1]); $this->assertEquals('GBP', $results['currencies'][2]); diff --git a/tests/Unit/CompanyDocumentsTest.php b/tests/Unit/CompanyDocumentsTest.php index 317eaed54a..34e835b90f 100644 --- a/tests/Unit/CompanyDocumentsTest.php +++ b/tests/Unit/CompanyDocumentsTest.php @@ -23,7 +23,7 @@ use Tests\TestCase; class CompanyDocumentsTest extends TestCase { use MockAccountData; - use DatabaseTransactions; + // use DatabaseTransactions; protected function setUp(): void { diff --git a/tests/Unit/EInvoiceTest.php b/tests/Unit/EInvoiceTest.php index 88715bb061..95b7ef984b 100644 --- a/tests/Unit/EInvoiceTest.php +++ b/tests/Unit/EInvoiceTest.php @@ -29,7 +29,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class EInvoiceTest extends TestCase { use MockAccountData; - use DatabaseTransactions; + // use DatabaseTransactions; protected function setUp(): void { diff --git a/tests/Unit/EntityTest.php b/tests/Unit/EntityTest.php index 448a4c464d..5cebbf190f 100644 --- a/tests/Unit/EntityTest.php +++ b/tests/Unit/EntityTest.php @@ -34,7 +34,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class EntityTest extends TestCase { use MockAccountData; - use DatabaseTransactions; + // use DatabaseTransactions; public $invoice; diff --git a/tests/Unit/FactoryCreationTest.php b/tests/Unit/FactoryCreationTest.php index 11d301037b..9ed6933fe3 100644 --- a/tests/Unit/FactoryCreationTest.php +++ b/tests/Unit/FactoryCreationTest.php @@ -30,7 +30,7 @@ use Tests\TestCase; class FactoryCreationTest extends TestCase { use MakesHash; - use DatabaseTransactions; + // use DatabaseTransactions; use MockAccountData; protected function setUp(): void diff --git a/tests/Unit/GeneratesCounterTest.php b/tests/Unit/GeneratesCounterTest.php index 27fcd167dd..28d904a1de 100644 --- a/tests/Unit/GeneratesCounterTest.php +++ b/tests/Unit/GeneratesCounterTest.php @@ -39,7 +39,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class GeneratesCounterTest extends TestCase { use GeneratesCounter; - use DatabaseTransactions; + // use DatabaseTransactions; use MakesHash; use MockAccountData; diff --git a/tests/_bootstrap.php b/tests/_bootstrap.php index a631610f58..b3d9bbc7f3 100644 --- a/tests/_bootstrap.php +++ b/tests/_bootstrap.php @@ -1,12 +1 @@ Date: Fri, 15 Aug 2025 10:02:15 +1000 Subject: [PATCH 02/14] Updates for tests --- app/Providers/StaticServiceProvider.php | 1 - tests/MockAccountData.php | 84 +++++++++++++------------ tests/Unit/AutoBillInvoiceTest.php | 4 +- tests/Unit/Chart/ChartCurrencyTest.php | 12 ++-- tests/Unit/CompanyDocumentsTest.php | 2 +- tests/Unit/EntityTest.php | 13 +--- tests/Unit/GeneratesCounterTest.php | 13 ++-- 7 files changed, 62 insertions(+), 67 deletions(-) diff --git a/app/Providers/StaticServiceProvider.php b/app/Providers/StaticServiceProvider.php index d82675fcaa..07677af7d4 100644 --- a/app/Providers/StaticServiceProvider.php +++ b/app/Providers/StaticServiceProvider.php @@ -263,7 +263,6 @@ class StaticServiceProvider extends ServiceProvider }); - nlog("static service provider registered"); } public function boot() diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index b2cf963e09..6613650998 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -67,6 +67,7 @@ use App\DataMapper\ClientRegistrationFields; use App\Jobs\Company\CreateCompanyTaskStatuses; use App\Repositories\RecurringInvoiceRepository; use App\Factory\InvoiceToRecurringInvoiceFactory; +use App\Repositories\CreditRepository; /** * Class MockAccountData. @@ -211,18 +212,14 @@ trait MockAccountData Artisan::call('db:seed', ['--force' => true]); } - app()->singleton('currencies', function ($app) { $resource = Currency::query()->orderBy('name')->get(); - Cache::forever('currencies', $resource); - return $resource; }); - $this->faker = \Faker\Factory::create(); $fake_email = $this->faker->email(); @@ -566,27 +563,30 @@ trait MockAccountData $this->credit->number = $this->getNextCreditNumber($this->client, $this->credit); - CreditInvitation::factory()->create([ - 'user_id' => $user_id, - 'company_id' => $this->company->id, - 'client_contact_id' => $contact->id, - 'credit_id' => $this->credit->id, - ]); + // CreditInvitation::factory()->create([ + // 'user_id' => $user_id, + // 'company_id' => $this->company->id, + // 'client_contact_id' => $contact->id, + // 'credit_id' => $this->credit->id, + // ]); - CreditInvitation::factory()->create([ - 'user_id' => $user_id, - 'company_id' => $this->company->id, - 'client_contact_id' => $contact2->id, - 'credit_id' => $this->credit->id, - ]); + // CreditInvitation::factory()->create([ + // 'user_id' => $user_id, + // 'company_id' => $this->company->id, + // 'client_contact_id' => $contact2->id, + // 'credit_id' => $this->credit->id, + // ]); - $this->credit->setRelation('client', $this->client); - $this->credit->setRelation('company', $this->company); + // $this->credit->setRelation('client', $this->client); + // $this->credit->setRelation('company', $this->company); - $this->credit->save(); + // $this->credit->save(); - $this->credit->service()->createInvitations()->markSent(); + $repo = new CreditRepository(); + $repo->save([], $this->credit); + // $this->credit->service()->createInvitations()->markSent(); + // $this->credit->save(); $this->purchase_order = PurchaseOrderFactory::create($this->company->id, $user_id); $this->purchase_order->vendor_id = $this->vendor->id; @@ -650,19 +650,25 @@ trait MockAccountData $this->credit->ledger()->updateCreditBalance($this->credit->balance)->save(); $this->credit->number = $this->getNextCreditNumber($this->client, $this->credit); - CreditInvitation::factory()->create([ - 'user_id' => $user_id, - 'company_id' => $this->company->id, - 'client_contact_id' => $contact->id, - 'credit_id' => $this->credit->id, - ]); + $this->credit->save(); - CreditInvitation::factory()->create([ - 'user_id' => $user_id, - 'company_id' => $this->company->id, - 'client_contact_id' => $contact2->id, - 'credit_id' => $this->credit->id, - ]); + + $repo = new CreditRepository(); + $repo->save([], $this->credit); + + // CreditInvitation::factory()->create([ + // 'user_id' => $user_id, + // 'company_id' => $this->company->id, + // 'client_contact_id' => $contact->id, + // 'credit_id' => $this->credit->id, + // ]); + + // CreditInvitation::factory()->create([ + // 'user_id' => $user_id, + // 'company_id' => $this->company->id, + // 'client_contact_id' => $contact2->id, + // 'credit_id' => $this->credit->id, + // ]); $this->bank_integration = BankIntegration::factory()->create([ 'user_id' => $user_id, @@ -705,17 +711,17 @@ trait MockAccountData 'company_id' => $this->company->id, ]); - $invitations = CreditInvitation::whereCompanyId($this->credit->company_id) - ->whereCreditId($this->credit->id); + // $invitations = CreditInvitation::whereCompanyId($this->credit->company_id) + // ->whereCreditId($this->credit->id); - $this->credit->setRelation('invitations', $invitations); + // $this->credit->setRelation('invitations', $invitations); - $this->credit->service()->markSent(); + // $this->credit->service()->markSent(); - $this->credit->setRelation('client', $this->client); - $this->credit->setRelation('company', $this->company); + // $this->credit->setRelation('client', $this->client); + // $this->credit->setRelation('company', $this->company); - $this->credit->save(); + // $this->credit->save(); $contacts = $this->invoice->client->contacts; diff --git a/tests/Unit/AutoBillInvoiceTest.php b/tests/Unit/AutoBillInvoiceTest.php index 96c27c88ce..d45554e8ef 100644 --- a/tests/Unit/AutoBillInvoiceTest.php +++ b/tests/Unit/AutoBillInvoiceTest.php @@ -22,7 +22,7 @@ use Illuminate\Support\Facades\Artisan; */ class AutoBillInvoiceTest extends TestCase { - // use DatabaseTransactions; + use DatabaseTransactions; use MockAccountData; protected function setUp(): void @@ -30,12 +30,10 @@ class AutoBillInvoiceTest extends TestCase parent::setUp(); $this->makeTestData(); - } public function testAutoBillFunctionality() { - $this->assertEquals('1', $this->client->settings->currency_id); $this->assertEquals($this->client->balance, 10); $this->assertEquals($this->client->paid_to_date, 0); $this->assertEquals($this->client->credit_balance, 10); diff --git a/tests/Unit/Chart/ChartCurrencyTest.php b/tests/Unit/Chart/ChartCurrencyTest.php index 359b790ce7..d3aa9cc381 100644 --- a/tests/Unit/Chart/ChartCurrencyTest.php +++ b/tests/Unit/Chart/ChartCurrencyTest.php @@ -31,7 +31,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class ChartCurrencyTest extends TestCase { use MockAccountData; - // use DatabaseTransactions; + use DatabaseTransactions; protected function setUp(): void { @@ -111,7 +111,7 @@ class ChartCurrencyTest extends TestCase 'tax_rate1' => 0, 'tax_rate2' => 0, 'tax_rate3' => 0, -'discount' => 0, + 'discount' => 0, ]); $i2 = Invoice::factory()->create([ @@ -134,7 +134,7 @@ class ChartCurrencyTest extends TestCase 'tax_rate1' => 0, 'tax_rate2' => 0, 'tax_rate3' => 0, -'discount' => 0, + 'discount' => 0, ]); $repo = new InvoiceRepository(); @@ -144,14 +144,12 @@ class ChartCurrencyTest extends TestCase $i1->service()->markPaid()->save(); $i2->service()->markPaid()->save(); - -$this->assertEquals(100, $i1->amount); -$this->assertEquals(100, $i2->amount); + $this->assertEquals(100, $i1->amount); + $this->assertEquals(100, $i2->amount); $cs = new ChartService($company, $this->user, true); $results = $cs->totals('1970-01-01', '2050-01-01'); - nlog($results); $this->assertCount(2, $results['currencies']); $this->assertEquals('USD', $results['currencies'][1]); diff --git a/tests/Unit/CompanyDocumentsTest.php b/tests/Unit/CompanyDocumentsTest.php index 34e835b90f..317eaed54a 100644 --- a/tests/Unit/CompanyDocumentsTest.php +++ b/tests/Unit/CompanyDocumentsTest.php @@ -23,7 +23,7 @@ use Tests\TestCase; class CompanyDocumentsTest extends TestCase { use MockAccountData; - // use DatabaseTransactions; + use DatabaseTransactions; protected function setUp(): void { diff --git a/tests/Unit/EntityTest.php b/tests/Unit/EntityTest.php index 5cebbf190f..aeb182055e 100644 --- a/tests/Unit/EntityTest.php +++ b/tests/Unit/EntityTest.php @@ -34,7 +34,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class EntityTest extends TestCase { use MockAccountData; - // use DatabaseTransactions; + use DatabaseTransactions; public $invoice; @@ -89,17 +89,6 @@ class EntityTest extends TestCase protected function tearDown(): void { - - - // $this->company->company_users->each(function ($company_user) { - // $company_user->user->forceDelete(); - // $company_user->forceDelete(); - // }); - - // // Clean up any resources or reset state if necessary - // $this->account->delete(); - - parent::tearDown(); } } diff --git a/tests/Unit/GeneratesCounterTest.php b/tests/Unit/GeneratesCounterTest.php index 28d904a1de..5b0cad3920 100644 --- a/tests/Unit/GeneratesCounterTest.php +++ b/tests/Unit/GeneratesCounterTest.php @@ -422,13 +422,16 @@ class GeneratesCounterTest extends TestCase public function testInvoiceNumberValue() { - $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); - $this->assertEquals($invoice_number, '0002'); + $this->assertEquals('0002', $this->invoice->fresh()->number); $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); $this->assertEquals($invoice_number, '0003'); + + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + + $this->assertEquals($invoice_number, '0004'); } public function testQuoteNumberValue() @@ -605,11 +608,13 @@ class GeneratesCounterTest extends TestCase $invoice_number = $this->getNextInvoiceNumber($cliz->fresh(), $this->invoice); - $this->assertEquals($invoice_number, '0002'); + $this->assertEquals('0002', $this->invoice->fresh()->number); + + $this->assertEquals('0003', $invoice_number); $invoice_number = $this->getNextInvoiceNumber($cliz->fresh(), $this->invoice); - $this->assertEquals($invoice_number, '0003'); + $this->assertEquals('0004', $invoice_number ); } public function testClientNumber() From d5a7cab86c08c4fb247abe59dcd9d660d2ddfd12 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 10:21:54 +1000 Subject: [PATCH 03/14] Updates for tests --- tests/Feature/EInvoice/PeppolApiTest.php | 2 +- tests/Feature/EInvoice/PeppolTest.php | 2 +- tests/Feature/ProjectApiTest.php | 2 +- tests/Unit/CloneQuoteToInvoiceFactoryTest.php | 5 +- tests/Unit/EInvoiceTest.php | 3 +- tests/Unit/FactoryCreationTest.php | 2 +- tests/Unit/GeneratesCounterTest.php | 2 +- tests/Unit/InvitationTest.php | 20 ++-- tests/Unit/InvoiceMarkPaidTest.php | 112 ++++++++++++++++-- tests/Unit/LateFeeTest.php | 7 +- 10 files changed, 127 insertions(+), 30 deletions(-) diff --git a/tests/Feature/EInvoice/PeppolApiTest.php b/tests/Feature/EInvoice/PeppolApiTest.php index 516229023d..2e1da3405d 100644 --- a/tests/Feature/EInvoice/PeppolApiTest.php +++ b/tests/Feature/EInvoice/PeppolApiTest.php @@ -22,7 +22,7 @@ use Tests\TestCase; */ class PeppolApiTest extends TestCase { - // use DatabaseTransactions; + use DatabaseTransactions; use MockAccountData; protected function setUp(): void diff --git a/tests/Feature/EInvoice/PeppolTest.php b/tests/Feature/EInvoice/PeppolTest.php index f5fdc95c06..475eb2d83f 100644 --- a/tests/Feature/EInvoice/PeppolTest.php +++ b/tests/Feature/EInvoice/PeppolTest.php @@ -42,7 +42,7 @@ use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronicaHeaderType\FatturaE class PeppolTest extends TestCase { - // use DatabaseTransactions; + use DatabaseTransactions; use MockAccountData; protected int $iterations = 10; diff --git a/tests/Feature/ProjectApiTest.php b/tests/Feature/ProjectApiTest.php index afda82037a..d1c064b232 100644 --- a/tests/Feature/ProjectApiTest.php +++ b/tests/Feature/ProjectApiTest.php @@ -32,7 +32,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class ProjectApiTest extends TestCase { use MakesHash; - // use DatabaseTransactions; + use DatabaseTransactions; use MockAccountData; protected $faker; diff --git a/tests/Unit/CloneQuoteToInvoiceFactoryTest.php b/tests/Unit/CloneQuoteToInvoiceFactoryTest.php index 698f3e8780..93a42a7720 100644 --- a/tests/Unit/CloneQuoteToInvoiceFactoryTest.php +++ b/tests/Unit/CloneQuoteToInvoiceFactoryTest.php @@ -17,6 +17,7 @@ use Tests\MockAccountData; use App\Factory\InvoiceItemFactory; use App\Factory\CloneQuoteToInvoiceFactory; use Illuminate\Foundation\Testing\DatabaseTransactions; +use Illuminate\Database\Eloquent\Model; /** * @@ -24,13 +25,15 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class CloneQuoteToInvoiceFactoryTest extends TestCase { use MockAccountData; - // use DatabaseTransactions; + use DatabaseTransactions; protected function setUp(): void { parent::setUp(); $this->makeTestData(); + + Model::reguard(); } public function testCloneItemSanityInvoice() diff --git a/tests/Unit/EInvoiceTest.php b/tests/Unit/EInvoiceTest.php index 95b7ef984b..5ad45381d6 100644 --- a/tests/Unit/EInvoiceTest.php +++ b/tests/Unit/EInvoiceTest.php @@ -29,7 +29,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class EInvoiceTest extends TestCase { use MockAccountData; - // use DatabaseTransactions; + use DatabaseTransactions; protected function setUp(): void { @@ -74,7 +74,6 @@ class EInvoiceTest extends TestCase $data = $this->getExpiredPurchases([$company->company_key], true); - $this->assertEquals(100, $data['purchased']); $this->assertEquals(-50, $data['sent'] + $data['received']); diff --git a/tests/Unit/FactoryCreationTest.php b/tests/Unit/FactoryCreationTest.php index 9ed6933fe3..11d301037b 100644 --- a/tests/Unit/FactoryCreationTest.php +++ b/tests/Unit/FactoryCreationTest.php @@ -30,7 +30,7 @@ use Tests\TestCase; class FactoryCreationTest extends TestCase { use MakesHash; - // use DatabaseTransactions; + use DatabaseTransactions; use MockAccountData; protected function setUp(): void diff --git a/tests/Unit/GeneratesCounterTest.php b/tests/Unit/GeneratesCounterTest.php index 5b0cad3920..5746362ada 100644 --- a/tests/Unit/GeneratesCounterTest.php +++ b/tests/Unit/GeneratesCounterTest.php @@ -39,7 +39,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; class GeneratesCounterTest extends TestCase { use GeneratesCounter; - // use DatabaseTransactions; + use DatabaseTransactions; use MakesHash; use MockAccountData; diff --git a/tests/Unit/InvitationTest.php b/tests/Unit/InvitationTest.php index 7aa231c363..d342b1f5b3 100644 --- a/tests/Unit/InvitationTest.php +++ b/tests/Unit/InvitationTest.php @@ -11,18 +11,20 @@ namespace Tests\Unit; -use App\Factory\InvoiceInvitationFactory; -use App\Utils\Traits\MakesHash; -use Illuminate\Foundation\Testing\DatabaseTransactions; -use Illuminate\Routing\Middleware\ThrottleRequests; -use Illuminate\Validation\ValidationException; -use Tests\MockAccountData; use Tests\TestCase; +use Tests\MockAccountData; +use App\Utils\Traits\MakesHash; +use Illuminate\Database\Eloquent\Model; +use App\Factory\InvoiceInvitationFactory; +use Illuminate\Validation\ValidationException; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Foundation\Testing\DatabaseTransactions; + class InvitationTest extends TestCase { use MockAccountData; - // use DatabaseTransactions; + use DatabaseTransactions; use MakesHash; protected function setUp(): void @@ -36,6 +38,8 @@ class InvitationTest extends TestCase ); $this->withoutExceptionHandling(); + + Model::reguard(); } public function testInvitationSanity() @@ -63,7 +67,7 @@ class InvitationTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->putJson('/api/v1/invoices/'.$this->invoice->hashed_id, $this->invoice->toArray()); + ])->putJson('/api/v1/invoices/'.$this->invoice->hashed_id, $data); $response->assertStatus(200); diff --git a/tests/Unit/InvoiceMarkPaidTest.php b/tests/Unit/InvoiceMarkPaidTest.php index f28d9b9f88..3fb9629129 100644 --- a/tests/Unit/InvoiceMarkPaidTest.php +++ b/tests/Unit/InvoiceMarkPaidTest.php @@ -11,36 +11,114 @@ namespace Tests\Unit; -use App\DataMapper\InvoiceItem; -use App\Factory\InvoiceFactory; -use App\Factory\InvoiceItemFactory; -use App\Helpers\Invoice\InvoiceSum; -use App\Helpers\Invoice\InvoiceSumInclusive; +use Tests\TestCase; +use App\Models\User; +use App\Models\Account; +use App\Models\Company; use App\Models\Invoice; use App\Models\Payment; -use App\Repositories\InvoiceRepository; -use Illuminate\Foundation\Testing\DatabaseTransactions; use Tests\MockAccountData; -use Tests\TestCase; +use App\Models\CompanyToken; +use App\DataMapper\InvoiceItem; +use App\Factory\InvoiceFactory; +use App\DataMapper\CompanySettings; +use App\Factory\CompanyUserFactory; +use App\Factory\InvoiceItemFactory; +use App\Helpers\Invoice\InvoiceSum; +use App\Repositories\InvoiceRepository; +use Illuminate\Database\Eloquent\Model; +use App\Helpers\Invoice\InvoiceSumInclusive; +use Illuminate\Foundation\Testing\DatabaseTransactions; class InvoiceMarkPaidTest extends TestCase { use MockAccountData; - // use DatabaseTransactions; + use DatabaseTransactions; public $invoice; + public $company; + + public $user; + + public $payload; + + public $account; + + public $client; + + public $token; + + public $cu; + public $faker; public function setUp(): void { parent::setUp(); - $this->makeTestData(); + // $this->makeTestData(); + + $this->faker = \Faker\Factory::create(); + + Model::reguard(); + } + + private function buildData() + { + if($this->account) + $this->account->forceDelete(); + + /** @var \App\Models\Account $account */ + $this->account = Account::factory()->create([ + 'hosted_client_count' => 1000, + 'hosted_company_count' => 1000, + ]); + + $this->account->num_users = 3; + $this->account->save(); + + $this->user = User::factory()->create([ + 'account_id' => $this->account->id, + 'confirmation_code' => 'xyz123', + 'email' => $this->faker->unique()->safeEmail(), + ]); + + $settings = CompanySettings::defaults(); + $settings->client_online_payment_notification = false; + $settings->client_manual_payment_notification = false; + + $this->company = Company::factory()->create([ + 'account_id' => $this->account->id, + 'settings' => $settings, + ]); + + $this->company->settings = $settings; + $this->company->save(); + + $this->cu = CompanyUserFactory::create($this->user->id, $this->company->id, $this->account->id); + $this->cu->is_owner = true; + $this->cu->is_admin = true; + $this->cu->is_locked = false; + $this->cu->save(); + + $this->token = \Illuminate\Support\Str::random(64); + + $company_token = new CompanyToken(); + $company_token->user_id = $this->user->id; + $company_token->company_id = $this->company->id; + $company_token->account_id = $this->account->id; + $company_token->name = 'test token'; + $company_token->token = $this->token; + $company_token->is_system = true; + + $company_token->save(); + } public function testInvoiceMarkPaidFromDraft() { - + $this->buildData(); + $c = \App\Models\Client::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, @@ -75,6 +153,9 @@ class InvoiceMarkPaidTest extends TestCase $i->calc()->getInvoice(); + $repo = new InvoiceRepository(); + $repo->save([], $i); + $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, @@ -92,8 +173,7 @@ class InvoiceMarkPaidTest extends TestCase $this->assertEquals(10, $i->paid_to_date); $this->assertEquals(4, $i->status_id); - - $c->forceDelete(); +$this->account->delete(); } @@ -101,6 +181,7 @@ class InvoiceMarkPaidTest extends TestCase public function testInvoiceMarkPaidFromDraftBulk() { + $this->buildData(); $c = \App\Models\Client::factory()->create([ 'user_id' => $this->user->id, @@ -137,6 +218,9 @@ class InvoiceMarkPaidTest extends TestCase $i->calc()->getInvoice(); + $repo = new InvoiceRepository(); + $repo->save([], $i); + $data = [ 'action' => 'mark_paid', 'ids' => [$i->hashed_id] @@ -161,6 +245,8 @@ class InvoiceMarkPaidTest extends TestCase $c->forceDelete(); + + $this->account->delete(); } } diff --git a/tests/Unit/LateFeeTest.php b/tests/Unit/LateFeeTest.php index 68cfbe4edc..534f7d7bd9 100644 --- a/tests/Unit/LateFeeTest.php +++ b/tests/Unit/LateFeeTest.php @@ -370,7 +370,12 @@ class LateFeeTest extends TestCase $this->assertEquals(2, count($i->line_items)); - $i->service()->autoBill(); + try{ + $i->service()->autoBill(); + } + catch(\Exception $e){ + nlog($e->getMessage()); + } $i = $i->fresh(); From a89e51ebdcfda39306121f1ed2654c9c3d44cbb5 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 10:37:42 +1000 Subject: [PATCH 04/14] Static analysis and cleanup for tests --- .../Controllers/ProtectedDownloadController.php | 3 ++- .../ConnectNordigenBankIntegrationRequest.php | 1 + .../TaskScheduler/PaymentScheduleRequest.php | 1 + .../Invoice/InvoiceTransactionEventEntry.php | 2 +- app/Models/Account.php | 1 + app/Models/Client.php | 3 +++ app/Models/Company.php | 1 + app/Models/Design.php | 1 + app/Models/Expense.php | 5 +++-- app/Models/Project.php | 1 + app/Models/PurchaseOrder.php | 2 ++ app/Models/Subscription.php | 1 + app/Models/Vendor.php | 1 + tests/Feature/Export/ReportCsvGenerationTest.php | 15 +++++++++++++++ tests/Feature/UpdateExchangeRatesTest.php | 4 +--- 15 files changed, 35 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/ProtectedDownloadController.php b/app/Http/Controllers/ProtectedDownloadController.php index 9c0e6de972..4a3a866b2c 100644 --- a/app/Http/Controllers/ProtectedDownloadController.php +++ b/app/Http/Controllers/ProtectedDownloadController.php @@ -39,7 +39,8 @@ class ProtectedDownloadController extends BaseController return response()->streamDownload(function () use ($hashed_path) { $stream = Storage::readStream($hashed_path); - if ($stream === false) { + // if($stream ===false){ + if ($stream === null) { throw new SystemError('Unable to read file', 500); } diff --git a/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php b/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php index 78f02caf7c..aa5892dc2d 100644 --- a/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php +++ b/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php @@ -60,6 +60,7 @@ class ConnectNordigenBankIntegrationRequest extends Request /** * @return array{ * user_id: int, + * bank_account_id?: string, * company_key: string, * context: string, * is_react: bool, diff --git a/app/Http/Requests/TaskScheduler/PaymentScheduleRequest.php b/app/Http/Requests/TaskScheduler/PaymentScheduleRequest.php index f0da846f2a..1d8790bdea 100644 --- a/app/Http/Requests/TaskScheduler/PaymentScheduleRequest.php +++ b/app/Http/Requests/TaskScheduler/PaymentScheduleRequest.php @@ -150,6 +150,7 @@ class PaymentScheduleRequest extends Request RecurringInvoice::FREQUENCY_ANNUALLY => $date->startOfDay()->addYear(), RecurringInvoice::FREQUENCY_TWO_YEARS => $date->startOfDay()->addYears(2), RecurringInvoice::FREQUENCY_THREE_YEARS => $date->startOfDay()->addYears(3), + default => $date->startOfDay()->addMonthNoOverflow(), }; } } diff --git a/app/Listeners/Invoice/InvoiceTransactionEventEntry.php b/app/Listeners/Invoice/InvoiceTransactionEventEntry.php index 4814ec5397..7a4ea68af5 100644 --- a/app/Listeners/Invoice/InvoiceTransactionEventEntry.php +++ b/app/Listeners/Invoice/InvoiceTransactionEventEntry.php @@ -118,7 +118,7 @@ class InvoiceTransactionEventEntry return new TransactionEventMetadata([ 'tax_report' => [ 'tax_details' => $details, - 'payment_history' => $this->payments->toArray() ?? [], + 'payment_history' => $this->payments->toArray() ?? [], //@phpstan-ignore-line 'tax_summary' => [ 'total_taxes' => $invoice->total_taxes, 'total_paid' => $this->getTotalTaxPaid($invoice), diff --git a/app/Models/Account.php b/app/Models/Account.php index 7a67967b61..261caba6d8 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -75,6 +75,7 @@ use Laracasts\Presenter\PresentableTrait; * @property bool $is_trial * @property int $e_invoice_quota * @property int $docuninja_num_users + * @property string|null $e_invoicing_token * @property-read int|null $bank_integrations_count * @property-read int|null $companies_count * @property-read int|null $company_users_count diff --git a/app/Models/Client.php b/app/Models/Client.php index 8ba23516f6..1cdec93974 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -87,6 +87,9 @@ use Illuminate\Contracts\Translation\HasLocalePreference; * @property-read \App\Models\User $user * @property-read \App\Models\Company $company * @property-read \App\Models\Country|null $country + * @property-read \App\Models\Industry|null $industry + * @property-read \App\Models\Country|null $shipping_country + * @property-read \App\Models\Size|null $size * @property-read \Illuminate\Database\Eloquent\Collection $activities * @property-read \Illuminate\Database\Eloquent\Collection $company_ledger * @property-read \Illuminate\Database\Eloquent\Collection $contacts diff --git a/app/Models/Company.php b/app/Models/Company.php index 93445dd034..dcefe8aa30 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -123,6 +123,7 @@ use Laracasts\Presenter\PresentableTrait; * @property string|null $inbound_mailbox_blacklist * @property string|null $e_invoice_certificate_passphrase * @property string|null $e_invoice_certificate + * @property object|null $origin_tax_data * @property int $deleted_at * @property string|null $smtp_username * @property string|null $smtp_password diff --git a/app/Models/Design.php b/app/Models/Design.php index a60a5f8404..e07ab1a01e 100644 --- a/app/Models/Design.php +++ b/app/Models/Design.php @@ -30,6 +30,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property int|null $created_at * @property int|null $updated_at * @property int|null $deleted_at + * @property string|null $entities * @property-read \App\Models\Company|null $company * @property-read string $hashed_id * @method static \Illuminate\Database\Eloquent\Builder|BaseModel company() diff --git a/app/Models/Expense.php b/app/Models/Expense.php index 6f27da21d9..a0923ff3db 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -66,19 +66,20 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property float $tax_amount3 * @property bool $uses_inclusive_taxes * @property bool $calculate_tax_by_amount + * @property-read int|null $documents_count + * @property-read mixed $hashed_id * @property-read \App\Models\User|null $assigned_user * @property-read \App\Models\ExpenseCategory|null $category * @property-read \App\Models\Client|null $client * @property-read \App\Models\Company $company * @property-read \App\Models\Currency|null $currency * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read int|null $documents_count - * @property-read mixed $hashed_id * @property-read \App\Models\PaymentType|null $payment_type * @property-read \App\Models\Project|null $project * @property-read \App\Models\PurchaseOrder|null $purchase_order * @property-read \App\Models\User $user * @property-read \App\Models\Vendor|null $vendor + * @property-read \App\Models\Currency|null $invoice_currency * @method static \Illuminate\Database\Eloquent\Builder|BaseModel company() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns) * @method static \Database\Factories\ExpenseFactory factory($count = null, $state = []) diff --git a/app/Models/Project.php b/app/Models/Project.php index 7005919339..c06b3de4dd 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -34,6 +34,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; * @property bool $is_deleted * @property string|null $number * @property string $color + * @property int|null $current_hours * @property-read \App\Models\Client|null $client * @property-read \App\Models\Company $company * @property-read int|null $documents_count diff --git a/app/Models/PurchaseOrder.php b/app/Models/PurchaseOrder.php index a93b1cf4f0..7683ce23f8 100644 --- a/app/Models/PurchaseOrder.php +++ b/app/Models/PurchaseOrder.php @@ -101,6 +101,8 @@ use App\Events\PurchaseOrder\PurchaseOrderWasEmailed; * @property \App\Models\User $user * @property \App\Models\Vendor $vendor * @property \App\Models\PurchaseOrderInvitation $invitation + * @property \App\Models\Currency|null $currency + * @property \App\Models\Location|null $location * @method static \Illuminate\Database\Eloquent\Builder|PurchaseOrder exclude($columns) * @method static \Database\Factories\PurchaseOrderFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|PurchaseOrder filter(\App\Filters\QueryFilters $filters) diff --git a/app/Models/Subscription.php b/app/Models/Subscription.php index 1d154b87cc..6df86256f0 100644 --- a/app/Models/Subscription.php +++ b/app/Models/Subscription.php @@ -56,6 +56,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property float $promo_price * @property int $registration_required * @property int $use_inventory_management + * @property string|null $steps * @property string|null $optional_product_ids * @property string|null $optional_recurring_product_ids * @property-read \App\Models\Company $company diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index 0a5c790277..8c34c18f23 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -59,6 +59,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property int|null $language_id * @property int|null $last_login * @property bool $is_tax_exempt + * @property string|null $classification * @property-read \Illuminate\Database\Eloquent\Collection $activities * @property-read int|null $activities_count * @property-read \App\Models\Language|null $language diff --git a/tests/Feature/Export/ReportCsvGenerationTest.php b/tests/Feature/Export/ReportCsvGenerationTest.php index b403498121..2d659819a7 100644 --- a/tests/Feature/Export/ReportCsvGenerationTest.php +++ b/tests/Feature/Export/ReportCsvGenerationTest.php @@ -650,6 +650,21 @@ $this->account->forceDelete(); 'public_notes' => 'Public5', 'private_notes' => 'Private5', 'terms' => 'Terms5', + 'tax_rate1' => 0, + 'tax_rate2' => 0, + 'tax_rate3' => 0, + 'discount' => 0, + 'line_items' => [ + [ + 'quantity' => 1, + 'product_key' => 'product_key', + 'notes' => 'notes', + 'cost' => 1000, + 'custom_value1' => 'Custom 1', + 'custom_value2' => 'Custom 2', + 'custom_value3' => 'Custom 3', + ] + ] ]); diff --git a/tests/Feature/UpdateExchangeRatesTest.php b/tests/Feature/UpdateExchangeRatesTest.php index deed4825df..283b201f2a 100644 --- a/tests/Feature/UpdateExchangeRatesTest.php +++ b/tests/Feature/UpdateExchangeRatesTest.php @@ -50,9 +50,7 @@ class UpdateExchangeRatesTest extends TestCase UpdateExchangeRates::dispatchSync(); - $gbp_currency = app('currencies')->first(function ($item) { - return $item->id == 2; - }); + $gbp_currency = \App\Models\Currency::find(2); $this->assertEquals($currency_api->rates->GBP, $gbp_currency->exchange_rate); From 2438bf92842ca41f6eeb0d99fda51705316e114d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 10:44:19 +1000 Subject: [PATCH 05/14] Fixes for tests --- .../Export/ReportCsvGenerationTest.php | 32 +++++++++++++++++-- tests/Unit/LateFeeTest.php | 12 +++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/tests/Feature/Export/ReportCsvGenerationTest.php b/tests/Feature/Export/ReportCsvGenerationTest.php index 2d659819a7..be3202c8a0 100644 --- a/tests/Feature/Export/ReportCsvGenerationTest.php +++ b/tests/Feature/Export/ReportCsvGenerationTest.php @@ -920,11 +920,25 @@ $this->account->forceDelete(); 'balance' => 100, 'number' => '12345', 'status_id' => 2, - 'discount' => 10, + 'discount' => 0, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', + 'tax_rate1' => 0, + 'tax_rate2' => 0, + 'tax_rate3' => 0, + 'line_items' => [ + [ + 'quantity' => 1, + 'product_key' => 'product_key', + 'notes' => 'notes', + 'cost' => 100, + 'custom_value1' => 'Custom 1', + 'custom_value2' => 'Custom 2', + 'custom_value3' => 'Custom 3', + ] + ] ]); $invoice->client->balance = 100; @@ -1284,6 +1298,20 @@ $this->account->forceDelete(); 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', + 'tax_rate1' => 0, + 'tax_rate2' => 0, + 'tax_rate3' => 0, + 'line_items' => [ + [ + 'quantity' => 1, + 'product_key' => 'product_key', + 'notes' => 'notes', + 'cost' => 100, + 'custom_value1' => 'Custom 1', + 'custom_value2' => 'Custom 2', + 'custom_value3' => 'Custom 3', + ] + ] ]); $repo = new InvoiceRepository(); @@ -1455,7 +1483,7 @@ $this->account->forceDelete(); 'balance' => 50, 'number' => '1234', 'status_id' => 2, - 'discount' => 10, + 'discount' => 0, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', diff --git a/tests/Unit/LateFeeTest.php b/tests/Unit/LateFeeTest.php index 534f7d7bd9..7ae014bbd0 100644 --- a/tests/Unit/LateFeeTest.php +++ b/tests/Unit/LateFeeTest.php @@ -53,7 +53,7 @@ class LateFeeTest extends TestCase $this->makeTestData(); - $this->withoutExceptionHandling(); + // $this->withoutExceptionHandling(); } @@ -370,12 +370,12 @@ class LateFeeTest extends TestCase $this->assertEquals(2, count($i->line_items)); - try{ + // try{ $i->service()->autoBill(); - } - catch(\Exception $e){ - nlog($e->getMessage()); - } + // } + // catch(\Exception $e){ + // nlog($e->getMessage()); + // } $i = $i->fresh(); From 7573c611cf85abaa45ff87b091574cd83a963a04 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 10:57:35 +1000 Subject: [PATCH 06/14] check vat number prior to validation --- app/Services/Tax/TaxService.php | 2 +- app/Services/Tax/VatNumberCheck.php | 7 +- .../Export/ReportCsvGenerationTest.php | 73 ++++++++++++------- 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/app/Services/Tax/TaxService.php b/app/Services/Tax/TaxService.php index 960fc58147..a22bb85df3 100644 --- a/app/Services/Tax/TaxService.php +++ b/app/Services/Tax/TaxService.php @@ -31,7 +31,7 @@ class TaxService $vat_check = (new VatNumberCheck($this->client->vat_number, $client_country_code))->run(); - nlog($vat_check); + // nlog($vat_check); if ($vat_check->isValid()) { diff --git a/app/Services/Tax/VatNumberCheck.php b/app/Services/Tax/VatNumberCheck.php index 36d77de502..93f1a931aa 100644 --- a/app/Services/Tax/VatNumberCheck.php +++ b/app/Services/Tax/VatNumberCheck.php @@ -22,7 +22,12 @@ class VatNumberCheck public function run() { - return $this->checkvat_number(); + if(strlen($this->vat_number ?? '') == ){ + $this->response = ['valid' => false, 'error' => 'No VAT number provided']; + } + else{ + return $this->checkvat_number(); + } } private function checkvat_number(): self diff --git a/tests/Feature/Export/ReportCsvGenerationTest.php b/tests/Feature/Export/ReportCsvGenerationTest.php index be3202c8a0..aa6ebfa184 100644 --- a/tests/Feature/Export/ReportCsvGenerationTest.php +++ b/tests/Feature/Export/ReportCsvGenerationTest.php @@ -1172,13 +1172,15 @@ $this->account->forceDelete(); $this->assertEquals('', $this->getFirstValueByColumn($csv, 'Client Assigned User')); $this->assertEquals('USD', $this->getFirstValueByColumn($csv, 'Client Currency')); -$this->account->forceDelete(); + $this->account->forceDelete(); } public function testCreditJsonReport() { + config(['queue.default' => 'redis']); + Credit::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, @@ -1205,7 +1207,6 @@ $this->account->forceDelete(); 'X-API-TOKEN' => $this->token, ])->postJson('/api/v1/reports/credits?output=json', $data); - $response->assertStatus(200); $arr = $response->json(); @@ -1217,8 +1218,7 @@ $this->account->forceDelete(); $response->assertStatus(409); - -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -1285,7 +1285,7 @@ $this->account->forceDelete(); public function testInvoiceCustomColumnsCsvGeneration() { - \App\Models\Invoice::factory()->create([ + $invoice = \App\Models\Invoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, @@ -1475,7 +1475,7 @@ $this->account->forceDelete(); public function testInvoiceItemsCustomColumnsCsvGeneration() { - \App\Models\Invoice::factory()->create([ + $invoice = \App\Models\Invoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, @@ -1642,7 +1642,6 @@ $this->account->forceDelete(); $csv = $response->body(); - $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Quote Number')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Quantity')); @@ -1655,7 +1654,6 @@ $this->account->forceDelete(); $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Item Tax Name 1')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Tax Rate 1')); - $data = [ 'date_range' => 'all', 'report_keys' => $this->all_client_report_keys, @@ -1668,8 +1666,7 @@ $this->account->forceDelete(); 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/quote_items', $data)->assertStatus(200); - -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -1730,8 +1727,7 @@ $this->account->forceDelete(); $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Purchase Order Private Notes')); $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Purchase Order Terms')); - -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -1748,7 +1744,6 @@ $this->account->forceDelete(); ] ); - \App\Models\PurchaseOrder::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, @@ -1817,7 +1812,7 @@ $this->account->forceDelete(); $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Item Tax Name 1')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Tax Rate 1')); -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -1879,7 +1874,7 @@ $this->account->forceDelete(); ])->post('/api/v1/reports/quotes', $data)->assertStatus(200); -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -1896,11 +1891,25 @@ $this->account->forceDelete(); 'balance' => 100, 'number' => '12345', 'status_id' => 2, - 'discount' => 10, + 'discount' => 0, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', + 'tax_rate1' => 0, + 'tax_rate2' => 0, + 'tax_rate3' => 0, + 'line_items' => [ + [ + 'quantity' => 1, + 'product_key' => 'product_key', + 'notes' => 'notes', + 'cost' => 100, + 'custom_value1' => 'Custom 1', + 'custom_value2' => 'Custom 2', + 'custom_value3' => 'Custom 3', + ] + ] ]); $repo = new InvoiceRepository(); @@ -1935,7 +1944,7 @@ $this->account->forceDelete(); $this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Payment Amount')); $this->assertEquals(now()->addSeconds($this->company->timezone()->utc_offset)->format('Y-m-d'), $this->getFirstValueByColumn($csv, 'Payment Date')); -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -1982,7 +1991,7 @@ $this->account->forceDelete(); $this->assertEquals('john@doe.com', $res[1]); -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -2019,6 +2028,20 @@ $this->account->forceDelete(); 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', + 'tax_rate1' => 0, + 'tax_rate2' => 0, + 'tax_rate3' => 0, + 'line_items' => [ + [ + 'quantity' => 1, + 'product_key' => 'product_key', + 'notes' => 'notes', + 'cost' => 110, + 'custom_value1' => 'Custom 1', + 'custom_value2' => 'Custom 2', + 'custom_value3' => 'Custom 3', + ] + ] ]); $data = [ @@ -2034,8 +2057,6 @@ $this->account->forceDelete(); $response->assertStatus(200); - $response->assertStatus(200); - $arr = $response->json(); $hash = $arr['message']; @@ -2079,7 +2100,7 @@ $this->account->forceDelete(); 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/credits', $data)->assertStatus(200); -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -2165,7 +2186,7 @@ $this->account->forceDelete(); $this->assertEquals(floatval(30), $this->getFirstValueByColumn($csv, 'Invoice Tax Rate 3')); $this->assertEquals('Sent', $this->getFirstValueByColumn($csv, 'Invoice Status')); -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -2249,7 +2270,7 @@ $this->account->forceDelete(); $this->assertEquals(floatval(30), $this->getFirstValueByColumn($csv, 'Recurring Invoice Tax Rate 3')); $this->assertEquals('Daily', $this->getFirstValueByColumn($csv, 'Recurring Invoice How Often')); -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -2257,7 +2278,7 @@ $this->account->forceDelete(); public function testQuoteCsvGeneration() { - \App\Models\Quote::factory()->create([ + $quote = \App\Models\Quote::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, @@ -2333,7 +2354,7 @@ $this->account->forceDelete(); $this->assertEquals(floatval(30), $this->getFirstValueByColumn($csv, 'Quote Tax Rate 3')); $this->assertEquals('Expired', $this->getFirstValueByColumn($csv, 'Quote Status')); -$this->account->forceDelete(); + $this->account->forceDelete(); } @@ -2386,7 +2407,7 @@ $this->account->forceDelete(); $response = $this->poll($hash); $csv = $response->body(); -$this->account->forceDelete(); + $this->account->forceDelete(); } From d81bc1e7d519bdaa0a9fd3a49a3cf753496098a1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 11:20:53 +1000 Subject: [PATCH 07/14] Minor fixes for contact exports --- app/Export/CSV/ContactExport.php | 6 +++--- app/Services/Tax/VatNumberCheck.php | 3 ++- tests/Unit/LateFeeTest.php | 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/Export/CSV/ContactExport.php b/app/Export/CSV/ContactExport.php index 7344f04bbc..0c7789e188 100644 --- a/app/Export/CSV/ContactExport.php +++ b/app/Export/CSV/ContactExport.php @@ -135,18 +135,18 @@ class ContactExport extends BaseExport } } - // return $entity; + return $this->decorateAdvancedFields($contact->client, $entity); } private function decorateAdvancedFields(Client $client, array $entity): array { if (in_array('client.country_id', $this->input['report_keys'])) { - $entity['country'] = $client->country ? ctrans("texts.country_{$client->country->name}") : ''; + $entity['client.country_id'] = $client->country ? ctrans("texts.country_{$client->country->name}") : ''; } if (in_array('client.shipping_country_id', $this->input['report_keys'])) { - $entity['shipping_country'] = $client->shipping_country ? ctrans("texts.country_{$client->shipping_country->name}") : ''; + $entity['client.shipping_country_id'] = $client->shipping_country ? ctrans("texts.country_{$client->shipping_country->name}") : ''; } if (in_array('client.currency', $this->input['report_keys'])) { diff --git a/app/Services/Tax/VatNumberCheck.php b/app/Services/Tax/VatNumberCheck.php index 93f1a931aa..06dff2cd44 100644 --- a/app/Services/Tax/VatNumberCheck.php +++ b/app/Services/Tax/VatNumberCheck.php @@ -22,8 +22,9 @@ class VatNumberCheck public function run() { - if(strlen($this->vat_number ?? '') == ){ + if(strlen($this->vat_number ?? '') == 0){ $this->response = ['valid' => false, 'error' => 'No VAT number provided']; + return $this; } else{ return $this->checkvat_number(); diff --git a/tests/Unit/LateFeeTest.php b/tests/Unit/LateFeeTest.php index 7ae014bbd0..954fde7523 100644 --- a/tests/Unit/LateFeeTest.php +++ b/tests/Unit/LateFeeTest.php @@ -271,6 +271,8 @@ class LateFeeTest extends TestCase public function testLateFeeRemovals() { + config(['queue.default' => 'sync']); + $data = []; $data[1]['min_limit'] = -1; $data[1]['max_limit'] = -1; From 0d6ad1c4a2208fc42f3c8f9f789c40727fcd6f3d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 11:26:00 +1000 Subject: [PATCH 08/14] Validation fix for payment schedules --- app/Http/Requests/TaskScheduler/PaymentScheduleRequest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Http/Requests/TaskScheduler/PaymentScheduleRequest.php b/app/Http/Requests/TaskScheduler/PaymentScheduleRequest.php index 1d8790bdea..146751fd97 100644 --- a/app/Http/Requests/TaskScheduler/PaymentScheduleRequest.php +++ b/app/Http/Requests/TaskScheduler/PaymentScheduleRequest.php @@ -56,11 +56,12 @@ class PaymentScheduleRequest extends Request $input['is_paused'] = false; $input['parameters']['auto_bill'] = (bool) isset($input['parameters']['auto_bill']) ? $input['parameters']['auto_bill'] : false; - $input['parameters']['schedule'] = []; - if(isset($input['parameters']['schedule']) && is_array($input['parameters']['schedule']) && count($input['parameters']['schedule']) > 0) { $input['parameters']['schedule'] = $input['parameters']['schedule']; } + else{ + $input['parameters']['schedule'] = []; + } if (isset($input['schedule']) && is_array($input['schedule']) && count($input['schedule']) > 0) { $schedule_map = collect($input['schedule'])->map(function ($schedule, $key) { From db0c040d0ae6d41835e277edba64c7c29d389e53 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 11:30:10 +1000 Subject: [PATCH 09/14] Minor fixes for late fee tests --- tests/Unit/LateFeeTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Unit/LateFeeTest.php b/tests/Unit/LateFeeTest.php index 954fde7523..7d7a710507 100644 --- a/tests/Unit/LateFeeTest.php +++ b/tests/Unit/LateFeeTest.php @@ -350,6 +350,8 @@ class LateFeeTest extends TestCase $i = $i->calc()->getInvoice(); + $repo = new \App\Repositories\InvoiceRepository(); + $repo->save([], $i); $this->assertEquals(3, count($i->line_items)); $this->assertEquals(21, $i->amount); From 4ed0ccef955cef020e67d26292584d073d2c0741 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 11:32:41 +1000 Subject: [PATCH 10/14] Minor fixes for late fee tests --- tests/Unit/LateFeeTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Unit/LateFeeTest.php b/tests/Unit/LateFeeTest.php index 7d7a710507..280e0a274b 100644 --- a/tests/Unit/LateFeeTest.php +++ b/tests/Unit/LateFeeTest.php @@ -271,6 +271,10 @@ class LateFeeTest extends TestCase public function testLateFeeRemovals() { + if(!config('ninja.testvars.stripe')){ + $this->markTestSkipped('Stripe is not enabled'); + } + config(['queue.default' => 'sync']); $data = []; From 625d78af5db9dbdf16830e2e8d7a2be5d12e5187 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 11:36:51 +1000 Subject: [PATCH 11/14] Minor fixes for updateexchangeratestest --- tests/Feature/UpdateExchangeRatesTest.php | 24 +++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/Feature/UpdateExchangeRatesTest.php b/tests/Feature/UpdateExchangeRatesTest.php index 283b201f2a..108f826d3f 100644 --- a/tests/Feature/UpdateExchangeRatesTest.php +++ b/tests/Feature/UpdateExchangeRatesTest.php @@ -11,13 +11,14 @@ namespace Tests\Feature; -use App\Jobs\Util\UpdateExchangeRates; -use App\Libraries\Currency\Conversion\CurrencyApi; -use App\Models\Currency; -use App\Utils\Traits\MakesHash; -use Illuminate\Foundation\Testing\DatabaseTransactions; -use Tests\MockAccountData; use Tests\TestCase; +use App\Models\Currency; +use Tests\MockAccountData; +use App\Utils\Traits\MakesHash; +use App\Jobs\Util\UpdateExchangeRates; +use Illuminate\Support\Facades\Artisan; +use App\Libraries\Currency\Conversion\CurrencyApi; +use Illuminate\Foundation\Testing\DatabaseTransactions; /** * @@ -26,9 +27,7 @@ use Tests\TestCase; class UpdateExchangeRatesTest extends TestCase { use MakesHash; - use DatabaseTransactions; - use MockAccountData; - + protected function setUp(): void { parent::setUp(); @@ -37,6 +36,10 @@ class UpdateExchangeRatesTest extends TestCase $this->markTestSkipped("no currency key set"); } + if (Currency::count() == 0) { + Artisan::call('db:seed', ['--force' => true]); + } + } public function testExchangeRate() @@ -48,10 +51,11 @@ class UpdateExchangeRatesTest extends TestCase $currency_api = json_decode($response->getBody()); - UpdateExchangeRates::dispatchSync(); + (new UpdateExchangeRates())->handle(); $gbp_currency = \App\Models\Currency::find(2); + $this->assertNotNull($gbp_currency); $this->assertEquals($currency_api->rates->GBP, $gbp_currency->exchange_rate); } From 86c5837929ad3d4a883ce217784307eb82611250 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 14:06:04 +1000 Subject: [PATCH 12/14] Fixes for test namespace --- tests/Feature/Import/XLS/OfficeParseTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/Import/XLS/OfficeParseTest.php b/tests/Feature/Import/XLS/OfficeParseTest.php index 9bc879434b..5eed4a1946 100644 --- a/tests/Feature/Import/XLS/OfficeParseTest.php +++ b/tests/Feature/Import/XLS/OfficeParseTest.php @@ -9,7 +9,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace Tests\Feature\Import\CSV; +namespace Tests\Feature\Import\XLS; use App\Import\Providers\Csv; use App\Import\Transformer\BaseTransformer; From 8208db23d21e7ccb2511a9bd3d4cdb72b000a6e6 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 15:34:04 +1000 Subject: [PATCH 13/14] Static analysis --- app/Http/Controllers/Auth/LoginController.php | 21 ++++++++----------- app/Models/Company.php | 3 +++ app/Models/Credit.php | 1 + app/Models/Invoice.php | 2 ++ app/Models/PurchaseOrder.php | 3 +++ app/Models/Quote.php | 2 ++ app/Models/RecurringInvoice.php | 1 + app/Models/Vendor.php | 2 ++ app/Services/Report/TaxPeriodReport.php | 2 +- .../InvoiceOutstandingTasksService.php | 2 +- 10 files changed, 25 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index b5ece9130f..7ae0dcaefc 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -113,7 +113,6 @@ class LoginController extends BaseController ->increment() ->batch(); - $ip = ''; if (request()->hasHeader('Cf-Connecting-Ip')) { @@ -330,15 +329,15 @@ class LoginController extends BaseController Auth::login($existing_login_user, false); /** @var \App\Models\User $user */ - $user = auth()->user(); + // $user = auth()->user(); - $user->update([ + $existing_login_user->update([ 'oauth_user_id' => $user->id, 'oauth_provider_id' => $provider, ]); /** @var \App\Models\CompanyUser $cu */ - $cu = $this->hydrateCompanyUser($user); + $cu = $this->hydrateCompanyUser($existing_login_user); if ($cu->count() == 0) { return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400); @@ -378,22 +377,20 @@ class LoginController extends BaseController $account = (new CreateAccount($new_account, request()->getClientIp()))->handle(); - Auth::login($account->default_company->owner(), false); + $account_user = $account->default_company->owner(); + Auth::login($account_user, false); - /** @var \App\Models\User $user */ - $user = auth()->user(); - - $user->email_verified_at = now(); - $user->save(); + $account_user->email_verified_at = now(); + $account_user->save(); /** @var \App\Models\CompanyUser $cu */ - $cu = $this->hydrateCompanyUser($user); + $cu = $this->hydrateCompanyUser($account_user); if ($cu->count() == 0) { return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400); } - if (Ninja::isHosted() && !$cu->first()->is_owner && !auth()->user()->account->isEnterprisePaidClient()) { + if (Ninja::isHosted() && !$cu->first()->is_owner && !$account_user->account->isEnterprisePaidClient()) { return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403); } diff --git a/app/Models/Company.php b/app/Models/Company.php index dcefe8aa30..e850664dfc 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -134,6 +134,9 @@ use Laracasts\Presenter\PresentableTrait; * @property \App\DataMapper\QuickbooksSettings|null $quickbooks * @property boolean $smtp_verify_peer * @property int|null $legal_entity_id + * @property bool $invoice_task_item_description + * @property bool $show_task_item_description + * @property bool $invoice_task_project_header * @property-read \App\Models\Account $account * @property-read \Illuminate\Database\Eloquent\Collection $activities * @property-read int|null $activities_count diff --git a/app/Models/Credit.php b/app/Models/Credit.php index 1121ae1fb3..091430fcd6 100644 --- a/app/Models/Credit.php +++ b/app/Models/Credit.php @@ -118,6 +118,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property \App\Models\User $user * @property \App\Models\Client $client * @property \App\Models\Vendor|null $vendor + * @property-read \App\Models\Location|null $location * @property-read mixed $pivot * @property-read \Illuminate\Database\Eloquent\Collection $activities * @property-read \Illuminate\Database\Eloquent\Collection $company_ledger diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 6ce917f057..2c936176db 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -121,12 +121,14 @@ use App\Utils\Number; * @property-read int|null $payments_count * @property-read mixed $pivot * @property-read \App\Models\Project|null $project + * @property-read \App\Models\Quote|null $quote * @property-read \App\Models\RecurringInvoice|null $recurring_invoice * @property-read \App\Models\Subscription|null $subscription * @property-read \App\Models\Task|null $task * @property-read int|null $tasks_count * @property-read \App\Models\User $user * @property-read \App\Models\Vendor|null $vendor + * @property-read \App\Models\Location|null $location * @property-read \Illuminate\Database\Eloquent\Collection $transaction_events * @property-read \Illuminate\Database\Eloquent\Collection $activities * @property-read \Illuminate\Database\Eloquent\Collection $company_ledger diff --git a/app/Models/PurchaseOrder.php b/app/Models/PurchaseOrder.php index 7683ce23f8..c9e88d636c 100644 --- a/app/Models/PurchaseOrder.php +++ b/app/Models/PurchaseOrder.php @@ -89,6 +89,9 @@ use App\Events\PurchaseOrder\PurchaseOrderWasEmailed; * @property int|null $updated_at * @property int|null $expense_id * @property int|null $currency_id + * @property int|null $location_id + * @property int|null $invoice_id + * @property object|null $tax_data * @property-read int|null $activities_count * @property \App\Models\User|null $assigned_user * @property \App\Models\Client|null $client diff --git a/app/Models/Quote.php b/app/Models/Quote.php index 992456593b..0d801914ed 100644 --- a/app/Models/Quote.php +++ b/app/Models/Quote.php @@ -96,6 +96,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property string|null $reminder3_sent * @property string|null $reminder_last_sent * @property float $paid_to_date + * @property object|null $tax_data * @property int|null $subscription_id * @property \App\Models\User|null $assigned_user * @property \App\Models\Client $client @@ -111,6 +112,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property-read \App\Models\Project|null $project * @property-read \App\Models\User $user * @property-read \App\Models\Vendor|null $vendor + * @property-read \App\Models\Location|null $location * @property-read \Illuminate\Database\Eloquent\Collection $activities * @property-read \Illuminate\Database\Eloquent\Collection $documents * @property-read \Illuminate\Database\Eloquent\Collection $history diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php index d4dec50630..01579692f2 100644 --- a/app/Models/RecurringInvoice.php +++ b/app/Models/RecurringInvoice.php @@ -109,6 +109,7 @@ use App\Models\Presenters\RecurringInvoicePresenter; * @property-read \App\Models\Subscription|null $subscription * @property-read \App\Models\User $user * @property-read \App\Models\Vendor|null $vendor + * @property-read \App\Models\Location|null $location * @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns) * @method static \Database\Factories\RecurringInvoiceFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice filter(\App\Filters\QueryFilters $filters) diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index 8c34c18f23..a4f1b8e195 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -74,6 +74,8 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact * @property-read int|null $primary_contact_count * @property-read \App\Models\User $user + * @property-read \Illuminate\Database\Eloquent\Collection $locations + * @property-read int|null $locations_count * @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns) * @method static \Database\Factories\VendorFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|Vendor filter(\App\Filters\QueryFilters $filters) diff --git a/app/Services/Report/TaxPeriodReport.php b/app/Services/Report/TaxPeriodReport.php index b4b62fdc16..d4cc77c1e5 100644 --- a/app/Services/Report/TaxPeriodReport.php +++ b/app/Services/Report/TaxPeriodReport.php @@ -125,7 +125,7 @@ class TaxPeriodReport extends BaseExport ->map(function ($group) { return $group->first(); })->each(function ($pp){ - nlog($pp->paymentable->id. " - Paid Updater"); + // nlog($pp->paymentable->id. " - Paid Updater"); (new InvoiceTransactionEventEntryCash())->run($pp->paymentable, \Carbon\Carbon::parse($pp->created_at)->startOfMonth()->format('Y-m-d'), \Carbon\Carbon::parse($pp->created_at)->endOfMonth()->format('Y-m-d')); }); diff --git a/app/Services/Scheduler/InvoiceOutstandingTasksService.php b/app/Services/Scheduler/InvoiceOutstandingTasksService.php index 503aa91dc9..3613bccd8c 100644 --- a/app/Services/Scheduler/InvoiceOutstandingTasksService.php +++ b/app/Services/Scheduler/InvoiceOutstandingTasksService.php @@ -144,7 +144,7 @@ class InvoiceOutstandingTasksService EmailStatement::THIS_YEAR => [now()->startOfDay()->firstOfYear()->format('Y-m-d'), now()->startOfDay()->lastOfYear()->format('Y-m-d')], EmailStatement::LAST_YEAR => [now()->startOfDay()->subYearNoOverflow()->firstOfYear()->format('Y-m-d'), now()->startOfDay()->subYearNoOverflow()->lastOfYear()->format('Y-m-d')], EmailStatement::ALL_TIME => [ - Task::query() + Task::query() //@phpstan-ignore-line ->where('company_id', $this->scheduler->company_id) ->where('is_deleted', 0) ->selectRaw('MIN(tasks.calculated_start_date) as start_date') From 5b5222b4d370b6e081e8536b9034377a49f95f66 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 15 Aug 2025 18:50:16 +1000 Subject: [PATCH 14/14] Fixes for BE => BE tax free transactions --- VERSION.txt | 2 +- app/Services/Chart/ChartService.php | 1 - app/Services/EDocument/Jobs/SendEDocument.php | 4 ++-- app/Services/EDocument/Standards/Peppol.php | 4 ++++ config/ninja.php | 4 ++-- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 027ea4a128..6832cc314f 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.12.14 \ No newline at end of file +5.12.15 \ No newline at end of file diff --git a/app/Services/Chart/ChartService.php b/app/Services/Chart/ChartService.php index ac16ee1dbb..a62737e2c2 100644 --- a/app/Services/Chart/ChartService.php +++ b/app/Services/Chart/ChartService.php @@ -94,7 +94,6 @@ class ChartService $data[$key]['expenses'] = $this->getExpenseChartQuery($start_date, $end_date, $key); } - $data[999]['invoices'] = $this->getAggregateInvoiceChartQuery($start_date, $end_date); $data[999]['outstanding'] = $this->getAggregateOutstandingChartQuery($start_date, $end_date); $data[999]['payments'] = $this->getAggregatePaymentChartQuery($start_date, $end_date); diff --git a/app/Services/EDocument/Jobs/SendEDocument.php b/app/Services/EDocument/Jobs/SendEDocument.php index dbb5593cb0..14c79bff7b 100644 --- a/app/Services/EDocument/Jobs/SendEDocument.php +++ b/app/Services/EDocument/Jobs/SendEDocument.php @@ -250,11 +250,11 @@ class SendEDocument implements ShouldQueue nlog($exception->getMessage()); } - config(['queue.failed.driver' => null]); + // config(['queue.failed.driver' => null]); } public function middleware() { - return [new WithoutOverlapping($this->entity.$this->id.$this->db)]; + return [(new WithoutOverlapping($this->entity.$this->id.$this->db))->releaseAfter(60)->expireAfter(60)]; } } diff --git a/app/Services/EDocument/Standards/Peppol.php b/app/Services/EDocument/Standards/Peppol.php index b043a07d4e..ee7b7c0912 100644 --- a/app/Services/EDocument/Standards/Peppol.php +++ b/app/Services/EDocument/Standards/Peppol.php @@ -717,6 +717,10 @@ class Peppol extends AbstractService $tax_type = 'G'; //Free export item, VAT not charged $reason_code = 'vatex-eu-g'; $reason = 'Export outside the EU'; + } elseif($this->invoice->client->country->iso_3166_2 == $this->company->country()->iso_3166_2) { + $tax_type = 'E'; + $reason_code = "vatex-eu-o"; + $reason = 'Services outside scope of tax'; } else { $tax_type = 'O'; $reason_code = "vatex-eu-o"; diff --git a/config/ninja.php b/config/ninja.php index 59a79c8ffa..b59dd528cf 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -17,8 +17,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => env('APP_VERSION', '5.12.14'), - 'app_tag' => env('APP_TAG', '5.12.14'), + 'app_version' => env('APP_VERSION', '5.12.15'), + 'app_tag' => env('APP_TAG', '5.12.15'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false),