From 48f46dbd45d3d604f9be0b9f9335caa5b607f6d6 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 9 Sep 2022 18:36:54 +1000 Subject: [PATCH 01/27] Configuration for in app purchases --- app/Libraries/MultiDB.php | 18 ++++++ .../AppStoreRenewSubscription.php | 58 +++++++++++++++++++ config/purchase.php | 5 +- 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 app/Listeners/Subscription/AppStoreRenewSubscription.php diff --git a/app/Libraries/MultiDB.php b/app/Libraries/MultiDB.php index 56f3d1d9ac79..dabc5fc647d2 100644 --- a/app/Libraries/MultiDB.php +++ b/app/Libraries/MultiDB.php @@ -329,6 +329,24 @@ class MultiDB return false; } + public static function findAndSetDbByInappTransactionId($transaction_id) :bool + { + $current_db = config('database.default'); + + foreach (self::$dbs as $db) { + if (Account::on($db)->where('inapp_transaction_id', $transaction_id)->exists()) { + self::setDb($db); + + return true; + } + } + + self::setDB($current_db); + + return false; + } + + public static function findAndSetDbByContactKey($contact_key) :bool { $current_db = config('database.default'); diff --git a/app/Listeners/Subscription/AppStoreRenewSubscription.php b/app/Listeners/Subscription/AppStoreRenewSubscription.php new file mode 100644 index 000000000000..d304b2ebe20a --- /dev/null +++ b/app/Listeners/Subscription/AppStoreRenewSubscription.php @@ -0,0 +1,58 @@ +getSubscriptionId(); //$subscription_id + + MultiDB::findAndSetDbByInappTransactionId($inapp_transaction_id); + + $account = Account::where('inapp_transaction_id', $inapp_transaction_id)->first(); + + if($account->plan_term == 'month') + $account->plan_expires = now()->addMonth(); + elseif($account->plan_term == 'year') + $account->plan_expires = now()->addYear(); + + $account->save(); + + // $server_notification = $event->getServerNotification(); + // $subscription = $event->getSubscription(); + // $subscription_identifier = $event->getSubscriptionIdentifier(); + + } + +} \ No newline at end of file diff --git a/config/purchase.php b/config/purchase.php index 38a6c52dd3fa..2791bd868288 100644 --- a/config/purchase.php +++ b/config/purchase.php @@ -1,5 +1,6 @@ [], DidFailToRenew::class => [], DidRecover::class => [], - DidRenew::class => [], + DidRenew::class => [AppStoreRenewSubscription::class], InitialBuy::class => [], InteractiveRenewal::class => [], PriceIncreaseConsent::class => [], From 700451bac1e6847127989fd15eec9979b2221875 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 10 Sep 2022 08:24:23 +1000 Subject: [PATCH 02/27] Move lightlogs to batch --- app/Http/Controllers/PreviewPurchaseOrderController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/PreviewPurchaseOrderController.php b/app/Http/Controllers/PreviewPurchaseOrderController.php index e159e02101e2..aeabf41ea549 100644 --- a/app/Http/Controllers/PreviewPurchaseOrderController.php +++ b/app/Http/Controllers/PreviewPurchaseOrderController.php @@ -292,7 +292,7 @@ class PreviewPurchaseOrderController extends BaseController { LightLogs::create(new LivePreview()) ->increment() - ->queue(); + ->batch(); } From 3613a0e2d519ad7b7c4f1d5b3edaf07f99bcab78 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 10 Sep 2022 09:44:43 +1000 Subject: [PATCH 03/27] Improve client imports --- .../ValidationRules/Account/BlackListRule.php | 1 + app/Import/Providers/BaseImport.php | 20 ++--- composer.lock | 75 ++++++++++--------- 3 files changed, 49 insertions(+), 47 deletions(-) diff --git a/app/Http/ValidationRules/Account/BlackListRule.php b/app/Http/ValidationRules/Account/BlackListRule.php index 0a2a681f0ff3..17357088001d 100644 --- a/app/Http/ValidationRules/Account/BlackListRule.php +++ b/app/Http/ValidationRules/Account/BlackListRule.php @@ -26,6 +26,7 @@ class BlackListRule implements Rule 'arxxwalls.com', 'superhostforumla.com', 'wnpop.com', + 'dataservices.space', ]; /** diff --git a/app/Import/Providers/BaseImport.php b/app/Import/Providers/BaseImport.php index e63bffe6cbbb..1ec4151e88ad 100644 --- a/app/Import/Providers/BaseImport.php +++ b/app/Import/Providers/BaseImport.php @@ -173,18 +173,18 @@ class BaseImport $is_free_hosted_client = $this->company->account->isFreeHostedClient(); $hosted_client_count = $this->company->account->hosted_client_count; + if($this->factory_name instanceof ClientFactory && $is_free_hosted_client && (count($data) > $hosted_client_count)) + { + $this->error_array[$entity_type][] = [ + $entity_type => 'client', + 'error' => 'Error, you are attempting to import more clients than your plan allows', + ]; + + return $count; + } + foreach ($data as $key => $record) { - if($this->factory_name instanceof ClientFactory && $is_free_hosted_client && ($this->company->clients()->count() > $hosted_client_count)) - { - $this->error_array[$entity_type][] = [ - $entity_type => $record, - 'error' => 'Client limit reached', - ]; - - return $count; - } - try { $entity = $this->transformer->transform($record); // $validator = $this->request_name::runFormRequest($entity); diff --git a/composer.lock b/composer.lock index 725da7645b19..33dfd47e41b0 100644 --- a/composer.lock +++ b/composer.lock @@ -378,16 +378,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.235.3", + "version": "3.235.5", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "d14bf468240f5bd8a0754b8a8248ff219ebada02" + "reference": "3b002b92369dbcb8d86f32546cb324eabcd19a4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d14bf468240f5bd8a0754b8a8248ff219ebada02", - "reference": "d14bf468240f5bd8a0754b8a8248ff219ebada02", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3b002b92369dbcb8d86f32546cb324eabcd19a4e", + "reference": "3b002b92369dbcb8d86f32546cb324eabcd19a4e", "shasum": "" }, "require": { @@ -464,9 +464,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.235.3" + "source": "https://github.com/aws/aws-sdk-php/tree/3.235.5" }, - "time": "2022-09-07T18:17:39+00:00" + "time": "2022-09-09T18:19:38+00:00" }, { "name": "bacon/bacon-qr-code", @@ -3481,16 +3481,16 @@ }, { "name": "laravel/framework", - "version": "v9.28.0", + "version": "v9.29.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "396a89e1f3654123d1c7f56306051212e5c75bc0" + "reference": "585da0913e907fd54941260860ae3d7d4be8e8cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/396a89e1f3654123d1c7f56306051212e5c75bc0", - "reference": "396a89e1f3654123d1c7f56306051212e5c75bc0", + "url": "https://api.github.com/repos/laravel/framework/zipball/585da0913e907fd54941260860ae3d7d4be8e8cb", + "reference": "585da0913e907fd54941260860ae3d7d4be8e8cb", "shasum": "" }, "require": { @@ -3657,20 +3657,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-09-06T14:57:01+00:00" + "time": "2022-09-09T18:21:21+00:00" }, { "name": "laravel/serializable-closure", - "version": "v1.2.1", + "version": "v1.2.2", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "d78fd36ba031a1a695ea5a406f29996948d7011b" + "reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/d78fd36ba031a1a695ea5a406f29996948d7011b", - "reference": "d78fd36ba031a1a695ea5a406f29996948d7011b", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/47afb7fae28ed29057fdca37e16a84f90cc62fae", + "reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae", "shasum": "" }, "require": { @@ -3717,7 +3717,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2022-08-26T15:25:27+00:00" + "time": "2022-09-08T13:45:54+00:00" }, { "name": "laravel/slack-notification-channel", @@ -4387,16 +4387,16 @@ }, { "name": "league/flysystem", - "version": "3.2.1", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "81aea9e5217084c7850cd36e1587ee4aad721c6b" + "reference": "d8295793b3e2f91aa39e1feb2d5bfce772891ae2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/81aea9e5217084c7850cd36e1587ee4aad721c6b", - "reference": "81aea9e5217084c7850cd36e1587ee4aad721c6b", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/d8295793b3e2f91aa39e1feb2d5bfce772891ae2", + "reference": "d8295793b3e2f91aa39e1feb2d5bfce772891ae2", "shasum": "" }, "require": { @@ -4407,6 +4407,7 @@ "aws/aws-sdk-php": "3.209.31 || 3.210.0", "guzzlehttp/guzzle": "<7.0", "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", "symfony/http-client": "<5.2" }, "require-dev": { @@ -4420,7 +4421,7 @@ "friendsofphp/php-cs-fixer": "^3.5", "google/cloud-storage": "^1.23", "microsoft/azure-storage-blob": "^1.1", - "phpseclib/phpseclib": "^2.0", + "phpseclib/phpseclib": "^3.0.14", "phpstan/phpstan": "^0.12.26", "phpunit/phpunit": "^9.5.11", "sabre/dav": "^4.3.1" @@ -4457,11 +4458,11 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.2.1" + "source": "https://github.com/thephpleague/flysystem/tree/3.3.0" }, "funding": [ { - "url": "https://offset.earth/frankdejonge", + "url": "https://ecologi.com/frankdejonge", "type": "custom" }, { @@ -4473,20 +4474,20 @@ "type": "tidelift" } ], - "time": "2022-08-14T20:48:34+00:00" + "time": "2022-09-09T11:11:42+00:00" }, { "name": "league/flysystem-aws-s3-v3", - "version": "3.2.0", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "257893ef7398b3c9255b26dff8b0118bb93fc5ff" + "reference": "c9402e0b8d89d36b1b88ecf88c2a80b6d61fd114" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/257893ef7398b3c9255b26dff8b0118bb93fc5ff", - "reference": "257893ef7398b3c9255b26dff8b0118bb93fc5ff", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/c9402e0b8d89d36b1b88ecf88c2a80b6d61fd114", + "reference": "c9402e0b8d89d36b1b88ecf88c2a80b6d61fd114", "shasum": "" }, "require": { @@ -4527,11 +4528,11 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem-aws-s3-v3/issues", - "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.2.0" + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.3.0" }, "funding": [ { - "url": "https://offset.earth/frankdejonge", + "url": "https://ecologi.com/frankdejonge", "type": "custom" }, { @@ -4543,7 +4544,7 @@ "type": "tidelift" } ], - "time": "2022-07-26T07:22:40+00:00" + "time": "2022-09-09T10:03:42+00:00" }, { "name": "league/fractal", @@ -11988,16 +11989,16 @@ }, { "name": "turbo124/beacon", - "version": "v1.3.2", + "version": "v1.3.4", "source": { "type": "git", "url": "https://github.com/turbo124/beacon.git", - "reference": "e46e6122e28c2a7628ad40975bfd11a3ab883575" + "reference": "4a0c9c6af3d88142e89184e67e9f0547078d5ef0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/turbo124/beacon/zipball/e46e6122e28c2a7628ad40975bfd11a3ab883575", - "reference": "e46e6122e28c2a7628ad40975bfd11a3ab883575", + "url": "https://api.github.com/repos/turbo124/beacon/zipball/4a0c9c6af3d88142e89184e67e9f0547078d5ef0", + "reference": "4a0c9c6af3d88142e89184e67e9f0547078d5ef0", "shasum": "" }, "require": { @@ -12044,9 +12045,9 @@ "turbo124" ], "support": { - "source": "https://github.com/turbo124/beacon/tree/v1.3.2" + "source": "https://github.com/turbo124/beacon/tree/v1.3.4" }, - "time": "2022-09-08T08:08:59+00:00" + "time": "2022-09-09T23:30:23+00:00" }, { "name": "twilio/sdk", From 2cdc33149bbbbfa81395e80415610b7a15ed1e4a Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 11 Sep 2022 15:50:00 +1000 Subject: [PATCH 04/27] Add recurring invoice id to expense when it is generated --- app/Factory/RecurringExpenseToExpenseFactory.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/Factory/RecurringExpenseToExpenseFactory.php b/app/Factory/RecurringExpenseToExpenseFactory.php index 1f44a75d5a77..80e1378a9b0a 100644 --- a/app/Factory/RecurringExpenseToExpenseFactory.php +++ b/app/Factory/RecurringExpenseToExpenseFactory.php @@ -44,6 +44,10 @@ class RecurringExpenseToExpenseFactory $expense->payment_date = $recurring_expense->payment_date; $expense->amount = $recurring_expense->amount; $expense->foreign_amount = $recurring_expense->foreign_amount ?: 0; + + //11-09-2022 - we should be tracking the recurring expense!! + $expense->recurring_expense_id = $recurring_expense->id; + // $expense->private_notes = $recurring_expense->private_notes; // $expense->public_notes = $recurring_expense->public_notes; From 316daa166e5346e133210f4c66bc66724ce40f93 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 11 Sep 2022 20:29:11 +1000 Subject: [PATCH 05/27] Fixes for support messages --- app/Mail/SupportMessageSent.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Mail/SupportMessageSent.php b/app/Mail/SupportMessageSent.php index 5278d495cf84..f83eee125e98 100644 --- a/app/Mail/SupportMessageSent.php +++ b/app/Mail/SupportMessageSent.php @@ -8,6 +8,7 @@ use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; use LimitIterator; use SplFileObject; +use Illuminate\Support\Carbon; class SupportMessageSent extends Mailable { @@ -73,7 +74,7 @@ class SupportMessageSent extends Mailable $plan_status = ''; if(Carbon::parse($account->plan_expires)->lt(now())) - $plan_status = 'Plan Expired'; + $plan_status = 'Plan Expired :: '; if (Ninja::isHosted()) { $subject = "{$priority}Hosted-{$db}-{$is_large}{$platform}{$migrated}{$trial} :: {$plan} :: {$plan_status} ".date('M jS, g:ia'); From e90710d2f00ff9534b9d7eae7508ef650c2f6d82 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 11 Sep 2022 22:03:36 +1000 Subject: [PATCH 06/27] Fixes for check data --- app/Console/Commands/CheckData.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Console/Commands/CheckData.php b/app/Console/Commands/CheckData.php index 6349202a7d2d..0f7061f0a9ac 100644 --- a/app/Console/Commands/CheckData.php +++ b/app/Console/Commands/CheckData.php @@ -20,6 +20,7 @@ use App\Models\Client; use App\Models\ClientContact; use App\Models\Company; use App\Models\CompanyLedger; +use App\Models\CompanyUser; use App\Models\Contact; use App\Models\Credit; use App\Models\CreditInvitation; From 2346a4452d4786e8592e298550efd9444194e9dd Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 12 Sep 2022 07:09:20 +1000 Subject: [PATCH 07/27] Minor fixes for support messages --- app/Mail/SupportMessageSent.php | 2 +- composer.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/Mail/SupportMessageSent.php b/app/Mail/SupportMessageSent.php index f83eee125e98..7258aa19bf01 100644 --- a/app/Mail/SupportMessageSent.php +++ b/app/Mail/SupportMessageSent.php @@ -73,7 +73,7 @@ class SupportMessageSent extends Mailable $plan_status = ''; - if(Carbon::parse($account->plan_expires)->lt(now())) + if($account->plan_expires && Carbon::parse($account->plan_expires)->lt(now())) $plan_status = 'Plan Expired :: '; if (Ninja::isHosted()) { diff --git a/composer.lock b/composer.lock index 33dfd47e41b0..add2c282c382 100644 --- a/composer.lock +++ b/composer.lock @@ -1577,16 +1577,16 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.3.1", + "version": "v3.3.2", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "be85b3f05b46c39bbc0d95f6c071ddff669510fa" + "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/be85b3f05b46c39bbc0d95f6c071ddff669510fa", - "reference": "be85b3f05b46c39bbc0d95f6c071ddff669510fa", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8", + "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8", "shasum": "" }, "require": { @@ -1626,7 +1626,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.1" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2" }, "funding": [ { @@ -1634,7 +1634,7 @@ "type": "github" } ], - "time": "2022-01-18T15:43:28+00:00" + "time": "2022-09-10T18:51:20+00:00" }, { "name": "egulias/email-validator", From d68918b213b062eb71d4f9b61a506968d5b031bf Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 12 Sep 2022 08:33:59 +1000 Subject: [PATCH 08/27] Ensure we also query trashed client records before lock --- app/Services/Client/ClientService.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Services/Client/ClientService.php b/app/Services/Client/ClientService.php index 9e9c5fbf9579..a4d033c34559 100644 --- a/app/Services/Client/ClientService.php +++ b/app/Services/Client/ClientService.php @@ -33,7 +33,7 @@ class ClientService \DB::connection(config('database.default'))->transaction(function () use($amount) { - $this->client = Client::where('id', $this->client->id)->lockForUpdate()->first(); + $this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first(); $this->client->balance += $amount; $this->client->save(); @@ -49,7 +49,7 @@ class ClientService \DB::connection(config('database.default'))->transaction(function () use($balance, $paid_to_date) { - $this->client = Client::where('id', $this->client->id)->lockForUpdate()->first(); + $this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first(); $this->client->balance += $balance; $this->client->paid_to_date += $paid_to_date; $this->client->save(); @@ -65,7 +65,7 @@ class ClientService \DB::connection(config('database.default'))->transaction(function () use($amount) { - $this->client = Client::where('id', $this->client->id)->lockForUpdate()->first(); + $this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first(); $this->client->paid_to_date += $amount; $this->client->save(); @@ -83,7 +83,7 @@ class ClientService public function getCreditBalance() :float { - $credits = Credit::where('client_id', $this->client->id) + $credits = Credit::withTrashed()->where('client_id', $this->client->id) ->where('is_deleted', false) ->where('balance', '>', 0) ->where(function ($query) { From 3a33be37a0f63f4cb7bcfa2eee016ed75668fc0d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 12 Sep 2022 10:00:05 +1000 Subject: [PATCH 09/27] Logging around generates counter --- app/Utils/Traits/GeneratesCounter.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/Utils/Traits/GeneratesCounter.php b/app/Utils/Traits/GeneratesCounter.php index 4175acbe55e9..682611849449 100644 --- a/app/Utils/Traits/GeneratesCounter.php +++ b/app/Utils/Traits/GeneratesCounter.php @@ -416,6 +416,7 @@ trait GeneratesCounter { $check = false; $check_counter = 1; + $original_counter = $counter; do { $number = $this->padCounter($counter, $padding); @@ -430,6 +431,12 @@ trait GeneratesCounter $check_counter++; if ($check_counter > 100) { + + nlog("counter error"); + nlog("original_counter = {$original_counter}"); + nlog("counter = {$counter}"); + nlog("returning = {$number}"); + return $number.'_'.Str::random(5); } } while ($check); From ab2d5299231f9e6dab6e8beac8182ac4509eb595 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 12 Sep 2022 12:32:16 +1000 Subject: [PATCH 10/27] Additional logging in generates counter --- app/Utils/Traits/GeneratesCounter.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/Utils/Traits/GeneratesCounter.php b/app/Utils/Traits/GeneratesCounter.php index 682611849449..0f311c4fc013 100644 --- a/app/Utils/Traits/GeneratesCounter.php +++ b/app/Utils/Traits/GeneratesCounter.php @@ -412,20 +412,22 @@ trait GeneratesCounter * @param string $prefix * @return string The padded and prefixed entity number */ - private function checkEntityNumber($class, $entity, $counter, $padding, $pattern, $prefix = '') + private function checkEntityNumber($class, $entity, $counter, $padding, $pattern, $prefix = '') :string { $check = false; $check_counter = 1; $original_counter = $counter; do { + nlog($check_counter); + $number = $this->padCounter($counter, $padding); $number = $this->applyNumberPattern($entity, $number, $pattern); $number = $this->prefixCounter($number, $prefix); - $check = $class::whereCompanyId($entity->company_id)->whereNumber($number)->withTrashed()->exists(); + $check = $class::where('company_id', $entity->company_id)->where('number', $number)->withTrashed()->exists(); $counter++; $check_counter++; @@ -434,13 +436,17 @@ trait GeneratesCounter nlog("counter error"); nlog("original_counter = {$original_counter}"); + nlog("entity company = {$entity->company_id}"); nlog("counter = {$counter}"); nlog("returning = {$number}"); return $number.'_'.Str::random(5); } + } while ($check); + nlog($number); + return $number; } @@ -465,10 +471,12 @@ trait GeneratesCounter $settings = $entity->settings; if ($counter_name == 'invoice_number_counter' && ! property_exists($entity->settings, 'invoice_number_counter')) { + nlog("BAD STATE - why no invoice_number_counter set?"); $settings->invoice_number_counter = 0; } if (! property_exists($settings, $counter_name)) { + nlog("BAD STATE - why no {$counter_name} set?"); $settings->{$counter_name} = 1; } From 9dd06fae3498305464e4bc506518ea24c68c04ad Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 12 Sep 2022 13:03:39 +1000 Subject: [PATCH 11/27] minor fixes + additional logging --- app/Services/Invoice/MarkPaid.php | 2 +- app/Utils/Traits/GeneratesCounter.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Services/Invoice/MarkPaid.php b/app/Services/Invoice/MarkPaid.php index 9c60591515f6..60182238642c 100644 --- a/app/Services/Invoice/MarkPaid.php +++ b/app/Services/Invoice/MarkPaid.php @@ -55,7 +55,7 @@ class MarkPaid extends AbstractService \DB::connection(config('database.default'))->transaction(function () { - $this->invoice = Invoice::where('id', $this->invoice->id)->lockForUpdate()->first(); + $this->invoice = Invoice::withTrashed()->where('id', $this->invoice->id)->lockForUpdate()->first(); $this->payable_balance = $this->invoice->balance; diff --git a/app/Utils/Traits/GeneratesCounter.php b/app/Utils/Traits/GeneratesCounter.php index 0f311c4fc013..9dea5d139e02 100644 --- a/app/Utils/Traits/GeneratesCounter.php +++ b/app/Utils/Traits/GeneratesCounter.php @@ -435,6 +435,7 @@ trait GeneratesCounter if ($check_counter > 100) { nlog("counter error"); + nlog("check counter = {$check_counter}"); nlog("original_counter = {$original_counter}"); nlog("entity company = {$entity->company_id}"); nlog("counter = {$counter}"); From a1629bbab4e0839eb81ead3d2d93527ffa1812c6 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 12 Sep 2022 21:08:50 +1000 Subject: [PATCH 12/27] Fixes for applying numbers --- app/Http/Requests/Invoice/StoreInvoiceRequest.php | 2 +- app/Models/Client.php | 6 +++--- app/Services/Invoice/ApplyNumber.php | 4 +++- app/Utils/Traits/GeneratesCounter.php | 14 +------------- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/app/Http/Requests/Invoice/StoreInvoiceRequest.php b/app/Http/Requests/Invoice/StoreInvoiceRequest.php index 2cb1535c5bee..9387866e3685 100644 --- a/app/Http/Requests/Invoice/StoreInvoiceRequest.php +++ b/app/Http/Requests/Invoice/StoreInvoiceRequest.php @@ -62,7 +62,7 @@ class StoreInvoiceRequest extends Request $rules['invitations.*.client_contact_id'] = 'distinct'; - $rules['number'] = ['nullable', Rule::unique('invoices')->where('company_id', auth()->user()->company()->id)]; + $rules['number'] = ['bail', 'nullable', Rule::unique('invoices')->where('company_id', auth()->user()->company()->id)]; $rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())]; $rules['is_amount_discount'] = ['boolean']; diff --git a/app/Models/Client.php b/app/Models/Client.php index 5c414e978ae4..7b09fa68f80e 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -613,19 +613,19 @@ class Client extends BaseModel implements HasLocalePreference { $defaults = []; - if (! (array_key_exists('terms', $data) && strlen($data['terms']) > 1)) { + if (! (array_key_exists('terms', $data) && is_string($data['terms']) && strlen($data['terms']) > 1)) { $defaults['terms'] = $this->getSetting($entity_name.'_terms'); } elseif (array_key_exists('terms', $data)) { $defaults['terms'] = $data['terms']; } - if (! (array_key_exists('footer', $data) && strlen($data['footer']) > 1)) { + if (! (array_key_exists('footer', $data) && is_string($data['footer']) && strlen($data['footer']) > 1)) { $defaults['footer'] = $this->getSetting($entity_name.'_footer'); } elseif (array_key_exists('footer', $data)) { $defaults['footer'] = $data['footer']; } - if (strlen($this->public_notes) >= 1) { + if (is_string($this->public_notes) && strlen($this->public_notes) >= 1) { $defaults['public_notes'] = $this->public_notes; } diff --git a/app/Services/Invoice/ApplyNumber.php b/app/Services/Invoice/ApplyNumber.php index 58b976eb2b86..d71faf7c73ae 100644 --- a/app/Services/Invoice/ApplyNumber.php +++ b/app/Services/Invoice/ApplyNumber.php @@ -70,7 +70,6 @@ class ApplyNumber extends AbstractService $this->invoice->saveQuietly(); $this->completed = false; - } catch(QueryException $e){ @@ -84,5 +83,8 @@ class ApplyNumber extends AbstractService } while($this->completed); + + return $this; } + } diff --git a/app/Utils/Traits/GeneratesCounter.php b/app/Utils/Traits/GeneratesCounter.php index 9dea5d139e02..2debb8ac9647 100644 --- a/app/Utils/Traits/GeneratesCounter.php +++ b/app/Utils/Traits/GeneratesCounter.php @@ -416,10 +416,8 @@ trait GeneratesCounter { $check = false; $check_counter = 1; - $original_counter = $counter; do { - nlog($check_counter); $number = $this->padCounter($counter, $padding); @@ -433,21 +431,13 @@ trait GeneratesCounter $check_counter++; if ($check_counter > 100) { - - nlog("counter error"); - nlog("check counter = {$check_counter}"); - nlog("original_counter = {$original_counter}"); - nlog("entity company = {$entity->company_id}"); - nlog("counter = {$counter}"); - nlog("returning = {$number}"); return $number.'_'.Str::random(5); + } } while ($check); - nlog($number); - return $number; } @@ -472,12 +462,10 @@ trait GeneratesCounter $settings = $entity->settings; if ($counter_name == 'invoice_number_counter' && ! property_exists($entity->settings, 'invoice_number_counter')) { - nlog("BAD STATE - why no invoice_number_counter set?"); $settings->invoice_number_counter = 0; } if (! property_exists($settings, $counter_name)) { - nlog("BAD STATE - why no {$counter_name} set?"); $settings->{$counter_name} = 1; } From 0c0687febeffdb3c6f7e71403d6bec81428b3939 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 13 Sep 2022 07:54:32 +1000 Subject: [PATCH 13/27] Fixes for entity policy not capturing recurring invoice policies --- app/Policies/EntityPolicy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Policies/EntityPolicy.php b/app/Policies/EntityPolicy.php index 08beb1c9d7d4..c007aecdf7b3 100644 --- a/app/Policies/EntityPolicy.php +++ b/app/Policies/EntityPolicy.php @@ -47,7 +47,7 @@ class EntityPolicy public function edit(User $user, $entity) : bool { return ($user->isAdmin() && $entity->company_id == $user->companyId()) - || ($user->hasPermission('edit_'.strtolower(class_basename($entity))) && $entity->company_id == $user->companyId()) + || ($user->hasPermission('edit_'.strtolower(\Illuminate\Support\Str::snake(class_basename($entity)))) && $entity->company_id == $user->companyId()) || ($user->hasPermission('edit_all') && $entity->company_id == $user->companyId()) || $user->owns($entity) || $user->assigned($entity); From be19d42e78129c9eb5aac081ce8499aa96623557 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 13 Sep 2022 09:59:16 +1000 Subject: [PATCH 14/27] Update customer details --- app/Http/Livewire/RequiredClientInfo.php | 16 ++++++++++ .../Stripe/Jobs/UpdateCustomer.php | 6 ++-- app/PaymentDrivers/StripePaymentDriver.php | 30 +++++++++++++++++++ .../ninja2020/layout/payments.blade.php | 2 +- 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/app/Http/Livewire/RequiredClientInfo.php b/app/Http/Livewire/RequiredClientInfo.php index 349c8391547c..3778834bb665 100644 --- a/app/Http/Livewire/RequiredClientInfo.php +++ b/app/Http/Livewire/RequiredClientInfo.php @@ -14,6 +14,7 @@ namespace App\Http\Livewire; use App\Libraries\MultiDB; use App\Models\ClientContact; +use App\Models\CompanyGateway; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; use Livewire\Component; @@ -105,6 +106,8 @@ class RequiredClientInfo extends Component public $company; + public $company_gateway_id; + public function mount() { MultiDB::setDb($this->company->db); @@ -141,6 +144,8 @@ class RequiredClientInfo extends Component 'client_postal_code' => $this->contact->client->postal_code, ]); + //if stripe is enabled, we want to update the customer at this point. + return true; } @@ -150,6 +155,7 @@ class RequiredClientInfo extends Component private function updateClientDetails(array $data): bool { + nlog($this->company->id); $client = []; $contact = []; @@ -172,6 +178,16 @@ class RequiredClientInfo extends Component ->push(); if ($contact_update && $client_update) { + + $cg = CompanyGateway::find($this->company_gateway_id); + + if($cg && $cg->update_details){ + $payment_gateway = $cg->driver($this->client)->init(); + + if(method_exists($payment_gateway, "updateCustomer")) + $payment_gateway->updateCustomer(); + } + return true; } diff --git a/app/PaymentDrivers/Stripe/Jobs/UpdateCustomer.php b/app/PaymentDrivers/Stripe/Jobs/UpdateCustomer.php index a9aadefde559..add84804a95b 100644 --- a/app/PaymentDrivers/Stripe/Jobs/UpdateCustomer.php +++ b/app/PaymentDrivers/Stripe/Jobs/UpdateCustomer.php @@ -58,12 +58,12 @@ class UpdateCustomer implements ShouldQueue $company = Company::where('company_key', $this->company_key)->first(); - if($company->id !== config('ninja.ninja_default_company_id')) - return; - $company_gateway = CompanyGateway::find($this->company_gateway_id); $client = Client::withTrashed()->find($this->client_id); + if(!$company_gateway->update_details) + return; + $stripe = $company_gateway->driver($client)->init(); $customer = $stripe->findOrCreateCustomer(); diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index 4c3303f98bce..a46d17ace9c8 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -511,6 +511,36 @@ class StripePaymentDriver extends BaseDriver } } + public function updateCustomer() + { + if($this->client) + { + + $customer = $this->findOrCreateCustomer(); + //Else create a new record + $data['name'] = $this->client->present()->name(); + $data['phone'] = substr($this->client->present()->phone(), 0, 20); + + $data['address']['line1'] = $this->client->address1; + $data['address']['line2'] = $this->client->address2; + $data['address']['city'] = $this->client->city; + $data['address']['postal_code'] = $this->client->postal_code; + $data['address']['state'] = $this->client->state; + $data['address']['country'] = $this->client->country ? $this->client->country->iso_3166_2 : ''; + + $data['shipping']['name'] = $this->client->present()->name(); + $data['shipping']['address']['line1'] = $this->client->shipping_address1; + $data['shipping']['address']['line2'] = $this->client->shipping_address2; + $data['shipping']['address']['city'] = $this->client->shipping_city; + $data['shipping']['address']['postal_code'] = $this->client->shipping_postal_code; + $data['shipping']['address']['state'] = $this->client->shipping_state; + $data['shipping']['address']['country'] = $this->client->shipping_country ? $this->client->shipping_country->iso_3166_2 : ''; + + \Stripe\Customer::update($customer->id, $data, $this->stripe_connect_auth); + + } + } + public function refund(Payment $payment, $amount, $return_client_response = false) { $this->init(); diff --git a/resources/views/portal/ninja2020/layout/payments.blade.php b/resources/views/portal/ninja2020/layout/payments.blade.php index b21a08abc7cf..9101bff6c5b5 100644 --- a/resources/views/portal/ninja2020/layout/payments.blade.php +++ b/resources/views/portal/ninja2020/layout/payments.blade.php @@ -11,7 +11,7 @@ @endpush @section('body') - @livewire('required-client-info', ['fields' => method_exists($gateway, 'getClientRequiredFields') ? $gateway->getClientRequiredFields() : [], 'contact' => auth()->guard('contact')->user(), 'countries' => $countries, 'company' => $company]) + @livewire('required-client-info', ['fields' => method_exists($gateway, 'getClientRequiredFields') ? $gateway->getClientRequiredFields() : [], 'contact' => auth()->guard('contact')->user(), 'countries' => $countries, 'company' => $company, 'company_gateway_id' => $gateway->company_gateway->id])
From 3d32cc7ac8ac7bacbbf8368a77a7a7820e54ace2 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 13 Sep 2022 16:37:56 +1000 Subject: [PATCH 15/27] Fixes for restricting csv imports --- app/Import/Providers/BaseImport.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Import/Providers/BaseImport.php b/app/Import/Providers/BaseImport.php index 1ec4151e88ad..365ee46b37cc 100644 --- a/app/Import/Providers/BaseImport.php +++ b/app/Import/Providers/BaseImport.php @@ -173,7 +173,7 @@ class BaseImport $is_free_hosted_client = $this->company->account->isFreeHostedClient(); $hosted_client_count = $this->company->account->hosted_client_count; - if($this->factory_name instanceof ClientFactory && $is_free_hosted_client && (count($data) > $hosted_client_count)) + if($this->factory_name == 'App\Factory\ClientFactory' && $is_free_hosted_client && (count($data) > $hosted_client_count)) { $this->error_array[$entity_type][] = [ $entity_type => 'client', From 20f398d49b5dd46b87164f9912335c8139be8233 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 13 Sep 2022 19:32:53 +1000 Subject: [PATCH 16/27] Add redundancy checks when creating task numbers --- app/Repositories/InvoiceRepository.php | 1 - app/Repositories/TaskRepository.php | 33 +++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/app/Repositories/InvoiceRepository.php b/app/Repositories/InvoiceRepository.php index 3c60618501b1..eea2ae5ffb58 100644 --- a/app/Repositories/InvoiceRepository.php +++ b/app/Repositories/InvoiceRepository.php @@ -68,7 +68,6 @@ class InvoiceRepository extends BaseRepository return $invoice; } -// $invoice->service()->markDeleted()->handleCancellation()->save(); $invoice = $invoice->service()->markDeleted()->save(); parent::delete($invoice); diff --git a/app/Repositories/TaskRepository.php b/app/Repositories/TaskRepository.php index 386a9fd2c8c2..8acf1ec73dfb 100644 --- a/app/Repositories/TaskRepository.php +++ b/app/Repositories/TaskRepository.php @@ -14,6 +14,7 @@ namespace App\Repositories; use App\Factory\TaskFactory; use App\Models\Task; use App\Utils\Traits\GeneratesCounter; +use Illuminate\Database\QueryException; /** * TaskRepository. @@ -45,7 +46,7 @@ class TaskRepository extends BaseRepository $this->setDefaultStatus($task); } - $task->number = empty($task->number) || ! array_key_exists('number', $data) ? $this->getNextTaskNumber($task) : $data['number']; + $task->number = empty($task->number) || ! array_key_exists('number', $data) ? $this->trySaving($task) : $data['number']; if (isset($data['description'])) { $task->description = trim($data['description']); @@ -244,4 +245,34 @@ class TaskRepository extends BaseRepository return $task; } + + + private function trySaving(Task $task) + { + + $x=1; + + do{ + + try{ + + $task->number = $this->getNextTaskNumber($task); + $task->saveQuietly(); + $this->completed = false; + + } + catch(QueryException $e){ + + $x++; + + if($x>50) + $this->completed = false; + } + + } + while($this->completed); + + return $task->number; + + } } From 5de7d0954120d0115b6c8740aa140dcc72a12cfd Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Sep 2022 08:15:32 +1000 Subject: [PATCH 17/27] Port entity policy changes to view() policy --- app/Policies/EntityPolicy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Policies/EntityPolicy.php b/app/Policies/EntityPolicy.php index c007aecdf7b3..c7c45f28e9e6 100644 --- a/app/Policies/EntityPolicy.php +++ b/app/Policies/EntityPolicy.php @@ -64,7 +64,7 @@ class EntityPolicy public function view(User $user, $entity) : bool { return ($user->isAdmin() && $entity->company_id == $user->companyId()) - || ($user->hasPermission('view_'.strtolower(class_basename($entity))) && $entity->company_id == $user->companyId()) + || ($user->hasPermission('view_'.strtolower(\Illuminate\Support\Str::snake(class_basename($entity)))) && $entity->company_id == $user->companyId()) || ($user->hasPermission('view_all') && $entity->company_id == $user->companyId()) || $user->owns($entity) || $user->assigned($entity); From 2845f2c79e8d015f79c4e3e433da9102e09670a4 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Sep 2022 10:51:41 +1000 Subject: [PATCH 18/27] Set SEPA stripe token payments to pending --- app/PaymentDrivers/Stripe/Charge.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/PaymentDrivers/Stripe/Charge.php b/app/PaymentDrivers/Stripe/Charge.php index d9f7253a4e32..f1dee3019796 100644 --- a/app/PaymentDrivers/Stripe/Charge.php +++ b/app/PaymentDrivers/Stripe/Charge.php @@ -17,11 +17,12 @@ use App\Jobs\Util\SystemLogger; use App\Models\ClientGatewayToken; use App\Models\GatewayType; use App\Models\Invoice; +use App\Models\Payment; use App\Models\PaymentHash; use App\Models\PaymentType; use App\Models\SystemLog; -use App\PaymentDrivers\Stripe\ACH; use App\PaymentDrivers\StripePaymentDriver; +use App\PaymentDrivers\Stripe\ACH; use App\Utils\Ninja; use App\Utils\Traits\MakesHash; use Stripe\Exception\ApiConnectionException; @@ -137,8 +138,10 @@ class Charge if ($cgt->gateway_type_id == GatewayType::SEPA) { $payment_method_type = PaymentType::SEPA; + $status = Payment::STATUS_PENDING; } else { $payment_method_type = $response->charges->data[0]->payment_method_details->card->brand; + $status = Payment::STATUS_COMPLETED; } $data = [ @@ -148,7 +151,7 @@ class Charge 'amount' => $amount, ]; - $payment = $this->stripe->createPayment($data); + $payment = $this->stripe->createPayment($data, $status); $payment->meta = $cgt->meta; $payment->save(); From 895bb8deeff58e95a369836092639a8e47e1ef7a Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Sep 2022 11:33:54 +1000 Subject: [PATCH 19/27] Fixes for QR Ibans with no payment references --- app/DataMapper/CompanySettings.php | 1 + app/Helpers/SwissQr/SwissQrGenerator.php | 36 ++++++++++++++++++------ app/Utils/HtmlEngine.php | 2 +- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index ecc93b0d42d1..f99d52ce5d5b 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -26,6 +26,7 @@ class CompanySettings extends BaseSettings public $auto_archive_invoice = false; // @implemented public $qr_iban = ''; //@implemented + public $besr_id = ''; //@implemented public $lock_invoices = 'off'; //off,when_sent,when_paid //@implemented diff --git a/app/Helpers/SwissQr/SwissQrGenerator.php b/app/Helpers/SwissQr/SwissQrGenerator.php index 354b76392190..0302fcc657b8 100644 --- a/app/Helpers/SwissQr/SwissQrGenerator.php +++ b/app/Helpers/SwissQr/SwissQrGenerator.php @@ -104,16 +104,32 @@ class SwissQrGenerator // Add payment reference // This is what you will need to identify incoming payments. - $referenceNumber = QrBill\Reference\QrPaymentReferenceGenerator::generate( - $this->company->present()->besr_id() ?: '', // You receive this number from your bank (BESR-ID). Unless your bank is PostFinance, in that case use NULL. - $this->invoice->number// A number to match the payment with your internal data, e.g. an invoice number - ); - $qrBill->setPaymentReference( - QrBill\DataGroup\Element\PaymentReference::create( - QrBill\DataGroup\Element\PaymentReference::TYPE_QR, - $referenceNumber - )); + if(strlen($this->company->present()->besr_id()) > 1) + { + nlog("i have a besr"); + + $referenceNumber = QrBill\Reference\QrPaymentReferenceGenerator::generate( + $this->company->present()->besr_id() ?: '', // You receive this number from your bank (BESR-ID). Unless your bank is PostFinance, in that case use NULL. + $this->invoice->number// A number to match the payment with your internal data, e.g. an invoice number + ); + + $qrBill->setPaymentReference( + QrBill\DataGroup\Element\PaymentReference::create( + QrBill\DataGroup\Element\PaymentReference::TYPE_QR, + $referenceNumber + )); + + } + else{ + + nlog("i have no besr"); + $qrBill->setPaymentReference( + QrBill\DataGroup\Element\PaymentReference::create( + QrBill\DataGroup\Element\PaymentReference::TYPE_NON + )); + + } // Optionally, add some human-readable information about what the bill is for. $qrBill->setAdditionalInformation( @@ -141,6 +157,8 @@ class SwissQrGenerator nlog($violation); } + nlog($e->getMessage()); + return ''; // return $e->getMessage(); } diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php index d9141493f4f4..dae1e0f8ad25 100644 --- a/app/Utils/HtmlEngine.php +++ b/app/Utils/HtmlEngine.php @@ -168,7 +168,7 @@ class HtmlEngine $data['$invoice.vendor'] = ['value' => $this->entity->vendor->present()->name(), 'label' => ctrans('texts.vendor_name')]; } - if(strlen($this->company->getSetting('qr_iban')) > 5 && strlen($this->company->getSetting('besr_id')) > 1) + if(strlen($this->company->getSetting('qr_iban')) > 5) { try{ $data['$swiss_qr'] = ['value' => (new SwissQrGenerator($this->entity, $this->company))->run(), 'label' => '']; From 84347eb58352f83463d806b55b6c4af6a9db3ff7 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Sep 2022 13:08:35 +1000 Subject: [PATCH 20/27] Add logging --- app/Repositories/BaseRepository.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Repositories/BaseRepository.php b/app/Repositories/BaseRepository.php index 969bfc57363a..4611774fdc80 100644 --- a/app/Repositories/BaseRepository.php +++ b/app/Repositories/BaseRepository.php @@ -304,7 +304,9 @@ class BaseRepository if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) { - //10-07-2022 + //14-09-2022 log when we make changes to the invoice balance. + nlog("Adjustment - {$model->number} - " .$state['finished_amount']. " - " . $state['starting_amount']); + $model->service()->updateStatus()->save(); $model->client->service()->updateBalance(($state['finished_amount'] - $state['starting_amount']))->save(); $model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount']), "Update adjustment for invoice {$model->number}"); From c57c40aa276a2f41b8fc737d3057ae3e704ac3aa Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Sep 2022 13:37:39 +1000 Subject: [PATCH 21/27] Remove logging --- app/Helpers/SwissQr/SwissQrGenerator.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/Helpers/SwissQr/SwissQrGenerator.php b/app/Helpers/SwissQr/SwissQrGenerator.php index 0302fcc657b8..105b0807119d 100644 --- a/app/Helpers/SwissQr/SwissQrGenerator.php +++ b/app/Helpers/SwissQr/SwissQrGenerator.php @@ -107,8 +107,6 @@ class SwissQrGenerator if(strlen($this->company->present()->besr_id()) > 1) { - nlog("i have a besr"); - $referenceNumber = QrBill\Reference\QrPaymentReferenceGenerator::generate( $this->company->present()->besr_id() ?: '', // You receive this number from your bank (BESR-ID). Unless your bank is PostFinance, in that case use NULL. $this->invoice->number// A number to match the payment with your internal data, e.g. an invoice number @@ -123,7 +121,6 @@ class SwissQrGenerator } else{ - nlog("i have no besr"); $qrBill->setPaymentReference( QrBill\DataGroup\Element\PaymentReference::create( QrBill\DataGroup\Element\PaymentReference::TYPE_NON From 630d591fd431a248841db3a16d4089b6d9748e28 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Sep 2022 19:57:06 +1000 Subject: [PATCH 22/27] Fixes for adding a payment method with Checkout.com --- .../CheckoutComPaymentDriver.php | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/app/PaymentDrivers/CheckoutComPaymentDriver.php b/app/PaymentDrivers/CheckoutComPaymentDriver.php index a75e93a007aa..c580eb18b6be 100644 --- a/app/PaymentDrivers/CheckoutComPaymentDriver.php +++ b/app/PaymentDrivers/CheckoutComPaymentDriver.php @@ -34,6 +34,7 @@ use Checkout\CheckoutAuthorizationException; use Checkout\CheckoutDefaultSdk; use Checkout\CheckoutFourSdk; use Checkout\Common\CustomerRequest; +use Checkout\Customers\Four\CustomerRequest as FourCustomerRequest; use Checkout\Environment; use Checkout\Library\Exceptions\CheckoutHttpException; use Checkout\Models\Payments\IdSource; @@ -285,12 +286,31 @@ class CheckoutComPaymentDriver extends BaseDriver $response = $this->gateway->getCustomersClient()->get($this->client->present()->email()); return $response; + } catch (\Exception $e) { - $request = new CustomerRequest(); + + if ($this->is_four_api) { + $request = new FourCustomerRequest(); + } + else{ + $request = new CustomerRequest(); + } + $request->email = $this->client->present()->email(); $request->name = $this->client->present()->name(); + $request->phone = $this->client->present()->phone(); - return $request; + try { + $response = $this->gateway->getCustomersClient()->create($request); + } catch (CheckoutApiException $e) { + // API error + $error_details = $e->error_details; + $http_status_code = isset($e->http_metadata) ? $e->http_metadata->getStatusCode() : null; + } catch (CheckoutAuthorizationException $e) { + // Bad Invalid authorization + } + + return $response; } } From 26577d6aef1221616768831af8e92575ceb34251 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 15 Sep 2022 08:26:52 +1000 Subject: [PATCH 23/27] Adapt Email entity sending using emailentity --- app/Jobs/Entity/EmailEntity.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/Jobs/Entity/EmailEntity.php b/app/Jobs/Entity/EmailEntity.php index ce76748a6f6e..b9b3bc2445b8 100644 --- a/app/Jobs/Entity/EmailEntity.php +++ b/app/Jobs/Entity/EmailEntity.php @@ -23,6 +23,7 @@ use App\Models\Activity; use App\Models\Company; use App\Models\CreditInvitation; use App\Models\InvoiceInvitation; +use App\Models\PurchaseOrderInvitation; use App\Models\QuoteInvitation; use App\Models\RecurringInvoiceInvitation; use App\Utils\HtmlEngine; @@ -77,12 +78,16 @@ class EmailEntity implements ShouldQueue $this->invitation = $invitation; - $this->settings = $invitation->contact->client->getMergedSettings(); $this->entity_string = $this->resolveEntityString(); $this->entity = $invitation->{$this->entity_string}; + if($this->entity_string == 'purchase_order') + $this->settings = $this->company->settings; + else + $this->settings = $invitation->contact->client->getMergedSettings(); + $this->reminder_template = $reminder_template ?: $this->entity->calculateTemplate($this->entity_string); $this->html_engine = new HtmlEngine($invitation); @@ -139,6 +144,8 @@ class EmailEntity implements ShouldQueue return 'credit'; } elseif ($this->invitation instanceof RecurringInvoiceInvitation) { return 'recurring_invoice'; + } elseif($this->invitation instanceof PurchaseOrderInvitation) { + return 'purchase_order'; } } From 6015bb36dd73ad6d8b35af58e2226a898a78cb77 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 15 Sep 2022 08:52:28 +1000 Subject: [PATCH 24/27] Fixes for sending custom templates with purchase orders --- app/Http/Controllers/EmailController.php | 10 +++++++--- app/Jobs/Entity/EmailEntity.php | 8 +------- app/Jobs/PurchaseOrder/PurchaseOrderEmail.php | 9 +++++++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/EmailController.php b/app/Http/Controllers/EmailController.php index f752c6174e4b..17b3f8ff0a78 100644 --- a/app/Http/Controllers/EmailController.php +++ b/app/Http/Controllers/EmailController.php @@ -131,8 +131,10 @@ class EmailController extends BaseController if(Ninja::isHosted() && !$entity_obj->company->account->account_sms_verified) return response(['message' => 'Please verify your account to send emails.'], 400); - if($entity == 'purchaseOrder' || $entity == 'purchase_order' || $template == 'purchase_order'){ - return $this->sendPurchaseOrder($entity_obj, $data); + nlog($entity); + + if($entity == 'purchaseOrder' || $entity == 'purchase_order' || $template == 'purchase_order' || $entity == 'App\Models\PurchaseOrder'){ + return $this->sendPurchaseOrder($entity_obj, $data, $template); } $entity_obj->invitations->each(function ($invitation) use ($data, $entity_string, $entity_obj, $template) { @@ -183,13 +185,15 @@ class EmailController extends BaseController return $this->itemResponse($entity_obj->fresh()); } - private function sendPurchaseOrder($entity_obj, $data) + private function sendPurchaseOrder($entity_obj, $data, $template) { $this->entity_type = PurchaseOrder::class; $this->entity_transformer = PurchaseOrderTransformer::class; + $data['template'] = $template; + PurchaseOrderEmail::dispatch($entity_obj, $entity_obj->company, $data); return $this->itemResponse($entity_obj); diff --git a/app/Jobs/Entity/EmailEntity.php b/app/Jobs/Entity/EmailEntity.php index b9b3bc2445b8..c10a9ed9df8f 100644 --- a/app/Jobs/Entity/EmailEntity.php +++ b/app/Jobs/Entity/EmailEntity.php @@ -78,15 +78,11 @@ class EmailEntity implements ShouldQueue $this->invitation = $invitation; - $this->entity_string = $this->resolveEntityString(); $this->entity = $invitation->{$this->entity_string}; - if($this->entity_string == 'purchase_order') - $this->settings = $this->company->settings; - else - $this->settings = $invitation->contact->client->getMergedSettings(); + $this->settings = $invitation->contact->client->getMergedSettings(); $this->reminder_template = $reminder_template ?: $this->entity->calculateTemplate($this->entity_string); @@ -144,8 +140,6 @@ class EmailEntity implements ShouldQueue return 'credit'; } elseif ($this->invitation instanceof RecurringInvoiceInvitation) { return 'recurring_invoice'; - } elseif($this->invitation instanceof PurchaseOrderInvitation) { - return 'purchase_order'; } } diff --git a/app/Jobs/PurchaseOrder/PurchaseOrderEmail.php b/app/Jobs/PurchaseOrder/PurchaseOrderEmail.php index aeccc61a723c..0aa6967c147f 100644 --- a/app/Jobs/PurchaseOrder/PurchaseOrderEmail.php +++ b/app/Jobs/PurchaseOrder/PurchaseOrderEmail.php @@ -77,7 +77,12 @@ class PurchaseOrderEmail implements ShouldQueue /* Mark entity sent */ $invitation->purchase_order->service()->markSent()->save(); - $email_builder = (new PurchaseOrderEmailEngine($invitation, 'purchase_order', $this->template_data))->build(); + if(is_array($this->template_data) && array_key_exists('template', $this->template_data)) + $template = $this->template_data['template']; + else + $template = 'purchase_order'; + + $email_builder = (new PurchaseOrderEmailEngine($invitation, $template, $this->template_data))->build(); $nmo = new NinjaMailerObject; $nmo->mailable = new VendorTemplateEmail($email_builder, $invitation->contact, $invitation); @@ -86,7 +91,7 @@ class PurchaseOrderEmail implements ShouldQueue $nmo->to_user = $invitation->contact; $nmo->entity_string = 'purchase_order'; $nmo->invitation = $invitation; - $nmo->reminder_template = 'purchase_order'; + $nmo->reminder_template = 'email_template_purchase_order'; $nmo->entity = $invitation->purchase_order; NinjaMailerJob::dispatch($nmo)->delay(5); From b6b36c89fdd138bb42a249ba6a6845b42c455d73 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 15 Sep 2022 17:43:33 +1000 Subject: [PATCH 25/27] Add webhook functionality to credits --- app/Models/Webhook.php | 9 ++ app/Observers/CreditObserver.php | 21 +++ composer.json | 4 +- composer.lock | 177 ++++++++++++------------ tests/Feature/CompanyGatewayApiTest.php | 2 +- 5 files changed, 125 insertions(+), 88 deletions(-) diff --git a/app/Models/Webhook.php b/app/Models/Webhook.php index fb0bb4b73180..da8c142367e2 100644 --- a/app/Models/Webhook.php +++ b/app/Models/Webhook.php @@ -70,6 +70,12 @@ class Webhook extends BaseModel const EVENT_PROJECT_UPDATE = 26; + const EVENT_CREATE_CREDIT = 27; + + const EVENT_UPDATE_CREDIT = 28; + + const EVENT_DELETE_CREDIT = 29; + public static $valid_events = [ self::EVENT_CREATE_CLIENT, self::EVENT_CREATE_INVOICE, @@ -97,6 +103,9 @@ class Webhook extends BaseModel self::EVENT_REMIND_INVOICE, self::EVENT_PROJECT_CREATE, self::EVENT_PROJECT_UPDATE, + self::EVENT_CREATE_CREDIT, + self::EVENT_UPDATE_CREDIT, + self::EVENT_DELETE_CREDIT, ]; protected $fillable = [ diff --git a/app/Observers/CreditObserver.php b/app/Observers/CreditObserver.php index 497e32e6dc82..a60e5f02eb50 100644 --- a/app/Observers/CreditObserver.php +++ b/app/Observers/CreditObserver.php @@ -27,6 +27,13 @@ class CreditObserver */ public function created(Credit $credit) { + $subscriptions = Webhook::where('company_id', $credit->company->id) + ->where('event_id', Webhook::EVENT_CREATE_CREDIT) + ->exists(); + + if ($subscriptions) { + WebhookHandler::dispatch(Webhook::EVENT_CREATE_CREDIT, $credit, $credit->company)->delay(now()->addSeconds(2)); + } } /** @@ -37,6 +44,13 @@ class CreditObserver */ public function updated(Credit $credit) { + $subscriptions = Webhook::where('company_id', $credit->company->id) + ->where('event_id', Webhook::EVENT_UPDATE_CREDIT) + ->exists(); + + if ($subscriptions) { + WebhookHandler::dispatch(Webhook::EVENT_UPDATE_CREDIT, $credit, $credit->company)->delay(now()->addSeconds(2)); + } } /** @@ -47,6 +61,13 @@ class CreditObserver */ public function deleted(Credit $credit) { + $subscriptions = Webhook::where('company_id', $credit->company->id) + ->where('event_id', Webhook::EVENT_DELETE_CREDIT) + ->exists(); + + if ($subscriptions) { + WebhookHandler::dispatch(Webhook::EVENT_DELETE_CREDIT, $credit, $credit->company)->delay(now()->addSeconds(2)); + } } /** diff --git a/composer.json b/composer.json index da1207a62b31..db974d3876dd 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ "authorizenet/authorizenet": "^2.0", "awobaz/compoships": "^2.1", "bacon/bacon-qr-code": "^2.0", - "beganovich/snappdf": "^2", + "beganovich/snappdf": "^3", "braintree/braintree_php": "^6.0", "checkout/checkout-sdk-php": "^2.5", "cleverit/ubl_invoice": "^1.3", @@ -57,7 +57,7 @@ "intervention/image": "^2.5", "invoiceninja/inspector": "^1.0", "laracasts/presenter": "^0.2.1", - "laravel/framework": "^9.17", + "laravel/framework": "^9.3", "laravel/slack-notification-channel": "^2.2", "laravel/socialite": "^5", "laravel/tinker": "^2.7", diff --git a/composer.lock b/composer.lock index add2c282c382..2a1246227db9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8d9b065d1cf3f4fd42565e77e63c53fc", + "content-hash": "9dc581f41118f9f990e06f938c842839", "packages": [ { "name": "afosto/yaac", @@ -378,16 +378,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.235.5", + "version": "3.235.8", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "3b002b92369dbcb8d86f32546cb324eabcd19a4e" + "reference": "cc33d53d735a3835adff212598f2a20ee9ac9531" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3b002b92369dbcb8d86f32546cb324eabcd19a4e", - "reference": "3b002b92369dbcb8d86f32546cb324eabcd19a4e", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/cc33d53d735a3835adff212598f2a20ee9ac9531", + "reference": "cc33d53d735a3835adff212598f2a20ee9ac9531", "shasum": "" }, "require": { @@ -406,6 +406,7 @@ "aws/aws-php-sns-message-validator": "~1.0", "behat/behat": "~3.0", "composer/composer": "^1.10.22", + "dms/phpunit-arraysubset-asserts": "^0.4.0", "doctrine/cache": "~1.4", "ext-dom": "*", "ext-openssl": "*", @@ -413,10 +414,11 @@ "ext-sockets": "*", "nette/neon": "^2.3", "paragonie/random_compat": ">= 2", - "phpunit/phpunit": "^4.8.35 || ^5.6.3", + "phpunit/phpunit": "^4.8.35 || ^5.6.3 || ^9.5", "psr/cache": "^1.0", "psr/simple-cache": "^1.0", - "sebastian/comparator": "^1.2.3" + "sebastian/comparator": "^1.2.3 || ^4.0", + "yoast/phpunit-polyfills": "^1.0" }, "suggest": { "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", @@ -464,9 +466,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.235.5" + "source": "https://github.com/aws/aws-sdk-php/tree/3.235.8" }, - "time": "2022-09-09T18:19:38+00:00" + "time": "2022-09-14T18:18:31+00:00" }, { "name": "bacon/bacon-qr-code", @@ -524,16 +526,16 @@ }, { "name": "beganovich/snappdf", - "version": "v2.2.0", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/beganovich/snappdf.git", - "reference": "7964d03c091f3a30513fb6c44ea353c575ba523a" + "reference": "b2656c2c67be086b535cd13a704e27caaf5a7570" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/beganovich/snappdf/zipball/7964d03c091f3a30513fb6c44ea353c575ba523a", - "reference": "7964d03c091f3a30513fb6c44ea353c575ba523a", + "url": "https://api.github.com/repos/beganovich/snappdf/zipball/b2656c2c67be086b535cd13a704e27caaf5a7570", + "reference": "b2656c2c67be086b535cd13a704e27caaf5a7570", "shasum": "" }, "require": { @@ -570,9 +572,9 @@ "description": "Convert webpages or HTML into the PDF file using Chromium or Google Chrome.", "support": { "issues": "https://github.com/beganovich/snappdf/issues", - "source": "https://github.com/beganovich/snappdf/tree/v2.2.0" + "source": "https://github.com/beganovich/snappdf/tree/v3.1.0" }, - "time": "2022-06-29T13:08:15+00:00" + "time": "2022-09-14T10:35:47+00:00" }, { "name": "braintree/braintree_php", @@ -2162,16 +2164,16 @@ }, { "name": "google/apiclient-services", - "version": "v0.265.0", + "version": "v0.266.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "a23754daa452e26a8dd31a7848863c67a2e3d67e" + "reference": "27ead5edc8ba4a17ddd211ad03216c313a57411f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/a23754daa452e26a8dd31a7848863c67a2e3d67e", - "reference": "a23754daa452e26a8dd31a7848863c67a2e3d67e", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/27ead5edc8ba4a17ddd211ad03216c313a57411f", + "reference": "27ead5edc8ba4a17ddd211ad03216c313a57411f", "shasum": "" }, "require": { @@ -2200,9 +2202,9 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.265.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.266.0" }, - "time": "2022-09-04T00:58:12+00:00" + "time": "2022-09-12T01:28:14+00:00" }, { "name": "google/auth", @@ -3481,16 +3483,16 @@ }, { "name": "laravel/framework", - "version": "v9.29.0", + "version": "v9.30.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "585da0913e907fd54941260860ae3d7d4be8e8cb" + "reference": "2ca2b168a3e995a8ec6ea2805906379095d20080" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/585da0913e907fd54941260860ae3d7d4be8e8cb", - "reference": "585da0913e907fd54941260860ae3d7d4be8e8cb", + "url": "https://api.github.com/repos/laravel/framework/zipball/2ca2b168a3e995a8ec6ea2805906379095d20080", + "reference": "2ca2b168a3e995a8ec6ea2805906379095d20080", "shasum": "" }, "require": { @@ -3567,12 +3569,15 @@ "illuminate/view": "self.version" }, "require-dev": { + "ably/ably-php": "^1.0", "aws/aws-sdk-php": "^3.198.1", "doctrine/dbal": "^2.13.3|^3.1.4", "fakerphp/faker": "^1.9.2", "guzzlehttp/guzzle": "^7.2", "league/flysystem-aws-s3-v3": "^3.0", "league/flysystem-ftp": "^3.0", + "league/flysystem-path-prefixing": "^3.3", + "league/flysystem-read-only": "^3.3", "league/flysystem-sftp-v3": "^3.0", "mockery/mockery": "^1.4.4", "orchestra/testbench-core": "^7.1", @@ -3600,6 +3605,8 @@ "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", + "league/flysystem-read-only": "Required to use read-only disks (^3.3)", "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", "mockery/mockery": "Required to use mocking (^1.4.4).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", @@ -3657,7 +3664,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-09-09T18:21:21+00:00" + "time": "2022-09-13T14:06:14+00:00" }, { "name": "laravel/serializable-closure", @@ -5578,20 +5585,20 @@ }, { "name": "nette/utils", - "version": "v3.2.7", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "0af4e3de4df9f1543534beab255ccf459e7a2c99" + "reference": "02a54c4c872b99e4ec05c4aec54b5a06eb0f6368" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/0af4e3de4df9f1543534beab255ccf459e7a2c99", - "reference": "0af4e3de4df9f1543534beab255ccf459e7a2c99", + "url": "https://api.github.com/repos/nette/utils/zipball/02a54c4c872b99e4ec05c4aec54b5a06eb0f6368", + "reference": "02a54c4c872b99e4ec05c4aec54b5a06eb0f6368", "shasum": "" }, "require": { - "php": ">=7.2 <8.2" + "php": ">=7.2 <8.3" }, "conflict": { "nette/di": "<3.0.6" @@ -5657,9 +5664,9 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v3.2.7" + "source": "https://github.com/nette/utils/tree/v3.2.8" }, - "time": "2022-01-24T11:29:14+00:00" + "time": "2022-09-12T23:36:20+00:00" }, { "name": "nikic/php-parser", @@ -7653,20 +7660,20 @@ }, { "name": "ramsey/uuid", - "version": "4.4.0", + "version": "4.5.0", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "373f7bacfcf3de038778ff27dcce5672ddbf4c8a" + "reference": "ef842484ba57f163c6d465ab744bfecb872a11d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/373f7bacfcf3de038778ff27dcce5672ddbf4c8a", - "reference": "373f7bacfcf3de038778ff27dcce5672ddbf4c8a", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/ef842484ba57f163c6d465ab744bfecb872a11d4", + "reference": "ef842484ba57f163c6d465ab744bfecb872a11d4", "shasum": "" }, "require": { - "brick/math": "^0.8 || ^0.9 || ^0.10", + "brick/math": "^0.8.8 || ^0.9 || ^0.10", "ext-ctype": "*", "ext-json": "*", "php": "^8.0", @@ -7687,12 +7694,13 @@ "php-mock/php-mock-mockery": "^1.3", "php-parallel-lint/php-parallel-lint": "^1.1", "phpbench/phpbench": "^1.0", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-mockery": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", "phpunit/phpunit": "^8.5 || ^9", - "slevomat/coding-standard": "^7.0", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.5", "vimeo/psalm": "^4.9" }, @@ -7730,7 +7738,7 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.4.0" + "source": "https://github.com/ramsey/uuid/tree/4.5.0" }, "funding": [ { @@ -7742,7 +7750,7 @@ "type": "tidelift" } ], - "time": "2022-08-05T17:58:37+00:00" + "time": "2022-09-15T01:44:53+00:00" }, { "name": "razorpay/razorpay", @@ -11936,16 +11944,16 @@ }, { "name": "tijsverkoyen/css-to-inline-styles", - "version": "2.2.4", + "version": "2.2.5", "source": { "type": "git", "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", - "reference": "da444caae6aca7a19c0c140f68c6182e337d5b1c" + "reference": "4348a3a06651827a27d989ad1d13efec6bb49b19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/da444caae6aca7a19c0c140f68c6182e337d5b1c", - "reference": "da444caae6aca7a19c0c140f68c6182e337d5b1c", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/4348a3a06651827a27d989ad1d13efec6bb49b19", + "reference": "4348a3a06651827a27d989ad1d13efec6bb49b19", "shasum": "" }, "require": { @@ -11983,9 +11991,9 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "support": { "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", - "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.4" + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.5" }, - "time": "2021-12-08T09:12:39+00:00" + "time": "2022-09-12T13:28:28+00:00" }, { "name": "turbo124/beacon", @@ -12742,16 +12750,16 @@ }, { "name": "brianium/paratest", - "version": "v6.6.3", + "version": "v6.6.4", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "f2d781bb9136cda2f5e73ee778049e80ba681cf6" + "reference": "4ce800dc32fd0292a4f05c00f347142dce1ecdda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/f2d781bb9136cda2f5e73ee778049e80ba681cf6", - "reference": "f2d781bb9136cda2f5e73ee778049e80ba681cf6", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/4ce800dc32fd0292a4f05c00f347142dce1ecdda", + "reference": "4ce800dc32fd0292a4f05c00f347142dce1ecdda", "shasum": "" }, "require": { @@ -12761,24 +12769,23 @@ "ext-simplexml": "*", "jean85/pretty-package-versions": "^2.0.5", "php": "^7.3 || ^8.0", - "phpunit/php-code-coverage": "^9.2.16", + "phpunit/php-code-coverage": "^9.2.17", "phpunit/php-file-iterator": "^3.0.6", "phpunit/php-timer": "^5.0.3", - "phpunit/phpunit": "^9.5.23", + "phpunit/phpunit": "^9.5.24", "sebastian/environment": "^5.1.4", - "symfony/console": "^5.4.9 || ^6.1.2", - "symfony/polyfill-php80": "^v1.26.0", - "symfony/process": "^5.4.8 || ^6.1.0" + "symfony/console": "^5.4.12 || ^6.1.4", + "symfony/process": "^5.4.11 || ^6.1.3" }, "require-dev": { - "doctrine/coding-standard": "^9.0.0", + "doctrine/coding-standard": "^10.0.0", "ext-pcov": "*", "ext-posix": "*", - "infection/infection": "^0.26.13", + "infection/infection": "^0.26.14", "malukenho/mcbumpface": "^1.1.5", "squizlabs/php_codesniffer": "^3.7.1", - "symfony/filesystem": "^5.4.9 || ^6.1.0", - "vimeo/psalm": "^4.26.0" + "symfony/filesystem": "^5.4.12 || ^6.1.4", + "vimeo/psalm": "^4.27.0" }, "bin": [ "bin/paratest", @@ -12819,7 +12826,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v6.6.3" + "source": "https://github.com/paratestphp/paratest/tree/v6.6.4" }, "funding": [ { @@ -12831,7 +12838,7 @@ "type": "paypal" } ], - "time": "2022-08-25T05:44:14+00:00" + "time": "2022-09-13T10:47:01+00:00" }, { "name": "composer/package-versions-deprecated", @@ -14989,16 +14996,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { @@ -15051,7 +15058,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { @@ -15059,7 +15066,7 @@ "type": "github" } ], - "time": "2020-10-26T15:49:45+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { "name": "sebastian/complexity", @@ -15249,16 +15256,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { @@ -15314,7 +15321,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" }, "funding": [ { @@ -15322,7 +15329,7 @@ "type": "github" } ], - "time": "2021-11-11T14:18:36+00:00" + "time": "2022-09-14T06:03:37+00:00" }, { "name": "sebastian/global-state", @@ -15677,16 +15684,16 @@ }, { "name": "sebastian/type", - "version": "3.1.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb44e1cc6e557418387ad815780360057e40753e" + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb44e1cc6e557418387ad815780360057e40753e", - "reference": "fb44e1cc6e557418387ad815780360057e40753e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", "shasum": "" }, "require": { @@ -15698,7 +15705,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -15721,7 +15728,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.1.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" }, "funding": [ { @@ -15729,7 +15736,7 @@ "type": "github" } ], - "time": "2022-08-29T06:55:37+00:00" + "time": "2022-09-12T14:47:03+00:00" }, { "name": "sebastian/version", diff --git a/tests/Feature/CompanyGatewayApiTest.php b/tests/Feature/CompanyGatewayApiTest.php index 5b6bbf9e4b2f..b036dd35c8b9 100644 --- a/tests/Feature/CompanyGatewayApiTest.php +++ b/tests/Feature/CompanyGatewayApiTest.php @@ -512,6 +512,6 @@ class CompanyGatewayApiTest extends TestCase $company_gateway = CompanyGateway::find($id); - $this->assertEquals(1.2, $company_gateway->calcGatewayFee(10, GatewayType::CREDIT_CARD, true)); + $this->assertEquals(1.2, round($company_gateway->calcGatewayFee(10, GatewayType::CREDIT_CARD, true),1)); } } From 7a15afa827d002c04fc1887b9ba3a2f1c9801644 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 15 Sep 2022 17:56:11 +1000 Subject: [PATCH 26/27] Fixes for tests --- tests/Feature/CompanyGatewayResolutionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/CompanyGatewayResolutionTest.php b/tests/Feature/CompanyGatewayResolutionTest.php index 72f34e63b79c..ef294c2b26fc 100644 --- a/tests/Feature/CompanyGatewayResolutionTest.php +++ b/tests/Feature/CompanyGatewayResolutionTest.php @@ -233,6 +233,6 @@ class CompanyGatewayResolutionTest extends TestCase $this->cg->save(); $fee = $this->cg->calcGatewayFee(89, GatewayType::CREDIT_CARD, false); - $this->assertEquals(1.89, $fee); + $this->assertEquals(1.89, round($fee,2)); } } From 383c5c92bfe83dd4cc95bb6967f13a5d6944bc1d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 15 Sep 2022 19:39:03 +1000 Subject: [PATCH 27/27] v5.5.22 --- VERSION.txt | 2 +- config/ninja.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 7d5275de2ccd..f84782e2e9f0 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.5.21 \ No newline at end of file +5.5.22 \ No newline at end of file diff --git a/config/ninja.php b/config/ninja.php index 5289374b4f34..b56ba5adf83d 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -14,8 +14,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => '5.5.21', - 'app_tag' => '5.5.21', + 'app_version' => '5.5.22', + 'app_tag' => '5.5.22', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''),