Bug fixes

This commit is contained in:
Hillel Coren 2015-01-11 13:56:58 +02:00
parent 0c0a71a8ed
commit 0948b46ea2
14 changed files with 662 additions and 720 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
/app/config/staging /app/config/staging
/app/config/development /app/config/development
/app/config/production
/app/config/fortrabbit /app/config/fortrabbit
/app/config/ubuntu /app/config/ubuntu
/app/config/packages/anahkiasen/rocketeer/ /app/config/packages/anahkiasen/rocketeer/

View File

@ -13,7 +13,7 @@ return array(
| |
*/ */
'debug' => false, 'debug' => true,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -38,6 +38,7 @@ class AppController extends BaseController {
$app = Input::get('app'); $app = Input::get('app');
$app['key'] = str_random(RANDOM_KEY_LENGTH); $app['key'] = str_random(RANDOM_KEY_LENGTH);
$app['debug'] = false;
$database = Input::get('database'); $database = Input::get('database');
$dbType = $database['default']; $dbType = $database['default'];

View File

@ -149,13 +149,24 @@ class Account extends Eloquent
return $prefix . str_pad($counter, 4, "0", STR_PAD_LEFT); return $prefix . str_pad($counter, 4, "0", STR_PAD_LEFT);
} }
public function incrementCounter($isQuote = false) public function incrementCounter($invoiceNumber, $isQuote = false, $isRecurring)
{ {
// check if the user modified the invoice number
if (!$isRecurring && $invoiceNumber != $this->getNextInvoiceNumber($isQuote)) {
$number = intval(preg_replace('/[^0-9]/', '', $invoiceNumber));
if ($isQuote && !$this->share_counter) {
$this->quote_number_counter = $number + 1;
} else {
$this->invoice_number_counter = $number + 1;
}
// otherwise, just increment the counter
} else {
if ($isQuote && !$this->share_counter) { if ($isQuote && !$this->share_counter) {
$this->quote_number_counter += 1; $this->quote_number_counter += 1;
} else { } else {
$this->invoice_number_counter += 1; $this->invoice_number_counter += 1;
} }
}
$this->save(); $this->save();
} }

View File

@ -222,7 +222,7 @@ class Invoice extends EntityModel
Invoice::created(function($invoice) Invoice::created(function($invoice)
{ {
$invoice->account->incrementCounter($invoice->is_quote); $invoice->account->incrementCounter($invoice->invoice_number, $invoice->is_quote, $invoice->recurring_invoice_id);
Activity::createInvoice($invoice); Activity::createInvoice($invoice);
}); });

View File

@ -4,13 +4,11 @@ use Invoice;
use Payment; use Payment;
use Contact; use Contact;
use Invitation; use Invitation;
use URL;
use Auth;
use Activity; use Activity;
use Utils; use Utils;
class ContactMailer extends Mailer { class ContactMailer extends Mailer
{
public function sendInvoice(Invoice $invoice) public function sendInvoice(Invoice $invoice)
{ {
$invoice->load('invitations', 'client', 'account'); $invoice->load('invitations', 'client', 'account');
@ -20,10 +18,11 @@ class ContactMailer extends Mailer {
$subject = trans("texts.{$entityType}_subject", ['invoice' => $invoice->invoice_number, 'account' => $invoice->account->getDisplayName()]); $subject = trans("texts.{$entityType}_subject", ['invoice' => $invoice->invoice_number, 'account' => $invoice->account->getDisplayName()]);
$accountName = $invoice->account->getDisplayName(); $accountName = $invoice->account->getDisplayName();
foreach ($invoice->invitations as $invitation) foreach ($invoice->invitations as $invitation) {
{ if (!$invitation->user || !$invitation->user->email) {
if (!$invitation->user->email) return false;
{ }
if (!$invitation->contact || $invitation->contact->email) {
return false; return false;
} }
@ -38,7 +37,7 @@ class ContactMailer extends Mailer {
'contactName' => $invitation->contact->getDisplayName(), 'contactName' => $invitation->contact->getDisplayName(),
'invoiceAmount' => Utils::formatMoney($invoice->amount, $invoice->client->currency_id), 'invoiceAmount' => Utils::formatMoney($invoice->amount, $invoice->client->currency_id),
'emailFooter' => $invoice->account->email_footer, 'emailFooter' => $invoice->account->email_footer,
'showNinjaFooter' => !$invoice->account->isPro() 'showNinjaFooter' => !$invoice->account->isPro(),
]; ];
$fromEmail = $invitation->user->email; $fromEmail = $invitation->user->email;
@ -47,8 +46,7 @@ class ContactMailer extends Mailer {
Activity::emailInvoice($invitation); Activity::emailInvoice($invitation);
} }
if (!$invoice->isSent()) if (!$invoice->isSent()) {
{
$invoice->invoice_status_id = INVOICE_STATUS_SENT; $invoice->invoice_status_id = INVOICE_STATUS_SENT;
$invoice->save(); $invoice->save();
} }
@ -67,7 +65,7 @@ class ContactMailer extends Mailer {
'clientName' => $payment->client->getDisplayName(), 'clientName' => $payment->client->getDisplayName(),
'emailFooter' => $payment->account->email_footer, 'emailFooter' => $payment->account->email_footer,
'paymentAmount' => Utils::formatMoney($payment->amount, $payment->client->currency_id), 'paymentAmount' => Utils::formatMoney($payment->amount, $payment->client->currency_id),
'showNinjaFooter' => !$payment->account->isPro() 'showNinjaFooter' => !$payment->account->isPro(),
]; ];
$user = $payment->invitation->user; $user = $payment->invitation->user;

View File

@ -11,6 +11,7 @@ class ClientRepository
->join('contacts', 'contacts.client_id', '=', 'clients.id') ->join('contacts', 'contacts.client_id', '=', 'clients.id')
->where('clients.account_id', '=', \Auth::user()->account_id) ->where('clients.account_id', '=', \Auth::user()->account_id)
->where('contacts.is_primary', '=', true) ->where('contacts.is_primary', '=', true)
->where('contacts.deleted_at', '=', null)
->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','clients.currency_id', 'clients.deleted_at', 'clients.is_deleted'); ->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','clients.currency_id', 'clients.deleted_at', 'clients.is_deleted');
if (!\Session::get('show_trash:client')) if (!\Session::get('show_trash:client'))
@ -201,6 +202,9 @@ class ClientRepository
if ($action == 'restore') if ($action == 'restore')
{ {
$client->restore(); $client->restore();
$client->is_deleted = false;
$client->save();
} }
else else
{ {

View File

@ -5,7 +5,6 @@ use InvoiceItem;
use Invitation; use Invitation;
use Product; use Product;
use Utils; use Utils;
use TaxRate;
class InvoiceRepository class InvoiceRepository
{ {
@ -22,20 +21,16 @@ class InvoiceRepository
->where('contacts.is_primary', '=', true) ->where('contacts.is_primary', '=', true)
->select('clients.public_id as client_public_id', 'invoice_number', 'invoice_status_id', 'clients.name as client_name', 'invoices.public_id', 'amount', 'invoices.balance', 'invoice_date', 'due_date', 'invoice_statuses.name as invoice_status_name', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'quote_id', 'quote_invoice_id', 'invoices.deleted_at', 'invoices.is_deleted'); ->select('clients.public_id as client_public_id', 'invoice_number', 'invoice_status_id', 'clients.name as client_name', 'invoices.public_id', 'amount', 'invoices.balance', 'invoice_date', 'due_date', 'invoice_statuses.name as invoice_status_name', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'quote_id', 'quote_invoice_id', 'invoices.deleted_at', 'invoices.is_deleted');
if (!\Session::get('show_trash:' . $entityType)) if (!\Session::get('show_trash:'.$entityType)) {
{
$query->where('invoices.deleted_at', '=', null); $query->where('invoices.deleted_at', '=', null);
} }
if ($clientPublicId) if ($clientPublicId) {
{
$query->where('clients.public_id', '=', $clientPublicId); $query->where('clients.public_id', '=', $clientPublicId);
} }
if ($filter) if ($filter) {
{ $query->where(function ($query) use ($filter) {
$query->where(function($query) use ($filter)
{
$query->where('clients.name', 'like', '%'.$filter.'%') $query->where('clients.name', 'like', '%'.$filter.'%')
->orWhere('invoices.invoice_number', 'like', '%'.$filter.'%') ->orWhere('invoices.invoice_number', 'like', '%'.$filter.'%')
->orWhere('invoice_statuses.name', 'like', '%'.$filter.'%') ->orWhere('invoice_statuses.name', 'like', '%'.$filter.'%')
@ -57,24 +52,21 @@ class InvoiceRepository
->where('invoices.account_id', '=', $accountId) ->where('invoices.account_id', '=', $accountId)
->where('invoices.is_quote', '=', false) ->where('invoices.is_quote', '=', false)
->where('clients.deleted_at', '=', null) ->where('clients.deleted_at', '=', null)
->where('contacts.deleted_at', '=', null)
->where('invoices.is_recurring', '=', true) ->where('invoices.is_recurring', '=', true)
->where('contacts.is_primary', '=', true) ->where('contacts.is_primary', '=', true)
->select('clients.public_id as client_public_id', 'clients.name as client_name', 'invoices.public_id', 'amount', 'frequencies.name as frequency', 'start_date', 'end_date', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'invoices.deleted_at', 'invoices.is_deleted'); ->select('clients.public_id as client_public_id', 'clients.name as client_name', 'invoices.public_id', 'amount', 'frequencies.name as frequency', 'start_date', 'end_date', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'invoices.deleted_at', 'invoices.is_deleted');
if ($clientPublicId) if ($clientPublicId) {
{
$query->where('clients.public_id', '=', $clientPublicId); $query->where('clients.public_id', '=', $clientPublicId);
} }
if (!\Session::get('show_trash:invoice')) if (!\Session::get('show_trash:invoice')) {
{
$query->where('invoices.deleted_at', '=', null); $query->where('invoices.deleted_at', '=', null);
} }
if ($filter) if ($filter) {
{ $query->where(function ($query) use ($filter) {
$query->where(function($query) use ($filter)
{
$query->where('clients.name', 'like', '%'.$filter.'%') $query->where('clients.name', 'like', '%'.$filter.'%')
->orWhere('invoices.invoice_number', 'like', '%'.$filter.'%'); ->orWhere('invoices.invoice_number', 'like', '%'.$filter.'%');
}); });
@ -102,8 +94,7 @@ class InvoiceRepository
->addColumn('invoice_date', function ($model) { return Utils::fromSqlDate($model->invoice_date); }) ->addColumn('invoice_date', function ($model) { return Utils::fromSqlDate($model->invoice_date); })
->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id); }); ->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id); });
if ($entityType == ENTITY_INVOICE) if ($entityType == ENTITY_INVOICE) {
{
$table->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id); }); $table->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id); });
} }
@ -119,32 +110,28 @@ class InvoiceRepository
$table = \Datatable::query($query); $table = \Datatable::query($query);
if (!$clientPublicId) if (!$clientPublicId) {
{
$table->addColumn('checkbox', function ($model) { return '<input type="checkbox" name="ids[]" value="'.$model->public_id.'" '.Utils::getEntityRowClass($model).'>'; }); $table->addColumn('checkbox', function ($model) { return '<input type="checkbox" name="ids[]" value="'.$model->public_id.'" '.Utils::getEntityRowClass($model).'>'; });
} }
$table->addColumn("invoice_number", function ($model) use ($entityType) { return link_to("{$entityType}s/".$model->public_id.'/edit', $model->invoice_number, ['class' => Utils::getEntityRowClass($model)]); }); $table->addColumn("invoice_number", function ($model) use ($entityType) { return link_to("{$entityType}s/".$model->public_id.'/edit', $model->invoice_number, ['class' => Utils::getEntityRowClass($model)]); });
if (!$clientPublicId) if (!$clientPublicId) {
{
$table->addColumn('client_name', function ($model) { return link_to('clients/'.$model->client_public_id, Utils::getClientDisplayName($model)); }); $table->addColumn('client_name', function ($model) { return link_to('clients/'.$model->client_public_id, Utils::getClientDisplayName($model)); });
} }
$table->addColumn("invoice_date", function ($model) { return Utils::fromSqlDate($model->invoice_date); }) $table->addColumn("invoice_date", function ($model) { return Utils::fromSqlDate($model->invoice_date); })
->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id); }); ->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id); });
if ($entityType == ENTITY_INVOICE) if ($entityType == ENTITY_INVOICE) {
{
$table->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id); }); $table->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id); });
} }
return $table->addColumn('due_date', function ($model) { return Utils::fromSqlDate($model->due_date); }) return $table->addColumn('due_date', function ($model) { return Utils::fromSqlDate($model->due_date); })
->addColumn('invoice_status_name', function ($model) { return $model->invoice_status_name; }) ->addColumn('invoice_status_name', function ($model) { return $model->invoice_status_name; })
->addColumn('dropdown', function($model) use ($entityType) ->addColumn('dropdown', function ($model) use ($entityType) {
{
if ($model->is_deleted) if ($model->is_deleted) {
{
return '<div style="height:38px"/>'; return '<div style="height:38px"/>';
} }
@ -154,33 +141,25 @@ class InvoiceRepository
</button> </button>
<ul class="dropdown-menu" role="menu">'; <ul class="dropdown-menu" role="menu">';
if (!$model->deleted_at || $model->deleted_at == '0000-00-00') if (!$model->deleted_at || $model->deleted_at == '0000-00-00') {
{
$str .= '<li><a href="'.\URL::to("{$entityType}s/".$model->public_id.'/edit').'">'.trans("texts.edit_{$entityType}").'</a></li> $str .= '<li><a href="'.\URL::to("{$entityType}s/".$model->public_id.'/edit').'">'.trans("texts.edit_{$entityType}").'</a></li>
<li><a href="'.\URL::to("{$entityType}s/".$model->public_id.'/clone').'">'.trans("texts.clone_{$entityType}").'</a></li> <li><a href="'.\URL::to("{$entityType}s/".$model->public_id.'/clone').'">'.trans("texts.clone_{$entityType}").'</a></li>
<li class="divider"></li>'; <li class="divider"></li>';
if ($model->invoice_status_id < INVOICE_STATUS_SENT) if ($model->invoice_status_id < INVOICE_STATUS_SENT) {
{
$str .= '<li><a href="javascript:markEntity('.$model->public_id.', '.INVOICE_STATUS_SENT.')">'.trans("texts.mark_sent").'</a></li>'; $str .= '<li><a href="javascript:markEntity('.$model->public_id.', '.INVOICE_STATUS_SENT.')">'.trans("texts.mark_sent").'</a></li>';
} }
if ($entityType == ENTITY_INVOICE) if ($entityType == ENTITY_INVOICE) {
{ if ($model->invoice_status_id < INVOICE_STATUS_PAID) {
if ($model->invoice_status_id < INVOICE_STATUS_PAID)
{
$str .= '<li><a href="'.\URL::to('payments/create/'.$model->client_public_id.'/'.$model->public_id).'">'.trans('texts.enter_payment').'</a></li>'; $str .= '<li><a href="'.\URL::to('payments/create/'.$model->client_public_id.'/'.$model->public_id).'">'.trans('texts.enter_payment').'</a></li>';
} }
if ($model->quote_id) if ($model->quote_id) {
{
$str .= '<li><a href="'.\URL::to("quotes/{$model->quote_id}/edit").'">'.trans("texts.view_quote").'</a></li>'; $str .= '<li><a href="'.\URL::to("quotes/{$model->quote_id}/edit").'">'.trans("texts.view_quote").'</a></li>';
} }
} } elseif ($entityType == ENTITY_QUOTE) {
else if ($entityType == ENTITY_QUOTE) if ($model->quote_invoice_id) {
{
if ($model->quote_invoice_id)
{
$str .= '<li><a href="'.\URL::to("invoices/{$model->quote_invoice_id}/edit").'">'.trans("texts.view_invoice").'</a></li>'; $str .= '<li><a href="'.\URL::to("invoices/{$model->quote_invoice_id}/edit").'">'.trans("texts.view_invoice").'</a></li>';
} }
} }
@ -188,9 +167,7 @@ class InvoiceRepository
$str .= '<li class="divider"></li> $str .= '<li class="divider"></li>
<li><a href="javascript:archiveEntity('.$model->public_id.')">'.trans("texts.archive_{$entityType}").'</a></li> <li><a href="javascript:archiveEntity('.$model->public_id.')">'.trans("texts.archive_{$entityType}").'</a></li>
<li><a href="javascript:deleteEntity('.$model->public_id.')">'.trans("texts.delete_{$entityType}").'</a></li>'; <li><a href="javascript:deleteEntity('.$model->public_id.')">'.trans("texts.delete_{$entityType}").'</a></li>';
} } else {
else
{
$str .= '<li><a href="javascript:restoreEntity('.$model->public_id.')">'.trans("texts.restore_{$entityType}").'</a></li> $str .= '<li><a href="javascript:restoreEntity('.$model->public_id.')">'.trans("texts.restore_{$entityType}").'</a></li>
<li><a href="javascript:deleteEntity('.$model->public_id.')">'.trans("texts.delete_{$entityType}").'</a></li>'; <li><a href="javascript:deleteEntity('.$model->public_id.')">'.trans("texts.delete_{$entityType}").'</a></li>';
} }
@ -207,8 +184,7 @@ class InvoiceRepository
$rules = ['email' => 'required|email']; $rules = ['email' => 'required|email'];
$validator = \Validator::make($contact, $rules); $validator = \Validator::make($contact, $rules);
if ($validator->fails()) if ($validator->fails()) {
{
return $validator; return $validator;
} }
@ -216,18 +192,16 @@ class InvoiceRepository
$invoiceId = isset($invoice['public_id']) && $invoice['public_id'] ? Invoice::getPrivateId($invoice['public_id']) : null; $invoiceId = isset($invoice['public_id']) && $invoice['public_id'] ? Invoice::getPrivateId($invoice['public_id']) : null;
$rules = [ $rules = [
'invoice_number' => 'required|unique:invoices,invoice_number,'.$invoiceId.',id,account_id,'.\Auth::user()->account_id, 'invoice_number' => 'required|unique:invoices,invoice_number,'.$invoiceId.',id,account_id,'.\Auth::user()->account_id,
'discount' => 'positive' 'discount' => 'positive',
]; ];
if ($invoice['is_recurring'] && $invoice['start_date'] && $invoice['end_date']) if ($invoice['is_recurring'] && $invoice['start_date'] && $invoice['end_date']) {
{
$rules['end_date'] = 'after:'.$invoice['start_date']; $rules['end_date'] = 'after:'.$invoice['start_date'];
} }
$validator = \Validator::make($invoice, $rules); $validator = \Validator::make($invoice, $rules);
if ($validator->fails()) if ($validator->fails()) {
{
return $validator; return $validator;
} }
@ -236,16 +210,12 @@ class InvoiceRepository
public function save($publicId, $data, $entityType) public function save($publicId, $data, $entityType)
{ {
if ($publicId) if ($publicId) {
{
$invoice = Invoice::scope($publicId)->firstOrFail(); $invoice = Invoice::scope($publicId)->firstOrFail();
} } else {
else
{
$invoice = Invoice::createNew(); $invoice = Invoice::createNew();
if ($entityType == ENTITY_QUOTE) if ($entityType == ENTITY_QUOTE) {
{
$invoice->is_quote = true; $invoice->is_quote = true;
} }
} }
@ -257,15 +227,12 @@ class InvoiceRepository
$invoice->is_recurring = $data['is_recurring'] && !Utils::isDemo() ? true : false; $invoice->is_recurring = $data['is_recurring'] && !Utils::isDemo() ? true : false;
$invoice->invoice_date = Utils::toSqlDate($data['invoice_date']); $invoice->invoice_date = Utils::toSqlDate($data['invoice_date']);
if ($invoice->is_recurring) if ($invoice->is_recurring) {
{
$invoice->frequency_id = $data['frequency_id'] ? $data['frequency_id'] : 0; $invoice->frequency_id = $data['frequency_id'] ? $data['frequency_id'] : 0;
$invoice->start_date = Utils::toSqlDate($data['start_date']); $invoice->start_date = Utils::toSqlDate($data['start_date']);
$invoice->end_date = Utils::toSqlDate($data['end_date']); $invoice->end_date = Utils::toSqlDate($data['end_date']);
$invoice->due_date = null; $invoice->due_date = null;
} } else {
else
{
$invoice->due_date = Utils::toSqlDate($data['due_date']); $invoice->due_date = Utils::toSqlDate($data['due_date']);
$invoice->frequency_id = 0; $invoice->frequency_id = 0;
$invoice->start_date = null; $invoice->start_date = null;
@ -277,23 +244,18 @@ class InvoiceRepository
$invoice->po_number = trim($data['po_number']); $invoice->po_number = trim($data['po_number']);
$invoice->invoice_design_id = $data['invoice_design_id']; $invoice->invoice_design_id = $data['invoice_design_id'];
if (isset($data['tax_name']) && isset($data['tax_rate']) && Utils::parseFloat($data['tax_rate']) > 0) if (isset($data['tax_name']) && isset($data['tax_rate']) && Utils::parseFloat($data['tax_rate']) > 0) {
{
$invoice->tax_rate = Utils::parseFloat($data['tax_rate']); $invoice->tax_rate = Utils::parseFloat($data['tax_rate']);
$invoice->tax_name = trim($data['tax_name']); $invoice->tax_name = trim($data['tax_name']);
} } else {
else
{
$invoice->tax_rate = 0; $invoice->tax_rate = 0;
$invoice->tax_name = ''; $invoice->tax_name = '';
} }
$total = 0; $total = 0;
foreach ($data['invoice_items'] as $item) foreach ($data['invoice_items'] as $item) {
{ if (!$item->cost && !$item->product_key && !$item->notes) {
if (!$item->cost && !$item->product_key && !$item->notes)
{
continue; continue;
} }
@ -301,8 +263,7 @@ class InvoiceRepository
$invoiceItemQty = Utils::parseFloat($item->qty); $invoiceItemQty = Utils::parseFloat($item->qty);
$invoiceItemTaxRate = 0; $invoiceItemTaxRate = 0;
if (isset($item->tax_rate) && Utils::parseFloat($item->tax_rate) > 0) if (isset($item->tax_rate) && Utils::parseFloat($item->tax_rate) > 0) {
{
$invoiceItemTaxRate = Utils::parseFloat($item->tax_rate); $invoiceItemTaxRate = Utils::parseFloat($item->tax_rate);
} }
@ -311,14 +272,10 @@ class InvoiceRepository
$total += round($lineTotal + ($lineTotal * $invoiceItemTaxRate / 100), 2); $total += round($lineTotal + ($lineTotal * $invoiceItemTaxRate / 100), 2);
} }
if ($invoice->discount > 0) if ($invoice->discount > 0) {
{ if ($invoice->is_amount_discount) {
if ($invoice->is_amount_discount)
{
$total -= $invoice->discount; $total -= $invoice->discount;
} } else {
else
{
$total *= (100 - $invoice->discount) / 100; $total *= (100 - $invoice->discount) / 100;
} }
} }
@ -347,12 +304,9 @@ class InvoiceRepository
$total += $invoice->custom_value2; $total += $invoice->custom_value2;
} }
if ($publicId) if ($publicId) {
{
$invoice->balance = $total - ($invoice->amount - $invoice->balance); $invoice->balance = $total - ($invoice->amount - $invoice->balance);
} } else {
else
{
$invoice->balance = $total; $invoice->balance = $total;
} }
@ -361,25 +315,20 @@ class InvoiceRepository
$invoice->invoice_items()->forceDelete(); $invoice->invoice_items()->forceDelete();
foreach ($data['invoice_items'] as $item) foreach ($data['invoice_items'] as $item) {
{ if (!$item->cost && !$item->product_key && !$item->notes) {
if (!$item->cost && !$item->product_key && !$item->notes)
{
continue; continue;
} }
if ($item->product_key) if ($item->product_key) {
{
$product = Product::findProductByKey(trim($item->product_key)); $product = Product::findProductByKey(trim($item->product_key));
if (!$product) if (!$product) {
{
$product = Product::createNew(); $product = Product::createNew();
$product->product_key = trim($item->product_key); $product->product_key = trim($item->product_key);
} }
if (\Auth::user()->account->update_products) if (\Auth::user()->account->update_products) {
{
$product->notes = $item->notes; $product->notes = $item->notes;
$product->cost = $item->cost; $product->cost = $item->cost;
//$product->qty = $item->qty; //$product->qty = $item->qty;
@ -396,8 +345,7 @@ class InvoiceRepository
$invoiceItem->qty = Utils::parseFloat($item->qty); $invoiceItem->qty = Utils::parseFloat($item->qty);
$invoiceItem->tax_rate = 0; $invoiceItem->tax_rate = 0;
if (isset($item->tax_rate) && Utils::parseFloat($item->tax_rate) > 0) if (isset($item->tax_rate) && Utils::parseFloat($item->tax_rate) > 0) {
{
$invoiceItem->tax_rate = Utils::parseFloat($item->tax_rate); $invoiceItem->tax_rate = Utils::parseFloat($item->tax_rate);
$invoiceItem->tax_name = trim($item->tax_name); $invoiceItem->tax_name = trim($item->tax_name);
} }
@ -405,8 +353,7 @@ class InvoiceRepository
$invoice->invoice_items()->save($invoiceItem); $invoice->invoice_items()->save($invoiceItem);
} }
if ($data['set_default_terms']) if ($data['set_default_terms']) {
{
$account = \Auth::user()->account; $account = \Auth::user()->account;
$account->invoice_terms = $invoice->terms; $account->invoice_terms = $invoice->terms;
$account->save(); $account->save();
@ -424,17 +371,13 @@ class InvoiceRepository
$clone->balance = $invoice->amount; $clone->balance = $invoice->amount;
// if the invoice prefix is diff than quote prefix, use the same number for the invoice // if the invoice prefix is diff than quote prefix, use the same number for the invoice
if (($account->invoice_number_prefix || $account->quote_number_prefix) && $account->invoice_number_prefix != $account->quote_number_prefix) if (($account->invoice_number_prefix || $account->quote_number_prefix) && $account->invoice_number_prefix != $account->quote_number_prefix) {
{
$invoiceNumber = $invoice->invoice_number; $invoiceNumber = $invoice->invoice_number;
if (strpos($invoiceNumber, $account->quote_number_prefix) === 0) if (strpos($invoiceNumber, $account->quote_number_prefix) === 0) {
{
$invoiceNumber = substr($invoiceNumber, strlen($account->quote_number_prefix)); $invoiceNumber = substr($invoiceNumber, strlen($account->quote_number_prefix));
} }
$clone->invoice_number = $account->invoice_number_prefix.$invoiceNumber; $clone->invoice_number = $account->invoice_number_prefix.$invoiceNumber;
} } else {
else
{
$clone->invoice_number = $account->getNextInvoiceNumber(); $clone->invoice_number = $account->getNextInvoiceNumber();
} }
@ -459,27 +402,23 @@ class InvoiceRepository
'custom_value1', 'custom_value1',
'custom_value2', 'custom_value2',
'custom_taxes1', 'custom_taxes1',
'custom_taxes2'] as $field) 'custom_taxes2', ] as $field) {
{
$clone->$field = $invoice->$field; $clone->$field = $invoice->$field;
} }
if ($quotePublicId) if ($quotePublicId) {
{
$clone->is_quote = false; $clone->is_quote = false;
$clone->quote_id = $quotePublicId; $clone->quote_id = $quotePublicId;
} }
$clone->save(); $clone->save();
if ($quotePublicId) if ($quotePublicId) {
{
$invoice->quote_invoice_id = $clone->public_id; $invoice->quote_invoice_id = $clone->public_id;
$invoice->save(); $invoice->save();
} }
foreach ($invoice->invoice_items as $item) foreach ($invoice->invoice_items as $item) {
{
$cloneItem = InvoiceItem::createNew($invoice); $cloneItem = InvoiceItem::createNew($invoice);
foreach ([ foreach ([
@ -489,16 +428,14 @@ class InvoiceRepository
'cost', 'cost',
'qty', 'qty',
'tax_name', 'tax_name',
'tax_rate'] as $field) 'tax_rate', ] as $field) {
{
$cloneItem->$field = $item->$field; $cloneItem->$field = $item->$field;
} }
$clone->invoice_items()->save($cloneItem); $clone->invoice_items()->save($cloneItem);
} }
foreach ($invoice->invitations as $invitation) foreach ($invoice->invitations as $invitation) {
{
$cloneInvitation = Invitation::createNew($invoice); $cloneInvitation = Invitation::createNew($invoice);
$cloneInvitation->contact_id = $invitation->contact_id; $cloneInvitation->contact_id = $invitation->contact_id;
$cloneInvitation->invitation_key = str_random(RANDOM_KEY_LENGTH); $cloneInvitation->invitation_key = str_random(RANDOM_KEY_LENGTH);
@ -508,31 +445,22 @@ class InvoiceRepository
return $clone; return $clone;
} }
public function bulk($ids, $action, $statusId = false) public function bulk($ids, $action, $statusId = false)
{ {
if (!$ids) if (!$ids) {
{
return 0; return 0;
} }
$invoices = Invoice::withTrashed()->scope($ids)->get(); $invoices = Invoice::withTrashed()->scope($ids)->get();
foreach ($invoices as $invoice) foreach ($invoices as $invoice) {
{ if ($action == 'mark') {
if ($action == 'mark')
{
$invoice->invoice_status_id = $statusId; $invoice->invoice_status_id = $statusId;
$invoice->save(); $invoice->save();
} } elseif ($action == 'restore') {
else if ($action == 'restore')
{
$invoice->restore(); $invoice->restore();
} } else {
else if ($action == 'delete') {
{
if ($action == 'delete')
{
$invoice->is_deleted = true; $invoice->is_deleted = true;
$invoice->save(); $invoice->save();
} }

View File

@ -79,8 +79,7 @@ if (Utils::isNinja()) {
Route::get('/demo', 'AccountController@demo'); Route::get('/demo', 'AccountController@demo');
} }
Route::group(array('before' => 'auth'), function() Route::group(array('before' => 'auth'), function() {
{
Route::get('dashboard', 'DashboardController@index'); Route::get('dashboard', 'DashboardController@index');
Route::get('view_archive/{entity_type}/{visible}', 'AccountController@setTrashVisible'); Route::get('view_archive/{entity_type}/{visible}', 'AccountController@setTrashVisible');
Route::get('hide_message', 'HomeController@hideMessage'); Route::get('hide_message', 'HomeController@hideMessage');
@ -130,13 +129,17 @@ Route::group(array('before' => 'auth'), function()
Route::get('api/quotes/{client_id?}', array('as'=>'api.quotes', 'uses'=>'QuoteController@getDatatable')); Route::get('api/quotes/{client_id?}', array('as'=>'api.quotes', 'uses'=>'QuoteController@getDatatable'));
Route::post('quotes/bulk', 'QuoteController@bulk'); Route::post('quotes/bulk', 'QuoteController@bulk');
Route::get('payments/{id}/edit', function() { return View::make('header'); }); Route::get('payments/{id}/edit', function() {
return View::make('header');
});
Route::resource('payments', 'PaymentController'); Route::resource('payments', 'PaymentController');
Route::get('payments/create/{client_id?}/{invoice_id?}', 'PaymentController@create'); Route::get('payments/create/{client_id?}/{invoice_id?}', 'PaymentController@create');
Route::get('api/payments/{client_id?}', array('as'=>'api.payments', 'uses'=>'PaymentController@getDatatable')); Route::get('api/payments/{client_id?}', array('as'=>'api.payments', 'uses'=>'PaymentController@getDatatable'));
Route::post('payments/bulk', 'PaymentController@bulk'); Route::post('payments/bulk', 'PaymentController@bulk');
Route::get('credits/{id}/edit', function() { return View::make('header'); }); Route::get('credits/{id}/edit', function() {
return View::make('header');
});
Route::resource('credits', 'CreditController'); Route::resource('credits', 'CreditController');
Route::get('credits/create/{client_id?}/{invoice_id?}', 'CreditController@create'); Route::get('credits/create/{client_id?}/{invoice_id?}', 'CreditController@create');
Route::get('api/credits/{client_id?}', array('as'=>'api.credits', 'uses'=>'CreditController@getDatatable')); Route::get('api/credits/{client_id?}', array('as'=>'api.credits', 'uses'=>'CreditController@getDatatable'));
@ -338,16 +341,13 @@ HTML::macro('breadcrumbs', function() {
$parts = explode('?', $_SERVER['REQUEST_URI']); $parts = explode('?', $_SERVER['REQUEST_URI']);
$path = $parts[0]; $path = $parts[0];
if ($basePath != '/') if ($basePath != '/') {
{
$path = str_replace($basePath, '', $path); $path = str_replace($basePath, '', $path);
} }
$crumbs = explode('/', $path); $crumbs = explode('/', $path);
foreach ($crumbs as $key => $val) foreach ($crumbs as $key => $val) {
{ if (is_numeric($val)) {
if (is_numeric($val))
{
unset($crumbs[$key]); unset($crumbs[$key]);
} }
} }
@ -355,15 +355,16 @@ HTML::macro('breadcrumbs', function() {
$crumbs = array_values($crumbs); $crumbs = array_values($crumbs);
for ($i=0; $i<count($crumbs); $i++) { for ($i=0; $i<count($crumbs); $i++) {
$crumb = trim($crumbs[$i]); $crumb = trim($crumbs[$i]);
if (!$crumb) continue; if (!$crumb) {
if ($crumb == 'company') return ''; continue;
$name = trans("texts.$crumb");
if ($i==count($crumbs)-1)
{
$str .= "<li class='active'>$name</li>";
} }
else if ($crumb == 'company') {
{ return '';
}
$name = trans("texts.$crumb");
if ($i==count($crumbs)-1) {
$str .= "<li class='active'>$name</li>";
} else {
$str .= '<li>'.link_to($crumb, $name).'</li>'; $str .= '<li>'.link_to($crumb, $name).'</li>';
} }
} }
@ -380,26 +381,20 @@ function otrans($text)
{ {
$locale = Session::get(SESSION_LOCALE); $locale = Session::get(SESSION_LOCALE);
if ($locale == 'en') if ($locale == 'en') {
{
return trans($text); return trans($text);
} } else {
else
{
$string = trans($text); $string = trans($text);
$english = trans($text, [], 'en'); $english = trans($text, [], 'en');
return $string != $english ? $string : ''; return $string != $english ? $string : '';
} }
} }
Validator::extend('positive', function($attribute, $value, $parameters) Validator::extend('positive', function($attribute, $value, $parameters) {
{
return Utils::parseFloat($value) >= 0; return Utils::parseFloat($value) >= 0;
}); });
Validator::extend('has_credit', function($attribute, $value, $parameters) Validator::extend('has_credit', function($attribute, $value, $parameters) {
{
$publicClientId = $parameters[0]; $publicClientId = $parameters[0];
$amount = $parameters[1]; $amount = $parameters[1];

View File

@ -82,12 +82,14 @@
</thead> </thead>
<tbody> <tbody>
@foreach ($pastDue as $invoice) @foreach ($pastDue as $invoice)
@if (!$invoice->client->trashed())
<tr> <tr>
<td>{{ $invoice->getLink() }}</td> <td>{{ $invoice->getLink() }}</td>
<td>{{ $invoice->client->getDisplayName() }}</td> <td>{{ $invoice->client->getDisplayName() }}</td>
<td>{{ Utils::fromSqlDate($invoice->due_date) }}</td> <td>{{ Utils::fromSqlDate($invoice->due_date) }}</td>
<td>{{ Utils::formatMoney($invoice->balance, $invoice->client->currency_id) }}</td> <td>{{ Utils::formatMoney($invoice->balance, $invoice->client->currency_id) }}</td>
</tr> </tr>
@endif
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
@ -114,12 +116,14 @@
</thead> </thead>
<tbody> <tbody>
@foreach ($upcoming as $invoice) @foreach ($upcoming as $invoice)
@if (!$invoice->client->trashed())
<tr> <tr>
<td>{{ $invoice->getLink() }}</td> <td>{{ $invoice->getLink() }}</td>
<td>{{ $invoice->client->getDisplayName() }}</td> <td>{{ $invoice->client->getDisplayName() }}</td>
<td>{{ Utils::fromSqlDate($invoice->due_date) }}</td> <td>{{ Utils::fromSqlDate($invoice->due_date) }}</td>
<td>{{ Utils::formatMoney($invoice->balance, $invoice->client->currency_id) }}</td> <td>{{ Utils::formatMoney($invoice->balance, $invoice->client->currency_id) }}</td>
</tr> </tr>
@endif
@endforeach @endforeach
</tbody> </tbody>
</table> </table>

View File

@ -135,7 +135,7 @@
<i style="display:none" data-bind="visible: actionsVisible() &amp;&amp; $parent.invoice_items().length > 1" class="fa fa-sort"></i> <i style="display:none" data-bind="visible: actionsVisible() &amp;&amp; $parent.invoice_items().length > 1" class="fa fa-sort"></i>
</td> </td>
<td> <td>
{{ Former::text('product_key')->useDatalist($products, 'product_key')->onkeyup('onItemChange()') {{ Former::text('product_key')->useDatalist($products->toArray(), 'product_key')->onkeyup('onItemChange()')
->raw()->data_bind("value: product_key, valueUpdate: 'afterkeydown'")->addClass('datalist') }} ->raw()->data_bind("value: product_key, valueUpdate: 'afterkeydown'")->addClass('datalist') }}
</td> </td>
<td> <td>
@ -323,7 +323,7 @@
@if ($invoice && $invoice->id && $entityType == ENTITY_INVOICE) @if ($invoice && $invoice->id && $entityType == ENTITY_INVOICE)
{{ Button::primary(trans('texts.enter_payment'), array('onclick' => 'onPaymentClick()'))->append_with_icon('usd'); }} {{ Button::primary(trans('texts.enter_payment'), array('onclick' => 'onPaymentClick()'))->append_with_icon('usd'); }}
@endif @endif
@elseif ($invoice && $invoice->trashed()) @elseif ($invoice && $invoice->trashed() && !$invoice->is_deleted == '1')
{{ Button::success(trans('texts.restore'), ['onclick' => 'submitAction("restore")'])->append_with_icon('cloud-download') }} {{ Button::success(trans('texts.restore'), ['onclick' => 'submitAction("restore")'])->append_with_icon('cloud-download') }}
@endif @endif

View File

@ -90,7 +90,7 @@ FLUSH PRIVILEGES;</pre>
{{ Former::text('first_name') }} {{ Former::text('first_name') }}
{{ Former::text('last_name') }} {{ Former::text('last_name') }}
{{ Former::text('email') }} {{ Former::text('email') }}
{{ Former::text('password') }} {{ Former::password('password') }}
</div> </div>
</div> </div>