mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Add recurring options to ivnoice
This commit is contained in:
parent
a10f06796a
commit
f14de42684
@ -53,6 +53,7 @@ class RecurringInvoiceFactory
|
||||
$invoice->remaining_cycles = -1;
|
||||
$invoice->paid_to_date = 0;
|
||||
$invoice->auto_bill_enabled = false;
|
||||
$invoice->is_proforma = false;
|
||||
$invoice->auto_bill = 'off';
|
||||
|
||||
return $invoice;
|
||||
|
@ -46,6 +46,7 @@ class RecurringInvoiceToInvoiceFactory
|
||||
$invoice->custom_value4 = $recurring_invoice->custom_value4;
|
||||
$invoice->amount = $recurring_invoice->amount;
|
||||
$invoice->uses_inclusive_taxes = $recurring_invoice->uses_inclusive_taxes;
|
||||
$invoice->is_proforma = $recurring_invoice->is_proforma;
|
||||
|
||||
$invoice->custom_surcharge1 = $recurring_invoice->custom_surcharge1;
|
||||
$invoice->custom_surcharge2 = $recurring_invoice->custom_surcharge2;
|
||||
|
@ -80,6 +80,7 @@ class PrePaymentController extends Controller
|
||||
$invoice = $invoice_repo->save($data, $invoice)
|
||||
->service()
|
||||
->markSent()
|
||||
->applyNumber()
|
||||
->fillDefaults()
|
||||
->save();
|
||||
|
||||
@ -107,6 +108,9 @@ class PrePaymentController extends Controller
|
||||
'hashed_ids' => $invoices->pluck('hashed_id'),
|
||||
'total' => $total,
|
||||
'pre_payment' => true,
|
||||
'frequency_id' => $request->frequency_id,
|
||||
'remaining_cycles' => $request->remaining_cycles,
|
||||
'is_recurring' => $request->is_recurring,
|
||||
];
|
||||
|
||||
|
||||
|
@ -138,9 +138,9 @@ class PortalComposer
|
||||
$data[] = ['title' => ctrans('texts.subscriptions'), 'url' => 'client.subscriptions.index', 'icon' => 'calendar'];
|
||||
}
|
||||
|
||||
if(property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) {
|
||||
// if(property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) {
|
||||
$data[] = ['title' => ctrans('texts.pre_payment'), 'url' => 'client.pre_payments.index', 'icon' => 'dollar-sign'];
|
||||
}
|
||||
// }
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ class InstantPayment
|
||||
use MakesHash;
|
||||
use MakesDates;
|
||||
|
||||
/** $request mixed */
|
||||
public Request $request;
|
||||
|
||||
public function __construct(Request $request)
|
||||
@ -214,7 +215,16 @@ class InstantPayment
|
||||
$credit_totals = 0;
|
||||
}
|
||||
|
||||
$hash_data = ['invoices' => $payable_invoices->toArray(), 'credits' => $credit_totals, 'amount_with_fee' => max(0, (($invoice_totals + $fee_totals) - $credit_totals)), 'pre_payment' => $this->request->pre_payment];
|
||||
/** $hash_data = mixed[] */
|
||||
$hash_data = [
|
||||
'invoices' => $payable_invoices->toArray(),
|
||||
'credits' => $credit_totals,
|
||||
'amount_with_fee' => max(0, (($invoice_totals + $fee_totals) - $credit_totals)),
|
||||
'pre_payment' => $this->request->pre_payment,
|
||||
'frequency_id' => $this->request->frequency_id,
|
||||
'remaining_cycles' => $this->request->remaining_cycles,
|
||||
'is_recurring' => $this->request->is_recurring,
|
||||
];
|
||||
|
||||
if ($this->request->query('hash')) {
|
||||
$hash_data['billing_context'] = Cache::get($this->request->query('hash'));
|
||||
|
@ -40,6 +40,13 @@ class ApplyNumber extends AbstractService
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
/** Do no give pro forma invoices a proper invoice number */
|
||||
if($this->invoice->is_proforma) {
|
||||
$this->invoice->number = ctrans('texts.pre_payment') . " " . now()->format('Y-m-d : H:i:s');
|
||||
$this->invoice->saveQuietly();
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
switch ($this->client->getSetting('counter_number_applied')) {
|
||||
case 'when_saved':
|
||||
$this->trySaving();
|
||||
|
@ -121,7 +121,17 @@ class AutoBillInvoice extends AbstractService
|
||||
|
||||
$payment_hash = PaymentHash::create([
|
||||
'hash' => Str::random(64),
|
||||
'data' => ['amount_with_fee' => $amount + $fee, 'invoices' => [['invoice_id' => $this->invoice->hashed_id, 'amount' => $amount, 'invoice_number' => $this->invoice->number]]],
|
||||
'data' => [
|
||||
'amount_with_fee' => $amount + $fee,
|
||||
'invoices' => [
|
||||
[
|
||||
'invoice_id' => $this->invoice->hashed_id,
|
||||
'amount' => $amount,
|
||||
'invoice_number' => $this->invoice->number,
|
||||
'pre_payment' => $this->invoice->is_proforma,
|
||||
],
|
||||
],
|
||||
],
|
||||
'fee_total' => $fee,
|
||||
'fee_invoice_id' => $this->invoice->id,
|
||||
]);
|
||||
|
@ -11,12 +11,14 @@
|
||||
|
||||
namespace App\Services\Payment;
|
||||
|
||||
use App\Events\Invoice\InvoiceWasUpdated;
|
||||
use App\Utils\Ninja;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PaymentHash;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Factory\RecurringInvoiceFactory;
|
||||
use App\Events\Invoice\InvoiceWasUpdated;
|
||||
|
||||
class UpdateInvoicePayment
|
||||
{
|
||||
@ -93,9 +95,31 @@ class UpdateInvoicePayment
|
||||
$invoice->is_deleted = true;
|
||||
$invoice->deleted_at = now();
|
||||
$invoice->saveQuietly();
|
||||
|
||||
if (property_exists($this->payment_hash->data, 'is_recurring') && $this->payment_hash->data->is_recurring == "1") {
|
||||
$recurring_invoice = RecurringInvoiceFactory::create($invoice->company_id, $invoice->user_id);
|
||||
$recurring_invoice->client_id = $invoice->client_id;
|
||||
$recurring_invoice->line_items = $invoice->line_items;
|
||||
$recurring_invoice->frequency_id = $this->payment_hash->data->is_recurring ?: RecurringInvoice::FREQUENCY_MONTHLY;
|
||||
$recurring_invoice->date = now();
|
||||
$recurring_invoice->remaining_cycles = $this->payment_hash->data->remaining_cycles;
|
||||
$recurring_invoice->auto_bill = 'always';
|
||||
$recurring_invoice->auto_bill_enabled = true;
|
||||
$recurring_invoice->due_date_days = 'on_receipt';
|
||||
$recurring_invoice->next_send_date = now()->format('Y-m-d');
|
||||
$recurring_invoice->next_send_date_client = now()->format('Y-m-d');
|
||||
|
||||
$recurring_invoice->saveQuietly();
|
||||
$recurring_invoice->next_send_date = $recurring_invoice->nextSendDate();
|
||||
$recurring_invoice->next_send_date_client = $recurring_invoice->nextSendDateClient();
|
||||
$recurring_invoice->saveQuietly();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (strlen($invoice->number) > 1 && str_starts_with($invoice->number, "####"))
|
||||
$invoice->number = '';
|
||||
|
||||
|
@ -1087,7 +1087,7 @@ class SubscriptionService
|
||||
}
|
||||
|
||||
|
||||
private function setAutoBillFlag($auto_bill)
|
||||
private function setAutoBillFlag($auto_bill): bool
|
||||
{
|
||||
if ($auto_bill == 'always' || $auto_bill == 'optout') {
|
||||
return true;
|
||||
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('recurring_invoices', function (Blueprint $table) {
|
||||
$table->boolean('is_proforma')->default(false);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
@ -5021,7 +5021,9 @@ $LANG = array(
|
||||
'payment_type_Klarna' => 'Klarna',
|
||||
'payment_type_Interac E Transfer' => 'Interac E Transfer',
|
||||
'pre_payment' => 'Pre Payment',
|
||||
'client_remaining_cycles_helper' => 'The number of times this invoice will be generated',
|
||||
'number_of_payments' => 'Number of payments',
|
||||
'number_of_payments_helper' => 'The number of times this payment will be made',
|
||||
'pre_payment_indefinitely' => 'Continue until cancelled',
|
||||
);
|
||||
|
||||
|
||||
|
@ -14,6 +14,9 @@
|
||||
<input type="hidden" name="payment_method_id" id="payment_method_id">
|
||||
<input type="hidden" name="signature">
|
||||
<input type="hidden" name="pre_payment" value="{{ isset($pre_payment) ? $pre_payment : false }}">
|
||||
<input type="hidden" name="is_recurring" value="{{ isset($is_recurring) ? $is_recurring : false }}">
|
||||
<input type="hidden" name="frequency_id" value="{{ isset($frequency_id) ? $frequency_id : false }}">
|
||||
<input type="hidden" name="remaining_cycles" value="{{ isset($remaining_cycles) ? $remaining_cycles : false }}">
|
||||
|
||||
<div class="container mx-auto">
|
||||
<div class="grid grid-cols-6 gap-4">
|
||||
|
@ -56,15 +56,15 @@
|
||||
@endcomponent
|
||||
|
||||
<div x-cloak x-show="show">
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.cycles_remaining')])
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.number_of_payments')])
|
||||
<select name="remaining_cycles" class="form-select input w-full bg-white">
|
||||
<option value="-1" selected>{{ ctrans('texts.freq_indefinitely')}}</option>
|
||||
<option value="-1" selected>{{ ctrans('texts.pre_payment_indefinitely')}}</option>
|
||||
@for($i = 1; $i < 60; $i++)
|
||||
<option value={{$i}}>{{$i}}</option>
|
||||
@endfor
|
||||
</select>
|
||||
<span class="py-2">
|
||||
<label for="remaining_cycles" class="col-form-label text-center col-lg-3 text-gray-900">{{ ctrans ('texts.client_remaining_cycles_helper')}}</label>
|
||||
<label for="remaining_cycles" class="col-form-label text-center col-lg-3 text-gray-900">{{ ctrans ('texts.number_of_payments_helper')}}</label>
|
||||
</span>
|
||||
@endcomponent
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.frequency')])
|
||||
@ -73,14 +73,14 @@
|
||||
<option value="2">{{ ctrans('texts.freq_weekly') }}</option>
|
||||
<option value="3">{{ ctrans('texts.freq_two_weeks') }}</option>
|
||||
<option value="4">{{ ctrans('texts.freq_four_weeks') }}</option>
|
||||
<option value="5">{{ ctrans('texts.freq_monthly') }}</option>
|
||||
<option value="5" selected>{{ ctrans('texts.freq_monthly') }}</option>
|
||||
<option value="6">{{ ctrans('texts.freq_two_months') }}</option>
|
||||
<option value="7">{{ ctrans('texts.freq_three_months') }}</option>
|
||||
<option value="8">{{ ctrans('texts.') }}</option>
|
||||
<option value="9">{{ ctrans('texts.') }}</option>
|
||||
<option value="10">{{ ctrans('texts.') }}</option>
|
||||
<option value="11">{{ ctrans('texts.') }}</option>
|
||||
<option value="12">{{ ctrans('texts.') }}</option>
|
||||
<option value="8">{{ ctrans('texts.freq_four_months') }}</option>
|
||||
<option value="9">{{ ctrans('texts.freq_six_months') }}</option>
|
||||
<option value="10">{{ ctrans('texts.freq_annually') }}</option>
|
||||
<option value="11">{{ ctrans('texts.freq_two_years') }}</option>
|
||||
<option value="12">{{ ctrans('texts.freq_three_years') }}</option>
|
||||
</select>
|
||||
@endcomponent
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user