2015-03-24 09:21:12 +01:00
< ? php namespace App\Ninja\Repositories ;
2013-12-25 22:34:42 +01:00
2015-08-10 17:48:41 +02:00
use Carbon ;
use Utils ;
2015-03-31 11:38:24 +02:00
use App\Models\Invoice ;
use App\Models\InvoiceItem ;
use App\Models\Invitation ;
use App\Models\Product ;
2015-05-27 18:52:10 +02:00
use App\Models\Task ;
2015-09-10 19:50:09 +02:00
use App\Services\PaymentService ;
2015-10-28 20:22:07 +01:00
use App\Ninja\Repositories\BaseRepository ;
2013-12-25 22:34:42 +01:00
2015-10-28 20:22:07 +01:00
class InvoiceRepository extends BaseRepository
2013-12-25 22:34:42 +01:00
{
2015-10-28 20:22:07 +01:00
public function getClassName ()
{
return 'App\Models\Invoice' ;
}
2015-09-10 19:50:09 +02:00
public function __construct ( PaymentService $paymentService )
{
$this -> paymentService = $paymentService ;
}
2015-01-11 12:56:58 +01:00
public function getInvoices ( $accountId , $clientPublicId = false , $entityType = ENTITY_INVOICE , $filter = false )
{
$query = \DB :: table ( 'invoices' )
-> join ( 'clients' , 'clients.id' , '=' , 'invoices.client_id' )
-> 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 )
2015-01-11 12:56:58 +01:00
-> where ( 'invoices.is_recurring' , '=' , false )
-> where ( 'contacts.is_primary' , '=' , true )
2015-04-16 21:57:12 +02:00
-> 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' , 'invoices.partial' );
2015-01-11 12:56:58 +01:00
if ( ! \Session :: get ( 'show_trash:' . $entityType )) {
$query -> where ( 'invoices.deleted_at' , '=' , null );
}
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 . '%' )
-> orWhere ( 'invoice_statuses.name' , 'like' , '%' . $filter . '%' )
2014-02-26 17:08:40 +01:00
-> 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
});
2015-01-11 12:56:58 +01:00
}
return $query ;
}
public function getRecurringInvoices ( $accountId , $clientPublicId = false , $filter = false )
{
$query = \DB :: table ( 'invoices' )
-> join ( 'clients' , 'clients.id' , '=' , 'invoices.client_id' )
-> join ( 'frequencies' , 'frequencies.id' , '=' , 'invoices.frequency_id' )
-> join ( 'contacts' , 'contacts.client_id' , '=' , 'clients.id' )
-> where ( 'invoices.account_id' , '=' , $accountId )
-> where ( 'invoices.is_quote' , '=' , false )
-> where ( 'contacts.deleted_at' , '=' , null )
-> where ( 'invoices.is_recurring' , '=' , true )
-> where ( 'contacts.is_primary' , '=' , true )
2015-06-03 19:55:48 +02:00
-> where ( 'clients.deleted_at' , '=' , null )
2015-01-11 12:56:58 +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' , 'invoices.deleted_at' , 'invoices.is_deleted' );
if ( $clientPublicId ) {
$query -> where ( 'clients.public_id' , '=' , $clientPublicId );
}
if ( ! \Session :: get ( 'show_trash:invoice' )) {
$query -> where ( 'invoices.deleted_at' , '=' , null );
}
if ( $filter ) {
$query -> where ( function ( $query ) use ( $filter ) {
$query -> where ( 'clients.name' , 'like' , '%' . $filter . '%' )
-> orWhere ( 'invoices.invoice_number' , 'like' , '%' . $filter . '%' );
2013-12-25 22:34:42 +01:00
});
2015-01-11 12:56:58 +01:00
}
2013-12-25 22:34:42 +01:00
2015-01-11 12:56:58 +01:00
return $query ;
}
2013-12-25 22:34:42 +01:00
2015-01-11 12:56:58 +01:00
public function getClientDatatable ( $contactId , $entityType , $search )
{
$query = \DB :: table ( 'invitations' )
-> join ( 'invoices' , 'invoices.id' , '=' , 'invitations.invoice_id' )
-> join ( 'clients' , 'clients.id' , '=' , 'invoices.client_id' )
2014-11-12 22:09:42 +01:00
-> where ( 'invitations.contact_id' , '=' , $contactId )
-> where ( 'invitations.deleted_at' , '=' , null )
-> where ( 'invoices.is_quote' , '=' , $entityType == ENTITY_QUOTE )
-> where ( 'invoices.is_deleted' , '=' , false )
-> where ( 'clients.deleted_at' , '=' , null )
-> where ( 'invoices.is_recurring' , '=' , false )
2015-04-16 21:57:12 +02:00
-> select ( 'invitation_key' , 'invoice_number' , 'invoice_date' , 'invoices.balance as balance' , 'due_date' , 'clients.public_id as client_public_id' , 'clients.name as client_name' , 'invoices.public_id' , 'amount' , 'start_date' , 'end_date' , 'clients.currency_id' , 'invoices.partial' );
2014-11-12 22:09:42 +01:00
2015-01-11 12:56:58 +01:00
$table = \Datatable :: query ( $query )
-> addColumn ( 'invoice_number' , function ( $model ) use ( $entityType ) { return link_to ( '/view/' . $model -> invitation_key , $model -> invoice_number ); })
-> addColumn ( 'invoice_date' , function ( $model ) { return Utils :: fromSqlDate ( $model -> invoice_date ); })
-> addColumn ( 'amount' , function ( $model ) { return Utils :: formatMoney ( $model -> amount , $model -> currency_id ); });
2014-11-12 22:09:42 +01:00
2015-01-11 12:56:58 +01:00
if ( $entityType == ENTITY_INVOICE ) {
2015-04-16 21:57:12 +02:00
$table -> addColumn ( 'balance' , function ( $model ) {
return $model -> partial > 0 ?
trans ( 'texts.partial_remaining' , [ 'partial' => Utils :: formatMoney ( $model -> partial , $model -> currency_id ), 'balance' => Utils :: formatMoney ( $model -> balance , $model -> currency_id )]) :
Utils :: formatMoney ( $model -> balance , $model -> currency_id );
});
2015-01-11 12:56:58 +01:00
}
return $table -> addColumn ( 'due_date' , function ( $model ) { return Utils :: fromSqlDate ( $model -> due_date ); })
-> make ();
}
2014-11-12 22:09:42 +01:00
2015-01-11 12:56:58 +01:00
public function getDatatable ( $accountId , $clientPublicId = null , $entityType , $search )
{
$query = $this -> getInvoices ( $accountId , $clientPublicId , $entityType , $search )
2014-05-20 23:40:09 +02:00
-> where ( 'invoices.is_quote' , '=' , $entityType == ENTITY_QUOTE ? true : false );
2014-05-17 21:29:57 +02:00
2015-01-11 12:56:58 +01:00
$table = \Datatable :: query ( $query );
2014-05-17 21:29:57 +02:00
2015-01-11 12:56:58 +01:00
if ( ! $clientPublicId ) {
$table -> addColumn ( 'checkbox' , function ( $model ) { return '<input type="checkbox" name="ids[]" value="' . $model -> public_id . '" ' . Utils :: getEntityRowClass ( $model ) . '>' ; });
}
2014-05-17 21:29:57 +02:00
2015-01-11 12:56:58 +01:00
$table -> addColumn ( " invoice_number " , function ( $model ) use ( $entityType ) { return link_to ( " { $entityType } s/ " . $model -> public_id . '/edit' , $model -> invoice_number , [ 'class' => Utils :: getEntityRowClass ( $model )]); });
2014-05-17 21:29:57 +02:00
2015-01-11 12:56:58 +01:00
if ( ! $clientPublicId ) {
$table -> addColumn ( 'client_name' , function ( $model ) { return link_to ( 'clients/' . $model -> client_public_id , Utils :: getClientDisplayName ( $model )); });
}
2014-05-17 21:29:57 +02:00
2015-01-11 12:56:58 +01:00
$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 ) {
2015-04-16 21:57:12 +02:00
$table -> addColumn ( 'balance' , function ( $model ) {
return $model -> partial > 0 ?
trans ( 'texts.partial_remaining' , [ 'partial' => Utils :: formatMoney ( $model -> partial , $model -> currency_id ), 'balance' => Utils :: formatMoney ( $model -> balance , $model -> currency_id )]) :
Utils :: formatMoney ( $model -> balance , $model -> currency_id );
});
2015-01-11 12:56:58 +01:00
}
return $table -> addColumn ( 'due_date' , function ( $model ) { return Utils :: fromSqlDate ( $model -> due_date ); })
2015-04-22 21:21:04 +02:00
-> addColumn ( 'invoice_status_name' , function ( $model ) { return $model -> quote_invoice_id ? link_to ( " invoices/ { $model -> quote_invoice_id } /edit " , trans ( 'texts.converted' )) : self :: getStatusLabel ( $model -> invoice_status_id , $model -> invoice_status_name ); })
2015-01-11 12:56:58 +01:00
-> addColumn ( 'dropdown' , function ( $model ) use ( $entityType ) {
2014-05-20 23:40:09 +02:00
2015-01-11 12:56:58 +01:00
$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 " > ' ;
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 >
< li >< a href = " '. \ URL::to( " { $entityType } s / " . $model->public_id .'/clone').' " > '.trans("texts.clone_{$entityType}").' </ a ></ li >
2015-01-25 20:26:15 +01:00
< li >< a href = " ' . \ URL::to( " { $entityType } s / { $entityType } _history / { $model -> public_id } " ) . ' " > ' . trans("texts.view_history") . ' </ a ></ li >
2015-01-11 12:56:58 +01:00
< li class = " divider " ></ li > ' ;
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>' ;
}
if ( $entityType == ENTITY_INVOICE ) {
2015-05-27 22:37:39 +02:00
if ( $model -> balance > 0 ) {
2015-01-11 13:30:08 +01:00
$str .= '<li><a href="' . \URL :: to ( 'payments/create/' . $model -> client_public_id . '/' . $model -> public_id ) . '">' . trans ( 'texts.enter_payment' ) . '</a></li>' ;
2015-01-11 12:56:58 +01:00
}
if ( $model -> quote_id ) {
2015-01-11 13:30:08 +01:00
$str .= '<li><a href="' . \URL :: to ( " quotes/ { $model -> quote_id } /edit " ) . '">' . trans ( " texts.view_quote " ) . '</a></li>' ;
2015-01-11 12:56:58 +01:00
}
} elseif ( $entityType == ENTITY_QUOTE ) {
if ( $model -> quote_invoice_id ) {
$str .= '<li><a href="' . \URL :: to ( " invoices/ { $model -> quote_invoice_id } /edit " ) . '">' . trans ( " texts.view_invoice " ) . '</a></li>' ;
2015-02-10 14:50:38 +01:00
} else {
$str .= '<li><a href="javascript:convertEntity(' . $model -> public_id . ')">' . trans ( " texts.convert_to_invoice " ) . '</a></li>' ;
2015-01-11 12:56:58 +01:00
}
}
$str .= ' < li class = " divider " ></ li >
2015-10-30 13:56:25 +01:00
< li >< a href = " javascript:archiveEntity('. $model->public_id .') " > '.trans("texts.archive_{$entityType}").' </ a ></ li > ' ;
2015-01-11 12:56:58 +01:00
} else {
2015-10-30 13:56:25 +01:00
$str .= '<li><a href="javascript:restoreEntity(' . $model -> public_id . ')">' . trans ( " texts.restore_ { $entityType } " ) . '</a></li>' ;
}
if ( ! $model -> is_deleted ) {
$str .= '<li><a href="javascript:deleteEntity(' . $model -> public_id . ')">' . trans ( " texts.delete_ { $entityType } " ) . '</a></li>' ;
2014-10-14 21:04:48 +02:00
}
2015-01-11 12:56:58 +01:00
return $str . ' </ ul >
</ div > ' ;
})
2014-11-23 22:47:10 +01:00
-> make ();
2014-05-25 20:38:40 +02:00
}
2015-01-11 12:56:58 +01:00
2015-04-22 21:21:04 +02:00
private function getStatusLabel ( $statusId , $statusName ) {
2015-09-07 11:07:55 +02:00
$label = trans ( " texts.status_ " . strtolower ( $statusName ));
2015-04-22 21:21:04 +02:00
$class = 'default' ;
switch ( $statusId ) {
case INVOICE_STATUS_SENT :
$class = 'info' ;
break ;
case INVOICE_STATUS_VIEWED :
$class = 'warning' ;
break ;
case INVOICE_STATUS_PARTIAL :
$class = 'primary' ;
break ;
case INVOICE_STATUS_PAID :
$class = 'success' ;
break ;
}
2015-09-07 11:07:55 +02:00
return " <h4><div class= \" label label- { $class } \" > $label </div></h4> " ;
2015-04-22 21:21:04 +02:00
}
2015-10-28 20:22:07 +01:00
public function save ( $data )
2014-05-20 23:40:09 +02:00
{
2015-10-25 08:13:06 +01:00
$account = \Auth :: user () -> account ;
2015-10-28 20:22:07 +01:00
$publicId = isset ( $data [ 'public_id' ]) ? $data [ 'public_id' ] : false ;
$isNew = ! $publicId || $publicId == '-1' ;
2015-10-25 08:13:06 +01:00
2015-10-28 20:22:07 +01:00
if ( $isNew ) {
$entityType = ENTITY_INVOICE ;
if ( isset ( $data [ 'is_recurring' ]) && $data [ 'is_recurring' ]) {
2015-10-25 08:13:06 +01:00
$entityType = ENTITY_RECURRING_INVOICE ;
2015-10-28 20:22:07 +01:00
} elseif ( isset ( $data [ 'is_quote' ]) && $data [ 'is_quote' ]) {
$entityType = ENTITY_QUOTE ;
2015-01-11 12:56:58 +01:00
}
2015-10-25 08:13:06 +01:00
$invoice = $account -> createInvoice ( $entityType , $data [ 'client_id' ]);
2015-11-02 23:05:28 +01:00
if ( isset ( $data [ 'has_tasks' ]) && $data [ 'has_tasks' ]) {
$invoice -> has_tasks = true ;
}
2015-10-28 20:22:07 +01:00
} else {
$invoice = Invoice :: scope ( $publicId ) -> firstOrFail ();
2015-01-11 12:56:58 +01:00
}
2015-02-27 09:10:23 +01:00
2015-04-13 14:00:31 +02:00
if (( isset ( $data [ 'set_default_terms' ]) && $data [ 'set_default_terms' ])
|| ( isset ( $data [ 'set_default_footer' ]) && $data [ 'set_default_footer' ])) {
if ( isset ( $data [ 'set_default_terms' ]) && $data [ 'set_default_terms' ]) {
2015-10-29 15:42:05 +01:00
$account -> { " { $entityType } _terms " } = trim ( $data [ 'terms' ]);
2015-04-13 14:00:31 +02:00
}
if ( isset ( $data [ 'set_default_footer' ]) && $data [ 'set_default_footer' ]) {
$account -> invoice_footer = trim ( $data [ 'invoice_footer' ]);
}
$account -> save ();
}
2015-10-25 08:49:10 +01:00
if ( isset ( $data [ 'invoice_number' ]) && ! $invoice -> is_recurring ) {
2015-07-30 16:44:47 +02:00
$invoice -> invoice_number = trim ( $data [ 'invoice_number' ]);
}
2015-01-11 12:56:58 +01:00
$invoice -> discount = round ( Utils :: parseFloat ( $data [ 'discount' ]), 2 );
$invoice -> is_amount_discount = $data [ 'is_amount_discount' ] ? true : false ;
2015-04-16 19:12:56 +02:00
$invoice -> partial = round ( Utils :: parseFloat ( $data [ 'partial' ]), 2 );
2015-02-27 09:10:23 +01:00
$invoice -> invoice_date = isset ( $data [ 'invoice_date_sql' ]) ? $data [ 'invoice_date_sql' ] : Utils :: toSqlDate ( $data [ 'invoice_date' ]);
2015-11-02 23:05:28 +01:00
2015-01-11 12:56:58 +01:00
if ( $invoice -> is_recurring ) {
2015-09-20 23:05:02 +02:00
if ( $invoice -> start_date && $invoice -> start_date != Utils :: toSqlDate ( $data [ 'start_date' ])) {
$invoice -> last_sent_date = null ;
}
2015-01-11 12:56:58 +01:00
$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 ;
2015-09-10 19:50:09 +02:00
$invoice -> auto_bill = isset ( $data [ 'auto_bill' ]) && $data [ 'auto_bill' ] ? true : false ;
2015-01-11 12:56:58 +01:00
} else {
2015-02-27 09:10:23 +01:00
$invoice -> due_date = isset ( $data [ 'due_date_sql' ]) ? $data [ 'due_date_sql' ] : Utils :: toSqlDate ( $data [ 'due_date' ]);
2015-01-11 12:56:58 +01:00
$invoice -> frequency_id = 0 ;
$invoice -> start_date = null ;
$invoice -> end_date = null ;
}
2015-04-27 14:28:40 +02:00
$invoice -> terms = trim ( $data [ 'terms' ]) ? trim ( $data [ 'terms' ]) : ( ! $publicId && $account -> invoice_terms ? $account -> invoice_terms : '' );
$invoice -> invoice_footer = trim ( $data [ 'invoice_footer' ]) ? trim ( $data [ 'invoice_footer' ]) : ( ! $publicId && $account -> invoice_footer ? $account -> invoice_footer : '' );
2015-01-11 12:56:58 +01:00
$invoice -> public_notes = trim ( $data [ 'public_notes' ]);
2015-06-03 19:55:48 +02:00
// process date variables
$invoice -> terms = Utils :: processVariables ( $invoice -> terms );
$invoice -> invoice_footer = Utils :: processVariables ( $invoice -> invoice_footer );
$invoice -> public_notes = Utils :: processVariables ( $invoice -> public_notes );
2015-01-11 12:56:58 +01:00
$invoice -> po_number = trim ( $data [ 'po_number' ]);
$invoice -> invoice_design_id = $data [ 'invoice_design_id' ];
2015-01-25 07:48:40 +01:00
if ( isset ( $data [ 'tax_name' ]) && isset ( $data [ 'tax_rate' ]) && $data [ 'tax_name' ]) {
2015-01-11 12:56:58 +01:00
$invoice -> tax_rate = Utils :: parseFloat ( $data [ 'tax_rate' ]);
$invoice -> tax_name = trim ( $data [ 'tax_name' ]);
} else {
$invoice -> tax_rate = 0 ;
$invoice -> tax_name = '' ;
}
$total = 0 ;
2015-08-12 21:16:02 +02:00
$itemTax = 0 ;
2015-01-11 12:56:58 +01:00
foreach ( $data [ 'invoice_items' ] as $item ) {
2015-02-27 09:10:23 +01:00
$item = ( array ) $item ;
if ( ! $item [ 'cost' ] && ! $item [ 'product_key' ] && ! $item [ 'notes' ]) {
2015-01-11 12:56:58 +01:00
continue ;
}
2015-03-10 12:15:01 +01:00
$invoiceItemCost = round ( Utils :: parseFloat ( $item [ 'cost' ]), 2 );
$invoiceItemQty = round ( Utils :: parseFloat ( $item [ 'qty' ]), 2 );
2015-01-11 12:56:58 +01:00
2015-08-12 21:16:02 +02:00
$lineTotal = $invoiceItemCost * $invoiceItemQty ;
$total += round ( $lineTotal , 2 );
}
foreach ( $data [ 'invoice_items' ] as $item ) {
$item = ( array ) $item ;
2015-02-27 09:10:23 +01:00
if ( isset ( $item [ 'tax_rate' ]) && Utils :: parseFloat ( $item [ 'tax_rate' ]) > 0 ) {
2015-08-12 21:16:02 +02:00
$invoiceItemCost = round ( Utils :: parseFloat ( $item [ 'cost' ]), 2 );
$invoiceItemQty = round ( Utils :: parseFloat ( $item [ 'qty' ]), 2 );
2015-02-27 09:10:23 +01:00
$invoiceItemTaxRate = Utils :: parseFloat ( $item [ 'tax_rate' ]);
2015-08-12 21:16:02 +02:00
$lineTotal = $invoiceItemCost * $invoiceItemQty ;
2015-01-11 12:56:58 +01:00
2015-08-12 21:16:02 +02:00
if ( $invoice -> discount > 0 ) {
if ( $invoice -> is_amount_discount ) {
$lineTotal -= round (( $lineTotal / $total ) * $invoice -> discount , 2 );
} else {
$lineTotal -= round ( $lineTotal * ( $invoice -> discount / 100 ), 2 );
}
}
2015-01-11 12:56:58 +01:00
2015-08-12 21:16:02 +02:00
$itemTax += round ( $lineTotal * $invoiceItemTaxRate / 100 , 2 );
}
2015-01-11 12:56:58 +01:00
}
if ( $invoice -> discount > 0 ) {
if ( $invoice -> is_amount_discount ) {
$total -= $invoice -> discount ;
} else {
$total *= ( 100 - $invoice -> discount ) / 100 ;
}
}
2015-10-28 20:22:07 +01:00
if ( isset ( $data [ 'custom_value1' ])) {
$invoice -> custom_value1 = round ( $data [ 'custom_value1' ], 2 );
if ( $isNew ) {
$invoice -> custom_taxes1 = $account -> custom_invoice_taxes1 ? : false ;
}
}
if ( isset ( $data [ 'custom_value2' ])) {
$invoice -> custom_value2 = round ( $data [ 'custom_value2' ], 2 );
if ( $isNew ) {
$invoice -> custom_taxes2 = $account -> custom_invoice_taxes2 ? : false ;
}
}
2015-10-11 16:41:09 +02:00
if ( isset ( $data [ 'custom_text_value1' ])) {
$invoice -> custom_text_value1 = trim ( $data [ 'custom_text_value1' ]);
}
if ( isset ( $data [ 'custom_text_value2' ])) {
$invoice -> custom_text_value2 = trim ( $data [ 'custom_text_value2' ]);
}
2015-01-11 12:56:58 +01:00
// 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 ;
}
$total += $total * $invoice -> tax_rate / 100 ;
$total = round ( $total , 2 );
2015-08-12 21:16:02 +02:00
$total += $itemTax ;
2015-01-11 12:56:58 +01: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 ;
}
if ( $publicId ) {
$invoice -> balance = $total - ( $invoice -> amount - $invoice -> balance );
} else {
$invoice -> balance = $total ;
}
$invoice -> amount = $total ;
$invoice -> save ();
2015-02-27 09:10:23 +01:00
if ( $publicId ) {
$invoice -> invoice_items () -> forceDelete ();
}
2015-01-11 12:56:58 +01:00
foreach ( $data [ 'invoice_items' ] as $item ) {
2015-02-27 09:10:23 +01:00
$item = ( array ) $item ;
if ( ! $item [ 'cost' ] && ! $item [ 'product_key' ] && ! $item [ 'notes' ]) {
2015-01-11 12:56:58 +01:00
continue ;
}
2015-05-27 18:52:10 +02:00
if ( isset ( $item [ 'task_public_id' ]) && $item [ 'task_public_id' ]) {
$task = Task :: scope ( $item [ 'task_public_id' ]) -> where ( 'invoice_id' , '=' , null ) -> firstOrFail ();
$task -> invoice_id = $invoice -> id ;
2015-05-27 22:20:35 +02:00
$task -> client_id = $invoice -> client_id ;
2015-05-27 18:52:10 +02:00
$task -> save ();
2015-07-30 19:48:59 +02:00
} else if ( $item [ 'product_key' ] && ! $invoice -> has_tasks ) {
2015-02-27 09:10:23 +01:00
$product = Product :: findProductByKey ( trim ( $item [ 'product_key' ]));
2015-01-11 12:56:58 +01:00
if ( \Auth :: user () -> account -> update_products ) {
2015-08-13 07:45:48 +02:00
if ( ! $product ) {
$product = Product :: createNew ();
$product -> product_key = trim ( $item [ 'product_key' ]);
}
2015-02-27 09:10:23 +01:00
$product -> notes = $item [ 'notes' ];
$product -> cost = $item [ 'cost' ];
2015-08-13 07:45:48 +02:00
$product -> save ();
2015-01-11 12:56:58 +01:00
}
}
$invoiceItem = InvoiceItem :: createNew ();
$invoiceItem -> product_id = isset ( $product ) ? $product -> id : null ;
2015-03-17 14:43:13 +01:00
$invoiceItem -> product_key = trim ( $invoice -> is_recurring ? $item [ 'product_key' ] : Utils :: processVariables ( $item [ 'product_key' ]));
2015-02-27 09:10:23 +01:00
$invoiceItem -> notes = trim ( $invoice -> is_recurring ? $item [ 'notes' ] : Utils :: processVariables ( $item [ 'notes' ]));
$invoiceItem -> cost = Utils :: parseFloat ( $item [ 'cost' ]);
$invoiceItem -> qty = Utils :: parseFloat ( $item [ 'qty' ]);
2015-01-11 12:56:58 +01:00
$invoiceItem -> tax_rate = 0 ;
2015-02-27 09:10:23 +01:00
if ( isset ( $item [ 'tax_rate' ]) && isset ( $item [ 'tax_name' ]) && $item [ 'tax_name' ]) {
$invoiceItem [ 'tax_rate' ] = Utils :: parseFloat ( $item [ 'tax_rate' ]);
$invoiceItem [ 'tax_name' ] = trim ( $item [ 'tax_name' ]);
2015-01-11 12:56:58 +01:00
}
$invoice -> invoice_items () -> save ( $invoiceItem );
}
return $invoice ;
2014-05-20 23:40:09 +02:00
}
2015-01-11 12:56:58 +01:00
public function cloneInvoice ( $invoice , $quotePublicId = null )
2014-05-20 23:40:09 +02:00
{
2015-01-11 12:56:58 +01:00
$invoice -> load ( 'invitations' , 'invoice_items' );
$account = $invoice -> account ;
$clone = Invoice :: createNew ( $invoice );
$clone -> balance = $invoice -> amount ;
2014-05-20 23:40:09 +02:00
2015-01-11 12:56:58 +01:00
// if the invoice prefix is diff than quote prefix, use the same number for the invoice
2015-02-08 19:04:36 +01:00
if (( $account -> invoice_number_prefix || $account -> quote_number_prefix )
&& $account -> invoice_number_prefix != $account -> quote_number_prefix
&& $account -> share_counter ) {
2015-01-11 12:56:58 +01:00
$invoiceNumber = $invoice -> invoice_number ;
2015-06-07 10:05:30 +02:00
if ( $account -> quote_number_prefix && strpos ( $invoiceNumber , $account -> quote_number_prefix ) === 0 ) {
2015-01-11 12:56:58 +01:00
$invoiceNumber = substr ( $invoiceNumber , strlen ( $account -> quote_number_prefix ));
}
$clone -> invoice_number = $account -> invoice_number_prefix . $invoiceNumber ;
} else {
2015-10-23 13:55:18 +02:00
$clone -> invoice_number = $account -> getNextInvoiceNumber ( $invoice );
2015-01-11 12:56:58 +01:00
}
2014-05-20 23:40:09 +02:00
2015-01-11 12:56:58 +01:00
foreach ([
'client_id' ,
'discount' ,
'is_amount_discount' ,
'invoice_date' ,
'po_number' ,
'due_date' ,
'is_recurring' ,
'frequency_id' ,
'start_date' ,
'end_date' ,
'terms' ,
2015-02-28 22:42:47 +01:00
'invoice_footer' ,
2015-01-11 12:56:58 +01:00
'public_notes' ,
'invoice_design_id' ,
'tax_name' ,
'tax_rate' ,
'amount' ,
'is_quote' ,
'custom_value1' ,
'custom_value2' ,
'custom_taxes1' ,
2015-06-04 22:53:58 +02:00
'custom_taxes2' ,
2015-10-11 16:41:09 +02:00
'partial' ,
'custom_text_value1' ,
'custom_text_value2' ] as $field ) {
2015-01-11 12:56:58 +01:00
$clone -> $field = $invoice -> $field ;
}
2014-05-20 23:40:09 +02:00
2015-01-11 12:56:58 +01:00
if ( $quotePublicId ) {
$clone -> is_quote = false ;
$clone -> quote_id = $quotePublicId ;
}
2014-01-12 19:55:33 +01:00
2015-01-11 12:56:58 +01:00
$clone -> save ();
2014-01-12 19:55:33 +01:00
2015-01-11 12:56:58 +01:00
if ( $quotePublicId ) {
$invoice -> quote_invoice_id = $clone -> public_id ;
$invoice -> save ();
}
foreach ( $invoice -> invoice_items as $item ) {
$cloneItem = InvoiceItem :: createNew ( $invoice );
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 ) {
$cloneInvitation = Invitation :: createNew ( $invoice );
$cloneInvitation -> contact_id = $invitation -> contact_id ;
$cloneInvitation -> invitation_key = str_random ( RANDOM_KEY_LENGTH );
$clone -> invitations () -> save ( $cloneInvitation );
}
return $clone ;
}
2015-10-29 15:42:05 +01:00
public function markSent ( $invoice )
2015-01-11 12:56:58 +01:00
{
2015-10-29 15:42:05 +01:00
$invoice -> markInvitationsSent ();
2015-01-11 12:56:58 +01:00
}
2015-07-12 21:43:45 +02:00
2015-10-13 09:11:44 +02:00
public function findInvoiceByInvitation ( $invitationKey )
{
$invitation = Invitation :: where ( 'invitation_key' , '=' , $invitationKey ) -> first ();
2015-10-20 19:12:34 +02:00
2015-10-13 09:11:44 +02:00
if ( ! $invitation ) {
2015-10-20 19:12:34 +02:00
return false ;
2015-10-13 09:11:44 +02:00
}
$invoice = $invitation -> invoice ;
if ( ! $invoice || $invoice -> is_deleted ) {
2015-10-20 19:12:34 +02:00
return false ;
2015-10-13 09:11:44 +02:00
}
$invoice -> load ( 'user' , 'invoice_items' , 'invoice_design' , 'account.country' , 'client.contacts' , 'client.country' );
$client = $invoice -> client ;
if ( ! $client || $client -> is_deleted ) {
2015-10-20 19:12:34 +02:00
return false ;
2015-10-13 09:11:44 +02:00
}
return $invitation ;
}
2015-07-12 21:43:45 +02:00
public function findOpenInvoices ( $clientId )
{
return Invoice :: scope ()
-> whereClientId ( $clientId )
-> whereIsQuote ( false )
-> whereIsRecurring ( false )
2015-07-30 16:44:47 +02:00
-> whereDeletedAt ( null )
2015-07-12 21:43:45 +02:00
-> whereHasTasks ( true )
2015-07-30 16:44:47 +02:00
-> where ( 'invoice_status_id' , '<' , 5 )
2015-07-12 21:43:45 +02:00
-> select ([ 'public_id' , 'invoice_number' ])
-> get ();
}
2015-08-10 17:48:41 +02:00
public function createRecurringInvoice ( $recurInvoice )
{
$recurInvoice -> load ( 'account.timezone' , 'invoice_items' , 'client' , 'user' );
if ( $recurInvoice -> client -> deleted_at ) {
return false ;
}
if ( ! $recurInvoice -> user -> confirmed ) {
return false ;
}
if ( ! $recurInvoice -> shouldSendToday ()) {
return false ;
}
$invoice = Invoice :: createNew ( $recurInvoice );
$invoice -> client_id = $recurInvoice -> client_id ;
$invoice -> recurring_invoice_id = $recurInvoice -> id ;
2015-10-25 08:49:10 +01:00
$invoice -> invoice_number = 'R' . $recurInvoice -> account -> getNextInvoiceNumber ( $recurInvoice );
2015-08-10 17:48:41 +02:00
$invoice -> amount = $recurInvoice -> amount ;
$invoice -> balance = $recurInvoice -> amount ;
$invoice -> invoice_date = date_create () -> format ( 'Y-m-d' );
$invoice -> discount = $recurInvoice -> discount ;
$invoice -> po_number = $recurInvoice -> po_number ;
$invoice -> public_notes = Utils :: processVariables ( $recurInvoice -> public_notes );
$invoice -> terms = Utils :: processVariables ( $recurInvoice -> terms );
$invoice -> invoice_footer = Utils :: processVariables ( $recurInvoice -> invoice_footer );
$invoice -> tax_name = $recurInvoice -> tax_name ;
$invoice -> tax_rate = $recurInvoice -> tax_rate ;
$invoice -> invoice_design_id = $recurInvoice -> invoice_design_id ;
2015-10-28 20:22:07 +01:00
$invoice -> custom_value1 = $recurInvoice -> custom_value1 ? : 0 ;
$invoice -> custom_value2 = $recurInvoice -> custom_value2 ? : 0 ;
$invoice -> custom_taxes1 = $recurInvoice -> custom_taxes1 ? : 0 ;
$invoice -> custom_taxes2 = $recurInvoice -> custom_taxes2 ? : 0 ;
2015-10-11 16:41:09 +02:00
$invoice -> custom_text_value1 = $recurInvoice -> custom_text_value1 ;
$invoice -> custom_text_value2 = $recurInvoice -> custom_text_value2 ;
2015-08-10 17:48:41 +02:00
$invoice -> is_amount_discount = $recurInvoice -> is_amount_discount ;
if ( $invoice -> client -> payment_terms != 0 ) {
$days = $invoice -> client -> payment_terms ;
if ( $days == - 1 ) {
$days = 0 ;
}
$invoice -> due_date = date_create () -> modify ( $days . ' day' ) -> format ( 'Y-m-d' );
}
$invoice -> save ();
foreach ( $recurInvoice -> invoice_items as $recurItem ) {
$item = InvoiceItem :: createNew ( $recurItem );
$item -> product_id = $recurItem -> product_id ;
$item -> qty = $recurItem -> qty ;
$item -> cost = $recurItem -> cost ;
$item -> notes = Utils :: processVariables ( $recurItem -> notes );
$item -> product_key = Utils :: processVariables ( $recurItem -> product_key );
$item -> tax_name = $recurItem -> tax_name ;
$item -> tax_rate = $recurItem -> tax_rate ;
$invoice -> invoice_items () -> save ( $item );
}
foreach ( $recurInvoice -> invitations as $recurInvitation ) {
$invitation = Invitation :: createNew ( $recurInvitation );
$invitation -> contact_id = $recurInvitation -> contact_id ;
$invitation -> invitation_key = str_random ( RANDOM_KEY_LENGTH );
$invoice -> invitations () -> save ( $invitation );
}
2015-09-10 19:50:09 +02:00
$recurInvoice -> last_sent_date = date ( 'Y-m-d' );
2015-08-10 17:48:41 +02:00
$recurInvoice -> save ();
2015-09-10 19:50:09 +02:00
if ( $recurInvoice -> auto_bill ) {
if ( $this -> paymentService -> autoBillInvoice ( $invoice )) {
$invoice -> invoice_status_id = INVOICE_STATUS_PAID ;
}
}
2015-08-10 17:48:41 +02:00
return $invoice ;
}
2015-09-17 21:01:06 +02:00
public function findNeedingReminding ( $account )
{
$dates = [];
for ( $i = 1 ; $i <= 3 ; $i ++ ) {
$field = " enable_reminder { $i } " ;
if ( ! $account -> $field ) {
continue ;
}
$field = " num_days_reminder { $i } " ;
$dates [] = " due_date = ' " . date ( 'Y-m-d' , strtotime ( " - { $account -> $field } days " )) . " ' " ;
}
$sql = implode ( ' OR ' , $dates );
$invoices = Invoice :: whereAccountId ( $account -> id )
-> where ( 'balance' , '>' , 0 )
2015-10-06 19:55:55 +02:00
-> whereRaw ( '(' . $sql . ')' )
2015-09-17 21:01:06 +02:00
-> get ();
return $invoices ;
}
2013-12-25 22:34:42 +01:00
}