1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-08 12:12:48 +01:00

Creating re-usable products from invoice line items

This commit is contained in:
vagrant 2013-11-27 07:38:37 +00:00
parent 7b41fbc779
commit 426e7838c9
10 changed files with 91 additions and 28 deletions

0
LICENSE Normal file → Executable file
View File

0
README.md Normal file → Executable file
View File

View File

@ -42,7 +42,7 @@ class InvoiceController extends \BaseController {
$invoice = Invoice::with('invoice_items', 'client.account.account_gateways')->where('invoice_key', '=', $invoiceKey)->firstOrFail();
$contact = null;
Activity::viewInvoice($invoice, $contact)
Activity::viewInvoice($invoice, $contact);
return View::make('invoices.view')->with('invoice', $invoice);
}
@ -181,6 +181,7 @@ class InvoiceController extends \BaseController {
'title' => 'New',
'client' => $client,
'account' => Auth::user()->account,
'products' => Product::getProducts()->get(),
'clients' => Client::where('account_id','=',Auth::user()->account_id)->get());
return View::make('invoices.edit', $data);
}
@ -241,7 +242,7 @@ class InvoiceController extends \BaseController {
$invoice->client_id = $clientId;
$invoice->number = Input::get('number');
$invoice->discount = Input::get('discount');
$invoice->discount = 0;
$invoice->issued_on = $date->format('Y-m-d');
$invoice->save();
@ -252,11 +253,17 @@ class InvoiceController extends \BaseController {
continue;
}
$product = new Product;
$product->product_key = $item->product_key;
$product->notes = $item->notes;
$product->cost = $item->cost;
$product->save();
$product = Product::findProduct($item->product_key);
if (!$product)
{
$product = new Product;
$product->account_id = Auth::user()->account_id;
$product->product_key = $item->product_key;
$product->notes = $item->notes;
$product->cost = $item->cost;
$product->save();
}
$invoiceItem = new InvoiceItem;
$invoiceItem->product_id = $product->id;
@ -316,6 +323,7 @@ class InvoiceController extends \BaseController {
'url' => 'invoices/' . $id,
'title' => 'Edit',
'account' => Auth::user()->account,
'products' => Product::getProducts()->get(),
'client' => $invoice->client,
'clients' => Client::where('account_id','=',Auth::user()->account_id)->get());
return View::make('invoices.edit', $data);

View File

@ -18,7 +18,7 @@ class Activity extends Eloquent
$activity->user_id = $user->id;
$activity->account_id = $user->account_id;
return $user;
return $activity;
}
public static function createClient($client)
@ -26,7 +26,7 @@ class Activity extends Eloquent
$activity = Activity::getBlank();
$activity->client_id = $client->id;
$activity->activity_type_id = ACTIVITY_TYPE_CREATE_CLIENT;
$activity->message = $user->getFullName() . ' created client ' . $client->name;
$activity->message = Auth::user()->getFullName() . ' created client ' . $client->name;
$activity->save();
}
@ -35,7 +35,7 @@ class Activity extends Eloquent
$activity = Activity::getBlank();
$activity->client_id = $client->id;
$activity->activity_type_id = ACTIVITY_TYPE_ARCHIVE_CLIENT;
$activity->message = $user->getFullName() . ' archived client ' . $client->name;
$activity->message = Auth::user()->getFullName() . ' archived client ' . $client->name;
$activity->save();
}
@ -45,7 +45,7 @@ class Activity extends Eloquent
$activity->invoice_id = $invoice->id;
$activity->client_id = $invoice->client_id;
$activity->activity_type_id = ACTIVITY_TYPE_CREATE_INVOICE;
$activity->message = $user->getFullName() . ' created invoice ' . $invoice->number;
$activity->message = Auth::user()->getFullName() . ' created invoice ' . $invoice->number;
$activity->save();
}
@ -55,7 +55,7 @@ class Activity extends Eloquent
$activity->invoice_id = $invoice->id;
$activity->client_id = $invoice->client_id;
$activity->activity_type_id = ACTIVITY_TYPE_ARCHIVE_INVOICE;
$activity->message = $user->getFullName() . ' archived invoice ' . $invoice->number;
$activity->message = Auth::user()->getFullName() . ' archived invoice ' . $invoice->number;
$activity->save();
}
@ -65,7 +65,7 @@ class Activity extends Eloquent
$activity->invoice_id = $invoice->id;
$activity->client_id = $invoice->client_id;
$activity->activity_type_id = ACTIVITY_TYPE_EMAIL_INVOICE;
$activity->message = $user->getFullName() . ' emailed invoice ' . $invoice->number . ' to ' . $contact->getFullName();
$activity->message = Auth::user()->getFullName() . ' emailed invoice ' . $invoice->number . ' to ' . $contact->getFullName();
$activity->save();
}
@ -74,7 +74,7 @@ class Activity extends Eloquent
if (Auth::check())
{
$activity = Activity::getBlank();
$activity->message = $user->getFullName() . ' created invoice ' . $payment->transaction_reference;
$activity->message = Auth::user()->getFullName() . ' created invoice ' . $payment->transaction_reference;
}
else
{
@ -96,7 +96,7 @@ class Activity extends Eloquent
$activity->invoice_id = $invoice->id;
$activity->client_id = $invoice->client_id;
$activity->activity_type_id = ACTIVITY_TYPE_ARCHIVE_PAYMENT;
$activity->message = $user->getFullName() . ' archived payment ' . $invoice->number;
$activity->message = Auth::user()->getFullName() . ' archived payment ' . $invoice->number;
$activity->save();
}

View File

@ -3,4 +3,22 @@
class Product extends Eloquent
{
protected $softDelete = true;
public static function getProducts()
{
return Product::where('account_id','=',Auth::user()->account_id);
}
public static function findProduct($key)
{
return Product::getProducts()->where('product_key','=',$key)->first();
}
public static function getProductKeys($products)
{
$products = array_pluck($products, 'product_key');
$products = array_combine($products, $products);
return $products;
}
}

View File

@ -97,6 +97,10 @@ function toArray($data)
return json_decode(json_encode((array) $data), true);
}
define("ENV_DEVELOPMENT", "local");
define("ENV_STAGING", "staging");
define("ENV_PRODUCTION", "production");
define("ACCOUNT_DETAILS", "details");
define("ACCOUNT_SETTINGS", "settings");
define("ACCOUNT_IMPORT", "import");

View File

@ -197,7 +197,7 @@
}
.invoice-table td {
padding: 0px !important;
padding: 2px !important;
}
.invoice-table td input,
@ -225,6 +225,7 @@
<body>
@if (App::environment() != ENV_DEVELOPMENT)
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
@ -235,6 +236,8 @@
ga('send', 'pageview');
</script>
@endif
<div class="container">
<p/>

View File

@ -32,7 +32,7 @@
<p>&nbsp;</p>
<input type="text" name="items" data-bind="value: ko.toJSON(items)" style="display:none"/>
<table class="table invoice-table" style="margin-bottom: 0px !important;">
<table class="table invoice-table" style="margin-bottom: 0px !important">
<thead>
<tr>
<th class="hide-border"></th>
@ -51,23 +51,23 @@
<i data-bind="visible: actionsVisible" class="fa fa-sort"></i>
</td>
<td style="width:120px">
<input data-bind="value: product_key, valueUpdate: 'afterkeydown'" onchange="refreshPDF()"/>
{{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'product_key')->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" onchange="refreshPDF()"></textarea>
<textarea data-bind="value: notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" class="form-control" onchange="refreshPDF()"></textarea>
</td>
<td style="width:100px">
<input data-bind="value: cost, valueUpdate: 'afterkeydown'" style="text-align: right" onchange="refreshPDF()"//>
<input 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" onchange="refreshPDF()"//>
<input data-bind="value: qty, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
</td>
<!--
<td style="width:100px">
<input data-bind="value: tax, valueUpdate: 'afterkeydown'"/>
</td>
-->
<td style="width:100px;background-color: #FFFFFF;text-align: right">
<td style="width:100px;background-color: #FFFFFF;text-align: right;padding-top:9px !important">
<span data-bind="text: total"></span>
</td>
<td style="width:20px; cursor:pointer" class="hide-border">
@ -106,9 +106,8 @@
<p>&nbsp;</p>
<!-- <textarea rows="20" cols="120" id="pdfText" onkeyup="runCode()"></textarea> -->
<!-- <iframe frameborder="1" width="600" height="600" style="display:block;margin: 0 auto"></iframe> -->
<iframe frameborder="1" width="92%" height="600" style="display:block;margin: 0 auto"></iframe>
<!-- <iframe frameborder="1" width="100%" height="600" style="display:block;margin: 0 auto"></iframe> -->
<iframe frameborder="1" width="100%" height="500"></iframe>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
@ -159,6 +158,7 @@
}
*/
$(function() {
$('#issued_on').datepicker({
@ -192,10 +192,31 @@
$('#number').change(refreshPDF);
refreshPDF();
applyComboboxListeners();
refreshPDF();
});
function applyComboboxListeners() {
var value;
$('.datalist').on('focus', function() {
value = $(this).val();
}).on('blur', function() {
if (value != $(this).val()) refreshPDF();
}).on('input', function() {
var key = $(this).val();
for (var i=0; i<products.length; i++) {
var product = products[i];
if (product.product_key == key) {
var model = ko.dataFor(this);
console.log(model);
model.notes(product.notes);
model.cost(product.cost);
break;
}
}
});
}
function runCode() {
var text = $('#pdfText').val();
eval(text);
@ -317,6 +338,7 @@
self.addItem = function() {
self.items.push(new ItemModel());
applyComboboxListeners();
}
this.rawSubtotal = ko.computed(function() {
@ -389,9 +411,12 @@
}
}
var products = {{ $products }};
window.model = new InvoiceModel();
ko.applyBindings(model);
</script>

View File

@ -21,6 +21,8 @@
</head>
<body>
@if (App::environment() != ENV_DEVELOPMENT)
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
@ -29,8 +31,9 @@
ga('create', 'UA-46031341-1', 'sketch-out.com');
ga('send', 'pageview');
</script>
@endif
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">

View File

@ -302,3 +302,5 @@ function isStorageSupported() {
}
}