mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-08 17:24:29 -04:00
Allow admin to set min/max amount for each payment type
This commit is contained in:
parent
03cc5035c5
commit
620e93084f
@ -1,6 +1,8 @@
|
|||||||
<?php namespace App\Http\Controllers;
|
<?php namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\AccountGateway;
|
use App\Models\AccountGateway;
|
||||||
|
use App\Models\AccountGatewaySettings;
|
||||||
|
use App\Models\GatewayType;
|
||||||
use App\Services\TemplateService;
|
use App\Services\TemplateService;
|
||||||
use Auth;
|
use Auth;
|
||||||
use File;
|
use File;
|
||||||
@ -458,10 +460,12 @@ class AccountController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
return View::make('accounts.payments', [
|
return View::make('accounts.payments', [
|
||||||
'showAdd' => $count < count(Gateway::$alternate) + 1,
|
'showAdd' => $count < count(Gateway::$alternate) + 1,
|
||||||
'title' => trans('texts.online_payments'),
|
'title' => trans('texts.online_payments'),
|
||||||
'tokenBillingOptions' => $tokenBillingOptions,
|
'tokenBillingOptions' => $tokenBillingOptions,
|
||||||
'account' => $account,
|
'currency' => Utils::getFromCache(Session::get(SESSION_CURRENCY, DEFAULT_CURRENCY),
|
||||||
|
'currencies'),
|
||||||
|
'account' => $account,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1224,6 +1228,35 @@ class AccountController extends BaseController
|
|||||||
return Redirect::to('settings/'.ACCOUNT_PAYMENTS);
|
return Redirect::to('settings/'.ACCOUNT_PAYMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function savePaymentGatewayLimits()
|
||||||
|
{
|
||||||
|
$gateway_type_id = intval(Input::get('gateway_type_id'));
|
||||||
|
$gateway_settings = AccountGatewaySettings::scope()->where('gateway_type_id', '=', $gateway_type_id)->first();
|
||||||
|
|
||||||
|
if ( ! $gateway_settings) {
|
||||||
|
$gateway_settings = AccountGatewaySettings::createNew();
|
||||||
|
$gateway_settings->gateway_type_id = $gateway_type_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$gateway_settings->min_limit = Input::get('limit_min_enable') ? intval(Input::get('limit_min')) : 0;
|
||||||
|
$gateway_settings->max_limit = Input::get('limit_max_enable') ? intval(Input::get('limit_max')) : 0;
|
||||||
|
|
||||||
|
if ($gateway_settings->max_limit && $gateway_settings->min_limit > $gateway_settings->max_limit) {
|
||||||
|
$gateway_settings->max_limit = $gateway_settings->min_limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$gateway_settings->save();
|
||||||
|
|
||||||
|
event(new UserSettingsChanged());
|
||||||
|
|
||||||
|
Session::flash('message', trans('texts.updated_settings'));
|
||||||
|
|
||||||
|
return Redirect::to('settings/' . ACCOUNT_PAYMENTS);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
|
@ -132,6 +132,7 @@ Route::group(['middleware' => 'auth:user'], function() {
|
|||||||
|
|
||||||
Route::get('settings/user_details', 'AccountController@showUserDetails');
|
Route::get('settings/user_details', 'AccountController@showUserDetails');
|
||||||
Route::post('settings/user_details', 'AccountController@saveUserDetails');
|
Route::post('settings/user_details', 'AccountController@saveUserDetails');
|
||||||
|
Route::post('settings/payment_gateway_limits', 'AccountController@savePaymentGatewayLimits');
|
||||||
Route::post('users/change_password', 'UserController@changePassword');
|
Route::post('users/change_password', 'UserController@changePassword');
|
||||||
|
|
||||||
Route::resource('clients', 'ClientController');
|
Route::resource('clients', 'ClientController');
|
||||||
@ -703,11 +704,11 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('PAYMENT_METHOD_STATUS_VERIFICATION_FAILED', 'verification_failed');
|
define('PAYMENT_METHOD_STATUS_VERIFICATION_FAILED', 'verification_failed');
|
||||||
define('PAYMENT_METHOD_STATUS_VERIFIED', 'verified');
|
define('PAYMENT_METHOD_STATUS_VERIFIED', 'verified');
|
||||||
|
|
||||||
define('GATEWAY_TYPE_CREDIT_CARD', 'credit_card');
|
define('GATEWAY_TYPE_CREDIT_CARD', 1);
|
||||||
define('GATEWAY_TYPE_BANK_TRANSFER', 'bank_transfer');
|
define('GATEWAY_TYPE_BANK_TRANSFER', 2);
|
||||||
define('GATEWAY_TYPE_PAYPAL', 'paypal');
|
define('GATEWAY_TYPE_PAYPAL', 3);
|
||||||
define('GATEWAY_TYPE_BITCOIN', 'bitcoin');
|
define('GATEWAY_TYPE_BITCOIN', 4);
|
||||||
define('GATEWAY_TYPE_DWOLLA', 'dwolla');
|
define('GATEWAY_TYPE_DWOLLA', 5);
|
||||||
define('GATEWAY_TYPE_TOKEN', 'token');
|
define('GATEWAY_TYPE_TOKEN', 'token');
|
||||||
|
|
||||||
define('REMINDER1', 'reminder1');
|
define('REMINDER1', 'reminder1');
|
||||||
@ -851,6 +852,7 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
'invoiceStatus' => 'App\Models\InvoiceStatus',
|
'invoiceStatus' => 'App\Models\InvoiceStatus',
|
||||||
'frequencies' => 'App\Models\Frequency',
|
'frequencies' => 'App\Models\Frequency',
|
||||||
'gateways' => 'App\Models\Gateway',
|
'gateways' => 'App\Models\Gateway',
|
||||||
|
'gatewayTypes' => 'App\Models\GatewayType',
|
||||||
'fonts' => 'App\Models\Font',
|
'fonts' => 'App\Models\Font',
|
||||||
'banks' => 'App\Models\Bank',
|
'banks' => 'App\Models\Bank',
|
||||||
];
|
];
|
||||||
|
62
app/Models/AccountGatewaySettings.php
Normal file
62
app/Models/AccountGatewaySettings.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php namespace App\Models;
|
||||||
|
|
||||||
|
use Auth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class AccountGatewaySettings
|
||||||
|
*/
|
||||||
|
class AccountGatewaySettings extends EntityModel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $dates = ['updated_at'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||||
|
*/
|
||||||
|
public function gatewayType()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('App\Models\GatewayType');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null $context
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function createNew($context = null)
|
||||||
|
{
|
||||||
|
$className = get_called_class();
|
||||||
|
$entity = new $className();
|
||||||
|
|
||||||
|
if ($context) {
|
||||||
|
$user = $context instanceof User ? $context : $context->user;
|
||||||
|
$account = $context->account;
|
||||||
|
} elseif (Auth::check()) {
|
||||||
|
$user = Auth::user();
|
||||||
|
$account = Auth::user()->account;
|
||||||
|
} else {
|
||||||
|
Utils::fatalError();
|
||||||
|
}
|
||||||
|
|
||||||
|
$entity->user_id = $user->id;
|
||||||
|
$entity->account_id = $account->id;
|
||||||
|
|
||||||
|
// store references to the original user/account to prevent needing to reload them
|
||||||
|
$entity->setRelation('user', $user);
|
||||||
|
$entity->setRelation('account', $account);
|
||||||
|
|
||||||
|
if (method_exists($className, 'trashed')){
|
||||||
|
$lastEntity = $className::whereAccountId($entity->account_id)->withTrashed();
|
||||||
|
} else {
|
||||||
|
$lastEntity = $className::whereAccountId($entity->account_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCreatedAtAttribute($value)
|
||||||
|
{
|
||||||
|
// to Disable created_at
|
||||||
|
}
|
||||||
|
}
|
22
app/Models/GatewayType.php
Normal file
22
app/Models/GatewayType.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php namespace App\Models;
|
||||||
|
|
||||||
|
use Eloquent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class GatewayType
|
||||||
|
*/
|
||||||
|
class GatewayType extends Eloquent
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,11 @@
|
|||||||
<?php namespace App\Ninja\Datatables;
|
<?php namespace App\Ninja\Datatables;
|
||||||
|
|
||||||
|
use App\Models\AccountGatewaySettings;
|
||||||
|
use App\Models\GatewayType;
|
||||||
use URL;
|
use URL;
|
||||||
|
use Cache;
|
||||||
|
use Utils;
|
||||||
|
use Session;
|
||||||
use App\Models\AccountGateway;
|
use App\Models\AccountGateway;
|
||||||
|
|
||||||
class AccountGatewayDatatable extends EntityDatatable
|
class AccountGatewayDatatable extends EntityDatatable
|
||||||
@ -45,12 +50,55 @@ class AccountGatewayDatatable extends EntityDatatable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'limit',
|
||||||
|
function ($model) {
|
||||||
|
$accountGateway = AccountGateway::find($model->id);
|
||||||
|
$paymentDriver = $accountGateway->paymentDriver();
|
||||||
|
$gatewayTypes = $paymentDriver->gatewayTypes();
|
||||||
|
$gatewayTypes = array_diff($gatewayTypes, array(GATEWAY_TYPE_TOKEN));
|
||||||
|
|
||||||
|
$html = '';
|
||||||
|
foreach ($gatewayTypes as $gatewayTypeId) {
|
||||||
|
$accountGatewaySettings = AccountGatewaySettings::scope()->where('account_gateway_settings.gateway_type_id',
|
||||||
|
'=', $gatewayTypeId)->first();
|
||||||
|
$gatewayType = GatewayType::find($gatewayTypeId);
|
||||||
|
|
||||||
|
if (count($gatewayTypes) > 1) {
|
||||||
|
if ($html) {
|
||||||
|
$html .= '<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= $gatewayType->name . ' — ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decide how many nines to add to the end of the max.
|
||||||
|
$currency = Utils::getFromCache(Session::get(SESSION_CURRENCY, DEFAULT_CURRENCY), 'currencies');
|
||||||
|
$limit_max_adjustment = $currency->precision ? floatval('.' . str_repeat('9',
|
||||||
|
$currency->precision)) : 0;
|
||||||
|
|
||||||
|
if ($accountGatewaySettings && $accountGatewaySettings->min_limit && $accountGatewaySettings->max_limit) {
|
||||||
|
$html .= Utils::formatMoney($accountGatewaySettings->min_limit) . ' - ' . Utils::formatMoney($accountGatewaySettings->max_limit + $limit_max_adjustment);
|
||||||
|
} elseif ($accountGatewaySettings && $accountGatewaySettings->min_limit) {
|
||||||
|
$html .= trans('texts.min_limit',
|
||||||
|
array('min' => Utils::formatMoney($accountGatewaySettings->min_limit)));
|
||||||
|
} elseif ($accountGatewaySettings && $accountGatewaySettings->max_limit) {
|
||||||
|
$html .= trans('texts.max_limit',
|
||||||
|
array('max' => Utils::formatMoney($accountGatewaySettings->max_limit + $limit_max_adjustment)));
|
||||||
|
} else {
|
||||||
|
$html .= trans('texts.no_limit');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function actions()
|
public function actions()
|
||||||
{
|
{
|
||||||
return [
|
$actions = [
|
||||||
[
|
[
|
||||||
uctrans('texts.resend_confirmation_email'),
|
uctrans('texts.resend_confirmation_email'),
|
||||||
function ($model) {
|
function ($model) {
|
||||||
@ -98,6 +146,30 @@ class AccountGatewayDatatable extends EntityDatatable
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
foreach (Cache::get('gatewayTypes') as $gatewayType) {
|
||||||
|
$actions[] = [
|
||||||
|
trans('texts.set_limits', ['gateway_type' => $gatewayType->name]),
|
||||||
|
function () use ($gatewayType) {
|
||||||
|
$accountGatewaySettings = AccountGatewaySettings::scope()->where('account_gateway_settings.gateway_type_id',
|
||||||
|
'=', $gatewayType->id)->first();
|
||||||
|
$min = $accountGatewaySettings ? $accountGatewaySettings->min_limit : 0;
|
||||||
|
$max = $accountGatewaySettings ? $accountGatewaySettings->max_limit : 0;
|
||||||
|
|
||||||
|
return "javascript:showLimitsModal('{$gatewayType->name}',{$gatewayType->id},$min,$max)";
|
||||||
|
},
|
||||||
|
function ($model) use ($gatewayType) {
|
||||||
|
// Only show this action if the given gateway supports this gateway type
|
||||||
|
$accountGateway = AccountGateway::find($model->id);
|
||||||
|
$paymentDriver = $accountGateway->paymentDriver();
|
||||||
|
$gatewayTypes = $paymentDriver->gatewayTypes();
|
||||||
|
|
||||||
|
return in_array($gatewayType->id, $gatewayTypes);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,8 @@
|
|||||||
"stacktrace-js": "~1.0.1",
|
"stacktrace-js": "~1.0.1",
|
||||||
"fuse.js": "~2.0.2",
|
"fuse.js": "~2.0.2",
|
||||||
"dropzone": "~4.3.0",
|
"dropzone": "~4.3.0",
|
||||||
"sweetalert": "~1.1.3"
|
"sweetalert": "~1.1.3",
|
||||||
|
"nouislider": "~8.5.1"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"jquery": "~1.11"
|
"jquery": "~1.11"
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class CreateGatewayTypes extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('gateway_types');
|
||||||
|
Schema::create('gateway_types', function($t)
|
||||||
|
{
|
||||||
|
$t->increments('id');
|
||||||
|
$t->string('name');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::dropIfExists('account_gateway_settings');
|
||||||
|
Schema::create('account_gateway_settings', function($t)
|
||||||
|
{
|
||||||
|
$t->increments('id');
|
||||||
|
|
||||||
|
$t->unsignedInteger('account_id');
|
||||||
|
$t->unsignedInteger('user_id');
|
||||||
|
$t->unsignedInteger('gateway_type_id')->nullable();
|
||||||
|
|
||||||
|
$t->timestamp('updated_at')->nullable();
|
||||||
|
|
||||||
|
|
||||||
|
$t->unsignedInteger('min_limit');
|
||||||
|
$t->unsignedInteger('max_limit');
|
||||||
|
|
||||||
|
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||||
|
$t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
$t->foreign('gateway_type_id')->references('id')->on('gateway_types')->onDelete('cascade');
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('account_gateway_settings');
|
||||||
|
Schema::dropIfExists('gateway_types');
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,7 @@ class DatabaseSeeder extends Seeder
|
|||||||
$this->call('InvoiceDesignsSeeder');
|
$this->call('InvoiceDesignsSeeder');
|
||||||
$this->call('PaymentTermsSeeder');
|
$this->call('PaymentTermsSeeder');
|
||||||
$this->call('PaymentTypesSeeder');
|
$this->call('PaymentTypesSeeder');
|
||||||
|
$this->call('GatewayTypesSeeder');
|
||||||
$this->call('LanguageSeeder');
|
$this->call('LanguageSeeder');
|
||||||
$this->call('IndustrySeeder');
|
$this->call('IndustrySeeder');
|
||||||
}
|
}
|
||||||
|
28
database/seeds/GatewayTypesSeeder.php
Normal file
28
database/seeds/GatewayTypesSeeder.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\GatewayType;
|
||||||
|
|
||||||
|
class GatewayTypesSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
Eloquent::unguard();
|
||||||
|
|
||||||
|
|
||||||
|
$gateway_types = [
|
||||||
|
['name' => 'Credit Card'],
|
||||||
|
['name' => 'Bank Transfer'],
|
||||||
|
['name' => 'PayPal'],
|
||||||
|
['name' => 'Bitcoin'],
|
||||||
|
['name' => 'Dwolla'],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($gateway_types as $gateway_type) {
|
||||||
|
$record = GatewayType::where('name', '=', $gateway_type['name'])->first();
|
||||||
|
if (!$record) {
|
||||||
|
GatewayType::create($gateway_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,7 @@ class UpdateSeeder extends Seeder
|
|||||||
$this->call('InvoiceDesignsSeeder');
|
$this->call('InvoiceDesignsSeeder');
|
||||||
$this->call('PaymentTermsSeeder');
|
$this->call('PaymentTermsSeeder');
|
||||||
$this->call('PaymentTypesSeeder');
|
$this->call('PaymentTypesSeeder');
|
||||||
|
$this->call('GatewayTypesSeeder');
|
||||||
$this->call('LanguageSeeder');
|
$this->call('LanguageSeeder');
|
||||||
$this->call('IndustrySeeder');
|
$this->call('IndustrySeeder');
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,7 @@ elixir(function(mix) {
|
|||||||
//bowerDir + '/stacktrace-js/dist/stacktrace-with-polyfills.min.js',
|
//bowerDir + '/stacktrace-js/dist/stacktrace-with-polyfills.min.js',
|
||||||
bowerDir + '/fuse.js/src/fuse.js',
|
bowerDir + '/fuse.js/src/fuse.js',
|
||||||
bowerDir + '/sweetalert/dist/sweetalert-dev.js',
|
bowerDir + '/sweetalert/dist/sweetalert-dev.js',
|
||||||
|
bowerDir + '/nouislider/distribute/nouislider.js',
|
||||||
'bootstrap-combobox.js',
|
'bootstrap-combobox.js',
|
||||||
'script.js',
|
'script.js',
|
||||||
'pdf.pdfmake.js',
|
'pdf.pdfmake.js',
|
||||||
|
65703
public/built.js
65703
public/built.js
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
13481
public/css/built.css
vendored
13481
public/css/built.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
9549
public/css/built.public.css
vendored
9549
public/css/built.public.css
vendored
File diff suppressed because one or more lines are too long
1428
public/js/Chart.min.js
vendored
1428
public/js/Chart.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
9559
public/js/d3.min.js
vendored
9559
public/js/d3.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
74412
public/pdf.built.js
74412
public/pdf.built.js
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
141
resources/assets/css/style.css
vendored
141
resources/assets/css/style.css
vendored
@ -1091,3 +1091,144 @@ div.panel-body div.panel-body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Limits */
|
||||||
|
.noUi-target,
|
||||||
|
.noUi-target * {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-ms-touch-action: none;
|
||||||
|
touch-action: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.noUi-target {
|
||||||
|
position: relative;
|
||||||
|
direction: ltr;
|
||||||
|
margin:0 17px;
|
||||||
|
}
|
||||||
|
.noUi-base {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1; /* Fix 401 */
|
||||||
|
}
|
||||||
|
.noUi-origin {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.noUi-handle {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.noUi-stacking .noUi-handle {
|
||||||
|
/* This class is applied to the lower origin when
|
||||||
|
its values is > 50%. */
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
.noUi-state-tap .noUi-origin {
|
||||||
|
-webkit-transition: left 0.3s, top 0.3s;
|
||||||
|
transition: left 0.3s, top 0.3s;
|
||||||
|
}
|
||||||
|
.noUi-state-drag * {
|
||||||
|
cursor: inherit !important;
|
||||||
|
}
|
||||||
|
.noUi-base,
|
||||||
|
.noUi-handle {
|
||||||
|
-webkit-transform: translate3d(0,0,0);
|
||||||
|
transform: translate3d(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.noUi-horizontal {
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
.noUi-horizontal .noUi-handle {
|
||||||
|
width: 34px;
|
||||||
|
height: 25px;
|
||||||
|
left: -17px;
|
||||||
|
top: -6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noUi-background {
|
||||||
|
background: #f9f9f9;
|
||||||
|
}
|
||||||
|
.noUi-connect {
|
||||||
|
background: #286090;
|
||||||
|
}
|
||||||
|
.noUi-origin {
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.noUi-target {
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noUi-draggable {
|
||||||
|
cursor: w-resize;
|
||||||
|
}
|
||||||
|
.noUi-vertical .noUi-draggable {
|
||||||
|
cursor: n-resize;
|
||||||
|
}
|
||||||
|
.noUi-handle {
|
||||||
|
border: 1px solid #777;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: #FFF;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noUi-handle:before,
|
||||||
|
.noUi-handle:after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
height: 13px;
|
||||||
|
width: 1px;
|
||||||
|
background: #777;
|
||||||
|
left: 14px;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
.noUi-handle:after {
|
||||||
|
left: 17px;
|
||||||
|
}
|
||||||
|
.noUi-vertical .noUi-handle:before,
|
||||||
|
.noUi-vertical .noUi-handle:after {
|
||||||
|
width: 14px;
|
||||||
|
height: 1px;
|
||||||
|
left: 6px;
|
||||||
|
top: 14px;
|
||||||
|
}
|
||||||
|
.noUi-vertical .noUi-handle:after {
|
||||||
|
top: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#payment-limits-slider{
|
||||||
|
margin-bottom:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#payment-limit-min-container .input-group,
|
||||||
|
#payment-limit-max-container .input-group{
|
||||||
|
max-width:200px;
|
||||||
|
clear:both;
|
||||||
|
}
|
||||||
|
|
||||||
|
#payment-limit-max-container{
|
||||||
|
text-align:right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#payment-limit-max-container .input-group,
|
||||||
|
#payment-limit-max-container label{
|
||||||
|
float:right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#payment-limit-min[disabled],
|
||||||
|
#payment-limit-max[disabled]{
|
||||||
|
background-color: #eee!important;
|
||||||
|
color: #999!important;
|
||||||
|
}
|
@ -2095,6 +2095,17 @@ $LANG = array(
|
|||||||
'city_state_postal' => 'City/State/Postal',
|
'city_state_postal' => 'City/State/Postal',
|
||||||
'custom_field' => 'Custom Field',
|
'custom_field' => 'Custom Field',
|
||||||
|
|
||||||
|
// Limits
|
||||||
|
'limit' => 'Limit',
|
||||||
|
'min_limit' => 'Min: :min',
|
||||||
|
'max_limit' => 'Max: :max',
|
||||||
|
'no_limit' => 'No Limits',
|
||||||
|
'set_limits' => 'Set :gateway_type Limits',
|
||||||
|
'enable_min' => 'Enable min',
|
||||||
|
'enable_max' => 'Enable max',
|
||||||
|
'min' => 'Min',
|
||||||
|
'max' => 'Max',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return $LANG;
|
return $LANG;
|
||||||
|
@ -50,15 +50,79 @@
|
|||||||
{!! Datatable::table()
|
{!! Datatable::table()
|
||||||
->addColumn(
|
->addColumn(
|
||||||
trans('texts.name'),
|
trans('texts.name'),
|
||||||
|
trans('texts.limit'),
|
||||||
trans('texts.action'))
|
trans('texts.action'))
|
||||||
->setUrl(url('api/gateways/'))
|
->setUrl(url('api/gateways/'))
|
||||||
->setOptions('sPaginationType', 'bootstrap')
|
->setOptions('sPaginationType', 'bootstrap')
|
||||||
->setOptions('bFilter', false)
|
->setOptions('bFilter', false)
|
||||||
->setOptions('bAutoWidth', false)
|
->setOptions('bAutoWidth', false)
|
||||||
->setOptions('aoColumns', [[ "sWidth"=> "80%" ], ["sWidth"=> "20%"]])
|
->setOptions('aoColumns', [[ "sWidth"=> "50%" ], ["sWidth"=> "30%"], ["sWidth"=> "20%"]])
|
||||||
->setOptions('aoColumnDefs', [['bSortable'=>false, 'aTargets'=>[1]]])
|
->setOptions('aoColumnDefs', [['bSortable'=>false, 'aTargets'=>[1]]])
|
||||||
->render('datatable') !!}
|
->render('datatable') !!}
|
||||||
|
|
||||||
|
{!! Former::open( 'settings/payment_gateway_limits') !!}
|
||||||
|
<div class="modal fade" id="paymentLimitsModal" tabindex="-1" role="dialog"
|
||||||
|
aria-labelledby="paymentLimitsModalLabel"
|
||||||
|
aria-hidden="true">
|
||||||
|
<div class="modal-dialog" style="min-width:150px">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title" id="paymentLimitsModalLabel"></h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row" style="text-align:center">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<div id="payment-limits-slider"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div id="payment-limit-min-container">
|
||||||
|
<label for="payment-limit-min">{{ trans('texts.min') }}</label><br>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon">{{ $currency->symbol }}</span>
|
||||||
|
<input type="number" class="form-control" min="0" id="payment-limit-min"
|
||||||
|
name="limit_min">
|
||||||
|
@if ($currency->precision)
|
||||||
|
<span class="input-group-addon">{{ $currency->decimal_separator }}{{ str_repeat( '0', $currency->precision) }}</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<label><input type="checkbox" id="payment-limit-min-enable"
|
||||||
|
name="limit_min_enable"> {{ trans('texts.enable_min') }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div id="payment-limit-max-container">
|
||||||
|
<label for="payment-limit-max">{{ trans('texts.max') }}</label><br>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon">{{ $currency->symbol }}</span>
|
||||||
|
<input type="number" class="form-control" min="0" id="payment-limit-max"
|
||||||
|
name="limit_max">
|
||||||
|
@if ($currency->precision)
|
||||||
|
<span class="input-group-addon">{{ $currency->decimal_separator }}{{ str_repeat( '9', $currency->precision) }}</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<label><input type="checkbox" id="payment-limit-max-enable"
|
||||||
|
name="limit_max_enable"> {{ trans('texts.enable_max') }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="gateway_type_id" id="payment-limit-gateway-type">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer" style="margin-top: 0px">
|
||||||
|
<button type="button" class="btn btn-default"
|
||||||
|
data-dismiss="modal">{{ trans('texts.cancel') }}</button>
|
||||||
|
<button type="submit" class="btn btn-primary">{{ trans('texts.save') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{!! Former::close() !!}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
window.onDatatableReady = actionListHandler;
|
window.onDatatableReady = actionListHandler;
|
||||||
function setTrashVisible() {
|
function setTrashVisible() {
|
||||||
@ -69,6 +133,89 @@
|
|||||||
refreshDatatable();
|
refreshDatatable();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showLimitsModal(gateway_type, gateway_type_id, min_limit, max_limit) {
|
||||||
|
var modalLabel = {!! json_encode(trans('texts.set_limits')) !!};
|
||||||
|
$('#paymentLimitsModalLabel').text(modalLabel.replace(':gateway_type', gateway_type));
|
||||||
|
|
||||||
|
limitsSlider.noUiSlider.set([min_limit, max_limit ? max_limit : 100000]);
|
||||||
|
|
||||||
|
if (min_limit) {
|
||||||
|
$('#payment-limit-min').removeAttr('disabled');
|
||||||
|
$('#payment-limit-min-enable').prop('checked', true);
|
||||||
|
} else {
|
||||||
|
$('#payment-limit-min').attr('disabled', 'disabled');
|
||||||
|
$('#payment-limit-min-enable').prop('checked', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_limit) {
|
||||||
|
$('#payment-limit-max').removeAttr('disabled');
|
||||||
|
$('#payment-limit-max-enable').prop('checked', true);
|
||||||
|
} else {
|
||||||
|
$('#payment-limit-max').attr('disabled', 'disabled');
|
||||||
|
$('#payment-limit-max-enable').prop('checked', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#payment-limit-gateway-type').val(gateway_type_id);
|
||||||
|
|
||||||
|
$('#paymentLimitsModal').modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
var limitsSlider = document.getElementById('payment-limits-slider');
|
||||||
|
noUiSlider.create(limitsSlider, {
|
||||||
|
start: [0, 100000],
|
||||||
|
connect: true,
|
||||||
|
range: {
|
||||||
|
'min': [0, 1],
|
||||||
|
'30%': [500, 1],
|
||||||
|
'70%': [5000, 1],
|
||||||
|
'max': [100000, 1]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
limitsSlider.noUiSlider.on('update', function (values, handle) {
|
||||||
|
var value = values[handle];
|
||||||
|
if (handle == 1) {
|
||||||
|
$('#payment-limit-max').val(Math.round(value)).removeAttr('disabled');
|
||||||
|
$('#payment-limit-max-enable').prop('checked', true);
|
||||||
|
} else {
|
||||||
|
$('#payment-limit-min').val(Math.round(value)).removeAttr('disabled');
|
||||||
|
$('#payment-limit-min-enable').prop('checked', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#payment-limit-min').on('change keyup', function () {
|
||||||
|
setTimeout(function () {
|
||||||
|
limitsSlider.noUiSlider.set([$('#payment-limit-min').val(), null]);
|
||||||
|
}, 100);
|
||||||
|
$('#payment-limit-min-enable').attr('checked', 'checked');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#payment-limit-max').on('change keyup', function () {
|
||||||
|
setTimeout(function () {
|
||||||
|
limitsSlider.noUiSlider.set([null, $('#payment-limit-max').val()]);
|
||||||
|
}, 100);
|
||||||
|
$('#payment-limit-max-enable').attr('checked', 'checked');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#payment-limit-min-enable').change(function () {
|
||||||
|
if ($(this).is(':checked')) {
|
||||||
|
$('#payment-limit-min').removeAttr('disabled');
|
||||||
|
} else {
|
||||||
|
$('#payment-limit-min').attr('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#payment-limit-max-enable').change(function () {
|
||||||
|
if ($(this).is(':checked')) {
|
||||||
|
$('#payment-limit-max').removeAttr('disabled');
|
||||||
|
} else {
|
||||||
|
$('#payment-limit-max').attr('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@stop
|
@stop
|
||||||
|
Loading…
x
Reference in New Issue
Block a user