mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
Prevent duplicate form submissions
This commit is contained in:
parent
746d5ec773
commit
b79d5210fa
@ -119,6 +119,6 @@ return array(
|
||||
|
|
||||
*/
|
||||
|
||||
'pretend' => false,
|
||||
'pretend' => true,
|
||||
|
||||
);
|
@ -92,8 +92,11 @@ class ClientController extends \BaseController {
|
||||
$contact->phone = Input::get('phone');
|
||||
$client->contacts()->save($contact);
|
||||
|
||||
$url = 'clients/' . $client->id;
|
||||
processedRequest($url);
|
||||
|
||||
Session::flash('message', 'Successfully created client');
|
||||
return Redirect::to('clients/' . $client->id);
|
||||
return Redirect::to($url);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,9 +144,23 @@ class ClientController extends \BaseController {
|
||||
->withInput(Input::except('password'));
|
||||
} else {
|
||||
$client = Client::find($id);
|
||||
$client->name = Input::get('name');
|
||||
$client->name = Input::get('name');
|
||||
$client->work_phone = Input::get('work_phone');
|
||||
$client->address1 = Input::get('address1');
|
||||
$client->address2 = Input::get('address2');
|
||||
$client->city = Input::get('city');
|
||||
$client->state = Input::get('state');
|
||||
$client->notes = Input::get('notes');
|
||||
$client->postal_code = Input::get('postal_code');
|
||||
$client->save();
|
||||
|
||||
$contact = $client->contacts[0];
|
||||
$contact->email = Input::get('email');
|
||||
$contact->first_name = Input::get('first_name');
|
||||
$contact->last_name = Input::get('last_name');
|
||||
$contact->phone = Input::get('phone');
|
||||
$contact->save();
|
||||
|
||||
Session::flash('message', 'Successfully updated client');
|
||||
return Redirect::to('clients');
|
||||
}
|
||||
|
@ -37,14 +37,14 @@ class InvoiceController extends \BaseController {
|
||||
}
|
||||
|
||||
|
||||
public function view($invoiceKey)
|
||||
public function view($key)
|
||||
{
|
||||
$invoice = Invoice::with('invoice_items', 'client.account.account_gateways')->where('invoice_key', '=', $invoiceKey)->firstOrFail();
|
||||
$invitation = Invitation::with('invoice.invoice_items', 'invoice.client.account.account_gateways')->where('key', '=', $key)->firstOrFail();
|
||||
$contact = null;
|
||||
|
||||
Activity::viewInvoice($invoice, $contact);
|
||||
Activity::viewInvoice($invitation);
|
||||
|
||||
return View::make('invoices.view')->with('invoice', $invoice);
|
||||
return View::make('invoices.view')->with('invoice', $invitation->invoice);
|
||||
}
|
||||
|
||||
private function createGateway($accountGateway)
|
||||
@ -91,7 +91,7 @@ class InvoiceController extends \BaseController {
|
||||
|
||||
public function show_payment($invoiceKey)
|
||||
{
|
||||
$invoice = Invoice::with('invoice_items', 'client.account.account_gateways.gateway')->where('invoice_key', '=', $invoiceKey)->firstOrFail();
|
||||
$invoice = Invoice::with('invoice_items', 'client.account.account_gateways.gateway')->where('key', '=', $invoiceKey)->firstOrFail();
|
||||
$accountGateway = $invoice->client->account->account_gateways[0];
|
||||
$gateway = InvoiceController::createGateway($accountGateway);
|
||||
|
||||
@ -159,7 +159,7 @@ class InvoiceController extends \BaseController {
|
||||
$payment->save();
|
||||
|
||||
Session::flash('message', 'Successfully applied payment');
|
||||
return Redirect::to('view/' . $payment->invoice->invoice_key);
|
||||
return Redirect::to('view/' . $payment->invoice->key);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -247,16 +247,14 @@ class InvoiceController extends \BaseController {
|
||||
$invoice->invoice_items()->forceDelete();
|
||||
} else {
|
||||
$invoice = new Invoice;
|
||||
$invoice->invoice_key = str_random(20);
|
||||
$invoice->account_id = Auth::user()->account_id;
|
||||
}
|
||||
|
||||
$date = DateTime::createFromFormat('m/d/Y', Input::get('invoice_date'));
|
||||
|
||||
$invoice->client_id = $clientId;
|
||||
$invoice->invoice_number = Input::get('invoice_number');
|
||||
$invoice->discount = 0;
|
||||
$invoice->invoice_date = $date->format('Y-m-d');
|
||||
$invoice->invoice_date = toSqlDate(Input::get('invoice_date'));
|
||||
$invoice->due_date = toSqlDate(Input::get('due_date'));
|
||||
$invoice->save();
|
||||
|
||||
$items = json_decode(Input::get('items'));
|
||||
@ -277,7 +275,7 @@ class InvoiceController extends \BaseController {
|
||||
{
|
||||
$product = new Product;
|
||||
$product->account_id = Auth::user()->account_id;
|
||||
$product->product_key = $item->product_key;
|
||||
$product->key = $item->product_key;
|
||||
}
|
||||
|
||||
$product->notes = $item->notes;
|
||||
@ -298,20 +296,30 @@ class InvoiceController extends \BaseController {
|
||||
if (Input::get('send_email_checkBox'))
|
||||
{
|
||||
$data = array('link' => URL::to('view') . '/' . $invoice->invoice_key);
|
||||
/*
|
||||
Mail::send(array('html'=>'emails.invoice_html','text'=>'emails.invoice_text'), $data, function($message) use ($contact)
|
||||
{
|
||||
$message->from('hillelcoren@gmail.com', 'Hillel Coren');
|
||||
$message->to($contact->email);
|
||||
});
|
||||
*/
|
||||
|
||||
$invitation = new Invitation;
|
||||
$invitation->invoice_id = $invoice->id;
|
||||
$invitation->user_id = Auth::user()->id;
|
||||
$invitation->contact_id = $contact->id;
|
||||
$invitation->key = str_random(20);
|
||||
$invitation->save();
|
||||
|
||||
Activity::emailInvoice($invoice, $contact);
|
||||
|
||||
Session::flash('message', 'Successfully emailed invoice');
|
||||
} else {
|
||||
Session::flash('message', 'Successfully saved invoice');
|
||||
}
|
||||
|
||||
return Redirect::to('invoices/' . $invoice->id . '/edit');
|
||||
$url = 'invoices/' . $invoice->id . '/edit';
|
||||
processedRequest($url);
|
||||
return Redirect::to($url);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::dropIfExists('invitations');
|
||||
Schema::dropIfExists('activities');
|
||||
Schema::dropIfExists('account_gateways');
|
||||
Schema::dropIfExists('gateways');
|
||||
@ -138,14 +139,26 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
|
||||
$t->string('invoice_key')->unique();
|
||||
$t->string('invoice_number');
|
||||
$t->float('discount');
|
||||
$t->date('invoice_date');
|
||||
$t->date('due_date');
|
||||
|
||||
//$t->foreign('account_id')->references('id')->on('accounts');
|
||||
});
|
||||
|
||||
|
||||
Schema::create('invitations', function($t)
|
||||
{
|
||||
$t->increments('id');
|
||||
$t->integer('user_id');
|
||||
$t->integer('contact_id');
|
||||
$t->integer('invoice_id');
|
||||
$t->string('key')->unique();
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
});
|
||||
|
||||
Schema::create('invoice_items', function($t)
|
||||
{
|
||||
$t->increments('id');
|
||||
@ -169,7 +182,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
|
||||
$t->string('product_key');
|
||||
$t->string('key');
|
||||
$t->string('notes');
|
||||
$t->decimal('cost', 8, 2);
|
||||
$t->integer('qty');
|
||||
@ -203,6 +216,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->integer('contact_id');
|
||||
$t->integer('invoice_id');
|
||||
$t->integer('payment_id');
|
||||
$t->integer('invitation_id');
|
||||
$t->timestamps();
|
||||
|
||||
$t->integer('activity_type_id');
|
||||
@ -217,6 +231,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('invitations');
|
||||
Schema::dropIfExists('activities');
|
||||
Schema::dropIfExists('account_gateways');
|
||||
Schema::dropIfExists('gateways');
|
||||
|
@ -73,7 +73,19 @@ Route::filter('guest', function()
|
||||
|
||||
Route::filter('csrf', function()
|
||||
{
|
||||
if (Session::token() != Input::get('_token'))
|
||||
if (!Input::get('_token'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$tokenInput = Input::get('_token');
|
||||
$tokenSession = Session::token();
|
||||
|
||||
if ($url = Session::get($tokenInput))
|
||||
{
|
||||
return Redirect::to($url);
|
||||
}
|
||||
else if ($tokenSession != $tokenInput)
|
||||
{
|
||||
throw new Illuminate\Session\TokenMismatchException;
|
||||
}
|
||||
|
@ -59,13 +59,13 @@ class Activity extends Eloquent
|
||||
$activity->save();
|
||||
}
|
||||
|
||||
public static function emailInvoice($invoice, $contact)
|
||||
public static function emailInvoice($invitation)
|
||||
{
|
||||
$activity = Activity::getBlank();
|
||||
$activity->invoice_id = $invoice->id;
|
||||
$activity->client_id = $invoice->client_id;
|
||||
$activity->invoice_id = $invitation->invoice_id;
|
||||
$activity->contact_id = $invitation->contact_id;
|
||||
$activity->activity_type_id = ACTIVITY_TYPE_EMAIL_INVOICE;
|
||||
$activity->message = Auth::user()->getFullName() . ' emailed invoice ' . $invoice->number . ' to ' . $contact->getFullName();
|
||||
//$activity->message = Auth::user()->getFullName() . ' emailed invoice ' . $invitation->invoice->number . ' to ' . $contact->getFullName();
|
||||
$activity->save();
|
||||
}
|
||||
|
||||
@ -100,12 +100,12 @@ class Activity extends Eloquent
|
||||
$activity->save();
|
||||
}
|
||||
|
||||
public static function viewInvoice($invoice, $contact)
|
||||
public static function viewInvoice($invitation)
|
||||
{
|
||||
$activity = new Activity;
|
||||
//$activity->contact_id = $contact->id;
|
||||
$activity->invoice_id = $invoice->id;
|
||||
$activity->client_id = $invoice->client_id;
|
||||
$activity->invitation_id = $invitation->invitation_id;
|
||||
$activity->contact_id = $invitation->contact_id;
|
||||
$activity->invoice_id = $invitation->invoice_id;
|
||||
$activity->activity_type_id = ACTIVITY_TYPE_VIEW_INVOICE;
|
||||
//$activity->message = $contact->getFullName() . ' viewed invoice ' . $invoice->number;
|
||||
$activity->save();
|
||||
|
16
app/models/Invitation.php
Normal file
16
app/models/Invitation.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
class Invitation extends Eloquent
|
||||
{
|
||||
protected $softDelete = true;
|
||||
|
||||
public function invoice()
|
||||
{
|
||||
return $this->belongsTo('Invoice');
|
||||
}
|
||||
}
|
||||
|
||||
Invitation::created(function($invitation)
|
||||
{
|
||||
Activity::emailInvoice($invitation);
|
||||
});
|
@ -11,12 +11,12 @@ class Product extends Eloquent
|
||||
|
||||
public static function findProduct($key)
|
||||
{
|
||||
return Product::getProducts()->where('product_key','=',$key)->first();
|
||||
return Product::getProducts()->where('key','=',$key)->first();
|
||||
}
|
||||
|
||||
public static function getProductKeys($products)
|
||||
{
|
||||
$products = array_pluck($products, 'product_key');
|
||||
$products = array_pluck($products, 'key');
|
||||
$products = array_combine($products, $products);
|
||||
|
||||
return $products;
|
||||
|
@ -24,13 +24,13 @@ Route::get('complete', 'InvoiceController@do_payment');
|
||||
|
||||
Route::filter('auth', function()
|
||||
{
|
||||
if (!Auth::check())
|
||||
if (!Auth::check())
|
||||
{
|
||||
return Redirect::to('/');
|
||||
}
|
||||
});
|
||||
|
||||
Route::group(array('before' => 'auth'), function()
|
||||
Route::group(array('before' => array('auth', 'csrf')), function()
|
||||
{
|
||||
Route::get('account/{section?}', 'AccountController@showSection');
|
||||
Route::post('account/{section?}', 'AccountController@doSection');
|
||||
@ -39,7 +39,7 @@ Route::group(array('before' => 'auth'), function()
|
||||
Route::get('api/clients', array('as'=>'api.clients', 'uses'=>'ClientController@getDatatable'));
|
||||
|
||||
Route::resource('invoices', 'InvoiceController');
|
||||
Route::get('api/invoices', array('as'=>'api.invoices', 'uses'=>'InvoiceController@getDatatable'));
|
||||
Route::get('api/invoices', array('as'=>'api.invoices', 'uses'=>'InvoiceController@getDatatable'));
|
||||
Route::get('invoices/create/{client_id}', 'InvoiceController@create');
|
||||
|
||||
Route::get('payments', 'PaymentController@index');
|
||||
@ -105,6 +105,32 @@ function toSpaceCase($camelStr)
|
||||
return preg_replace('/([a-z])([A-Z])/s','$1 $2', $camelStr);
|
||||
}
|
||||
|
||||
function toSqlDate($date)
|
||||
{
|
||||
if (!$date)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
return DateTime::createFromFormat('m/d/Y', $date);
|
||||
}
|
||||
|
||||
function fromSqlDate($date)
|
||||
{
|
||||
if (!$date || $date == '0000-00-00')
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
return DateTime::createFromFormat('Y-m-d', $date)->format('m/d/Y');
|
||||
}
|
||||
|
||||
function processedRequest($url)
|
||||
{
|
||||
Session::put(Input::get('_token'), $url);
|
||||
Session::put('_token', md5(microtime()));
|
||||
}
|
||||
|
||||
define("ENV_DEVELOPMENT", "local");
|
||||
define("ENV_STAGING", "staging");
|
||||
define("ENV_PRODUCTION", "production");
|
||||
|
@ -14,7 +14,7 @@
|
||||
{{ Former::populate($client); }}
|
||||
@endif
|
||||
|
||||
{{ Former::open($url)->addClass('col-md-9 col-md-offset-1')->method($method)->rules(array(
|
||||
{{ Former::open($url)->addClass('col-md-9 col-md-offset-1 main_form')->method($method)->rules(array(
|
||||
'name' => 'required',
|
||||
'email' => 'email'
|
||||
)); }}
|
||||
@ -38,7 +38,7 @@
|
||||
{{ Former::text('state') }}
|
||||
{{ Former::text('postal_code') }}
|
||||
|
||||
{{ Former::actions()->lg_primary_submit('Save') }}
|
||||
{{ Former::actions( Button::lg_primary_submit('Save') ) }}
|
||||
{{ Former::close() }}
|
||||
|
||||
@stop
|
@ -13,7 +13,8 @@
|
||||
|
||||
@if ($invoice)
|
||||
{{ Former::populate($invoice); }}
|
||||
{{ Former::populateField('invoice_date', DateTime::createFromFormat('Y-m-d', $invoice->invoice_date)->format('m/d/Y')); }}
|
||||
{{ Former::populateField('invoice_date', fromSqlDate($invoice->invoice_date)); }}
|
||||
{{ Former::populateField('due_date', fromSqlDate($invoice->due_date)); }}
|
||||
@else
|
||||
{{ Former::populateField('invoice_date', date('m/d/Y')) }}
|
||||
@endif
|
||||
@ -26,6 +27,7 @@
|
||||
<div class="col-md-5">
|
||||
{{ Former::text('invoice_number')->label('Invoice #') }}
|
||||
{{ Former::text('invoice_date') }}
|
||||
{{ Former::text('due_date') }}
|
||||
{{-- Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") --}}
|
||||
</div>
|
||||
</div>
|
||||
@ -53,7 +55,7 @@
|
||||
<i data-bind="visible: actionsVisible" class="fa fa-sort"></i>
|
||||
</td>
|
||||
<td style="width:120px">
|
||||
{{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'product_key')
|
||||
{{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'key')
|
||||
->raw()->data_bind("value: product_key, valueUpdate: 'afterkeydown'")->addClass('datalist') }}
|
||||
</td>
|
||||
<td style="width:300px">
|
||||
@ -106,7 +108,7 @@
|
||||
<p> </p>
|
||||
<div class="form-actions">
|
||||
{{ Button::primary('Download PDF', array('onclick' => 'onDownloadClick()')) }}
|
||||
{{ Button::primary_submit('Save Invoice') }}
|
||||
{{ Button::primary_submit('Save Invoice', array('onclick' => 'onSaveClick()')) }}
|
||||
{{ Button::primary('Send Email', array('onclick' => 'onEmailClick()')) }}
|
||||
</div>
|
||||
<p> </p>
|
||||
@ -174,6 +176,11 @@
|
||||
refreshPDF();
|
||||
});
|
||||
|
||||
$('#due_date').datepicker({
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
});
|
||||
|
||||
var $input = $('select#client');
|
||||
$input.combobox();
|
||||
$('.combobox-container input.form-control').attr('name', 'client_combobox').on('change', function(e) {
|
||||
@ -212,7 +219,7 @@
|
||||
var key = $(this).val();
|
||||
for (var i=0; i<products.length; i++) {
|
||||
var product = products[i];
|
||||
if (product.product_key == key) {
|
||||
if (product.key == key) {
|
||||
var model = ko.dataFor(this);
|
||||
console.log(model);
|
||||
model.notes(product.notes);
|
||||
@ -277,6 +284,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
function onSaveClick() {
|
||||
$('.main_form').submit();
|
||||
}
|
||||
|
||||
function newClient() {
|
||||
var name = $('#client_name').val();
|
||||
var email = $('#client_email').val();
|
||||
|
Loading…
x
Reference in New Issue
Block a user