From 64793841d4ea0a597d97ffb736954ecc5ac97ecb Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 9 Jan 2024 19:43:51 +1100 Subject: [PATCH 1/5] adjustments for request validations --- app/Http/Requests/Login/LoginRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Requests/Login/LoginRequest.php b/app/Http/Requests/Login/LoginRequest.php index 7d0ab21d8cb0..42aed76b9374 100644 --- a/app/Http/Requests/Login/LoginRequest.php +++ b/app/Http/Requests/Login/LoginRequest.php @@ -36,7 +36,7 @@ class LoginRequest extends Request public function rules() { if (Ninja::isHosted()) { - $email_rules = ['required', new BlackListRule, new EmailBlackListRule]; + $email_rules = ['required', new EmailBlackListRule]; } else { $email_rules = 'required'; } From 293ad19bd8d5010b50cf2a6760551d337387f0c1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 9 Jan 2024 20:05:18 +1100 Subject: [PATCH 2/5] Tests for product cost migration --- ...9_084515_product_cost_field_population.php | 50 ++++++++++++ tests/Feature/ProductTest.php | 76 ++++++++++++++++++- 2 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 database/migrations/2024_01_09_084515_product_cost_field_population.php diff --git a/database/migrations/2024_01_09_084515_product_cost_field_population.php b/database/migrations/2024_01_09_084515_product_cost_field_population.php new file mode 100644 index 000000000000..4397f8e0fab7 --- /dev/null +++ b/database/migrations/2024_01_09_084515_product_cost_field_population.php @@ -0,0 +1,50 @@ +where('is_deleted', false) + ->cursor() + ->each(function (Invoice $invoice) { + + + $line_items = $invoice->line_items; + + foreach ($line_items as $key => $item) + { + + if($item?->product_cost == 0 && $product = Product::where('company_id', $invoice->company_id)->where('product_key', $item->product_key)->where('cost', '>', 0)->first()) + { + $line_items[$key]->product_cost = $product->cost; + } + } + + $invoice->line_items = $line_items; + $invoice->saveQuietly(); + + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // + } +}; diff --git a/tests/Feature/ProductTest.php b/tests/Feature/ProductTest.php index 7a709e398d33..8f39621a7de9 100644 --- a/tests/Feature/ProductTest.php +++ b/tests/Feature/ProductTest.php @@ -11,14 +11,16 @@ namespace Tests\Feature; +use App\DataMapper\InvoiceItem; +use Tests\TestCase; +use App\Models\Invoice; use App\Models\Product; +use Tests\MockAccountData; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; -use Illuminate\Foundation\Testing\DatabaseTransactions; -use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Support\Facades\Session; -use Tests\MockAccountData; -use Tests\TestCase; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Foundation\Testing\DatabaseTransactions; /** * @test @@ -49,6 +51,72 @@ class ProductTest extends TestCase } + public function testProductCostMigration() + { + $items = []; + + $item = new InvoiceItem(); + $item->product_cost = 0; + $item->product_key = 'test'; + $item->quantity = 1; + $item->cost = 10; + $item->notes = 'product'; + + $items[] = $item; + + $p = Product::factory() + ->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'product_key' => 'test', + 'cost' => 10, + 'price' => 20, + 'quantity' => 1, + 'notes' => 'product', + ]); + + $i = Invoice::factory() + ->create([ + 'client_id' => $this->client->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'line_items' => $items, + ]); + + + $line_items = $i->line_items; + + $this->assertEquals(0, $line_items[0]->product_cost); + + Invoice::withTrashed() + ->where('is_deleted', false) + ->cursor() + ->each(function (Invoice $invoice) { + + + $line_items = $invoice->line_items; + + foreach ($line_items as $key => $item) { + + if($item?->product_cost == 0 && $product = Product::where('company_id', $invoice->company_id)->where('product_key', $item->product_key)->where('cost', '>', 0)->first()) { + $line_items[$key]->product_cost = $product->cost; + } + } + + $invoice->line_items = $line_items; + $invoice->saveQuietly(); + + }); + + + $i = $i->fresh(); + $line_items = $i->line_items; + + $this->assertEquals(10, $line_items[0]->product_cost); + + + } + public function testSetTaxId() { $p = Product::factory()->create([ From a293f53c083f04c0405ace40015ed0a0c19d1934 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 9 Jan 2024 21:29:32 +1100 Subject: [PATCH 3/5] Tests for client currency conversion --- ...01_09_084515_product_cost_field_population.php | 2 ++ tests/Feature/ProductTest.php | 2 ++ tests/Unit/CurrencyApiTest.php | 15 +++++++++++++++ 3 files changed, 19 insertions(+) diff --git a/database/migrations/2024_01_09_084515_product_cost_field_population.php b/database/migrations/2024_01_09_084515_product_cost_field_population.php index 4397f8e0fab7..830470d94ca9 100644 --- a/database/migrations/2024_01_09_084515_product_cost_field_population.php +++ b/database/migrations/2024_01_09_084515_product_cost_field_population.php @@ -17,6 +17,8 @@ return new class extends Migration return; } + set_time_limit(0); + Invoice::withTrashed() ->where('is_deleted', false) ->cursor() diff --git a/tests/Feature/ProductTest.php b/tests/Feature/ProductTest.php index 8f39621a7de9..2bdd330f198e 100644 --- a/tests/Feature/ProductTest.php +++ b/tests/Feature/ProductTest.php @@ -32,6 +32,8 @@ class ProductTest extends TestCase use DatabaseTransactions; use MockAccountData; + protected $faker; + protected function setUp() :void { parent::setUp(); diff --git a/tests/Unit/CurrencyApiTest.php b/tests/Unit/CurrencyApiTest.php index 153e566b25df..d863dfac09e7 100644 --- a/tests/Unit/CurrencyApiTest.php +++ b/tests/Unit/CurrencyApiTest.php @@ -12,6 +12,7 @@ namespace Tests\Unit; use App\Libraries\Currency\Conversion\CurrencyApi; +use App\Models\Currency; use Illuminate\Support\Carbon; use Tests\TestCase; @@ -26,6 +27,20 @@ class CurrencyApiTest extends TestCase parent::setUp(); } + public function testConversionAudToEur() + { + $converter = new CurrencyApi(); + + $converted_amount = $converter->convert(100, 12, 3); + + $aud_currency = Currency::find(12); + $eur_currency = Currency::find(3); + + $converted_synthetic = 100 / ($aud_currency->exchange_rate / $eur_currency->exchange_rate); + + $this->assertEquals(round($converted_synthetic, 2), round($converted_amount, 2)); + } + public function testCurrencyConversionWorking() { $converter = new CurrencyApi(); From edd0a57b2962ba6f3d3fced48e5c8fdb607be226 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 9 Jan 2024 21:49:29 +1100 Subject: [PATCH 4/5] working on client currency conversion --- app/Models/Client.php | 9 ++++ app/Services/Invoice/InvoiceService.php | 2 +- tests/Feature/ClientTest.php | 56 +++++++++++++++++++------ tests/Unit/CurrencyApiTest.php | 1 + 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/app/Models/Client.php b/app/Models/Client.php index a72dd3344c29..8272e2fc10a5 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -812,6 +812,15 @@ class Client extends BaseModel implements HasLocalePreference return $defaults; } + public function setExchangeRate() + { + + $converter = new CurrencyApi(); + + return 1/$converter->convert(1, $this->currency()->id, $this->company->settings->currency_id); + + } + public function timezone_offset() :int { $offset = 0; diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index e435263879b1..045282f41aaf 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -567,7 +567,7 @@ class InvoiceService /* If client currency differs from the company default currency, then insert the client exchange rate on the model.*/ if (! isset($this->invoice->exchange_rate) && $this->invoice->client->currency()->id != (int) $this->invoice->company->settings->currency_id) { - $this->invoice->exchange_rate = $this->invoice->client->currency()->exchange_rate; + $this->invoice->exchange_rate = $this->invoice->client->setExchangeRate(); } if ($this->invoice->client->getSetting('auto_bill_standard_invoices')) { diff --git a/tests/Feature/ClientTest.php b/tests/Feature/ClientTest.php index b09978d6af67..92632dad2380 100644 --- a/tests/Feature/ClientTest.php +++ b/tests/Feature/ClientTest.php @@ -11,25 +11,27 @@ namespace Tests\Feature; +use Tests\TestCase; +use App\Models\User; +use App\Models\Client; +use App\Models\Credit; +use App\Models\Account; +use App\Models\Company; +use App\Models\Currency; +use Tests\MockAccountData; +use Illuminate\Support\Str; +use App\Models\CompanyToken; +use App\Models\ClientContact; +use App\Utils\Traits\MakesHash; +use App\DataMapper\ClientSettings; use App\DataMapper\CompanySettings; use App\DataMapper\DefaultSettings; use App\Factory\InvoiceItemFactory; -use App\Models\Account; -use App\Models\Client; -use App\Models\ClientContact; -use App\Models\Company; -use App\Models\CompanyToken; -use App\Models\Credit; -use App\Models\User; -use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; -use Illuminate\Foundation\Testing\DatabaseTransactions; -use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Support\Facades\Session; -use Illuminate\Support\Str; use Illuminate\Validation\ValidationException; -use Tests\MockAccountData; -use Tests\TestCase; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Foundation\Testing\DatabaseTransactions; /** * @test @@ -65,6 +67,34 @@ class ClientTest extends TestCase $this->makeTestData(); } + public function testClientExchangeRateCalculation() + { + $settings = ClientSettings::defaults(); + $settings->currency_id = 12; + + $c = Client::factory() + ->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'settings' => $settings + ]); + + $settings = $this->company->settings; + $settings->currency_id = '3'; + + $this->company->saveSettings($settings, $this->company); + + $client_exchange_rate = round($c->setExchangeRate(),2); + + $aud_currency = Currency::find(12); + $eur_currency = Currency::find(3); + + $synthetic_exchange = $aud_currency->exchange_rate / $eur_currency->exchange_rate; + + $this->assertEquals($client_exchange_rate, round($synthetic_exchange,2)); + + } + public function testStoreClientFixes2() { $data = [ diff --git a/tests/Unit/CurrencyApiTest.php b/tests/Unit/CurrencyApiTest.php index d863dfac09e7..5db10d26ef9f 100644 --- a/tests/Unit/CurrencyApiTest.php +++ b/tests/Unit/CurrencyApiTest.php @@ -39,6 +39,7 @@ class CurrencyApiTest extends TestCase $converted_synthetic = 100 / ($aud_currency->exchange_rate / $eur_currency->exchange_rate); $this->assertEquals(round($converted_synthetic, 2), round($converted_amount, 2)); + } public function testCurrencyConversionWorking() From 1ec4773ad38fd45b85e5321a46d2a258bda9c404 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 9 Jan 2024 22:16:37 +1100 Subject: [PATCH 5/5] Fixes for tests --- tests/Feature/ProductTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/ProductTest.php b/tests/Feature/ProductTest.php index 2bdd330f198e..40af31f9a9cc 100644 --- a/tests/Feature/ProductTest.php +++ b/tests/Feature/ProductTest.php @@ -100,7 +100,7 @@ class ProductTest extends TestCase foreach ($line_items as $key => $item) { - if($item?->product_cost == 0 && $product = Product::where('company_id', $invoice->company_id)->where('product_key', $item->product_key)->where('cost', '>', 0)->first()) { + if(property_exists($item, 'product_cost') && $item->product_cost == 0 && $product = Product::where('company_id', $invoice->company_id)->where('product_key', $item->product_key)->where('cost', '>', 0)->first()) { $line_items[$key]->product_cost = $product->cost; } }