From 8d9950ebbdfbbabc72788cbf77e9c5790b6413f1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Jul 2021 08:39:30 +1000 Subject: [PATCH 1/7] Add company country as default if none is set --- app/Repositories/ClientRepository.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/Repositories/ClientRepository.php b/app/Repositories/ClientRepository.php index d2a904a9857b..5074e2976ba4 100644 --- a/app/Repositories/ClientRepository.php +++ b/app/Repositories/ClientRepository.php @@ -58,6 +58,10 @@ class ClientRepository extends BaseRepository return $client; } + if(!$client->id && (!array_key_exists('country_id', $data) || empty($data['country_id']))){ + $data['country_id'] = auth()->user()->company()->settings->country_id; + } + $client->fill($data); if (!isset($client->number) || empty($client->number)) { From fcbef56e46e5440229a45d37c3496663566249bd Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Jul 2021 09:11:42 +1000 Subject: [PATCH 2/7] Fixes for schema migrations and always set default country on clients --- app/Repositories/ClientRepository.php | 2 +- database/schema/db-ninja-01-schema.dump | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Repositories/ClientRepository.php b/app/Repositories/ClientRepository.php index 5074e2976ba4..7dd720c0fd00 100644 --- a/app/Repositories/ClientRepository.php +++ b/app/Repositories/ClientRepository.php @@ -58,7 +58,7 @@ class ClientRepository extends BaseRepository return $client; } - if(!$client->id && (!array_key_exists('country_id', $data) || empty($data['country_id']))){ + if(!$client->id && auth()->user() && auth()->user()->company() && (!array_key_exists('country_id', $data) || empty($data['country_id']))){ $data['country_id'] = auth()->user()->company()->settings->country_id; } diff --git a/database/schema/db-ninja-01-schema.dump b/database/schema/db-ninja-01-schema.dump index 3cd2f293f54b..7e27ead7077a 100644 --- a/database/schema/db-ninja-01-schema.dump +++ b/database/schema/db-ninja-01-schema.dump @@ -1044,7 +1044,7 @@ CREATE TABLE `migrations` ( `migration` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL, `batch` int(11) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `password_resets`; /*!40101 SET @saved_cs_client = @@character_set_client */; From 9941d72d31f3a6e98f9a1e204e83b08319374ef0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Jul 2021 09:31:01 +1000 Subject: [PATCH 3/7] Fixes for Github Actions --- .env.ci | 2 +- app/Services/Subscription/SubscriptionService.php | 6 +++--- config/database.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.env.ci b/.env.ci index 1fde559c0b81..a033ea644c05 100644 --- a/.env.ci +++ b/.env.ci @@ -5,7 +5,7 @@ APP_DEBUG=true APP_URL=http://ninja.test MULTI_DB_ENABLED=false # database -DB_CONNECTION=db-ninja-01 +DB_CONNECTION=mysql DB_DATABASE1=ninja DB_USERNAME1=root DB_PASSWORD1=ninja diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php index e83e69dbc721..963bb93217a8 100644 --- a/app/Services/Subscription/SubscriptionService.php +++ b/app/Services/Subscription/SubscriptionService.php @@ -511,7 +511,7 @@ class SubscriptionService $total_payable = $pro_rata_refund_amount + $pro_rata_charge_amount + $this->subscription->price; - return $this->proRataInvoice($last_invoice, $target_subscription); + return $this->proRataInvoice($last_invoice, $target_subscription, $recurring_invoice->client_id); } @@ -614,7 +614,7 @@ nlog("handle plan change"); * @param Subscription $target * @return Invoice */ - private function proRataInvoice($last_invoice, $target) + private function proRataInvoice($last_invoice, $target, $client_id) { $subscription_repo = new SubscriptionRepository(); $invoice_repo = new InvoiceRepository(); @@ -626,7 +626,7 @@ nlog("handle plan change"); $invoice->line_items = array_merge($subscription_repo->generateLineItems($target), $this->calculateProRataRefundItems($last_invoice)); $data = [ - 'client_id' => $last_invoice->client_id, + 'client_id' => $client_id, 'quantity' => 1, 'date' => now()->format('Y-m-d'), ]; diff --git a/config/database.php b/config/database.php index 0e9e4b7692ed..30f3f2d5d158 100644 --- a/config/database.php +++ b/config/database.php @@ -46,7 +46,7 @@ return [ 'prefix' => '', 'prefix_indexes' => true, 'strict' => env('DB_STRICT', false), - 'engine' => 'InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8', + // 'engine' => 'InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8', ], 'sqlite' => [ From 85ccca8f23fa8aed50fbad2b8eb4abeb620f2073 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Jul 2021 09:44:43 +1000 Subject: [PATCH 4/7] Fixes for recurring mock invoice number --- tests/MockAccountData.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index 28832098fdc1..227200e9dd81 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -488,7 +488,7 @@ trait MockAccountData $recurring_invoice->next_send_date = Carbon::now(); $recurring_invoice->save(); - $recurring_invoice->number = $this->getNextInvoiceNumber($this->invoice->client, $this->invoice); + $recurring_invoice->number = $this->getNextRecurringInvoiceNumber($this->invoice->client, $this->invoice); $recurring_invoice->save(); $recurring_invoice = InvoiceToRecurringInvoiceFactory::create($this->invoice); @@ -499,7 +499,7 @@ trait MockAccountData $recurring_invoice->next_send_date = Carbon::now(); $recurring_invoice->save(); - $recurring_invoice->number = $this->getNextInvoiceNumber($this->invoice->client, $this->invoice); + $recurring_invoice->number = $this->getNextRecurringInvoiceNumber($this->invoice->client, $this->invoice); $recurring_invoice->save(); $recurring_invoice = InvoiceToRecurringInvoiceFactory::create($this->invoice); @@ -510,7 +510,7 @@ trait MockAccountData $recurring_invoice->next_send_date = Carbon::now(); $recurring_invoice->save(); - $recurring_invoice->number = $this->getNextInvoiceNumber($this->invoice->client, $this->invoice); + $recurring_invoice->number = $this->getNextRecurringInvoiceNumber($this->invoice->client, $this->invoice); $recurring_invoice->save(); $recurring_invoice = InvoiceToRecurringInvoiceFactory::create($this->invoice); @@ -521,7 +521,7 @@ trait MockAccountData $recurring_invoice->next_send_date = Carbon::now(); $recurring_invoice->save(); - $recurring_invoice->number = $this->getNextInvoiceNumber($this->invoice->client, $this->invoice); + $recurring_invoice->number = $this->getNextRecurringInvoiceNumber($this->invoice->client, $this->invoice); $recurring_invoice->save(); $recurring_invoice = InvoiceToRecurringInvoiceFactory::create($this->invoice); @@ -532,7 +532,7 @@ trait MockAccountData $recurring_invoice->next_send_date = Carbon::now(); $recurring_invoice->save(); - $recurring_invoice->number = $this->getNextInvoiceNumber($this->invoice->client, $this->invoice); + $recurring_invoice->number = $this->getNextRecurringInvoiceNumber($this->invoice->client, $this->invoice); $recurring_invoice->save(); $recurring_invoice = InvoiceToRecurringInvoiceFactory::create($this->invoice); @@ -543,7 +543,7 @@ trait MockAccountData $recurring_invoice->next_send_date = Carbon::now()->addDays(10); $recurring_invoice->save(); - $recurring_invoice->number = $this->getNextInvoiceNumber($this->invoice->client, $this->invoice); + $recurring_invoice->number = $this->getNextRecurringInvoiceNumber($this->invoice->client, $this->invoice); $recurring_invoice->save(); $gs = new GroupSetting; From bfd6cf876b937bcbb77d3e8e8b73a9406a7fda27 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Jul 2021 10:31:07 +1000 Subject: [PATCH 5/7] Fixes for tests --- app/Jobs/Account/CreateAccount.php | 2 ++ tests/Unit/GeneratesCounterTest.php | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/Jobs/Account/CreateAccount.php b/app/Jobs/Account/CreateAccount.php index 9ea168d03ed3..61c685bc4512 100644 --- a/app/Jobs/Account/CreateAccount.php +++ b/app/Jobs/Account/CreateAccount.php @@ -77,6 +77,8 @@ class CreateAccount $sp794f3f->key = Str::random(32); } + $sp794f3f->trial_started = now(); + $sp794f3f->trial_plan = 'pro'; $sp794f3f->save(); $sp035a66 = CreateCompany::dispatchNow($this->request, $sp794f3f); diff --git a/tests/Unit/GeneratesCounterTest.php b/tests/Unit/GeneratesCounterTest.php index df24792e025c..6fb5bbe8872c 100644 --- a/tests/Unit/GeneratesCounterTest.php +++ b/tests/Unit/GeneratesCounterTest.php @@ -175,11 +175,11 @@ class GeneratesCounterTest extends TestCase $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); - $this->assertEquals($invoice_number, '0007'); + $this->assertEquals($invoice_number, '0002'); $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); - $this->assertEquals($invoice_number, '0008'); + $this->assertEquals($invoice_number, '0002'); } public function testQuoteNumberValue() @@ -338,11 +338,11 @@ class GeneratesCounterTest extends TestCase $invoice_number = $this->getNextInvoiceNumber($cliz->fresh(), $this->invoice); - $this->assertEquals($invoice_number, '0007'); + $this->assertEquals($invoice_number, '0002'); $invoice_number = $this->getNextInvoiceNumber($cliz->fresh(), $this->invoice); - $this->assertEquals($invoice_number, '0008'); + $this->assertEquals($invoice_number, '0002'); } public function testClientNumber() From e808cc62a8cab8f7940342add6e9a07bd7517e23 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Jul 2021 12:22:37 +1000 Subject: [PATCH 6/7] Fixes for Client - Paid To Date updating when a payment with no invoices is generated --- app/Jobs/Account/CreateAccount.php | 11 +++++++---- app/Listeners/Activity/PaymentUpdatedActivity.php | 2 +- app/Repositories/PaymentRepository.php | 5 +++++ app/Services/Invoice/ApplyPayment.php | 2 ++ app/Services/Invoice/InvoiceService.php | 6 +----- app/Services/Invoice/MarkPaid.php | 10 ++++------ 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/app/Jobs/Account/CreateAccount.php b/app/Jobs/Account/CreateAccount.php index 61c685bc4512..3c03138d04d1 100644 --- a/app/Jobs/Account/CreateAccount.php +++ b/app/Jobs/Account/CreateAccount.php @@ -77,10 +77,13 @@ class CreateAccount $sp794f3f->key = Str::random(32); } - $sp794f3f->trial_started = now(); - $sp794f3f->trial_plan = 'pro'; - $sp794f3f->save(); - + if(Ninja::isHosted()) + { + $sp794f3f->trial_started = now(); + $sp794f3f->trial_plan = 'pro'; + $sp794f3f->save(); + } + $sp035a66 = CreateCompany::dispatchNow($this->request, $sp794f3f); $sp035a66->load('account'); $sp794f3f->default_company_id = $sp035a66->id; diff --git a/app/Listeners/Activity/PaymentUpdatedActivity.php b/app/Listeners/Activity/PaymentUpdatedActivity.php index 4ddd72a41ab0..5d4dbe55afd5 100644 --- a/app/Listeners/Activity/PaymentUpdatedActivity.php +++ b/app/Listeners/Activity/PaymentUpdatedActivity.php @@ -48,7 +48,7 @@ class PaymentUpdatedActivity implements ShouldQueue $fields = new stdClass; -$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->payment->user_id; + $user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->payment->user_id; $fields->payment_id = $payment->id; $fields->client_id = $payment->client_id; diff --git a/app/Repositories/PaymentRepository.php b/app/Repositories/PaymentRepository.php index 411a052aab6a..b5913f8b37b3 100644 --- a/app/Repositories/PaymentRepository.php +++ b/app/Repositories/PaymentRepository.php @@ -80,6 +80,11 @@ class PaymentRepository extends BaseRepository { $client->service()->updatePaidToDate($data['amount'])->save(); } + elseif($data['amount'] >0){ + + //this fixes an edge case with unapplied payments + $client->service()->updatePaidToDate($data['amount'])->save(); + } if (array_key_exists('credits', $data) && is_array($data['credits']) && count($data['credits']) > 0) { $_credit_totals = array_sum(array_column($data['credits'], 'amount')); diff --git a/app/Services/Invoice/ApplyPayment.php b/app/Services/Invoice/ApplyPayment.php index 196fb6e04b9e..da4dbe96449e 100644 --- a/app/Services/Invoice/ApplyPayment.php +++ b/app/Services/Invoice/ApplyPayment.php @@ -104,6 +104,8 @@ class ApplyPayment extends AbstractService ->ledger() ->updatePaymentBalance($amount_paid); + nlog("updating client balance by amount {$amount_paid}"); + $this->invoice ->client ->service() diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index 2daf4bc074fa..8fa43294be92 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -33,13 +33,9 @@ class InvoiceService private $invoice; - protected $client_service; - public function __construct($invoice) { $this->invoice = $invoice; - - $this->client_service = new ClientService($invoice->client); } /** @@ -49,7 +45,7 @@ class InvoiceService */ public function markPaid() { - $this->invoice = (new MarkPaid($this->client_service, $this->invoice))->run(); + $this->invoice = (new MarkPaid($this->invoice))->run(); return $this; } diff --git a/app/Services/Invoice/MarkPaid.php b/app/Services/Invoice/MarkPaid.php index 68563ee5dfc7..7cbd52736242 100644 --- a/app/Services/Invoice/MarkPaid.php +++ b/app/Services/Invoice/MarkPaid.php @@ -29,14 +29,10 @@ class MarkPaid extends AbstractService { use GeneratesCounter; - private $client_service; - private $invoice; - public function __construct(ClientService $client_service, Invoice $invoice) + public function __construct(Invoice $invoice) { - $this->client_service = $client_service; - $this->invoice = $invoice; } @@ -92,7 +88,9 @@ class MarkPaid extends AbstractService $payment->ledger() ->updatePaymentBalance($payment->amount * -1); - $this->client_service + $this->invoice + ->client + ->service() ->updateBalance($payment->amount * -1) ->updatePaidToDate($payment->amount) ->save(); From 5946fac405926968813ac589ecd92140699e05a1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Jul 2021 14:57:43 +1000 Subject: [PATCH 7/7] Update support message subject format --- app/Mail/SupportMessageSent.php | 4 +- tests/Feature/UpdatePaymentTest.php | 137 ++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 tests/Feature/UpdatePaymentTest.php diff --git a/app/Mail/SupportMessageSent.php b/app/Mail/SupportMessageSent.php index 0f0cf099d7c5..fb634195a004 100644 --- a/app/Mail/SupportMessageSent.php +++ b/app/Mail/SupportMessageSent.php @@ -62,9 +62,9 @@ class SupportMessageSent extends Mailable $user = auth()->user(); if(Ninja::isHosted()) - $subject = "{$priority}Hosted-{$company->db} :: Customer Support - [{$plan}]"; + $subject = "{$priority}Hosted-{$company->db} :: Customer Support - [{$plan}] ".date('M jS, g:ia'); else - $subject = "{$priority}Self Hosted :: Customer Support - [{$plan}]"; + $subject = "{$priority}Self Hosted :: Customer Support - [{$plan}] ".date('M jS, g:ia'); return $this->from(config('mail.from.address'), $user->present()->name()) ->replyTo($user->email, $user->present()->name()) diff --git a/tests/Feature/UpdatePaymentTest.php b/tests/Feature/UpdatePaymentTest.php new file mode 100644 index 000000000000..95e5ffb58bf6 --- /dev/null +++ b/tests/Feature/UpdatePaymentTest.php @@ -0,0 +1,137 @@ +faker = \Faker\Factory::create(); + + $this->makeTestData(); + $this->withoutExceptionHandling(); + + $this->withoutMiddleware( + ThrottleRequests::class + ); + } + + public function testUpdatePaymentClientPaidToDate() + { + + //Create new client + $client = Client::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + ]); + + + $this->assertEquals(0, $client->balance); + $this->assertEquals(0, $client->paid_to_date); + + //Create Invoice + $invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id + $invoice->client_id = $client->id; + $invoice->line_items = $this->buildLineItems(); + $invoice->uses_inclusive_taxes = false; + $invoice->save(); + $invoice = (new InvoiceSum($invoice))->build()->getInvoice(); + $invoice->save(); + + $this->assertEquals(0, $invoice->balance); + + $invoice->service()->markSent()->save(); + + $this->assertEquals(10, $invoice->balance); + + + //create Unapplied payment via API + + // $data = [ + // 'amount' => $this->invoice->amount, + // 'client_id' => $client->hashed_id, + // 'invoices' => [ + // [ + // 'invoice_id' => $this->invoice->hashed_id, + // 'amount' => $this->invoice->amount, + // ], + // ], + // 'date' => '2020/12/12', + + // ]; + + $data = [ + 'amount' => 10, + 'client_id' => $client->hashed_id + ]; + + $response = null; + + try { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/payments?include=invoices,paymentables', $data); + } catch (ValidationException $e) { + $message = json_decode($e->validator->getMessageBag(), 1); + $this->assertNotNull($message); + } + + // $arr = $response->json(); + // $response->assertStatus(200); + // $payment_id = $arr['data']['id']; + // $payment = Payment::find($this->decodePrimaryKey($payment_id))->first(); + // $payment->load('invoices'); + + // $this->assertNotNull($payment); + // $this->assertNotNull($payment->invoices()); + // $this->assertEquals(1, $payment->invoices()->count()); + + $this->assertEquals(10, $client->fresh()->paid_to_date); + + } + +} \ No newline at end of file