mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-17 16:42:48 +01:00
Allow client to choose auto bill settings
This commit is contained in:
parent
70b9c9bba7
commit
9a64db3234
@ -305,7 +305,7 @@ class PublicClientController extends BaseController
|
||||
->make();
|
||||
}
|
||||
|
||||
public function invoiceIndex()
|
||||
public function recurringInvoiceIndex()
|
||||
{
|
||||
if (!$invitation = $this->getInvitation()) {
|
||||
return $this->returnError();
|
||||
@ -322,6 +322,34 @@ class PublicClientController extends BaseController
|
||||
$data = [
|
||||
'color' => $color,
|
||||
'account' => $account,
|
||||
'client' => $invitation->invoice->client,
|
||||
'clientFontUrl' => $account->getFontsUrl(),
|
||||
'title' => trans('texts.recurring_invoices'),
|
||||
'entityType' => ENTITY_RECURRING_INVOICE,
|
||||
'columns' => Utils::trans(['frequency', 'start_date', 'end_date', 'invoice_total', 'auto_bill']),
|
||||
];
|
||||
|
||||
return response()->view('public_list', $data);
|
||||
}
|
||||
|
||||
public function invoiceIndex()
|
||||
{
|
||||
if (!$invitation = $this->getInvitation()) {
|
||||
return $this->returnError();
|
||||
}
|
||||
|
||||
$account = $invitation->account;
|
||||
|
||||
if (!$account->enable_client_portal) {
|
||||
return $this->returnError();
|
||||
}
|
||||
|
||||
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
||||
|
||||
$data = [
|
||||
'color' => $color,
|
||||
'account' => $account,
|
||||
'client' => $invitation->invoice->client,
|
||||
'clientFontUrl' => $account->getFontsUrl(),
|
||||
'title' => trans('texts.invoices'),
|
||||
'entityType' => ENTITY_INVOICE,
|
||||
@ -340,6 +368,15 @@ class PublicClientController extends BaseController
|
||||
return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_INVOICE, Input::get('sSearch'));
|
||||
}
|
||||
|
||||
public function recurringInvoiceDatatable()
|
||||
{
|
||||
if (!$invitation = $this->getInvitation()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->invoiceRepo->getClientRecurringDatatable($invitation->contact_id);
|
||||
}
|
||||
|
||||
|
||||
public function paymentIndex()
|
||||
{
|
||||
@ -860,4 +897,28 @@ class PublicClientController extends BaseController
|
||||
Session::flash('error', $message);
|
||||
Utils::logError("Payment Method Error [{$type}]: " . ($exception ? Utils::getErrorString($exception) : $message), 'PHP', true);
|
||||
}
|
||||
|
||||
public function setAutoBill(){
|
||||
if (!$invitation = $this->getInvitation()) {
|
||||
return $this->returnError();
|
||||
}
|
||||
|
||||
$validator = Validator::make(Input::all(), array('public_id' => 'required'));
|
||||
$client = $invitation->invoice->client;
|
||||
|
||||
if ($validator->fails()) {
|
||||
return Redirect::to('client/invoices/recurring');
|
||||
}
|
||||
|
||||
$publicId = Input::get('public_id');
|
||||
$enable = Input::get('enable');
|
||||
$invoice = $client->invoices->where('public_id', intval($publicId))->first();
|
||||
|
||||
if ($invoice && $invoice->is_recurring && $invoice->enable_auto_bill > AUTO_BILL_OFF) {
|
||||
$invoice->auto_bill = $enable ? true : false;
|
||||
$invoice->save();
|
||||
}
|
||||
|
||||
return Redirect::to('client/invoices/recurring');
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ Route::group(['middleware' => 'auth:client'], function() {
|
||||
Route::post('client/paymentmethods/{source_id}/remove', 'PublicClientController@removePaymentMethod');
|
||||
Route::get('client/quotes', 'PublicClientController@quoteIndex');
|
||||
Route::get('client/invoices', 'PublicClientController@invoiceIndex');
|
||||
Route::get('client/invoices/recurring', 'PublicClientController@recurringInvoiceIndex');
|
||||
Route::post('client/invoices/auto_bill', 'PublicClientController@setAutoBill');
|
||||
Route::get('client/documents', 'PublicClientController@documentIndex');
|
||||
Route::get('client/payments', 'PublicClientController@paymentIndex');
|
||||
Route::get('client/dashboard', 'PublicClientController@dashboard');
|
||||
@ -60,6 +62,7 @@ Route::group(['middleware' => 'auth:client'], function() {
|
||||
|
||||
Route::get('api/client.quotes', array('as'=>'api.client.quotes', 'uses'=>'PublicClientController@quoteDatatable'));
|
||||
Route::get('api/client.invoices', array('as'=>'api.client.invoices', 'uses'=>'PublicClientController@invoiceDatatable'));
|
||||
Route::get('api/client.recurring_invoices', array('as'=>'api.client.recurring_invoices', 'uses'=>'PublicClientController@recurringInvoiceDatatable'));
|
||||
Route::get('api/client.documents', array('as'=>'api.client.documents', 'uses'=>'PublicClientController@documentDatatable'));
|
||||
Route::get('api/client.payments', array('as'=>'api.client.payments', 'uses'=>'PublicClientController@paymentDatatable'));
|
||||
Route::get('api/client.activity', array('as'=>'api.client.activity', 'uses'=>'PublicClientController@activityDatatable'));
|
||||
@ -687,6 +690,10 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
|
||||
define('RESELLER_REVENUE_SHARE', 'A');
|
||||
define('RESELLER_LIMITED_USERS', 'B');
|
||||
|
||||
define('AUTO_BILL_OFF', 0);
|
||||
define('AUTO_BILL_OPT_IN', 1);
|
||||
define('AUTO_BILL_OPT_OUT', 2);
|
||||
|
||||
// These must be lowercase
|
||||
define('PLAN_FREE', 'free');
|
||||
|
@ -319,6 +319,10 @@ class Client extends EntityModel
|
||||
$this->last_login = Carbon::now()->toDateTimeString();
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function hasAutoBillInvoices(){
|
||||
return $this->invoices()->where('auto_bill', 1)->count() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
Client::creating(function ($client) {
|
||||
|
@ -145,21 +145,68 @@ class InvoiceRepository extends BaseRepository
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function getClientDatatable($contactId, $entityType, $search)
|
||||
public function getClientRecurringDatatable($contactId)
|
||||
{
|
||||
$query = DB::table('invitations')
|
||||
->join('accounts', 'accounts.id', '=', 'invitations.account_id')
|
||||
->join('invoices', 'invoices.id', '=', 'invitations.invoice_id')
|
||||
->join('clients', 'clients.id', '=', 'invoices.client_id')
|
||||
->join('frequencies', 'frequencies.id', '=', 'invoices.frequency_id')
|
||||
->where('invitations.contact_id', '=', $contactId)
|
||||
->where('invitations.deleted_at', '=', null)
|
||||
->where('invoices.is_quote', '=', $entityType == ENTITY_QUOTE)
|
||||
->where('invoices.is_quote', '=', false)
|
||||
->where('invoices.is_deleted', '=', false)
|
||||
->where('clients.deleted_at', '=', null)
|
||||
->where('invoices.is_recurring', '=', false)
|
||||
// This needs to be a setting to also hide the activity on the dashboard page
|
||||
//->where('invoices.invoice_status_id', '>=', INVOICE_STATUS_SENT)
|
||||
->where('invoices.is_recurring', '=', true)
|
||||
->where('invoices.enable_auto_bill', '>', AUTO_BILL_OFF)
|
||||
//->where('invoices.start_date', '>=', date('Y-m-d H:i:s'))
|
||||
->select(
|
||||
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
|
||||
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
|
||||
'invitations.invitation_key',
|
||||
'invoices.invoice_number',
|
||||
'invoices.due_date',
|
||||
'clients.public_id as client_public_id',
|
||||
'clients.name as client_name',
|
||||
'invoices.public_id',
|
||||
'invoices.amount',
|
||||
'invoices.start_date',
|
||||
'invoices.end_date',
|
||||
'invoices.auto_bill',
|
||||
'frequencies.name as frequency'
|
||||
);
|
||||
|
||||
$table = \Datatable::query($query)
|
||||
->addColumn('frequency', function ($model) { return $model->frequency; })
|
||||
->addColumn('start_date', function ($model) { return Utils::fromSqlDate($model->start_date); })
|
||||
->addColumn('end_date', function ($model) { return Utils::fromSqlDate($model->end_date); })
|
||||
->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id); })
|
||||
->addColumn('auto_bill', function ($model) {
|
||||
if ($model->auto_bill) {
|
||||
return trans('texts.enabled') . ' <a href="javascript:setAutoBill('.$model->public_id.',false)">('.trans('texts.disable').')</a>';
|
||||
} else {
|
||||
return trans('texts.disabled') . ' <a href="javascript:setAutoBill('.$model->public_id.',true)">('.trans('texts.enable').')</a>';
|
||||
}
|
||||
});
|
||||
|
||||
return $table->make();
|
||||
}
|
||||
|
||||
public function getClientDatatable($contactId, $entityType, $search)
|
||||
{
|
||||
$query = DB::table('invitations')
|
||||
->join('accounts', 'accounts.id', '=', 'invitations.account_id')
|
||||
->join('invoices', 'invoices.id', '=', 'invitations.invoice_id')
|
||||
->join('clients', 'clients.id', '=', 'invoices.client_id')
|
||||
->where('invitations.contact_id', '=', $contactId)
|
||||
->where('invitations.deleted_at', '=', null)
|
||||
->where('invoices.is_quote', '=', $entityType == ENTITY_QUOTE)
|
||||
->where('invoices.is_deleted', '=', false)
|
||||
->where('clients.deleted_at', '=', null)
|
||||
->where('invoices.is_recurring', '=', false)
|
||||
// This needs to be a setting to also hide the activity on the dashboard page
|
||||
//->where('invoices.invoice_status_id', '>=', INVOICE_STATUS_SENT)
|
||||
->select(
|
||||
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
|
||||
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
|
||||
'invitations.invitation_key',
|
||||
@ -269,6 +316,16 @@ class InvoiceRepository extends BaseRepository
|
||||
$invoice->start_date = Utils::toSqlDate($data['start_date']);
|
||||
$invoice->end_date = Utils::toSqlDate($data['end_date']);
|
||||
$invoice->auto_bill = isset($data['auto_bill']) && $data['auto_bill'] ? true : false;
|
||||
$invoice->enable_auto_bill = isset($data['enable_auto_bill']) ? intval($data['enable_auto_bill']) : 0;
|
||||
|
||||
if ($invoice->enable_auto_bill != AUTO_BILL_OPT_IN && $invoice->enable_auto_bill != AUTO_BILL_OPT_OUT ) {
|
||||
// Auto-bill is not enabled
|
||||
$invoice->enable_auto_bill = AUTO_BILL_OFF;
|
||||
$invoice->auto_bill = false;
|
||||
} elseif ($isNew) {
|
||||
$invoice->auto_bill = $invoice->enable_auto_bill == AUTO_BILL_OPT_OUT;
|
||||
}
|
||||
|
||||
|
||||
if (isset($data['recurring_due_date'])) {
|
||||
$invoice->due_date = $data['recurring_due_date'];
|
||||
|
@ -33,6 +33,15 @@ class PaymentsChanges extends Migration
|
||||
$table->date('expiration')->nullable();
|
||||
$table->text('gateway_error')->nullable();
|
||||
});
|
||||
|
||||
Schema::table('invoices', function($table)
|
||||
{
|
||||
$table->tinyInteger('enable_auto_bill')->default(AUTO_BILL_OFF);
|
||||
});
|
||||
|
||||
\DB::table('invoices')
|
||||
->where('auto_bill', '=', 1)
|
||||
->update(array('enable_auto_bill' => AUTO_BILL_OPT_OUT));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,6 +62,10 @@ class PaymentsChanges extends Migration
|
||||
$table->dropColumn('expiration');
|
||||
$table->dropColumn('gateway_error');
|
||||
});
|
||||
|
||||
Schema::table('invoices', function ($table) {
|
||||
$table->dropColumn('enable_auto_bill');
|
||||
});
|
||||
|
||||
Schema::dropIfExists('payment_statuses');
|
||||
}
|
||||
|
@ -1266,7 +1266,15 @@ $LANG = array(
|
||||
'add_payment_method' => 'Add Payment Method',
|
||||
'account_holder_type' => 'Account Holder Type',
|
||||
'ach_authorization' => 'I authorize :company to electronically debit my account and, if necessary, electronically credit my account to correct erroneous debits.',
|
||||
'ach_authorization_required' => 'You must consent to ACH transactions.'
|
||||
'ach_authorization_required' => 'You must consent to ACH transactions.',
|
||||
'off' => 'Off',
|
||||
'opt_in' => 'Opt-in',
|
||||
'opt_out' => 'Opt-out',
|
||||
'enabled_by_client' => 'Enabled by client',
|
||||
'disabled_by_client' => 'Disabled by client',
|
||||
'manage_auto_bill' => 'Manage Auto-bill',
|
||||
'enabled' => 'Enabled',
|
||||
'disabled' => 'Disabled',
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -159,10 +159,25 @@
|
||||
</span>
|
||||
@if($account->getTokenGatewayId())
|
||||
<span data-bind="visible: is_recurring()" style="display: none">
|
||||
{!! Former::checkbox('auto_bill')
|
||||
->label(trans('texts.auto_bill'))
|
||||
->text(trans('texts.enable'))
|
||||
->data_bind("checked: auto_bill, valueUpdate: 'afterkeydown'") !!}
|
||||
{!! Former::radios('enable_auto_bill')->radios([
|
||||
trans('texts.off') => array('name' => 'enable_auto_bill', 'value' => 0, 'data-bind' => "checked: enable_auto_bill, valueUpdate: 'afterkeydown', checkedValue:0"),
|
||||
trans('texts.opt_in') => array('name' => 'enable_auto_bill', 'value' => 1, 'data-bind' => "checked: enable_auto_bill, valueUpdate: 'afterkeydown', checkedValue:1"),
|
||||
trans('texts.opt_out') => array('name' => 'enable_auto_bill', 'value' => 2, 'data-bind' => "checked: enable_auto_bill, valueUpdate: 'afterkeydown', checkedValue:2"),
|
||||
])->inline()
|
||||
->label(trans('texts.auto_bill')) !!}
|
||||
<input type="hidden" name="auto_bill" data-bind="attr: { value: auto_bill() }" />
|
||||
<div class="row">
|
||||
<div class="col-sm-8 col-sm-offset-4">
|
||||
<div style="margin:-10px 0 10px;">
|
||||
<div data-bind="visible: enable_auto_bill() == 1 && auto_bill() && public_id() != 0" style="display: none">
|
||||
{{trans('texts.enabled_by_client')}} <a href="#" data-bind="click:function(){auto_bill(false)}">({{trans('texts.disable')}})</a>
|
||||
</div>
|
||||
<div data-bind="visible: enable_auto_bill() == 2 && !auto_bill() && public_id() != 0" style="display: none">
|
||||
{{trans('texts.disabled_by_client')}} <a href="#" data-bind="click:function(){auto_bill(true)}">({{trans('texts.enable')}})</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
@endif
|
||||
{!! Former::text('po_number')->label(trans('texts.po_number_short'))->data_bind("value: po_number, valueUpdate: 'afterkeydown'") !!}
|
||||
|
@ -188,7 +188,8 @@ function InvoiceModel(data) {
|
||||
self.tax_rate2 = ko.observable();
|
||||
self.is_recurring = ko.observable(0);
|
||||
self.is_quote = ko.observable({{ $entityType == ENTITY_QUOTE ? '1' : '0' }});
|
||||
self.auto_bill = ko.observable();
|
||||
self.auto_bill = ko.observable(false);
|
||||
self.enable_auto_bill = ko.observable(0);
|
||||
self.invoice_status_id = ko.observable(0);
|
||||
self.invoice_items = ko.observableArray();
|
||||
self.documents = ko.observableArray();
|
||||
|
@ -35,7 +35,12 @@
|
||||
</div>
|
||||
-->
|
||||
|
||||
<h3>{{ $title }}</h3>
|
||||
@if($entityType == ENTITY_INVOICE && $account->getTokenGatewayId() && $client->hasAutoBillInvoices())
|
||||
<div class="pull-right" style="margin-top:5px">
|
||||
{!! Button::info(trans("texts.manage_auto_bill"))->asLinkTo(URL::to('/client/invoices/recurring'))->appendIcon(Icon::create('repeat')) !!}
|
||||
</div>
|
||||
@endif
|
||||
<h3>{{ $title }}</h3>
|
||||
|
||||
{!! Datatable::table()
|
||||
->addColumn($columns)
|
||||
@ -45,6 +50,22 @@
|
||||
|
||||
</div>
|
||||
|
||||
@if($entityType == ENTITY_RECURRING_INVOICE)
|
||||
{!! Former::open(URL::to('/client/invoices/auto_bill'))->id('auto_bill_form') !!}
|
||||
<input type="hidden" name="public_id" id="auto_bill_public_id">
|
||||
<input type="hidden" name="enable" id="auto_bill_enable">
|
||||
{!! Former::close() !!}
|
||||
|
||||
<script type="text/javascript">
|
||||
function setAutoBill(publicId, enable){
|
||||
$('#auto_bill_public_id').val(publicId);
|
||||
$('#auto_bill_enable').val(enable?'1':'0');
|
||||
$('#auto_bill_form').submit();
|
||||
}
|
||||
</script>
|
||||
@endif
|
||||
|
||||
|
||||
<p> </p>
|
||||
|
||||
@stop
|
Loading…
Reference in New Issue
Block a user