From 5ccd6949bdfaf30eb20d68bccf292ff54547b4a6 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jan 2024 09:51:41 +1100 Subject: [PATCH 1/8] Temp fix for partial due dates --- app/Models/BaseModel.php | 6 +----- app/Models/Invoice.php | 5 ++++- app/Transformers/InvoiceTransformer.php | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php index 8de87e02a2a5..1f8c27449912 100644 --- a/app/Models/BaseModel.php +++ b/app/Models/BaseModel.php @@ -97,11 +97,7 @@ class BaseModel extends Model public function dateMutator($value) { - if (! empty($value)) { - return (new Carbon($value))->format('Y-m-d'); - } - - return $value; + return (new Carbon($value))->format('Y-m-d'); } // public function __call($method, $params) diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 2d9a5babc397..ef82156fa61e 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -245,6 +245,9 @@ class Invoice extends BaseModel public function getPartialDueDateAttribute($value) { + if($value == "0000-00-00 00:00:00") + return null; + return $this->dateMutator($value); } @@ -396,7 +399,7 @@ class Invoice extends BaseModel public function getStatusAttribute() { $due_date = $this->due_date ? Carbon::parse($this->due_date) : false; - $partial_due_date = $this->partial_due_Date ? Carbon::parse($this->partial_due_date) : false; + $partial_due_date = $this->partial_due_date ? Carbon::parse($this->partial_due_date) : false; if ($this->status_id == self::STATUS_SENT && $due_date && $due_date->gt(now())) { return self::STATUS_UNPAID; diff --git a/app/Transformers/InvoiceTransformer.php b/app/Transformers/InvoiceTransformer.php index 85605ed37485..455568a0ca15 100644 --- a/app/Transformers/InvoiceTransformer.php +++ b/app/Transformers/InvoiceTransformer.php @@ -132,7 +132,7 @@ class InvoiceTransformer extends EntityTransformer 'is_amount_discount' => (bool) ($invoice->is_amount_discount ?: false), 'footer' => $invoice->footer ?: '', 'partial' => (float) ($invoice->partial ?: 0.0), - 'partial_due_date' => $invoice->partial_due_date ?: '', + 'partial_due_date' => ($invoice->partial_due_date && $invoice->partial_due_date != "-0001-11-30") ?: '', 'custom_value1' => (string) $invoice->custom_value1 ?: '', 'custom_value2' => (string) $invoice->custom_value2 ?: '', 'custom_value3' => (string) $invoice->custom_value3 ?: '', From 24c9edd1a7c4108cd72825eee269ab5e99be6079 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jan 2024 10:50:39 +1100 Subject: [PATCH 2/8] Adjustments for PDf previews --- app/Models/Invoice.php | 5 +---- app/Services/Pdf/PdfMock.php | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index ef82156fa61e..2d9a5babc397 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -245,9 +245,6 @@ class Invoice extends BaseModel public function getPartialDueDateAttribute($value) { - if($value == "0000-00-00 00:00:00") - return null; - return $this->dateMutator($value); } @@ -399,7 +396,7 @@ class Invoice extends BaseModel public function getStatusAttribute() { $due_date = $this->due_date ? Carbon::parse($this->due_date) : false; - $partial_due_date = $this->partial_due_date ? Carbon::parse($this->partial_due_date) : false; + $partial_due_date = $this->partial_due_Date ? Carbon::parse($this->partial_due_date) : false; if ($this->status_id == self::STATUS_SENT && $due_date && $due_date->gt(now())) { return self::STATUS_UNPAID; diff --git a/app/Services/Pdf/PdfMock.php b/app/Services/Pdf/PdfMock.php index 7cc2bd72a3b6..ee96b808a912 100644 --- a/app/Services/Pdf/PdfMock.php +++ b/app/Services/Pdf/PdfMock.php @@ -462,7 +462,7 @@ class PdfMock '$viewLink' => 'View Invoice', '$autoBill' => 'This invoice will automatically be billed to your credit card on file on the due date.', '$view_url' => 'http://ninja.test:8000/client/invoice/UAUY8vIPuno72igmXbbpldwo5BDDKIqs', - '$font_url' => 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', + '$font_url' => isset($this->settings?->primary_font) ? \App\Utils\Helpers::resolveFont($this->settings->primary_font)['url'] : 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', '$details' => '', '$balance' => '$40.00', '$partial' => '$30.00', From a3b0d199f552dbce8cc0a75f8974b10a2a467c48 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jan 2024 11:23:42 +1100 Subject: [PATCH 3/8] Minor fixes for tets --- tests/Integration/EventTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Integration/EventTest.php b/tests/Integration/EventTest.php index 3bcbbaff5313..d6ca4dce5d76 100644 --- a/tests/Integration/EventTest.php +++ b/tests/Integration/EventTest.php @@ -397,6 +397,7 @@ class EventTest extends TestCase ]; $quote = Quote::find($this->decodePrimaryKey($arr['data']['id'])); + $quote->due_date = now()->addYear(); $quote->status_id = Quote::STATUS_SENT; $quote->save(); From 6236bf0deec6a485617c3348b36e197baee91c5b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jan 2024 11:45:51 +1100 Subject: [PATCH 4/8] Fixes for clone quotes --- app/Factory/CloneQuoteToInvoiceFactory.php | 5 +++-- app/Models/Invoice.php | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/Factory/CloneQuoteToInvoiceFactory.php b/app/Factory/CloneQuoteToInvoiceFactory.php index 30400edccae6..10c1c7f86cae 100644 --- a/app/Factory/CloneQuoteToInvoiceFactory.php +++ b/app/Factory/CloneQuoteToInvoiceFactory.php @@ -28,7 +28,8 @@ class CloneQuoteToInvoiceFactory unset($quote_array['invoice_id']); unset($quote_array['id']); unset($quote_array['invitations']); - + unset($quote_array['user']); + //preserve terms if they exist on Quotes //if(array_key_exists('terms', $quote_array) && strlen($quote_array['terms']) < 2) if (! $quote->company->use_quote_terms_on_conversion) { @@ -38,7 +39,6 @@ class CloneQuoteToInvoiceFactory // unset($quote_array['public_notes']); unset($quote_array['footer']); unset($quote_array['design_id']); - unset($quote_array['user']); foreach ($quote_array as $key => $value) { $invoice->{$key} = $value; @@ -59,6 +59,7 @@ class CloneQuoteToInvoiceFactory $invoice->last_sent_date = null; $invoice->last_viewed = null; + return $invoice; } } diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 2d9a5babc397..a9ff626e819c 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -240,12 +240,12 @@ class Invoice extends BaseModel public function getDueDateAttribute($value) { - return $this->dateMutator($value); + return $value ? $this->dateMutator($value) : null; } public function getPartialDueDateAttribute($value) { - return $this->dateMutator($value); + return $value ? $this->dateMutator($value) : null; } public function company(): \Illuminate\Database\Eloquent\Relations\BelongsTo From 173ed1518906a19c2f05b7d6007e0cf266680de2 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jan 2024 17:21:40 +1100 Subject: [PATCH 5/8] Fixes for payment methods --- app/Models/Client.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/Client.php b/app/Models/Client.php index 953d40f0cb95..8c13c850244f 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -545,14 +545,14 @@ class Client extends BaseModel implements HasLocalePreference $cg = CompanyGateway::query()->find($pm['company_gateway_id']); - if ($cg && ! property_exists($cg->fees_and_limits, strval(GatewayType::CREDIT_CARD))) { + if ($cg && is_object($cg->fees_and_limits) && ! property_exists($cg->fees_and_limits, strval(GatewayType::CREDIT_CARD))) { $fees_and_limits = $cg->fees_and_limits; $fees_and_limits->{GatewayType::CREDIT_CARD} = new FeesAndLimits; $cg->fees_and_limits = $fees_and_limits; $cg->save(); } - if ($cg && $cg->fees_and_limits->{GatewayType::CREDIT_CARD}->is_enabled) { + if ($cg && is_object($cg->fees_and_limits)&& $cg->fees_and_limits->{GatewayType::CREDIT_CARD}->is_enabled) { return $cg; } } From 365d4b9c21f398de3751c355da9d309377640e62 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jan 2024 17:33:11 +1100 Subject: [PATCH 6/8] Fixes for authorizing payment methods --- app/Models/Client.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/Models/Client.php b/app/Models/Client.php index 8c13c850244f..a72dd3344c29 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -545,6 +545,9 @@ class Client extends BaseModel implements HasLocalePreference $cg = CompanyGateway::query()->find($pm['company_gateway_id']); + if($cg->gateway_key == '80af24a6a691230bbec33e930ab40666') //ensure we don't attempt to authorize paypal platform - yet. + continue; + if ($cg && is_object($cg->fees_and_limits) && ! property_exists($cg->fees_and_limits, strval(GatewayType::CREDIT_CARD))) { $fees_and_limits = $cg->fees_and_limits; $fees_and_limits->{GatewayType::CREDIT_CARD} = new FeesAndLimits; From 7b0614ee89016fbf34bfedf03f07b7f8fc133cc4 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jan 2024 17:47:39 +1100 Subject: [PATCH 7/8] Fixes for Swiss QR codes where first char is always removed --- app/Helpers/SwissQr/SwissQrGenerator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Helpers/SwissQr/SwissQrGenerator.php b/app/Helpers/SwissQr/SwissQrGenerator.php index b4e0b0d37392..f9fdbd726fc7 100644 --- a/app/Helpers/SwissQr/SwissQrGenerator.php +++ b/app/Helpers/SwissQr/SwissQrGenerator.php @@ -115,7 +115,7 @@ class SwissQrGenerator } else { $tempInvoiceNumber = $this->invoice->number; $tempInvoiceNumber = preg_replace('/[^A-Za-z0-9]/', '', $tempInvoiceNumber); - $tempInvoiceNumber = substr($tempInvoiceNumber, 1); + // $tempInvoiceNumber = substr($tempInvoiceNumber, 1); $calcInvoiceNumber = ""; $array = str_split($tempInvoiceNumber); From 0c64e38208d2ff2f20a5fcc198974713d9f1155f Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jan 2024 18:42:44 +1100 Subject: [PATCH 8/8] Reset counters at client and group levels --- app/Utils/Traits/GeneratesCounter.php | 18 ++-- tests/Unit/GeneratesCounterTest.php | 144 +++++++++++++++++++++++--- 2 files changed, 142 insertions(+), 20 deletions(-) diff --git a/app/Utils/Traits/GeneratesCounter.php b/app/Utils/Traits/GeneratesCounter.php index 89c69b107391..bf49f5438cad 100644 --- a/app/Utils/Traits/GeneratesCounter.php +++ b/app/Utils/Traits/GeneratesCounter.php @@ -510,13 +510,17 @@ trait GeneratesCounter private function resetCounters(Client $client) { $reset_counter_frequency = (int) $client->getSetting('reset_counter_frequency_id'); + $settings_entity = $client->getSettingEntity('reset_counter_frequency_id'); + $settings = $settings_entity->settings; if ($reset_counter_frequency == 0) { if ($client->getSetting('reset_counter_date')) { - $settings = $client->company->settings; + // $settings = $client->company->settings; $settings->reset_counter_date = ""; - $client->company->settings = $settings; - $client->company->save(); + $settings_entity->settings = $settings; + $settings_entity->saveQuietly(); + // $client->company->settings = $settings; + // $client->company->save(); } return; @@ -570,7 +574,7 @@ trait GeneratesCounter break; } - $settings = $client->company->settings; + // $settings = $client->company->settings; $settings->reset_counter_date = $new_reset_date->format('Y-m-d'); $settings->invoice_number_counter = 1; $settings->quote_number_counter = 1; @@ -583,8 +587,10 @@ trait GeneratesCounter $settings->recurring_expense_number_counter = 1; $settings->purchase_order_number_counter = 1; - $client->company->settings = $settings; - $client->company->save(); + // $client->company->settings = $settings; + // $client->company->save(); + $settings_entity->settings = $settings; + $settings_entity->saveQuietly(); } private function resetCompanyCounters($company) diff --git a/tests/Unit/GeneratesCounterTest.php b/tests/Unit/GeneratesCounterTest.php index 6d9be6b50004..2bfc84619546 100644 --- a/tests/Unit/GeneratesCounterTest.php +++ b/tests/Unit/GeneratesCounterTest.php @@ -11,23 +11,24 @@ namespace Tests\Unit; -use App\DataMapper\ClientSettings; +use Tests\TestCase; +use App\Models\Quote; +use App\Models\Client; +use App\Models\Credit; +use App\Models\Company; +use App\Models\Invoice; +use App\Models\Timezone; +use Tests\MockAccountData; +use App\Models\GroupSetting; use App\Factory\ClientFactory; use App\Factory\VendorFactory; -use App\Models\Client; -use App\Models\Company; -use App\Models\Credit; -use App\Models\Invoice; -use App\Models\Quote; -use App\Models\RecurringInvoice; -use App\Models\Timezone; -use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\MakesHash; +use App\Models\RecurringInvoice; +use App\DataMapper\ClientSettings; +use App\Utils\Traits\GeneratesCounter; use Illuminate\Database\Eloquent\Model; -use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Session; -use Tests\MockAccountData; -use Tests\TestCase; +use Illuminate\Foundation\Testing\DatabaseTransactions; /** * @test @@ -53,6 +54,121 @@ class GeneratesCounterTest extends TestCase $this->makeTestData(); } + public function testResetCounterGroup() + { + $timezone = Timezone::find(1); + + $date_formatted = now($timezone->name)->format('Ymd'); + + $gs = new GroupSetting; + $gs->name = 'Test'; + $gs->company_id = $this->client->company_id; + $gs->settings = ClientSettings::buildClientSettings($this->company->settings, $this->client->settings); + $gs->save(); + + $this->client->group_settings_id = $gs->id; + $this->client->save(); + + $settings = $gs->settings; + // $settings = $this->client->settings; + $settings->invoice_number_pattern = '{$date:Ymd}-{$group_counter}'; + $settings->timezone_id = 1; + $gs->settings = $settings; + $gs->save(); + + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0001', $invoice_number); + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0002', $invoice_number); + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0003', $invoice_number); + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0004', $invoice_number); + + $settings->reset_counter_date = now($timezone->name)->format('Y-m-d'); + $settings->reset_counter_frequency_id = RecurringInvoice::FREQUENCY_DAILY; + $gs->settings = $settings; + $gs->save(); + + $this->travel(5)->days(); + $date_formatted = now($timezone->name)->format('Ymd'); + + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0001', $invoice_number); + + $this->invoice->number = $invoice_number; + $this->invoice->save(); + + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0002', $invoice_number); + + $settings->reset_counter_date = now($timezone->name)->format('Y-m-d'); + $settings->reset_counter_frequency_id = RecurringInvoice::FREQUENCY_DAILY; + $gs->settings = $settings; + $gs->save(); + + $this->travel(5)->days(); + $date_formatted = now($timezone->name)->format('Ymd'); + + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0001', $invoice_number); + + $this->travelBack(); + } + + + public function testResetCounterClient() + { + $timezone = Timezone::find(1); + + $date_formatted = now($timezone->name)->format('Ymd'); + + $settings = $this->client->settings; + $settings->invoice_number_pattern = '{$date:Ymd}-{$client_counter}'; + $settings->timezone_id = 1; + $this->client->settings = $settings; + $this->client->save(); + + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0001', $invoice_number); + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0002', $invoice_number); + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0003', $invoice_number); + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0004', $invoice_number); + + $settings->reset_counter_date = now($timezone->name)->format('Y-m-d'); + $settings->reset_counter_frequency_id = RecurringInvoice::FREQUENCY_DAILY; + $this->client->settings = $settings; + $this->client->save(); + + $this->travel(5)->days(); + $date_formatted = now($timezone->name)->format('Ymd'); + + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0001', $invoice_number); + + $this->invoice->number = $invoice_number; + $this->invoice->save(); + + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0002', $invoice_number); + + $settings->reset_counter_date = now($timezone->name)->format('Y-m-d'); + $settings->reset_counter_frequency_id = RecurringInvoice::FREQUENCY_DAILY; + $this->client->settings = $settings; + $this->client->save(); + + $this->travel(5)->days(); + $date_formatted = now($timezone->name)->format('Ymd'); + + $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + $this->assertEquals($date_formatted.'-0001', $invoice_number); + + $this->travelBack(); + } + public function testResetCounter() { $timezone = Timezone::find(1); @@ -82,8 +198,8 @@ class GeneratesCounterTest extends TestCase $this->company->settings = $settings; $this->company->save(); - $this->client->settings = $settings; - $this->client->save(); + // $this->client->settings = $settings; + // $this->client->save(); $this->travel(5)->days(); $date_formatted = now($timezone->name)->format('Ymd');