mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-18 00:53:10 +01:00
Bug fixes
This commit is contained in:
parent
d97c805d46
commit
f946791780
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
/app/config/staging
|
||||
/app/config/development
|
||||
/app/storage/
|
||||
/public/logo
|
||||
/bootstrap/compiled.php
|
||||
/vendor
|
||||
|
@ -7,7 +7,7 @@ class ActivityController extends \BaseController {
|
||||
$clientId = Client::getPrivateId($clientPublicId);
|
||||
|
||||
return Datatable::collection(Activity::scope()->where('client_id','=',$clientId)->get())
|
||||
->addColumn('date', function($model) { return Utils::timestampToDateString($model->created_at); })
|
||||
->addColumn('date', function($model) { return Utils::timestampToDateTimeString($model->created_at); })
|
||||
->addColumn('message', function($model) { return $model->message; })
|
||||
->addColumn('balance', function($model) { return '$' . $model->balance; })
|
||||
->orderColumns('date')
|
||||
|
@ -15,12 +15,12 @@ class ClientController extends \BaseController {
|
||||
return View::make('list', array(
|
||||
'entityType'=>ENTITY_CLIENT,
|
||||
'title' => '- Clients',
|
||||
'columns'=>['checkbox', 'Client', 'Contact', 'Balance', 'Last Login', 'Date Created', 'Email', 'Phone', 'Action']
|
||||
'columns'=>['checkbox', 'Client', 'Contact', 'Date Created', 'Email', 'Phone', 'Last Login', 'Balance', 'Action']
|
||||
));
|
||||
}
|
||||
|
||||
public function getDatatable()
|
||||
{
|
||||
{
|
||||
$query = DB::table('clients')
|
||||
->join('contacts', 'contacts.client_id', '=', 'clients.id')
|
||||
->where('clients.account_id', '=', Auth::user()->account_id)
|
||||
@ -28,15 +28,30 @@ class ClientController extends \BaseController {
|
||||
->where('contacts.is_primary', '=', true)
|
||||
->select('clients.public_id','clients.name','contacts.first_name','contacts.last_name','clients.balance','clients.last_login','clients.created_at','clients.work_phone','contacts.email');
|
||||
|
||||
$filter = Input::get('sSearch');
|
||||
if ($filter)
|
||||
{
|
||||
$query->where(function($query) use ($filter)
|
||||
{
|
||||
$query->where('clients.name', 'like', '%'.$filter.'%')
|
||||
->orWhere('contacts.first_name', 'like', '%'.$filter.'%')
|
||||
->orWhere('contacts.last_name', 'like', '%'.$filter.'%')
|
||||
->orWhere('contacts.email', 'like', '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
//$query->get();
|
||||
//dd(DB::getQueryLog());
|
||||
|
||||
return Datatable::query($query)
|
||||
->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; })
|
||||
->addColumn('name', function($model) { return link_to('clients/' . $model->public_id, $model->name); })
|
||||
->addColumn('first_name', function($model) { return $model->first_name . ' ' . $model->last_name; })
|
||||
->addColumn('balance', function($model) { return '$' . $model->balance; })
|
||||
->addColumn('last_login', function($model) { return Utils::timestampToDateString($model->last_login); })
|
||||
->addColumn('created_at', function($model) { return Utils::timestampToDateString($model->created_at); })
|
||||
->addColumn('email', function($model) { return $model->email ? HTML::mailto($model->email, $model->email) : ''; })
|
||||
->addColumn('work_phone', function($model) { return Utils::formatPhoneNumber($model->work_phone); })
|
||||
->addColumn('last_login', function($model) { return Utils::timestampToDateString($model->last_login); })
|
||||
->addColumn('balance', function($model) { return '$' . $model->balance; })
|
||||
->addColumn('dropdown', function($model)
|
||||
{
|
||||
return '<div class="btn-group tr-action" style="visibility:hidden;">
|
||||
@ -71,6 +86,8 @@ class ClientController extends \BaseController {
|
||||
'method' => 'POST',
|
||||
'url' => 'clients',
|
||||
'title' => '- New Client',
|
||||
'clientSizes' => ClientSize::orderBy('id')->get(),
|
||||
'clientIndustries' => ClientIndustry::orderBy('name')->get(),
|
||||
'countries' => Country::orderBy('name')->get());
|
||||
|
||||
return View::make('clients.edit', $data);
|
||||
@ -94,13 +111,13 @@ class ClientController extends \BaseController {
|
||||
*/
|
||||
public function show($publicId)
|
||||
{
|
||||
$client = Client::scope($publicId)->with('contacts')->firstOrFail();
|
||||
$client = Client::scope($publicId)->with('contacts', 'client_size', 'client_industry')->firstOrFail();
|
||||
Utils::trackViewed($client->name, ENTITY_CLIENT);
|
||||
|
||||
$data = array(
|
||||
'client' => $client,
|
||||
'title' => '- ' . $client->name,
|
||||
'hasRecurringInvoices' => Invoice::scope()->where('frequency_id', '>', '0')->count() > 0
|
||||
'hasRecurringInvoices' => Invoice::scope()->where('frequency_id', '>', '0')->whereClientId($client->id)->count() > 0
|
||||
);
|
||||
|
||||
return View::make('clients.show', $data);
|
||||
@ -120,6 +137,8 @@ class ClientController extends \BaseController {
|
||||
'method' => 'PUT',
|
||||
'url' => 'clients/' . $publicId,
|
||||
'title' => '- ' . $client->name,
|
||||
'clientSizes' => ClientSize::orderBy('id')->get(),
|
||||
'clientIndustries' => ClientIndustry::orderBy('name')->get(),
|
||||
'countries' => Country::orderBy('name')->get());
|
||||
return View::make('clients.edit', $data);
|
||||
}
|
||||
@ -161,10 +180,11 @@ class ClientController extends \BaseController {
|
||||
$client->city = trim(Input::get('city'));
|
||||
$client->state = trim(Input::get('state'));
|
||||
$client->notes = trim(Input::get('notes'));
|
||||
$client->postal_code = trim(Input::get('postal_code'));
|
||||
if (Input::get('country_id')) {
|
||||
$client->country_id = Input::get('country_id');
|
||||
}
|
||||
$client->postal_code = trim(Input::get('postal_code'));
|
||||
$client->country_id = Input::get('country_id') ? Input::get('country_id') : null;
|
||||
$client->client_size_id = Input::get('client_size_id') ? Input::get('client_size_id') : null;
|
||||
$client->client_industry_id = Input::get('client_industry_id') ? Input::get('client_industry_id') : null;
|
||||
|
||||
$client->save();
|
||||
|
||||
$data = json_decode(Input::get('data'));
|
||||
@ -201,7 +221,12 @@ class ClientController extends \BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
Session::flash('message', 'Successfully updated client');
|
||||
if ($publicId) {
|
||||
Session::flash('message', 'Successfully updated client');
|
||||
} else {
|
||||
Session::flash('message', 'Successfully created client');
|
||||
}
|
||||
|
||||
return Redirect::to('clients/' . $client->public_id);
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ class CreditController extends \BaseController {
|
||||
return View::make('list', array(
|
||||
'entityType'=>ENTITY_CREDIT,
|
||||
'title' => '- Credits',
|
||||
'columns'=>['checkbox', 'Client', 'Amount', 'Credit Date', 'Action']
|
||||
'columns'=>['checkbox', 'Client', 'Credit Amount', 'Credit Date', 'Action']
|
||||
));
|
||||
}
|
||||
|
||||
@ -28,6 +28,15 @@ class CreditController extends \BaseController {
|
||||
$query->where('clients.public_id', '=', $clientPublicId);
|
||||
}
|
||||
|
||||
$filter = Input::get('sSearch');
|
||||
if ($filter)
|
||||
{
|
||||
$query->where(function($query) use ($filter)
|
||||
{
|
||||
$query->where('clients.name', 'like', '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
$table = Datatable::query($query);
|
||||
|
||||
if (!$clientPublicId) {
|
||||
|
@ -18,13 +18,13 @@ class InvoiceController extends \BaseController {
|
||||
$data = [
|
||||
'title' => '- Invoices',
|
||||
'entityType'=>ENTITY_INVOICE,
|
||||
'columns'=>['checkbox', 'Invoice Number', 'Client', 'Total', 'Amount Due', 'Invoice Date', 'Due Date', 'Status', 'Action']
|
||||
'columns'=>['checkbox', 'Invoice Number', 'Client', 'Invoice Date', 'Invoice Total', 'Balance Due', 'Due Date', 'Status', 'Action']
|
||||
];
|
||||
|
||||
if (Invoice::scope()->where('frequency_id', '>', '0')->count() > 0)
|
||||
{
|
||||
$data['secEntityType'] = ENTITY_RECURRING_INVOICE;
|
||||
$data['secColumns'] = ['checkbox', 'Client', 'Total', 'Frequency', 'Start Date', 'End Date', 'Action'];
|
||||
$data['secColumns'] = ['checkbox', 'Frequency', 'Client', 'Start Date', 'End Date', 'Invoice Total', 'Action'];
|
||||
}
|
||||
|
||||
return View::make('list', $data);
|
||||
@ -44,6 +44,17 @@ class InvoiceController extends \BaseController {
|
||||
$query->where('clients.public_id', '=', $clientPublicId);
|
||||
}
|
||||
|
||||
$filter = Input::get('sSearch');
|
||||
if ($filter)
|
||||
{
|
||||
$query->where(function($query) use ($filter)
|
||||
{
|
||||
$query->where('clients.name', 'like', '%'.$filter.'%')
|
||||
->orWhere('invoices.invoice_number', 'like', '%'.$filter.'%')
|
||||
->orWhere('invoice_statuses.name', 'like', '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
$table = Datatable::query($query);
|
||||
|
||||
if (!$clientPublicId) {
|
||||
@ -56,9 +67,9 @@ class InvoiceController extends \BaseController {
|
||||
$table->addColumn('client', function($model) { return link_to('clients/' . $model->client_public_id, $model->client_name); });
|
||||
}
|
||||
|
||||
return $table->addColumn('total', function($model) { return '$' . money_format('%i', $model->total); })
|
||||
return $table->addColumn('invoice_date', function($model) { return Utils::fromSqlDate($model->invoice_date); })
|
||||
->addColumn('total', function($model) { return '$' . money_format('%i', $model->total); })
|
||||
->addColumn('balance', function($model) { return '$' . money_format('%i', $model->balance); })
|
||||
->addColumn('invoice_date', function($model) { return Utils::fromSqlDate($model->invoice_date); })
|
||||
->addColumn('due_date', function($model) { return Utils::fromSqlDate($model->due_date); })
|
||||
->addColumn('invoice_status_name', function($model) { return $model->invoice_status_name; })
|
||||
->addColumn('dropdown', function($model)
|
||||
@ -93,20 +104,31 @@ class InvoiceController extends \BaseController {
|
||||
$query->where('clients.public_id', '=', $clientPublicId);
|
||||
}
|
||||
|
||||
$filter = Input::get('sSearch');
|
||||
if ($filter)
|
||||
{
|
||||
$query->where(function($query) use ($filter)
|
||||
{
|
||||
$query->where('clients.name', 'like', '%'.$filter.'%')
|
||||
->orWhere('invoices.invoice_number', 'like', '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
$table = Datatable::query($query);
|
||||
|
||||
if (!$clientPublicId) {
|
||||
$table->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; });
|
||||
}
|
||||
|
||||
$table->addColumn('frequency', function($model) { return link_to('invoices/' . $model->public_id, $model->frequency); });
|
||||
|
||||
if (!$clientPublicId) {
|
||||
$table->addColumn('client', function($model) { return link_to('clients/' . $model->client_public_id, $model->client_name); });
|
||||
}
|
||||
|
||||
return $table->addColumn('total', function($model) { return '$' . money_format('%i', $model->total); })
|
||||
->addColumn('frequency', function($model) { return $model->frequency; })
|
||||
->addColumn('start_date', function($model) { return Utils::fromSqlDate($model->start_date); })
|
||||
return $table->addColumn('start_date', function($model) { return Utils::fromSqlDate($model->start_date); })
|
||||
->addColumn('end_date', function($model) { return Utils::fromSqlDate($model->end_date); })
|
||||
->addColumn('total', function($model) { return '$' . money_format('%i', $model->total); })
|
||||
->addColumn('dropdown', function($model)
|
||||
{
|
||||
return '<div class="btn-group tr-action" style="visibility:hidden;">
|
||||
@ -340,7 +362,7 @@ class InvoiceController extends \BaseController {
|
||||
'account' => Auth::user()->account,
|
||||
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
||||
'countries' => Country::orderBy('name')->get(),
|
||||
'clients' => Client::scope()->orderBy('name')->get(),
|
||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
||||
'frequencies' => array(
|
||||
1 => 'Weekly',
|
||||
2 => 'Two weeks',
|
||||
@ -371,7 +393,7 @@ class InvoiceController extends \BaseController {
|
||||
{
|
||||
return InvoiceController::bulk();
|
||||
}
|
||||
|
||||
|
||||
$rules = array(
|
||||
'client' => 'required',
|
||||
);
|
||||
@ -388,33 +410,33 @@ class InvoiceController extends \BaseController {
|
||||
if ($clientPublicId == "-1")
|
||||
{
|
||||
$client = Client::createNew();
|
||||
$client->name = trim(Input::get('name'));
|
||||
$client->work_phone = trim(Input::get('work_phone'));
|
||||
$client->address1 = trim(Input::get('address1'));
|
||||
$client->address2 = trim(Input::get('address2'));
|
||||
$client->city = trim(Input::get('city'));
|
||||
$client->state = trim(Input::get('state'));
|
||||
$client->postal_code = trim(Input::get('postal_code'));
|
||||
if (Input::get('country_id')) {
|
||||
$client->country_id = Input::get('country_id');
|
||||
}
|
||||
$client->save();
|
||||
$clientId = $client->id;
|
||||
|
||||
$contact = Contact::createNew();
|
||||
$contact->is_primary = true;
|
||||
$contact->first_name = trim(Input::get('first_name'));
|
||||
$contact->last_name = trim(Input::get('last_name'));
|
||||
$contact->phone = trim(Input::get('phone'));
|
||||
$contact->email = trim(Input::get('email'));
|
||||
$client->contacts()->save($contact);
|
||||
$contact->is_primary = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$client = Client::scope($clientPublicId)->with('contacts')->firstOrFail();
|
||||
$contact = $client->contacts()->first();
|
||||
$contact = $client->contacts()->where('is_primary', '=', true)->firstOrFail();
|
||||
}
|
||||
|
||||
$client->name = trim(Input::get('name'));
|
||||
$client->work_phone = trim(Input::get('work_phone'));
|
||||
$client->address1 = trim(Input::get('address1'));
|
||||
$client->address2 = trim(Input::get('address2'));
|
||||
$client->city = trim(Input::get('city'));
|
||||
$client->state = trim(Input::get('state'));
|
||||
$client->postal_code = trim(Input::get('postal_code'));
|
||||
if (Input::get('country_id')) {
|
||||
$client->country_id = Input::get('country_id');
|
||||
}
|
||||
$client->save();
|
||||
|
||||
$contact->first_name = trim(Input::get('first_name'));
|
||||
$contact->last_name = trim(Input::get('last_name'));
|
||||
$contact->phone = trim(Input::get('phone'));
|
||||
$contact->email = trim(Input::get('email'));
|
||||
$client->contacts()->save($contact);
|
||||
|
||||
if ($publicId) {
|
||||
$invoice = Invoice::scope($publicId)->firstOrFail();
|
||||
$invoice->invoice_items()->forceDelete();
|
||||
@ -423,7 +445,7 @@ class InvoiceController extends \BaseController {
|
||||
}
|
||||
|
||||
$invoice->client_id = $client->id;
|
||||
$invoice->discount = 0;
|
||||
$invoice->discount = Input::get('discount');
|
||||
$invoice->invoice_number = trim(Input::get('invoice_number'));
|
||||
$invoice->invoice_date = Utils::toSqlDate(Input::get('invoice_date'));
|
||||
$invoice->due_date = Utils::toSqlDate(Input::get('due_date'));
|
||||
@ -432,7 +454,8 @@ class InvoiceController extends \BaseController {
|
||||
$invoice->start_date = Utils::toSqlDate(Input::get('start_date'));
|
||||
$invoice->end_date = Utils::toSqlDate(Input::get('end_date'));
|
||||
$invoice->notes = Input::get('notes');
|
||||
|
||||
$invoice->po_number = Input::get('po_number');
|
||||
|
||||
$client->invoices()->save($invoice);
|
||||
|
||||
$items = json_decode(Input::get('items'));
|
||||
@ -500,7 +523,11 @@ class InvoiceController extends \BaseController {
|
||||
/*
|
||||
*/
|
||||
|
||||
if ($action == 'email')
|
||||
if ($action == 'clone')
|
||||
{
|
||||
return InvoiceController::cloneInvoice($publicId);
|
||||
}
|
||||
else if ($action == 'email')
|
||||
{
|
||||
$this->mailer->sendInvoice($invoice, $contact);
|
||||
|
||||
@ -561,4 +588,37 @@ class InvoiceController extends \BaseController {
|
||||
|
||||
return Redirect::to('invoices');
|
||||
}
|
||||
|
||||
public static function cloneInvoice($publicId)
|
||||
{
|
||||
$invoice = Invoice::with('invoice_items')->scope($publicId)->firstOrFail();
|
||||
|
||||
$clone = Invoice::createNew();
|
||||
foreach (['client_id', 'discount', 'invoice_date', 'due_date', 'frequency_id', 'start_date', 'end_date', 'notes'] as $field)
|
||||
{
|
||||
$clone->$field = $invoice->$field;
|
||||
}
|
||||
|
||||
if (!$clone->isRecurring())
|
||||
{
|
||||
$clone->invoice_number = Auth::user()->account->getNextInvoiceNumber();
|
||||
}
|
||||
|
||||
$clone->save();
|
||||
|
||||
foreach ($invoice->invoice_items as $item)
|
||||
{
|
||||
$cloneItem = InvoiceItem::createNew();
|
||||
|
||||
foreach (['product_id', 'product_key', 'notes', 'cost', 'qty'] as $field)
|
||||
{
|
||||
$cloneItem->$field = $item->$field;
|
||||
}
|
||||
|
||||
$clone->invoice_items()->save($cloneItem);
|
||||
}
|
||||
|
||||
Session::flash('message', 'Successfully cloned invoice');
|
||||
return Redirect::to('invoices/' . $clone->public_id);
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ class PaymentController extends \BaseController
|
||||
return View::make('list', array(
|
||||
'entityType'=>ENTITY_PAYMENT,
|
||||
'title' => '- Payments',
|
||||
'columns'=>['checkbox', 'Transaction Reference', 'Client', 'Invoice', 'Amount', 'Payment Date', 'Action']
|
||||
'columns'=>['checkbox', 'Transaction Reference', 'Client', 'Invoice', 'Payment Amount', 'Payment Date', 'Action']
|
||||
));
|
||||
}
|
||||
|
||||
@ -24,6 +24,15 @@ class PaymentController extends \BaseController
|
||||
$query->where('clients.public_id', '=', $clientPublicId);
|
||||
}
|
||||
|
||||
$filter = Input::get('sSearch');
|
||||
if ($filter)
|
||||
{
|
||||
$query->where(function($query) use ($filter)
|
||||
{
|
||||
$query->where('clients.name', 'like', '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
$table = Datatable::query($query);
|
||||
|
||||
if (!$clientPublicId) {
|
||||
|
@ -23,6 +23,8 @@ class ConfideSetupUsersTable extends Migration {
|
||||
Schema::dropIfExists('invoices');
|
||||
Schema::dropIfExists('password_reminders');
|
||||
Schema::dropIfExists('clients');
|
||||
Schema::dropIfExists('client_sizes');
|
||||
Schema::dropIfExists('client_industries');
|
||||
Schema::dropIfExists('users');
|
||||
Schema::dropIfExists('accounts');
|
||||
Schema::dropIfExists('invoice_statuses');
|
||||
@ -85,7 +87,6 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->foreign('timezone_id')->references('id')->on('timezones');
|
||||
$t->foreign('country_id')->references('id')->on('countries');
|
||||
});
|
||||
|
||||
|
||||
Schema::create('gateways', function($t)
|
||||
{
|
||||
@ -115,7 +116,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
Schema::create('users', function($t)
|
||||
{
|
||||
$t->increments('id');
|
||||
$t->unsignedInteger('account_id');
|
||||
$t->unsignedInteger('account_id')->index();
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
|
||||
@ -144,11 +145,23 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->string('token');
|
||||
});
|
||||
|
||||
Schema::create('client_sizes', function($t)
|
||||
{
|
||||
$t->increments('id');
|
||||
$t->string('name');
|
||||
});
|
||||
|
||||
Schema::create('client_industries', function($t)
|
||||
{
|
||||
$t->increments('id');
|
||||
$t->string('name');
|
||||
});
|
||||
|
||||
Schema::create('clients', function($t)
|
||||
{
|
||||
$t->increments('id');
|
||||
$t->unsignedInteger('user_id');
|
||||
$t->unsignedInteger('account_id');
|
||||
$t->unsignedInteger('account_id')->index();
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
|
||||
@ -163,12 +176,17 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->text('notes');
|
||||
$t->decimal('balance', 10, 2);
|
||||
$t->timestamp('last_login');
|
||||
$t->string('website');
|
||||
$t->unsignedInteger('client_industry_id')->nullable();
|
||||
$t->unsignedInteger('client_size_id')->nullable();
|
||||
|
||||
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
$t->foreign('user_id')->references('id')->on('users');
|
||||
$t->foreign('country_id')->references('id')->on('countries');
|
||||
$t->foreign('client_industry_id')->references('id')->on('client_industries');
|
||||
$t->foreign('client_size_id')->references('id')->on('client_sizes');
|
||||
|
||||
$t->unsignedInteger('public_id');
|
||||
$t->unsignedInteger('public_id')->index();
|
||||
$t->unique( array('account_id','public_id') );
|
||||
});
|
||||
|
||||
@ -177,7 +195,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->increments('id');
|
||||
$t->unsignedInteger('account_id');
|
||||
$t->unsignedInteger('user_id');
|
||||
$t->unsignedInteger('client_id');
|
||||
$t->unsignedInteger('client_id')->index();
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
|
||||
@ -210,15 +228,16 @@ class ConfideSetupUsersTable extends Migration {
|
||||
Schema::create('invoices', function($t)
|
||||
{
|
||||
$t->increments('id');
|
||||
$t->unsignedInteger('client_id');
|
||||
$t->unsignedInteger('client_id')->index();
|
||||
$t->unsignedInteger('user_id');
|
||||
$t->unsignedInteger('account_id');
|
||||
$t->unsignedInteger('account_id')->index();
|
||||
$t->unsignedInteger('invoice_status_id')->default(1);
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
|
||||
$t->string('invoice_number');
|
||||
$t->float('discount');
|
||||
$t->string('po_number');
|
||||
$t->date('invoice_date');
|
||||
$t->date('due_date')->nullable();
|
||||
$t->text('notes');
|
||||
@ -227,7 +246,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->date('start_date')->nullable();
|
||||
$t->date('end_date')->nullable();
|
||||
$t->date('last_sent_date')->nullable();
|
||||
$t->unsignedInteger('recurring_invoice_id')->nullable();
|
||||
$t->unsignedInteger('recurring_invoice_id')->index()->nullable();
|
||||
|
||||
|
||||
$t->decimal('total', 10, 2);
|
||||
@ -239,7 +258,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->foreign('invoice_status_id')->references('id')->on('invoice_statuses');
|
||||
$t->foreign('recurring_invoice_id')->references('id')->on('invoices');
|
||||
|
||||
$t->unsignedInteger('public_id');
|
||||
$t->unsignedInteger('public_id')->index();
|
||||
$t->unique( array('account_id','public_id') );
|
||||
});
|
||||
|
||||
@ -250,8 +269,8 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->unsignedInteger('account_id');
|
||||
$t->unsignedInteger('user_id');
|
||||
$t->unsignedInteger('contact_id');
|
||||
$t->unsignedInteger('invoice_id');
|
||||
$t->string('invitation_key')->unique();
|
||||
$t->unsignedInteger('invoice_id')->index();
|
||||
$t->string('invitation_key')->index()->unique();
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
|
||||
@ -261,14 +280,14 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
|
||||
$t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
|
||||
|
||||
$t->unsignedInteger('public_id');
|
||||
$t->unsignedInteger('public_id')->index();
|
||||
$t->unique( array('account_id','public_id') );
|
||||
});
|
||||
|
||||
Schema::create('products', function($t)
|
||||
{
|
||||
$t->increments('id');
|
||||
$t->unsignedInteger('account_id');
|
||||
$t->unsignedInteger('account_id')->index();
|
||||
$t->unsignedInteger('user_id');
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
@ -291,7 +310,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->increments('id');
|
||||
$t->unsignedInteger('account_id');
|
||||
$t->unsignedInteger('user_id');
|
||||
$t->unsignedInteger('invoice_id');
|
||||
$t->unsignedInteger('invoice_id')->index();
|
||||
$t->unsignedInteger('product_id')->nullable();
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
@ -313,8 +332,8 @@ class ConfideSetupUsersTable extends Migration {
|
||||
{
|
||||
$t->increments('id');
|
||||
$t->unsignedInteger('invoice_id')->nullable();
|
||||
$t->unsignedInteger('account_id');
|
||||
$t->unsignedInteger('client_id');
|
||||
$t->unsignedInteger('account_id')->index();
|
||||
$t->unsignedInteger('client_id')->index();
|
||||
$t->unsignedInteger('contact_id')->nullable();
|
||||
$t->unsignedInteger('invitation_id')->nullable();
|
||||
$t->unsignedInteger('user_id')->nullable();
|
||||
@ -332,16 +351,16 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->foreign('contact_id')->references('id')->on('contacts');
|
||||
$t->foreign('user_id')->references('id')->on('users');
|
||||
|
||||
$t->unsignedInteger('public_id');
|
||||
$t->unsignedInteger('public_id')->index();
|
||||
$t->unique( array('account_id','public_id') );
|
||||
});
|
||||
|
||||
Schema::create('credits', function($t)
|
||||
{
|
||||
$t->increments('id');
|
||||
$t->unsignedInteger('account_id');
|
||||
$t->unsignedInteger('account_id')->index();
|
||||
$t->unsignedInteger('user_id');
|
||||
$t->unsignedInteger('client_id')->nullable();
|
||||
$t->unsignedInteger('client_id')->index()->nullable();
|
||||
$t->unsignedInteger('contact_id')->nullable();
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
@ -355,7 +374,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->foreign('contact_id')->references('id')->on('contacts');
|
||||
$t->foreign('user_id')->references('id')->on('users');
|
||||
|
||||
$t->unsignedInteger('public_id');
|
||||
$t->unsignedInteger('public_id')->index();
|
||||
$t->unique( array('account_id','public_id') );
|
||||
});
|
||||
|
||||
@ -403,6 +422,8 @@ class ConfideSetupUsersTable extends Migration {
|
||||
Schema::dropIfExists('invoices');
|
||||
Schema::dropIfExists('password_reminders');
|
||||
Schema::dropIfExists('clients');
|
||||
Schema::dropIfExists('client_sizes');
|
||||
Schema::dropIfExists('client_industries');
|
||||
Schema::dropIfExists('users');
|
||||
Schema::dropIfExists('accounts');
|
||||
Schema::dropIfExists('invoice_statuses');
|
||||
|
@ -58,6 +58,17 @@ class ConstantsSeeder extends Seeder
|
||||
Frequency::create(array('name' => 'Six months'));
|
||||
Frequency::create(array('name' => 'Annually'));
|
||||
|
||||
ClientIndustry::create(array('name' => 'Accounting'));
|
||||
ClientIndustry::create(array('name' => 'Travel'));
|
||||
ClientIndustry::create(array('name' => 'Engineering'));
|
||||
ClientIndustry::create(array('name' => 'Marketing'));
|
||||
|
||||
ClientSize::create(array('name' => '1 - 10'));
|
||||
ClientSize::create(array('name' => '11 - 50'));
|
||||
ClientSize::create(array('name' => '51 - 100'));
|
||||
ClientSize::create(array('name' => '101 - 500'));
|
||||
ClientSize::create(array('name' => '500+'));
|
||||
|
||||
$gateways = [
|
||||
array('name'=>'Authorize.Net AIM', 'provider'=>'AuthorizeNet_AIM'),
|
||||
array('name'=>'Authorize.Net SIM', 'provider'=>'AuthorizeNet_SIM'),
|
||||
|
@ -62,7 +62,7 @@ class Utils
|
||||
return '';
|
||||
}
|
||||
|
||||
return $date->format('l M jS, Y g:ia');
|
||||
return $date->format('D M jS, Y g:ia');
|
||||
}
|
||||
|
||||
public static function timestampToDateString($timestamp) {
|
||||
@ -212,4 +212,5 @@ class Utils
|
||||
{
|
||||
return ucwords(str_replace('_', ' ', $entityType));
|
||||
}
|
||||
|
||||
}
|
@ -39,6 +39,16 @@ class Client extends EntityModel
|
||||
return $this->belongsTo('Country');
|
||||
}
|
||||
|
||||
public function client_size()
|
||||
{
|
||||
return $this->belongsTo('ClientSize');
|
||||
}
|
||||
|
||||
public function client_industry()
|
||||
{
|
||||
return $this->belongsTo('ClientIndustry');
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
@ -104,6 +114,23 @@ class Client extends EntityModel
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function getIndustry()
|
||||
{
|
||||
$str = '';
|
||||
|
||||
if ($this->client_industry)
|
||||
{
|
||||
$str .= $this->client_industry->name . ' ';
|
||||
}
|
||||
|
||||
if ($this->client_size)
|
||||
{
|
||||
$str .= $this->client_size->name;
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function getDateCreated()
|
||||
{
|
||||
if ($this->created_at == '0000-00-00 00:00:00')
|
||||
|
6
app/models/ClientIndustry.php
Executable file
6
app/models/ClientIndustry.php
Executable file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
class ClientIndustry extends Eloquent
|
||||
{
|
||||
public $timestamps = false;
|
||||
}
|
6
app/models/ClientSize.php
Executable file
6
app/models/ClientSize.php
Executable file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
class ClientSize extends Eloquent
|
||||
{
|
||||
public $timestamps = false;
|
||||
}
|
@ -14,6 +14,8 @@
|
||||
//dd(DB::getQueryLog());
|
||||
//dd(Client::getPrivateId(1));
|
||||
//dd(new DateTime());
|
||||
|
||||
|
||||
Route::get('/send_emails', function() {
|
||||
Artisan::call('ninja:send-invoices');
|
||||
});
|
||||
|
@ -25,8 +25,7 @@
|
||||
{{ Former::legend('Organization') }}
|
||||
{{ Former::text('name') }}
|
||||
{{ Former::text('work_phone')->label('Phone') }}
|
||||
{{ Former::textarea('notes') }}
|
||||
|
||||
|
||||
|
||||
{{ Former::legend('Address') }}
|
||||
{{ Former::text('address1')->label('Street') }}
|
||||
@ -61,9 +60,15 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{ Former::legend('Additional Info') }}
|
||||
{{ Former::select('client_size_id')->addOption('','')->label('Size')
|
||||
->fromQuery($clientSizes, 'name', 'id')->select($client ? $client->client_size_id : '') }}
|
||||
{{ Former::select('client_industry_id')->addOption('','')->label('Industry')
|
||||
->fromQuery($clientIndustries, 'name', 'id')->select($client ? $client->client_industry_id : '') }}
|
||||
{{ Former::textarea('notes') }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
<p>{{ $client->getAddress() }}</p>
|
||||
<p>{{ $client->getPhone() }}</p>
|
||||
<p>{{ $client->getNotes() }}</p>
|
||||
<p>{{ $client->getIndustry() }}</p>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
@ -91,7 +92,7 @@
|
||||
|
||||
@if ($hasRecurringInvoices)
|
||||
{{ Datatable::table()
|
||||
->addColumn('Total', 'How Often', 'Start Date', 'End Date')
|
||||
->addColumn('How Often', 'Start Date', 'End Date', 'Invoice Total')
|
||||
->setUrl(url('api/recurring_invoices/' . $client->public_id))
|
||||
->setOptions('sPaginationType', 'bootstrap')
|
||||
->setOptions('bFilter', false)
|
||||
@ -99,7 +100,7 @@
|
||||
@endif
|
||||
|
||||
{{ Datatable::table()
|
||||
->addColumn('Invoice Number', 'Total', 'Amount Due', 'Invoice Date', 'Due Date', 'Status')
|
||||
->addColumn('Invoice Number', 'Invoice Date', 'Invoice Total', 'Balance Due', 'Due Date', 'Status')
|
||||
->setUrl(url('api/invoices/' . $client->public_id))
|
||||
->setOptions('sPaginationType', 'bootstrap')
|
||||
->setOptions('bFilter', false)
|
||||
@ -109,7 +110,7 @@
|
||||
<div class="tab-pane" id="payments">
|
||||
|
||||
{{ Datatable::table()
|
||||
->addColumn('Transaction Reference', 'Invoice', 'Amount', 'Payment Date')
|
||||
->addColumn('Transaction Reference', 'Invoice', 'Payment Amount', 'Payment Date')
|
||||
->setUrl(url('api/payments/' . $client->public_id))
|
||||
->setOptions('sPaginationType', 'bootstrap')
|
||||
->setOptions('bFilter', false)
|
||||
@ -119,7 +120,7 @@
|
||||
<div class="tab-pane" id="credits">
|
||||
|
||||
{{ Datatable::table()
|
||||
->addColumn('Amount', 'Credit Date')
|
||||
->addColumn('Credit Amount', 'Credit Date')
|
||||
->setUrl(url('api/credits/' . $client->public_id))
|
||||
->setOptions('sPaginationType', 'bootstrap')
|
||||
->setOptions('bFilter', false)
|
||||
|
@ -7,7 +7,11 @@
|
||||
<thead>
|
||||
<tr>
|
||||
@foreach($columns as $i => $c)
|
||||
<th align="center" valign="middle" class="head{{ $i }}">
|
||||
<th align="center" valign="middle" class="head{{ $i }}"
|
||||
@if ($c == 'checkbox')
|
||||
style="width:20px"
|
||||
@endif
|
||||
>
|
||||
@if ($c == 'checkbox' && $hasCheckboxes = true)
|
||||
<input type="checkbox" class="selectAll"/>
|
||||
@else
|
||||
@ -45,7 +49,6 @@
|
||||
{{ json_encode($k) }}: {{ $o }},
|
||||
@endforeach
|
||||
"fnDrawCallback": function(oSettings) {
|
||||
//jQuery.uniform.update();
|
||||
if (window.onDatatableReady) {
|
||||
window.onDatatableReady();
|
||||
}
|
||||
|
@ -33,22 +33,25 @@
|
||||
@endif
|
||||
|
||||
<div class="row" style="min-height:195px">
|
||||
<div class="col-md-6" id="col_1">
|
||||
<div class="col-md-7" id="col_1">
|
||||
{{ Former::select('client')->addOption('', '')->fromQuery($clients, 'name', 'public_id')->select($client ? $client->public_id : '')->addGroupClass('client_select')
|
||||
->help('<a style="cursor:pointer" data-toggle="modal" id="modalLink" onclick="showCreateNew()">Create new client</a>') }}
|
||||
{{ Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") }}
|
||||
{{ Former::textarea('notes') }}
|
||||
|
||||
</div>
|
||||
<div class="col-md-5" id="col_2">
|
||||
<div class="col-md-4" id="col_2">
|
||||
<div id="recurring_checkbox">
|
||||
{{ Former::checkbox('recurring')->text('Enable automatic invoicing | <a href="#">Learn more</a>')->onchange('toggleRecurring()')
|
||||
{{ Former::checkbox('recurring')->text('Enable | <a href="#">Learn more</a>')->onchange('toggleRecurring()')
|
||||
->inlineHelp($invoice && $invoice->last_sent_date ? 'Last invoice sent ' . Utils::timestampToDateString($invoice->last_sent_date) : '') }}
|
||||
</div>
|
||||
<div id="recurring_off">
|
||||
{{ Former::text('invoice_number')->label('Invoice #') }}
|
||||
{{ Former::text('po_number')->label('PO number') }}
|
||||
{{ Former::text('invoice_date') }}
|
||||
{{ Former::text('due_date') }}
|
||||
|
||||
{{-- Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") --}}
|
||||
|
||||
{{-- Former::text('invoice_date')->label('Invoice Date')->data_date_format('yyyy-mm-dd') --}}
|
||||
</div>
|
||||
<div id="recurring_on" style="display:none">
|
||||
@ -56,8 +59,11 @@
|
||||
{{ Former::text('start_date')->onchange('updateRecurringStats()') }}
|
||||
{{ Former::text('end_date')->onchange('updateRecurringStats()') }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-3" id="col_3" style="display:none">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -71,8 +77,8 @@
|
||||
<th class="hide-border"></th>
|
||||
<th>Item</th>
|
||||
<th>Description</th>
|
||||
<th>Unit Cost</th>
|
||||
<th>Quantity</th>
|
||||
<th>Rate</th>
|
||||
<th>Units</th>
|
||||
<th>Line Total</th>
|
||||
<th class="hide-border"></th>
|
||||
</tr>
|
||||
@ -130,7 +136,7 @@
|
||||
<tr>
|
||||
<td class="hide-border"></td>
|
||||
<td colspan="2" class="hide-border"/>
|
||||
<td colspan="2"><b>Invoice Total</b></td>
|
||||
<td colspan="2"><b>Balance Due</b></td>
|
||||
<td style="text-align: right"><span data-bind="text: total"/></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
@ -146,11 +152,15 @@
|
||||
@endif
|
||||
</div>
|
||||
|
||||
|
||||
{{ Button::normal('Download PDF', array('onclick' => 'onDownloadClick()')) }}
|
||||
|
||||
@if ($invoice)
|
||||
{{ DropdownButton::normal('Download PDF',
|
||||
{{ DropdownButton::primary('Save Invoice',
|
||||
Navigation::links(
|
||||
array(
|
||||
array('Download PDF', "javascript:onDownloadClick()"),
|
||||
array('Save Invoice', "javascript:onSaveClick()"),
|
||||
array('Clone Invoice', "javascript:onCloneClick()"),
|
||||
array(Navigation::DIVIDER),
|
||||
array('Archive Invoice', "javascript:onArchiveClick()"),
|
||||
array('Delete Invoice', "javascript:onDeleteClick()"),
|
||||
@ -158,18 +168,17 @@
|
||||
)
|
||||
, array('id'=>'actionDropDown','style'=>'text-align:left'))->split(); }}
|
||||
@else
|
||||
{{ Button::normal('Download PDF', array('onclick' => 'onDownloadClick()')) }}
|
||||
{{ Button::primary_submit('Save Invoice') }}
|
||||
@endif
|
||||
|
||||
{{ Button::primary_submit('Save Invoice') }}
|
||||
{{ Button::primary('Send Email', array('id' => 'email_button', 'onclick' => 'onEmailClick()')) }}
|
||||
</div>
|
||||
<p> </p>
|
||||
|
||||
<!-- <textarea rows="20" cols="120" id="pdfText" onkeyup="runCode()"></textarea> -->
|
||||
<!-- <iframe frameborder="1" width="100%" height="600" style="display:block;margin: 0 auto"></iframe> -->
|
||||
<!-- <iframe frameborder="1" width="100%" height="500"></iframe> -->
|
||||
<canvas id="the-canvas" style="width:100%;border:solid 1px #CCCCCC;"></canvas>
|
||||
<iframe id="theIFrame" frameborder="1" width="100%" height="500"></iframe>
|
||||
<canvas id="theCanvas" style="display:none;width:100%;border:solid 1px #CCCCCC;"></canvas>
|
||||
|
||||
|
||||
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
@ -253,13 +262,13 @@
|
||||
|
||||
$(function() {
|
||||
|
||||
$('form').change(refreshPDF);
|
||||
|
||||
$('#country_id').combobox();
|
||||
|
||||
$('#invoice_date').datepicker({
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
}).on('changeDate', function(e) {
|
||||
refreshPDF();
|
||||
});
|
||||
|
||||
$('#due_date, #start_date, #end_date').datepicker({
|
||||
@ -270,11 +279,13 @@
|
||||
var $input = $('select#client');
|
||||
$input.combobox();
|
||||
$('.client_select input.form-control').on('change', function(e) {
|
||||
refreshPDF();
|
||||
if ($('input[name=client]').val() != '-1') {
|
||||
$('#modalLink').text('Create new client');
|
||||
var clientId = parseInt($('input[name=client]').val(), 10);
|
||||
$('#modalLink').text(clientId ? 'Edit client details' : 'Create new client');
|
||||
if (clientId > 0) {
|
||||
loadClientDetails(clientId);
|
||||
}
|
||||
});
|
||||
}).trigger('change');
|
||||
|
||||
//enableHoverClick($('.combobox-container input.form-control'), $('.combobox-container input[name=client]'), '{{ URL::to('clients') }}');
|
||||
|
||||
@if ($client)
|
||||
@ -296,7 +307,7 @@
|
||||
$('#invoice_number').change(refreshPDF);
|
||||
|
||||
$('#actionDropDown > button:first').click(function() {
|
||||
onDownloadClick();
|
||||
onSaveClick();
|
||||
});
|
||||
|
||||
|
||||
@ -305,24 +316,46 @@
|
||||
|
||||
@if ($invoice && $invoice->isRecurring())
|
||||
$('#recurring').prop('checked', true);
|
||||
@elseif ($invoice && $invoice->isSent())
|
||||
$('#recurring_checkbox').hide();
|
||||
@elseif (isset($invoice->recurring_invoice_id) && $invoice->recurring_invoice_id)
|
||||
$('#recurring_checkbox > div > div').html('Created by a {{ link_to('/invoices/'.$invoice->recurring_invoice_id, 'recurring invoice') }}').css('padding-top','6px');
|
||||
@elseif ($invoice && $invoice->isSent())
|
||||
$('#recurring_checkbox').hide();
|
||||
@endif
|
||||
|
||||
toggleRecurring();
|
||||
toggleRecurring();
|
||||
|
||||
applyComboboxListeners();
|
||||
refreshPDF();
|
||||
});
|
||||
|
||||
function showCreateNew() {
|
||||
if ($('input[name=client]').val() != '-1') {
|
||||
function loadClientDetails(clientId) {
|
||||
var client = clientMap[clientId];
|
||||
$('#name').val(client.name);
|
||||
$('#work_phone').val(client.work_phone);
|
||||
$('#address1').val(client.address1);
|
||||
$('#address2').val(client.address2);
|
||||
$('#city').val(client.city);
|
||||
$('#state').val(client.state);
|
||||
$('#postal_code').val(client.postal_code);
|
||||
$('#country_id').val(client.country_id).combobox('refresh');
|
||||
for (var i=0; i<client.contacts.length; i++) {
|
||||
var contact = client.contacts[i];
|
||||
if (contact.is_primary) {
|
||||
$('#first_name').val(contact.first_name);
|
||||
$('#last_name').val(contact.last_name);
|
||||
$('#email').val(contact.email);
|
||||
$('#phone').val(contact.phone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showCreateNew() {
|
||||
if (!$('input[name=client]').val()) {
|
||||
$('#myModal input').val('');
|
||||
$('#myModal #country_id').val('');
|
||||
$('#nameError').css( "display", "none" );
|
||||
}
|
||||
}
|
||||
|
||||
$('#myModal').modal('show');
|
||||
}
|
||||
|
||||
@ -357,6 +390,8 @@
|
||||
var invoice = {
|
||||
invoice_number: $('#invoice_number').val(),
|
||||
invoice_date: $('#invoice_date').val(),
|
||||
discount: parseFloat($('#discount').val()),
|
||||
po_number: $('#po_number').val(),
|
||||
account: {
|
||||
name: "{{ $account->name }}",
|
||||
address1: "{{ $account->address1 }}",
|
||||
@ -376,8 +411,20 @@
|
||||
invoice_items: []
|
||||
};
|
||||
|
||||
var clientId = $('input[name=client]').val();
|
||||
|
||||
var client = {
|
||||
name: $('#name').val(),
|
||||
address1: $('#address1').val(),
|
||||
address2: $('#address2').val(),
|
||||
city: $('#city').val(),
|
||||
state: $('#state').val(),
|
||||
postal_code: $('#postal_code').val(),
|
||||
country: {
|
||||
name: $('.country_select input[type=text]').val()
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
var clientId = $('input[name=client]').val();
|
||||
if (clientId == '-1') {
|
||||
var client = {
|
||||
name: $('#name').val(),
|
||||
@ -393,6 +440,7 @@
|
||||
} else if (clientMap.hasOwnProperty(clientId)) {
|
||||
var client = clientMap[clientId];
|
||||
}
|
||||
*/
|
||||
invoice.client = client;
|
||||
|
||||
for(var i=0; i<model.items().length; i++) {
|
||||
@ -417,10 +465,10 @@
|
||||
|
||||
function _refreshPDF() {
|
||||
var invoice = createInvoiceModel();
|
||||
var doc = generatePDF(invoice);
|
||||
var doc = generatePDF(invoice);
|
||||
|
||||
/*
|
||||
var string = doc.output('dataurlstring');
|
||||
|
||||
//console.log(string);
|
||||
var pdfAsArray = convertDataURIToBinary(string);
|
||||
PDFJS.getDocument(pdfAsArray).then(function getPdfHelloWorld(pdf) {
|
||||
|
||||
@ -428,7 +476,7 @@
|
||||
var scale = 1.5;
|
||||
var viewport = page.getViewport(scale);
|
||||
|
||||
var canvas = document.getElementById('the-canvas');
|
||||
var canvas = document.getElementById('theCanvas');
|
||||
var context = canvas.getContext('2d');
|
||||
canvas.height = viewport.height;
|
||||
canvas.width = viewport.width;
|
||||
@ -436,8 +484,10 @@
|
||||
page.render({canvasContext: context, viewport: viewport});
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
//$('iframe').attr('src', string);
|
||||
var string = doc.output('datauristring');
|
||||
$('#theIFrame').attr('src', string);
|
||||
}
|
||||
|
||||
function onDownloadClick() {
|
||||
@ -453,6 +503,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
function onSaveClick() {
|
||||
$('.main_form').submit();
|
||||
}
|
||||
|
||||
function onCloneClick() {
|
||||
$('#action').val('clone');
|
||||
$('.main_form').submit();
|
||||
}
|
||||
|
||||
function onArchiveClick() {
|
||||
$('#action').val('archive');
|
||||
$('.main_form').submit();
|
||||
@ -471,7 +530,9 @@
|
||||
if (!name) $('#nameError').css( "display", "inline" );
|
||||
} else {
|
||||
$('select#client').combobox('setSelected');
|
||||
$('input[name=client]').val('-1');
|
||||
if (!$('input[name=client]').val()) {
|
||||
$('input[name=client]').val('-1');
|
||||
}
|
||||
$('.client_select input.form-control').val(name);
|
||||
$('.client_select .combobox-container').addClass('combobox-selected');
|
||||
|
||||
@ -556,7 +617,7 @@
|
||||
this.total = ko.computed(function() {
|
||||
var total = self.rawSubtotal();
|
||||
|
||||
var discount = parseInt(self.discount());
|
||||
var discount = parseFloat(self.discount());
|
||||
if (discount > 0) {
|
||||
total = total * ((100 - discount)/100);
|
||||
}
|
||||
|
@ -18,14 +18,16 @@
|
||||
, array('id'=>'archive'))->split(); }}
|
||||
|
||||
|
||||
{{ Button::primary_link(URL::to($entityType . 's/create'), 'New ' . Utils::getEntityName($entityType), array('class' => 'pull-right')) }}
|
||||
|
||||
<div id="top_right_buttons" class="pull-right">
|
||||
<input id="tableFilter" type="text" style="width:140px;margin-right:4px" class="form-control pull-left" placeholder="Filter"/>
|
||||
{{ Button::primary_link(URL::to($entityType . 's/create'), 'New ' . Utils::getEntityName($entityType), array('class' => 'pull-right')) }}
|
||||
</div>
|
||||
|
||||
@if (isset($secEntityType))
|
||||
{{ Datatable::table()
|
||||
->addColumn($secColumns)
|
||||
->setUrl(route('api.' . $secEntityType . 's'))
|
||||
->setOptions('sPaginationType', 'bootstrap')
|
||||
->setOptions('bFilter', false)
|
||||
->render('datatable') }}
|
||||
@endif
|
||||
|
||||
@ -33,7 +35,6 @@
|
||||
->addColumn($columns)
|
||||
->setUrl(route('api.' . $entityType . 's'))
|
||||
->setOptions('sPaginationType', 'bootstrap')
|
||||
->setOptions('bFilter', false)
|
||||
->render('datatable') }}
|
||||
|
||||
{{ Former::close() }}
|
||||
@ -46,6 +47,7 @@
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$('#action').val(action);
|
||||
$('form.listForm').submit();
|
||||
}
|
||||
@ -67,8 +69,36 @@
|
||||
@stop
|
||||
|
||||
@section('onReady')
|
||||
|
||||
|
||||
var tableFilter = '';
|
||||
var searchTimeout = false;
|
||||
|
||||
var oTable0 = $('#DataTables_Table_0').dataTable();
|
||||
var oTable1 = $('#DataTables_Table_1').dataTable();
|
||||
function filterTable(val) {
|
||||
if (val == tableFilter) {
|
||||
return;
|
||||
}
|
||||
tableFilter = val;
|
||||
oTable0.fnFilter(val);
|
||||
@if (isset($secEntityType))
|
||||
oTable1.fnFilter(val);
|
||||
@endif
|
||||
}
|
||||
|
||||
$('#tableFilter').on('keyup', function(){
|
||||
if (searchTimeout) {
|
||||
window.clearTimeout(searchTimeout);
|
||||
}
|
||||
|
||||
searchTimeout = setTimeout(function() {
|
||||
filterTable($('#tableFilter').val());
|
||||
}, 1000);
|
||||
})
|
||||
|
||||
window.onDatatableReady = function() {
|
||||
console.log('data loaded');
|
||||
|
||||
$(':checkbox').click(function() {
|
||||
setArchiveEnabled();
|
||||
});
|
||||
@ -90,6 +120,7 @@
|
||||
$dropdown.css('visibility','hidden');
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
$('#archive > button').prop('disabled', true);
|
||||
|
9
public/js/bootstrap-combobox.js
vendored
9
public/js/bootstrap-combobox.js
vendored
@ -102,9 +102,12 @@
|
||||
|
||||
, select: function () {
|
||||
var val = this.$menu.find('.active').attr('data-value');
|
||||
this.$element.val(this.updater(val)).trigger('change');
|
||||
this.$target.val(this.map[val]).trigger('change');
|
||||
this.$source.val(this.map[val]).trigger('change');
|
||||
this.$element.val(this.updater(val));
|
||||
this.$target.val(this.map[val]);
|
||||
this.$source.val(this.map[val]);
|
||||
this.$element.trigger('change');
|
||||
this.$target.trigger('change');
|
||||
this.$source.trigger('change');
|
||||
this.$container.addClass('combobox-selected');
|
||||
this.selected = true;
|
||||
return this.hide();
|
||||
|
@ -1,5 +1,4 @@
|
||||
function generatePDF(invoice) {
|
||||
|
||||
var invoiceNumber = invoice.invoice_number;
|
||||
var issuedOn = invoice.invoice_date;
|
||||
var amount = '$0.00';
|
||||
@ -9,7 +8,7 @@ function generatePDF(invoice) {
|
||||
var headerLeft = 360;
|
||||
var headerRight = 540;
|
||||
var rowHeight = 15;
|
||||
var footerLeft = 450;
|
||||
var footerLeft = 420;
|
||||
|
||||
var tableTop = 240;
|
||||
var tableLeft = 60;
|
||||
@ -30,10 +29,18 @@ function generatePDF(invoice) {
|
||||
/* table header */
|
||||
doc.setDrawColor(200,200,200);
|
||||
doc.setFillColor(230,230,230);
|
||||
doc.rect(headerLeft - 6, headerTop + rowHeight + 4, headerRight - headerLeft + 12, rowHeight + 2, 'FD');
|
||||
var x1 = headerLeft - 6;
|
||||
var y1 = headerTop + rowHeight + 4;
|
||||
var x2 = headerRight - headerLeft + 12;
|
||||
var y2 = rowHeight + 2;
|
||||
if (invoice.po_number) {
|
||||
y1 += rowHeight;
|
||||
}
|
||||
doc.rect(x1, y1, x2, y2, 'FD');
|
||||
|
||||
var invoiceNumberX = headerRight - (doc.getStringUnitWidth(invoiceNumber) * doc.internal.getFontSize());
|
||||
var issuedOnX = headerRight - (doc.getStringUnitWidth(issuedOn) * doc.internal.getFontSize());
|
||||
var poNumberX = headerRight - (doc.getStringUnitWidth(invoice.po_number) * doc.internal.getFontSize());
|
||||
|
||||
doc.setFontType("normal");
|
||||
if (invoice.client) {
|
||||
@ -55,13 +62,23 @@ function generatePDF(invoice) {
|
||||
}
|
||||
}
|
||||
|
||||
doc.text(headerLeft, headerTop, 'Invoice #');
|
||||
doc.text(invoiceNumberX, headerTop, invoiceNumber);
|
||||
doc.text(headerLeft, headerTop + rowHeight, 'Invoice Date');
|
||||
doc.text(issuedOnX, headerTop + rowHeight, issuedOn);
|
||||
var headerY = headerTop;
|
||||
doc.text(headerLeft, headerY, 'Invoice #');
|
||||
doc.text(invoiceNumberX, headerY, invoiceNumber);
|
||||
|
||||
if (invoice.po_number) {
|
||||
headerY += rowHeight;
|
||||
doc.text(headerLeft, headerY, 'PO Number');
|
||||
doc.text(poNumberX, headerY, invoice.po_number);
|
||||
}
|
||||
|
||||
headerY += rowHeight;
|
||||
doc.text(headerLeft, headerY, 'Invoice Date');
|
||||
doc.text(issuedOnX, headerY, issuedOn);
|
||||
|
||||
headerY += rowHeight;
|
||||
doc.setFontType("bold");
|
||||
doc.text(headerLeft, headerTop + (2 * rowHeight), 'Amount Due');
|
||||
doc.text(headerLeft, headerY, 'Amount Due');
|
||||
|
||||
doc.setDrawColor(200,200,200);
|
||||
doc.setFillColor(230,230,230);
|
||||
@ -122,6 +139,21 @@ function generatePDF(invoice) {
|
||||
var x = tableTop + (line * rowHeight);
|
||||
doc.lines([[0,0],[headerRight-tableLeft+5,0]],tableLeft - 8, x);
|
||||
|
||||
if (invoice.discount > 0) {
|
||||
x += 16;
|
||||
doc.text(footerLeft, x, 'Subtotal');
|
||||
var total = formatNumber(total);
|
||||
var totalX = headerRight - (doc.getStringUnitWidth(total) * doc.internal.getFontSize());
|
||||
doc.text(totalX, x, total);
|
||||
|
||||
x += 16;
|
||||
doc.text(footerLeft, x, 'Discount');
|
||||
var discount = formatNumber(total * (invoice.discount/100));
|
||||
total -= discount;
|
||||
var discountX = headerRight - (doc.getStringUnitWidth(discount) * doc.internal.getFontSize());
|
||||
doc.text(discountX, x, discount);
|
||||
}
|
||||
|
||||
x += 16;
|
||||
doc.setFontType("bold");
|
||||
doc.text(footerLeft, x, 'Total');
|
||||
@ -131,9 +163,10 @@ function generatePDF(invoice) {
|
||||
doc.text(totalX, x, total);
|
||||
|
||||
totalX = headerRight - (doc.getStringUnitWidth(total) * doc.internal.getFontSize());
|
||||
doc.text(totalX, headerTop + (2 * rowHeight), total);
|
||||
doc.text(totalX, headerY, total);
|
||||
|
||||
/* payment stub */
|
||||
/*
|
||||
var y = 680;
|
||||
doc.lines([[0,0],[headerRight-tableLeft+5,0]],tableLeft - 8, y - 30);
|
||||
doc.setFontSize(20);
|
||||
@ -191,7 +224,8 @@ function generatePDF(invoice) {
|
||||
y += 16;
|
||||
doc.setFontType("bold");
|
||||
doc.text(headerLeft, y, 'Amount Enclosed');
|
||||
|
||||
*/
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
@ -282,20 +316,18 @@ function formatMoney(num) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Set the defaults for DataTables initialisation */
|
||||
$.extend( true, $.fn.dataTable.defaults, {
|
||||
"sDom": "t<'row-fluid'<'span6'i><'span6'p>>",
|
||||
//"sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>",
|
||||
"sPaginationType": "bootstrap",
|
||||
"bProcessing": false,
|
||||
//"bProcessing": true,
|
||||
//"iDisplayLength": 50,
|
||||
"bInfo": true,
|
||||
"oLanguage": {
|
||||
//"sLengthMenu": "_MENU_ records per page"
|
||||
"sLengthMenu": "_MENU_"
|
||||
"sLengthMenu": "_MENU_",
|
||||
"sSearch": ""
|
||||
},
|
||||
//"sScrollY": "500px",
|
||||
} );
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.8 KiB |
Loading…
Reference in New Issue
Block a user