mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Refactoring subscriptions
This commit is contained in:
parent
986e7fee86
commit
aabe5683e1
@ -32,6 +32,7 @@ use App\Models\Expense;
|
||||
use App\Models\Product;
|
||||
use App\Models\Project;
|
||||
use App\Models\Quote;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Models\Task;
|
||||
use App\Models\User;
|
||||
use App\Models\Vendor;
|
||||
@ -255,6 +256,7 @@ class CreateSingleAccount extends Command
|
||||
$sub->recurring_product_ids = "{$p1->hashed_id}";
|
||||
$sub->webhook_configuration = $webhook_config;
|
||||
$sub->allow_plan_changes = true;
|
||||
$sub->frequency_id = RecurringInvoice::FREQUENCY_MONTHLY;
|
||||
$sub->save();
|
||||
|
||||
$sub = SubscriptionFactory::create($company->id, $user->id);
|
||||
@ -263,6 +265,7 @@ class CreateSingleAccount extends Command
|
||||
$sub->recurring_product_ids = "{$p2->hashed_id}";
|
||||
$sub->webhook_configuration = $webhook_config;
|
||||
$sub->allow_plan_changes = true;
|
||||
$sub->frequency_id = RecurringInvoice::FREQUENCY_MONTHLY;
|
||||
$sub->save();
|
||||
|
||||
$sub = SubscriptionFactory::create($company->id, $user->id);
|
||||
@ -271,6 +274,7 @@ class CreateSingleAccount extends Command
|
||||
$sub->recurring_product_ids = "{$p3->hashed_id}";
|
||||
$sub->webhook_configuration = $webhook_config;
|
||||
$sub->allow_plan_changes = true;
|
||||
$sub->frequency_id = RecurringInvoice::FREQUENCY_MONTHLY;
|
||||
$sub->save();
|
||||
}
|
||||
|
||||
|
@ -112,6 +112,7 @@ class BillingPortalPurchase extends Component
|
||||
'show_loading_bar' => false,
|
||||
'not_eligible' => null,
|
||||
'not_eligible_message' => null,
|
||||
'payment_required' => true,
|
||||
];
|
||||
|
||||
/**
|
||||
@ -269,8 +270,11 @@ class BillingPortalPurchase extends Component
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->steps['fetched_payment_methods'] = true;
|
||||
|
||||
if((int)$this->subscription->price == 0)
|
||||
$this->steps['payment_required'] = false;
|
||||
else
|
||||
$this->steps['fetched_payment_methods'] = true;
|
||||
|
||||
$this->methods = $contact->client->service()->getPaymentMethods($this->price);
|
||||
|
||||
@ -357,6 +361,30 @@ class BillingPortalPurchase extends Component
|
||||
'email' => $this->email ?? $this->contact->email,
|
||||
'quantity' => $this->quantity,
|
||||
'contact_id' => $this->contact->id,
|
||||
'client_id' => $this->contact->client->id,
|
||||
]);
|
||||
}
|
||||
|
||||
public function handlePaymentNotRequired()
|
||||
{
|
||||
|
||||
$is_eligible = $this->subscription->service()->isEligible($this->contact);
|
||||
|
||||
if ($is_eligible['status_code'] != 200) {
|
||||
$this->steps['not_eligible'] = true;
|
||||
$this->steps['not_eligible_message'] = $is_eligible['exception']['message'];
|
||||
$this->steps['show_loading_bar'] = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
return $this->subscription->service()->handleNoPaymentRequired([
|
||||
'email' => $this->email ?? $this->contact->email,
|
||||
'quantity' => $this->quantity,
|
||||
'contact_id' => $this->contact->id,
|
||||
'client_id' => $this->contact->client->id,
|
||||
'coupon' => '',
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -105,10 +105,10 @@ class NinjaMailerJob implements ShouldQueue
|
||||
|
||||
switch ($class) {
|
||||
case Invoice::class:
|
||||
event(new InvoiceWasEmailedAndFailed($this->nmo->invitation, $this->nmo->company, $message, $this->nmo->reminder_template, Ninja::eventVars(auth()->user()->id)));
|
||||
event(new InvoiceWasEmailedAndFailed($this->nmo->invitation, $this->nmo->company, $message, $this->nmo->reminder_template, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
break;
|
||||
case Payment::class:
|
||||
event(new PaymentWasEmailedAndFailed($this->nmo->entity, $this->nmo->company, $message, Ninja::eventVars(auth()->user()->id)));
|
||||
event(new PaymentWasEmailedAndFailed($this->nmo->entity, $this->nmo->company, $message, Ninja::eventVars(auth()->user ? auth()->user()->id : null)));
|
||||
break;
|
||||
default:
|
||||
# code...
|
||||
|
@ -29,6 +29,7 @@ use App\Models\SystemLog;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use App\Repositories\RecurringInvoiceRepository;
|
||||
use App\Repositories\SubscriptionRepository;
|
||||
use App\Services\Subscription\ZeroCostProduct;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\CleanLineItems;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
@ -93,12 +94,10 @@ class SubscriptionService
|
||||
|
||||
$response = $this->triggerWebhook($context);
|
||||
|
||||
nlog($response);
|
||||
// nlog($response);
|
||||
|
||||
if(array_key_exists('post_purchase_url', $this->subscription->webhook_configuration) && strlen($this->subscription->webhook_configuration['post_purchase_url']) >=1)
|
||||
return redirect($this->subscription->webhook_configuration['post_purchase_url']);
|
||||
$this->handleRedirect('/client/recurring_invoices/'.$recurring_invoice->hashed_id);
|
||||
|
||||
return redirect('/client/recurring_invoices/'.$recurring_invoice->hashed_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -114,10 +113,7 @@ class SubscriptionService
|
||||
//execute any webhooks
|
||||
$this->triggerWebhook($context);
|
||||
|
||||
if(array_key_exists('post_purchase_url', $this->subscription->webhook_configuration) && strlen($this->subscription->webhook_configuration['post_purchase_url']) >=1)
|
||||
return redirect($this->subscription->webhook_configuration['post_purchase_url']);
|
||||
|
||||
return redirect('/client/invoices/'.$this->encodePrimaryKey($payment_hash->fee_invoice_id));
|
||||
$this->handleRedirect('/client/invoices/'.$this->encodePrimaryKey($payment_hash->fee_invoice_id));
|
||||
|
||||
}
|
||||
}
|
||||
@ -417,6 +413,7 @@ class SubscriptionService
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function createInvoice($data): ?\App\Models\Invoice
|
||||
{
|
||||
|
||||
@ -438,7 +435,7 @@ class SubscriptionService
|
||||
}
|
||||
|
||||
|
||||
private function convertInvoiceToRecurring($client_id) :RecurringInvoice
|
||||
public function convertInvoiceToRecurring($client_id) :RecurringInvoice
|
||||
{
|
||||
|
||||
$subscription_repo = new SubscriptionRepository();
|
||||
@ -480,7 +477,8 @@ class SubscriptionService
|
||||
else {
|
||||
|
||||
$status = $response->getStatusCode();
|
||||
$response_body = $response->getBody();
|
||||
|
||||
//$response_body = $response->getReasonPhrase();
|
||||
$body = array_merge($body, ['status' => $status, 'response_body' => $response_body]);
|
||||
|
||||
}
|
||||
@ -580,6 +578,36 @@ class SubscriptionService
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 'email' => $this->email ?? $this->contact->email,
|
||||
* 'quantity' => $this->quantity,
|
||||
* 'contact_id' => $this->contact->id,
|
||||
*/
|
||||
public function handleNoPaymentRequired(array $data)
|
||||
{
|
||||
|
||||
$context = (new ZeroCostProduct($this->subscription, $data))->run();
|
||||
|
||||
// Forward payload to webhook
|
||||
if(array_key_exists('context', $context))
|
||||
$response = $this->triggerWebhook($context);
|
||||
|
||||
// Hit the redirect
|
||||
return $this->handleRedirect($context['redirect_url']);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles redirecting the user
|
||||
*/
|
||||
private function handleRedirect($default_redirect)
|
||||
{
|
||||
|
||||
if(array_key_exists('return_url', $this->subscription->webhook_configuration) && strlen($this->subscription->webhook_configuration['return_url']) >=1)
|
||||
return redirect($this->subscription->webhook_configuration['return_url']);
|
||||
|
||||
return redirect($default_redirect);
|
||||
}
|
||||
}
|
||||
|
84
app/Services/Subscription/ZeroCostProduct.php
Normal file
84
app/Services/Subscription/ZeroCostProduct.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Services\Subscription;
|
||||
|
||||
use App\Models\Subscription;
|
||||
use App\Repositories\RecurringInvoiceRepository;
|
||||
use App\Services\AbstractService;
|
||||
|
||||
class ZeroCostProduct extends AbstractService
|
||||
{
|
||||
private $subscription;
|
||||
|
||||
private $data;
|
||||
|
||||
/**
|
||||
$data = [
|
||||
'email' => $this->email ?? $this->contact->email,
|
||||
'quantity' => $this->quantity,
|
||||
'contact_id' => $this->contact->id,
|
||||
'client_id' => $this->contact->client->id,
|
||||
];
|
||||
*/
|
||||
public function __construct(Subscription $subscription, array $data)
|
||||
{
|
||||
$this->subscription = $subscription;
|
||||
|
||||
$this->data = $data;
|
||||
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
//create a zero dollar invoice.
|
||||
|
||||
$invoice = $this->subscription->service()->createInvoice($this->data);
|
||||
|
||||
$invoice->service()
|
||||
->markPaid()
|
||||
->save();
|
||||
|
||||
$redirect_url = "/client/invoices/{$invoice->hashed_id}";
|
||||
|
||||
//create a recurring zero dollar invoice attached to this subscription.
|
||||
|
||||
if(strlen($this->subscription->recurring_product_ids) >=1){
|
||||
|
||||
$recurring_invoice = $this->subscription->service()->convertInvoiceToRecurring($this->data['client_id']);
|
||||
$recurring_invoice_repo = new RecurringInvoiceRepository();
|
||||
|
||||
$recurring_invoice->next_send_date = now();
|
||||
$recurring_invoice = $recurring_invoice_repo->save([], $recurring_invoice);
|
||||
$recurring_invoice->next_send_date = $recurring_invoice->nextSendDate();
|
||||
|
||||
/* Start the recurring service */
|
||||
$recurring_invoice->service()
|
||||
->start()
|
||||
->save();
|
||||
|
||||
$context = [
|
||||
'context' => 'recurring_purchase',
|
||||
'recurring_invoice' => $recurring_invoice->hashed_id,
|
||||
'invoice' => $invoice->hashed_id,
|
||||
'client' => $recurring_invoice->client->hashed_id,
|
||||
'subscription' => $this->subscription->hashed_id,
|
||||
'contact' => auth('contact')->user()->hashed_id,
|
||||
'redirect_url' => "/client/recurring_invoices/{$recurring_invoice->hashed_id}",
|
||||
];
|
||||
|
||||
return $context;
|
||||
}
|
||||
|
||||
return ['redirect_url' => $redirect_url];
|
||||
}
|
||||
|
||||
}
|
@ -40,11 +40,13 @@ trait SubscriptionHooker
|
||||
RequestOptions::JSON => ['body' => $body], RequestOptions::ALLOW_REDIRECTS => false
|
||||
]);
|
||||
|
||||
return $response;
|
||||
return array_merge($body, ['exception' => json_decode($response->getBody(),true), 'status_code' => $response->getStatusCode()]);
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
$body = array_merge($body, ['exception' => $e->getMessage()]);
|
||||
//;
|
||||
// dd($e);
|
||||
$body = array_merge($body, ['exception' => ['message' => $e->getMessage(), 'status_code' => 500]]);
|
||||
return $body;
|
||||
}
|
||||
|
||||
|
@ -4210,7 +4210,7 @@ $LANG = array(
|
||||
'activity_83' => ':user deleted subscription :subscription',
|
||||
'activity_84' => ':user restored subscription :subscription',
|
||||
'amount_greater_than_balance_v5' => 'The amount is greater than the invoice balance. You cannot overpay an invoice.',
|
||||
|
||||
'click_to_continue' => 'Click to continue',
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -135,6 +135,13 @@
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
@elseif(!$steps['payment_required'])
|
||||
<form wire:submit.prevent="handlePaymentNotRequired" class="mt-8">
|
||||
@csrf
|
||||
<button class="px-3 py-2 border rounded mr-4 hover:border-blue-600">
|
||||
{{ ctrans('texts.click_to_continue') }}
|
||||
</button>
|
||||
</form>
|
||||
@elseif($steps['show_start_trial'])
|
||||
<form wire:submit.prevent="handleTrial" class="mt-8">
|
||||
@csrf
|
||||
|
Loading…
x
Reference in New Issue
Block a user