1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-08 20:22:42 +01:00
This commit is contained in:
Troels Liebe Bentsen 2014-09-29 12:38:17 +02:00
commit 3da8555a53
56 changed files with 890 additions and 754 deletions

View File

@ -1,9 +0,0 @@
<?php
return array(
//'TAG_MANAGER_KEY' => '',
//'ANALYTICS_KEY' => '',
'NINJA_DEV' => true,
);

1
.gitignore vendored
View File

@ -16,6 +16,7 @@
/ninja.sublime-project /ninja.sublime-project
/ninja.sublime-workspace /ninja.sublime-workspace
/tests/_log /tests/_log
.env.development.php
.idea .idea
.project .project
/nbproject/private/ /nbproject/private/

View File

@ -3,13 +3,13 @@
### [https://www.invoiceninja.com](https://www.invoiceninja.com) ### [https://www.invoiceninja.com](https://www.invoiceninja.com)
**If you'd like to use our code to sell your own invoicing app get in touch.** If you'd like to use our code to sell your own invoicing app get in touch.
### Introduction ### Introduction
Most online invoicing sites are expensive. They shouldn't be. The aim of this project is to provide a free, open-source alternative. Additionally, the hope is the codebase will serve as a sample site for Laravel as well as other JavaScript technologies. Most online invoicing sites are expensive. They shouldn't be. The aim of this project is to provide a free, open-source alternative. Additionally, the hope is the codebase will serve as a sample site for Laravel as well as other JavaScript technologies.
[This guide](http://hillelcoren.com/invoice-ninja/self-hosting/) is the simplest way to setup the site. The high level instructions for setting up the site using Git are below but there's also a more detailed [setup guide](http://hillelcoren.com/invoice-ninja/laravel-ubuntu-virtualbox/). To deploy the app with [Docker](http://www.docker.com/) you can use [this project](https://github.com/rollbrettler/Dockerfiles/tree/master/invoice-ninja). To setup the site you can either use this [zip file](http://hillelcoren.com/invoice-ninja/self-hosting/) (easier to setup) or checkout the code from GitHub following the instructions below (easier to stay up to date). There's also a more detailed setup guide [available here](http://hillelcoren.com/invoice-ninja/laravel-ubuntu-virtualbox/). To deploy the app with [Docker](http://www.docker.com/) you can use [this project](https://github.com/rollbrettler/Dockerfiles/tree/master/invoice-ninja).
To connect follow [@invoiceninja](https://twitter.com/invoiceninja) or join the [Facebook Group](https://www.facebook.com/invoiceninja). For discussion of the code please use the [Google Group](https://groups.google.com/d/forum/invoiceninja). To connect follow [@invoiceninja](https://twitter.com/invoiceninja) or join the [Facebook Group](https://www.facebook.com/invoiceninja). For discussion of the code please use the [Google Group](https://groups.google.com/d/forum/invoiceninja).
@ -18,6 +18,7 @@ If you'd like to translate the site please use [caouecs/Laravel4-long](https://g
Site design by [kantorp-wegl.in](http://kantorp-wegl.in/) Site design by [kantorp-wegl.in](http://kantorp-wegl.in/)
### Features ### Features
* Core application built using Laravel 4.1 * Core application built using Laravel 4.1
* Invoice PDF generation directly in the browser * Invoice PDF generation directly in the browser
* Integrates with many payment providers * Integrates with many payment providers
@ -62,6 +63,27 @@ Configure development/config/database.php and development/config/mail.php and in
Add public/ to your web server root Add public/ to your web server root
### Deleveloper Notes
* If you make any changes to the JavaScript files you need to run grunt to create the built files. See Gruntfile.js for more details.
* The lookup tables are cached in memory (ie, Currencies, Timezones, Languages, etc). If you add a record to the database you need to clear the cache by uncommenting Cache::flush() in app/routes.php.
* If you run into any composer errors try running composer dump-autoload.
### Ubuntu Notes
# Install php-mcrypt
apt-get install php5-mcrypt
sudo php5enmod mcrypt
# Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
# Install Bower
sudo apt-get install npm nodejs-legacy
sudo npm install -g bower
sudo ln -s /usr/local/lib/node_modules/bower/bin/bower /usr/local/bin/bower
### Frameworks/Libraries ### Frameworks/Libraries
* [laravel/laravel](https://github.com/laravel/laravel) - A PHP Framework For Web Artisans * [laravel/laravel](https://github.com/laravel/laravel) - A PHP Framework For Web Artisans
* [twbs/bootstrap](https://github.com/twbs/bootstrap) - Sleek, intuitive, and powerful front-end framework for faster and easier web development. * [twbs/bootstrap](https://github.com/twbs/bootstrap) - Sleek, intuitive, and powerful front-end framework for faster and easier web development.
@ -86,24 +108,9 @@ Add public/ to your web server root
* [briannesbitt/Carbon](https://github.com/briannesbitt/Carbon) - A simple API extension for DateTime with PHP 5.3+ * [briannesbitt/Carbon](https://github.com/briannesbitt/Carbon) - A simple API extension for DateTime with PHP 5.3+
* [thomaspark/bootswatch](https://github.com/thomaspark/bootswatch) - Themes for Bootstrap * [thomaspark/bootswatch](https://github.com/thomaspark/bootswatch) - Themes for Bootstrap
* [mozilla/pdf.js](https://github.com/mozilla/pdf.js) - PDF Reader in JavaScript * [mozilla/pdf.js](https://github.com/mozilla/pdf.js) - PDF Reader in JavaScript
* [nnnick/Chart.js](https://github.com/nnnick/Chart.js) - Simple HTML5 Charts using the <canvas> tag * [nnnick/Chart.js](https://github.com/nnnick/Chart.js) - Simple HTML5 Charts using the canvas tag
* [josscrowcroft/accounting.js](https://github.com/josscrowcroft/accounting.js) - A lightweight JavaScript library for number, money and currency formatting * [josscrowcroft/accounting.js](https://github.com/josscrowcroft/accounting.js) - A lightweight JavaScript library for number, money and currency formatting
* [jashkenas/underscore](https://github.com/jashkenas/underscore) - JavaScript's utility _ belt * [jashkenas/underscore](https://github.com/jashkenas/underscore) - JavaScript's utility _ belt
* [caouecs/Laravel4-long](https://github.com/caouecs/Laravel4-lang) - List of languages for Laravel4 * [caouecs/Laravel4-long](https://github.com/caouecs/Laravel4-lang) - List of languages for Laravel4
* [calvinfroedge/PHP-Payments](https://github.com/calvinfroedge/PHP-Payments) - A uniform payments interface for PHP * [calvinfroedge/PHP-Payments](https://github.com/calvinfroedge/PHP-Payments) - A uniform payments interface for PHP
* [bgrins/spectrum](https://github.com/bgrins/spectrum) - The No Hassle JavaScript Colorpicker * [bgrins/spectrum](https://github.com/bgrins/spectrum) - The No Hassle JavaScript Colorpicker
### Ubuntu Notes
# Install php-mcrypt
apt-get install php5-mcrypt
sudo php5enmod mcrypt
# Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
# Install Bower
sudo apt-get install npm nodejs-legacy
sudo npm install -g bower
sudo ln -s /usr/local/lib/node_modules/bower/bin/bower /usr/local/bin/bower

View File

@ -26,7 +26,7 @@ return array(
| |
*/ */
'url' => 'http://www.invoiceninja.com', 'url' => 'https://www.invoiceninja.com',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -19,6 +19,49 @@ class AccountController extends \BaseController {
$this->contactMailer = $contactMailer; $this->contactMailer = $contactMailer;
} }
public function install()
{
if (!Utils::isNinja() && !Schema::hasTable('accounts')) {
try {
Artisan::call('migrate');
Artisan::call('db:seed');
} catch (Exception $e) {
Response::make($e->getMessage(), 500);
}
}
return Redirect::to('/');
}
public function update()
{
if (!Utils::isNinja()) {
try {
Artisan::call('migrate');
} catch (Exception $e) {
Response::make($e->getMessage(), 500);
}
}
return Redirect::to('/');
}
public function reset()
{
if (Utils::isNinjaDev()) {
Confide::logout();
try {
Artisan::call('migrate:reset');
Artisan::call('migrate');
Artisan::call('db:seed');
} catch (Exception $e) {
Response::make($e->getMessage(), 500);
}
}
return Redirect::to('/');
}
public function getStarted() public function getStarted()
{ {
if (Auth::check()) if (Auth::check())
@ -92,6 +135,7 @@ class AccountController extends \BaseController {
'datetimeFormats' => DatetimeFormat::remember(DEFAULT_QUERY_CACHE)->get(), 'datetimeFormats' => DatetimeFormat::remember(DEFAULT_QUERY_CACHE)->get(),
'currencies' => Currency::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), 'currencies' => Currency::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(),
'languages' => Language::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), 'languages' => Language::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(),
'showUser' => Auth::user()->id === Auth::user()->account->users()->first()->id,
]; ];
return View::make('accounts.details', $data); return View::make('accounts.details', $data);
@ -623,12 +667,13 @@ class AccountController extends \BaseController {
} }
else else
{ {
$account = Account::findOrFail(Auth::user()->account_id); $account = Account::with('account_gateways')->findOrFail(Auth::user()->account_id);
if ($gatewayId) if ($gatewayId)
{ {
$accountGateway = AccountGateway::createNew(); $accountGateway = AccountGateway::createNew();
$accountGateway->gateway_id = $gatewayId; $accountGateway->gateway_id = $gatewayId;
$isMasked = false;
$config = new stdClass; $config = new stdClass;
foreach ($fields as $field => $details) foreach ($fields as $field => $details)
@ -637,27 +682,35 @@ class AccountController extends \BaseController {
if ($value && $value === str_repeat('*', strlen($value))) if ($value && $value === str_repeat('*', strlen($value)))
{ {
Session::flash('error', trans('validation.notmasked')); $isMasked = true;
return Redirect::to('company/payments');
} }
$config->$field = $value; $config->$field = $value;
} }
$cardCount = 0; $cardCount = 0;
if ($creditcards) if ($creditcards)
{ {
foreach($creditcards as $card => $value) foreach($creditcards as $card => $value)
{ {
$cardCount += intval($value); $cardCount += intval($value);
} }
} }
$accountGateway->config = json_encode($config); if ($isMasked && count($account->account_gateways))
$accountGateway->accepted_credit_cards = $cardCount; {
$currentGateway = $account->account_gateways[0];
$currentGateway->accepted_credit_cards = $cardCount;
$currentGateway->save();
}
else
{
$accountGateway->config = json_encode($config);
$accountGateway->accepted_credit_cards = $cardCount;
$account->account_gateways()->delete(); $account->account_gateways()->delete();
$account->account_gateways()->save($accountGateway); $account->account_gateways()->save($accountGateway);
}
Session::flash('message', trans('texts.updated_settings')); Session::flash('message', trans('texts.updated_settings'));
} }
@ -674,9 +727,15 @@ class AccountController extends \BaseController {
{ {
$rules = array( $rules = array(
'name' => 'required', 'name' => 'required',
'email' => 'email|required|unique:users,email,' . Auth::user()->id . ',id'
); );
$user = Auth::user()->account->users()->first();
if (Auth::user()->id === $user->id)
{
$rules['email'] = 'email|required|unique:users,email,' . $user->id . ',id';
}
$validator = Validator::make(Input::all(), $rules); $validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) if ($validator->fails())
@ -706,13 +765,15 @@ class AccountController extends \BaseController {
$account->language_id = Input::get('language_id') ? Input::get('language_id') : 1; // English $account->language_id = Input::get('language_id') ? Input::get('language_id') : 1; // English
$account->save(); $account->save();
$user = Auth::user(); if (Auth::user()->id === $user->id)
$user->first_name = trim(Input::get('first_name')); {
$user->last_name = trim(Input::get('last_name')); $user->first_name = trim(Input::get('first_name'));
$user->username = trim(Input::get('email')); $user->last_name = trim(Input::get('last_name'));
$user->email = trim(strtolower(Input::get('email'))); $user->username = trim(Input::get('email'));
$user->phone = trim(Input::get('phone')); $user->email = trim(strtolower(Input::get('email')));
$user->save(); $user->phone = trim(Input::get('phone'));
$user->save();
}
/* Logo image file */ /* Logo image file */
if ($file = Input::file('logo')) if ($file = Input::file('logo'))
@ -797,4 +858,14 @@ class AccountController extends \BaseController {
return "{$user->first_name} {$user->last_name}"; return "{$user->first_name} {$user->last_name}";
} }
public function cancelAccount()
{
$account = Auth::user()->account;
$account->forceDelete();
Confide::logout();
return Redirect::to('/')->with('clearGuestKey', true);
}
} }

View File

@ -207,12 +207,12 @@ class ClientController extends \BaseController {
$client->city = trim(Input::get('city')); $client->city = trim(Input::get('city'));
$client->state = trim(Input::get('state')); $client->state = trim(Input::get('state'));
$client->postal_code = trim(Input::get('postal_code')); $client->postal_code = trim(Input::get('postal_code'));
$client->country_id = Input::get('country_id') ? Input::get('country_id') : null; $client->country_id = Input::get('country_id') ? : null;
$client->private_notes = trim(Input::get('private_notes')); $client->private_notes = trim(Input::get('private_notes'));
$client->size_id = Input::get('size_id') ? Input::get('size_id') : null; $client->size_id = Input::get('size_id') ? : null;
$client->industry_id = Input::get('industry_id') ? Input::get('industry_id') : null; $client->industry_id = Input::get('industry_id') ? : null;
$client->currency_id = Input::get('currency_id') ? Input::get('currency_id') : 1; $client->currency_id = Input::get('currency_id') ? : 1;
$client->payment_terms = Input::get('payment_terms'); $client->payment_terms = Input::get('payment_terms') ? : 0;
$client->website = trim(Input::get('website')); $client->website = trim(Input::get('website'));
$client->save(); $client->save();

View File

@ -15,7 +15,7 @@ class DashboardController extends \BaseController {
->leftJoin('clients', 'accounts.id', '=', 'clients.account_id') ->leftJoin('clients', 'accounts.id', '=', 'clients.account_id')
->leftJoin('invoices', 'clients.id', '=', 'invoices.client_id') ->leftJoin('invoices', 'clients.id', '=', 'invoices.client_id')
->where('accounts.id', '=', Auth::user()->account_id) ->where('accounts.id', '=', Auth::user()->account_id)
->where('clients.deleted_at', '=', null) ->where('clients.is_deleted', '=', false)
->groupBy('accounts.id') ->groupBy('accounts.id')
->first(); ->first();
@ -25,7 +25,7 @@ class DashboardController extends \BaseController {
->select($select) ->select($select)
->leftJoin('clients', 'accounts.id', '=', 'clients.account_id') ->leftJoin('clients', 'accounts.id', '=', 'clients.account_id')
->where('accounts.id', '=', Auth::user()->account_id) ->where('accounts.id', '=', Auth::user()->account_id)
->where('clients.deleted_at', '=', null) ->where('clients.is_deleted', '=', false)
->groupBy('accounts.id') ->groupBy('accounts.id')
->first(); ->first();
@ -37,6 +37,7 @@ class DashboardController extends \BaseController {
->where('balance', '>', 0) ->where('balance', '>', 0)
->where('is_recurring', '=', false) ->where('is_recurring', '=', false)
->where('is_quote', '=', false) ->where('is_quote', '=', false)
->where('is_deleted', '=', false)
->orderBy('due_date', 'asc')->take(6)->get(); ->orderBy('due_date', 'asc')->take(6)->get();
$upcoming = Invoice::scope() $upcoming = Invoice::scope()
@ -44,6 +45,7 @@ class DashboardController extends \BaseController {
->where('balance', '>', 0) ->where('balance', '>', 0)
->where('is_recurring', '=', false) ->where('is_recurring', '=', false)
->where('is_quote', '=', false) ->where('is_quote', '=', false)
->where('is_deleted', '=', false)
->orderBy('due_date', 'asc')->take(6)->get(); ->orderBy('due_date', 'asc')->take(6)->get();
$data = [ $data = [

View File

@ -122,12 +122,10 @@ class PaymentController extends \BaseController
$gateway->$function($val); $gateway->$function($val);
} }
/* if (Utils::isNinjaDev())
if (!Utils::isProd())
{ {
$gateway->setTestMode(true); $gateway->setTestMode(true);
} }
*/
return $gateway; return $gateway;
} }

View File

@ -132,19 +132,19 @@ class ConfideSetupUsersTable extends Migration {
$t->timestamps(); $t->timestamps();
$t->softDeletes(); $t->softDeletes();
$t->string('name'); $t->string('name')->nullable();
$t->string('ip'); $t->string('ip');
$t->string('account_key')->unique(); $t->string('account_key')->unique();
$t->timestamp('last_login'); $t->timestamp('last_login');
$t->string('address1'); $t->string('address1')->nullable();
$t->string('address2'); $t->string('address2')->nullable();
$t->string('city'); $t->string('city')->nullable();
$t->string('state'); $t->string('state')->nullable();
$t->string('postal_code'); $t->string('postal_code')->nullable();
$t->unsignedInteger('country_id')->nullable(); $t->unsignedInteger('country_id')->nullable();
$t->text('invoice_terms'); $t->text('invoice_terms')->nullable();
$t->text('email_footer'); $t->text('email_footer')->nullable();
$t->unsignedInteger('industry_id')->nullable(); $t->unsignedInteger('industry_id')->nullable();
$t->unsignedInteger('size_id')->nullable(); $t->unsignedInteger('size_id')->nullable();
@ -177,16 +177,16 @@ class ConfideSetupUsersTable extends Migration {
$t->timestamps(); $t->timestamps();
$t->softDeletes(); $t->softDeletes();
$t->string('first_name'); $t->string('first_name')->nullable();
$t->string('last_name'); $t->string('last_name')->nullable();
$t->string('phone'); $t->string('phone')->nullable();
$t->string('username')->unique(); $t->string('username')->unique();
$t->string('email'); $t->string('email')->nullable();
$t->string('password'); $t->string('password');
$t->string('confirmation_code'); $t->string('confirmation_code');
$t->boolean('registered')->default(false); $t->boolean('registered')->default(false);
$t->boolean('confirmed')->default(false); $t->boolean('confirmed')->default(false);
$t->integer('theme_id'); $t->integer('theme_id')->nullable();
$t->boolean('notify_sent')->default(true); $t->boolean('notify_sent')->default(true);
$t->boolean('notify_viewed')->default(false); $t->boolean('notify_viewed')->default(false);
@ -194,7 +194,7 @@ class ConfideSetupUsersTable extends Migration {
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$t->unsignedInteger('public_id'); $t->unsignedInteger('public_id')->nullable();
$t->unique( array('account_id','public_id') ); $t->unique( array('account_id','public_id') );
}); });
@ -202,7 +202,7 @@ class ConfideSetupUsersTable extends Migration {
{ {
$t->increments('id'); $t->increments('id');
$t->unsignedInteger('account_id'); $t->unsignedInteger('account_id');
$t->unsignedInteger('user_id'); $t->unsignedInteger('user_id');
$t->unsignedInteger('gateway_id'); $t->unsignedInteger('gateway_id');
$t->timestamps(); $t->timestamps();
$t->softDeletes(); $t->softDeletes();
@ -235,23 +235,23 @@ class ConfideSetupUsersTable extends Migration {
$t->timestamps(); $t->timestamps();
$t->softDeletes(); $t->softDeletes();
$t->string('name'); $t->string('name')->nullable();
$t->string('address1'); $t->string('address1')->nullable();
$t->string('address2'); $t->string('address2')->nullable();
$t->string('city'); $t->string('city')->nullable();
$t->string('state'); $t->string('state')->nullable();
$t->string('postal_code'); $t->string('postal_code')->nullable();
$t->unsignedInteger('country_id')->nullable(); $t->unsignedInteger('country_id')->nullable();
$t->string('work_phone'); $t->string('work_phone')->nullable();
$t->text('private_notes'); $t->text('private_notes')->nullable();
$t->decimal('balance', 13, 2); $t->decimal('balance', 13, 2)->nullable();
$t->decimal('paid_to_date', 13, 2); $t->decimal('paid_to_date', 13, 2)->nullable();
$t->timestamp('last_login')->nullable(); $t->timestamp('last_login')->nullable();
$t->string('website'); $t->string('website')->nullable();
$t->unsignedInteger('industry_id')->nullable(); $t->unsignedInteger('industry_id')->nullable();
$t->unsignedInteger('size_id')->nullable(); $t->unsignedInteger('size_id')->nullable();
$t->boolean('is_deleted'); $t->boolean('is_deleted')->default(false);
$t->integer('payment_terms'); $t->integer('payment_terms')->nullable();
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$t->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
@ -273,18 +273,18 @@ class ConfideSetupUsersTable extends Migration {
$t->timestamps(); $t->timestamps();
$t->softDeletes(); $t->softDeletes();
$t->boolean('is_primary'); $t->boolean('is_primary')->default(0);
$t->boolean('send_invoice'); $t->boolean('send_invoice')->default(0);
$t->string('first_name'); $t->string('first_name')->nullable();
$t->string('last_name'); $t->string('last_name')->nullable();
$t->string('email'); $t->string('email')->nullable();
$t->string('phone'); $t->string('phone')->nullable();
$t->timestamp('last_login'); $t->timestamp('last_login');
$t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); $t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
$t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');; $t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');;
$t->unsignedInteger('public_id'); $t->unsignedInteger('public_id')->nullable();
$t->unique( array('account_id','public_id') ); $t->unique( array('account_id','public_id') );
}); });
@ -317,7 +317,7 @@ class ConfideSetupUsersTable extends Migration {
$t->date('due_date')->nullable(); $t->date('due_date')->nullable();
$t->text('terms'); $t->text('terms');
$t->text('public_notes'); $t->text('public_notes');
$t->boolean('is_deleted'); $t->boolean('is_deleted')->default(false);
$t->boolean('is_recurring'); $t->boolean('is_recurring');
$t->unsignedInteger('frequency_id'); $t->unsignedInteger('frequency_id');
$t->date('start_date')->nullable(); $t->date('start_date')->nullable();
@ -331,11 +331,11 @@ class ConfideSetupUsersTable extends Migration {
$t->decimal('amount', 13, 2); $t->decimal('amount', 13, 2);
$t->decimal('balance', 13, 2); $t->decimal('balance', 13, 2);
$t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); $t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
$t->foreign('account_id')->references('id')->on('accounts'); $t->foreign('account_id')->references('id')->on('accounts');
$t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');; $t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$t->foreign('invoice_status_id')->references('id')->on('invoice_statuses'); $t->foreign('invoice_status_id')->references('id')->on('invoice_statuses');
$t->foreign('recurring_invoice_id')->references('id')->on('invoices'); $t->foreign('recurring_invoice_id')->references('id')->on('invoices')->onDelete('cascade');
$t->unsignedInteger('public_id')->index(); $t->unsignedInteger('public_id')->index();
$t->unique( array('account_id','public_id') ); $t->unique( array('account_id','public_id') );
@ -354,7 +354,7 @@ class ConfideSetupUsersTable extends Migration {
$t->timestamps(); $t->timestamps();
$t->softDeletes(); $t->softDeletes();
$t->string('transaction_reference'); $t->string('transaction_reference')->nullable();
$t->timestamp('sent_date'); $t->timestamp('sent_date');
$t->timestamp('viewed_date'); $t->timestamp('viewed_date');
@ -395,7 +395,7 @@ class ConfideSetupUsersTable extends Migration {
$t->string('product_key'); $t->string('product_key');
$t->text('notes'); $t->text('notes');
$t->decimal('cost', 13, 2); $t->decimal('cost', 13, 2);
$t->decimal('qty', 13, 2); $t->decimal('qty', 13, 2)->nullable();
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');; $t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');;
@ -418,10 +418,10 @@ class ConfideSetupUsersTable extends Migration {
$t->string('product_key'); $t->string('product_key');
$t->text('notes'); $t->text('notes');
$t->decimal('cost', 13, 2); $t->decimal('cost', 13, 2);
$t->decimal('qty', 13, 2); $t->decimal('qty', 13, 2)->nullable();
$t->string('tax_name'); $t->string('tax_name')->nullable();
$t->decimal('tax_rate', 13, 2); $t->decimal('tax_rate', 13, 2)->nullable();
$t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade'); $t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
$t->foreign('product_id')->references('id')->on('products'); $t->foreign('product_id')->references('id')->on('products');
@ -445,11 +445,11 @@ class ConfideSetupUsersTable extends Migration {
$t->timestamps(); $t->timestamps();
$t->softDeletes(); $t->softDeletes();
$t->boolean('is_deleted'); $t->boolean('is_deleted')->default(false);
$t->decimal('amount', 13, 2); $t->decimal('amount', 13, 2);
$t->date('payment_date'); $t->date('payment_date')->nullable();
$t->string('transaction_reference'); $t->string('transaction_reference')->nullable();
$t->string('payer_id'); $t->string('payer_id')->nullable();
$t->foreign('invoice_id')->references('id')->on('invoices'); $t->foreign('invoice_id')->references('id')->on('invoices');
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
@ -472,11 +472,11 @@ class ConfideSetupUsersTable extends Migration {
$t->timestamps(); $t->timestamps();
$t->softDeletes(); $t->softDeletes();
$t->boolean('is_deleted'); $t->boolean('is_deleted')->default(false);
$t->decimal('amount', 13, 2); $t->decimal('amount', 13, 2);
$t->decimal('balance', 13, 2); $t->decimal('balance', 13, 2);
$t->date('credit_date')->nullable(); $t->date('credit_date')->nullable();
$t->string('credit_number'); $t->string('credit_number')->nullable();
$t->text('private_notes'); $t->text('private_notes');
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
@ -495,17 +495,17 @@ class ConfideSetupUsersTable extends Migration {
$t->unsignedInteger('account_id'); $t->unsignedInteger('account_id');
$t->unsignedInteger('client_id'); $t->unsignedInteger('client_id');
$t->unsignedInteger('user_id'); $t->unsignedInteger('user_id');
$t->unsignedInteger('contact_id'); $t->unsignedInteger('contact_id')->nullable();
$t->unsignedInteger('payment_id'); $t->unsignedInteger('payment_id')->nullable();
$t->unsignedInteger('invoice_id'); $t->unsignedInteger('invoice_id')->nullable();
$t->unsignedInteger('credit_id'); $t->unsignedInteger('credit_id')->nullable();
$t->unsignedInteger('invitation_id'); $t->unsignedInteger('invitation_id')->nullable();
$t->text('message'); $t->text('message')->nullable();
$t->text('json_backup'); $t->text('json_backup')->nullable();
$t->integer('activity_type_id'); $t->integer('activity_type_id');
$t->decimal('adjustment', 13, 2); $t->decimal('adjustment', 13, 2)->nullable();
$t->decimal('balance', 13, 2); $t->decimal('balance', 13, 2)->nullable();
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); $t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');

View File

@ -14,8 +14,8 @@ class AddPhoneToAccount extends Migration {
{ {
Schema::table('accounts', function($table) Schema::table('accounts', function($table)
{ {
$table->string('work_phone'); $table->string('work_phone')->nullable();
$table->string('work_email'); $table->string('work_email')->nullable();
}); });
} }

View File

@ -26,6 +26,7 @@ class AddLanguageSupport extends Migration {
DB::table('languages')->insert(['name' => 'Brazilian Portuguese', 'locale' => 'pt_BR']); DB::table('languages')->insert(['name' => 'Brazilian Portuguese', 'locale' => 'pt_BR']);
DB::table('languages')->insert(['name' => 'Dutch', 'locale' => 'nl']); DB::table('languages')->insert(['name' => 'Dutch', 'locale' => 'nl']);
DB::table('languages')->insert(['name' => 'Spanish', 'locale' => 'es']); DB::table('languages')->insert(['name' => 'Spanish', 'locale' => 'es']);
DB::table('languages')->insert(['name' => 'Norwegian', 'locale' => 'nb_NO']);
Schema::table('accounts', function($table) Schema::table('accounts', function($table)
{ {

View File

@ -12,19 +12,16 @@ class CreatePaymentLibraries extends Migration {
*/ */
public function up() public function up()
{ {
Schema::dropIfExists('payment_libraries'); Schema::dropIfExists('payment_libraries');
Schema::create('payment_libraries', function($t) Schema::create('payment_libraries', function($t)
{ {
$t->increments('id'); $t->increments('id');
$t->timestamps(); $t->timestamps();
$t->string('name'); $t->string('name');
$t->boolean('visible')->default(true); $t->boolean('visible')->default(true);
}); });
DB::table('payment_libraries')->insert(['name' => 'Omnipay']);
DB::table('payment_libraries')->insert(['name' => 'PHP-Payments']);
Schema::table('gateways', function($table) Schema::table('gateways', function($table)
{ {
@ -35,7 +32,7 @@ class CreatePaymentLibraries extends Migration {
Schema::table('gateways', function($table) Schema::table('gateways', function($table)
{ {
$table->foreign('payment_library_id')->references('id')->on('payment_libraries')->onDelete('cascade'); $table->foreign('payment_library_id')->references('id')->on('payment_libraries')->onDelete('cascade');
}); });
} }

View File

@ -15,8 +15,8 @@ class AddSortAndRecommendedToGateways extends Migration {
Schema::table('gateways', function($table) Schema::table('gateways', function($table)
{ {
$table->unsignedInteger('sort_order')->default(10000); $table->unsignedInteger('sort_order')->default(10000);
$table->boolean('recommended'); $table->boolean('recommended')->default(0);
$table->string('site_url', 200); $table->string('site_url', 200)->nullable();
}); });
} }

View File

@ -14,7 +14,7 @@ class AddProPlan extends Migration {
{ {
Schema::table('accounts', function($table) Schema::table('accounts', function($table)
{ {
$table->date('pro_plan_paid'); $table->date('pro_plan_paid')->nullable();
}); });
} }

View File

@ -14,20 +14,20 @@ class AddCustomFields extends Migration {
{ {
Schema::table('accounts', function($table) Schema::table('accounts', function($table)
{ {
$table->string('custom_label1'); $table->string('custom_label1')->nullable();
$table->string('custom_value1'); $table->string('custom_value1')->nullable();
$table->string('custom_label2'); $table->string('custom_label2')->nullable();
$table->string('custom_value2'); $table->string('custom_value2')->nullable();
$table->string('custom_client_label1'); $table->string('custom_client_label1')->nullable();
$table->string('custom_client_label2'); $table->string('custom_client_label2')->nullable();
}); });
Schema::table('clients', function($table) Schema::table('clients', function($table)
{ {
$table->string('custom_value1'); $table->string('custom_value1')->nullable();
$table->string('custom_value2'); $table->string('custom_value2')->nullable();
}); });
} }

View File

@ -14,8 +14,8 @@ class AddAdvancedSettings extends Migration {
{ {
Schema::table('accounts', function($table) Schema::table('accounts', function($table)
{ {
$table->string('primary_color'); $table->string('primary_color')->nullable();
$table->string('secondary_color'); $table->string('secondary_color')->nullable();
}); });
Schema::table('payments', function($table) Schema::table('payments', function($table)

View File

@ -14,7 +14,7 @@ class AddQuotes extends Migration {
{ {
Schema::table('invoices', function($table) Schema::table('invoices', function($table)
{ {
$table->boolean('is_quote'); $table->boolean('is_quote')->default(0);
$table->unsignedInteger('quote_id')->nullable(); $table->unsignedInteger('quote_id')->nullable();
$table->unsignedInteger('quote_invoice_id')->nullable(); $table->unsignedInteger('quote_invoice_id')->nullable();
}); });

View File

@ -14,14 +14,14 @@ class SupportHidingQuantity extends Migration {
{ {
Schema::table('accounts', function($table) Schema::table('accounts', function($table)
{ {
$table->boolean('hide_quantity'); $table->boolean('hide_quantity')->default(0);
$table->boolean('hide_paid_to_date'); $table->boolean('hide_paid_to_date')->default(0);
$table->string('custom_invoice_label1'); $table->string('custom_invoice_label1')->nullable();
$table->string('custom_invoice_label2'); $table->string('custom_invoice_label2')->nullable();
$table->boolean('custom_invoice_taxes1'); $table->boolean('custom_invoice_taxes1')->nullable();
$table->boolean('custom_invoice_taxes2'); $table->boolean('custom_invoice_taxes2')->nullable();
}); });
Schema::table('invoices', function($table) Schema::table('invoices', function($table)

View File

@ -129,8 +129,10 @@ class ConstantsSeeder extends Seeder
Currency::create(array('name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); Currency::create(array('name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'));
Currency::create(array('name' => 'Israeli Shekel', 'code' => 'ILS', 'symbol' => 'NIS ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); Currency::create(array('name' => 'Israeli Shekel', 'code' => 'ILS', 'symbol' => 'NIS ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'));
Currency::create(array('name' => 'Singapore Dollar', 'code' => 'SGD', 'symbol' => 'SGD ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); Currency::create(array('name' => 'Singapore Dollar', 'code' => 'SGD', 'symbol' => 'SGD ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'));
Currency::create(array('name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); Currency::create(array('name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'));
Currency::create(array('name' => 'Norske Kroner', 'code' => 'NOK', 'symbol' => 'kr', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); Currency::create(array('name' => 'Norske Kroner', 'code' => 'NOK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'));
Currency::create(array('name' => 'Kenyan Shilling', 'code' => 'KES', 'symbol' => 'KSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'));
Currency::create(array('name' => 'Canadian Dollar', 'code' => 'CAD', 'symbol' => 'C$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'));
DatetimeFormat::create(array('format' => 'd/M/Y g:i a', 'label' => '10/Mar/2013')); DatetimeFormat::create(array('format' => 'd/M/Y g:i a', 'label' => '10/Mar/2013'));
DatetimeFormat::create(array('format' => 'd-M-Yk g:i a', 'label' => '10-Mar-2013')); DatetimeFormat::create(array('format' => 'd-M-Yk g:i a', 'label' => '10-Mar-2013'));
@ -148,6 +150,9 @@ class ConstantsSeeder extends Seeder
DateFormat::create(array('format' => 'F j, Y', 'picker_format' => 'MM d, yyyy', 'label' => 'March 10, 2013')); DateFormat::create(array('format' => 'F j, Y', 'picker_format' => 'MM d, yyyy', 'label' => 'March 10, 2013'));
DateFormat::create(array('format' => 'D M j, Y', 'picker_format' => 'D MM d, yyyy', 'label' => 'Mon March 10, 2013')); DateFormat::create(array('format' => 'D M j, Y', 'picker_format' => 'D MM d, yyyy', 'label' => 'Mon March 10, 2013'));
PaymentLibrary::create(['name' => 'Omnipay']);
PaymentLibrary::create(['name' => 'PHP-Payments']);
/* /*
d, dd: Numeric date, no leading zero and leading zero, respectively. Eg, 5, 05. d, dd: Numeric date, no leading zero and leading zero, respectively. Eg, 5, 05.
D, DD: Abbreviated and full weekday names, respectively. Eg, Mon, Monday. D, DD: Abbreviated and full weekday names, respectively. Eg, Mon, Monday.

View File

@ -404,5 +404,13 @@ return array(
'pending' => 'Pending', 'pending' => 'Pending',
'deleted_user' => 'Successfully deleted user', 'deleted_user' => 'Successfully deleted user',
'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users', 'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users',
'confirm_email_invoice' => 'Are you sure you want to email this invoice?',
'confirm_email_quote' => 'Are you sure you want to email this quote?',
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
'cancel_account' => 'Cancel Account',
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
'go_back' => 'Go Back',
); );

View File

@ -420,4 +420,12 @@ return array(
'deleted_user' => 'Successfully deleted user', 'deleted_user' => 'Successfully deleted user',
'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users', 'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users',
'confirm_email_invoice' => 'Are you sure you want to email this invoice?',
'confirm_email_quote' => 'Are you sure you want to email this quote?',
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
'cancel_account' => 'Cancel Account',
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
'go_back' => 'Go Back',
); );

View File

@ -402,5 +402,13 @@ return array(
'pending' => 'Pending', 'pending' => 'Pending',
'deleted_user' => 'Successfully deleted user', 'deleted_user' => 'Successfully deleted user',
'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users', 'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users',
'confirm_email_invoice' => 'Are you sure you want to email this invoice?',
'confirm_email_quote' => 'Are you sure you want to email this quote?',
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
'cancel_account' => 'Cancel Account',
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
'go_back' => 'Go Back',
); );

View File

@ -404,5 +404,13 @@ return array(
'pending' => 'Pending', 'pending' => 'Pending',
'deleted_user' => 'Successfully deleted user', 'deleted_user' => 'Successfully deleted user',
'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users', 'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users',
'confirm_email_invoice' => 'Are you sure you want to email this invoice?',
'confirm_email_quote' => 'Are you sure you want to email this quote?',
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
'cancel_account' => 'Cancel Account',
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
'go_back' => 'Go Back',
); );

View File

@ -404,5 +404,13 @@ return array(
'pending' => 'Pending', 'pending' => 'Pending',
'deleted_user' => 'Successfully deleted user', 'deleted_user' => 'Successfully deleted user',
'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users', 'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users',
'confirm_email_invoice' => 'Are you sure you want to email this invoice?',
'confirm_email_quote' => 'Are you sure you want to email this quote?',
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
'cancel_account' => 'Cancel Account',
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
'go_back' => 'Go Back',
); );

View File

@ -420,6 +420,13 @@ return array(
'deleted_user' => 'Successfully deleted user', 'deleted_user' => 'Successfully deleted user',
'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users', 'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users',
'confirm_email_invoice' => 'Are you sure you want to email this invoice?',
'confirm_email_quote' => 'Are you sure you want to email this quote?',
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
'cancel_account' => 'Cancel Account',
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
'go_back' => 'Go Back',
); );

View File

@ -420,4 +420,12 @@ return array(
'deleted_user' => 'Bruker slettet', 'deleted_user' => 'Bruker slettet',
'limit_users' => 'Dessverre, vil dette overstiger grensen p&#229; ' . MAX_NUM_USERS . ' brukere', 'limit_users' => 'Dessverre, vil dette overstiger grensen p&#229; ' . MAX_NUM_USERS . ' brukere',
'confirm_email_invoice' => 'Are you sure you want to email this invoice?',
'confirm_email_quote' => 'Are you sure you want to email this quote?',
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
'cancel_account' => 'Cancel Account',
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
'go_back' => 'Go Back',
); );

View File

@ -405,5 +405,13 @@ return array(
'pending' => 'Pending', 'pending' => 'Pending',
'deleted_user' => 'Successfully deleted user', 'deleted_user' => 'Successfully deleted user',
'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users', 'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users',
'confirm_email_invoice' => 'Are you sure you want to email this invoice?',
'confirm_email_quote' => 'Are you sure you want to email this quote?',
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
'cancel_account' => 'Cancel Account',
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
'go_back' => 'Go Back',
); );

View File

@ -393,5 +393,13 @@ return array(
'pending' => 'Pending', 'pending' => 'Pending',
'deleted_user' => 'Successfully deleted user', 'deleted_user' => 'Successfully deleted user',
'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users', 'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users',
'confirm_email_invoice' => 'Are you sure you want to email this invoice?',
'confirm_email_quote' => 'Are you sure you want to email this quote?',
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
'cancel_account' => 'Cancel Account',
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
'go_back' => 'Go Back',
); );

View File

@ -119,7 +119,7 @@ class Activity extends Eloquent
$adjustment = 0; $adjustment = 0;
$client = $invoice->client; $client = $invoice->client;
if (!$invoice->is_quote) if (!$invoice->is_quote && !$invoice->is_recurring)
{ {
$adjustment = $invoice->amount; $adjustment = $invoice->amount;
$client->balance = $client->balance + $adjustment; $client->balance = $client->balance + $adjustment;
@ -170,11 +170,12 @@ class Activity extends Eloquent
public static function updateInvoice($invoice) public static function updateInvoice($invoice)
{ {
$client = $invoice->client;
if ($invoice->is_deleted && !$invoice->getOriginal('is_deleted')) if ($invoice->is_deleted && !$invoice->getOriginal('is_deleted'))
{ {
if (!$invoice->is_quote) if (!$invoice->is_quote && !$invoice->is_recurring)
{ {
$client = $invoice->client;
$client->balance = $client->balance - $invoice->balance; $client->balance = $client->balance - $invoice->balance;
$client->paid_to_date = $client->paid_to_date - ($invoice->amount - $invoice->balance); $client->paid_to_date = $client->paid_to_date - ($invoice->amount - $invoice->balance);
$client->save(); $client->save();
@ -198,11 +199,13 @@ class Activity extends Eloquent
return; return;
} }
$backupInvoice = Invoice::with('invoice_items', 'client.account', 'client.contacts')->find($invoice->id); $backupInvoice = Invoice::with('invoice_items', 'client.account', 'client.contacts')->find($invoice->id);
$client = $invoice->client; if (!$invoice->is_quote && !$invoice->is_recurring)
$client->balance = $client->balance + $diff; {
$client->save(); $client->balance = $client->balance + $diff;
$client->save();
}
$activity = Activity::getBlank($invoice); $activity = Activity::getBlank($invoice);
$activity->client_id = $invoice->client_id; $activity->client_id = $invoice->client_id;
@ -210,7 +213,7 @@ class Activity extends Eloquent
$activity->activity_type_id = $invoice->is_quote ? ACTIVITY_TYPE_UPDATE_QUOTE : ACTIVITY_TYPE_UPDATE_INVOICE; $activity->activity_type_id = $invoice->is_quote ? ACTIVITY_TYPE_UPDATE_QUOTE : ACTIVITY_TYPE_UPDATE_INVOICE;
$activity->message = Utils::encodeActivity(Auth::user(), 'updated', $invoice); $activity->message = Utils::encodeActivity(Auth::user(), 'updated', $invoice);
$activity->balance = $client->balance; $activity->balance = $client->balance;
$activity->adjustment = $invoice->is_quote ? 0 : $diff; $activity->adjustment = $invoice->is_quote || $invoice->is_recurring ? 0 : $diff;
$activity->json_backup = $backupInvoice->hidePrivateFields()->toJSON(); $activity->json_backup = $backupInvoice->hidePrivateFields()->toJSON();
$activity->save(); $activity->save();
} }
@ -265,13 +268,13 @@ class Activity extends Eloquent
{ {
$activity = Activity::getBlank($client); $activity = Activity::getBlank($client);
$activity->contact_id = $payment->contact_id; $activity->contact_id = $payment->contact_id;
$activity->message = Utils::encodeActivity($payment->invitation->contact, 'entered ' . $payment->getName()); $activity->message = Utils::encodeActivity($payment->invitation->contact, 'entered ' . $payment->getName() . ' for ', $payment->invoice);
} }
else else
{ {
$activity = Activity::getBlank(); $activity = Activity::getBlank();
$message = $payment->payment_type_id == PAYMENT_TYPE_CREDIT ? 'applied credit' : 'entered ' . $payment->getName(); $message = $payment->payment_type_id == PAYMENT_TYPE_CREDIT ? 'applied credit for ' : 'entered ' . $payment->getName() . ' for ';
$activity->message = Utils::encodeActivity(Auth::user(), $message); $activity->message = Utils::encodeActivity(Auth::user(), $message, $payment->invoice);
} }
$activity->payment_id = $payment->id; $activity->payment_id = $payment->id;

View File

@ -21,7 +21,7 @@ class Gateway extends Eloquent
if ($paymentLibrary->id == PAYMENT_LIBRARY_OMNIPAY) if ($paymentLibrary->id == PAYMENT_LIBRARY_OMNIPAY)
{ {
$fields = Omnipay::create($this->provider)->getDefaultParameters(); $fields = Omnipay::create($this->provider)->getDefaultParameters();
} }
else else
{ {

View File

@ -3,6 +3,7 @@
class PaymentLibrary extends Eloquent class PaymentLibrary extends Eloquent
{ {
protected $table = 'payment_libraries'; protected $table = 'payment_libraries';
public $timestamps = true;
public function gateways() public function gateways()
{ {

View File

@ -1,6 +1,7 @@
<?php namespace ninja\mailers; <?php namespace ninja\mailers;
use Mail; use Mail;
use Utils;
class Mailer { class Mailer {
@ -12,9 +13,18 @@ class Mailer {
]; ];
Mail::send($views, $data, function($message) use ($toEmail, $fromEmail, $fromName, $subject) Mail::send($views, $data, function($message) use ($toEmail, $fromEmail, $fromName, $subject)
{ {
$replyEmail = $fromEmail;
// We're unable to set the true fromEmail for emails sent from Yahoo or AOL accounts
// http://blog.mandrill.com/yahoos-recent-dmarc-changes-and-how-that-impacts-senders.html
if (strpos($fromEmail, '@yahoo.') !== false || strpos($fromEmail, '@aol.') !== FALSE)
{
$fromEmail = CONTACT_EMAIL;
}
$message->to($toEmail)->from($fromEmail, $fromName)->sender($fromEmail, $fromName) $message->to($toEmail)->from($fromEmail, $fromName)->sender($fromEmail, $fromName)
->replyTo($fromEmail, $fromName)->returnPath($fromEmail)->subject($subject); ->replyTo($replyEmail, $fromName)->subject($subject);
}); });
} }
} }

View File

@ -23,7 +23,18 @@ class UserMailer extends Mailer {
'invitationMessage' => $invitor ? trans('texts.invitation_message', ['invitor' => $invitor->getDisplayName()]) : '' 'invitationMessage' => $invitor ? trans('texts.invitation_message', ['invitor' => $invitor->getDisplayName()]) : ''
]; ];
$this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data); if ($invitor)
{
$fromEmail = $invitor->email;
$fromName = $invitor->getDisplayName();
}
else
{
$fromEmail = CONTACT_EMAIL;
$fromName = CONTACT_NAME;
}
$this->sendTo($user->email, $fromEmail, $fromName, $subject, $view, $data);
} }
public function sendNotification(User $user, Invoice $invoice, $notificationType, Payment $payment = null) public function sendNotification(User $user, Invoice $invoice, $notificationType, Payment $payment = null)
@ -46,7 +57,7 @@ class UserMailer extends Mailer {
'invoiceLink' => SITE_URL . "/{$entityType}s/{$invoice->public_id}" 'invoiceLink' => SITE_URL . "/{$entityType}s/{$invoice->public_id}"
]; ];
if ($payment) if ($payment)
{ {
$data['paymentAmount'] = Utils::formatMoney($payment->amount, $invoice->client->currency_id); $data['paymentAmount'] = Utils::formatMoney($payment->amount, $invoice->client->currency_id);
} }

View File

@ -188,7 +188,7 @@ class ClientRepository
public function bulk($ids, $action) public function bulk($ids, $action)
{ {
$clients = Client::scope($ids)->get(); $clients = Client::withTrashed()->scope($ids)->get();
foreach ($clients as $client) foreach ($clients as $client)
{ {

View File

@ -66,7 +66,7 @@ class CreditRepository
return 0; return 0;
} }
$credits = Credit::scope($ids)->get(); $credits = Credit::withTrashed()->scope($ids)->get();
foreach ($credits as $credit) foreach ($credits as $credit)
{ {

View File

@ -435,7 +435,7 @@ class InvoiceRepository
return 0; return 0;
} }
$invoices = Invoice::scope($ids)->get(); $invoices = Invoice::withTrashed()->scope($ids)->get();
foreach ($invoices as $invoice) foreach ($invoices as $invoice)
{ {

View File

@ -112,7 +112,7 @@ class PaymentRepository
return 0; return 0;
} }
$payments = Payment::scope($ids)->get(); $payments = Payment::withTrashed()->scope($ids)->get();
foreach ($payments as $payment) foreach ($payments as $payment)
{ {

View File

@ -22,6 +22,9 @@
//dd(gethostname()); //dd(gethostname());
//Log::error('test'); //Log::error('test');
Route::get('install', 'AccountController@install');
Route::get('update', 'AccountController@update');
Route::get('reset', 'AccountController@reset');
Route::get('/', 'HomeController@showIndex'); Route::get('/', 'HomeController@showIndex');
Route::get('/rocksteady', 'HomeController@showIndex'); Route::get('/rocksteady', 'HomeController@showIndex');
@ -33,7 +36,7 @@ Route::post('/contact_submit', 'HomeController@doContactUs');
Route::get('/faq', 'HomeController@showFaq'); Route::get('/faq', 'HomeController@showFaq');
Route::get('/features', 'HomeController@showFeatures'); Route::get('/features', 'HomeController@showFeatures');
Route::get('/testimonials', 'HomeController@showTestimonials'); Route::get('/testimonials', 'HomeController@showTestimonials');
Route::get('/compare-online-invoicing-sites', 'HomeController@showCompare'); Route::get('/compare-online-invoicing', 'HomeController@showCompare');
Route::get('log_error', 'HomeController@logError'); Route::get('log_error', 'HomeController@logError');
Route::get('invoice_now', 'HomeController@invoiceNow'); Route::get('invoice_now', 'HomeController@invoiceNow');
@ -52,7 +55,6 @@ Route::post('signup/validate', 'AccountController@checkEmail');
Route::post('signup/submit', 'AccountController@submitSignup'); Route::post('signup/submit', 'AccountController@submitSignup');
// Confide routes // Confide routes
Route::get('login', 'UserController@login'); Route::get('login', 'UserController@login');
Route::post('login', 'UserController@do_login'); Route::post('login', 'UserController@do_login');
@ -81,6 +83,7 @@ Route::group(array('before' => 'auth'), function()
Route::get('company/advanced_settings/chart_builder', 'ReportController@report'); Route::get('company/advanced_settings/chart_builder', 'ReportController@report');
Route::post('company/advanced_settings/chart_builder', 'ReportController@report'); Route::post('company/advanced_settings/chart_builder', 'ReportController@report');
Route::post('company/cancel_account', 'AccountController@cancelAccount');
Route::get('account/getSearchData', array('as' => 'getSearchData', 'uses' => 'AccountController@getSearchData')); Route::get('account/getSearchData', array('as' => 'getSearchData', 'uses' => 'AccountController@getSearchData'));
Route::get('company/{section?}/{sub_section?}', 'AccountController@showSection'); Route::get('company/{section?}/{sub_section?}', 'AccountController@showSection');
Route::post('company/{section?}/{sub_section?}', 'AccountController@doSection'); Route::post('company/{section?}/{sub_section?}', 'AccountController@doSection');
@ -136,9 +139,9 @@ Route::group(array('prefix' => 'api/v1', 'before' => 'auth.basic'), function()
Route::post('api/hooks', 'IntegrationController@subscribe'); Route::post('api/hooks', 'IntegrationController@subscribe');
}); });
define('CONTACT_EMAIL', 'contact@invoiceninja.com'); define('CONTACT_EMAIL', Config::get('mail.from.address'));
define('CONTACT_NAME', 'Invoice Ninja'); define('CONTACT_NAME', Config::get('mail.from.name'));
define('SITE_URL', 'https://www.invoiceninja.com'); define('SITE_URL', Config::get('app.url'));
define('ENV_DEVELOPMENT', 'local'); define('ENV_DEVELOPMENT', 'local');
define('ENV_STAGING', 'staging'); define('ENV_STAGING', 'staging');
@ -231,7 +234,7 @@ define('NINJA_ACCOUNT_KEY', 'zg4ylmzDkdkPOT8yoKQw9LTWaoZJx79h');
define('NINJA_GATEWAY_ID', GATEWAY_AUTHORIZE_NET); define('NINJA_GATEWAY_ID', GATEWAY_AUTHORIZE_NET);
define('NINJA_GATEWAY_CONFIG', '{"apiLoginId":"626vWcD5","transactionKey":"4bn26TgL9r4Br4qJ","testMode":"","developerMode":""}'); define('NINJA_GATEWAY_CONFIG', '{"apiLoginId":"626vWcD5","transactionKey":"4bn26TgL9r4Br4qJ","testMode":"","developerMode":""}');
define('NINJA_URL', 'https://www.invoiceninja.com'); define('NINJA_URL', 'https://www.invoiceninja.com');
define('NINJA_VERSION', '1.3.1'); define('NINJA_VERSION', '1.3.3');
define('PRO_PLAN_PRICE', 50); define('PRO_PLAN_PRICE', 50);
define('LICENSE_PRICE', 30.00); define('LICENSE_PRICE', 30.00);

View File

@ -17,11 +17,13 @@
)) }} )) }}
{{ Former::populate($account) }} {{ Former::populate($account) }}
{{ Former::populateField('first_name', $account->users()->first()->first_name) }} @if ($showUser)
{{ Former::populateField('last_name', $account->users()->first()->last_name) }} {{ Former::populateField('first_name', $account->users()->first()->first_name) }}
{{ Former::populateField('email', $account->users()->first()->email) }} {{ Former::populateField('last_name', $account->users()->first()->last_name) }}
{{ Former::populateField('phone', $account->users()->first()->phone) }} {{ Former::populateField('email', $account->users()->first()->email) }}
{{ Former::populateField('phone', $account->users()->first()->phone) }}
@endif
<div class="row"> <div class="row">
<div class="col-md-5"> <div class="col-md-5">
@ -56,11 +58,13 @@
<div class="col-md-5 col-md-offset-1"> <div class="col-md-5 col-md-offset-1">
{{ Former::legend('users') }} @if ($showUser)
{{ Former::text('first_name') }} {{ Former::legend('users') }}
{{ Former::text('last_name') }} {{ Former::text('first_name') }}
{{ Former::text('email') }} {{ Former::text('last_name') }}
{{ Former::text('phone') }} {{ Former::text('email') }}
{{ Former::text('phone') }}
@endif
{{ Former::legend('localization') }} {{ Former::legend('localization') }}
{{ Former::select('language_id')->addOption('','') {{ Former::select('language_id')->addOption('','')

View File

@ -1,17 +1,60 @@
@extends('accounts.nav') @extends('accounts.nav')
@section('content') @section('content')
@parent @parent
{{ Former::open_for_files('company/import_map')->addClass('col-md-9 col-md-offset-1') }} {{ Former::open_for_files('company/import_map')->addClass('col-md-9 col-md-offset-1') }}
{{ Former::legend('import_clients') }} {{ Former::legend('import_clients') }}
{{ Former::file('file')->label(trans('texts.csv_file')) }} {{ Former::file('file')->label(trans('texts.csv_file')) }}
{{ Former::actions( Button::lg_info_submit(trans('texts.upload'))->append_with_icon('open') ) }} {{ Former::actions( Button::lg_info_submit(trans('texts.upload'))->append_with_icon('open') ) }}
{{ Former::close() }} {{ Former::close() }}
{{ Former::open('company/export')->addClass('col-md-9 col-md-offset-1') }} {{ Former::open('company/export')->addClass('col-md-9 col-md-offset-1') }}
{{ Former::legend('export_clients') }} {{ Former::legend('export_clients') }}
{{ Former::actions( Button::lg_primary_submit(trans('texts.download'))->append_with_icon('download-alt') ) }} {{ Former::actions( Button::lg_primary_submit(trans('texts.download'))->append_with_icon('download-alt') ) }}
{{ Former::close() }} {{ Former::close() }}
<p>&nbsp;</p>
<p>&nbsp;</p>
{{ Former::open('company/cancel_account')->addClass('col-md-9 col-md-offset-1 cancel-account') }}
{{ Former::legend('cancel_account') }}
{{ Former::actions( Button::lg_danger_button(trans('texts.cancel_account'), ['onclick' => 'showConfirm()'])->append_with_icon('trash') ) }}
<div class="modal fade" id="confirmCancelModal" tabindex="-1" role="dialog" aria-labelledby="confirmCancelModalLabel" aria-hidden="true">
<div class="modal-dialog" style="min-width:150px">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="confirmCancelModalLabel">{{ trans('texts.cancel_account') }}</h4>
</div>
<div style="background-color: #fff; padding-left: 16px; padding-right: 16px">
&nbsp;<p>{{ trans('texts.cancel_account_message') }}</p>&nbsp;
</div>
<div class="modal-footer" style="margin-top: 0px">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('texts.go_back') }}</button>
<button type="button" class="btn btn-primary" onclick="confirmCancel()">{{ trans('texts.cancel_account') }}</button>
</div>
</div>
</div>
</div>
{{ Former::close() }}
<script type="text/javascript">
function showConfirm() {
$('#confirmCancelModal').modal('show');
}
function confirmCancel() {
$('form.cancel-account').submit();
}
</script>
@stop @stop

View File

@ -3,7 +3,9 @@
@section('content') @section('content')
@parent @parent
{{ Former::open($url)->method($method)->addClass('col-md-8 col-md-offset-2 warn-on-exit') }} {{ Former::open($url)->method($method)
->rules(['product_key' => 'required|max:20'])
->addClass('col-md-8 col-md-offset-2 warn-on-exit') }}
{{ Former::legend($title) }} {{ Former::legend($title) }}

View File

@ -19,8 +19,8 @@
@if ($showNinjaFooter) @if ($showNinjaFooter)
<p/> <p/>
{{ trans('texts.ninja_email_footer', ['site' => '<a href="https://www.invoiceninja.com/?utm_source=invoice_email_footer">Invoice Ninja</a>']) }} {{ trans('texts.ninja_email_footer', ['site' => '<a href="' . NINJA_URL . '/?utm_source=invoice_email_footer">Invoice Ninja</a>']) }}
@endif @endif
</body> </body>
</html> </html>

View File

@ -12,5 +12,5 @@
@if ($showNinjaFooter) @if ($showNinjaFooter)
{{ trans('texts.ninja_email_footer', ['site' => 'Invoice Ninja']) }} {{ trans('texts.ninja_email_footer', ['site' => 'Invoice Ninja']) }}
https://www.invoiceninja.com {{ NINJA_URL }}
@endif @endif

View File

@ -18,8 +18,8 @@
@if ($showNinjaFooter) @if ($showNinjaFooter)
<p/> <p/>
{{ trans('texts.ninja_email_footer', ['site' => '<a href="https://www.invoiceninja.com/?utm_source=payment_email_footer">Invoice Ninja</a>']) }} {{ trans('texts.ninja_email_footer', ['site' => '<a href="' . NINJA_URL . '/?utm_source=payment_email_footer">Invoice Ninja</a>']) }}
@endif @endif
</body> </body>
</html> </html>

View File

@ -11,5 +11,5 @@
@if ($showNinjaFooter) @if ($showNinjaFooter)
{{ trans('texts.ninja_email_footer', ['site' => 'Invoice Ninja']) }} {{ trans('texts.ninja_email_footer', ['site' => 'Invoice Ninja']) }}
https://www.invoiceninja.com {{ NINJA_URL }}
@endif @endif

View File

@ -385,7 +385,8 @@ Want something changed? We're {{ link_to('https://github.com/hillelcoren/invoice
@endif @endif
@if (!Utils::isNinjaProd() && !Utils::isNinjaDev()) {{-- Per our license, please do not remove or modify this link. --}}
@if (!Utils::isNinja())
<div class="container">{{ trans('texts.powered_by') }} <a href="https://www.invoiceninja.com/?utm_source=powered_by" target="_blank">InvoiceNinja.com</a></div> <div class="container">{{ trans('texts.powered_by') }} <a href="https://www.invoiceninja.com/?utm_source=powered_by" target="_blank">InvoiceNinja.com</a></div>
@endif @endif

View File

@ -723,17 +723,19 @@
} }
function onEmailClick() { function onEmailClick() {
@if (Auth::user()->confirmed) if (confirm('{{ trans("texts.confirm_email_$entityType") }}')) {
if (confirm('Are you sure you want to email this {{ $entityType }}?')) {
submitAction('email'); submitAction('email');
} }
@else
submitAction('email');
@endif
} }
function onSaveClick() { function onSaveClick() {
submitAction(''); if (model.invoice().is_recurring()) {
if (confirm('{{ trans("texts.confirm_recurring_email_$entityType") }}')) {
submitAction('');
}
} else {
submitAction('');
}
} }
function submitAction(value) { function submitAction(value) {

View File

@ -9,9 +9,9 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta property="og:site_name" content="Invoice Ninja"></meta> <meta property="og:site_name" content="Invoice Ninja"></meta>
<meta property="og:url" content="https://www.invoiceninja.com"></meta> <meta property="og:url" content="{{ SITE_URL }}"></meta>
<meta property="og:title" content="Invoice Ninja"></meta> <meta property="og:title" content="Invoice Ninja"></meta>
<meta property="og:image" content="https://www.invoiceninja.com/images/social.jpg"></meta> <meta property="og:image" content="{{ SITE_URL }}/images/social.jpg"></meta>
<meta property="og:description" content="Simple, Intuitive Invoicing."></meta> <meta property="og:description" content="Simple, Intuitive Invoicing."></meta>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -20,7 +20,6 @@
<link href='//fonts.googleapis.com/css?family=Roboto:400,700,900,100' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Roboto:400,700,900,100' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Roboto+Slab:400,300,700' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Roboto+Slab:400,300,700' rel='stylesheet' type='text/css'>
<link href="{{ asset('favicon.ico') }}" rel="icon" type="image/x-icon"> <link href="{{ asset('favicon.ico') }}" rel="icon" type="image/x-icon">
<link href="https://www.invoiceninja.com" rel="canonical"></link>
<script src="{{ asset('built.js') }}" type="text/javascript"></script> <script src="{{ asset('built.js') }}" type="text/javascript"></script>
@ -33,7 +32,7 @@
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: '{{ URL::to('log_error') }}', url: '{{ URL::to('log_error') }}',
data: 'error='+encodeURIComponent(e)+'&url='+encodeURIComponent(window.location) data: 'error='+encodeURIComponent(e.message + ' - ' + e.filename + ': ' + e.lineno)+'&url='+encodeURIComponent(window.location)
}); });
} catch(err) {} } catch(err) {}
return false; return false;
@ -94,7 +93,6 @@
@yield('body') @yield('body')
<script type="text/javascript"> <script type="text/javascript">
NINJA.formIsChanged = false; NINJA.formIsChanged = false;
$(function() { $(function() {

View File

@ -26,6 +26,7 @@
<th>Custom Logo</th> <th>Custom Logo</th>
<th>Multiple Templates</th> <th>Multiple Templates</th>
<th>Recurring Payments</th> <th>Recurring Payments</th>
<th>Open Source</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -38,6 +39,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.freshbooks.com" target="_blank">FreshBooks</a></td> <td><a href="http://www.freshbooks.com" target="_blank">FreshBooks</a></td>
@ -48,6 +50,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.waveapps.com" target="_blank">Wave</a></td> <td><a href="http://www.waveapps.com" target="_blank">Wave</a></td>
@ -58,6 +61,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.nutcache.com" target="_blank">NutCache</a></td> <td><a href="http://www.nutcache.com" target="_blank">NutCache</a></td>
@ -68,6 +72,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://curdbee.com/" target="_blank">CurdBee</a></td> <td><a href="http://curdbee.com/" target="_blank">CurdBee</a></td>
@ -78,6 +83,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="https://www.zoho.com/invoice/" target="_blank">Zoho Invoice</a></td> <td><a href="https://www.zoho.com/invoice/" target="_blank">Zoho Invoice</a></td>
@ -88,6 +94,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.roninapp.com/" target="_blank">Ronin</a></td> <td><a href="http://www.roninapp.com/" target="_blank">Ronin</a></td>
@ -98,6 +105,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://invoiceable.co/" target="_blank">Invoiceable</a></td> <td><a href="http://invoiceable.co/" target="_blank">Invoiceable</a></td>
@ -108,6 +116,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.getharvest.com/" target="_blank">Harvest</a></td> <td><a href="http://www.getharvest.com/" target="_blank">Harvest</a></td>
@ -118,6 +127,7 @@
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://invoiceocean.com/" target="_blank">InvoiceOcean</a></td> <td><a href="http://invoiceocean.com/" target="_blank">InvoiceOcean</a></td>
@ -128,6 +138,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -147,6 +158,7 @@
<th>Custom Logo</th> <th>Custom Logo</th>
<th>Multiple Templates</th> <th>Multiple Templates</th>
<th>Recurring Payments</th> <th>Recurring Payments</th>
<th>Open Source</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -159,6 +171,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.freeagent.com" target="_blank">FreeAgent</a></td> <td><a href="http://www.freeagent.com" target="_blank">FreeAgent</a></td>
@ -169,6 +182,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="https://www.xero.com/" target="_blank">Xero</a></td> <td><a href="https://www.xero.com/" target="_blank">Xero</a></td>
@ -179,6 +193,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.invoice2go.com" target="_blank">Invoice2go</a></td> <td><a href="http://www.invoice2go.com" target="_blank">Invoice2go</a></td>
@ -189,6 +204,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://invoicemachine.com/" target="_blank">Invoice Machine</a></td> <td><a href="http://invoicemachine.com/" target="_blank">Invoice Machine</a></td>
@ -199,6 +215,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.freshbooks.com" target="_blank">FreshBooks</a></td> <td><a href="http://www.freshbooks.com" target="_blank">FreshBooks</a></td>
@ -209,6 +226,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://curdbee.com" target="_blank">CurdBee</a></td> <td><a href="http://curdbee.com" target="_blank">CurdBee</a></td>
@ -219,6 +237,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="https://www.zoho.com/invoice/" target="_blank">Zoho Invoice</a></td> <td><a href="https://www.zoho.com/invoice/" target="_blank">Zoho Invoice</a></td>
@ -229,6 +248,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.roninapp.com/" target="_blank">Ronin</a></td> <td><a href="http://www.roninapp.com/" target="_blank">Ronin</a></td>
@ -239,6 +259,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.getharvest.com/" target="_blank">Harvest</a></td> <td><a href="http://www.getharvest.com/" target="_blank">Harvest</a></td>
@ -249,6 +270,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://invoiceocean.com/" target="_blank">Invoice Ocean</a></td> <td><a href="http://invoiceocean.com/" target="_blank">Invoice Ocean</a></td>
@ -259,6 +281,7 @@
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.apptivo.com/" target="_blank">Apptivo</a></td> <td><a href="http://www.apptivo.com/" target="_blank">Apptivo</a></td>
@ -269,6 +292,7 @@
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-remove"/></td> <td><span class="glyphicon glyphicon-remove"/></td>
<td><span class="glyphicon glyphicon-ok"/></td> <td><span class="glyphicon glyphicon-ok"/></td>
<td><span class="glyphicon glyphicon-remove"/></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -121,6 +121,7 @@
<div class="navbar" style="margin-bottom:0px"> <div class="navbar" style="margin-bottom:0px">
<div class="container"> <div class="container">
<div class="navbar-header"> <div class="navbar-header">
{{-- Per our license, please do not remove or modify this link. --}}
<a class="navbar-brand" href="https://www.invoiceninja.com/"><img src="{{ asset('images/invoiceninja-logo.png') }}"></a> <a class="navbar-brand" href="https://www.invoiceninja.com/"><img src="{{ asset('images/invoiceninja-logo.png') }}"></a>
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span> <span class="sr-only">Toggle navigation</span>
@ -135,6 +136,7 @@
<li class="hide-desktop">{{ link_to('https://www.invoiceninja.com/contact', 'Contact Us' ) }}</li> <li class="hide-desktop">{{ link_to('https://www.invoiceninja.com/contact', 'Contact Us' ) }}</li>
<li>{{ link_to('https://www.invoiceninja.com/features', 'Features' ) }}</li> <li>{{ link_to('https://www.invoiceninja.com/features', 'Features' ) }}</li>
<li>{{ link_to('https://www.invoiceninja.com/plans', 'Plans' ) }}</li> <li>{{ link_to('https://www.invoiceninja.com/plans', 'Plans' ) }}</li>
<li>{{ link_to('https://www.invoiceninja.com/compare-online-invoicing', 'Compare' ) }}</li>
<li>{{ link_to('https://www.invoiceninja.com/testimonials', 'Testimonials' ) }}</li> <li>{{ link_to('https://www.invoiceninja.com/testimonials', 'Testimonials' ) }}</li>
<li>{{ link_to('https://www.invoiceninja.com/faq', 'FAQ' ) }}</li> <li>{{ link_to('https://www.invoiceninja.com/faq', 'FAQ' ) }}</li>
<li><span class="glyphicon glyphicon-user"></span> <li><span class="glyphicon glyphicon-user"></span>
@ -214,6 +216,7 @@
<ul class="navbar-vertical"> <ul class="navbar-vertical">
<li>{{ link_to('https://www.invoiceninja.com/features', 'Features' ) }}</li> <li>{{ link_to('https://www.invoiceninja.com/features', 'Features' ) }}</li>
<li>{{ link_to('https://www.invoiceninja.com/plans', 'Plans' ) }}</li> <li>{{ link_to('https://www.invoiceninja.com/plans', 'Plans' ) }}</li>
<li>{{ link_to('https://www.invoiceninja.com/compare-online-invoicing', 'Compare' ) }}</li>
<li>{{ link_to('https://www.invoiceninja.com/testimonials', 'Testimonials' ) }}</li> <li>{{ link_to('https://www.invoiceninja.com/testimonials', 'Testimonials' ) }}</li>
<li>{{ link_to('https://www.invoiceninja.com/faq', 'FAQ' ) }}</li> <li>{{ link_to('https://www.invoiceninja.com/faq', 'FAQ' ) }}</li>
<li>{{ link_to('http://blog.invoiceninja.com', 'Blog' ) }}</li> <li>{{ link_to('http://blog.invoiceninja.com', 'Blog' ) }}</li>

View File

@ -16,9 +16,9 @@
"anahkiasen/former": "dev-master", "anahkiasen/former": "dev-master",
"barryvdh/laravel-debugbar": "dev-master", "barryvdh/laravel-debugbar": "dev-master",
"chumper/datatable": "2.x", "chumper/datatable": "2.x",
"omnipay/omnipay": "2.x", "omnipay/omnipay": "~2.0",
"intervention/image": "1.x", "intervention/image": "1.x",
"webpatser/laravel-countries": "dev-master" "webpatser/laravel-countries": "dev-master"
}, },
"require-dev": { "require-dev": {
"codeception/codeception": "dev-master" "codeception/codeception": "dev-master"

911
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -2026,6 +2026,10 @@ div {
word-break: break-word; word-break: break-word;
} }
div.input-group {
word-break: normal;
}
div.required > label { div.required > label {
font-weight: bold !important; font-weight: bold !important;
} }

View File

@ -46614,7 +46614,7 @@ function GetReportTemplate1(doc, invoice, layout, checkMath)
var left = layout.headerRight - invoice.imageWidth; var left = layout.headerRight - invoice.imageWidth;
doc.addImage(invoice.image, 'JPEG', layout.marginLeft, 30); doc.addImage(invoice.image, 'JPEG', layout.marginLeft, 30);
} }
if (!invoice.is_pro && logoImages.imageLogo1) if (!invoice.is_pro && logoImages.imageLogo1)
{ {
pageHeight=820; pageHeight=820;
@ -46622,7 +46622,6 @@ function GetReportTemplate1(doc, invoice, layout, checkMath)
doc.addImage(logoImages.imageLogo1, 'JPEG', layout.marginLeft, y, logoImages.imageLogoWidth1, logoImages.imageLogoHeight1); doc.addImage(logoImages.imageLogo1, 'JPEG', layout.marginLeft, y, logoImages.imageLogoWidth1, logoImages.imageLogoHeight1);
} }
doc.setFontSize(9); doc.setFontSize(9);
SetPdfColor('LightBlue', doc, 'primary'); SetPdfColor('LightBlue', doc, 'primary');
displayAccount(doc, invoice, 220, layout.accountTop, layout); displayAccount(doc, invoice, 220, layout.accountTop, layout);
@ -47181,8 +47180,8 @@ function displayAccount(doc, invoice, x, y, layout) {
account.country ? account.country.name : false account.country ? account.country.name : false
]; ];
var nameWidth = doc.getStringUnitWidth(account.name) * doc.internal.getFontSize() * 1.1; var nameWidth = account.name ? (doc.getStringUnitWidth(account.name) * doc.internal.getFontSize() * 1.1) : 0;
var emailWidth = doc.getStringUnitWidth(account.work_email) * doc.internal.getFontSize() * 1.1; var emailWidth = account.work_email ? (doc.getStringUnitWidth(account.work_email) * doc.internal.getFontSize() * 1.1) : 0;
width = Math.max(emailWidth, nameWidth, 120); width = Math.max(emailWidth, nameWidth, 120);
x += width; x += width;

View File

@ -251,6 +251,10 @@ div {
word-break: break-word; word-break: break-word;
} }
div.input-group {
word-break: normal;
}
div.required > label { div.required > label {
font-weight: bold !important; font-weight: bold !important;
} }

View File

@ -689,7 +689,7 @@ function GetReportTemplate1(doc, invoice, layout, checkMath)
var left = layout.headerRight - invoice.imageWidth; var left = layout.headerRight - invoice.imageWidth;
doc.addImage(invoice.image, 'JPEG', layout.marginLeft, 30); doc.addImage(invoice.image, 'JPEG', layout.marginLeft, 30);
} }
if (!invoice.is_pro && logoImages.imageLogo1) if (!invoice.is_pro && logoImages.imageLogo1)
{ {
pageHeight=820; pageHeight=820;
@ -697,7 +697,6 @@ function GetReportTemplate1(doc, invoice, layout, checkMath)
doc.addImage(logoImages.imageLogo1, 'JPEG', layout.marginLeft, y, logoImages.imageLogoWidth1, logoImages.imageLogoHeight1); doc.addImage(logoImages.imageLogo1, 'JPEG', layout.marginLeft, y, logoImages.imageLogoWidth1, logoImages.imageLogoHeight1);
} }
doc.setFontSize(9); doc.setFontSize(9);
SetPdfColor('LightBlue', doc, 'primary'); SetPdfColor('LightBlue', doc, 'primary');
displayAccount(doc, invoice, 220, layout.accountTop, layout); displayAccount(doc, invoice, 220, layout.accountTop, layout);
@ -1256,8 +1255,8 @@ function displayAccount(doc, invoice, x, y, layout) {
account.country ? account.country.name : false account.country ? account.country.name : false
]; ];
var nameWidth = doc.getStringUnitWidth(account.name) * doc.internal.getFontSize() * 1.1; var nameWidth = account.name ? (doc.getStringUnitWidth(account.name) * doc.internal.getFontSize() * 1.1) : 0;
var emailWidth = doc.getStringUnitWidth(account.work_email) * doc.internal.getFontSize() * 1.1; var emailWidth = account.work_email ? (doc.getStringUnitWidth(account.work_email) * doc.internal.getFontSize() * 1.1) : 0;
width = Math.max(emailWidth, nameWidth, 120); width = Math.max(emailWidth, nameWidth, 120);
x += width; x += width;