mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
bug fixes
This commit is contained in:
parent
472d2c9249
commit
5b13f2d8ef
@ -44,7 +44,6 @@ class SendRecurringInvoices extends Command {
|
||||
$invoice->invoice_number = 'R' . $recurInvoice->account->getNextInvoiceNumber();
|
||||
$invoice->amount = $recurInvoice->amount;
|
||||
$invoice->balance = $recurInvoice->amount;
|
||||
$invoice->currency_id = $recurInvoice->currency_id;
|
||||
$invoice->invoice_date = date_create()->format('Y-m-d');
|
||||
|
||||
if ($invoice->client->payment_terms)
|
||||
|
@ -71,7 +71,7 @@ return array(
|
||||
*/
|
||||
|
||||
'email_reset_password' => 'confide::emails.passwordreset', // with $user and $token.
|
||||
'email_account_confirmation' => 'confide::emails.confirm', // with $user
|
||||
'email_account_confirmation' => 'emails.confirm_html', // with $user
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -44,9 +44,9 @@ class AccountController extends \BaseController {
|
||||
$random = str_random(RANDOM_KEY_LENGTH);
|
||||
|
||||
$user = new User;
|
||||
$user->username = $random;
|
||||
$user->password = $random;
|
||||
$user->password_confirmation = $random;
|
||||
$user->username = $random;
|
||||
$account->users()->save($user);
|
||||
|
||||
Session::forget(RECENTLY_VIEWED);
|
||||
@ -486,7 +486,7 @@ class AccountController extends \BaseController {
|
||||
$user->username = trim(Input::get('email'));
|
||||
$user->email = trim(Input::get('email'));
|
||||
$user->phone = trim(Input::get('phone'));
|
||||
$user->amend(); // need to 'amend' to avoid password validation rules
|
||||
$user->save();
|
||||
|
||||
/* Logo image file */
|
||||
if ($file = Input::file('logo'))
|
||||
@ -520,7 +520,7 @@ class AccountController extends \BaseController {
|
||||
'new_first_name' => 'required',
|
||||
'new_last_name' => 'required',
|
||||
'new_password' => 'required|min:6',
|
||||
'new_email' => 'email|required'
|
||||
'new_email' => 'email|required|unique:users,email,' . Auth::user()->id . ',id'
|
||||
);
|
||||
|
||||
$validator = Validator::make(Input::all(), $rules);
|
||||
@ -537,7 +537,7 @@ class AccountController extends \BaseController {
|
||||
$user->password = trim(Input::get('new_password'));
|
||||
$user->password_confirmation = trim(Input::get('new_password'));
|
||||
$user->registered = true;
|
||||
$user->save();
|
||||
$user->amend();
|
||||
|
||||
$activities = Activity::scope()->get();
|
||||
foreach ($activities as $activity)
|
||||
|
@ -8,7 +8,7 @@ class ActivityController extends \BaseController {
|
||||
->join('clients', 'clients.id', '=', 'activities.client_id')
|
||||
->where('clients.public_id', '=', $clientPublicId)
|
||||
->where('activities.account_id', '=', Auth::user()->account_id)
|
||||
->select('activities.message', 'activities.created_at', 'activities.currency_id', 'activities.balance', 'activities.adjustment');
|
||||
->select('activities.message', 'activities.created_at', 'clients.currency_id', 'activities.balance', 'activities.adjustment');
|
||||
|
||||
return Datatable::query($query)
|
||||
->addColumn('created_at', function($model) { return Utils::timestampToDateTimeString(strtotime($model->created_at)); })
|
||||
|
@ -104,6 +104,7 @@ class ClientController extends \BaseController {
|
||||
|
||||
$data = array(
|
||||
'client' => $client,
|
||||
'credit' => $client->getTotalCredit(),
|
||||
'title' => '- ' . $client->getDisplayName(),
|
||||
'hasRecurringInvoices' => Invoice::scope()->where('is_recurring', '=', true)->whereClientId($client->id)->count() > 0
|
||||
);
|
||||
|
@ -23,7 +23,7 @@ class CreditController extends \BaseController {
|
||||
return View::make('list', array(
|
||||
'entityType'=>ENTITY_CREDIT,
|
||||
'title' => '- Credits',
|
||||
'columns'=>['checkbox', 'Client', 'Credit Amount', 'Credit Date', 'Private Notes', 'Action']
|
||||
'columns'=>['checkbox', 'Client', 'Credit Amount', 'Credit Balance', 'Credit Date', 'Private Notes', 'Action']
|
||||
));
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ class CreditController extends \BaseController {
|
||||
}
|
||||
|
||||
return $table->addColumn('amount', function($model){ return Utils::formatMoney($model->amount, $model->currency_id); })
|
||||
->addColumn('balance', function($model){ return Utils::formatMoney($model->balance, $model->currency_id); })
|
||||
->addColumn('credit_date', function($model) { return Utils::fromSqlDate($model->credit_date); })
|
||||
->addColumn('private_notes', function($model) { return $model->private_notes; })
|
||||
->addColumn('dropdown', function($model)
|
||||
@ -58,17 +59,17 @@ class CreditController extends \BaseController {
|
||||
}
|
||||
|
||||
|
||||
public function create($clientPublicId = 0, $invoicePublicId = 0)
|
||||
public function create($clientPublicId = 0)
|
||||
{
|
||||
$data = array(
|
||||
'clientPublicId' => Input::old('client') ? Input::old('client') : $clientPublicId,
|
||||
'invoicePublicId' => Input::old('invoice') ? Input::old('invoice') : $invoicePublicId,
|
||||
//'invoicePublicId' => Input::old('invoice') ? Input::old('invoice') : $invoicePublicId,
|
||||
'credit' => null,
|
||||
'method' => 'POST',
|
||||
'url' => 'credits',
|
||||
'title' => '- New Credit',
|
||||
//'currencies' => Currency::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(),
|
||||
'invoices' => Invoice::scope()->with('client', 'invoice_status')->orderBy('invoice_number')->get(),
|
||||
//'invoices' => Invoice::scope()->with('client', 'invoice_status')->orderBy('invoice_number')->get(),
|
||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get());
|
||||
|
||||
return View::make('credits.edit', $data);
|
||||
|
@ -67,9 +67,7 @@ class InvoiceController extends \BaseController {
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="' . URL::to('invoices/'.$model->public_id.'/edit') . '">Edit Invoice</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="' . URL::to('payments/create/' . $model->client_public_id . '/' . $model->public_id ) . '">Enter Payment</a></li>
|
||||
<li><a href="' . URL::to('credits/create/' . $model->client_public_id . '/' . $model->public_id ) . '">Enter Credit</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="javascript:archiveEntity(' . $model->public_id . ')">Archive Invoice</a></li>
|
||||
<li><a href="javascript:deleteEntity(' . $model->public_id . ')">Delete Invoice</a></li>
|
||||
@ -216,7 +214,6 @@ class InvoiceController extends \BaseController {
|
||||
$payment->invoice_id = $invoice->id;
|
||||
$payment->amount = $invoice->amount;
|
||||
$payment->client_id = $invoice->client_id;
|
||||
$payment->currency_id = $invoice->currency_id ? $invoice->currency_id : 0;
|
||||
$payment->contact_id = $invitation->contact_id;
|
||||
$payment->transaction_reference = $ref;
|
||||
$payment->payment_date = date_create();
|
||||
@ -519,7 +516,7 @@ class InvoiceController extends \BaseController {
|
||||
$invoice = Invoice::with('invoice_items')->scope($publicId)->firstOrFail();
|
||||
|
||||
$clone = Invoice::createNew();
|
||||
foreach (['client_id', 'discount', 'invoice_date', 'due_date', 'is_recurring', 'frequency_id', 'start_date', 'end_date', 'terms', 'currency_id'] as $field)
|
||||
foreach (['client_id', 'discount', 'invoice_date', 'due_date', 'is_recurring', 'frequency_id', 'start_date', 'end_date', 'terms'] as $field)
|
||||
{
|
||||
$clone->$field = $invoice->$field;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class PaymentController extends \BaseController
|
||||
return View::make('list', array(
|
||||
'entityType'=>ENTITY_PAYMENT,
|
||||
'title' => '- Payments',
|
||||
'columns'=>['checkbox', 'Transaction Reference', 'Method', 'Client', 'Invoice', 'Payment Amount', 'Payment Date', 'Action']
|
||||
'columns'=>['checkbox', 'Invoice', 'Client', 'Transaction Reference', 'Method', 'Payment Amount', 'Payment Date', 'Action']
|
||||
));
|
||||
}
|
||||
|
||||
@ -31,16 +31,16 @@ class PaymentController extends \BaseController
|
||||
$table->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; });
|
||||
}
|
||||
|
||||
$table->addColumn('transaction_reference', function($model) { return $model->transaction_reference ? $model->transaction_reference : '<i>Manual entry</i>'; })
|
||||
->addColumn('method', function($model) { return $model->payment_type ? $model->payment_type : ($model->transaction_reference ? '<i>Online payment</i>' : ''); });
|
||||
|
||||
$table->addColumn('invoice_number', function($model) { return $model->invoice_public_id ? link_to('invoices/' . $model->invoice_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)); });
|
||||
}
|
||||
|
||||
return $table->addColumn('invoice_number', function($model) { return $model->invoice_public_id ? link_to('invoices/' . $model->invoice_public_id . '/edit', $model->invoice_number) : ''; })
|
||||
->addColumn('amount', function($model) { return Utils::formatMoney($model->amount, $model->currency_id); })
|
||||
$table->addColumn('transaction_reference', function($model) { return $model->transaction_reference ? $model->transaction_reference : '<i>Manual entry</i>'; })
|
||||
->addColumn('method', function($model) { return $model->payment_type ? $model->payment_type : ($model->transaction_reference ? '<i>Online payment</i>' : ''); });
|
||||
|
||||
return $table->addColumn('amount', function($model) { return Utils::formatMoney($model->amount, $model->currency_id); })
|
||||
->addColumn('payment_date', function($model) { return Utils::dateToString($model->payment_date); })
|
||||
->addColumn('dropdown', function($model)
|
||||
{
|
||||
@ -107,18 +107,11 @@ class PaymentController extends \BaseController
|
||||
|
||||
private function save($publicId = null)
|
||||
{
|
||||
$rules = array(
|
||||
'client' => 'required',
|
||||
'invoice' => 'required',
|
||||
'amount' => 'required|positive'
|
||||
);
|
||||
$validator = Validator::make(Input::all(), $rules);
|
||||
|
||||
if ($validator->fails())
|
||||
if ($errors = $this->paymentRepo->getErrors(Input::all()))
|
||||
{
|
||||
$url = $publicId ? 'payments/' . $publicId . '/edit' : 'payments/create';
|
||||
return Redirect::to($url)
|
||||
->withErrors($validator)
|
||||
->withErrors($errors)
|
||||
->withInput();
|
||||
}
|
||||
else
|
||||
|
@ -464,23 +464,20 @@ class ConfideSetupUsersTable extends Migration {
|
||||
{
|
||||
$t->increments('id');
|
||||
$t->unsignedInteger('account_id')->index();
|
||||
$t->unsignedInteger('client_id')->index();
|
||||
$t->unsignedInteger('user_id');
|
||||
$t->unsignedInteger('client_id')->index()->nullable();
|
||||
$t->unsignedInteger('invoice_id')->nullable();
|
||||
$t->unsignedInteger('contact_id')->nullable();
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
|
||||
$t->boolean('is_deleted');
|
||||
$t->decimal('amount', 13, 4);
|
||||
$t->decimal('balance', 13, 4);
|
||||
$t->date('credit_date')->nullable();
|
||||
$t->string('credit_number');
|
||||
$t->text('private_notes');
|
||||
|
||||
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
$t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
|
||||
$t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
|
||||
$t->foreign('contact_id')->references('id')->on('contacts');
|
||||
$t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');;
|
||||
|
||||
$t->unsignedInteger('public_id')->index();
|
||||
@ -500,7 +497,6 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->unsignedInteger('invoice_id');
|
||||
$t->unsignedInteger('credit_id');
|
||||
$t->unsignedInteger('invitation_id');
|
||||
$t->unsignedInteger('currency_id')->nullable();
|
||||
|
||||
$t->text('message');
|
||||
$t->text('json_backup');
|
||||
@ -510,7 +506,6 @@ class ConfideSetupUsersTable extends Migration {
|
||||
|
||||
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
$t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
|
||||
$t->foreign('currency_id')->references('id')->on('currencies');
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,8 @@ return array(
|
||||
"url" => "The :attribute format is invalid.",
|
||||
|
||||
"positive" => "The :attribute must be greater than zero.",
|
||||
"has_credit" => "The client does not have enough credit.",
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -108,7 +108,6 @@ class Activity extends Eloquent
|
||||
$activity = Activity::getBlank($invoice);
|
||||
$activity->invoice_id = $invoice->id;
|
||||
$activity->client_id = $invoice->client_id;
|
||||
$activity->currency_id = $invoice->client->currency_id;
|
||||
$activity->activity_type_id = ACTIVITY_TYPE_CREATE_INVOICE;
|
||||
$activity->message = $message;
|
||||
$activity->balance = $invoice->client->balance;
|
||||
@ -268,13 +267,14 @@ class Activity extends Eloquent
|
||||
if (Auth::check())
|
||||
{
|
||||
$activity = Activity::getBlank();
|
||||
$activity->message = Utils::encodeActivity(Auth::user(), 'created payment');
|
||||
$message = $payment->payment_type_id == PAYMENT_TYPE_CREDIT ? 'applied credit' : 'entered payment';
|
||||
$activity->message = Utils::encodeActivity(Auth::user(), $message);
|
||||
}
|
||||
else
|
||||
{
|
||||
$activity = new Activity;
|
||||
$activity->contact_id = $payment->contact_id;
|
||||
$activity->message = Utils::encodeActivity($payment->invitation->contact, 'created payment');
|
||||
$activity->message = Utils::encodeActivity($payment->invitation->contact, 'entered payment');
|
||||
}
|
||||
|
||||
$activity->payment_id = $payment->id;
|
||||
@ -288,8 +288,8 @@ class Activity extends Eloquent
|
||||
$invoice->save();
|
||||
}
|
||||
|
||||
$activity->payment_id = $payment->id;
|
||||
$activity->client_id = $payment->client_id;
|
||||
$activity->currency_id = $client->currency_id;
|
||||
$activity->activity_type_id = ACTIVITY_TYPE_CREATE_PAYMENT;
|
||||
$activity->balance = $client->balance;
|
||||
$activity->adjustment = $payment->amount * -1;
|
||||
@ -310,6 +310,7 @@ class Activity extends Eloquent
|
||||
$invoice->save();
|
||||
|
||||
$activity = Activity::getBlank();
|
||||
$activity->payment_id = $payment->id;
|
||||
$activity->client_id = $invoice->client_id;
|
||||
$activity->invoice_id = $invoice->id;
|
||||
$activity->activity_type_id = ACTIVITY_TYPE_DELETE_PAYMENT;
|
||||
@ -362,6 +363,7 @@ class Activity extends Eloquent
|
||||
$invoice->save();
|
||||
|
||||
$activity = Activity::getBlank();
|
||||
$activity->payment_id = $payment->id;
|
||||
$activity->invoice_id = $invoice->id;
|
||||
$activity->client_id = $client->id;
|
||||
$activity->activity_type_id = ACTIVITY_TYPE_ARCHIVE_PAYMENT;
|
||||
@ -374,28 +376,12 @@ class Activity extends Eloquent
|
||||
|
||||
public static function createCredit($credit)
|
||||
{
|
||||
$client = $credit->client;
|
||||
$client->balance = $client->balance - $credit->amount;
|
||||
$client->save();
|
||||
|
||||
$activity = Activity::getBlank();
|
||||
$activity->message = Utils::encodeActivity(Auth::user(), 'created credit');
|
||||
$activity->message = Utils::encodeActivity(Auth::user(), 'entered ' . Utils::formatMoney($credit->amount, $credit->client->currency_id) . ' credit');
|
||||
$activity->credit_id = $credit->id;
|
||||
$activity->client_id = $credit->client_id;
|
||||
|
||||
if ($credit->invoice_id)
|
||||
{
|
||||
$activity->invoice_id = $credit->invoice_id;
|
||||
|
||||
$invoice = $credit->invoice;
|
||||
$invoice->balance = $invoice->balance - $credit->amount;
|
||||
$invoice->save();
|
||||
}
|
||||
|
||||
$activity->currency_id = $client->currency_id;
|
||||
$activity->activity_type_id = ACTIVITY_TYPE_CREATE_CREDIT;
|
||||
$activity->balance = $client->balance;
|
||||
$activity->adjustment = $credit->amount * -1;
|
||||
$activity->balance = $credit->client->balance;
|
||||
$activity->save();
|
||||
}
|
||||
|
||||
@ -403,24 +389,12 @@ class Activity extends Eloquent
|
||||
{
|
||||
if ($credit->is_deleted && !$credit->getOriginal('is_deleted'))
|
||||
{
|
||||
$client = $credit->client;
|
||||
$client->balance = $client->balance + $credit->amount;
|
||||
$client->save();
|
||||
|
||||
if ($credit->invoice)
|
||||
{
|
||||
$invoice = $credit->invoice;
|
||||
$invoice->balance = $invoice->balance + $credit->amount;
|
||||
$invoice->save();
|
||||
}
|
||||
|
||||
$activity = Activity::getBlank();
|
||||
$activity->client_id = $invoice->client_id;
|
||||
$activity->invoice_id = $credit->invoice ? $credit->invoice->id : null;
|
||||
$activity->credit_id = $credit->id;
|
||||
$activity->client_id = $credit->client_id;
|
||||
$activity->activity_type_id = ACTIVITY_TYPE_DELETE_CREDIT;
|
||||
$activity->message = Utils::encodeActivity(Auth::user(), 'deleted credit');
|
||||
$activity->balance = $client->balance;
|
||||
$activity->adjustment = $credit->amount;
|
||||
$activity->message = Utils::encodeActivity(Auth::user(), 'deleted ' . Utils::formatMoney($credit->balance, $credit->client->currency_id) . ' credit');
|
||||
$activity->balance = $credit->client->balance;
|
||||
$activity->save();
|
||||
}
|
||||
else
|
||||
@ -457,24 +431,12 @@ class Activity extends Eloquent
|
||||
return;
|
||||
}
|
||||
|
||||
$client = $credit->client;
|
||||
$client->balance = $client->balance + $credit->amount;
|
||||
$client->save();
|
||||
|
||||
if ($credit->invoice)
|
||||
{
|
||||
$invoice = $credit->invoice;
|
||||
$invoice->balance = $invoice->balance + $credit->amount;
|
||||
$invoice->save();
|
||||
}
|
||||
|
||||
$activity = Activity::getBlank();
|
||||
$activity->invoice_id = $credit->invoice ? $credit->invoice->id : null;
|
||||
$activity->client_id = $client->id;
|
||||
$activity->credit_id = $credit->id;
|
||||
$activity->activity_type_id = ACTIVITY_TYPE_ARCHIVE_CREDIT;
|
||||
$activity->message = Utils::encodeActivity(Auth::user(), 'archived credit');
|
||||
$activity->balance = $client->balance;
|
||||
$activity->adjustment = $credit->amount;
|
||||
$activity->message = Utils::encodeActivity(Auth::user(), 'archived ' . Utils::formatMoney($credit->balance, $credit->client->currency_id) . ' credit');
|
||||
$activity->balance = $credit->client->balance;
|
||||
$activity->save();
|
||||
}
|
||||
}
|
@ -47,6 +47,14 @@ class Client extends EntityModel
|
||||
return $this->belongsTo('Industry');
|
||||
}
|
||||
|
||||
public function getTotalCredit()
|
||||
{
|
||||
return DB::table('credits')
|
||||
->where('client_id','=',$this->id)
|
||||
->whereNull('deleted_at')
|
||||
->sum('balance');
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->getDisplayName();
|
||||
|
@ -21,6 +21,24 @@ class Credit extends EntityModel
|
||||
{
|
||||
return ENTITY_CREDIT;
|
||||
}
|
||||
|
||||
public function apply($amount)
|
||||
{
|
||||
if ($amount > $this->balance)
|
||||
{
|
||||
$applied = $this->balance;
|
||||
$this->balance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$applied = $amount;
|
||||
$this->balance = $this->balance - $amount;
|
||||
}
|
||||
|
||||
$this->save();
|
||||
|
||||
return $applied;
|
||||
}
|
||||
}
|
||||
|
||||
Credit::created(function($credit)
|
||||
|
@ -9,14 +9,18 @@ class User extends ConfideUser implements UserInterface, RemindableInterface
|
||||
protected $softDelete = true;
|
||||
|
||||
public static $rules = array(
|
||||
/*
|
||||
'username' => 'required|unique:users',
|
||||
'password' => 'required|between:6,32|confirmed',
|
||||
'password_confirmation' => 'between:6,32',
|
||||
*/
|
||||
);
|
||||
|
||||
protected $updateRules = array(
|
||||
/*
|
||||
'email' => 'required|unique:users',
|
||||
'username' => 'required|unique:users',
|
||||
*/
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@ class CreditRepository
|
||||
->where('clients.deleted_at', '=', null)
|
||||
->where('credits.deleted_at', '=', null)
|
||||
->where('contacts.is_primary', '=', true)
|
||||
->select('credits.public_id', 'clients.name as client_name', 'clients.public_id as client_public_id', 'credits.amount', 'credits.credit_date', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'credits.private_notes');
|
||||
->select('credits.public_id', 'clients.name as client_name', 'clients.public_id as client_public_id', 'credits.amount', 'credits.balance', 'credits.credit_date', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'credits.private_notes');
|
||||
|
||||
if ($clientPublicId)
|
||||
{
|
||||
@ -47,9 +47,8 @@ class CreditRepository
|
||||
|
||||
$credit->client_id = Client::getPrivateId($input['client']);
|
||||
$credit->credit_date = Utils::toSqlDate($input['credit_date']);
|
||||
$credit->invoice_id = isset($input['invoice']) && $input['invoice'] != "-1" ? Invoice::getPrivateId($input['invoice']) : null;
|
||||
$credit->amount = Utils::parseFloat($input['amount']);
|
||||
//$credit->currency_id = $input['currency_id'] ? $input['currency_id'] : null;
|
||||
$credit->balance = Utils::parseFloat($input['amount']);
|
||||
$credit->private_notes = trim($input['private_notes']);
|
||||
$credit->save();
|
||||
|
||||
|
@ -122,7 +122,6 @@ class InvoiceRepository
|
||||
$invoice->terms = trim($data['terms']);
|
||||
$invoice->public_notes = trim($data['public_notes']);
|
||||
$invoice->po_number = trim($data['po_number']);
|
||||
//$invoice->currency_id = $data['currency_id'];
|
||||
|
||||
if (isset($data['tax_rate']) && Utils::parseFloat($data['tax_rate']) > 0)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php namespace ninja\repositories;
|
||||
|
||||
use Payment;
|
||||
use Credit;
|
||||
use Invoice;
|
||||
use Client;
|
||||
use Utils;
|
||||
@ -36,6 +37,29 @@ class PaymentRepository
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function getErrors($input)
|
||||
{
|
||||
$rules = array(
|
||||
'client' => 'required',
|
||||
'invoice' => 'required',
|
||||
'amount' => 'required|positive'
|
||||
);
|
||||
|
||||
if ($input['payment_type_id'] == PAYMENT_TYPE_CREDIT)
|
||||
{
|
||||
$rules['payment_type_id'] = 'has_credit:' . $input['client'] . ',' . $input['amount'];
|
||||
}
|
||||
|
||||
$validator = \Validator::make($input, $rules);
|
||||
|
||||
if ($validator->fails())
|
||||
{
|
||||
return $validator;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function save($publicId = null, $input)
|
||||
{
|
||||
if ($publicId)
|
||||
@ -47,12 +71,30 @@ class PaymentRepository
|
||||
$payment = Payment::createNew();
|
||||
}
|
||||
|
||||
$paymentTypeId = $input['payment_type_id'] ? $input['payment_type_id'] : null;
|
||||
$amount = Utils::parseFloat($input['amount']);
|
||||
|
||||
if ($paymentTypeId == PAYMENT_TYPE_CREDIT)
|
||||
{
|
||||
$credits = Credit::scope()->where('balance', '>', 0)->orderBy('created_at')->get();
|
||||
$applied = 0;
|
||||
|
||||
foreach ($credits as $credit)
|
||||
{
|
||||
$applied += $credit->apply($amount);
|
||||
|
||||
if ($applied >= $amount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$payment->client_id = Client::getPrivateId($input['client']);
|
||||
$payment->invoice_id = isset($input['invoice']) && $input['invoice'] != "-1" ? Invoice::getPrivateId($input['invoice']) : null;
|
||||
//$payment->currency_id = $input['currency_id'] ? $input['currency_id'] : null;
|
||||
$payment->payment_type_id = $input['payment_type_id'] ? $input['payment_type_id'] : null;
|
||||
$payment->payment_type_id = $paymentTypeId;
|
||||
$payment->payment_date = Utils::toSqlDate($input['payment_date']);
|
||||
$payment->amount = Utils::parseFloat($input['amount']);
|
||||
$payment->amount = $amount;
|
||||
$payment->save();
|
||||
|
||||
return $payment;
|
||||
|
@ -22,6 +22,7 @@
|
||||
//Log::error('test');
|
||||
|
||||
|
||||
/*
|
||||
Event::listen('illuminate.query', function($query, $bindings, $time, $name)
|
||||
{
|
||||
$data = compact('bindings', 'time', 'name');
|
||||
@ -45,7 +46,7 @@ Event::listen('illuminate.query', function($query, $bindings, $time, $name)
|
||||
|
||||
Log::info($query, $data);
|
||||
});
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
// TODO_FIX replace with cron
|
||||
@ -189,6 +190,8 @@ define('INVOICE_STATUS_VIEWED', 3);
|
||||
define('INVOICE_STATUS_PARTIAL', 4);
|
||||
define('INVOICE_STATUS_PAID', 5);
|
||||
|
||||
define('PAYMENT_TYPE_CREDIT', 1);
|
||||
|
||||
define('FREQUENCY_WEEKLY', 1);
|
||||
define('FREQUENCY_TWO_WEEKS', 2);
|
||||
define('FREQUENCY_FOUR_WEEKS', 3);
|
||||
@ -220,3 +223,14 @@ Validator::extend('positive', function($attribute, $value, $parameters)
|
||||
{
|
||||
return Utils::parseFloat($value) > 0;
|
||||
});
|
||||
|
||||
Validator::extend('has_credit', function($attribute, $value, $parameters)
|
||||
{
|
||||
$publicClientId = $parameters[0];
|
||||
$amount = $parameters[1];
|
||||
|
||||
$client = Client::scope($publicClientId)->firstOrFail();
|
||||
$credit = $client->getTotalCredit();
|
||||
|
||||
return $credit >= $amount;
|
||||
});
|
@ -62,9 +62,25 @@
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h3>Standing</h3>
|
||||
<h3>{{ Utils::formatMoney($client->paid_to_date, $client->currency_id); }} <small>Paid to Date USD</small></h3>
|
||||
<h3>{{ Utils::formatMoney($client->balance, $client->currency_id); }} <small>Balance USD</small></h3>
|
||||
<h3>Standing
|
||||
<table class="table" style="width:300px">
|
||||
<tr>
|
||||
<td><small>Paid to Date</small></td>
|
||||
<td style="text-align: right">{{ Utils::formatMoney($client->paid_to_date, $client->currency_id); }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><small>Balance</small></td>
|
||||
<td style="text-align: right">{{ Utils::formatMoney($client->balance, $client->currency_id); }}</td>
|
||||
</tr>
|
||||
@if ($credit > 0)
|
||||
<tr>
|
||||
<td><small>Credit</small></td>
|
||||
<td style="text-align: right">{{ Utils::formatMoney($credit, $client->currency_id); }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
</table>
|
||||
</h3>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -112,7 +128,7 @@
|
||||
<div class="tab-pane" id="payments">
|
||||
|
||||
{{ Datatable::table()
|
||||
->addColumn('Transaction Reference', 'Method', 'Invoice', 'Payment Amount', 'Payment Date')
|
||||
->addColumn('Invoice', 'Transaction Reference', 'Method', 'Payment Amount', 'Payment Date')
|
||||
->setUrl(url('api/payments/' . $client->public_id))
|
||||
->setOptions('sPaginationType', 'bootstrap')
|
||||
->setOptions('bFilter', false)
|
||||
@ -122,7 +138,7 @@
|
||||
<div class="tab-pane" id="credits">
|
||||
|
||||
{{ Datatable::table()
|
||||
->addColumn('Credit Amount', 'Credit Date', 'Private Notes')
|
||||
->addColumn('Credit Amount', 'Credit Balance', 'Credit Date', 'Private Notes')
|
||||
->setUrl(url('api/credits/' . $client->public_id))
|
||||
->setOptions('sPaginationType', 'bootstrap')
|
||||
->setOptions('bFilter', false)
|
||||
|
@ -23,7 +23,6 @@
|
||||
@endif
|
||||
|
||||
{{ Former::select('client')->addOption('', '')->addGroupClass('client-select') }}
|
||||
{{ Former::select('invoice')->addOption('', '')->addGroupClass('invoice-select') }}
|
||||
{{ Former::text('amount') }}
|
||||
{{ Former::text('credit_date')->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT)) }}
|
||||
{{-- Former::select('currency_id')->addOption('','')->label('Currency')
|
||||
@ -46,12 +45,22 @@
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
var invoices = {{ $invoices }};
|
||||
var clients = {{ $clients }};
|
||||
|
||||
$(function() {
|
||||
|
||||
populateInvoiceComboboxes({{ $clientPublicId }}, {{ $invoicePublicId }});
|
||||
var $clientSelect = $('select#client');
|
||||
for (var i=0; i<clients.length; i++) {
|
||||
var client = clients[i];
|
||||
$clientSelect.append(new Option(getClientDisplayName(client), client.public_id));
|
||||
}
|
||||
|
||||
if ({{ $clientPublicId ? 'true' : 'false' }}) {
|
||||
$clientSelect.val({{ $clientPublicId }});
|
||||
}
|
||||
|
||||
$clientSelect.combobox();
|
||||
|
||||
|
||||
|
||||
$('#currency_id').combobox();
|
||||
|
8
app/views/emails/confirm_html.blade.php
Executable file
8
app/views/emails/confirm_html.blade.php
Executable file
@ -0,0 +1,8 @@
|
||||
<h1>{{ Lang::get('confide::confide.email.account_confirmation.subject') }}</h1>
|
||||
|
||||
<p>{{ Lang::get('confide::confide.email.account_confirmation.body') }}</p>
|
||||
<a href='{{{ URL::to("user/confirm/{$user->confirmation_code}") }}}'>
|
||||
{{{ URL::to("user/confirm/{$user->confirmation_code}") }}}
|
||||
</a>
|
||||
|
||||
<p>{{ Lang::get('confide::confide.email.account_confirmation.farewell') }}</p>
|
@ -176,7 +176,9 @@
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!--
|
||||
Want something changed? We're {{ link_to('https://github.com/hillelcoren/invoice-ninja', 'open source', array('target'=>'_blank')) }}, email us at {{ link_to('mailto:contact@invoiceninja.com', 'contact@invoiceninja.com') }}.
|
||||
-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -247,6 +247,9 @@
|
||||
|
||||
@if ($invoice)
|
||||
|
||||
{{ Button::success('Enter Payment', array('onclick' => 'onPaymentClick()')) }}
|
||||
|
||||
<!--
|
||||
<div id="relatedActions" style="text-align:left" class="btn-group">
|
||||
<button class="btn-success btn" type="button">Enter Payment</button>
|
||||
<button class="btn-success btn dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
@ -257,6 +260,7 @@
|
||||
<li><a href="javascript:onCreditClick()">Enter Credit</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
-->
|
||||
|
||||
@endif
|
||||
|
||||
|
@ -5,6 +5,8 @@ var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Const
|
||||
var isChrome = !!window.chrome && !isOpera; // Chrome 1+
|
||||
var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
|
||||
|
||||
var NINJA = {};
|
||||
|
||||
function generatePDF(invoice, checkMath) {
|
||||
var client = invoice.client;
|
||||
var account = invoice.account;
|
||||
@ -148,9 +150,49 @@ function generatePDF(invoice, checkMath) {
|
||||
|
||||
headerY += rowHeight;
|
||||
doc.setFontType("bold");
|
||||
doc.text(headerLeft, headerY, 'Amount Due');
|
||||
doc.text(headerLeft, headerY, 'Balance Due');
|
||||
|
||||
var balance = formatMoney(invoice.balance, currencyId);
|
||||
var total = 0;
|
||||
|
||||
for (var i=0; i<invoice.invoice_items.length; i++) {
|
||||
var item = invoice.invoice_items[i];
|
||||
var tax = 0;
|
||||
if (item.tax && parseFloat(item.tax.rate)) {
|
||||
tax = parseFloat(item.tax.rate);
|
||||
} else if (item.tax_rate && parseFloat(item.tax_rate)) {
|
||||
tax = parseFloat(item.tax_rate);
|
||||
}
|
||||
|
||||
var lineTotal = item.cost * item.qty;
|
||||
if (tax) {
|
||||
lineTotal += lineTotal * tax / 100;
|
||||
}
|
||||
if (lineTotal) {
|
||||
total += lineTotal;
|
||||
}
|
||||
}
|
||||
|
||||
if (invoice.discount > 0) {
|
||||
|
||||
var discount = total * (invoice.discount/100);
|
||||
total -= discount;
|
||||
}
|
||||
|
||||
var tax = 0;
|
||||
if (invoice.tax && parseFloat(invoice.tax.rate)) {
|
||||
tax = parseFloat(invoice.tax.rate);
|
||||
} else if (invoice.tax_rate && parseFloat(invoice.tax_rate)) {
|
||||
tax = parseFloat(invoice.tax_rate);
|
||||
}
|
||||
|
||||
if (tax) {
|
||||
var tax = total * (tax/100);
|
||||
total = parseFloat(total) + parseFloat(tax);
|
||||
}
|
||||
|
||||
total = formatMoney(total - (invoice.amount - invoice.balance), currencyId);
|
||||
|
||||
var balance = formatMoney(total, currencyId);
|
||||
balanceX = headerRight - (doc.getStringUnitWidth(balance) * doc.internal.getFontSize());
|
||||
doc.text(balanceX, headerY, balance);
|
||||
|
||||
@ -259,9 +301,9 @@ function generatePDF(invoice, checkMath) {
|
||||
|
||||
x += 16;
|
||||
doc.text(footerLeft, x, 'Subtotal');
|
||||
var total = formatMoney(total, currencyId, true);
|
||||
var totalX = headerRight - (doc.getStringUnitWidth(total) * doc.internal.getFontSize());
|
||||
doc.text(totalX, x, total);
|
||||
var prettyTotal = formatMoney(total, currencyId, true);
|
||||
var totalX = headerRight - (doc.getStringUnitWidth(prettyTotal) * doc.internal.getFontSize());
|
||||
doc.text(totalX, x, prettyTotal);
|
||||
|
||||
if (invoice.discount > 0) {
|
||||
|
||||
@ -298,8 +340,6 @@ function generatePDF(invoice, checkMath) {
|
||||
doc.text(paidX, x, paid);
|
||||
|
||||
x += 16;
|
||||
doc.setFontType("bold");
|
||||
doc.text(footerLeft, x, 'Balance Due');
|
||||
|
||||
if (checkMath && parseFloat(total) != parseFloat(invoice.amount))
|
||||
{
|
||||
@ -311,77 +351,38 @@ function generatePDF(invoice, checkMath) {
|
||||
return doc;
|
||||
}
|
||||
|
||||
var total = formatMoney(total - (invoice.amount - invoice.balance), currencyId);
|
||||
|
||||
doc.setDrawColor(200,200,200);
|
||||
doc.setFillColor(230,230,230);
|
||||
var x1 = footerLeft - tablePadding;
|
||||
var y1 = x - 11;
|
||||
var x2 = headerRight - footerLeft + 11;
|
||||
var y2 = 16;
|
||||
doc.rect(x1, y1, x2, y2, 'FD');
|
||||
|
||||
doc.setFontType("bold");
|
||||
doc.text(footerLeft, x, 'Balance Due');
|
||||
|
||||
console.log('total %s', total);
|
||||
console.log('inovice.amount %s', invoice.amount);
|
||||
console.log('invoice.blance %s', invoice.balance);
|
||||
total = formatMoney(total - (invoice.amount - invoice.balance), currencyId);
|
||||
var totalX = headerRight - (doc.getStringUnitWidth(total) * doc.internal.getFontSize());
|
||||
doc.text(totalX, x, total);
|
||||
|
||||
|
||||
|
||||
/* payment stub */
|
||||
/*
|
||||
var y = 680;
|
||||
doc.lines([[0,0],[headerRight-tableLeft+5,0]],tableLeft - 8, y - 30);
|
||||
doc.setFontSize(20);
|
||||
doc.text(tableLeft, y, 'Payment Stub');
|
||||
|
||||
doc.setFontSize(10);
|
||||
doc.setFontType("normal");
|
||||
y += 40;
|
||||
doc.text(tableLeft, y, invoice.account.name);
|
||||
y += 16;
|
||||
doc.text(tableLeft, y, invoice.account.address1);
|
||||
if (invoice.account.address2) {
|
||||
y += 16;
|
||||
doc.text(tableLeft, y, invoice.account.address2);
|
||||
}
|
||||
y += 16;
|
||||
doc.text(tableLeft, y, invoice.account.city + ', ' + invoice.account.state + ' ' + invoice.account.postal_code);
|
||||
y += 16;
|
||||
doc.text(tableLeft, y, invoice.account.country ? invoice.account.country.name : '');
|
||||
|
||||
|
||||
if (invoice.client) {
|
||||
|
||||
var clientX = headerRight - (doc.getStringUnitWidth(invoice.client.name) * doc.internal.getFontSize());
|
||||
}
|
||||
var numberX = headerRight - (doc.getStringUnitWidth(invoice.invoice_number) * doc.internal.getFontSize());
|
||||
var dateX = headerRight - (doc.getStringUnitWidth(issuedOn) * doc.internal.getFontSize());
|
||||
var totalX = headerRight - (doc.getStringUnitWidth(total) * doc.internal.getFontSize());
|
||||
|
||||
y = 720;
|
||||
if (invoice.client) {
|
||||
doc.setFontType("bold");
|
||||
doc.text(headerLeft, y, 'Client');
|
||||
doc.setFontType("normal");
|
||||
doc.text(clientX, y, invoice.client.name);
|
||||
}
|
||||
|
||||
y += 16;
|
||||
doc.setFontType("bold");
|
||||
doc.text(headerLeft, y, 'Invoice #');
|
||||
doc.setFontType("normal");
|
||||
doc.text(numberX, y, invoice.invoice_number);
|
||||
|
||||
y += 16;
|
||||
doc.setFontType("bold");
|
||||
doc.text(headerLeft, y, 'Invoice Date');
|
||||
doc.setFontType("normal");
|
||||
doc.text(dateX, y, issuedOn);
|
||||
|
||||
y += 16;
|
||||
doc.setFontType("bold");
|
||||
doc.text(headerLeft, y, 'Amount Due');
|
||||
doc.setFontType("normal");
|
||||
doc.text(totalX, y, total);
|
||||
|
||||
y += 16;
|
||||
doc.setFontType("bold");
|
||||
doc.text(headerLeft, y, 'Amount Enclosed');
|
||||
*/
|
||||
doc.text(marginLeft, 790, "Created by InvoiceNinja.com");
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
NINJA.parseFloat = function(str) {
|
||||
str = str.replace(/[^0-9\.\-]/g, '');
|
||||
return window.parseFloat(str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Handle converting variables in the invoices (ie, MONTH+1) */
|
||||
function processVariables(str) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user