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/Jobs/Account/CreateAccount.php b/app/Jobs/Account/CreateAccount.php index 9ea168d03ed3..3c03138d04d1 100644 --- a/app/Jobs/Account/CreateAccount.php +++ b/app/Jobs/Account/CreateAccount.php @@ -77,8 +77,13 @@ class CreateAccount $sp794f3f->key = Str::random(32); } - $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/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/app/Repositories/ClientRepository.php b/app/Repositories/ClientRepository.php index d2a904a9857b..7dd720c0fd00 100644 --- a/app/Repositories/ClientRepository.php +++ b/app/Repositories/ClientRepository.php @@ -58,6 +58,10 @@ class ClientRepository extends BaseRepository return $client; } + 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; + } + $client->fill($data); if (!isset($client->number) || empty($client->number)) { 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(); 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' => [ 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 */; 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 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; 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()