1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-09 20:52:56 +01:00

Implemented word wrapping

This commit is contained in:
Hillel Coren 2013-12-01 14:22:08 +02:00
parent 329a47e761
commit aff89cd073
11 changed files with 232 additions and 113 deletions

View File

@ -95,7 +95,7 @@ class ClientController extends \BaseController {
public function show($id)
{
$client = Client::with('contacts')->find($id);
trackViewed(Request::url(), $client->name);
trackViewed($client->name);
return View::make('clients.show')->with('client', $client);
@ -157,7 +157,9 @@ class ClientController extends \BaseController {
$client->state = Input::get('state');
$client->notes = Input::get('notes');
$client->postal_code = Input::get('postal_code');
$client->country_id = Input::get('country_id');
if (Input::get('country_id')) {
$client->country_id = Input::get('country_id');
}
$client->save();
$data = json_decode(Input::get('data'));

View File

@ -206,7 +206,7 @@ class InvoiceController extends \BaseController {
public function edit($id)
{
$invoice = Invoice::with('client', 'invoice_items')->find($id);
trackViewed(Request::url(), $invoice->invoice_number . ' - ' . $invoice->client->name);
trackViewed($invoice->invoice_number . ' - ' . $invoice->client->name);
$data = array(
'invoice' => $invoice,
@ -223,12 +223,11 @@ class InvoiceController extends \BaseController {
public function create($clientId = 0)
{
$client = null;
if ($clientId) {
$client = Client::find($clientId);
}
$invoiceNumber = Auth::user()->account->getNextInvoiceNumber();
$data = array(
'invoice' => null,
'invoiceNumber' => $invoiceNumber,
'method' => 'POST',
'url' => 'invoices',
'title' => 'New',
@ -312,22 +311,25 @@ class InvoiceController extends \BaseController {
$item->qty = 0;
}
$product = Product::findProduct($item->product_key);
if (!$product)
if ($item->product_key)
{
$product = new Product;
$product->account_id = Auth::user()->account_id;
$product->key = $item->product_key;
$product = Product::findProduct($item->product_key);
if (!$product)
{
$product = new Product;
$product->account_id = Auth::user()->account_id;
$product->key = $item->product_key;
}
$product->notes = $item->notes;
$product->cost = $item->cost;
$product->qty = $item->qty;
$product->save();
}
$product->notes = $item->notes;
$product->cost = $item->cost;
$product->qty = $item->qty;
$product->save();
$invoiceItem = new InvoiceItem;
$invoiceItem->product_id = $product->id;
$invoiceItem->product_id = isset($product) ? $product->id : null;
$invoiceItem->product_key = $item->product_key;
$invoiceItem->notes = $item->notes;
$invoiceItem->cost = $item->cost;

View File

@ -10,20 +10,41 @@ class ConfideSetupUsersTable extends Migration {
*/
public function up()
{
Schema::dropIfExists('invoice_statuses');
Schema::dropIfExists('invitations');
Schema::dropIfExists('activities');
Schema::dropIfExists('invitations');
Schema::dropIfExists('account_gateways');
Schema::dropIfExists('gateways');
Schema::dropIfExists('products');
Schema::dropIfExists('invoice_items');
Schema::dropIfExists('contacts');
Schema::dropIfExists('payments');
Schema::dropIfExists('invoice_items');
Schema::dropIfExists('products');
Schema::dropIfExists('contacts');
Schema::dropIfExists('invoices');
Schema::dropIfExists('accounts');
Schema::dropIfExists('users');
Schema::dropIfExists('password_reminders');
Schema::dropIfExists('clients');
Schema::dropIfExists('accounts');
Schema::dropIfExists('invoice_statuses');
Schema::dropIfExists('countries');
Schema::create('countries', function($table)
{
$table->increments('id');
$table->string('capital', 255)->nullable();
$table->string('citizenship', 255)->nullable();
$table->string('country_code', 3)->default('');
$table->string('currency', 255)->nullable();
$table->string('currency_code', 255)->nullable();
$table->string('currency_sub_unit', 255)->nullable();
$table->string('full_name', 255)->nullable();
$table->string('iso_3166_2', 2)->default('');
$table->string('iso_3166_3', 3)->default('');
$table->string('name', 255)->default('');
$table->string('region_code', 3)->default('');
$table->string('sub_region_code', 3)->default('');
$table->boolean('eea')->default(0);
});
Schema::create('accounts', function($t)
{
@ -41,7 +62,9 @@ class ConfideSetupUsersTable extends Migration {
$t->string('city');
$t->string('state');
$t->string('postal_code');
$t->integer('country_id');
$t->unsignedInteger('country_id')->nullable();
$t->foreign('country_id')->references('id')->on('countries');
});
@ -59,18 +82,21 @@ class ConfideSetupUsersTable extends Migration {
Schema::create('account_gateways', function($t)
{
$t->increments('id');
$t->integer('account_id');
$t->integer('gateway_id');
$t->unsignedInteger('account_id');
$t->unsignedInteger('gateway_id');
$t->timestamps();
$t->softDeletes();
$t->text('config');
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$t->foreign('gateway_id')->references('id')->on('gateways');
});
Schema::create('users', function($t)
{
$t->increments('id');
$t->integer('account_id');
$t->unsignedInteger('account_id');
$t->timestamps();
$t->softDeletes();
@ -84,7 +110,7 @@ class ConfideSetupUsersTable extends Migration {
$t->boolean('is_guest')->default(true);
$t->boolean('confirmed')->default(false);
//$t->foreign('account_id')->references('id')->on('accounts');
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
});
Schema::create('password_reminders', function($t)
@ -98,7 +124,8 @@ class ConfideSetupUsersTable extends Migration {
Schema::create('clients', function($t)
{
$t->increments('id');
$t->integer('account_id');
$t->unsignedInteger('account_id');
$t->unsignedInteger('country_id')->nullable();
$t->timestamps();
$t->softDeletes();
@ -108,17 +135,18 @@ class ConfideSetupUsersTable extends Migration {
$t->string('city');
$t->string('state');
$t->string('postal_code');
$t->integer('country_id');
$t->string('work_phone');
$t->text('notes');
$t->decimal('balance', 10, 2);
//$t->foreign('account_id')->references('id')->on('accounts');
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$t->foreign('country_id')->references('id')->on('countries');
});
Schema::create('contacts', function($t)
{
$t->increments('id');
$t->integer('client_id');
$t->unsignedInteger('client_id');
$t->timestamps();
$t->softDeletes();
@ -128,27 +156,9 @@ class ConfideSetupUsersTable extends Migration {
$t->string('phone');
$t->timestamp('last_login');
//$t->foreign('account_id')->references('id')->on('accounts');
$t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
});
Schema::create('invoices', function($t)
{
$t->increments('id');
$t->integer('client_id');
$t->integer('account_id');
$t->integer('invoice_status_id')->default(1);
$t->timestamps();
$t->softDeletes();
$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('invoice_statuses', function($t)
{
$t->increments('id');
@ -156,37 +166,45 @@ class ConfideSetupUsersTable extends Migration {
});
Schema::create('invoices', function($t)
{
$t->increments('id');
$t->unsignedInteger('client_id');
$t->unsignedInteger('account_id');
$t->unsignedInteger('invoice_status_id')->default(1);
$t->timestamps();
$t->softDeletes();
$t->string('invoice_number');
$t->float('discount');
$t->date('invoice_date');
$t->date('due_date');
$t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
$t->foreign('account_id')->references('id')->on('accounts');
$t->foreign('invoice_status_id')->references('id')->on('invoice_statuses');
});
Schema::create('invitations', function($t)
{
$t->increments('id');
$t->integer('user_id');
$t->integer('contact_id');
$t->integer('invoice_id');
$t->unsignedInteger('user_id');
$t->unsignedInteger('contact_id');
$t->unsignedInteger('invoice_id');
$t->string('key')->unique();
$t->timestamps();
$t->softDeletes();
});
Schema::create('invoice_items', function($t)
{
$t->increments('id');
$t->integer('invoice_id');
$t->timestamps();
$t->softDeletes();
$t->integer('product_id');
$t->string('product_key');
$t->string('notes');
$t->decimal('cost', 8, 2);
$t->integer('qty');
//$t->foreign('account_id')->references('id')->on('accounts');
$t->foreign('user_id')->references('id')->on('users');
$t->foreign('contact_id')->references('id')->on('contacts');
$t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
});
Schema::create('products', function($t)
{
$t->increments('id');
$t->integer('account_id');
$t->unsignedInteger('account_id');
$t->timestamps();
$t->softDeletes();
@ -195,17 +213,35 @@ class ConfideSetupUsersTable extends Migration {
$t->decimal('cost', 8, 2);
$t->integer('qty');
//$t->foreign('account_id')->references('id')->on('accounts');
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
});
Schema::create('invoice_items', function($t)
{
$t->increments('id');
$t->unsignedInteger('invoice_id');
$t->unsignedInteger('product_id')->nullable();
$t->timestamps();
$t->softDeletes();
$t->string('product_key');
$t->string('notes');
$t->decimal('cost', 8, 2);
$t->integer('qty');
$t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
$t->foreign('product_id')->references('id')->on('products');
});
Schema::create('payments', function($t)
{
$t->increments('id');
$t->integer('invoice_id');
$t->integer('account_id');
$t->integer('client_id');
$t->integer('contact_id');
$t->integer('user_id');
$t->unsignedInteger('invoice_id');
$t->unsignedInteger('account_id');
$t->unsignedInteger('client_id')->nullable();
$t->unsignedInteger('contact_id')->nullable();
$t->unsignedInteger('user_id');
$t->timestamps();
$t->softDeletes();
@ -213,19 +249,23 @@ class ConfideSetupUsersTable extends Migration {
$t->string('transaction_reference');
$t->string('payer_id');
//$t->foreign('account_id')->references('id')->on('accounts');
$t->foreign('invoice_id')->references('id')->on('invoices');
$t->foreign('account_id')->references('id')->on('accounts');
$t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
$t->foreign('contact_id')->references('id')->on('contacts');
$t->foreign('user_id')->references('id')->on('users');
});
Schema::create('activities', function($t)
{
$t->increments('id');
$t->integer('account_id');
$t->integer('user_id');
$t->integer('client_id');
$t->integer('contact_id');
$t->integer('invoice_id');
$t->integer('payment_id');
$t->integer('invitation_id');
$t->unsignedInteger('account_id');
$t->unsignedInteger('client_id');
$t->unsignedInteger('user_id')->nullable();
$t->unsignedInteger('contact_id')->nullable();
$t->unsignedInteger('invoice_id')->nullable();
$t->unsignedInteger('payment_id')->nullable();
$t->unsignedInteger('invitation_id')->nullable();
$t->timestamps();
$t->integer('activity_type_id');
@ -240,20 +280,21 @@ class ConfideSetupUsersTable extends Migration {
*/
public function down()
{
Schema::dropIfExists('invoice_statuses');
Schema::dropIfExists('invitations');
Schema::dropIfExists('activities');
Schema::dropIfExists('invitations');
Schema::dropIfExists('account_gateways');
Schema::dropIfExists('gateways');
Schema::dropIfExists('products');
Schema::dropIfExists('invoice_items');
Schema::dropIfExists('contacts');
Schema::dropIfExists('payments');
Schema::dropIfExists('invoice_items');
Schema::dropIfExists('products');
Schema::dropIfExists('contacts');
Schema::dropIfExists('invoices');
Schema::dropIfExists('clients');
Schema::dropIfExists('password_reminders');
Schema::dropIfExists('users');
Schema::dropIfExists('password_reminders');
Schema::dropIfExists('clients');
Schema::dropIfExists('accounts');
}
Schema::dropIfExists('invoice_statuses');
Schema::dropIfExists('countries');
}
}

View File

@ -11,6 +11,7 @@ class SetupCountriesTable extends Migration {
public function up()
{
// Creates the users table
/*
Schema::create('countries', function($table)
{
$table->integer('id')->index();
@ -30,6 +31,7 @@ class SetupCountriesTable extends Migration {
$table->primary('id');
});
*/
}
/**
@ -39,7 +41,7 @@ class SetupCountriesTable extends Migration {
*/
public function down()
{
Schema::drop('countries');
//Schema::drop('countries');
}
}
}

View File

@ -31,7 +31,6 @@ class ConstantsSeeder extends Seeder
$client->invoices()->save($invoice);
*/
InvoiceStatus::create(array('name' => 'Draft'));
InvoiceStatus::create(array('name' => 'Sent'));
InvoiceStatus::create(array('name' => 'Viewed'));

View File

@ -14,6 +14,11 @@ class Account extends Eloquent
return $this->hasMany('Client');
}
public function invoices()
{
return $this->hasMany('Invoice');
}
public function account_gateways()
{
return $this->hasMany('AccountGateway');
@ -60,4 +65,19 @@ class Account extends Eloquent
list($width, $height) = getimagesize($this->getLogoPath());
return $height;
}
public function getNextInvoiceNumber()
{
$order = $this->invoices()->orderBy('invoice_number', 'DESC')->first();
if ($order)
{
$number = intval($order->invoice_number) + 1;
return str_pad($number, 5, "0", STR_PAD_LEFT);
}
else
{
return DEFAULT_INVOICE_NUMBER;
}
}
}

View File

@ -91,7 +91,6 @@ class Client extends Eloquent
return $this->created_at->format('m/d/y h:i a');
}
}
}
Client::created(function($client)

View File

@ -143,8 +143,9 @@ function processedRequest($url)
function trackViewed($url, $name)
function trackViewed($name)
{
$url = Request::url();
$viewed = Session::get(RECENTLY_VIEWED);
if (!$viewed)
@ -168,7 +169,7 @@ function trackViewed($url, $name)
array_unshift($viewed, $object);
if (count($viewed) > 5)
if (count($viewed) > RECENTLY_VIEWED_LIMIT)
{
array_pop($viewed);
}
@ -190,4 +191,8 @@ define("ACCOUNT_DETAILS", "details");
define("ACCOUNT_SETTINGS", "settings");
define("ACCOUNT_IMPORT", "import");
define("ACCOUNT_MAP", "import_map");
define("ACCOUNT_EXPORT", "export");
define("ACCOUNT_EXPORT", "export");
define("DEFAULT_INVOICE_NUMBER", "00001");
define("RECENTLY_VIEWED_LIMIT", 8);

View File

@ -27,9 +27,9 @@
</div>
<div class="col-md-6">
<h3>Balance</h3>
<h3>Standing</h3>
<h3>$0.00 <small>Paid to Date USD</small></h3>
<h3>$0.00 <small>Outstanding USD</small></h3>
<h3>$0.00 <small>Balance USD</small></h3>
</div>
</div>

View File

@ -267,7 +267,9 @@
<li><a href="#">No items</a></li>
@else
@foreach (Session::get(RECENTLY_VIEWED) as $link)
@if (Request::url() != $link->url)
<li><a href="{{ $link->url }}">{{ $link->name }}</a></li>
@endif
@endforeach
@endif
</ul>

View File

@ -6,7 +6,8 @@
{{ Former::open($url)->method($method)->addClass('main_form')->rules(array(
'invoice_number' => 'required',
'invoice_date' => 'required'
'invoice_date' => 'required',
'product_key' => 'max:14',
)); }}
<!-- <h3>{{ $title }} Invoice</h3> -->
@ -16,6 +17,7 @@
{{ Former::populateField('invoice_date', fromSqlDate($invoice->invoice_date)); }}
{{ Former::populateField('due_date', fromSqlDate($invoice->due_date)); }}
@else
{{ Former::populateField('invoice_number', $invoiceNumber) }}
{{ Former::populateField('invoice_date', date('m/d/Y')) }}
@endif
@ -54,18 +56,18 @@
<!-- <i data-bind="click: $parent.addItem, visible: actionsVisible" class="fa fa-plus-circle" style="cursor:pointer" title="Add item"></i>&nbsp; -->
<i data-bind="visible: actionsVisible" class="fa fa-sort"></i>
</td>
<td style="width:120px">
{{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'key')
<td style="width:120px">
{{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'key')->onkeyup('onChange()')
->raw()->data_bind("value: product_key, valueUpdate: 'afterkeydown'")->addClass('datalist') }}
</td>
<td style="width:300px">
<textarea data-bind="value: notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" class="form-control" onchange="refreshPDF()"></textarea>
<textarea onkeyup="checkWordWrap(event)" data-bind="value: notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" style="resize: none;" class="form-control" onchange="refreshPDF()"></textarea>
</td>
<td style="width:100px">
<input data-bind="value: cost, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
<input onkeyup="onChange()" data-bind="value: cost, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
</td>
<td style="width:80px">
<input data-bind="value: qty, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
<input onkeyup="onChange()" data-bind="value: qty, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
</td>
<!--
<td style="width:100px">
@ -93,9 +95,7 @@
</tr>
<tr>
<td class="hide-border"></td>
<td colspan="2" class="hide-border">
<a href="#" onclick="model.addItem()">Add line item</a>
</td>
<td colspan="2"/>
<td colspan="2"><b>Invoice Total</b></td>
<td style="text-align: right"><span data-bind="text: total"/></td>
</tr>
@ -221,7 +221,6 @@
var product = products[i];
if (product.key == key) {
var model = ko.dataFor(this);
console.log(model);
model.notes(product.notes);
model.cost(product.cost);
model.qty(product.qty);
@ -434,6 +433,54 @@
this.showActions = function() {
this.actionsVisible(true);
}
this.isEmpty = function() {
return !self.product_key() && !self.notes() && !self.cost() && !self.qty() && !self.tax();
}
}
function checkWordWrap(event)
{
var doc = new jsPDF('p', 'pt');
doc.setFont('Helvetica','');
doc.setFontSize(10);
var $textarea = $(event.target || event.srcElement);
var lines = $textarea.val().split("\n");
for (var i = 0; i < lines.length; i++) {
var numLines = doc.splitTextToSize(lines[i], 200).length;
if (numLines <= 1) continue;
var j = 0; space = lines[i].length;
while (j++ < lines[i].length) {
if (lines[i].charAt(j) === " ") space = j;
}
lines[i + 1] = lines[i].substring(space + 1) + (lines[i + 1] || "");
lines[i] = lines[i].substring(0, space);
}
var val = lines.slice(0, 6).join("\n");
if (val != $textarea.val())
{
var model = ko.dataFor($textarea[0]);
model.notes(val);
refreshPDF();
}
$textarea.height(val.split('\n').length * 22);
onChange();
}
function onChange()
{
var hasEmpty = false;
for(var i=0; i<model.items().length; i++) {
var item = model.items()[i];
if (item.isEmpty()) {
hasEmpty = true;
}
}
if (!hasEmpty) {
model.addItem();
}
}
var products = {{ $products }};