From 021761d33d9ad0e330f66d86655cb7db374c3c98 Mon Sep 17 00:00:00 2001
From: David Bomba
Date: Sun, 27 Jun 2021 19:20:56 +1000
Subject: [PATCH 1/4] Make navigating subscriptions easier
---
app/Jobs/Account/CreateAccount.php | 3 +++
app/Models/Account.php | 15 +++++++++++++++
app/Transformers/ActivityTransformer.php | 1 +
...bscriptions-recurring-invoices-table.blade.php | 8 ++++++++
4 files changed, 27 insertions(+)
diff --git a/app/Jobs/Account/CreateAccount.php b/app/Jobs/Account/CreateAccount.php
index ec24b4f6122f..86458d904b0b 100644
--- a/app/Jobs/Account/CreateAccount.php
+++ b/app/Jobs/Account/CreateAccount.php
@@ -77,6 +77,9 @@ class CreateAccount
$sp794f3f->save();
+ if(Ninja::isHosted())
+ $sp794f3f->startTrial();
+
$sp035a66 = CreateCompany::dispatchNow($this->request, $sp794f3f);
$sp035a66->load('account');
$sp794f3f->default_company_id = $sp035a66->id;
diff --git a/app/Models/Account.php b/app/Models/Account.php
index ddb97dd9075c..c062ef6dbf54 100644
--- a/app/Models/Account.php
+++ b/app/Models/Account.php
@@ -227,6 +227,21 @@ class Account extends BaseModel
return $plan_details && $plan_details['trial'];
}
+ public function startTrial($plan)
+ {
+ if (! Ninja::isNinja()) {
+ return;
+ }
+
+ if ($this->trial_started && $this->trial_started != '0000-00-00') {
+ return;
+ }
+
+ $this->trial_plan = $plan;
+ $this->trial_started = now();
+ $this->save();
+ }
+
public function getPlanDetails($include_inactive = false, $include_trial = true)
{
$plan = $this->plan;
diff --git a/app/Transformers/ActivityTransformer.php b/app/Transformers/ActivityTransformer.php
index d9000135881b..a284f0489829 100644
--- a/app/Transformers/ActivityTransformer.php
+++ b/app/Transformers/ActivityTransformer.php
@@ -36,6 +36,7 @@ class ActivityTransformer extends EntityTransformer
'id' => (string) $this->encodePrimaryKey($activity->id),
'activity_type_id' => (string) $activity->activity_type_id,
'client_id' => $activity->client_id ? (string) $this->encodePrimaryKey($activity->client_id) : '',
+ 'recurring_invoice_id' => $activity->recurring_invoice_id ? (string) $this->encodePrimaryKey($activity->recurring_invoice_id) : '',
'company_id' => $activity->company_id ? (string) $this->encodePrimaryKey($activity->company_id) : '',
'user_id' => (string) $this->encodePrimaryKey($activity->user_id),
'invoice_id' => $activity->invoice_id ? (string) $this->encodePrimaryKey($activity->invoice_id) : '',
diff --git a/resources/views/portal/ninja2020/components/livewire/subscriptions-recurring-invoices-table.blade.php b/resources/views/portal/ninja2020/components/livewire/subscriptions-recurring-invoices-table.blade.php
index d09928a13366..c744bfce27e1 100644
--- a/resources/views/portal/ninja2020/components/livewire/subscriptions-recurring-invoices-table.blade.php
+++ b/resources/views/portal/ninja2020/components/livewire/subscriptions-recurring-invoices-table.blade.php
@@ -40,6 +40,8 @@
{{ ctrans('texts.date') }}
+
+ |
@@ -63,6 +65,12 @@
{{ $recurring_invoice->formatDate($recurring_invoice->date, $recurring_invoice->client->date_format()) }}
|
+
+
+ {{ ctrans('texts.view') }}
+
+ |
@empty
From d7e551fc957087b3094a27257572b15b74cbb4c6 Mon Sep 17 00:00:00 2001
From: David Bomba
Date: Sun, 27 Jun 2021 21:55:15 +1000
Subject: [PATCH 2/4] Fixes for subscriptions
---
app/Http/Livewire/SubscriptionPlanSwitch.php | 38 ++++++---
app/Jobs/Account/CreateAccount.php | 2 +-
app/Repositories/SubscriptionRepository.php | 11 +--
.../Subscription/SubscriptionService.php | 78 ++++++++++++++++++-
resources/lang/en/texts.php | 1 +
.../subscription-plan-switch.blade.php | 21 +++--
6 files changed, 125 insertions(+), 26 deletions(-)
diff --git a/app/Http/Livewire/SubscriptionPlanSwitch.php b/app/Http/Livewire/SubscriptionPlanSwitch.php
index 75e7533cdc95..a3be473ecf30 100644
--- a/app/Http/Livewire/SubscriptionPlanSwitch.php
+++ b/app/Http/Livewire/SubscriptionPlanSwitch.php
@@ -90,24 +90,40 @@ class SubscriptionPlanSwitch extends Component
$this->state['show_loading_bar'] = true;
- $this->state['invoice'] = $this->target->service()->createChangePlanInvoice([
+ $payment_required = $this->target->service()->changePlanPaymentCheck([
'recurring_invoice' => $this->recurring_invoice,
'subscription' => $this->subscription,
'target' => $this->target,
'hash' => $this->hash,
]);
- Cache::put($this->hash, [
- 'subscription_id' => $this->target->id,
- 'target_id' => $this->target->id,
- 'recurring_invoice' => $this->recurring_invoice->id,
- 'client_id' => $this->recurring_invoice->client->id,
- 'invoice_id' => $this->state['invoice']->id,
- 'context' => 'change_plan',
- now()->addMinutes(60)]
- );
+ if($payment_required)
+ {
+
+ $this->state['invoice'] = $this->target->service()->createChangePlanInvoice([
+ 'recurring_invoice' => $this->recurring_invoice,
+ 'subscription' => $this->subscription,
+ 'target' => $this->target,
+ 'hash' => $this->hash,
+ ]);
+
+ Cache::put($this->hash, [
+ 'subscription_id' => $this->target->id,
+ 'target_id' => $this->target->id,
+ 'recurring_invoice' => $this->recurring_invoice->id,
+ 'client_id' => $this->recurring_invoice->client->id,
+ 'invoice_id' => $this->state['invoice']->id,
+ 'context' => 'change_plan',
+ now()->addMinutes(60)]
+ );
+
+ $this->state['payment_initialised'] = true;
+
+ }
+ else
+ $this->handlePaymentNotRequired();
+
- $this->state['payment_initialised'] = true;
$this->emit('beforePaymentEventsCompleted');
}
diff --git a/app/Jobs/Account/CreateAccount.php b/app/Jobs/Account/CreateAccount.php
index 86458d904b0b..8e356babd8b4 100644
--- a/app/Jobs/Account/CreateAccount.php
+++ b/app/Jobs/Account/CreateAccount.php
@@ -78,7 +78,7 @@ class CreateAccount
$sp794f3f->save();
if(Ninja::isHosted())
- $sp794f3f->startTrial();
+ $sp794f3f->startTrial('pro');
$sp035a66 = CreateCompany::dispatchNow($this->request, $sp794f3f);
$sp035a66->load('account');
diff --git a/app/Repositories/SubscriptionRepository.php b/app/Repositories/SubscriptionRepository.php
index 53fdad8a61d4..9ecf608b1245 100644
--- a/app/Repositories/SubscriptionRepository.php
+++ b/app/Repositories/SubscriptionRepository.php
@@ -96,8 +96,9 @@ class SubscriptionRepository extends BaseRepository
return $data;
}
- public function generateLineItems($subscription, $is_recurring = false)
+ public function generateLineItems($subscription, $is_recurring = false, $is_credit = false)
{
+ $multiplier = $is_credit ? -1 : 1;
$line_items = [];
@@ -105,13 +106,13 @@ class SubscriptionRepository extends BaseRepository
{
foreach($subscription->service()->products() as $product)
{
- $line_items[] = (array)$this->makeLineItem($product);
+ $line_items[] = (array)$this->makeLineItem($product, $multiplier);
}
}
foreach($subscription->service()->recurring_products() as $product)
{
- $line_items[] = (array)$this->makeLineItem($product);
+ $line_items[] = (array)$this->makeLineItem($product, $multiplier);
}
$line_items = $this->cleanItems($line_items);
@@ -120,13 +121,13 @@ class SubscriptionRepository extends BaseRepository
}
- private function makeLineItem($product)
+ private function makeLineItem($product, $multiplier)
{
$item = new InvoiceItem;
$item->quantity = $product->quantity;
$item->product_key = $product->product_key;
$item->notes = $product->notes;
- $item->cost = $product->price;
+ $item->cost = $product->price*$multiplier;
$item->tax_rate1 = $product->tax_rate1 ?: 0;
$item->tax_name1 = $product->tax_name1 ?: '';
$item->tax_rate2 = $product->tax_rate2 ?: 0;
diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php
index 9db0f6b96d57..d692aead90a6 100644
--- a/app/Services/Subscription/SubscriptionService.php
+++ b/app/Services/Subscription/SubscriptionService.php
@@ -214,11 +214,11 @@ class SubscriptionService
if ($outstanding->count() == 0){
//nothing outstanding
- return $target->price - $this->calculateProRataRefund($outstanding_invoice);
+ return $target->price - $this->calculateProRataRefundForSubscription($outstanding_invoice);
}
elseif ($outstanding->count() == 1){
//user has multiple amounts outstanding
- return $target->price - $this->calculateProRataRefund($outstanding_invoice);
+ return $target->price - $this->calculateProRataRefundForSubscription($outstanding_invoice);
}
elseif ($outstanding->count() > 1) {
//user is changing plan mid frequency cycle
@@ -230,6 +230,35 @@ class SubscriptionService
}
+ /**
+ * We refund unused days left.
+ *
+ * @param Invoice $invoice
+ * @return float
+ */
+ private function calculateProRataRefundForSubscription($invoice) :float
+ {
+ if(!$invoice->date)
+ return 0;
+
+ $start_date = Carbon::parse($invoice->date);
+
+ $current_date = now();
+
+ $days_of_subscription_used = $start_date->diffInDays($current_date);
+
+ $days_in_frequency = $this->getDaysInFrequency();
+
+ $pro_rata_refund = round((($days_in_frequency - $days_of_subscription_used)/$days_in_frequency) * $this->subscription->price ,2);
+
+ // nlog("days in frequency = {$days_in_frequency} - days of subscription used {$days_of_subscription_used}");
+ // nlog("invoice amount = {$invoice->amount}");
+ // nlog("pro rata refund = {$pro_rata_refund}");
+
+ return $pro_rata_refund;
+
+ }
+
/**
* We refund unused days left.
*
@@ -251,6 +280,10 @@ class SubscriptionService
$pro_rata_refund = round((($days_in_frequency - $days_of_subscription_used)/$days_in_frequency) * $invoice->amount ,2);
+ // nlog("days in frequency = {$days_in_frequency} - days of subscription used {$days_of_subscription_used}");
+ // nlog("invoice amount = {$invoice->amount}");
+ // nlog("pro rata refund = {$pro_rata_refund}");
+
return $pro_rata_refund;
}
@@ -384,6 +417,44 @@ class SubscriptionService
}
+ public function changePlanPaymentCheck($data)
+ {
+
+ $recurring_invoice = $data['recurring_invoice'];
+ $old_subscription = $data['subscription'];
+ $target_subscription = $data['target'];
+
+ $pro_rata_charge_amount = 0;
+ $pro_rata_refund_amount = 0;
+
+ $last_invoice = Invoice::where('subscription_id', $recurring_invoice->subscription_id)
+ ->where('client_id', $recurring_invoice->client_id)
+ ->where('is_deleted', 0)
+ ->withTrashed()
+ ->orderBy('id', 'desc')
+ ->first();
+
+ if($last_invoice->balance > 0)
+ {
+ $pro_rata_charge_amount = $this->calculateProRataCharge($last_invoice, $old_subscription);
+ nlog("pro rata charge = {$pro_rata_charge_amount}");
+
+ }
+ else
+ {
+ $pro_rata_refund_amount = $this->calculateProRataRefund($last_invoice, $old_subscription) * -1;
+ nlog("pro rata refund = {$pro_rata_refund_amount}");
+ }
+
+ $total_payable = $pro_rata_refund_amount + $pro_rata_charge_amount + $this->subscription->price;
+
+ if($total_payable > 0)
+ return true;
+
+ return false;
+
+ }
+
/**
* When changing plans, we need to generate a pro rata invoice
*
@@ -392,6 +463,7 @@ class SubscriptionService
*/
public function createChangePlanInvoice($data)
{
+
$recurring_invoice = $data['recurring_invoice'];
$old_subscription = $data['subscription'];
$target_subscription = $data['target'];
@@ -500,7 +572,7 @@ class SubscriptionService
$credit->date = now()->format('Y-m-d');
$credit->subscription_id = $this->subscription->id;
- $line_items = $subscription_repo->generateLineItems($target);
+ $line_items = $subscription_repo->generateLineItems($target, false, true);
$credit->line_items = array_merge($line_items, $this->calculateProRataRefundItems($last_invoice, true));
diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php
index 69f9c02c86e9..236923e0c1a4 100644
--- a/resources/lang/en/texts.php
+++ b/resources/lang/en/texts.php
@@ -4272,6 +4272,7 @@ $LANG = array(
'default_payment_method' => 'Make this your preferred way of paying.',
'already_default_payment_method' => 'This is your preferred way of paying.',
'auto_bill_disabled' => 'Auto Bill Disabled',
+ 'select_payment_method' => 'Select a payment method:',
);
return $LANG;
diff --git a/resources/views/portal/ninja2020/components/livewire/subscription-plan-switch.blade.php b/resources/views/portal/ninja2020/components/livewire/subscription-plan-switch.blade.php
index ea6856b34019..b71272ce0e88 100644
--- a/resources/views/portal/ninja2020/components/livewire/subscription-plan-switch.blade.php
+++ b/resources/views/portal/ninja2020/components/livewire/subscription-plan-switch.blade.php
@@ -10,11 +10,10 @@
- Select a payment method:
- {{--
--}}
- {{-- {{ ctrans('texts.total') }}: {{ \App\Utils\Number::formatMoney($total, $subscription->company) }}--}}
- {{-- {{ \App\Utils\Number::formatMoney($subscription->price, $subscription->company) }}--}}
- {{--
--}}
+ {{ ctrans('texts.select_payment_method')}}
+
+ {{ ctrans('texts.total') }}: {{ \App\Utils\Number::formatMoney($amount, $subscription->company) }}
+
@@ -63,9 +62,19 @@
@elseif($amount < 0)
-