From 67dff394b4c112b1b402f6d5df18af6f5d4c0689 Mon Sep 17 00:00:00 2001
From: Hillel Coren
Date: Tue, 16 Jun 2015 22:35:35 +0300
Subject: [PATCH] Added multi-company support
---
.env.example | 2 +
app/Exceptions/Handler.php | 9 +-
app/Http/Controllers/AccountController.php | 11 +-
app/Http/Controllers/Auth/AuthController.php | 31 ++++-
app/Http/Controllers/HomeController.php | 5 +
app/Http/Controllers/PaymentController.php | 8 +-
app/Http/Controllers/UserController.php | 33 ++++-
app/Http/routes.php | 4 +-
app/Libraries/Utils.php | 9 +-
app/Listeners/HandleUserSettingsChanged.php | 11 +-
app/Models/User.php | 22 ++-
app/Models/UserAccount.php | 52 +++++++
app/Ninja/Repositories/AccountRepository.php | 128 ++++++++++++++++++
app/Providers/AppServiceProvider.php | 4 +
...015_06_14_173025_multi_company_support.php | 42 ++++++
public/css/built.css | 15 ++
public/css/style.css | 15 ++
resources/lang/da/texts.php | 10 ++
resources/lang/de/texts.php | 9 ++
resources/lang/en/texts.php | 7 +
resources/lang/es/texts.php | 9 ++
resources/lang/es_ES/texts.php | 10 ++
resources/lang/fr/texts.php | 10 ++
resources/lang/fr_CA/texts.php | 10 ++
resources/lang/it/texts.php | 10 ++
resources/lang/lt/texts.php | 10 ++
resources/lang/nb_NO/texts.php | 10 ++
resources/lang/nl/texts.php | 10 ++
resources/lang/pt_BR/texts.php | 9 ++
resources/lang/sv/texts.php | 10 ++
resources/views/auth/login.blade.php | 8 +-
resources/views/header.blade.php | 105 ++++++++------
resources/views/list.blade.php | 2 +
33 files changed, 576 insertions(+), 64 deletions(-)
create mode 100644 app/Models/UserAccount.php
create mode 100644 database/migrations/2015_06_14_173025_multi_company_support.php
diff --git a/.env.example b/.env.example
index c40ef51eb943..abc9da3a5254 100644
--- a/.env.example
+++ b/.env.example
@@ -19,3 +19,5 @@ MAIL_USERNAME
MAIL_FROM_ADDRESS
MAIL_FROM_NAME
MAIL_PASSWORD
+
+ALLOW_NEW_ACCOUNTS
\ No newline at end of file
diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index 084f74fcc498..e0db4f0a89f5 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -1,8 +1,10 @@
get_class($e),
diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php
index e7b08bf612f9..8503d0b76494 100644
--- a/app/Http/Controllers/AccountController.php
+++ b/app/Http/Controllers/AccountController.php
@@ -77,10 +77,12 @@ class AccountController extends BaseController
{
if (Auth::check()) {
return Redirect::to('invoices/create');
- } elseif (!Utils::isNinja() && Account::count() > 0) {
- return Redirect::to('/login');
}
+ if (!Utils::isNinja() && !Utils::allowNewAccounts() && Account::count() > 0) {
+ return Redirect::to('/login');
+ }
+
$user = false;
$guestKey = Input::get('guest_key');
@@ -728,7 +730,7 @@ class AccountController extends BaseController
$email = trim(Input::get('email'));
if (!$email || $email == 'user@example.com') {
- return RESULT_SUCCESS;
+ return '';
}
$license = new License();
@@ -742,7 +744,7 @@ class AccountController extends BaseController
$license->is_claimed = 1;
$license->save();
- return RESULT_SUCCESS;
+ return '';
}
public function cancelAccount()
@@ -762,6 +764,7 @@ class AccountController extends BaseController
$account->forceDelete();
Auth::logout();
+ Session::flush();
return Redirect::to('/')->with('clearGuestKey', true);
}
diff --git a/app/Http/Controllers/Auth/AuthController.php b/app/Http/Controllers/Auth/AuthController.php
index 797c54ac4a92..8cde7ad8190c 100644
--- a/app/Http/Controllers/Auth/AuthController.php
+++ b/app/Http/Controllers/Auth/AuthController.php
@@ -3,10 +3,12 @@
use Auth;
use Event;
use Utils;
+use Session;
use Illuminate\Http\Request;
use App\Models\User;
use App\Events\UserLoggedIn;
use App\Http\Controllers\Controller;
+use App\Ninja\Repositories\AccountRepository;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\Registrar;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
@@ -28,6 +30,7 @@ class AuthController extends Controller {
protected $loginPath = '/login';
protected $redirectTo = '/dashboard';
+ protected $accountRepo;
/**
* Create a new authentication controller instance.
@@ -36,12 +39,13 @@ class AuthController extends Controller {
* @param \Illuminate\Contracts\Auth\Registrar $registrar
* @return void
*/
- public function __construct(Guard $auth, Registrar $registrar)
+ public function __construct(Guard $auth, Registrar $registrar, AccountRepository $repo)
{
$this->auth = $auth;
$this->registrar = $registrar;
+ $this->accountRepo = $repo;
- $this->middleware('guest', ['except' => 'getLogout']);
+ //$this->middleware('guest', ['except' => 'getLogout']);
}
public function getLoginWrapper()
@@ -55,13 +59,36 @@ class AuthController extends Controller {
public function postLoginWrapper(Request $request)
{
+ $userId = Auth::check() ? Auth::user()->id : null;
$response = self::postLogin($request);
if (Auth::check()) {
Event::fire(new UserLoggedIn());
+
+ if (Utils::isPro()) {
+ $users = false;
+ // we're linking a new account
+ if ($userId && Auth::user()->id != $userId) {
+ $users = $this->accountRepo->associateAccounts($userId, Auth::user()->id);
+ Session::flash('message', trans('texts.associated_accounts'));
+ // check if other accounts are linked
+ } else {
+ $users = $this->accountRepo->loadAccounts(Auth::user()->id);
+ }
+
+ Session::put(SESSION_USER_ACCOUNTS, $users);
+ }
}
return $response;
}
+ public function getLogoutWrapper()
+ {
+ $response = self::getLogout();
+
+ Session::flush();
+
+ return $response;
+ }
}
diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php
index adf28e133cec..1db0b1698224 100644
--- a/app/Http/Controllers/HomeController.php
+++ b/app/Http/Controllers/HomeController.php
@@ -45,6 +45,11 @@ class HomeController extends BaseController
public function invoiceNow()
{
+ if (Auth::check() && Input::get('logout')) {
+ Auth::user()->clearSession();
+ Auth::logout();
+ }
+
if (Auth::check()) {
return Redirect::to('invoices/create')->with('sign_up', Input::get('sign_up'));
} else {
diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php
index a3103b8b780a..4196e1d1661f 100644
--- a/app/Http/Controllers/PaymentController.php
+++ b/app/Http/Controllers/PaymentController.php
@@ -630,8 +630,9 @@ class PaymentController extends BaseController
$invoice = $invitation->invoice;
$accountGateway = $invoice->client->account->getGatewayByType(Session::get('payment_type'));
- if ($invoice->account->account_key == NINJA_ACCOUNT_KEY) {
- $account = Account::find($invoice->client->public_id);
+ if ($invoice->account->account_key == NINJA_ACCOUNT_KEY
+ && $invoice->amount == PRO_PLAN_PRICE) {
+ $account = Account::with('users')->find($invoice->client->public_id);
if ($account->pro_plan_paid && $account->pro_plan_paid != '0000-00-00') {
$date = DateTime::createFromFormat('Y-m-d', $account->pro_plan_paid);
$account->pro_plan_paid = $date->modify('+1 year')->format('Y-m-d');
@@ -639,6 +640,9 @@ class PaymentController extends BaseController
$account->pro_plan_paid = date_create()->format('Y-m-d');
}
$account->save();
+
+ $user = $account->users()->first();
+ $this->accountRepo->syncAccounts($user->id, $account->pro_plan_paid);
}
$payment = Payment::createNew($invitation);
diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
index 1a1afd3f1df9..6a1b425ce4a1 100644
--- a/app/Http/Controllers/UserController.php
+++ b/app/Http/Controllers/UserController.php
@@ -7,6 +7,7 @@ use DB;
use Event;
use Input;
use View;
+use Request;
use Redirect;
use Session;
use URL;
@@ -309,10 +310,8 @@ class UserController extends BaseController
}
}
- Session::forget('news_feed_id');
- Session::forget('news_feed_message');
-
Auth::logout();
+ Session::flush();
return Redirect::to('/')->with('clearGuestKey', true);
}
@@ -342,4 +341,32 @@ class UserController extends BaseController
return RESULT_SUCCESS;
}
+
+ public function switchAccount($newUserId)
+ {
+ $oldUserId = Auth::user()->id;
+ $referer = Request::header('referer');
+ $account = $this->accountRepo->findUserAccounts($newUserId, $oldUserId);
+
+ if ($account) {
+ if ($account->hasUserId($newUserId) && $account->hasUserId($oldUserId)) {
+ Auth::loginUsingId($newUserId);
+ Auth::user()->account->loadLocalizationSettings();
+ }
+ }
+
+ return Redirect::to($referer);
+ }
+
+ public function unlinkAccount($userAccountId, $userId)
+ {
+ $this->accountRepo->unlinkAccount($userAccountId, $userId);
+ $referer = Request::header('referer');
+
+ $users = $this->accountRepo->loadAccounts(Auth::user()->id);
+ Session::put(SESSION_USER_ACCOUNTS, $users);
+
+ Session::flash('message', trans('texts.unlinked_account'));
+ return Redirect::to($referer);
+ }
}
diff --git a/app/Http/routes.php b/app/Http/routes.php
index 391e2df44670..8cf91232690a 100644
--- a/app/Http/routes.php
+++ b/app/Http/routes.php
@@ -67,8 +67,7 @@ get('/signup', array('as' => 'signup', 'uses' => 'Auth\AuthController@getRegiste
post('/signup', array('as' => 'signup', 'uses' => 'Auth\AuthController@postRegister'));
get('/login', array('as' => 'login', 'uses' => 'Auth\AuthController@getLoginWrapper'));
post('/login', array('as' => 'login', 'uses' => 'Auth\AuthController@postLoginWrapper'));
-//get('/logout', array('as' => 'logout', 'uses' => 'Auth\AuthController@getLogoutWrapper'));
-get('/logout', array('as' => 'logout', 'uses' => 'Auth\AuthController@getLogout'));
+get('/logout', array('as' => 'logout', 'uses' => 'Auth\AuthController@getLogoutWrapper'));
get('/forgot', array('as' => 'forgot', 'uses' => 'Auth\PasswordController@getEmail'));
post('/forgot', array('as' => 'forgot', 'uses' => 'Auth\PasswordController@postEmail'));
get('/password/reset/{token}', array('as' => 'forgot', 'uses' => 'Auth\PasswordController@getReset'));
@@ -95,6 +94,7 @@ Route::group(['middleware' => 'auth'], function() {
Route::get('restore_user/{user_id}', 'UserController@restoreUser');
Route::post('users/change_password', 'UserController@changePassword');
Route::get('/switch_account/{user_id}', 'UserController@switchAccount');
+ Route::get('/unlink_account/{user_account_id}/{user_id}', 'UserController@unlinkAccount');
Route::get('api/tokens', array('as'=>'api.tokens', 'uses'=>'TokenController@getDatatable'));
Route::resource('tokens', 'TokenController');
diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php
index d09e60cfab4f..94025347fcda 100644
--- a/app/Libraries/Utils.php
+++ b/app/Libraries/Utils.php
@@ -51,12 +51,17 @@ class Utils
public static function isNinjaProd()
{
- return isset($_ENV['NINJA_PROD']) && $_ENV['NINJA_PROD'];
+ return isset($_ENV['NINJA_PROD']) && $_ENV['NINJA_PROD'] == 'true';
}
public static function isNinjaDev()
{
- return isset($_ENV['NINJA_DEV']) && $_ENV['NINJA_DEV'];
+ return isset($_ENV['NINJA_DEV']) && $_ENV['NINJA_DEV'] == 'true';
+ }
+
+ public static function allowNewAccounts()
+ {
+ return isset($_ENV['ALLOW_NEW_ACCOUNTS']) && $_ENV['ALLOW_NEW_ACCOUNTS'] == 'true';
}
public static function isPro()
diff --git a/app/Listeners/HandleUserSettingsChanged.php b/app/Listeners/HandleUserSettingsChanged.php
index e01a010c9dd1..f15966db9764 100644
--- a/app/Listeners/HandleUserSettingsChanged.php
+++ b/app/Listeners/HandleUserSettingsChanged.php
@@ -1,9 +1,9 @@
accountRepo = $accountRepo;
}
/**
@@ -29,6 +29,9 @@ class HandleUserSettingsChanged {
{
$account = Auth::user()->account;
$account->loadLocalizationSettings();
+
+ $users = $this->accountRepo->loadAccounts(Auth::user()->id);
+ Session::put(SESSION_USER_ACCOUNTS, $users);
}
}
diff --git a/app/Models/User.php b/app/Models/User.php
index 593d19e1486e..66d33492db2a 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -128,6 +128,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return Session::get(SESSION_COUNTER, 0);
}
+ /*
public function getPopOverText()
{
if (!Utils::isNinja() || !Auth::check() || Session::has('error')) {
@@ -146,7 +147,8 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return false;
}
-
+ */
+
public function afterSave($success = true, $forced = false)
{
if ($this->email) {
@@ -176,4 +178,22 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return 'remember_token';
}
+ public function clearSession()
+ {
+ $keys = [
+ RECENTLY_VIEWED,
+ SESSION_USER_ACCOUNTS,
+ SESSION_TIMEZONE,
+ SESSION_DATE_FORMAT,
+ SESSION_DATE_PICKER_FORMAT,
+ SESSION_DATETIME_FORMAT,
+ SESSION_CURRENCY,
+ SESSION_LOCALE,
+ ];
+
+ foreach ($keys as $key) {
+ Session::forget($key);
+ }
+ }
+
}
diff --git a/app/Models/UserAccount.php b/app/Models/UserAccount.php
new file mode 100644
index 000000000000..a1cd15f89b2d
--- /dev/null
+++ b/app/Models/UserAccount.php
@@ -0,0 +1,52 @@
+$field && $this->$field == $userId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public function setUserId($userId)
+ {
+ if (self::hasUserId($userId)) {
+ return;
+ }
+
+ for ($i=1; $i<=5; $i++) {
+ $field = "user_id{$i}";
+ if (!$this->$field) {
+ $this->$field = $userId;
+ break;
+ }
+ }
+ }
+
+ public function removeUserId($userId)
+ {
+ if (!$userId || !self::hasUserId($userId)) {
+ return;
+ }
+
+ for ($i=1; $i<=5; $i++) {
+ $field = "user_id{$i}";
+ if ($this->$field && $this->$field == $userId) {
+ $this->$field = null;
+ }
+ }
+ }
+}
diff --git a/app/Ninja/Repositories/AccountRepository.php b/app/Ninja/Repositories/AccountRepository.php
index 2b7f66595e42..cf9dd153f856 100644
--- a/app/Ninja/Repositories/AccountRepository.php
+++ b/app/Ninja/Repositories/AccountRepository.php
@@ -4,6 +4,8 @@ use Auth;
use Request;
use Session;
use Utils;
+use DB;
+use stdClass;
use App\Models\AccountGateway;
use App\Models\Invitation;
@@ -14,6 +16,7 @@ use App\Models\Language;
use App\Models\Contact;
use App\Models\Account;
use App\Models\User;
+use App\Models\UserAccount;
class AccountRepository
{
@@ -244,4 +247,129 @@ class AccountRepository
curl_exec($ch);
curl_close($ch);
}
+
+ public function findUserAccounts($userId1, $userId2 = false)
+ {
+ $query = UserAccount::where('user_id1', '=', $userId1)
+ ->orWhere('user_id2', '=', $userId1)
+ ->orWhere('user_id3', '=', $userId1)
+ ->orWhere('user_id4', '=', $userId1)
+ ->orWhere('user_id5', '=', $userId1);
+
+ if ($userId2) {
+ $query->orWhere('user_id1', '=', $userId2)
+ ->orWhere('user_id2', '=', $userId2)
+ ->orWhere('user_id3', '=', $userId2)
+ ->orWhere('user_id4', '=', $userId2)
+ ->orWhere('user_id5', '=', $userId2);
+ }
+
+ return $query->first(['id', 'user_id1', 'user_id2', 'user_id3', 'user_id4', 'user_id5']);
+ }
+
+ public function prepareUsersData($record) {
+
+ if (!$record) {
+ return false;
+ }
+
+ $userIds = [];
+ for ($i=1; $i<=5; $i++) {
+ $field = "user_id$i";
+ if ($record->$field) {
+ $userIds[] = $record->$field;
+ }
+ }
+
+ $users = User::with('account')
+ ->whereIn('id', $userIds)
+ ->get();
+
+ $data = [];
+ foreach ($users as $user) {
+ $item = new stdClass();
+ $item->id = $record->id;
+ $item->user_id = $user->id;
+ $item->user_name = $user->getDisplayName();
+ $item->account_id = $user->account->id;
+ $item->account_name = $user->account->getDisplayName();
+ $item->pro_plan_paid = $user->account->pro_plan_paid;
+ $data[] = $item;
+ }
+
+ return $data;
+ }
+
+ public function loadAccounts($userId) {
+ $record = self::findUserAccounts($userId);
+ return self::prepareUsersData($record);
+ }
+
+ public function syncAccounts($userId, $proPlanPaid) {
+ $users = self::loadAccounts($userId);
+ self::syncUserAccounts($users, $proPlanPaid);
+ }
+
+ public function syncUserAccounts($users, $proPlanPaid = false) {
+
+ if (!$proPlanPaid) {
+ foreach ($users as $user) {
+ if ($user->pro_plan_paid && $user->pro_plan_paid != '0000-00-00') {
+ $proPlanPaid = $user->pro_plan_paid;
+ break;
+ }
+ }
+ }
+
+ if (!$proPlanPaid) {
+ return;
+ }
+
+ $accountIds = [];
+ foreach ($users as $user) {
+ if ($user->pro_plan_paid != $proPlanPaid) {
+ $accountIds[] = $user->account_id;
+ }
+ }
+
+ if (count($accountIds)) {
+ DB::table('accounts')
+ ->whereIn('id', $accountIds)
+ ->update(['pro_plan_paid' => $proPlanPaid]);
+ }
+ }
+
+ public function associateAccounts($userId1, $userId2) {
+
+ $record = self::findUserAccounts($userId1, $userId2);
+
+ if ($record) {
+ foreach ([$userId1, $userId2] as $userId) {
+ if (!$record->hasUserId($userId)) {
+ $record->setUserId($userId);
+ }
+ }
+ } else {
+ $record = new UserAccount();
+ $record->user_id1 = $userId1;
+ $record->user_id2 = $userId2;
+ }
+
+ $record->save();
+
+ $users = self::prepareUsersData($record);
+ self::syncUserAccounts($users);
+
+ return $users;
+ }
+
+ public function unlinkAccount($userAccountId, $userId) {
+
+ $userAccount = UserAccount::whereId($userAccountId)->first();
+
+ if ($userAccount->hasUserId(Auth::user()->id)) {
+ $userAccount->removeUserId($userId);
+ $userAccount->save();
+ }
+ }
}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index a55ecfd5b476..9efba90b91af 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -44,6 +44,10 @@ class AppServiceProvider extends ServiceProvider {
$str .= '
'.trans("texts.quotes").'
'.trans("texts.new_quote").'';
+ } else if ($type == ENTITY_CLIENT) {
+ $str .= '
+ '.trans("texts.credits").'
+ '.trans("texts.new_credit").'';
}
$str .= '
diff --git a/database/migrations/2015_06_14_173025_multi_company_support.php b/database/migrations/2015_06_14_173025_multi_company_support.php
new file mode 100644
index 000000000000..08f8cf243fc8
--- /dev/null
+++ b/database/migrations/2015_06_14_173025_multi_company_support.php
@@ -0,0 +1,42 @@
+increments('id');
+
+ $table->unsignedInteger('user_id1')->nullable();
+ $table->unsignedInteger('user_id2')->nullable();
+ $table->unsignedInteger('user_id3')->nullable();
+ $table->unsignedInteger('user_id4')->nullable();
+ $table->unsignedInteger('user_id5')->nullable();
+
+ $table->foreign('user_id1')->references('id')->on('users');
+ $table->foreign('user_id2')->references('id')->on('users');
+ $table->foreign('user_id3')->references('id')->on('users');
+ $table->foreign('user_id4')->references('id')->on('users');
+ $table->foreign('user_id5')->references('id')->on('users');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('user_accounts');
+ }
+}
diff --git a/public/css/built.css b/public/css/built.css
index 34b170e8e1ca..105822f56b38 100644
--- a/public/css/built.css
+++ b/public/css/built.css
@@ -3345,3 +3345,18 @@ button .glyphicon {
width: 35px;
margin-top: 20px;
}
+
+ul.user-accounts div.account {
+ font-size: large;
+}
+
+ul.user-accounts div.remove {
+ padding-top: 14px;
+ color: #BBB;
+ visibility: hidden;
+}
+
+ul.user-accounts a:hover div.remove {
+ visibility: visible;
+}
+
diff --git a/public/css/style.css b/public/css/style.css
index 736d63d1072b..5e536810750b 100644
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -961,3 +961,18 @@ button .glyphicon {
width: 35px;
margin-top: 20px;
}
+
+ul.user-accounts div.account {
+ font-size: large;
+}
+
+ul.user-accounts div.remove {
+ padding-top: 14px;
+ color: #BBB;
+ visibility: hidden;
+}
+
+ul.user-accounts a:hover div.remove {
+ visibility: visible;
+}
+
diff --git a/resources/lang/da/texts.php b/resources/lang/da/texts.php
index 96b073155e8b..706250b733d1 100644
--- a/resources/lang/da/texts.php
+++ b/resources/lang/da/texts.php
@@ -696,6 +696,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
+
diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php
index 617e306b773d..5b9c531f61c9 100644
--- a/resources/lang/de/texts.php
+++ b/resources/lang/de/texts.php
@@ -687,6 +687,15 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
);
\ No newline at end of file
diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php
index d9f56e4eddbd..bb940d5f5a37 100644
--- a/resources/lang/en/texts.php
+++ b/resources/lang/en/texts.php
@@ -696,5 +696,12 @@ return array(
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
);
diff --git a/resources/lang/es/texts.php b/resources/lang/es/texts.php
index 45b3492e16f0..0d32d825eed3 100644
--- a/resources/lang/es/texts.php
+++ b/resources/lang/es/texts.php
@@ -666,6 +666,15 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
);
\ No newline at end of file
diff --git a/resources/lang/es_ES/texts.php b/resources/lang/es_ES/texts.php
index 1fe6041634f1..38e48e8276d7 100644
--- a/resources/lang/es_ES/texts.php
+++ b/resources/lang/es_ES/texts.php
@@ -695,6 +695,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
+
);
\ No newline at end of file
diff --git a/resources/lang/fr/texts.php b/resources/lang/fr/texts.php
index f06c0f2e748b..e1c22cb9860f 100644
--- a/resources/lang/fr/texts.php
+++ b/resources/lang/fr/texts.php
@@ -687,6 +687,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
+
);
\ No newline at end of file
diff --git a/resources/lang/fr_CA/texts.php b/resources/lang/fr_CA/texts.php
index 8ab007fd034b..3e808ab19e7f 100644
--- a/resources/lang/fr_CA/texts.php
+++ b/resources/lang/fr_CA/texts.php
@@ -688,5 +688,15 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
+
);
diff --git a/resources/lang/it/texts.php b/resources/lang/it/texts.php
index 27a68990a798..8b5a3e5047de 100644
--- a/resources/lang/it/texts.php
+++ b/resources/lang/it/texts.php
@@ -690,6 +690,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
+
);
diff --git a/resources/lang/lt/texts.php b/resources/lang/lt/texts.php
index 3be68c86ad19..66f56de588f8 100644
--- a/resources/lang/lt/texts.php
+++ b/resources/lang/lt/texts.php
@@ -697,6 +697,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
+
);
diff --git a/resources/lang/nb_NO/texts.php b/resources/lang/nb_NO/texts.php
index 39321b953cdc..a5d9d569da21 100644
--- a/resources/lang/nb_NO/texts.php
+++ b/resources/lang/nb_NO/texts.php
@@ -695,6 +695,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
+
);
\ No newline at end of file
diff --git a/resources/lang/nl/texts.php b/resources/lang/nl/texts.php
index 7dc7ae608cb7..6dad49264bfe 100644
--- a/resources/lang/nl/texts.php
+++ b/resources/lang/nl/texts.php
@@ -690,6 +690,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
+
);
diff --git a/resources/lang/pt_BR/texts.php b/resources/lang/pt_BR/texts.php
index efb84c6e7fce..be2080b68341 100644
--- a/resources/lang/pt_BR/texts.php
+++ b/resources/lang/pt_BR/texts.php
@@ -690,6 +690,15 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
);
diff --git a/resources/lang/sv/texts.php b/resources/lang/sv/texts.php
index 5b3cad8ce34d..86a9de4b8471 100644
--- a/resources/lang/sv/texts.php
+++ b/resources/lang/sv/texts.php
@@ -693,6 +693,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
+ 'email_receipt' => 'Email payment receipt to the client',
+ 'created_payment_emailed_client' => 'Successfully created payment and emailed client',
+ 'add_account' => 'Add Account',
+ 'untitled' => 'Untitled',
+ 'new_account' => 'New Account',
+ 'associated_accounts' => 'Successfully linked accounts',
+ 'unlinked_account' => 'Successfully unlinked accounts',
+ 'login' => 'Login',
+ 'or' => 'or',
+
);
diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php
index 1983f0c258c1..e96fbedc186a 100644
--- a/resources/views/auth/login.blade.php
+++ b/resources/views/auth/login.blade.php
@@ -79,7 +79,13 @@
{!! Former::hidden('remember')->raw() !!}
- {!! Button::success(trans('texts.lets_go'))->large()->submit()->block() !!}
+ {!! Button::success(trans(Utils::allowNewAccounts() ? 'texts.login' : 'texts.lets_go'))->large()->submit()->block() !!}
+
+ @if (Utils::allowNewAccounts())
+ - {{ trans('texts.or') }} -
+ {!! Button::primary(trans('texts.new_account'))->asLinkTo(URL::to('/invoice_now?logout=true'))->large()->submit()->block() !!}
+ @endif
+
{!! link_to('/forgot', trans('texts.forgot_password')) !!}
diff --git a/resources/views/header.blade.php b/resources/views/header.blade.php
index 004296f63468..80d6446420eb 100644
--- a/resources/views/header.blade.php
+++ b/resources/views/header.blade.php
@@ -186,6 +186,13 @@
});
}
+ function unlinkAccount(userAccountId, userId) {
+ if (confirm('{!! trans("texts.are_you_sure") !!}')) {
+ window.location = '{{ URL::to('/unlink_account') }}' + '/' + userAccountId + '/' + userId;
+ }
+ return false;
+ }
+
function wordWrapText(value, width)
{
@if (Auth::user()->account->auto_wrap)
@@ -321,7 +328,6 @@
{!! HTML::menu_link('task') !!}
{!! HTML::menu_link('invoice') !!}
{!! HTML::menu_link('payment') !!}
- {!! HTML::menu_link('credit') !!}
+
+
- @if (Auth::user()->getPopOverText() && Utils::isRegistered())
-
- @endif
-
-
-
-
-
-
+
+
+
+
diff --git a/resources/views/list.blade.php b/resources/views/list.blade.php
index 65a4a417f969..cc9d3e35ce99 100644
--- a/resources/views/list.blade.php
+++ b/resources/views/list.blade.php
@@ -27,6 +27,8 @@
@if (Auth::user()->isPro() && $entityType == ENTITY_INVOICE)
{!! Button::normal(trans('texts.quotes'))->asLinkTo(URL::to('/quotes'))->appendIcon(Icon::create('list')) !!}
+ @elseif ($entityType == ENTITY_CLIENT)
+ {!! Button::normal(trans('texts.credits'))->asLinkTo(URL::to('/credits'))->appendIcon(Icon::create('list')) !!}
@endif
{!! Button::primary(trans("texts.new_$entityType"))->asLinkTo(URL::to("/{$entityType}s/create"))->appendIcon(Icon::create('plus-sign')) !!}