1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 21:22:58 +01:00
invoiceninja/app/ninja/repositories/InvoiceRepository.php

454 lines
14 KiB
PHP
Raw Normal View History

2013-12-25 22:34:42 +01:00
<?php namespace ninja\repositories;
use Invoice;
use InvoiceItem;
2014-05-20 23:40:09 +02:00
use Invitation;
2013-12-25 22:34:42 +01:00
use Product;
use Utils;
2013-12-29 00:33:48 +01:00
use TaxRate;
2013-12-25 22:34:42 +01:00
class InvoiceRepository
{
public function getInvoices($accountId, $clientPublicId = false, $filter = false)
{
$query = \DB::table('invoices')
->join('clients', 'clients.id', '=','invoices.client_id')
2014-02-16 21:32:25 +01:00
->join('invoice_statuses', 'invoice_statuses.id', '=', 'invoices.invoice_status_id')
->join('contacts', 'contacts.client_id', '=', 'clients.id')
2014-05-20 23:40:09 +02:00
->where('invoices.account_id', '=', $accountId)
->where('clients.deleted_at', '=', null)
2014-06-02 18:21:47 +02:00
->where('contacts.deleted_at', '=', null)
2013-12-30 21:17:45 +01:00
->where('invoices.is_recurring', '=', false)
->where('contacts.is_primary', '=', true)
2014-05-20 23:40:09 +02:00
->select('clients.public_id as client_public_id', 'invoice_number', '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');
2013-12-25 22:34:42 +01:00
2014-02-19 20:59:46 +01:00
if (!\Session::get('show_trash'))
2014-02-18 22:56:18 +01:00
{
$query->where('invoices.deleted_at', '=', null);
}
2013-12-25 22:34:42 +01:00
if ($clientPublicId)
{
$query->where('clients.public_id', '=', $clientPublicId);
}
if ($filter)
{
$query->where(function($query) use ($filter)
{
$query->where('clients.name', 'like', '%'.$filter.'%')
->orWhere('invoices.invoice_number', 'like', '%'.$filter.'%')
2014-02-26 17:08:40 +01:00
->orWhere('invoice_statuses.name', 'like', '%'.$filter.'%')
->orWhere('contacts.first_name', 'like', '%'.$filter.'%')
->orWhere('contacts.last_name', 'like', '%'.$filter.'%')
->orWhere('contacts.email', 'like', '%'.$filter.'%');
2013-12-25 22:34:42 +01:00
});
}
return $query;
}
public function getRecurringInvoices($accountId, $clientPublicId = false, $filter = false)
{
$query = \DB::table('invoices')
->join('clients', 'clients.id', '=','invoices.client_id')
2014-03-23 21:56:19 +01:00
->join('frequencies', 'frequencies.id', '=', 'invoices.frequency_id')
->join('contacts', 'contacts.client_id', '=', 'clients.id')
->where('invoices.account_id', '=', $accountId)
2014-05-20 23:40:09 +02:00
->where('invoices.is_quote', '=', false)
2014-02-18 22:56:18 +01:00
->where('clients.deleted_at', '=', null)
2013-12-25 22:34:42 +01:00
->where('invoices.is_recurring', '=', true)
2013-12-30 21:17:45 +01:00
->where('contacts.is_primary', '=', true)
2014-03-23 21:56:19 +01:00
->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');
2013-12-25 22:34:42 +01:00
if ($clientPublicId)
{
$query->where('clients.public_id', '=', $clientPublicId);
}
2014-02-19 20:59:46 +01:00
if (!\Session::get('show_trash'))
2014-02-18 22:56:18 +01:00
{
$query->where('invoices.deleted_at', '=', null);
}
2013-12-25 22:34:42 +01:00
if ($filter)
{
$query->where(function($query) use ($filter)
{
$query->where('clients.name', 'like', '%'.$filter.'%')
->orWhere('invoices.invoice_number', 'like', '%'.$filter.'%');
});
}
return $query;
}
2014-05-17 21:29:57 +02:00
public function getDatatable($accountId, $clientPublicId = null, $entityType, $search)
{
2014-05-20 23:40:09 +02:00
$query = $this->getInvoices($accountId, $clientPublicId, $search)
->where('invoices.is_quote', '=', $entityType == ENTITY_QUOTE ? true : false);
2014-05-17 21:29:57 +02:00
$table = \Datatable::query($query);
if (!$clientPublicId)
{
$table->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; });
}
$table->addColumn("invoice_number", function($model) use ($entityType) { return link_to("{$entityType}s/" . $model->public_id . '/edit', $model->invoice_number); });
if (!$clientPublicId)
{
$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); })
->addColumn('amount', function($model) { return Utils::formatMoney($model->amount, $model->currency_id); });
if ($entityType == ENTITY_INVOICE)
{
$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); })
->addColumn('invoice_status_name', function($model) { return $model->invoice_status_name; })
->addColumn('dropdown', function($model) use ($entityType)
{
$str = '<div class="btn-group tr-action" style="visibility:hidden;">
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown">
'.trans('texts.select').' <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
2014-05-20 23:40:09 +02:00
<li><a href="' . \URL::to("{$entityType}s/".$model->public_id.'/edit') . '">'.trans("texts.edit_{$entityType}").'</a></li>
2014-05-22 20:29:29 +02:00
<li><a href="' . \URL::to("{$entityType}s/".$model->public_id.'/clone') . '">'.trans("texts.clone_{$entityType}").'</a></li>
<li class="divider"></li><li>';
2014-05-17 21:29:57 +02:00
if ($entityType == ENTITY_INVOICE)
{
2014-05-22 20:29:29 +02:00
$str .= '<a href="' . \URL::to('payments/create/' . $model->client_public_id . '/' . $model->public_id ) . '">'.trans('texts.enter_payment').'</a></li>';
2014-05-20 23:40:09 +02:00
if ($model->quote_id)
{
$str .= '<li><a href="' . \URL::to("quotes/{$model->quote_id}/edit") . '">' . trans("texts.view_quote") . '</a></li>';
}
2014-05-17 21:29:57 +02:00
}
2014-05-20 23:40:09 +02:00
else if ($entityType == ENTITY_QUOTE)
2014-05-17 21:29:57 +02:00
{
2014-05-20 23:40:09 +02:00
if ($model->quote_invoice_id)
{
2014-05-22 20:29:29 +02:00
$str .= '<li><a href="' . \URL::to("invoices/{$model->quote_invoice_id}/edit") . '">' . trans("texts.view_invoice") . '</a></li>';
2014-05-20 23:40:09 +02:00
}
2014-05-17 21:29:57 +02:00
}
2014-05-20 23:40:09 +02:00
2014-05-17 21:29:57 +02:00
return $str . '<li class="divider"></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>
</ul>
</div>';
})
->make();
}
2014-01-01 16:23:32 +01:00
public function getErrors($input)
{
$contact = (array) $input->client->contacts[0];
$rules = ['email' => 'required|email'];
2014-07-27 22:31:41 +02:00
$validator = \Validator::make($contact, $rules);
2014-01-01 16:23:32 +01:00
2014-07-27 22:31:41 +02:00
if ($validator->fails())
{
return $validator;
}
2014-01-01 16:23:32 +01:00
2014-07-27 22:31:41 +02:00
$invoice = (array) $input;
$invoiceId = isset($invoice['public_id']) && $invoice['public_id'] ? Invoice::getPrivateId($invoice['public_id']) : null;
$rules = ['invoice_number' => 'required|unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . \Auth::user()->account_id];
2014-01-14 12:52:56 +01:00
2014-07-27 22:31:41 +02:00
if ($invoice['is_recurring'] && $invoice['start_date'] && $invoice['end_date'])
{
$rules['end_date'] = 'after:' . $invoice['start_date'];
}
2014-01-14 12:52:56 +01:00
2014-07-27 22:31:41 +02:00
$validator = \Validator::make($invoice, $rules);
2014-01-01 16:23:32 +01:00
2014-07-27 22:31:41 +02:00
if ($validator->fails())
{
return $validator;
}
2014-01-01 16:23:32 +01:00
2014-07-27 22:31:41 +02:00
return false;
2014-01-01 16:23:32 +01:00
}
2014-05-20 23:40:09 +02:00
public function save($publicId, $data, $entityType)
2013-12-25 22:34:42 +01:00
{
if ($publicId)
{
$invoice = Invoice::scope($publicId)->firstOrFail();
}
else
{
$invoice = Invoice::createNew();
2014-05-20 23:40:09 +02:00
if ($entityType == ENTITY_QUOTE)
{
$invoice->is_quote = true;
}
2013-12-25 22:34:42 +01:00
}
$invoice->client_id = $data['client_id'];
2014-01-14 12:52:56 +01:00
$invoice->discount = Utils::parseFloat($data['discount']);
2013-12-25 22:34:42 +01:00
$invoice->invoice_number = trim($data['invoice_number']);
2014-03-10 19:22:40 +01:00
$invoice->is_recurring = $data['is_recurring'] ? true : false;
2014-05-25 20:38:40 +02:00
$invoice->invoice_date = Utils::toSqlDate($data['invoice_date']);
if ($invoice->is_recurring)
{
$invoice->frequency_id = $data['frequency_id'] ? $data['frequency_id'] : 0;
$invoice->start_date = Utils::toSqlDate($data['start_date']);
$invoice->end_date = Utils::toSqlDate($data['end_date']);
$invoice->due_date = null;
}
else
{
$invoice->due_date = Utils::toSqlDate($data['due_date']);
$invoice->frequency_id = 0;
$invoice->start_date = null;
$invoice->end_date = null;
}
2013-12-25 22:34:42 +01:00
$invoice->terms = trim($data['terms']);
2013-12-30 21:17:45 +01:00
$invoice->public_notes = trim($data['public_notes']);
2013-12-25 22:34:42 +01:00
$invoice->po_number = trim($data['po_number']);
$invoice->invoice_design_id = $data['invoice_design_id'];
2014-04-12 20:55:40 +02:00
if (isset($data['tax_name']) && isset($data['tax_rate']) && Utils::parseFloat($data['tax_rate']) > 0)
2013-12-25 22:34:42 +01:00
{
2014-01-14 12:52:56 +01:00
$invoice->tax_rate = Utils::parseFloat($data['tax_rate']);
2014-01-01 16:23:32 +01:00
$invoice->tax_name = trim($data['tax_name']);
2014-01-01 00:50:13 +01:00
}
else
{
$invoice->tax_rate = 0;
$invoice->tax_name = '';
2013-12-25 22:34:42 +01:00
}
2014-01-01 00:50:13 +01:00
2013-12-31 20:49:54 +01:00
$total = 0;
2013-12-25 22:34:42 +01:00
foreach ($data['invoice_items'] as $item)
{
2014-07-20 12:38:42 +02:00
if (!$item->cost && !$item->product_key && !$item->notes)
2013-12-25 22:34:42 +01:00
{
continue;
}
2014-02-01 21:01:32 +01:00
$invoiceItemCost = Utils::parseFloat($item->cost);
$invoiceItemQty = Utils::parseFloat($item->qty);
$invoiceItemTaxRate = 0;
2013-12-25 22:34:42 +01:00
2014-01-14 12:52:56 +01:00
if (isset($item->tax_rate) && Utils::parseFloat($item->tax_rate) > 0)
2013-12-29 00:33:48 +01:00
{
2014-02-01 21:01:32 +01:00
$invoiceItemTaxRate = Utils::parseFloat($item->tax_rate);
2013-12-29 00:33:48 +01:00
}
2014-02-01 21:01:32 +01:00
$lineTotal = $invoiceItemCost * $invoiceItemQty;
2014-06-01 15:35:19 +02:00
$total += round($lineTotal + ($lineTotal * $invoiceItemTaxRate / 100), 2);
2013-12-31 20:49:54 +01:00
}
if ($invoice->discount > 0)
{
$total *= (100 - $invoice->discount) / 100;
2013-12-25 22:34:42 +01:00
}
2014-07-23 17:02:56 +02:00
$invoice->custom_value1 = round($data['custom_value1'], 2);
$invoice->custom_value2 = round($data['custom_value2'], 2);
2014-07-20 12:38:42 +02:00
$invoice->custom_taxes1 = $data['custom_taxes1'] ? true : false;
$invoice->custom_taxes2 = $data['custom_taxes2'] ? true : false;
// custom fields charged taxes
if ($invoice->custom_value1 && $invoice->custom_taxes1) {
$total += $invoice->custom_value1;
}
if ($invoice->custom_value2 && $invoice->custom_taxes2) {
$total += $invoice->custom_value2;
}
2013-12-31 20:49:54 +01:00
$total += $total * $invoice->tax_rate / 100;
2014-06-01 15:35:19 +02:00
$total = round($total, 2);
2013-12-31 20:49:54 +01:00
2014-07-20 12:38:42 +02:00
// custom fields not charged taxes
if ($invoice->custom_value1 && !$invoice->custom_taxes1) {
$total += $invoice->custom_value1;
}
if ($invoice->custom_value2 && !$invoice->custom_taxes2) {
$total += $invoice->custom_value2;
}
2014-04-03 19:54:06 +02:00
if ($publicId)
{
$invoice->balance = $total - ($invoice->amount - $invoice->balance);
}
else
{
$invoice->balance = $total;
}
$invoice->amount = $total;
2013-12-31 20:49:54 +01:00
$invoice->save();
2014-02-01 21:01:32 +01:00
$invoice->invoice_items()->forceDelete();
foreach ($data['invoice_items'] as $item)
{
2014-07-20 12:38:42 +02:00
if (!$item->cost && !$item->product_key && !$item->notes)
2014-02-01 21:01:32 +01:00
{
continue;
}
if ($item->product_key)
{
$product = Product::findProductByKey(trim($item->product_key));
if (!$product)
{
$product = Product::createNew();
$product->product_key = trim($item->product_key);
}
2014-04-23 23:48:09 +02:00
if (\Auth::user()->account->update_products)
{
$product->notes = $item->notes;
$product->cost = $item->cost;
//$product->qty = $item->qty;
}
2014-02-01 21:01:32 +01:00
$product->save();
}
$invoiceItem = InvoiceItem::createNew();
$invoiceItem->product_id = isset($product) ? $product->id : null;
$invoiceItem->product_key = trim($item->product_key);
$invoiceItem->notes = trim($item->notes);
$invoiceItem->cost = Utils::parseFloat($item->cost);
$invoiceItem->qty = Utils::parseFloat($item->qty);
$invoiceItem->tax_rate = 0;
if (isset($item->tax_rate) && Utils::parseFloat($item->tax_rate) > 0)
{
$invoiceItem->tax_rate = Utils::parseFloat($item->tax_rate);
$invoiceItem->tax_name = trim($item->tax_name);
}
$invoice->invoice_items()->save($invoiceItem);
}
2014-01-08 21:09:47 +01:00
if ($data['set_default_terms'])
{
$account = \Auth::user()->account;
$account->invoice_terms = $invoice->terms;
$account->save();
}
2013-12-25 22:34:42 +01:00
return $invoice;
}
2014-01-12 19:55:33 +01:00
2014-05-25 16:48:00 +02:00
public function cloneInvoice($invoice, $quotePublicId = null)
2014-05-20 23:40:09 +02:00
{
2014-05-25 16:25:58 +02:00
$invoice->load('invitations', 'invoice_items');
2014-05-25 16:48:00 +02:00
$clone = Invoice::createNew($invoice);
2014-05-20 23:40:09 +02:00
$clone->balance = $invoice->amount;
$clone->invoice_number = $invoice->account->getNextInvoiceNumber();
foreach ([
2014-05-22 20:29:29 +02:00
'client_id',
2014-05-20 23:40:09 +02:00
'discount',
2014-05-25 12:57:19 +02:00
//'shipping',
2014-05-20 23:40:09 +02:00
'invoice_date',
'po_number',
'due_date',
'is_recurring',
'frequency_id',
'start_date',
'end_date',
'terms',
'public_notes',
'invoice_design_id',
'tax_name',
'tax_rate',
'amount',
'is_quote'] as $field)
{
$clone->$field = $invoice->$field;
}
2014-05-25 12:57:19 +02:00
if ($quotePublicId)
2014-05-20 23:40:09 +02:00
{
$clone->is_quote = false;
2014-05-25 12:57:19 +02:00
$clone->quote_id = $quotePublicId;
2014-05-20 23:40:09 +02:00
}
2014-05-25 16:25:58 +02:00
2014-05-20 23:40:09 +02:00
$clone->save();
2014-05-25 12:57:19 +02:00
if ($quotePublicId)
2014-05-20 23:40:09 +02:00
{
2014-05-25 12:57:19 +02:00
$invoice->quote_invoice_id = $clone->public_id;
2014-05-20 23:40:09 +02:00
$invoice->save();
}
2014-05-25 16:25:58 +02:00
2014-05-20 23:40:09 +02:00
foreach ($invoice->invoice_items as $item)
{
2014-05-25 16:48:00 +02:00
$cloneItem = InvoiceItem::createNew($invoice);
2014-05-20 23:40:09 +02:00
foreach ([
'product_id',
'product_key',
'notes',
'cost',
'qty',
'tax_name',
'tax_rate'] as $field)
{
$cloneItem->$field = $item->$field;
}
$clone->invoice_items()->save($cloneItem);
}
foreach ($invoice->invitations as $invitation)
{
2014-05-25 16:48:00 +02:00
$cloneInvitation = Invitation::createNew($invoice);
2014-05-20 23:40:09 +02:00
$cloneInvitation->contact_id = $invitation->contact_id;
$cloneInvitation->invitation_key = str_random(RANDOM_KEY_LENGTH);
$clone->invitations()->save($cloneInvitation);
}
return $clone;
}
2014-01-12 19:55:33 +01:00
public function bulk($ids, $action)
{
if (!$ids)
{
return 0;
}
$invoices = Invoice::scope($ids)->get();
foreach ($invoices as $invoice)
{
if ($action == 'delete')
{
$invoice->is_deleted = true;
$invoice->save();
}
$invoice->delete();
}
return count($invoices);
}
2013-12-25 22:34:42 +01:00
}