mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 13:12:50 +01:00
Subscriptions v2
This commit is contained in:
parent
b7316255a9
commit
55c0453b75
@ -196,6 +196,7 @@ class BillingPortalPurchasev2 extends Component
|
||||
public $float_amount_total;
|
||||
public $payment_started = false;
|
||||
public $valid_coupon = false;
|
||||
public $payable_invoices = [];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
@ -310,12 +311,13 @@ class BillingPortalPurchasev2 extends Component
|
||||
{
|
||||
|
||||
if($this->coupon == $this->subscription->promo_code) {
|
||||
$this->buildBundle();
|
||||
$this->valid_coupon = true;
|
||||
$this->buildBundle();
|
||||
}
|
||||
else{
|
||||
$this->discount = 0;
|
||||
$this->valid_coupon = false;
|
||||
$this->buildBundle();
|
||||
}
|
||||
|
||||
}
|
||||
@ -378,24 +380,24 @@ class BillingPortalPurchasev2 extends Component
|
||||
return $k == $key;
|
||||
});
|
||||
|
||||
$qty = isset($this->data[$key]['optional_recurring_qty']) ? $this->data[$key]['optional_recurring_qty'] : 0;
|
||||
$qty = isset($this->data[$key]['optional_recurring_qty']) ? $this->data[$key]['optional_recurring_qty'] : false;
|
||||
$total = $p->price * $qty;
|
||||
|
||||
if($qty == 0)
|
||||
return;
|
||||
if($qty)
|
||||
{
|
||||
|
||||
$this->bundle->push([
|
||||
'description' => $p->notes,
|
||||
'product_key' => $p->product_key,
|
||||
'unit_cost' => $p->price,
|
||||
'product' => nl2br(substr($p->notes, 0, 50)),
|
||||
'price' => Number::formatMoney($total, $this->subscription->company).' / '. RecurringInvoice::frequencyForKey($this->subscription->frequency_id),
|
||||
'total' => $total,
|
||||
'qty' => $qty,
|
||||
'is_recurring' => true
|
||||
]);
|
||||
|
||||
$this->bundle->push([
|
||||
'description' => $p->notes,
|
||||
'product_key' => $p->product_key,
|
||||
'unit_cost' => $p->price,
|
||||
'product' => nl2br(substr($p->notes, 0, 50)),
|
||||
'price' => Number::formatMoney($total, $this->subscription->company).' / '. RecurringInvoice::frequencyForKey($this->subscription->frequency_id),
|
||||
'total' => $total,
|
||||
'qty' => $qty,
|
||||
'is_recurring' => true
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Optional products can have a variable quantity */
|
||||
@ -405,23 +407,23 @@ class BillingPortalPurchasev2 extends Component
|
||||
return $k == $key;
|
||||
});
|
||||
|
||||
$qty = isset($this->data[$key]['optional_qty']) ? $this->data[$key]['optional_qty'] : 0;
|
||||
$qty = isset($this->data[$key]['optional_qty']) ? $this->data[$key]['optional_qty'] : false;
|
||||
$total = $p->price * $qty;
|
||||
|
||||
if($qty == 0)
|
||||
return;
|
||||
|
||||
$this->bundle->push([
|
||||
'description' => $p->notes,
|
||||
'product_key' => $p->product_key,
|
||||
'unit_cost' => $p->price,
|
||||
'product' => nl2br(substr($p->notes, 0, 50)),
|
||||
'price' => Number::formatMoney($total, $this->subscription->company),
|
||||
'total' => $total,
|
||||
'qty' => $qty,
|
||||
'is_recurring' => false
|
||||
]);
|
||||
|
||||
if($qty)
|
||||
{
|
||||
$this->bundle->push([
|
||||
'description' => $p->notes,
|
||||
'product_key' => $p->product_key,
|
||||
'unit_cost' => $p->price,
|
||||
'product' => nl2br(substr($p->notes, 0, 50)),
|
||||
'price' => Number::formatMoney($total, $this->subscription->company),
|
||||
'total' => $total,
|
||||
'qty' => $qty,
|
||||
'is_recurring' => false
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -429,7 +431,7 @@ class BillingPortalPurchasev2 extends Component
|
||||
$this->sub_total = Number::formatMoney($this->bundle->sum('total'), $this->subscription->company);
|
||||
$this->total = $this->sub_total;
|
||||
|
||||
if($this->coupon == $this->subscription->promo_code)
|
||||
if($this->valid_coupon)
|
||||
{
|
||||
|
||||
if($this->subscription->is_amount_discount)
|
||||
@ -443,6 +445,11 @@ class BillingPortalPurchasev2 extends Component
|
||||
|
||||
$this->float_amount_total = ($this->bundle->sum('total') - $discount);
|
||||
}
|
||||
else {
|
||||
$this->float_amount_total = $this->bundle->sum('total');
|
||||
$this->total = Number::formatMoney($this->float_amount_total, $this->subscription->company);
|
||||
|
||||
}
|
||||
|
||||
|
||||
return $this;
|
||||
@ -490,7 +497,6 @@ class BillingPortalPurchasev2 extends Component
|
||||
*/
|
||||
protected function getPaymentMethods(): self
|
||||
{
|
||||
|
||||
$this->methods = $this->contact->client->service()->getPaymentMethods($this->float_amount_total);
|
||||
|
||||
return $this;
|
||||
@ -505,6 +511,7 @@ class BillingPortalPurchasev2 extends Component
|
||||
*/
|
||||
public function handleMethodSelectingEvent($company_gateway_id, $gateway_type_id)
|
||||
{
|
||||
|
||||
$this->company_gateway_id = $company_gateway_id;
|
||||
$this->payment_method_id = $gateway_type_id;
|
||||
|
||||
@ -546,19 +553,20 @@ class BillingPortalPurchasev2 extends Component
|
||||
->service()
|
||||
->createInvoiceV2($this->bundle, $this->contact->client_id, $this->valid_coupon)
|
||||
->service()
|
||||
// ->markSent()
|
||||
->markSent()
|
||||
->fillDefaults()
|
||||
->adjustInventory()
|
||||
->save();
|
||||
|
||||
// Cache::put($this->hash, [
|
||||
// 'subscription_id' => $this->subscription->id,
|
||||
// 'email' => $this->email ?? $this->contact->email,
|
||||
// 'client_id' => $this->contact->client->id,
|
||||
// 'invoice_id' => $this->invoice->id,
|
||||
// 'context' => 'purchase',
|
||||
// 'campaign' => $this->campaign,
|
||||
// ], now()->addMinutes(60));
|
||||
Cache::put($this->hash, [
|
||||
'subscription_id' => $this->subscription->id,
|
||||
'email' => $this->email ?? $this->contact->email,
|
||||
'client_id' => $this->contact->client->id,
|
||||
'invoice_id' => $this->invoice->id,
|
||||
'context' => 'purchase',
|
||||
'campaign' => $this->campaign,
|
||||
'bundle' => $this->bundle,
|
||||
], now()->addMinutes(60));
|
||||
|
||||
$this->emit('beforePaymentEventsCompleted');
|
||||
}
|
||||
|
@ -112,10 +112,19 @@ class UpdateOrCreateProduct implements ShouldQueue
|
||||
$product->tax_rate2 = isset($item->tax_rate2) ? $item->tax_rate2 : 0;
|
||||
$product->tax_name3 = isset($item->tax_name3) ? $item->tax_name3 : '';
|
||||
$product->tax_rate3 = isset($item->tax_rate3) ? $item->tax_rate3 : 0;
|
||||
$product->custom_value1 = isset($item->custom_value1) ? $item->custom_value1 : '';
|
||||
$product->custom_value2 = isset($item->custom_value2) ? $item->custom_value2 : '';
|
||||
$product->custom_value3 = isset($item->custom_value3) ? $item->custom_value3 : '';
|
||||
$product->custom_value4 = isset($item->custom_value4) ? $item->custom_value4 : '';
|
||||
|
||||
if(isset($item->custom_value1) && strlen($item->custom_value1) >=1)
|
||||
$product->custom_value1 = $item->custom_value1;
|
||||
|
||||
if(isset($item->custom_value2) && strlen($item->custom_value1) >=1)
|
||||
$product->custom_value2 = $item->custom_value2;
|
||||
|
||||
if(isset($item->custom_value3) && strlen($item->custom_value1) >=1)
|
||||
$product->custom_value3 = $item->custom_value3;
|
||||
|
||||
if(isset($item->custom_value4) && strlen($item->custom_value1) >=1)
|
||||
$product->custom_value4 = $item->custom_value4;
|
||||
|
||||
$product->user_id = $this->invoice->user_id;
|
||||
$product->company_id = $this->invoice->company_id;
|
||||
$product->project_id = $this->invoice->project_id;
|
||||
|
@ -118,6 +118,36 @@ class SubscriptionRepository extends BaseRepository
|
||||
return $line_items;
|
||||
}
|
||||
|
||||
public function generateBundleLineItems($bundle, $is_recurring = false, $is_credit = false)
|
||||
{
|
||||
$multiplier = $is_credit ? -1 : 1;
|
||||
|
||||
$line_items = [];
|
||||
|
||||
$line_items = collect($bundle)->filter(function ($item){
|
||||
|
||||
return $item->is_recurring;
|
||||
|
||||
})->map(function ($item){
|
||||
|
||||
$line_item = new InvoiceItem;
|
||||
$line_item->product_key = $item->product_key;
|
||||
$line_item->quantity = (float)$item->qty;
|
||||
$line_item->cost = (float)$item->unit_cost;
|
||||
$line_item->notes = $item->description;
|
||||
|
||||
return $line_item;
|
||||
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$line_items = $this->cleanItems($line_items);
|
||||
|
||||
return $line_items;
|
||||
}
|
||||
|
||||
|
||||
private function makeLineItem($product, $multiplier)
|
||||
{
|
||||
$item = new InvoiceItem;
|
||||
|
@ -79,7 +79,11 @@ class SubscriptionService
|
||||
// if we have a recurring product - then generate a recurring invoice
|
||||
if(strlen($this->subscription->recurring_product_ids) >=1){
|
||||
|
||||
$recurring_invoice = $this->convertInvoiceToRecurring($payment_hash->payment->client_id);
|
||||
if(isset($payment_hash->data->billing_context->bundle))
|
||||
$recurring_invoice = $this->convertInvoiceToRecurringBundle($payment_hash->payment->client_id, $payment_hash->data->billing_context->bundle);
|
||||
else
|
||||
$recurring_invoice = $this->convertInvoiceToRecurring($payment_hash->payment->client_id);
|
||||
|
||||
$recurring_invoice_repo = new RecurringInvoiceRepository();
|
||||
|
||||
$recurring_invoice = $recurring_invoice_repo->save([], $recurring_invoice);
|
||||
@ -718,18 +722,16 @@ class SubscriptionService
|
||||
|
||||
$line_item = new InvoiceItem;
|
||||
$line_item->product_key = $item['product_key'];
|
||||
$line_item->quantity = $item['qty'];
|
||||
$line_item->cost = $item['unit_cost'];
|
||||
$line_item->quantity = (float)$item['qty'];
|
||||
$line_item->cost = (float)$item['unit_cost'];
|
||||
$line_item->notes = $item['description'];
|
||||
|
||||
return $line_item;
|
||||
|
||||
})->toArray();
|
||||
|
||||
nlog($line_items);
|
||||
|
||||
$invoice->line_items = $line_items;
|
||||
|
||||
|
||||
if($valid_coupon){
|
||||
$invoice->discount = $this->subscription->promo_discount;
|
||||
$invoice->is_amount_discount = $this->subscription->is_amount_discount;
|
||||
@ -803,6 +805,41 @@ nlog($line_items);
|
||||
return $recurring_invoice;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a recurring invoice based on
|
||||
* the specifications of the subscription USING BUNDLE
|
||||
*
|
||||
* @param int $client_id The Client Id
|
||||
* @return RecurringInvoice
|
||||
*/
|
||||
public function convertInvoiceToRecurringBundle($client_id, $bundle) :RecurringInvoice
|
||||
{
|
||||
MultiDB::setDb($this->subscription->company->db);
|
||||
|
||||
$client = Client::withTrashed()->find($client_id);
|
||||
|
||||
$subscription_repo = new SubscriptionRepository();
|
||||
|
||||
$recurring_invoice = RecurringInvoiceFactory::create($this->subscription->company_id, $this->subscription->user_id);
|
||||
$recurring_invoice->client_id = $client_id;
|
||||
$recurring_invoice->line_items = $subscription_repo->generateBundleLineItems($bundle, true, false);
|
||||
$recurring_invoice->subscription_id = $this->subscription->id;
|
||||
$recurring_invoice->frequency_id = $this->subscription->frequency_id ?: RecurringInvoice::FREQUENCY_MONTHLY;
|
||||
$recurring_invoice->date = now();
|
||||
$recurring_invoice->remaining_cycles = -1;
|
||||
$recurring_invoice->auto_bill = $client->getSetting('auto_bill');
|
||||
$recurring_invoice->auto_bill_enabled = $this->setAutoBillFlag($recurring_invoice->auto_bill);
|
||||
$recurring_invoice->due_date_days = 'terms';
|
||||
$recurring_invoice->next_send_date = now()->format('Y-m-d');
|
||||
$recurring_invoice->next_send_date_client = now()->format('Y-m-d');
|
||||
$recurring_invoice->next_send_date = $recurring_invoice->nextSendDate();
|
||||
$recurring_invoice->next_send_date_client = $recurring_invoice->nextSendDateClient();
|
||||
|
||||
return $recurring_invoice;
|
||||
}
|
||||
|
||||
|
||||
private function setAutoBillFlag($auto_bill)
|
||||
{
|
||||
if ($auto_bill == 'always' || $auto_bill == 'optout') {
|
||||
|
@ -4902,7 +4902,11 @@ $LANG = array(
|
||||
'delete_tax_rate' => 'Delete Tax Rate',
|
||||
'restore_tax_rate' => 'Restore Tax Rate',
|
||||
'company_backup_file' => 'Select company backup file',
|
||||
'company_backup_file_help' => 'Please upload the .zip file used to create this backup.'
|
||||
'company_backup_file_help' => 'Please upload the .zip file used to create this backup.',
|
||||
'backup_restore' => 'Backup | Restore',
|
||||
'export_company' => 'Create company backup',
|
||||
'backup' => 'Backup',
|
||||
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -25,8 +25,8 @@
|
||||
@endif
|
||||
|
||||
<input type="hidden" name="action" value="payment">
|
||||
<input type="hidden" name="company_gateway_id" value=""/>
|
||||
<input type="hidden" name="payment_method_id" value=""/>
|
||||
<input type="hidden" name="company_gateway_id" value="{{ $company_gateway_id }}"/>
|
||||
<input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}"/>
|
||||
</form>
|
||||
</div>
|
||||
@endif
|
||||
@ -261,7 +261,7 @@
|
||||
{{ session('message') }}
|
||||
@endcomponent
|
||||
@endif
|
||||
@if(count($methods) > 0 && !$payment_started)
|
||||
@if(count($methods) > 0)
|
||||
<div class="mt-4">
|
||||
@foreach($methods as $method)
|
||||
<button
|
||||
|
Loading…
Reference in New Issue
Block a user