mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 05:02:36 +01:00
Merge branch 'develop' of github.com:hillelcoren/invoice-ninja into develop
Conflicts: resources/lang/en/texts.php resources/views/accounts/invoice_design.blade.php resources/views/invoices/edit.blade.php
This commit is contained in:
commit
0dcee794b5
@ -36,7 +36,7 @@ class SendReminders extends Command
|
|||||||
$this->info(count($accounts).' accounts found');
|
$this->info(count($accounts).' accounts found');
|
||||||
|
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
if (!$account->isPro()) {
|
if (!$account->hasFeature(FEATURE_EMAIL_TEMPLATES_REMINDERS)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use DateTime;
|
|||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use App\Models\Account;
|
use App\Models\Company;
|
||||||
use App\Ninja\Mailers\ContactMailer as Mailer;
|
use App\Ninja\Mailers\ContactMailer as Mailer;
|
||||||
use App\Ninja\Repositories\AccountRepository;
|
use App\Ninja\Repositories\AccountRepository;
|
||||||
|
|
||||||
@ -30,24 +30,32 @@ class SendRenewalInvoices extends Command
|
|||||||
$today = new DateTime();
|
$today = new DateTime();
|
||||||
$sentTo = [];
|
$sentTo = [];
|
||||||
|
|
||||||
// get all accounts with pro plans expiring in 10 days
|
// get all accounts with plans expiring in 10 days
|
||||||
$accounts = Account::whereRaw('datediff(curdate(), pro_plan_paid) = 355')
|
$companies = Company::whereRaw('datediff(plan_expires, curdate()) = 10')
|
||||||
->orderBy('id')
|
->orderBy('id')
|
||||||
->get();
|
->get();
|
||||||
$this->info(count($accounts).' accounts found');
|
$this->info(count($companies).' companies found');
|
||||||
|
|
||||||
foreach ($accounts as $account) {
|
foreach ($companies as $company) {
|
||||||
// don't send multiple invoices to multi-company users
|
if (!count($company->accounts)) {
|
||||||
if ($userAccountId = $this->accountRepo->getUserAccountId($account)) {
|
continue;
|
||||||
if (isset($sentTo[$userAccountId])) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
$sentTo[$userAccountId] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$account = $company->accounts->sortBy('id')->first();
|
||||||
|
$plan = $company->plan;
|
||||||
|
$term = $company->plan_term;
|
||||||
|
|
||||||
|
if ($company->pending_plan) {
|
||||||
|
$plan = $company->pending_plan;
|
||||||
|
$term = $company->pending_term;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($plan == PLAN_FREE || !$plan || !$term ){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$client = $this->accountRepo->getNinjaClient($account);
|
$client = $this->accountRepo->getNinjaClient($account);
|
||||||
$invitation = $this->accountRepo->createNinjaInvoice($client, $account);
|
$invitation = $this->accountRepo->createNinjaInvoice($client, $account, $plan, $term);
|
||||||
|
|
||||||
// set the due date to 10 days from now
|
// set the due date to 10 days from now
|
||||||
$invoice = $invitation->invoice;
|
$invoice = $invitation->invoice;
|
||||||
|
@ -31,6 +31,7 @@ use App\Ninja\Mailers\ContactMailer;
|
|||||||
use App\Events\UserSignedUp;
|
use App\Events\UserSignedUp;
|
||||||
use App\Events\UserSettingsChanged;
|
use App\Events\UserSettingsChanged;
|
||||||
use App\Services\AuthService;
|
use App\Services\AuthService;
|
||||||
|
use App\Services\PaymentService;
|
||||||
|
|
||||||
use App\Http\Requests\UpdateAccountRequest;
|
use App\Http\Requests\UpdateAccountRequest;
|
||||||
|
|
||||||
@ -40,8 +41,9 @@ class AccountController extends BaseController
|
|||||||
protected $userMailer;
|
protected $userMailer;
|
||||||
protected $contactMailer;
|
protected $contactMailer;
|
||||||
protected $referralRepository;
|
protected $referralRepository;
|
||||||
|
protected $paymentService;
|
||||||
|
|
||||||
public function __construct(AccountRepository $accountRepo, UserMailer $userMailer, ContactMailer $contactMailer, ReferralRepository $referralRepository)
|
public function __construct(AccountRepository $accountRepo, UserMailer $userMailer, ContactMailer $contactMailer, ReferralRepository $referralRepository, PaymentService $paymentService)
|
||||||
{
|
{
|
||||||
//parent::__construct();
|
//parent::__construct();
|
||||||
|
|
||||||
@ -49,6 +51,7 @@ class AccountController extends BaseController
|
|||||||
$this->userMailer = $userMailer;
|
$this->userMailer = $userMailer;
|
||||||
$this->contactMailer = $contactMailer;
|
$this->contactMailer = $contactMailer;
|
||||||
$this->referralRepository = $referralRepository;
|
$this->referralRepository = $referralRepository;
|
||||||
|
$this->paymentService = $paymentService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function demo()
|
public function demo()
|
||||||
@ -111,10 +114,135 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
public function enableProPlan()
|
public function enableProPlan()
|
||||||
{
|
{
|
||||||
$invitation = $this->accountRepo->enableProPlan();
|
if (Auth::user()->isPro() && ! Auth::user()->isTrial()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invitation = $this->accountRepo->enablePlan();
|
||||||
|
|
||||||
return $invitation->invitation_key;
|
return $invitation->invitation_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function changePlan() {
|
||||||
|
$user = Auth::user();
|
||||||
|
$account = $user->account;
|
||||||
|
|
||||||
|
$plan = Input::get('plan');
|
||||||
|
$term = Input::get('plan_term');
|
||||||
|
|
||||||
|
$planDetails = $account->getPlanDetails(false, false);
|
||||||
|
|
||||||
|
$credit = 0;
|
||||||
|
if ($planDetails) {
|
||||||
|
if ($planDetails['plan'] == PLAN_PRO && $plan == PLAN_ENTERPRISE) {
|
||||||
|
// Upgrade from pro to enterprise
|
||||||
|
if($planDetails['term'] == PLAN_TERM_YEARLY && $term == PLAN_TERM_MONTHLY) {
|
||||||
|
// Upgrade to yearly for now; switch to monthly in a year
|
||||||
|
$pending_monthly = true;
|
||||||
|
$term = PLAN_TERM_YEARLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
$new_plan = array(
|
||||||
|
'plan' => PLAN_ENTERPRISE,
|
||||||
|
'term' => $term,
|
||||||
|
);
|
||||||
|
} elseif ($planDetails['plan'] == $plan) {
|
||||||
|
// Term switch
|
||||||
|
if ($planDetails['term'] == PLAN_TERM_YEARLY && $term == PLAN_TERM_MONTHLY) {
|
||||||
|
$pending_change = array(
|
||||||
|
'plan' => $plan,
|
||||||
|
'term' => $term
|
||||||
|
);
|
||||||
|
} elseif ($planDetails['term'] == PLAN_TERM_MONTHLY && $term == PLAN_TERM_YEARLY) {
|
||||||
|
$new_plan = array(
|
||||||
|
'plan' => $plan,
|
||||||
|
'term' => $term,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Cancel the pending change
|
||||||
|
$account->company->pending_plan = null;
|
||||||
|
$account->company->pending_term = null;
|
||||||
|
$account->company->save();
|
||||||
|
Session::flash('message', trans('texts.updated_plan'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Downgrade
|
||||||
|
$refund_deadline = clone $planDetails['started'];
|
||||||
|
$refund_deadline->modify('+30 days');
|
||||||
|
|
||||||
|
if ($plan == PLAN_FREE && $refund_deadline >= date_create()) {
|
||||||
|
// Refund
|
||||||
|
$account->company->plan = null;
|
||||||
|
$account->company->plan_term = null;
|
||||||
|
$account->company->plan_started = null;
|
||||||
|
$account->company->plan_expires = null;
|
||||||
|
$account->company->plan_paid = null;
|
||||||
|
$account->company->pending_plan = null;
|
||||||
|
$account->company->pending_term = null;
|
||||||
|
|
||||||
|
if ($account->company->payment) {
|
||||||
|
$payment = $account->company->payment;
|
||||||
|
|
||||||
|
$gateway = $this->paymentService->createGateway($payment->account_gateway);
|
||||||
|
$refund = $gateway->refund(array(
|
||||||
|
'transactionReference' => $payment->transaction_reference,
|
||||||
|
'amount' => $payment->amount * 100
|
||||||
|
));
|
||||||
|
$refund->send();
|
||||||
|
$payment->delete();
|
||||||
|
Session::flash('message', trans('texts.plan_refunded'));
|
||||||
|
\Log::info("Refunded Plan Payment: {$account->name} - {$user->email}");
|
||||||
|
} else {
|
||||||
|
Session::flash('message', trans('texts.updated_plan'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$account->company->save();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$pending_change = array(
|
||||||
|
'plan' => $plan,
|
||||||
|
'term' => $plan == PLAN_FREE ? null : $term,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($new_plan)) {
|
||||||
|
$time_used = $planDetails['paid']->diff(date_create());
|
||||||
|
$days_used = $time_used->days;
|
||||||
|
|
||||||
|
if ($time_used->invert) {
|
||||||
|
// They paid in advance
|
||||||
|
$days_used *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$days_total = $planDetails['paid']->diff($planDetails['expires'])->days;
|
||||||
|
|
||||||
|
$percent_used = $days_used / $days_total;
|
||||||
|
$old_plan_price = Account::$plan_prices[$planDetails['plan']][$planDetails['term']];
|
||||||
|
$credit = $old_plan_price * (1 - $percent_used);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$new_plan = array(
|
||||||
|
'plan' => $plan,
|
||||||
|
'term' => $term,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($pending_change) && empty($new_plan)) {
|
||||||
|
$account->company->pending_plan = $pending_change['plan'];
|
||||||
|
$account->company->pending_term = $pending_change['term'];
|
||||||
|
$account->company->save();
|
||||||
|
|
||||||
|
Session::flash('message', trans('texts.updated_plan'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($new_plan)) {
|
||||||
|
$invitation = $this->accountRepo->enablePlan($new_plan['plan'], $new_plan['term'], $credit, !empty($pending_monthly));
|
||||||
|
return Redirect::to('payment/'.$invitation->invitation_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redirect::to('/settings/'.ACCOUNT_MANAGEMENT, 301);
|
||||||
|
}
|
||||||
|
|
||||||
public function setTrashVisible($entityType, $visible)
|
public function setTrashVisible($entityType, $visible)
|
||||||
{
|
{
|
||||||
@ -149,6 +277,8 @@ class AccountController extends BaseController
|
|||||||
return self::showInvoiceSettings();
|
return self::showInvoiceSettings();
|
||||||
} elseif ($section == ACCOUNT_IMPORT_EXPORT) {
|
} elseif ($section == ACCOUNT_IMPORT_EXPORT) {
|
||||||
return View::make('accounts.import_export', ['title' => trans('texts.import_export')]);
|
return View::make('accounts.import_export', ['title' => trans('texts.import_export')]);
|
||||||
|
} elseif ($section == ACCOUNT_MANAGEMENT) {
|
||||||
|
return self::showAccountManagement();
|
||||||
} elseif ($section == ACCOUNT_INVOICE_DESIGN || $section == ACCOUNT_CUSTOMIZE_DESIGN) {
|
} elseif ($section == ACCOUNT_INVOICE_DESIGN || $section == ACCOUNT_CUSTOMIZE_DESIGN) {
|
||||||
return self::showInvoiceDesign($section);
|
return self::showInvoiceDesign($section);
|
||||||
} elseif ($section == ACCOUNT_CLIENT_PORTAL) {
|
} elseif ($section == ACCOUNT_CLIENT_PORTAL) {
|
||||||
@ -232,6 +362,18 @@ class AccountController extends BaseController
|
|||||||
return View::make('accounts.details', $data);
|
return View::make('accounts.details', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function showAccountManagement()
|
||||||
|
{
|
||||||
|
$account = Auth::user()->account;
|
||||||
|
$data = [
|
||||||
|
'account' => $account,
|
||||||
|
'planDetails' => $account->getPlanDetails(true),
|
||||||
|
'title' => trans('texts.account_management'),
|
||||||
|
];
|
||||||
|
|
||||||
|
return View::make('accounts.management', $data);
|
||||||
|
}
|
||||||
|
|
||||||
public function showUserDetails()
|
public function showUserDetails()
|
||||||
{
|
{
|
||||||
$oauthLoginUrls = [];
|
$oauthLoginUrls = [];
|
||||||
@ -379,7 +521,7 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
$invoice->client = $client;
|
$invoice->client = $client;
|
||||||
$invoice->invoice_items = [$invoiceItem];
|
$invoice->invoice_items = [$invoiceItem];
|
||||||
//$invoice->documents = $account->isPro() ? [$document] : [];
|
//$invoice->documents = $account->hasFeature(FEATURE_DOCUMENTS) ? [$document] : [];
|
||||||
$invoice->documents = [];
|
$invoice->documents = [];
|
||||||
|
|
||||||
$data['account'] = $account;
|
$data['account'] = $account;
|
||||||
@ -553,7 +695,7 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
private function saveCustomizeDesign()
|
private function saveCustomizeDesign()
|
||||||
{
|
{
|
||||||
if (Auth::user()->account->isPro()) {
|
if (Auth::user()->account->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN)) {
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
$account->custom_design = Input::get('custom_design');
|
$account->custom_design = Input::get('custom_design');
|
||||||
$account->invoice_design_id = CUSTOM_DESIGN;
|
$account->invoice_design_id = CUSTOM_DESIGN;
|
||||||
@ -568,7 +710,7 @@ class AccountController extends BaseController
|
|||||||
private function saveClientPortal()
|
private function saveClientPortal()
|
||||||
{
|
{
|
||||||
// Only allowed for pro Invoice Ninja users or white labeled self-hosted users
|
// Only allowed for pro Invoice Ninja users or white labeled self-hosted users
|
||||||
if ((Utils::isNinja() && Auth::user()->account->isPro()) || Auth::user()->account->isWhiteLabel()) {
|
if (Auth::user()->account->hasFeature(FEATURE_CLIENT_PORTAL_CSS)) {
|
||||||
$input_css = Input::get('client_view_css');
|
$input_css = Input::get('client_view_css');
|
||||||
if (Utils::isNinja()) {
|
if (Utils::isNinja()) {
|
||||||
// Allow referencing the body element
|
// Allow referencing the body element
|
||||||
@ -619,7 +761,7 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
private function saveEmailTemplates()
|
private function saveEmailTemplates()
|
||||||
{
|
{
|
||||||
if (Auth::user()->account->isPro()) {
|
if (Auth::user()->account->hasFeature(FEATURE_EMAIL_TEMPLATES_REMINDERS)) {
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
|
|
||||||
foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_PAYMENT, REMINDER1, REMINDER2, REMINDER3] as $type) {
|
foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_PAYMENT, REMINDER1, REMINDER2, REMINDER3] as $type) {
|
||||||
@ -681,7 +823,7 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
private function saveEmailSettings()
|
private function saveEmailSettings()
|
||||||
{
|
{
|
||||||
if (Auth::user()->account->isPro()) {
|
if (Auth::user()->account->hasFeature(FEATURE_CUSTOM_EMAILS)) {
|
||||||
$rules = [];
|
$rules = [];
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
$iframeURL = preg_replace('/[^a-zA-Z0-9_\-\:\/\.]/', '', substr(strtolower(Input::get('iframe_url')), 0, MAX_IFRAME_URL_LENGTH));
|
$iframeURL = preg_replace('/[^a-zA-Z0-9_\-\:\/\.]/', '', substr(strtolower(Input::get('iframe_url')), 0, MAX_IFRAME_URL_LENGTH));
|
||||||
@ -724,7 +866,7 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
private function saveInvoiceSettings()
|
private function saveInvoiceSettings()
|
||||||
{
|
{
|
||||||
if (Auth::user()->account->isPro()) {
|
if (Auth::user()->account->hasFeature(FEATURE_INVOICE_SETTINGS)) {
|
||||||
$rules = [
|
$rules = [
|
||||||
'invoice_number_pattern' => 'has_counter',
|
'invoice_number_pattern' => 'has_counter',
|
||||||
'quote_number_pattern' => 'has_counter',
|
'quote_number_pattern' => 'has_counter',
|
||||||
@ -805,7 +947,7 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
private function saveInvoiceDesign()
|
private function saveInvoiceDesign()
|
||||||
{
|
{
|
||||||
if (Auth::user()->account->isPro()) {
|
if (Auth::user()->account->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN)) {
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
$account->hide_quantity = Input::get('hide_quantity') ? true : false;
|
$account->hide_quantity = Input::get('hide_quantity') ? true : false;
|
||||||
$account->hide_paid_to_date = Input::get('hide_paid_to_date') ? true : false;
|
$account->hide_paid_to_date = Input::get('hide_paid_to_date') ? true : false;
|
||||||
@ -1054,7 +1196,7 @@ class AccountController extends BaseController
|
|||||||
$user->registered = true;
|
$user->registered = true;
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
$user->account->startTrial();
|
$user->account->startTrial(PLAN_PRO);
|
||||||
|
|
||||||
if (Input::get('go_pro') == 'true') {
|
if (Input::get('go_pro') == 'true') {
|
||||||
Session::set(REQUESTED_PRO_PLAN, true);
|
Session::set(REQUESTED_PRO_PLAN, true);
|
||||||
@ -1110,6 +1252,9 @@ class AccountController extends BaseController
|
|||||||
\Log::info("Canceled Account: {$account->name} - {$user->email}");
|
\Log::info("Canceled Account: {$account->name} - {$user->email}");
|
||||||
|
|
||||||
$this->accountRepo->unlinkAccount($account);
|
$this->accountRepo->unlinkAccount($account);
|
||||||
|
if ($account->company->accounts->count() == 1) {
|
||||||
|
$account->company->forceDelete();
|
||||||
|
}
|
||||||
$account->forceDelete();
|
$account->forceDelete();
|
||||||
|
|
||||||
Auth::logout();
|
Auth::logout();
|
||||||
@ -1126,12 +1271,12 @@ class AccountController extends BaseController
|
|||||||
return Redirect::to('/settings/'.ACCOUNT_USER_DETAILS)->with('message', trans('texts.confirmation_resent'));
|
return Redirect::to('/settings/'.ACCOUNT_USER_DETAILS)->with('message', trans('texts.confirmation_resent'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function startTrial()
|
public function startTrial($plan)
|
||||||
{
|
{
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
|
|
||||||
if ($user->isEligibleForTrial()) {
|
if ($user->isEligibleForTrial($plan)) {
|
||||||
$user->account->startTrial();
|
$user->account->startTrial($plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::back()->with('message', trans('texts.trial_success'));
|
return Redirect::back()->with('message', trans('texts.trial_success'));
|
||||||
|
@ -133,6 +133,9 @@ class AuthController extends Controller {
|
|||||||
if (Auth::check() && !Auth::user()->registered) {
|
if (Auth::check() && !Auth::user()->registered) {
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
$this->accountRepo->unlinkAccount($account);
|
$this->accountRepo->unlinkAccount($account);
|
||||||
|
if ($account->company->accounts->count() == 1) {
|
||||||
|
$account->company->forceDelete();
|
||||||
|
}
|
||||||
$account->forceDelete();
|
$account->forceDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class AuthController extends Controller {
|
|||||||
$client = $invoice->client;
|
$client = $invoice->client;
|
||||||
$account = $client->account;
|
$account = $client->account;
|
||||||
|
|
||||||
$data['hideLogo'] = $account->isWhiteLabel();
|
$data['hideLogo'] = $account->hasFeature(FEATURE_WHITE_LABEL);
|
||||||
$data['clientViewCSS'] = $account->clientViewCSS();
|
$data['clientViewCSS'] = $account->clientViewCSS();
|
||||||
$data['clientFontUrl'] = $account->getFontsUrl();
|
$data['clientFontUrl'] = $account->getFontsUrl();
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ class PasswordController extends Controller {
|
|||||||
$client = $invoice->client;
|
$client = $invoice->client;
|
||||||
$account = $client->account;
|
$account = $client->account;
|
||||||
|
|
||||||
$data['hideLogo'] = $account->isWhiteLabel();
|
$data['hideLogo'] = $account->hasFeature(FEATURE_WHITE_LABEL);
|
||||||
$data['clientViewCSS'] = $account->clientViewCSS();
|
$data['clientViewCSS'] = $account->clientViewCSS();
|
||||||
$data['clientFontUrl'] = $account->getFontsUrl();
|
$data['clientFontUrl'] = $account->getFontsUrl();
|
||||||
}
|
}
|
||||||
@ -117,7 +117,7 @@ class PasswordController extends Controller {
|
|||||||
$client = $invoice->client;
|
$client = $invoice->client;
|
||||||
$account = $client->account;
|
$account = $client->account;
|
||||||
|
|
||||||
$data['hideLogo'] = $account->isWhiteLabel();
|
$data['hideLogo'] = $account->hasFeature(FEATURE_WHITE_LABEL);
|
||||||
$data['clientViewCSS'] = $account->clientViewCSS();
|
$data['clientViewCSS'] = $account->clientViewCSS();
|
||||||
$data['clientFontUrl'] = $account->getFontsUrl();
|
$data['clientFontUrl'] = $account->getFontsUrl();
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ class ClientController extends BaseController
|
|||||||
if(Task::canCreate()){
|
if(Task::canCreate()){
|
||||||
$actionLinks[] = ['label' => trans('texts.new_task'), 'url' => URL::to('/tasks/create/'.$client->public_id)];
|
$actionLinks[] = ['label' => trans('texts.new_task'), 'url' => URL::to('/tasks/create/'.$client->public_id)];
|
||||||
}
|
}
|
||||||
if (Utils::isPro() && Invoice::canCreate()) {
|
if (Utils::hasFeature(FEATURE_QUOTES) && Invoice::canCreate()) {
|
||||||
$actionLinks[] = ['label' => trans('texts.new_quote'), 'url' => URL::to('/quotes/create/'.$client->public_id)];
|
$actionLinks[] = ['label' => trans('texts.new_quote'), 'url' => URL::to('/quotes/create/'.$client->public_id)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +201,7 @@ class ClientController extends BaseController
|
|||||||
|
|
||||||
if (Auth::user()->account->isNinjaAccount()) {
|
if (Auth::user()->account->isNinjaAccount()) {
|
||||||
if ($account = Account::whereId($client->public_id)->first()) {
|
if ($account = Account::whereId($client->public_id)->first()) {
|
||||||
$data['proPlanPaid'] = $account['pro_plan_paid'];
|
$data['planDetails'] = $account->getPlanDetails(false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ class DocumentController extends BaseController
|
|||||||
|
|
||||||
public function postUpload()
|
public function postUpload()
|
||||||
{
|
{
|
||||||
if (!Utils::isPro()) {
|
if (!Utils::hasFeature(FEATURE_DOCUMENTS)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +132,11 @@ class InvoiceController extends BaseController
|
|||||||
$invoice->start_date = Utils::fromSqlDate($invoice->start_date);
|
$invoice->start_date = Utils::fromSqlDate($invoice->start_date);
|
||||||
$invoice->end_date = Utils::fromSqlDate($invoice->end_date);
|
$invoice->end_date = Utils::fromSqlDate($invoice->end_date);
|
||||||
$invoice->last_sent_date = Utils::fromSqlDate($invoice->last_sent_date);
|
$invoice->last_sent_date = Utils::fromSqlDate($invoice->last_sent_date);
|
||||||
$invoice->is_pro = Auth::user()->isPro();
|
$invoice->features = [
|
||||||
|
'customize_invoice_design' => Auth::user()->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN),
|
||||||
|
'remove_created_by' => Auth::user()->hasFeature(FEATURE_REMOVE_CREATED_BY),
|
||||||
|
'invoice_settings' => Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS),
|
||||||
|
];
|
||||||
|
|
||||||
$actions = [
|
$actions = [
|
||||||
['url' => 'javascript:onCloneClick()', 'label' => trans("texts.clone_{$entityType}")],
|
['url' => 'javascript:onCloneClick()', 'label' => trans("texts.clone_{$entityType}")],
|
||||||
@ -573,7 +577,11 @@ class InvoiceController extends BaseController
|
|||||||
$invoice->load('user', 'invoice_items', 'documents', 'expenses', 'expenses.documents', 'account.country', 'client.contacts', 'client.country');
|
$invoice->load('user', 'invoice_items', 'documents', 'expenses', 'expenses.documents', 'account.country', 'client.contacts', 'client.country');
|
||||||
$invoice->invoice_date = Utils::fromSqlDate($invoice->invoice_date);
|
$invoice->invoice_date = Utils::fromSqlDate($invoice->invoice_date);
|
||||||
$invoice->due_date = Utils::fromSqlDate($invoice->due_date);
|
$invoice->due_date = Utils::fromSqlDate($invoice->due_date);
|
||||||
$invoice->is_pro = Auth::user()->isPro();
|
$invoice->features = [
|
||||||
|
'customize_invoice_design' => Auth::user()->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN),
|
||||||
|
'remove_created_by' => Auth::user()->hasFeature(FEATURE_REMOVE_CREATED_BY),
|
||||||
|
'invoice_settings' => Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS),
|
||||||
|
];
|
||||||
$invoice->is_quote = intval($invoice->is_quote);
|
$invoice->is_quote = intval($invoice->is_quote);
|
||||||
|
|
||||||
$activityTypeId = $invoice->is_quote ? ACTIVITY_TYPE_UPDATE_QUOTE : ACTIVITY_TYPE_UPDATE_INVOICE;
|
$activityTypeId = $invoice->is_quote ? ACTIVITY_TYPE_UPDATE_QUOTE : ACTIVITY_TYPE_UPDATE_INVOICE;
|
||||||
@ -591,7 +599,11 @@ class InvoiceController extends BaseController
|
|||||||
$backup = json_decode($activity->json_backup);
|
$backup = json_decode($activity->json_backup);
|
||||||
$backup->invoice_date = Utils::fromSqlDate($backup->invoice_date);
|
$backup->invoice_date = Utils::fromSqlDate($backup->invoice_date);
|
||||||
$backup->due_date = Utils::fromSqlDate($backup->due_date);
|
$backup->due_date = Utils::fromSqlDate($backup->due_date);
|
||||||
$backup->is_pro = Auth::user()->isPro();
|
$invoice->features = [
|
||||||
|
'customize_invoice_design' => Auth::user()->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN),
|
||||||
|
'remove_created_by' => Auth::user()->hasFeature(FEATURE_REMOVE_CREATED_BY),
|
||||||
|
'invoice_settings' => Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS),
|
||||||
|
];
|
||||||
$backup->is_quote = isset($backup->is_quote) && intval($backup->is_quote);
|
$backup->is_quote = isset($backup->is_quote) && intval($backup->is_quote);
|
||||||
$backup->account = $invoice->account->toArray();
|
$backup->account = $invoice->account->toArray();
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ class PaymentController extends BaseController
|
|||||||
'currencyId' => $client->getCurrencyId(),
|
'currencyId' => $client->getCurrencyId(),
|
||||||
'currencyCode' => $client->currency ? $client->currency->code : ($account->currency ? $account->currency->code : 'USD'),
|
'currencyCode' => $client->currency ? $client->currency->code : ($account->currency ? $account->currency->code : 'USD'),
|
||||||
'account' => $client->account,
|
'account' => $client->account,
|
||||||
'hideLogo' => $account->isWhiteLabel(),
|
'hideLogo' => $account->hasFeature(FEATURE_WHITE_LABEL),
|
||||||
'hideHeader' => $account->isNinjaAccount(),
|
'hideHeader' => $account->isNinjaAccount(),
|
||||||
'clientViewCSS' => $account->clientViewCSS(),
|
'clientViewCSS' => $account->clientViewCSS(),
|
||||||
'clientFontUrl' => $account->getFontsUrl(),
|
'clientFontUrl' => $account->getFontsUrl(),
|
||||||
|
@ -72,7 +72,11 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
$invoice->invoice_date = Utils::fromSqlDate($invoice->invoice_date);
|
$invoice->invoice_date = Utils::fromSqlDate($invoice->invoice_date);
|
||||||
$invoice->due_date = Utils::fromSqlDate($invoice->due_date);
|
$invoice->due_date = Utils::fromSqlDate($invoice->due_date);
|
||||||
$invoice->is_pro = $account->isPro();
|
$invoice->features = [
|
||||||
|
'customize_invoice_design' => $account->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN),
|
||||||
|
'remove_created_by' => $account->hasFeature(FEATURE_REMOVE_CREATED_BY),
|
||||||
|
'invoice_settings' => $account->hasFeature(FEATURE_INVOICE_SETTINGS),
|
||||||
|
];
|
||||||
$invoice->invoice_fonts = $account->getFontsData();
|
$invoice->invoice_fonts = $account->getFontsData();
|
||||||
|
|
||||||
if ($invoice->invoice_design_id == CUSTOM_DESIGN) {
|
if ($invoice->invoice_design_id == CUSTOM_DESIGN) {
|
||||||
@ -122,10 +126,10 @@ class PublicClientController extends BaseController
|
|||||||
'account' => $account,
|
'account' => $account,
|
||||||
'showApprove' => $showApprove,
|
'showApprove' => $showApprove,
|
||||||
'showBreadcrumbs' => false,
|
'showBreadcrumbs' => false,
|
||||||
'hideLogo' => $account->isWhiteLabel(),
|
'hideLogo' => $account->hasFeature(FEATURE_WHITE_LABEL),
|
||||||
'hideHeader' => $account->isNinjaAccount() || !$account->enable_client_portal,
|
'hideHeader' => $account->isNinjaAccount() || !$account->enable_client_portal,
|
||||||
'hideDashboard' => !$account->enable_client_portal_dashboard,
|
'hideDashboard' => !$account->enable_client_portal_dashboard,
|
||||||
'showDocuments' => $account->isPro(),
|
'showDocuments' => $account->hasFeature(FEATURE_DOCUMENTS),
|
||||||
'clientViewCSS' => $account->clientViewCSS(),
|
'clientViewCSS' => $account->clientViewCSS(),
|
||||||
'clientFontUrl' => $account->getFontsUrl(),
|
'clientFontUrl' => $account->getFontsUrl(),
|
||||||
'invoice' => $invoice->hidePrivateFields(),
|
'invoice' => $invoice->hidePrivateFields(),
|
||||||
@ -140,7 +144,7 @@ class PublicClientController extends BaseController
|
|||||||
'phantomjs' => Input::has('phantomjs'),
|
'phantomjs' => Input::has('phantomjs'),
|
||||||
);
|
);
|
||||||
|
|
||||||
if($account->isPro() && $this->canCreateZip()){
|
if($account->hasFeature(FEATURE_DOCUMENTS) && $this->canCreateZip()){
|
||||||
$zipDocs = $this->getInvoiceZipDocuments($invoice, $size);
|
$zipDocs = $this->getInvoiceZipDocuments($invoice, $size);
|
||||||
|
|
||||||
if(count($zipDocs) > 1){
|
if(count($zipDocs) > 1){
|
||||||
@ -220,8 +224,8 @@ class PublicClientController extends BaseController
|
|||||||
'color' => $color,
|
'color' => $color,
|
||||||
'account' => $account,
|
'account' => $account,
|
||||||
'client' => $client,
|
'client' => $client,
|
||||||
'hideLogo' => $account->isWhiteLabel(),
|
'hideLogo' => $account->hasFeature(FEATURE_WHITE_LABEL),
|
||||||
'showDocuments' => $account->isPro(),
|
'showDocuments' => $account->hasFeature(FEATURE_DOCUMENTS),
|
||||||
'clientViewCSS' => $account->clientViewCSS(),
|
'clientViewCSS' => $account->clientViewCSS(),
|
||||||
'clientFontUrl' => $account->getFontsUrl(),
|
'clientFontUrl' => $account->getFontsUrl(),
|
||||||
];
|
];
|
||||||
@ -273,9 +277,9 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'color' => $color,
|
'color' => $color,
|
||||||
'hideLogo' => $account->isWhiteLabel(),
|
'hideLogo' => $account->hasFeature(FEATURE_WHITE_LABEL),
|
||||||
'hideDashboard' => !$account->enable_client_portal_dashboard,
|
'hideDashboard' => !$account->enable_client_portal_dashboard,
|
||||||
'showDocuments' => $account->isPro(),
|
'showDocuments' => $account->hasFeature(FEATURE_DOCUMENTS),
|
||||||
'clientViewCSS' => $account->clientViewCSS(),
|
'clientViewCSS' => $account->clientViewCSS(),
|
||||||
'clientFontUrl' => $account->getFontsUrl(),
|
'clientFontUrl' => $account->getFontsUrl(),
|
||||||
'title' => trans('texts.invoices'),
|
'title' => trans('texts.invoices'),
|
||||||
@ -310,9 +314,9 @@ class PublicClientController extends BaseController
|
|||||||
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
||||||
$data = [
|
$data = [
|
||||||
'color' => $color,
|
'color' => $color,
|
||||||
'hideLogo' => $account->isWhiteLabel(),
|
'hideLogo' => $account->hasFeature(FEATURE_WHITE_LABEL),
|
||||||
'hideDashboard' => !$account->enable_client_portal_dashboard,
|
'hideDashboard' => !$account->enable_client_portal_dashboard,
|
||||||
'showDocuments' => $account->isPro(),
|
'showDocuments' => $account->hasFeature(FEATURE_DOCUMENTS),
|
||||||
'clientViewCSS' => $account->clientViewCSS(),
|
'clientViewCSS' => $account->clientViewCSS(),
|
||||||
'clientFontUrl' => $account->getFontsUrl(),
|
'clientFontUrl' => $account->getFontsUrl(),
|
||||||
'entityType' => ENTITY_PAYMENT,
|
'entityType' => ENTITY_PAYMENT,
|
||||||
@ -354,9 +358,9 @@ class PublicClientController extends BaseController
|
|||||||
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
||||||
$data = [
|
$data = [
|
||||||
'color' => $color,
|
'color' => $color,
|
||||||
'hideLogo' => $account->isWhiteLabel(),
|
'hideLogo' => $account->hasFeature(FEATURE_WHITE_LABEL),
|
||||||
'hideDashboard' => !$account->enable_client_portal_dashboard,
|
'hideDashboard' => !$account->enable_client_portal_dashboard,
|
||||||
'showDocuments' => $account->isPro(),
|
'showDocuments' => $account->hasFeature(FEATURE_DOCUMENTS),
|
||||||
'clientViewCSS' => $account->clientViewCSS(),
|
'clientViewCSS' => $account->clientViewCSS(),
|
||||||
'clientFontUrl' => $account->getFontsUrl(),
|
'clientFontUrl' => $account->getFontsUrl(),
|
||||||
'title' => trans('texts.quotes'),
|
'title' => trans('texts.quotes'),
|
||||||
@ -392,9 +396,9 @@ class PublicClientController extends BaseController
|
|||||||
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
||||||
$data = [
|
$data = [
|
||||||
'color' => $color,
|
'color' => $color,
|
||||||
'hideLogo' => $account->isWhiteLabel(),
|
'hideLogo' => $account->hasFeature(FEATURE_WHITE_LABEL),
|
||||||
'hideDashboard' => !$account->enable_client_portal_dashboard,
|
'hideDashboard' => !$account->enable_client_portal_dashboard,
|
||||||
'showDocuments' => $account->isPro(),
|
'showDocuments' => $account->hasFeature(FEATURE_DOCUMENTS),
|
||||||
'clientViewCSS' => $account->clientViewCSS(),
|
'clientViewCSS' => $account->clientViewCSS(),
|
||||||
'clientFontUrl' => $account->getFontsUrl(),
|
'clientFontUrl' => $account->getFontsUrl(),
|
||||||
'title' => trans('texts.documents'),
|
'title' => trans('texts.documents'),
|
||||||
|
@ -47,7 +47,7 @@ class QuoteController extends BaseController
|
|||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
if (!Utils::isPro()) {
|
if (!Utils::hasFeature(FEATURE_QUOTES)) {
|
||||||
return Redirect::to('/invoices/create');
|
return Redirect::to('/invoices/create');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ class QuoteController extends BaseController
|
|||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Utils::isPro()) {
|
if (!Utils::hasFeature(FEATURE_QUOTES)) {
|
||||||
return Redirect::to('/invoices/create');
|
return Redirect::to('/invoices/create');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ class ReportController extends BaseController
|
|||||||
$message = '';
|
$message = '';
|
||||||
$fileName = storage_path().'/dataviz_sample.txt';
|
$fileName = storage_path().'/dataviz_sample.txt';
|
||||||
|
|
||||||
if (Auth::user()->account->isPro()) {
|
if (Auth::user()->account->hasFeature(FEATURE_REPORTS)) {
|
||||||
$account = Account::where('id', '=', Auth::user()->account->id)
|
$account = Account::where('id', '=', Auth::user()->account->id)
|
||||||
->with(['clients.invoices.invoice_items', 'clients.contacts'])
|
->with(['clients.invoices.invoice_items', 'clients.contacts'])
|
||||||
->first();
|
->first();
|
||||||
@ -99,7 +99,7 @@ class ReportController extends BaseController
|
|||||||
'title' => trans('texts.charts_and_reports'),
|
'title' => trans('texts.charts_and_reports'),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (Auth::user()->account->isPro()) {
|
if (Auth::user()->account->hasFeature(FEATURE_REPORTS)) {
|
||||||
if ($enableReport) {
|
if ($enableReport) {
|
||||||
$isExport = $action == 'export';
|
$isExport = $action == 'export';
|
||||||
$params = array_merge($params, self::generateReport($reportType, $startDate, $endDate, $dateField, $isExport));
|
$params = array_merge($params, self::generateReport($reportType, $startDate, $endDate, $dateField, $isExport));
|
||||||
|
@ -93,7 +93,7 @@ class TokenController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function save($tokenPublicId = false)
|
public function save($tokenPublicId = false)
|
||||||
{
|
{
|
||||||
if (Auth::user()->account->isPro()) {
|
if (Auth::user()->account->hasFeature(FEATURE_API)) {
|
||||||
$rules = [
|
$rules = [
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
];
|
];
|
||||||
|
@ -164,7 +164,7 @@ class UserController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function save($userPublicId = false)
|
public function save($userPublicId = false)
|
||||||
{
|
{
|
||||||
if (Auth::user()->isPro() && ! Auth::user()->isTrial()) {
|
if (Auth::user()->hasFeature(FEATURE_USERS)) {
|
||||||
$rules = [
|
$rules = [
|
||||||
'first_name' => 'required',
|
'first_name' => 'required',
|
||||||
'last_name' => 'required',
|
'last_name' => 'required',
|
||||||
@ -190,8 +190,10 @@ class UserController extends BaseController
|
|||||||
$user->last_name = trim(Input::get('last_name'));
|
$user->last_name = trim(Input::get('last_name'));
|
||||||
$user->username = trim(Input::get('email'));
|
$user->username = trim(Input::get('email'));
|
||||||
$user->email = trim(Input::get('email'));
|
$user->email = trim(Input::get('email'));
|
||||||
$user->is_admin = boolval(Input::get('is_admin'));
|
if (Auth::user()->hasFeature(FEATURE_USER_PERMISSIONS)) {
|
||||||
$user->permissions = Input::get('permissions');
|
$user->is_admin = boolval(Input::get('is_admin'));
|
||||||
|
$user->permissions = Input::get('permissions');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$lastUser = User::withTrashed()->where('account_id', '=', Auth::user()->account_id)
|
$lastUser = User::withTrashed()->where('account_id', '=', Auth::user()->account_id)
|
||||||
->orderBy('public_id', 'DESC')->first();
|
->orderBy('public_id', 'DESC')->first();
|
||||||
@ -202,12 +204,14 @@ class UserController extends BaseController
|
|||||||
$user->last_name = trim(Input::get('last_name'));
|
$user->last_name = trim(Input::get('last_name'));
|
||||||
$user->username = trim(Input::get('email'));
|
$user->username = trim(Input::get('email'));
|
||||||
$user->email = trim(Input::get('email'));
|
$user->email = trim(Input::get('email'));
|
||||||
$user->is_admin = boolval(Input::get('is_admin'));
|
|
||||||
$user->registered = true;
|
$user->registered = true;
|
||||||
$user->password = str_random(RANDOM_KEY_LENGTH);
|
$user->password = str_random(RANDOM_KEY_LENGTH);
|
||||||
$user->confirmation_code = str_random(RANDOM_KEY_LENGTH);
|
$user->confirmation_code = str_random(RANDOM_KEY_LENGTH);
|
||||||
$user->public_id = $lastUser->public_id + 1;
|
$user->public_id = $lastUser->public_id + 1;
|
||||||
$user->permissions = Input::get('permissions');
|
if (Auth::user()->hasFeature(FEATURE_USER_PERMISSIONS)) {
|
||||||
|
$user->is_admin = boolval(Input::get('is_admin'));
|
||||||
|
$user->permissions = Input::get('permissions');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$user->save();
|
$user->save();
|
||||||
@ -286,6 +290,9 @@ class UserController extends BaseController
|
|||||||
if (!Auth::user()->registered) {
|
if (!Auth::user()->registered) {
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
$this->accountRepo->unlinkAccount($account);
|
$this->accountRepo->unlinkAccount($account);
|
||||||
|
if ($account->company->accounts->count() == 1) {
|
||||||
|
$account->company->forceDelete();
|
||||||
|
}
|
||||||
$account->forceDelete();
|
$account->forceDelete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,8 +175,8 @@ class VendorController extends BaseController
|
|||||||
$data = array_merge($data, self::getViewModel());
|
$data = array_merge($data, self::getViewModel());
|
||||||
|
|
||||||
if (Auth::user()->account->isNinjaAccount()) {
|
if (Auth::user()->account->isNinjaAccount()) {
|
||||||
if ($account = Account::whereId($vendor->public_id)->first()) {
|
if ($account = Account::whereId($client->public_id)->first()) {
|
||||||
$data['proPlanPaid'] = $account['pro_plan_paid'];
|
$data['planDetails'] = $account->getPlanDetails(false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class ApiCheck {
|
|||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Utils::isPro() && !$loggingIn) {
|
if (!Utils::hasFeature(FEATURE_API) && !$loggingIn) {
|
||||||
return Response::json('API requires pro plan', 403, $headers);
|
return Response::json('API requires pro plan', 403, $headers);
|
||||||
} else {
|
} else {
|
||||||
$key = Auth::check() ? Auth::user()->account->id : $request->getClientIp();
|
$key = Auth::check() ? Auth::user()->account->id : $request->getClientIp();
|
||||||
|
@ -42,7 +42,7 @@ class Authenticate {
|
|||||||
|
|
||||||
// Does this account require portal passwords?
|
// Does this account require portal passwords?
|
||||||
$account = Account::whereId($account_id)->first();
|
$account = Account::whereId($account_id)->first();
|
||||||
if($account && (!$account->enable_portal_password || !$account->isPro())){
|
if($account && (!$account->enable_portal_password || !$account->hasFeature(FEATURE_CLIENT_PORTAL_PASSWORD))){
|
||||||
$authenticated = true;
|
$authenticated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,9 +141,10 @@ class StartupCheck
|
|||||||
}
|
}
|
||||||
} elseif ($productId == PRODUCT_WHITE_LABEL) {
|
} elseif ($productId == PRODUCT_WHITE_LABEL) {
|
||||||
if ($data == 'valid') {
|
if ($data == 'valid') {
|
||||||
$account = Auth::user()->account;
|
$company = Auth::user()->account->company;
|
||||||
$account->pro_plan_paid = date_create()->format('Y-m-d');
|
$company->plan_paid = date_create()->format('Y-m-d');
|
||||||
$account->save();
|
$company->plan = PLAN_WHITE_LABEL;
|
||||||
|
$company->save();
|
||||||
|
|
||||||
Session::flash('message', trans('texts.bought_white_label'));
|
Session::flash('message', trans('texts.bought_white_label'));
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,8 @@ Route::group([
|
|||||||
Route::resource('users', 'UserController');
|
Route::resource('users', 'UserController');
|
||||||
Route::post('users/bulk', 'UserController@bulk');
|
Route::post('users/bulk', 'UserController@bulk');
|
||||||
Route::get('send_confirmation/{user_id}', 'UserController@sendConfirmation');
|
Route::get('send_confirmation/{user_id}', 'UserController@sendConfirmation');
|
||||||
Route::get('start_trial', 'AccountController@startTrial');
|
Route::get('start_trial/{plan}', 'AccountController@startTrial')
|
||||||
|
->where(['plan'=>'pro']);
|
||||||
Route::get('restore_user/{user_id}', 'UserController@restoreUser');
|
Route::get('restore_user/{user_id}', 'UserController@restoreUser');
|
||||||
Route::post('users/change_password', 'UserController@changePassword');
|
Route::post('users/change_password', 'UserController@changePassword');
|
||||||
Route::get('/switch_account/{user_id}', 'UserController@switchAccount');
|
Route::get('/switch_account/{user_id}', 'UserController@switchAccount');
|
||||||
@ -212,6 +213,7 @@ Route::group([
|
|||||||
Route::get('settings/charts_and_reports', 'ReportController@showReports');
|
Route::get('settings/charts_and_reports', 'ReportController@showReports');
|
||||||
Route::post('settings/charts_and_reports', 'ReportController@showReports');
|
Route::post('settings/charts_and_reports', 'ReportController@showReports');
|
||||||
|
|
||||||
|
Route::post('settings/change_plan', 'AccountController@changePlan');
|
||||||
Route::post('settings/cancel_account', 'AccountController@cancelAccount');
|
Route::post('settings/cancel_account', 'AccountController@cancelAccount');
|
||||||
Route::post('settings/company_details', 'AccountController@updateDetails');
|
Route::post('settings/company_details', 'AccountController@updateDetails');
|
||||||
Route::get('settings/{section?}', 'AccountController@showSection');
|
Route::get('settings/{section?}', 'AccountController@showSection');
|
||||||
@ -354,6 +356,7 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('ACCOUNT_LOCALIZATION', 'localization');
|
define('ACCOUNT_LOCALIZATION', 'localization');
|
||||||
define('ACCOUNT_NOTIFICATIONS', 'notifications');
|
define('ACCOUNT_NOTIFICATIONS', 'notifications');
|
||||||
define('ACCOUNT_IMPORT_EXPORT', 'import_export');
|
define('ACCOUNT_IMPORT_EXPORT', 'import_export');
|
||||||
|
define('ACCOUNT_MANAGEMENT', 'account_management');
|
||||||
define('ACCOUNT_PAYMENTS', 'online_payments');
|
define('ACCOUNT_PAYMENTS', 'online_payments');
|
||||||
define('ACCOUNT_BANKS', 'bank_accounts');
|
define('ACCOUNT_BANKS', 'bank_accounts');
|
||||||
define('ACCOUNT_IMPORT_EXPENSES', 'import_expenses');
|
define('ACCOUNT_IMPORT_EXPENSES', 'import_expenses');
|
||||||
@ -552,7 +555,6 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('NINJA_WEB_URL', 'https://www.invoiceninja.com');
|
define('NINJA_WEB_URL', 'https://www.invoiceninja.com');
|
||||||
define('NINJA_APP_URL', 'https://app.invoiceninja.com');
|
define('NINJA_APP_URL', 'https://app.invoiceninja.com');
|
||||||
define('NINJA_VERSION', '2.5.1.3');
|
define('NINJA_VERSION', '2.5.1.3');
|
||||||
define('NINJA_DATE', '2000-01-01');
|
|
||||||
|
|
||||||
define('SOCIAL_LINK_FACEBOOK', 'https://www.facebook.com/invoiceninja');
|
define('SOCIAL_LINK_FACEBOOK', 'https://www.facebook.com/invoiceninja');
|
||||||
define('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja');
|
define('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja');
|
||||||
@ -582,6 +584,10 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('SELF_HOST_AFFILIATE_KEY', '8S69AD');
|
define('SELF_HOST_AFFILIATE_KEY', '8S69AD');
|
||||||
|
|
||||||
define('PRO_PLAN_PRICE', 50);
|
define('PRO_PLAN_PRICE', 50);
|
||||||
|
define('PLAN_PRICE_PRO_MONTHLY', 5);
|
||||||
|
define('PLAN_PRICE_PRO_YEARLY', 50);
|
||||||
|
define('PLAN_PRICE_ENTERPRISE_MONTHLY', 10);
|
||||||
|
define('PLAN_PRICE_ENTERPRISE_YEARLY', 100);
|
||||||
define('WHITE_LABEL_PRICE', 20);
|
define('WHITE_LABEL_PRICE', 20);
|
||||||
define('INVOICE_DESIGNS_PRICE', 10);
|
define('INVOICE_DESIGNS_PRICE', 10);
|
||||||
|
|
||||||
@ -644,7 +650,46 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
|
|
||||||
define('RESELLER_REVENUE_SHARE', 'A');
|
define('RESELLER_REVENUE_SHARE', 'A');
|
||||||
define('RESELLER_LIMITED_USERS', 'B');
|
define('RESELLER_LIMITED_USERS', 'B');
|
||||||
|
|
||||||
|
// These must be lowercase
|
||||||
|
define('PLAN_FREE', 'free');
|
||||||
|
define('PLAN_PRO', 'pro');
|
||||||
|
define('PLAN_ENTERPRISE', 'enterprise');
|
||||||
|
define('PLAN_WHITE_LABEL', 'white_label');
|
||||||
|
define('PLAN_TERM_MONTHLY', 'month');
|
||||||
|
define('PLAN_TERM_YEARLY', 'year');
|
||||||
|
|
||||||
|
// Pro
|
||||||
|
define('FEATURE_CUSTOMIZE_INVOICE_DESIGN', 'customize_invoice_design');
|
||||||
|
define('FEATURE_REMOVE_CREATED_BY', 'remove_created_by');
|
||||||
|
define('FEATURE_DIFFERENT_DESIGNS', 'different_designs');
|
||||||
|
define('FEATURE_EMAIL_TEMPLATES_REMINDERS', 'email_templates_reminders');
|
||||||
|
define('FEATURE_INVOICE_SETTINGS', 'invoice_settings');
|
||||||
|
define('FEATURE_CUSTOM_EMAILS', 'custom_emails');
|
||||||
|
define('FEATURE_PDF_ATTACHMENT', 'pdf_attachment');
|
||||||
|
define('FEATURE_MORE_INVOICE_DESIGNS', 'more_invoice_designs');
|
||||||
|
define('FEATURE_QUOTES', 'quotes');
|
||||||
|
define('FEATURE_REPORTS', 'reports');
|
||||||
|
define('FEATURE_API', 'api');
|
||||||
|
define('FEATURE_CLIENT_PORTAL_PASSWORD', 'client_portal_password');
|
||||||
|
define('FEATURE_CUSTOM_URL', 'custom_url');
|
||||||
|
|
||||||
|
define('FEATURE_MORE_CLIENTS', 'more_clients'); // No trial allowed
|
||||||
|
|
||||||
|
// Whitelabel
|
||||||
|
define('FEATURE_CLIENT_PORTAL_CSS', 'client_portal_css');
|
||||||
|
define('FEATURE_WHITE_LABEL', 'feature_white_label');
|
||||||
|
|
||||||
|
// Enterprise
|
||||||
|
define('FEATURE_DOCUMENTS', 'documents');
|
||||||
|
|
||||||
|
// No Trial allowed
|
||||||
|
define('FEATURE_USERS', 'users');// Grandfathered for old Pro users
|
||||||
|
define('FEATURE_USER_PERMISSIONS', 'user_permissions');
|
||||||
|
|
||||||
|
// Pro users who started paying on or before this date will be able to manage users
|
||||||
|
define('PRO_USERS_GRANDFATHER_DEADLINE', '2016-05-15');
|
||||||
|
|
||||||
$creditCards = [
|
$creditCards = [
|
||||||
1 => ['card' => 'images/credit_cards/Test-Visa-Icon.png', 'text' => 'Visa'],
|
1 => ['card' => 'images/credit_cards/Test-Visa-Icon.png', 'text' => 'Visa'],
|
||||||
2 => ['card' => 'images/credit_cards/Test-MasterCard-Icon.png', 'text' => 'Master Card'],
|
2 => ['card' => 'images/credit_cards/Test-MasterCard-Icon.png', 'text' => 'Master Card'],
|
||||||
|
@ -118,6 +118,11 @@ class Utils
|
|||||||
return Auth::check() && Auth::user()->isPro();
|
return Auth::check() && Auth::user()->isPro();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function hasFeature($feature)
|
||||||
|
{
|
||||||
|
return Auth::check() && Auth::user()->hasFeature($feature);
|
||||||
|
}
|
||||||
|
|
||||||
public static function isAdmin()
|
public static function isAdmin()
|
||||||
{
|
{
|
||||||
return Auth::check() && Auth::user()->is_admin;
|
return Auth::check() && Auth::user()->is_admin;
|
||||||
@ -440,7 +445,12 @@ class Utils
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dateTime = new DateTime($date);
|
if ($date instanceof DateTime) {
|
||||||
|
$dateTime = $date;
|
||||||
|
} else {
|
||||||
|
$dateTime = new DateTime($date);
|
||||||
|
}
|
||||||
|
|
||||||
$timestamp = $dateTime->getTimestamp();
|
$timestamp = $dateTime->getTimestamp();
|
||||||
$format = Session::get(SESSION_DATE_FORMAT, DEFAULT_DATE_FORMAT);
|
$format = Session::get(SESSION_DATE_FORMAT, DEFAULT_DATE_FORMAT);
|
||||||
|
|
||||||
@ -961,38 +971,6 @@ class Utils
|
|||||||
return $entity1;
|
return $entity1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function withinPastYear($date)
|
|
||||||
{
|
|
||||||
if (!$date || $date == '0000-00-00') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$today = new DateTime('now');
|
|
||||||
$datePaid = DateTime::createFromFormat('Y-m-d', $date);
|
|
||||||
$interval = $today->diff($datePaid);
|
|
||||||
|
|
||||||
return $interval->y == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getInterval($date)
|
|
||||||
{
|
|
||||||
if (!$date || $date == '0000-00-00') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$today = new DateTime('now');
|
|
||||||
$datePaid = DateTime::createFromFormat('Y-m-d', $date);
|
|
||||||
|
|
||||||
return $today->diff($datePaid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function withinPastTwoWeeks($date)
|
|
||||||
{
|
|
||||||
$interval = Utils::getInterval($date);
|
|
||||||
|
|
||||||
return $interval && $interval->d <= 14;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function addHttp($url)
|
public static function addHttp($url)
|
||||||
{
|
{
|
||||||
if (!preg_match("~^(?:f|ht)tps?://~i", $url)) {
|
if (!preg_match("~^(?:f|ht)tps?://~i", $url)) {
|
||||||
|
@ -14,10 +14,11 @@ class InvoiceListener
|
|||||||
{
|
{
|
||||||
public function createdInvoice(InvoiceWasCreated $event)
|
public function createdInvoice(InvoiceWasCreated $event)
|
||||||
{
|
{
|
||||||
if (Utils::isPro()) {
|
if (Utils::hasFeature(FEATURE_DIFFERENT_DESIGNS)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure the account has the same design set as the invoice does
|
||||||
if (Auth::check()) {
|
if (Auth::check()) {
|
||||||
$invoice = $event->invoice;
|
$invoice = $event->invoice;
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
|
@ -18,6 +18,17 @@ class Account extends Eloquent
|
|||||||
{
|
{
|
||||||
use PresentableTrait;
|
use PresentableTrait;
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
|
public static $plan_prices = array(
|
||||||
|
PLAN_PRO => array(
|
||||||
|
PLAN_TERM_MONTHLY => PLAN_PRICE_PRO_MONTHLY,
|
||||||
|
PLAN_TERM_YEARLY => PLAN_PRICE_PRO_YEARLY,
|
||||||
|
),
|
||||||
|
PLAN_ENTERPRISE => array(
|
||||||
|
PLAN_TERM_MONTHLY => PLAN_PRICE_ENTERPRISE_MONTHLY,
|
||||||
|
PLAN_TERM_YEARLY => PLAN_PRICE_ENTERPRISE_YEARLY,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
protected $presenter = 'App\Ninja\Presenters\AccountPresenter';
|
protected $presenter = 'App\Ninja\Presenters\AccountPresenter';
|
||||||
protected $dates = ['deleted_at'];
|
protected $dates = ['deleted_at'];
|
||||||
@ -57,6 +68,7 @@ class Account extends Eloquent
|
|||||||
ACCOUNT_PRODUCTS,
|
ACCOUNT_PRODUCTS,
|
||||||
ACCOUNT_NOTIFICATIONS,
|
ACCOUNT_NOTIFICATIONS,
|
||||||
ACCOUNT_IMPORT_EXPORT,
|
ACCOUNT_IMPORT_EXPORT,
|
||||||
|
ACCOUNT_MANAGEMENT,
|
||||||
];
|
];
|
||||||
|
|
||||||
public static $advancedSettings = [
|
public static $advancedSettings = [
|
||||||
@ -176,6 +188,11 @@ class Account extends Eloquent
|
|||||||
return $this->hasMany('App\Models\Payment','account_id','id')->withTrashed();
|
return $this->hasMany('App\Models\Payment','account_id','id')->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function company()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('App\Models\Company');
|
||||||
|
}
|
||||||
|
|
||||||
public function setIndustryIdAttribute($value)
|
public function setIndustryIdAttribute($value)
|
||||||
{
|
{
|
||||||
$this->attributes['industry_id'] = $value ?: null;
|
$this->attributes['industry_id'] = $value ?: null;
|
||||||
@ -516,7 +533,7 @@ class Account extends Eloquent
|
|||||||
|
|
||||||
public function getNumberPrefix($isQuote)
|
public function getNumberPrefix($isQuote)
|
||||||
{
|
{
|
||||||
if ( ! $this->isPro()) {
|
if ( ! $this->hasFeature(FEATURE_INVOICE_SETTINGS)) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,7 +542,7 @@ class Account extends Eloquent
|
|||||||
|
|
||||||
public function hasNumberPattern($isQuote)
|
public function hasNumberPattern($isQuote)
|
||||||
{
|
{
|
||||||
if ( ! $this->isPro()) {
|
if ( ! $this->hasFeature(FEATURE_INVOICE_SETTINGS)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,7 +662,7 @@ class Account extends Eloquent
|
|||||||
$default = $this->invoice_number_counter;
|
$default = $this->invoice_number_counter;
|
||||||
$actual = Utils::parseInt($invoice->invoice_number);
|
$actual = Utils::parseInt($invoice->invoice_number);
|
||||||
|
|
||||||
if ( ! $this->isPro() && $default != $actual) {
|
if ( ! $this->hasFeature(FEATURE_INVOICE_SETTINGS) && $default != $actual) {
|
||||||
$this->invoice_number_counter = $actual + 1;
|
$this->invoice_number_counter = $actual + 1;
|
||||||
} else {
|
} else {
|
||||||
$this->invoice_number_counter += 1;
|
$this->invoice_number_counter += 1;
|
||||||
@ -766,17 +783,80 @@ class Account extends Eloquent
|
|||||||
return $this->account_key === NINJA_ACCOUNT_KEY;
|
return $this->account_key === NINJA_ACCOUNT_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function startTrial()
|
public function startTrial($plan)
|
||||||
{
|
{
|
||||||
if ( ! Utils::isNinja()) {
|
if ( ! Utils::isNinja()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->pro_plan_trial = date_create()->format('Y-m-d');
|
$this->company->trial_plan = $plan;
|
||||||
$this->save();
|
$this->company->trial_started = date_create()->format('Y-m-d');
|
||||||
|
$this->company->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isPro()
|
public function hasFeature($feature)
|
||||||
|
{
|
||||||
|
$planDetails = $this->getPlanDetails();
|
||||||
|
$selfHost = !Utils::isNinjaProd();
|
||||||
|
|
||||||
|
if (!$selfHost && function_exists('ninja_account_features')) {
|
||||||
|
$result = ninja_account_features($this, $feature);
|
||||||
|
|
||||||
|
if ($result != null) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($feature) {
|
||||||
|
// Pro
|
||||||
|
case FEATURE_CUSTOMIZE_INVOICE_DESIGN:
|
||||||
|
case FEATURE_REMOVE_CREATED_BY:
|
||||||
|
case FEATURE_DIFFERENT_DESIGNS:
|
||||||
|
case FEATURE_EMAIL_TEMPLATES_REMINDERS:
|
||||||
|
case FEATURE_INVOICE_SETTINGS:
|
||||||
|
case FEATURE_CUSTOM_EMAILS:
|
||||||
|
case FEATURE_PDF_ATTACHMENT:
|
||||||
|
case FEATURE_MORE_INVOICE_DESIGNS:
|
||||||
|
case FEATURE_QUOTES:
|
||||||
|
case FEATURE_REPORTS:
|
||||||
|
case FEATURE_API:
|
||||||
|
case FEATURE_CLIENT_PORTAL_PASSWORD:
|
||||||
|
case FEATURE_CUSTOM_URL:
|
||||||
|
return $selfHost || !empty($planDetails);
|
||||||
|
|
||||||
|
// Pro; No trial allowed, unless they're trialing enterprise with an active pro plan
|
||||||
|
case FEATURE_MORE_CLIENTS:
|
||||||
|
return $selfHost || !empty($planDetails) && (!$planDetails['trial'] || !empty($this->getPlanDetails(false, false)));
|
||||||
|
|
||||||
|
// White Label
|
||||||
|
case FEATURE_WHITE_LABEL:
|
||||||
|
if ($this->isNinjaAccount() || (!$selfHost && $planDetails && !$plan_details['expires'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Fallthrough
|
||||||
|
case FEATURE_CLIENT_PORTAL_CSS:
|
||||||
|
return !empty($planDetails);// A plan is required even for self-hosted users
|
||||||
|
|
||||||
|
// Enterprise; No Trial allowed; grandfathered for old pro users
|
||||||
|
case FEATURE_USERS:// Grandfathered for old Pro users
|
||||||
|
if($planDetails && $planDetails['trial']) {
|
||||||
|
// Do they have a non-trial plan?
|
||||||
|
$planDetails = $this->getPlanDetails(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $selfHost || !empty($planDetails) && ($planDetails['plan'] == PLAN_ENTERPRISE || $planDetails['started'] <= date_create(PRO_USERS_GRANDFATHER_DEADLINE));
|
||||||
|
|
||||||
|
// Enterprise; No Trial allowed
|
||||||
|
case FEATURE_DOCUMENTS:
|
||||||
|
case FEATURE_USER_PERMISSIONS:
|
||||||
|
return $selfHost || !empty($planDetails) && $planDetails['plan'] == PLAN_ENTERPRISE && !$planDetails['trial'];
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isPro(&$plan_details = null)
|
||||||
{
|
{
|
||||||
if (!Utils::isNinjaProd()) {
|
if (!Utils::isNinjaProd()) {
|
||||||
return true;
|
return true;
|
||||||
@ -786,14 +866,113 @@ class Account extends Eloquent
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$datePaid = $this->pro_plan_paid;
|
$plan_details = $this->getPlanDetails();
|
||||||
$trialStart = $this->pro_plan_trial;
|
|
||||||
|
return !empty($plan_details);
|
||||||
|
}
|
||||||
|
|
||||||
if ($datePaid == NINJA_DATE) {
|
public function isEnterprise(&$plan_details = null)
|
||||||
|
{
|
||||||
|
if (!Utils::isNinjaProd()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Utils::withinPastTwoWeeks($trialStart) || Utils::withinPastYear($datePaid);
|
if ($this->isNinjaAccount()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plan_details = $this->getPlanDetails();
|
||||||
|
|
||||||
|
return $plan_details && $plan_details['plan'] == PLAN_ENTERPRISE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPlanDetails($include_inactive = false, $include_trial = true)
|
||||||
|
{
|
||||||
|
if (!$this->company) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plan = $this->company->plan;
|
||||||
|
$trial_plan = $this->company->trial_plan;
|
||||||
|
|
||||||
|
if(!$plan && (!$trial_plan || !$include_trial)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$trial_active = false;
|
||||||
|
if ($trial_plan && $include_trial) {
|
||||||
|
$trial_started = DateTime::createFromFormat('Y-m-d', $this->company->trial_started);
|
||||||
|
$trial_expires = clone $trial_started;
|
||||||
|
$trial_expires->modify('+2 weeks');
|
||||||
|
|
||||||
|
if ($trial_expires >= date_create()) {
|
||||||
|
$trial_active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$plan_active = false;
|
||||||
|
if ($plan) {
|
||||||
|
if ($this->company->plan_expires == null) {
|
||||||
|
$plan_active = true;
|
||||||
|
$plan_expires = false;
|
||||||
|
} else {
|
||||||
|
$plan_expires = DateTime::createFromFormat('Y-m-d', $this->company->plan_expires);
|
||||||
|
if ($plan_expires >= date_create()) {
|
||||||
|
$plan_active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$include_inactive && !$plan_active && !$trial_active) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should we show plan details or trial details?
|
||||||
|
if (($plan && !$trial_plan) || !$include_trial) {
|
||||||
|
$use_plan = true;
|
||||||
|
} elseif (!$plan && $trial_plan) {
|
||||||
|
$use_plan = false;
|
||||||
|
} else {
|
||||||
|
// There is both a plan and a trial
|
||||||
|
if (!empty($plan_active) && empty($trial_active)) {
|
||||||
|
$use_plan = true;
|
||||||
|
} elseif (empty($plan_active) && !empty($trial_active)) {
|
||||||
|
$use_plan = false;
|
||||||
|
} elseif (!empty($plan_active) && !empty($trial_active)) {
|
||||||
|
// Both are active; use whichever is a better plan
|
||||||
|
if ($plan == PLAN_ENTERPRISE) {
|
||||||
|
$use_plan = true;
|
||||||
|
} elseif ($trial_plan == PLAN_ENTERPRISE) {
|
||||||
|
$use_plan = false;
|
||||||
|
} else {
|
||||||
|
// They're both the same; show the plan
|
||||||
|
$use_plan = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Neither are active; use whichever expired most recently
|
||||||
|
$use_plan = $plan_expires >= $trial_expires;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($use_plan) {
|
||||||
|
return array(
|
||||||
|
'trial' => false,
|
||||||
|
'plan' => $plan,
|
||||||
|
'started' => DateTime::createFromFormat('Y-m-d', $this->company->plan_started),
|
||||||
|
'expires' => $plan_expires,
|
||||||
|
'paid' => DateTime::createFromFormat('Y-m-d', $this->company->plan_paid),
|
||||||
|
'term' => $this->company->plan_term,
|
||||||
|
'active' => $plan_active,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return array(
|
||||||
|
'trial' => true,
|
||||||
|
'plan' => $trial_plan,
|
||||||
|
'started' => $trial_started,
|
||||||
|
'expires' => $trial_expires,
|
||||||
|
'active' => $trial_active,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isTrial()
|
public function isTrial()
|
||||||
@ -801,35 +980,54 @@ class Account extends Eloquent
|
|||||||
if (!Utils::isNinjaProd()) {
|
if (!Utils::isNinjaProd()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$plan_details = $this->getPlanDetails();
|
||||||
|
|
||||||
if ($this->pro_plan_paid && $this->pro_plan_paid != '0000-00-00') {
|
return $plan_details && $plan_details['trial'];
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Utils::withinPastTwoWeeks($this->pro_plan_trial);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isEligibleForTrial()
|
public function isEligibleForTrial($plan = null)
|
||||||
{
|
{
|
||||||
return ! $this->pro_plan_trial || $this->pro_plan_trial == '0000-00-00';
|
if (!$this->company->trial_plan) {
|
||||||
|
if ($plan) {
|
||||||
|
return $plan == PLAN_PRO || $plan == PLAN_ENTERPRISE;
|
||||||
|
} else {
|
||||||
|
return array(PLAN_PRO, PLAN_ENTERPRISE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->company->trial_plan == PLAN_PRO) {
|
||||||
|
if ($plan) {
|
||||||
|
return $plan != PLAN_PRO;
|
||||||
|
} else {
|
||||||
|
return array(PLAN_ENTERPRISE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCountTrialDaysLeft()
|
public function getCountTrialDaysLeft()
|
||||||
{
|
{
|
||||||
$interval = Utils::getInterval($this->pro_plan_trial);
|
$planDetails = $this->getPlanDetails(true);
|
||||||
|
|
||||||
return $interval ? 14 - $interval->d : 0;
|
if(!$planDetails || !$planDetails['trial']) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$today = new DateTime('now');
|
||||||
|
$interval = $today->diff($planDetails['expires']);
|
||||||
|
|
||||||
|
return $interval ? $interval->d : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRenewalDate()
|
public function getRenewalDate()
|
||||||
{
|
{
|
||||||
if ($this->pro_plan_paid && $this->pro_plan_paid != '0000-00-00') {
|
$planDetails = $this->getPlanDetails();
|
||||||
$date = DateTime::createFromFormat('Y-m-d', $this->pro_plan_paid);
|
|
||||||
$date->modify('+1 year');
|
if ($planDetails) {
|
||||||
|
$date = $planDetails['expires'];
|
||||||
$date = max($date, date_create());
|
$date = max($date, date_create());
|
||||||
} elseif ($this->isTrial()) {
|
|
||||||
$date = date_create();
|
|
||||||
$date->modify('+'.$this->getCountTrialDaysLeft().' day');
|
|
||||||
} else {
|
} else {
|
||||||
$date = date_create();
|
$date = date_create();
|
||||||
}
|
}
|
||||||
@ -837,23 +1035,6 @@ class Account extends Eloquent
|
|||||||
return $date->format('Y-m-d');
|
return $date->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isWhiteLabel()
|
|
||||||
{
|
|
||||||
if ($this->isNinjaAccount()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Utils::isNinjaProd()) {
|
|
||||||
return self::isPro() && $this->pro_plan_paid != NINJA_DATE;
|
|
||||||
} else {
|
|
||||||
if ($this->pro_plan_paid == NINJA_DATE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Utils::withinPastYear($this->pro_plan_paid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLogoSize()
|
public function getLogoSize()
|
||||||
{
|
{
|
||||||
if(!$this->hasLogo()){
|
if(!$this->hasLogo()){
|
||||||
@ -930,7 +1111,7 @@ class Account extends Eloquent
|
|||||||
|
|
||||||
public function getEmailSubject($entityType)
|
public function getEmailSubject($entityType)
|
||||||
{
|
{
|
||||||
if ($this->isPro()) {
|
if ($this->hasFeature(FEATURE_CUSTOM_EMAILS)) {
|
||||||
$field = "email_subject_{$entityType}";
|
$field = "email_subject_{$entityType}";
|
||||||
$value = $this->$field;
|
$value = $this->$field;
|
||||||
|
|
||||||
@ -950,7 +1131,7 @@ class Account extends Eloquent
|
|||||||
|
|
||||||
$template = "<div>\$client,</div><br>";
|
$template = "<div>\$client,</div><br>";
|
||||||
|
|
||||||
if ($this->isPro() && $this->email_design_id != EMAIL_DESIGN_PLAIN) {
|
if ($this->hasFeature(FEATURE_CUSTOM_EMAILS) && $this->email_design_id != EMAIL_DESIGN_PLAIN) {
|
||||||
$template .= "<div>" . trans("texts.{$entityType}_message_button", ['amount' => '$amount']) . "</div><br>" .
|
$template .= "<div>" . trans("texts.{$entityType}_message_button", ['amount' => '$amount']) . "</div><br>" .
|
||||||
"<div style=\"text-align: center;\">\$viewButton</div><br>";
|
"<div style=\"text-align: center;\">\$viewButton</div><br>";
|
||||||
} else {
|
} else {
|
||||||
@ -969,7 +1150,7 @@ class Account extends Eloquent
|
|||||||
{
|
{
|
||||||
$template = false;
|
$template = false;
|
||||||
|
|
||||||
if ($this->isPro()) {
|
if ($this->hasFeature(FEATURE_CUSTOM_EMAILS)) {
|
||||||
$field = "email_template_{$entityType}";
|
$field = "email_template_{$entityType}";
|
||||||
$template = $this->$field;
|
$template = $this->$field;
|
||||||
}
|
}
|
||||||
@ -1065,7 +1246,7 @@ class Account extends Eloquent
|
|||||||
|
|
||||||
public function showCustomField($field, $entity = false)
|
public function showCustomField($field, $entity = false)
|
||||||
{
|
{
|
||||||
if ($this->isPro()) {
|
if ($this->hasFeature(FEATURE_INVOICE_SETTINGS)) {
|
||||||
return $this->$field ? true : false;
|
return $this->$field ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1081,18 +1262,18 @@ class Account extends Eloquent
|
|||||||
|
|
||||||
public function attatchPDF()
|
public function attatchPDF()
|
||||||
{
|
{
|
||||||
return $this->isPro() && $this->pdf_email_attachment;
|
return $this->hasFeaure(FEATURE_PDF_ATTACHMENT) && $this->pdf_email_attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEmailDesignId()
|
public function getEmailDesignId()
|
||||||
{
|
{
|
||||||
return $this->isPro() ? $this->email_design_id : EMAIL_DESIGN_PLAIN;
|
return $this->hasFeature(FEATURE_CUSTOM_EMAILS) ? $this->email_design_id : EMAIL_DESIGN_PLAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clientViewCSS(){
|
public function clientViewCSS(){
|
||||||
$css = null;
|
$css = '';
|
||||||
|
|
||||||
if ($this->isPro()) {
|
if ($this->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN)) {
|
||||||
$bodyFont = $this->getBodyFontCss();
|
$bodyFont = $this->getBodyFontCss();
|
||||||
$headerFont = $this->getHeaderFontCss();
|
$headerFont = $this->getHeaderFontCss();
|
||||||
|
|
||||||
@ -1100,11 +1281,10 @@ class Account extends Eloquent
|
|||||||
if ($headerFont != $bodyFont) {
|
if ($headerFont != $bodyFont) {
|
||||||
$css .= 'h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{'.$headerFont.'}';
|
$css .= 'h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{'.$headerFont.'}';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ((Utils::isNinja() && $this->isPro()) || $this->isWhiteLabel()) {
|
if ($this->hasFeature(FEATURE_CLIENT_PORTAL_CSS)) {
|
||||||
// For self-hosted users, a white-label license is required for custom CSS
|
// For self-hosted users, a white-label license is required for custom CSS
|
||||||
$css .= $this->client_view_css;
|
$css .= $this->client_view_css;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $css;
|
return $css;
|
||||||
@ -1126,11 +1306,11 @@ class Account extends Eloquent
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getHeaderFontId() {
|
public function getHeaderFontId() {
|
||||||
return ($this->isPro() && $this->header_font_id) ? $this->header_font_id : DEFAULT_HEADER_FONT;
|
return ($this->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN) && $this->header_font_id) ? $this->header_font_id : DEFAULT_HEADER_FONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBodyFontId() {
|
public function getBodyFontId() {
|
||||||
return ($this->isPro() && $this->body_font_id) ? $this->body_font_id : DEFAULT_BODY_FONT;
|
return ($this->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN) && $this->body_font_id) ? $this->body_font_id : DEFAULT_BODY_FONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHeaderFontName(){
|
public function getHeaderFontName(){
|
||||||
|
@ -155,7 +155,7 @@ class Client extends EntityModel
|
|||||||
$contact->send_invoice = true;
|
$contact->send_invoice = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Utils::isPro() || $this->account->enable_portal_password){
|
if (Utils::hasFeature(FEATURE_CLIENT_PORTAL_PASSWORD) && $this->account->enable_portal_password){
|
||||||
if(!empty($data['password']) && $data['password']!='-%unchanged%-'){
|
if(!empty($data['password']) && $data['password']!='-%unchanged%-'){
|
||||||
$contact->password = bcrypt($data['password']);
|
$contact->password = bcrypt($data['password']);
|
||||||
} else if(empty($data['password'])){
|
} else if(empty($data['password'])){
|
||||||
|
21
app/Models/Company.php
Normal file
21
app/Models/Company.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php namespace App\Models;
|
||||||
|
|
||||||
|
use Eloquent;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
class Company extends Eloquent
|
||||||
|
{
|
||||||
|
use SoftDeletes;
|
||||||
|
|
||||||
|
protected $dates = ['deleted_at'];
|
||||||
|
|
||||||
|
public function accounts()
|
||||||
|
{
|
||||||
|
return $this->hasMany('App\Models\Account');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function payment()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('App\Models\Payment');
|
||||||
|
}
|
||||||
|
}
|
@ -40,7 +40,7 @@ class Invitation extends EntityModel
|
|||||||
$url = SITE_URL;
|
$url = SITE_URL;
|
||||||
$iframe_url = $this->account->iframe_url;
|
$iframe_url = $this->account->iframe_url;
|
||||||
|
|
||||||
if ($this->account->isPro()) {
|
if ($this->account->hasFeature(FEATURE_CUSTOM_URL)) {
|
||||||
if ($iframe_url && !$forceOnsite) {
|
if ($iframe_url && !$forceOnsite) {
|
||||||
return "{$iframe_url}?{$this->invitation_key}";
|
return "{$iframe_url}?{$this->invitation_key}";
|
||||||
} elseif ($this->account->subdomain) {
|
} elseif ($this->account->subdomain) {
|
||||||
|
@ -409,7 +409,7 @@ class Invoice extends EntityModel implements BalanceAffecting
|
|||||||
'invoice_design',
|
'invoice_design',
|
||||||
'invoice_design_id',
|
'invoice_design_id',
|
||||||
'invoice_fonts',
|
'invoice_fonts',
|
||||||
'is_pro',
|
'features',
|
||||||
'is_quote',
|
'is_quote',
|
||||||
'custom_value1',
|
'custom_value1',
|
||||||
'custom_value2',
|
'custom_value2',
|
||||||
|
@ -112,9 +112,14 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||||||
return $this->account->isPro();
|
return $this->account->isPro();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasFeature($feature)
|
||||||
|
{
|
||||||
|
return $this->account->hasFeature($feature);
|
||||||
|
}
|
||||||
|
|
||||||
public function isPaidPro()
|
public function isPaidPro()
|
||||||
{
|
{
|
||||||
return $this->isPro() && ! $this->isTrial();
|
return $this->isPro($accountDetails) && !$accountDetails['trial'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isTrial()
|
public function isTrial()
|
||||||
@ -122,14 +127,14 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||||||
return $this->account->isTrial();
|
return $this->account->isTrial();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isEligibleForTrial()
|
public function isEligibleForTrial($plan = null)
|
||||||
{
|
{
|
||||||
return $this->account->isEligibleForTrial();
|
return $this->account->isEligibleForTrial($plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function maxInvoiceDesignId()
|
public function maxInvoiceDesignId()
|
||||||
{
|
{
|
||||||
return $this->isPro() ? 11 : (Utils::isNinja() ? COUNT_FREE_DESIGNS : COUNT_FREE_DESIGNS_SELF_HOST);
|
return $this->hasFeature(FEATURE_MORE_INVOICE_DESIGNS) ? 11 : (Utils::isNinja() ? COUNT_FREE_DESIGNS : COUNT_FREE_DESIGNS_SELF_HOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDisplayName()
|
public function getDisplayName()
|
||||||
@ -173,7 +178,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||||||
|
|
||||||
public function getMaxNumClients()
|
public function getMaxNumClients()
|
||||||
{
|
{
|
||||||
if ($this->isPro() && ! $this->isTrial()) {
|
if ($this->hasFeature(FEATURE_MORE_CLIENTS)) {
|
||||||
return MAX_NUM_CLIENTS_PRO;
|
return MAX_NUM_CLIENTS_PRO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +191,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||||||
|
|
||||||
public function getMaxNumVendors()
|
public function getMaxNumVendors()
|
||||||
{
|
{
|
||||||
if ($this->isPro() && ! $this->isTrial()) {
|
if ($this->hasFeature(FEATURE_MORE_CLIENTS)) {
|
||||||
return MAX_NUM_VENDORS_PRO;
|
return MAX_NUM_VENDORS_PRO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ class ContactMailer extends Mailer
|
|||||||
'amount' => $invoice->getRequestedAmount()
|
'amount' => $invoice->getRequestedAmount()
|
||||||
];
|
];
|
||||||
|
|
||||||
if (empty($invitation->contact->password) && $account->isPro() && $account->enable_portal_password && $account->send_portal_password) {
|
if (empty($invitation->contact->password) && $account->hasFeature(FEATURE_CLIENT_PORTAL_PASSWORD) && $account->enable_portal_password && $account->send_portal_password) {
|
||||||
// The contact needs a password
|
// The contact needs a password
|
||||||
$variables['password'] = $password = $this->generatePassword();
|
$variables['password'] = $password = $this->generatePassword();
|
||||||
$invitation->contact->password = bcrypt($password);
|
$invitation->contact->password = bcrypt($password);
|
||||||
@ -291,7 +291,7 @@ class ContactMailer extends Mailer
|
|||||||
$passwordHTML = isset($data['password'])?'<p>'.trans('texts.password').': '.$data['password'].'<p>':false;
|
$passwordHTML = isset($data['password'])?'<p>'.trans('texts.password').': '.$data['password'].'<p>':false;
|
||||||
$documentsHTML = '';
|
$documentsHTML = '';
|
||||||
|
|
||||||
if($account->isPro() && $invoice->hasDocuments()){
|
if($account->hasFeature(FEATURE_DOCUMENTS) && $invoice->hasDocuments()){
|
||||||
$documentsHTML .= trans('texts.email_documents_header').'<ul>';
|
$documentsHTML .= trans('texts.email_documents_header').'<ul>';
|
||||||
foreach($invoice->documents as $document){
|
foreach($invoice->documents as $document){
|
||||||
$documentsHTML .= '<li><a href="'.HTML::entities($document->getClientUrl($invitation)).'">'.HTML::entities($document->name).'</a></li>';
|
$documentsHTML .= '<li><a href="'.HTML::entities($document->getClientUrl($invitation)).'">'.HTML::entities($document->name).'</a></li>';
|
||||||
|
@ -17,6 +17,7 @@ use App\Models\Client;
|
|||||||
use App\Models\Language;
|
use App\Models\Language;
|
||||||
use App\Models\Contact;
|
use App\Models\Contact;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
|
use App\Models\Company;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\UserAccount;
|
use App\Models\UserAccount;
|
||||||
use App\Models\AccountToken;
|
use App\Models\AccountToken;
|
||||||
@ -25,9 +26,13 @@ class AccountRepository
|
|||||||
{
|
{
|
||||||
public function create($firstName = '', $lastName = '', $email = '', $password = '')
|
public function create($firstName = '', $lastName = '', $email = '', $password = '')
|
||||||
{
|
{
|
||||||
|
$company = new Company();
|
||||||
|
$company->save();
|
||||||
|
|
||||||
$account = new Account();
|
$account = new Account();
|
||||||
$account->ip = Request::getClientIp();
|
$account->ip = Request::getClientIp();
|
||||||
$account->account_key = str_random(RANDOM_KEY_LENGTH);
|
$account->account_key = str_random(RANDOM_KEY_LENGTH);
|
||||||
|
$account->company_id = $company->id;
|
||||||
|
|
||||||
// Track referal code
|
// Track referal code
|
||||||
if ($referralCode = Session::get(SESSION_REFERRAL_CODE)) {
|
if ($referralCode = Session::get(SESSION_REFERRAL_CODE)) {
|
||||||
@ -205,21 +210,23 @@ class AccountRepository
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enableProPlan()
|
public function enablePlan($plan = PLAN_PRO, $term = PLAN_TERM_MONTHLY, $credit = 0, $pending_monthly = false)
|
||||||
{
|
{
|
||||||
if (Auth::user()->isPro() && ! Auth::user()->isTrial()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
$client = $this->getNinjaClient($account);
|
$client = $this->getNinjaClient($account);
|
||||||
$invitation = $this->createNinjaInvoice($client, $account);
|
$invitation = $this->createNinjaInvoice($client, $account, $plan, $term, $credit, $pending_monthly);
|
||||||
|
|
||||||
return $invitation;
|
return $invitation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createNinjaInvoice($client, $clientAccount)
|
public function createNinjaInvoice($client, $clientAccount, $plan = PLAN_PRO, $term = PLAN_TERM_MONTHLY, $credit = 0, $pending_monthly = false)
|
||||||
{
|
{
|
||||||
|
if ($credit < 0) {
|
||||||
|
$credit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plan_cost = Account::$plan_prices[$plan][$term];
|
||||||
|
|
||||||
$account = $this->getNinjaAccount();
|
$account = $this->getNinjaAccount();
|
||||||
$lastInvoice = Invoice::withTrashed()->whereAccountId($account->id)->orderBy('public_id', 'DESC')->first();
|
$lastInvoice = Invoice::withTrashed()->whereAccountId($account->id)->orderBy('public_id', 'DESC')->first();
|
||||||
$publicId = $lastInvoice ? ($lastInvoice->public_id + 1) : 1;
|
$publicId = $lastInvoice ? ($lastInvoice->public_id + 1) : 1;
|
||||||
@ -230,19 +237,39 @@ class AccountRepository
|
|||||||
$invoice->client_id = $client->id;
|
$invoice->client_id = $client->id;
|
||||||
$invoice->invoice_number = $account->getNextInvoiceNumber($invoice);
|
$invoice->invoice_number = $account->getNextInvoiceNumber($invoice);
|
||||||
$invoice->invoice_date = $clientAccount->getRenewalDate();
|
$invoice->invoice_date = $clientAccount->getRenewalDate();
|
||||||
$invoice->amount = PRO_PLAN_PRICE;
|
$invoice->amount = $invoice->balance = $plan_cost - $credit;
|
||||||
$invoice->balance = PRO_PLAN_PRICE;
|
|
||||||
$invoice->save();
|
$invoice->save();
|
||||||
|
|
||||||
$item = new InvoiceItem();
|
if ($credit) {
|
||||||
$item->account_id = $account->id;
|
$credit_item = InvoiceItem::createNew($invoice);
|
||||||
$item->user_id = $account->users()->first()->id;
|
$credit_item->qty = 1;
|
||||||
$item->public_id = $publicId;
|
$credit_item->cost = -$credit;
|
||||||
|
$credit_item->notes = trans('texts.plan_credit_description');
|
||||||
|
$credit_item->product_key = trans('texts.plan_credit_product');
|
||||||
|
$invoice->invoice_items()->save($credit_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = InvoiceItem::createNew($invoice);
|
||||||
$item->qty = 1;
|
$item->qty = 1;
|
||||||
$item->cost = PRO_PLAN_PRICE;
|
$item->cost = $plan_cost;
|
||||||
$item->notes = trans('texts.pro_plan_description');
|
$item->notes = trans("texts.{$plan}_plan_{$term}_description");
|
||||||
$item->product_key = trans('texts.pro_plan_product');
|
|
||||||
|
// Don't change this without updating the regex in PaymentService->createPayment()
|
||||||
|
$item->product_key = 'Plan - '.ucfirst($plan).' ('.ucfirst($term).')';
|
||||||
$invoice->invoice_items()->save($item);
|
$invoice->invoice_items()->save($item);
|
||||||
|
|
||||||
|
if ($pending_monthly) {
|
||||||
|
$term_end = $term == PLAN_MONTHLY ? date_create('+1 month') : date_create('+1 year');
|
||||||
|
$pending_monthly_item = InvoiceItem::createNew($invoice);
|
||||||
|
$item->qty = 1;
|
||||||
|
$pending_monthly_item->cost = 0;
|
||||||
|
$pending_monthly_item->notes = trans("texts.plan_pending_monthly", array('date', Utils::dateToString($term_end)));
|
||||||
|
|
||||||
|
// Don't change this without updating the text in PaymentService->createPayment()
|
||||||
|
$pending_monthly_item->product_key = 'Pending Monthly';
|
||||||
|
$invoice->invoice_items()->save($pending_monthly_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$invitation = new Invitation();
|
$invitation = new Invitation();
|
||||||
$invitation->account_id = $account->id;
|
$invitation->account_id = $account->id;
|
||||||
@ -355,7 +382,7 @@ class AccountRepository
|
|||||||
$user->last_name = $lastName;
|
$user->last_name = $lastName;
|
||||||
$user->registered = true;
|
$user->registered = true;
|
||||||
|
|
||||||
$user->account->startTrial();
|
$user->account->startTrial(PLAN_PRO);
|
||||||
}
|
}
|
||||||
|
|
||||||
$user->oauth_provider_id = $providerId;
|
$user->oauth_provider_id = $providerId;
|
||||||
@ -471,10 +498,10 @@ class AccountRepository
|
|||||||
$item = new stdClass();
|
$item = new stdClass();
|
||||||
$item->id = $record->id;
|
$item->id = $record->id;
|
||||||
$item->user_id = $user->id;
|
$item->user_id = $user->id;
|
||||||
|
$item->public_id = $user->public_id;
|
||||||
$item->user_name = $user->getDisplayName();
|
$item->user_name = $user->getDisplayName();
|
||||||
$item->account_id = $user->account->id;
|
$item->account_id = $user->account->id;
|
||||||
$item->account_name = $user->account->getDisplayName();
|
$item->account_name = $user->account->getDisplayName();
|
||||||
$item->pro_plan_paid = $user->account->pro_plan_paid;
|
|
||||||
$item->logo_url = $user->account->hasLogo() ? $user->account->getLogoUrl() : null;
|
$item->logo_url = $user->account->hasLogo() ? $user->account->getLogoUrl() : null;
|
||||||
$data[] = $item;
|
$data[] = $item;
|
||||||
}
|
}
|
||||||
@ -487,43 +514,6 @@ class AccountRepository
|
|||||||
return self::prepareUsersData($record);
|
return self::prepareUsersData($record);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function syncAccounts($userId, $proPlanPaid) {
|
|
||||||
$users = self::loadAccounts($userId);
|
|
||||||
self::syncUserAccounts($users, $proPlanPaid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function syncUserAccounts($users, $proPlanPaid = false) {
|
|
||||||
if (!$users) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
public function associateAccounts($userId1, $userId2) {
|
||||||
|
|
||||||
$record = self::findUserAccounts($userId1, $userId2);
|
$record = self::findUserAccounts($userId1, $userId2);
|
||||||
@ -542,8 +532,59 @@ class AccountRepository
|
|||||||
|
|
||||||
$record->save();
|
$record->save();
|
||||||
|
|
||||||
$users = self::prepareUsersData($record);
|
$users = $this->getUserAccounts($record);
|
||||||
self::syncUserAccounts($users);
|
|
||||||
|
// Pick the primary user
|
||||||
|
foreach ($users as $user) {
|
||||||
|
if (!$user->public_id) {
|
||||||
|
$useAsPrimary = false;
|
||||||
|
if(empty($primaryUser)) {
|
||||||
|
$useAsPrimary = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$planDetails = $user->account->getPlanDetails(false, false);
|
||||||
|
$planLevel = 0;
|
||||||
|
|
||||||
|
if ($planDetails) {
|
||||||
|
$planLevel = 1;
|
||||||
|
if ($planDetails['plan'] == PLAN_ENTERPRISE) {
|
||||||
|
$planLevel = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$useAsPrimary && (
|
||||||
|
$planLevel > $primaryUserPlanLevel
|
||||||
|
|| ($planLevel == $primaryUserPlanLevel && $planDetails['expires'] > $primaryUserPlanExpires)
|
||||||
|
)) {
|
||||||
|
$useAsPrimary = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($useAsPrimary) {
|
||||||
|
$primaryUser = $user;
|
||||||
|
$primaryUserPlanLevel = $planLevel;
|
||||||
|
if ($planDetails) {
|
||||||
|
$primaryUserPlanExpires = $planDetails['expires'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge other companies into the primary user's company
|
||||||
|
if (!empty($primaryUser)) {
|
||||||
|
foreach ($users as $user) {
|
||||||
|
if ($user == $primaryUser || $user->public_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->account->company_id != $primaryUser->account->company_id) {
|
||||||
|
foreach ($user->account->company->accounts as $account) {
|
||||||
|
$account->company_id = $primaryUser->account->company_id;
|
||||||
|
$account->save();
|
||||||
|
}
|
||||||
|
$user->account->company->forceDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $users;
|
return $users;
|
||||||
}
|
}
|
||||||
@ -563,6 +604,15 @@ class AccountRepository
|
|||||||
$userAccount->removeUserId($userId);
|
$userAccount->removeUserId($userId);
|
||||||
$userAccount->save();
|
$userAccount->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user = User::whereId($userId)->first();
|
||||||
|
|
||||||
|
if (!$user->public_id && $user->account->company->accounts->count() > 1) {
|
||||||
|
$company = Company::create();
|
||||||
|
$company->save();
|
||||||
|
$user->account->company_id = $company->id;
|
||||||
|
$user->account->save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findWithReminders()
|
public function findWithReminders()
|
||||||
|
@ -4,7 +4,7 @@ use App\Models\Account;
|
|||||||
|
|
||||||
class NinjaRepository
|
class NinjaRepository
|
||||||
{
|
{
|
||||||
public function updateProPlanPaid($clientPublicId, $proPlanPaid)
|
public function updatePlanDetails($clientPublicId, $data)
|
||||||
{
|
{
|
||||||
$account = Account::whereId($clientPublicId)->first();
|
$account = Account::whereId($clientPublicId)->first();
|
||||||
|
|
||||||
@ -12,7 +12,13 @@ class NinjaRepository
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$account->pro_plan_paid = $proPlanPaid;
|
$company = $account->company;
|
||||||
$account->save();
|
$company->plan = !empty($data['plan']) && $data['plan'] != PLAN_FREE?$data['plan']:null;
|
||||||
|
$company->plan_term = !empty($data['plan_term'])?$data['plan_term']:null;
|
||||||
|
$company->plan_paid = !empty($data['plan_paid'])?$data['plan_paid']:null;
|
||||||
|
$company->plan_started = !empty($data['plan_started'])?$data['plan_started']:null;
|
||||||
|
$company->plan_expires = !empty($data['plan_expires'])?$data['plan_expires']:null;
|
||||||
|
|
||||||
|
$company->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,32 @@
|
|||||||
<?php namespace App\Ninja\Repositories;
|
<?php namespace App\Ninja\Repositories;
|
||||||
|
|
||||||
use DB;
|
use App\Models\Account;
|
||||||
use Utils;
|
use Utils;
|
||||||
|
|
||||||
class ReferralRepository
|
class ReferralRepository
|
||||||
{
|
{
|
||||||
public function getCounts($userId)
|
public function getCounts($userId)
|
||||||
{
|
{
|
||||||
$accounts = DB::table('accounts')
|
$accounts = Account::where('referral_user_id', $userId);
|
||||||
->where('referral_user_id', $userId)
|
|
||||||
->get(['id', 'pro_plan_paid']);
|
|
||||||
|
|
||||||
$counts = [
|
$counts = [
|
||||||
'free' => 0,
|
'free' => 0,
|
||||||
'pro' => 0
|
'pro' => 0,
|
||||||
|
'enterprise' => 0
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$counts['free']++;
|
$counts['free']++;
|
||||||
if (Utils::withinPastYear($account->pro_plan_paid)) {
|
$plan = $account->getPlanDetails(false, false);
|
||||||
|
|
||||||
|
if ($plan) {
|
||||||
$counts['pro']++;
|
$counts['pro']++;
|
||||||
|
if ($plan['plan'] == PLAN_ENTERPRISE) {
|
||||||
|
$counts['enterprise']++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $counts;
|
return $counts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -68,7 +68,7 @@ class AppServiceProvider extends ServiceProvider {
|
|||||||
if(!empty($items))$items[] = '<li class="divider"></li>';
|
if(!empty($items))$items[] = '<li class="divider"></li>';
|
||||||
$items[] = '<li><a href="'.URL::to('recurring_invoices').'">'.trans("texts.recurring_invoices").'</a></li>';
|
$items[] = '<li><a href="'.URL::to('recurring_invoices').'">'.trans("texts.recurring_invoices").'</a></li>';
|
||||||
if(Invoice::canCreate())$items[] = '<li><a href="'.URL::to('recurring_invoices/create').'">'.trans("texts.new_recurring_invoice").'</a></li>';
|
if(Invoice::canCreate())$items[] = '<li><a href="'.URL::to('recurring_invoices/create').'">'.trans("texts.new_recurring_invoice").'</a></li>';
|
||||||
if (Auth::user()->isPro()) {
|
if (Auth::user()->hasFeature(FEATURE_QUOTES)) {
|
||||||
$items[] = '<li class="divider"></li>';
|
$items[] = '<li class="divider"></li>';
|
||||||
$items[] = '<li><a href="'.URL::to('quotes').'">'.trans("texts.quotes").'</a></li>';
|
$items[] = '<li><a href="'.URL::to('quotes').'">'.trans("texts.quotes").'</a></li>';
|
||||||
if(Invoice::canCreate())$items[] = '<li><a href="'.URL::to('quotes/create').'">'.trans("texts.new_quote").'</a></li>';
|
if(Invoice::canCreate())$items[] = '<li><a href="'.URL::to('quotes/create').'">'.trans("texts.new_quote").'</a></li>';
|
||||||
|
@ -32,8 +32,8 @@ class ClientService extends BaseService
|
|||||||
|
|
||||||
public function save($data)
|
public function save($data)
|
||||||
{
|
{
|
||||||
if (Auth::user()->account->isNinjaAccount() && isset($data['pro_plan_paid'])) {
|
if (Auth::user()->account->isNinjaAccount() && isset($data['plan'])) {
|
||||||
$this->ninjaRepo->updateProPlanPaid($data['public_id'], $data['pro_plan_paid']);
|
$this->ninjaRepo->updatePlanDetails($data['public_id'], $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->clientRepo->save($data);
|
return $this->clientRepo->save($data);
|
||||||
@ -134,7 +134,7 @@ class ClientService extends BaseService
|
|||||||
return URL::to("quotes/create/{$model->public_id}");
|
return URL::to("quotes/create/{$model->public_id}");
|
||||||
},
|
},
|
||||||
function ($model) {
|
function ($model) {
|
||||||
return Auth::user()->isPro() && Invoice::canCreate();
|
return Auth::user()->hasFeature(FEATURE_QUOTES) && Invoice::canCreate();
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
@ -100,7 +100,7 @@ class InvoiceService extends BaseService
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($account->auto_convert_quote || ! $account->isPro()) {
|
if ($account->auto_convert_quote || ! $account->hasFeature(FEATURE_QUOTES)) {
|
||||||
$invoice = $this->convertQuote($quote, $invitation);
|
$invoice = $this->convertQuote($quote, $invitation);
|
||||||
|
|
||||||
event(new QuoteInvitationWasApproved($quote, $invoice, $invitation));
|
event(new QuoteInvitationWasApproved($quote, $invoice, $invitation));
|
||||||
|
@ -216,17 +216,6 @@ class PaymentService extends BaseService
|
|||||||
{
|
{
|
||||||
$invoice = $invitation->invoice;
|
$invoice = $invitation->invoice;
|
||||||
|
|
||||||
// enable pro plan for hosted users
|
|
||||||
if ($invoice->account->account_key == NINJA_ACCOUNT_KEY && $invoice->amount == PRO_PLAN_PRICE) {
|
|
||||||
$account = Account::with('users')->find($invoice->client->public_id);
|
|
||||||
$account->pro_plan_paid = $account->getRenewalDate();
|
|
||||||
$account->save();
|
|
||||||
|
|
||||||
// sync pro accounts
|
|
||||||
$user = $account->users()->first();
|
|
||||||
$this->accountRepo->syncAccounts($user->id, $account->pro_plan_paid);
|
|
||||||
}
|
|
||||||
|
|
||||||
$payment = Payment::createNew($invitation);
|
$payment = Payment::createNew($invitation);
|
||||||
$payment->invitation_id = $invitation->id;
|
$payment->invitation_id = $invitation->id;
|
||||||
$payment->account_gateway_id = $accountGateway->id;
|
$payment->account_gateway_id = $accountGateway->id;
|
||||||
@ -236,13 +225,66 @@ class PaymentService extends BaseService
|
|||||||
$payment->contact_id = $invitation->contact_id;
|
$payment->contact_id = $invitation->contact_id;
|
||||||
$payment->transaction_reference = $ref;
|
$payment->transaction_reference = $ref;
|
||||||
$payment->payment_date = date_create()->format('Y-m-d');
|
$payment->payment_date = date_create()->format('Y-m-d');
|
||||||
|
|
||||||
if ($payerId) {
|
if ($payerId) {
|
||||||
$payment->payer_id = $payerId;
|
$payment->payer_id = $payerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
$payment->save();
|
$payment->save();
|
||||||
|
|
||||||
|
// enable pro plan for hosted users
|
||||||
|
if ($invoice->account->account_key == NINJA_ACCOUNT_KEY) {
|
||||||
|
foreach ($invoice->invoice_items as $invoice_item) {
|
||||||
|
// Hacky, but invoices don't have meta fields to allow us to store this easily
|
||||||
|
if (1 == preg_match('/^Plan - (.+) \((.+)\)$/', $invoice_item->product_key, $matches)) {
|
||||||
|
$plan = strtolower($matches[1]);
|
||||||
|
$term = strtolower($matches[2]);
|
||||||
|
} elseif ($invoice_item->product_key == 'Pending Monthly') {
|
||||||
|
$pending_monthly = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($plan)) {
|
||||||
|
$account = Account::with('users')->find($invoice->client->public_id);
|
||||||
|
|
||||||
|
if(
|
||||||
|
$account->company->plan != $plan
|
||||||
|
|| DateTime::createFromFormat('Y-m-d', $account->company->plan_expires) >= date_create('-7 days')
|
||||||
|
) {
|
||||||
|
// Either this is a different plan, or the subscription expired more than a week ago
|
||||||
|
// Reset any grandfathering
|
||||||
|
$account->company->plan_started = date_create()->format('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
$account->company->plan == $plan
|
||||||
|
&& $account->company->plan_term == $term
|
||||||
|
&& DateTime::createFromFormat('Y-m-d', $account->company->plan_expires) >= date_create()
|
||||||
|
) {
|
||||||
|
// This is a renewal; mark it paid as of when this term expires
|
||||||
|
$account->company->plan_paid = $account->company->plan_expires;
|
||||||
|
} else {
|
||||||
|
$account->company->plan_paid = date_create()->format('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
$account->company->payment_id = $payment->id;
|
||||||
|
$account->company->plan = $plan;
|
||||||
|
$account->company->plan_term = $term;
|
||||||
|
$account->company->plan_expires = DateTime::createFromFormat('Y-m-d', $account->company->plan_paid)
|
||||||
|
->modify($term == PLAN_TERM_MONTHLY ? '+1 month' : '+1 year')->format('Y-m-d');
|
||||||
|
|
||||||
|
if (!empty($pending_monthly)) {
|
||||||
|
$account->company->pending_plan = $plan;
|
||||||
|
$account->company->pending_term = PLAN_TERM_MONTHLY;
|
||||||
|
} else {
|
||||||
|
$account->company->pending_plan = null;
|
||||||
|
$account->company->pending_term = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$account->company->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $payment;
|
return $payment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ class VendorService extends BaseService
|
|||||||
|
|
||||||
public function save($data)
|
public function save($data)
|
||||||
{
|
{
|
||||||
if (Auth::user()->account->isNinjaAccount() && isset($data['pro_plan_paid'])) {
|
if (Auth::user()->account->isNinjaAccount() && isset($data['plan'])) {
|
||||||
$this->ninjaRepo->updateProPlanPaid($data['public_id'], $data['pro_plan_paid']);
|
$this->ninjaRepo->updatePlanDetails($data['public_id'], $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->vendorRepo->save($data);
|
return $this->vendorRepo->save($data);
|
||||||
|
@ -63,6 +63,7 @@ class AddDocuments extends Migration {
|
|||||||
$table->dropColumn('logo_height');
|
$table->dropColumn('logo_height');
|
||||||
$table->dropColumn('logo_size');
|
$table->dropColumn('logo_size');
|
||||||
$table->dropColumn('invoice_embed_documents');
|
$table->dropColumn('invoice_embed_documents');
|
||||||
|
$table->dropColumn('document_email_attachment');
|
||||||
});
|
});
|
||||||
|
|
||||||
Schema::dropIfExists('documents');
|
Schema::dropIfExists('documents');
|
||||||
|
156
database/migrations/2016_04_16_103943_enterprise_plan.php
Normal file
156
database/migrations/2016_04_16_103943_enterprise_plan.php
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\Account;
|
||||||
|
|
||||||
|
class EnterprisePlan extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up() {
|
||||||
|
|
||||||
|
Schema::create('companies', function($table)
|
||||||
|
{
|
||||||
|
$table->increments('id');
|
||||||
|
|
||||||
|
$table->enum('plan', array('pro', 'enterprise', 'white_label'))->nullable();
|
||||||
|
$table->enum('plan_term', array('month', 'year'))->nullable();
|
||||||
|
$table->date('plan_started')->nullable();
|
||||||
|
$table->date('plan_paid')->nullable();
|
||||||
|
$table->date('plan_expires')->nullable();
|
||||||
|
|
||||||
|
$table->unsignedInteger('payment_id')->nullable();
|
||||||
|
$table->foreign('payment_id')->references('id')->on('payments');
|
||||||
|
|
||||||
|
$table->date('trial_started')->nullable();
|
||||||
|
$table->enum('trial_plan', array('pro', 'enterprise'))->nullable();
|
||||||
|
|
||||||
|
$table->enum('pending_plan', array('pro', 'enterprise', 'free'))->nullable();
|
||||||
|
$table->enum('pending_term', array('month', 'year'))->nullable();
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('accounts', function($table)
|
||||||
|
{
|
||||||
|
$table->unsignedInteger('company_id')->nullable();
|
||||||
|
$table->foreign('company_id')->references('id')->on('companies');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$single_account_ids = \DB::table('users')
|
||||||
|
->leftJoin('user_accounts', function ($join) {
|
||||||
|
$join->on('user_accounts.user_id1', '=', 'users.id');
|
||||||
|
$join->orOn('user_accounts.user_id2', '=', 'users.id');
|
||||||
|
$join->orOn('user_accounts.user_id3', '=', 'users.id');
|
||||||
|
$join->orOn('user_accounts.user_id4', '=', 'users.id');
|
||||||
|
$join->orOn('user_accounts.user_id5', '=', 'users.id');
|
||||||
|
})
|
||||||
|
->whereNull('user_accounts.id')
|
||||||
|
->where(function ($query) {
|
||||||
|
$query->whereNull('users.public_id');
|
||||||
|
$query->orWhere('users.public_id', '=', 0);
|
||||||
|
})
|
||||||
|
->lists('users.account_id');
|
||||||
|
|
||||||
|
$group_accounts = \DB::select(
|
||||||
|
'SELECT u1.account_id as account1, u2.account_id as account2, u3.account_id as account3, u4.account_id as account4, u5.account_id as account5 FROM `user_accounts`
|
||||||
|
LEFT JOIN users u1 ON (u1.public_id IS NULL OR u1.public_id = 0) AND user_accounts.user_id1 = u1.id
|
||||||
|
LEFT JOIN users u2 ON (u2.public_id IS NULL OR u2.public_id = 0) AND user_accounts.user_id2 = u2.id
|
||||||
|
LEFT JOIN users u3 ON (u3.public_id IS NULL OR u3.public_id = 0) AND user_accounts.user_id3 = u3.id
|
||||||
|
LEFT JOIN users u4 ON (u4.public_id IS NULL OR u4.public_id = 0) AND user_accounts.user_id4 = u4.id
|
||||||
|
LEFT JOIN users u5 ON (u5.public_id IS NULL OR u5.public_id = 0) AND user_accounts.user_id5 = u5.id');
|
||||||
|
|
||||||
|
foreach (Account::find($single_account_ids) as $account) {
|
||||||
|
$this->upAccounts($account);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($group_accounts as $group_account) {
|
||||||
|
$this->upAccounts(null, Account::find(get_object_vars($group_account)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Schema::table('accounts', function($table)
|
||||||
|
{
|
||||||
|
$table->dropColumn('pro_plan_paid');
|
||||||
|
$table->dropColumn('pro_plan_trial');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private function upAccounts($primaryAccount, $otherAccounts = array()) {
|
||||||
|
if(!$primaryAccount) {
|
||||||
|
$primaryAccount = $otherAccounts->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
$company = Company::create();
|
||||||
|
if ($primaryAccount->pro_plan_paid && $primaryAccount->pro_plan_paid != '0000-00-00') {
|
||||||
|
$company->plan = 'pro';
|
||||||
|
$company->plan_term = 'year';
|
||||||
|
$company->plan_started = $primaryAccount->pro_plan_paid;
|
||||||
|
$company->plan_paid = $primaryAccount->pro_plan_paid;
|
||||||
|
|
||||||
|
if (!Utils::isNinjaProd()) {
|
||||||
|
$company->plan = 'white_label';
|
||||||
|
$company->plan_term = null;
|
||||||
|
} elseif ($company->plan_paid != '2000-01-01'/* NINJA_DATE*/) {
|
||||||
|
$expires = DateTime::createFromFormat('Y-m-d', $primaryAccount->pro_plan_paid);
|
||||||
|
$expires->modify('+1 year');
|
||||||
|
$company->plan_expires = $expires->format('Y-m-d');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($primaryAccount->pro_plan_trial && $primaryAccount->pro_plan_trial != '0000-00-00') {
|
||||||
|
$company->trial_started = $primaryAccount->pro_plan_trial;
|
||||||
|
$company->trial_plan = 'pro';
|
||||||
|
}
|
||||||
|
|
||||||
|
$company->save();
|
||||||
|
|
||||||
|
$primaryAccount->company_id = $company->id;
|
||||||
|
$primaryAccount->save();
|
||||||
|
|
||||||
|
if (!empty($otherAccounts)) {
|
||||||
|
foreach ($otherAccounts as $account) {
|
||||||
|
if ($account && $account->id != $primaryAccount->id) {
|
||||||
|
$account->company_id = $company->id;
|
||||||
|
$account->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('accounts', function($table)
|
||||||
|
{
|
||||||
|
$table->date('pro_plan_paid')->nullable();
|
||||||
|
$table->date('pro_plan_trial')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (Company::all() as $company) {
|
||||||
|
foreach ($company->accounts as $account) {
|
||||||
|
$account->pro_plan_paid = $company->plan_paid;
|
||||||
|
$account->pro_plan_trial = $company->trial_started;
|
||||||
|
$account->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Schema::table('accounts', function($table)
|
||||||
|
{
|
||||||
|
$table->dropForeign('accounts_company_id_foreign');
|
||||||
|
$table->dropColumn('company_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::dropIfExists('companies');
|
||||||
|
}
|
||||||
|
}
|
@ -13,10 +13,13 @@ class UserTableSeeder extends Seeder
|
|||||||
|
|
||||||
Eloquent::unguard();
|
Eloquent::unguard();
|
||||||
|
|
||||||
|
$company = Company::create();
|
||||||
|
|
||||||
$account = Account::create([
|
$account = Account::create([
|
||||||
//'name' => 'Test Account',
|
//'name' => 'Test Account',
|
||||||
'account_key' => str_random(RANDOM_KEY_LENGTH),
|
'account_key' => str_random(RANDOM_KEY_LENGTH),
|
||||||
'timezone_id' => 1,
|
'timezone_id' => 1,
|
||||||
|
'company_id' => $company,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
User::create([
|
User::create([
|
||||||
|
File diff suppressed because one or more lines are too long
@ -55,7 +55,7 @@ function GetPdfMake(invoice, javascript, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// determine whether or not to show the header/footer
|
// determine whether or not to show the header/footer
|
||||||
if (invoice.is_pro) {
|
if (invoice.features.customize_invoice_design) {
|
||||||
if (key === 'header') {
|
if (key === 'header') {
|
||||||
return function(page, pages) {
|
return function(page, pages) {
|
||||||
return page === 1 || invoice.account.all_pages_header == '1' ? val : '';
|
return page === 1 || invoice.account.all_pages_header == '1' ? val : '';
|
||||||
@ -86,7 +86,7 @@ function GetPdfMake(invoice, javascript, callback) {
|
|||||||
// Add ninja logo to the footer
|
// Add ninja logo to the footer
|
||||||
var dd = JSON.parse(javascript, jsonCallBack);
|
var dd = JSON.parse(javascript, jsonCallBack);
|
||||||
var designId = invoice.invoice_design_id;
|
var designId = invoice.invoice_design_id;
|
||||||
if (!invoice.is_pro) {
|
if (!invoice.features.remove_created_by) {
|
||||||
if (designId == NINJA.TEMPLATES.CLEAN || designId == NINJA.TEMPLATES.NORMAL) {
|
if (designId == NINJA.TEMPLATES.CLEAN || designId == NINJA.TEMPLATES.NORMAL) {
|
||||||
dd.footer.columns.push({image: logoImages.imageLogo1, alignment: 'right', width: 130, margin: [0, 0, 0, 0]})
|
dd.footer.columns.push({image: logoImages.imageLogo1, alignment: 'right', width: 130, margin: [0, 0, 0, 0]})
|
||||||
} else if (designId == NINJA.TEMPLATES.BOLD) {
|
} else if (designId == NINJA.TEMPLATES.BOLD) {
|
||||||
@ -270,10 +270,10 @@ NINJA.invoiceColumns = function(invoice)
|
|||||||
|
|
||||||
columns.push("*")
|
columns.push("*")
|
||||||
|
|
||||||
if (invoice.is_pro && account.custom_invoice_item_label1) {
|
if (invoice.features.invoice_settings && account.custom_invoice_item_label1) {
|
||||||
columns.push("10%");
|
columns.push("10%");
|
||||||
}
|
}
|
||||||
if (invoice.is_pro && account.custom_invoice_item_label2) {
|
if (invoice.features.invoice_settings && account.custom_invoice_item_label2) {
|
||||||
columns.push("10%");
|
columns.push("10%");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +293,7 @@ NINJA.invoiceColumns = function(invoice)
|
|||||||
|
|
||||||
NINJA.invoiceFooter = function(invoice)
|
NINJA.invoiceFooter = function(invoice)
|
||||||
{
|
{
|
||||||
if (!invoice.is_pro && invoice.invoice_design_id == 3) {
|
if (!invoice.features.invoice_settings && invoice.invoice_design_id == 3) {
|
||||||
return invoice.invoice_footer ? invoice.invoice_footer.substring(0, 200) : ' ';
|
return invoice.invoice_footer ? invoice.invoice_footer.substring(0, 200) : ' ';
|
||||||
} else {
|
} else {
|
||||||
return invoice.invoice_footer || ' ';
|
return invoice.invoice_footer || ' ';
|
||||||
@ -325,10 +325,10 @@ NINJA.invoiceLines = function(invoice) {
|
|||||||
|
|
||||||
grid[0].push({text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']});
|
grid[0].push({text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']});
|
||||||
|
|
||||||
if (invoice.is_pro && account.custom_invoice_item_label1) {
|
if (invoice.features.invoice_settings && account.custom_invoice_item_label1) {
|
||||||
grid[0].push({text: account.custom_invoice_item_label1, style: ['tableHeader', 'custom1TableHeader']});
|
grid[0].push({text: account.custom_invoice_item_label1, style: ['tableHeader', 'custom1TableHeader']});
|
||||||
}
|
}
|
||||||
if (invoice.is_pro && account.custom_invoice_item_label2) {
|
if (invoice.features.invoice_ettings && account.custom_invoice_item_label2) {
|
||||||
grid[0].push({text: account.custom_invoice_item_label2, style: ['tableHeader', 'custom2TableHeader']});
|
grid[0].push({text: account.custom_invoice_item_label2, style: ['tableHeader', 'custom2TableHeader']});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,10 +385,10 @@ NINJA.invoiceLines = function(invoice) {
|
|||||||
row.push({style:["productKey", rowStyle], text:productKey || ' '}); // product key can be blank when selecting from a datalist
|
row.push({style:["productKey", rowStyle], text:productKey || ' '}); // product key can be blank when selecting from a datalist
|
||||||
}
|
}
|
||||||
row.push({style:["notes", rowStyle], stack:[{text:notes || ' '}]});
|
row.push({style:["notes", rowStyle], stack:[{text:notes || ' '}]});
|
||||||
if (invoice.is_pro && account.custom_invoice_item_label1) {
|
if (invoice.features.invoice_settings && account.custom_invoice_item_label1) {
|
||||||
row.push({style:["customValue1", rowStyle], text:item.custom_value1 || ' '});
|
row.push({style:["customValue1", rowStyle], text:item.custom_value1 || ' '});
|
||||||
}
|
}
|
||||||
if (invoice.is_pro && account.custom_invoice_item_label2) {
|
if (invoice.features.invoice_settings && account.custom_invoice_item_label2) {
|
||||||
row.push({style:["customValue2", rowStyle], text:item.custom_value2 || ' '});
|
row.push({style:["customValue2", rowStyle], text:item.custom_value2 || ' '});
|
||||||
}
|
}
|
||||||
row.push({style:["cost", rowStyle], text:cost});
|
row.push({style:["cost", rowStyle], text:cost});
|
||||||
@ -555,7 +555,7 @@ NINJA.accountAddress = function(invoice) {
|
|||||||
{text: account.country ? account.country.name : ''},
|
{text: account.country ? account.country.name : ''},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (invoice.is_pro) {
|
if (invoice.features.invoice_settings) {
|
||||||
data.push({text: invoice.account.custom_value1 ? invoice.account.custom_label1 + ' ' + invoice.account.custom_value1 : false});
|
data.push({text: invoice.account.custom_value1 ? invoice.account.custom_label1 + ' ' + invoice.account.custom_value1 : false});
|
||||||
data.push({text: invoice.account.custom_value2 ? invoice.account.custom_label2 + ' ' + invoice.account.custom_value2 : false});
|
data.push({text: invoice.account.custom_value2 ? invoice.account.custom_label2 + ' ' + invoice.account.custom_value2 : false});
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ $LANG = array(
|
|||||||
'company_details' => 'Company Details',
|
'company_details' => 'Company Details',
|
||||||
'online_payments' => 'Online Payments',
|
'online_payments' => 'Online Payments',
|
||||||
'notifications' => 'Email Notifications',
|
'notifications' => 'Email Notifications',
|
||||||
'import_export' => 'Import | Export | Cancel',
|
'import_export' => 'Import | Export',
|
||||||
'done' => 'Done',
|
'done' => 'Done',
|
||||||
'save' => 'Save',
|
'save' => 'Save',
|
||||||
'create' => 'Create',
|
'create' => 'Create',
|
||||||
@ -268,7 +268,6 @@ $LANG = array(
|
|||||||
'erase_data' => 'This will permanently erase your data.',
|
'erase_data' => 'This will permanently erase your data.',
|
||||||
'password' => 'Password',
|
'password' => 'Password',
|
||||||
'pro_plan_product' => 'Pro Plan',
|
'pro_plan_product' => 'Pro Plan',
|
||||||
'pro_plan_description' => 'One year enrollment in the Invoice Ninja Pro Plan.',
|
|
||||||
'pro_plan_success' => 'Thanks for choosing Invoice Ninja\'s Pro plan!<p/> <br/>
|
'pro_plan_success' => 'Thanks for choosing Invoice Ninja\'s Pro plan!<p/> <br/>
|
||||||
<b>Next Steps</b><p/>A payable invoice has been sent to the email
|
<b>Next Steps</b><p/>A payable invoice has been sent to the email
|
||||||
address associated with your account. To unlock all of the awesome
|
address associated with your account. To unlock all of the awesome
|
||||||
@ -368,7 +367,7 @@ $LANG = array(
|
|||||||
'confirm_email_invoice' => 'Are you sure you want to email this invoice?',
|
'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_email_quote' => 'Are you sure you want to email this quote?',
|
||||||
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
|
'confirm_recurring_email_invoice' => 'Are you sure you want this invoice emailed?',
|
||||||
'cancel_account' => 'Cancel Account',
|
'cancel_account' => 'Delete Account',
|
||||||
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
|
'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.',
|
||||||
'go_back' => 'Go Back',
|
'go_back' => 'Go Back',
|
||||||
'data_visualizations' => 'Data Visualizations',
|
'data_visualizations' => 'Data Visualizations',
|
||||||
@ -1126,12 +1125,58 @@ $LANG = array(
|
|||||||
'enable_client_portal_help' => 'Show/hide the client portal.',
|
'enable_client_portal_help' => 'Show/hide the client portal.',
|
||||||
'enable_client_portal_dashboard' => 'Dashboard',
|
'enable_client_portal_dashboard' => 'Dashboard',
|
||||||
'enable_client_portal_dashboard_help' => 'Show/hide the dashboard page in the client portal.',
|
'enable_client_portal_dashboard_help' => 'Show/hide the dashboard page in the client portal.',
|
||||||
|
|
||||||
|
// Plans
|
||||||
|
'account_management' => 'Account Management',
|
||||||
|
'plan_status' => 'Plan Status',
|
||||||
|
|
||||||
|
'plan_upgrade' => 'Upgrade',
|
||||||
|
'plan_change' => 'Change Plan',
|
||||||
|
'pending_change_to' => 'Changes To',
|
||||||
|
'plan_changes_to' => ':plan on :date',
|
||||||
|
'plan_term_changes_to' => ':plan (:term) on :date',
|
||||||
|
'cancel_plan_change' => 'Cancel Change',
|
||||||
|
'plan' => 'Plan',
|
||||||
|
'expires' => 'Expires',
|
||||||
|
'renews' => 'Renews',
|
||||||
|
'plan_expired' => ':plan Plan Expired',
|
||||||
|
'trial_expired' => ':plan Plan Trial Ended',
|
||||||
|
'never' => 'Never',
|
||||||
|
'plan_free' => 'Free',
|
||||||
|
'plan_pro' => 'Pro',
|
||||||
|
'plan_enterprise' => 'Enterprise',
|
||||||
|
'plan_white_label' => 'Self Hosted (White labeled)',
|
||||||
|
'plan_free_self_hosted' => 'Self Hosted (Free)',
|
||||||
|
'plan_trial' => 'Trial',
|
||||||
|
'plan_term' => 'Term',
|
||||||
|
'plan_term_monthly' => 'Monthly',
|
||||||
|
'plan_term_yearly' => 'Yearly',
|
||||||
|
'plan_term_month' => 'Month',
|
||||||
|
'plan_term_year' => 'Year',
|
||||||
|
'plan_price_monthly' => '$:price/Month',
|
||||||
|
'plan_price_yearly' => '$:price/Year',
|
||||||
|
'updated_plan' => 'Updated plan settings',
|
||||||
|
'plan_paid' => 'Term Started',
|
||||||
|
'plan_started' => 'Plan Started',
|
||||||
|
'plan_expires' => 'Plan Expires',
|
||||||
|
|
||||||
|
'white_label_button' => 'White Label',
|
||||||
|
|
||||||
|
'pro_plan_year_description' => 'One year enrollment in the Invoice Ninja Pro Plan.',
|
||||||
|
'pro_plan_month_description' => 'One month enrollment in the Invoice Ninja Pro Plan.',
|
||||||
|
'enterprise_plan_product' => 'Enterprise Plan',
|
||||||
|
'enterprise_plan_year_description' => 'One year enrollment in the Invoice Ninja Enterprise Plan.',
|
||||||
|
'enterprise_plan_month_description' => 'One month enrollment in the Invoice Ninja Enterprise Plan.',
|
||||||
|
'plan_credit_product' => 'Credit',
|
||||||
|
'plan_credit_description' => 'Credit for unused time',
|
||||||
|
'plan_pending_monthly' => 'Will switch to monthly on :date',
|
||||||
|
'plan_refunded' => 'A refund has been issued.',
|
||||||
|
|
||||||
'live_preview' => 'Live Preview',
|
'live_preview' => 'Live Preview',
|
||||||
'page_size' => 'Page Size',
|
'page_size' => 'Page Size',
|
||||||
'live_preview_disabled' => 'Live preview has been disabled to support selected font',
|
'live_preview_disabled' => 'Live preview has been disabled to support selected font',
|
||||||
'invoice_number_padding' => 'Padding',
|
'invoice_number_padding' => 'Padding',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return $LANG;
|
return $LANG;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
@if (Utils::isNinja())
|
@if (Utils::isNinja())
|
||||||
{!! Button::normal(trans('texts.zapier'))->asLinkTo(ZAPIER_URL)->withAttributes(['target' => '_blank']) !!}
|
{!! Button::normal(trans('texts.zapier'))->asLinkTo(ZAPIER_URL)->withAttributes(['target' => '_blank']) !!}
|
||||||
@endif
|
@endif
|
||||||
@if (Utils::isPro())
|
@if (Utils::hasFeature(FEATURE_API))
|
||||||
{!! Button::primary(trans('texts.add_token'))->asLinkTo(URL::to('/tokens/create'))->appendIcon(Icon::create('plus-sign')) !!}
|
{!! Button::primary(trans('texts.add_token'))->asLinkTo(URL::to('/tokens/create'))->appendIcon(Icon::create('plus-sign')) !!}
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
{!! Former::populateField('enable_portal_password', intval($enable_portal_password)) !!}
|
{!! Former::populateField('enable_portal_password', intval($enable_portal_password)) !!}
|
||||||
{!! Former::populateField('send_portal_password', intval($send_portal_password)) !!}
|
{!! Former::populateField('send_portal_password', intval($send_portal_password)) !!}
|
||||||
|
|
||||||
@if (!Utils::isNinja() && !Auth::user()->account->isWhiteLabel())
|
@if (!Utils::isNinja() && !Auth::user()->account->hasFeature(FEATURE_WHITE_LABEL))
|
||||||
<div class="alert alert-warning" style="font-size:larger;">
|
<div class="alert alert-warning" style="font-size:larger;">
|
||||||
<center>
|
<center>
|
||||||
{!! trans('texts.white_label_custom_css', ['link'=>'<a href="#" onclick="$(\'#whiteLabelModal\').modal(\'show\');">'.trans('texts.white_label_purchase_link').'</a>']) !!}
|
{!! trans('texts.white_label_custom_css', ['link'=>'<a href="#" onclick="$(\'#whiteLabelModal\').modal(\'show\');">'.trans('texts.white_label_purchase_link').'</a>']) !!}
|
||||||
@ -59,6 +59,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@if (Utils::hasFeature(FEATURE_CLIENT_PORTAL_CSS))
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h3 class="panel-title">{!! trans('texts.custom_css') !!}</h3>
|
<h3 class="panel-title">{!! trans('texts.custom_css') !!}</h3>
|
||||||
@ -74,6 +75,7 @@
|
|||||||
->style("min-width:100%;max-width:100%;font-family:'Roboto Mono', 'Lucida Console', Monaco, monospace;font-size:14px;'") !!}
|
->style("min-width:100%;max-width:100%;font-family:'Roboto Mono', 'Lucida Console', Monaco, monospace;font-size:14px;'") !!}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,7 +45,11 @@
|
|||||||
var customDesign = origCustomDesign = {!! $customDesign ?: 'JSON.parse(invoiceDesigns[0].javascript);' !!};
|
var customDesign = origCustomDesign = {!! $customDesign ?: 'JSON.parse(invoiceDesigns[0].javascript);' !!};
|
||||||
|
|
||||||
function getPDFString(cb, force) {
|
function getPDFString(cb, force) {
|
||||||
invoice.is_pro = {!! Auth::user()->isPro() ? 'true' : 'false' !!};
|
invoice.features = {
|
||||||
|
customize_invoice_design:{{ Auth::user()->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN) ? 'true' : 'false' }},
|
||||||
|
remove_created_by:{{ Auth::user()->hasFeature(FEATURE_REMOVE_CREATED_BY) ? 'true' : 'false' }},
|
||||||
|
invoice_settings:{{ Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS) ? 'true' : 'false' }}
|
||||||
|
};
|
||||||
invoice.account.hide_quantity = {!! Auth::user()->account->hide_quantity ? 'true' : 'false' !!};
|
invoice.account.hide_quantity = {!! Auth::user()->account->hide_quantity ? 'true' : 'false' !!};
|
||||||
invoice.account.hide_paid_to_date = {!! Auth::user()->account->hide_paid_to_date ? 'true' : 'false' !!};
|
invoice.account.hide_paid_to_date = {!! Auth::user()->account->hide_paid_to_date ? 'true' : 'false' !!};
|
||||||
invoice.invoice_design_id = {!! Auth::user()->account->invoice_design_id !!};
|
invoice.invoice_design_id = {!! Auth::user()->account->invoice_design_id !!};
|
||||||
@ -194,7 +198,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@if (!Auth::user()->isPro())
|
@if (!Auth::user()->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN))
|
||||||
$(function() {
|
$(function() {
|
||||||
$('form.warn-on-exit input, .save-button').prop('disabled', true);
|
$('form.warn-on-exit input, .save-button').prop('disabled', true);
|
||||||
});
|
});
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (Auth::user()->isPro())
|
@if (Auth::user()->hasFeature(FEATURE_CUSTOM_EMAILS))
|
||||||
<center>
|
<center>
|
||||||
{!! Button::success(trans('texts.save'))->large()->submit()->appendIcon(Icon::create('floppy-disk')) !!}
|
{!! Button::success(trans('texts.save'))->large()->submit()->appendIcon(Icon::create('floppy-disk')) !!}
|
||||||
</center>
|
</center>
|
||||||
|
@ -73,51 +73,7 @@
|
|||||||
{!! Former::close() !!}
|
{!! Former::close() !!}
|
||||||
|
|
||||||
|
|
||||||
{!! Former::open('settings/cancel_account')->addClass('cancel-account') !!}
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<h3 class="panel-title">{!! trans('texts.cancel_account') !!}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
{!! Former::actions( Button::danger(trans('texts.cancel_account'))->large()->withAttributes(['onclick' => 'showConfirm()'])->appendIcon(Icon::create('trash'))) !!}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<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">×</button>
|
|
||||||
<h4 class="modal-title" id="confirmCancelModalLabel">{!! trans('texts.cancel_account') !!}</h4>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="background-color: #fff; padding-left: 16px; padding-right: 16px">
|
|
||||||
<p>{{ trans('texts.cancel_account_message') }}</p>
|
|
||||||
<p>{!! Former::textarea('reason')->placeholder(trans('texts.reason_for_canceling'))->raw() !!}</p>
|
|
||||||
</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-danger" onclick="confirmCancel()">{{ trans('texts.cancel_account') }}</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{!! Former::close() !!}
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
function showConfirm() {
|
|
||||||
$('#confirmCancelModal').modal('show');
|
|
||||||
}
|
|
||||||
|
|
||||||
function confirmCancel() {
|
|
||||||
$('form.cancel-account').submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setEntityTypesVisible() {
|
function setEntityTypesVisible() {
|
||||||
var selector = '.entity-types input[type=checkbox]';
|
var selector = '.entity-types input[type=checkbox]';
|
||||||
if ($('#format').val() === 'JSON') {
|
if ($('#format').val() === 'JSON') {
|
||||||
|
@ -46,7 +46,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getPDFString(cb) {
|
function getPDFString(cb) {
|
||||||
invoice.is_pro = {!! Auth::user()->isPro() ? 'true' : 'false' !!};
|
invoice.features = {
|
||||||
|
customize_invoice_design:{{ Auth::user()->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN) ? 'true' : 'false' }},
|
||||||
|
remove_created_by:{{ Auth::user()->hasFeature(FEATURE_REMOVE_CREATED_BY) ? 'true' : 'false' }},
|
||||||
|
invoice_settings:{{ Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS) ? 'true' : 'false' }}
|
||||||
|
};
|
||||||
invoice.account.hide_quantity = $('#hide_quantity').is(":checked");
|
invoice.account.hide_quantity = $('#hide_quantity').is(":checked");
|
||||||
invoice.account.invoice_embed_documents = $('#invoice_embed_documents').is(":checked");
|
invoice.account.invoice_embed_documents = $('#invoice_embed_documents').is(":checked");
|
||||||
invoice.account.hide_paid_to_date = $('#hide_paid_to_date').is(":checked");
|
invoice.account.hide_paid_to_date = $('#hide_paid_to_date').is(":checked");
|
||||||
@ -87,7 +91,7 @@
|
|||||||
$(function() {
|
$(function() {
|
||||||
var options = {
|
var options = {
|
||||||
preferredFormat: 'hex',
|
preferredFormat: 'hex',
|
||||||
disabled: {!! Auth::user()->isPro() ? 'false' : 'true' !!},
|
disabled: {!! Auth::user()->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN) ? 'false' : 'true' !!},
|
||||||
showInitial: false,
|
showInitial: false,
|
||||||
showInput: true,
|
showInput: true,
|
||||||
allowEmpty: true,
|
allowEmpty: true,
|
||||||
@ -150,7 +154,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
|
||||||
@if (!Utils::isPro() || \App\Models\InvoiceDesign::count() == COUNT_FREE_DESIGNS_SELF_HOST)
|
@if (!Utils::hasFeature(FEATURE_MORE_INVOICE_DESIGNS) || \App\Models\InvoiceDesign::count() == COUNT_FREE_DESIGNS_SELF_HOST)
|
||||||
{!! Former::select('invoice_design_id')
|
{!! Former::select('invoice_design_id')
|
||||||
->fromQuery($invoiceDesigns, 'name', 'id')
|
->fromQuery($invoiceDesigns, 'name', 'id')
|
||||||
->addOption(trans('texts.more_designs') . '...', '-1') !!}
|
->addOption(trans('texts.more_designs') . '...', '-1') !!}
|
||||||
@ -261,7 +265,7 @@
|
|||||||
) !!}
|
) !!}
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
@if (!Auth::user()->isPro())
|
@if (!Auth::user()->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN))
|
||||||
<script>
|
<script>
|
||||||
$(function() {
|
$(function() {
|
||||||
$('form.warn-on-exit input, .save-button').prop('disabled', true);
|
$('form.warn-on-exit input, .save-button').prop('disabled', true);
|
||||||
|
@ -265,7 +265,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@if (Auth::user()->isPro())
|
@if (Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS))
|
||||||
<center>
|
<center>
|
||||||
{!! Button::success(trans('texts.save'))->large()->submit()->appendIcon(Icon::create('floppy-disk')) !!}
|
{!! Button::success(trans('texts.save'))->large()->submit()->appendIcon(Icon::create('floppy-disk')) !!}
|
||||||
</center>
|
</center>
|
||||||
|
225
resources/views/accounts/management.blade.php
Normal file
225
resources/views/accounts/management.blade.php
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
@extends('header')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
@parent
|
||||||
|
|
||||||
|
@include('accounts.nav', ['selected' => ACCOUNT_MANAGEMENT])
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
{!! Former::open('settings/change_plan')->addClass('change-plan') !!}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">{!! trans('texts.plan_status') !!}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">{{ trans('texts.plan') }}</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<p class="form-control-static">
|
||||||
|
@if ($planDetails && $planDetails['active'])
|
||||||
|
{{ trans('texts.plan_'.$planDetails['plan']) }}
|
||||||
|
@if ($planDetails['trial'])
|
||||||
|
({{ trans('texts.plan_trial') }})
|
||||||
|
@elseif ($planDetails['expires'])
|
||||||
|
({{ trans('texts.plan_term_'.$planDetails['term'].'ly') }})
|
||||||
|
@endif
|
||||||
|
@elseif(Utils::isNinjaProd())
|
||||||
|
{{ trans('texts.plan_free') }}
|
||||||
|
@else
|
||||||
|
{{ trans('texts.plan_free_self_hosted') }}
|
||||||
|
@endif
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if ($planDetails && $planDetails['active'])
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">
|
||||||
|
@if((!$account->company->pending_plan || $account->company->pending_plan == $planDetails['plan']) && $planDetails['expires'] && !$planDetails['trial'])
|
||||||
|
{{ trans('texts.renews') }}
|
||||||
|
@else
|
||||||
|
{{ trans('texts.expires') }}
|
||||||
|
@endif
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<p class="form-control-static">
|
||||||
|
@if ($planDetails['expires'] === false)
|
||||||
|
{{ trans('texts.never') }}
|
||||||
|
@else
|
||||||
|
{{ Utils::dateToString($planDetails['expires']) }}
|
||||||
|
@endif
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if ($account->company->pending_plan)
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">{{ trans('texts.pending_change_to') }}</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<p class="form-control-static">
|
||||||
|
@if ($account->company->pending_plan == PLAN_FREE)
|
||||||
|
{{ trans('texts.plan_changes_to', [
|
||||||
|
'plan'=>trans('texts.plan_free'),
|
||||||
|
'date'=>Utils::dateToString($planDetails['expires'])
|
||||||
|
]) }}
|
||||||
|
@else
|
||||||
|
{{ trans('texts.plan_term_changes_to', [
|
||||||
|
'plan'=>trans('texts.plan_'.$account->company->pending_plan),
|
||||||
|
'term'=>trans('texts.plan_term_'.$account->company->pending_term.'ly'),
|
||||||
|
'date'=>Utils::dateToString($planDetails['expires'])
|
||||||
|
]) }}
|
||||||
|
@endif<br>
|
||||||
|
<a href="#" onclick="cancelPendingChange()">{{ trans('texts.cancel_plan_change') }}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@if (Utils::isNinjaProd())
|
||||||
|
{!! Former::actions( Button::info(trans('texts.plan_change'))->large()->withAttributes(['onclick' => 'showChangePlan()'])->appendIcon(Icon::create('edit'))) !!}
|
||||||
|
@endif
|
||||||
|
@else
|
||||||
|
@if ($planDetails)
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">
|
||||||
|
@if ($planDetails['trial'])
|
||||||
|
{{ trans('texts.trial_expired', ['plan'=>trans('texts.plan_'.$planDetails['plan'])]) }}
|
||||||
|
@else
|
||||||
|
{{ trans('texts.plan_expired', ['plan'=>trans('texts.plan_'.$planDetails['plan'])]) }}
|
||||||
|
@endif
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<p class="form-control-static">
|
||||||
|
{{ Utils::dateToString($planDetails['expires']) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@if (Utils::isNinjaProd())
|
||||||
|
{!! Former::actions( Button::success(trans('texts.plan_upgrade'))->large()->withAttributes(['onclick' => 'showChangePlan()'])->appendIcon(Icon::create('plus-sign'))) !!}
|
||||||
|
@else
|
||||||
|
{!! Former::actions( Button::success(trans('texts.white_label_button'))->large()->withAttributes(['onclick' => 'loadImages("#whiteLabelModal");$("#whiteLabelModal").modal("show");'])->appendIcon(Icon::create('plus-sign'))) !!}
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if (Utils::isNinjaProd())
|
||||||
|
<div class="modal fade" id="changePlanModel" tabindex="-1" role="dialog" aria-labelledby="changePlanModelLabel" 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">×</button>
|
||||||
|
<h4 class="modal-title" id="changePlanModelLabel">
|
||||||
|
@if ($planDetails && $planDetails['active'])
|
||||||
|
{!! trans('texts.plan_change') !!}
|
||||||
|
@else
|
||||||
|
{!! trans('texts.plan_upgrade') !!}
|
||||||
|
@endif
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
@if ($planDetails && $planDetails['active'])
|
||||||
|
{!! Former::select('plan')
|
||||||
|
->addOption(trans('texts.plan_enterprise'), PLAN_ENTERPRISE)
|
||||||
|
->addOption(trans('texts.plan_pro'), PLAN_PRO)
|
||||||
|
->addOption(trans('texts.plan_free'), PLAN_FREE)!!}
|
||||||
|
@else
|
||||||
|
{!! Former::select('plan')
|
||||||
|
->addOption(trans('texts.plan_enterprise'), PLAN_ENTERPRISE)
|
||||||
|
->addOption(trans('texts.plan_pro'), PLAN_PRO)!!}
|
||||||
|
@endif
|
||||||
|
{!! Former::select('plan_term')
|
||||||
|
->addOption(trans('texts.plan_term_yearly'), PLAN_TERM_YEARLY)
|
||||||
|
->addOption(trans('texts.plan_term_monthly'), PLAN_TERM_MONTHLY)!!}
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer" style="margin-top: 0px">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('texts.go_back') }}</button>
|
||||||
|
@if ($planDetails && $planDetails['active'])
|
||||||
|
<button type="button" class="btn btn-primary" onclick="confirmChangePlan()">{{ trans('texts.plan_change') }}</button>
|
||||||
|
@else
|
||||||
|
<button type="button" class="btn btn-success" onclick="confirmChangePlan()">{{ trans('texts.plan_upgrade') }}</button>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
{!! Former::close() !!}
|
||||||
|
|
||||||
|
{!! Former::open('settings/cancel_account')->addClass('cancel-account') !!}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">{!! trans('texts.cancel_account') !!}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{!! Former::actions( Button::danger(trans('texts.cancel_account'))->large()->withAttributes(['onclick' => 'showConfirm()'])->appendIcon(Icon::create('trash'))) !!}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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">×</button>
|
||||||
|
<h4 class="modal-title" id="confirmCancelModalLabel">{!! trans('texts.cancel_account') !!}</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background-color: #fff; padding-left: 16px; padding-right: 16px">
|
||||||
|
<p>{{ trans('texts.cancel_account_message') }}</p>
|
||||||
|
<p>{!! Former::textarea('reason')->placeholder(trans('texts.reason_for_canceling'))->raw() !!}</p>
|
||||||
|
</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-danger" onclick="confirmCancel()">{{ trans('texts.cancel_account') }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{!! Former::close() !!}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
function showChangePlan() {
|
||||||
|
$('#changePlanModel').modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmChangePlan() {
|
||||||
|
$('form.change-plan').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showConfirm() {
|
||||||
|
$('#confirmCancelModal').modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmCancel() {
|
||||||
|
$('form.cancel-account').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@if ($account->company->pending_plan)
|
||||||
|
function cancelPendingChange(){
|
||||||
|
$('#plan').val('{{ $planDetails['plan'] }}')
|
||||||
|
$('#plan_term').val('{{ $planDetails['term'] }}')
|
||||||
|
confirmChangePlan();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@endif
|
||||||
|
|
||||||
|
jQuery(document).ready(function($){
|
||||||
|
function updatePlanModal() {
|
||||||
|
var plan = $('#plan').val();
|
||||||
|
$('#plan_term').closest('.form-group').toggle(plan!='free');
|
||||||
|
|
||||||
|
if(plan=='{{PLAN_PRO}}'){
|
||||||
|
$('#plan_term option[value=month]').text({!! json_encode(trans('texts.plan_price_monthly', ['price'=>PLAN_PRICE_PRO_MONTHLY])) !!});
|
||||||
|
$('#plan_term option[value=year]').text({!! json_encode(trans('texts.plan_price_yearly', ['price'=>PLAN_PRICE_PRO_YEARLY])) !!});
|
||||||
|
} else if(plan=='{{PLAN_ENTERPRISE}}') {
|
||||||
|
$('#plan_term option[value=month]').text({!! json_encode(trans('texts.plan_price_monthly', ['price'=>PLAN_PRICE_ENTERPRISE_MONTHLY])) !!});
|
||||||
|
$('#plan_term option[value=year]').text({!! json_encode(trans('texts.plan_price_yearly', ['price'=>PLAN_PRICE_ENTERPRISE_YEARLY])) !!});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$('#plan_term, #plan').change(updatePlanModal);
|
||||||
|
updatePlanModal();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@stop
|
@ -125,7 +125,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (Auth::user()->isPro())
|
@if (Auth::user()->hasFeature(FEATURE_EMAIL_TEMPLATES_REMINDERS))
|
||||||
<center>
|
<center>
|
||||||
{!! Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk')) !!}
|
{!! Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk')) !!}
|
||||||
</center>
|
</center>
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (Auth::user()->isPro())
|
@if (Auth::user()->hasFeature(FEATURE_API))
|
||||||
{!! Former::actions(
|
{!! Former::actions(
|
||||||
Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/settings/api_tokens'))->appendIcon(Icon::create('remove-circle'))->large(),
|
Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/settings/api_tokens'))->appendIcon(Icon::create('remove-circle'))->large(),
|
||||||
Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk'))
|
Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk'))
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
@if (Utils::isPro() && ! Utils::isTrial())
|
@if (Utils::hasFeature(FEATURE_USERS))
|
||||||
{!! Button::primary(trans('texts.add_user'))->asLinkTo(URL::to('/users/create'))->appendIcon(Icon::create('plus-sign')) !!}
|
{!! Button::primary(trans('texts.add_user'))->asLinkTo(URL::to('/users/create'))->appendIcon(Icon::create('plus-sign')) !!}
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
{!! Former::text('last_name')->data_bind("value: last_name, valueUpdate: 'afterkeydown'") !!}
|
{!! Former::text('last_name')->data_bind("value: last_name, valueUpdate: 'afterkeydown'") !!}
|
||||||
{!! Former::text('email')->data_bind("value: email, valueUpdate: 'afterkeydown'") !!}
|
{!! Former::text('email')->data_bind("value: email, valueUpdate: 'afterkeydown'") !!}
|
||||||
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown'") !!}
|
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown'") !!}
|
||||||
@if ($account->isPro() && $account->enable_portal_password)
|
@if ($account->hasFeature(FEATURE_CLIENT_PORTAL_PASSWORD) && $account->enable_portal_password)
|
||||||
{!! Former::password('password')->data_bind("value: password()?'-%unchanged%-':'', valueUpdate: 'afterkeydown'") !!}
|
{!! Former::password('password')->data_bind("value: password()?'-%unchanged%-':'', valueUpdate: 'afterkeydown'") !!}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
{!! Former::text('website') !!}
|
{!! Former::text('website') !!}
|
||||||
{!! Former::text('work_phone') !!}
|
{!! Former::text('work_phone') !!}
|
||||||
|
|
||||||
@if (Auth::user()->isPro())
|
@if (Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS))
|
||||||
@if ($customLabel1)
|
@if ($customLabel1)
|
||||||
{!! Former::text('custom_value1')->label($customLabel1) !!}
|
{!! Former::text('custom_value1')->label($customLabel1) !!}
|
||||||
@endif
|
@endif
|
||||||
@ -93,7 +93,7 @@
|
|||||||
attr: {name: 'contacts[' + \$index() + '][email]', id:'email'+\$index()}") !!}
|
attr: {name: 'contacts[' + \$index() + '][email]', id:'email'+\$index()}") !!}
|
||||||
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown',
|
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown',
|
||||||
attr: {name: 'contacts[' + \$index() + '][phone]'}") !!}
|
attr: {name: 'contacts[' + \$index() + '][phone]'}") !!}
|
||||||
@if ($account->isPro() && $account->enable_portal_password)
|
@if ($account->hasFeature(FEATURE_CLIENT_PORTAL_PASSWORD) && $account->enable_portal_password)
|
||||||
{!! Former::password('password')->data_bind("value: password()?'-%unchanged%-':'', valueUpdate: 'afterkeydown',
|
{!! Former::password('password')->data_bind("value: password()?'-%unchanged%-':'', valueUpdate: 'afterkeydown',
|
||||||
attr: {name: 'contacts[' + \$index() + '][password]'}") !!}
|
attr: {name: 'contacts[' + \$index() + '][password]'}") !!}
|
||||||
@endif
|
@endif
|
||||||
@ -134,15 +134,43 @@
|
|||||||
{!! Former::textarea('private_notes') !!}
|
{!! Former::textarea('private_notes') !!}
|
||||||
|
|
||||||
|
|
||||||
@if (isset($proPlanPaid))
|
@if (Auth::user()->account->isNinjaAccount())
|
||||||
{!! Former::populateField('pro_plan_paid', $proPlanPaid) !!}
|
@if (isset($planDetails))
|
||||||
{!! Former::text('pro_plan_paid')
|
{!! Former::populateField('plan', $planDetails['plan']) !!}
|
||||||
|
{!! Former::populateField('plan_term', $planDetails['term']) !!}
|
||||||
|
@if (!empty($planDetails['paid']))
|
||||||
|
{!! Former::populateField('plan_paid', $planDetails['paid']->format('Y-m-d')) !!}
|
||||||
|
@endif
|
||||||
|
@if (!empty($planDetails['expires']))
|
||||||
|
{!! Former::populateField('plan_expires', $planDetails['expires']->format('Y-m-d')) !!}
|
||||||
|
@endif
|
||||||
|
@if (!empty($planDetails['started']))
|
||||||
|
{!! Former::populateField('plan_started', $planDetails['started']->format('Y-m-d')) !!}
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
{!! Former::select('plan')
|
||||||
|
->addOption(trans('texts.plan_free'), PLAN_FREE)
|
||||||
|
->addOption(trans('texts.plan_pro'), PLAN_PRO)
|
||||||
|
->addOption(trans('texts.plan_enterprise'), PLAN_ENTERPRISE)!!}
|
||||||
|
{!! Former::select('plan_term')
|
||||||
|
->addOption()
|
||||||
|
->addOption(trans('texts.plan_term_yearly'), PLAN_TERM_YEARLY)
|
||||||
|
->addOption(trans('texts.plan_term_monthly'), PLAN_TERM_MONTHLY)!!}
|
||||||
|
{!! Former::text('plan_started')
|
||||||
->data_date_format('yyyy-mm-dd')
|
->data_date_format('yyyy-mm-dd')
|
||||||
->addGroupClass('pro_plan_paid_date')
|
->addGroupClass('plan_start_date')
|
||||||
|
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
|
||||||
|
{!! Former::text('plan_paid')
|
||||||
|
->data_date_format('yyyy-mm-dd')
|
||||||
|
->addGroupClass('plan_paid_date')
|
||||||
|
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
|
||||||
|
{!! Former::text('plan_expires')
|
||||||
|
->data_date_format('yyyy-mm-dd')
|
||||||
|
->addGroupClass('plan_expire_date')
|
||||||
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
|
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function() {
|
$(function() {
|
||||||
$('#pro_plan_paid').datepicker();
|
$('#plan_started, #plan_paid, #plan_expires').datepicker();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endif
|
@endif
|
||||||
|
@ -230,7 +230,7 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
||||||
@if (Utils::isPro() && $hasQuotes)
|
@if (Utils::hasFeature(FEATURE_QUOTES) && $hasQuotes)
|
||||||
<div class="tab-pane" id="quotes">
|
<div class="tab-pane" id="quotes">
|
||||||
|
|
||||||
{!! Datatable::table()
|
{!! Datatable::table()
|
||||||
|
@ -362,7 +362,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (Auth::user()->account->isPro())
|
@if (Auth::user()->account->hasFeature(FEATURE_DOCUMENTS))
|
||||||
function handleDocumentAdded(file){
|
function handleDocumentAdded(file){
|
||||||
if(file.mock)return;
|
if(file.mock)return;
|
||||||
file.index = model.documents().length;
|
file.index = model.documents().length;
|
||||||
|
@ -431,7 +431,7 @@
|
|||||||
|
|
||||||
<div class="btn-group user-dropdown">
|
<div class="btn-group user-dropdown">
|
||||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
|
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
|
||||||
<div id="myAccountButton" class="ellipsis nav-account-name" style="max-width:{{ Utils::isPro() && ! Utils::isTrial() ? '130' : '100' }}px;">
|
<div id="myAccountButton" class="ellipsis nav-account-name" style="max-width:{{ Utils::hasFeature(FEATURE_USERS) ? '130' : '100' }}px;">
|
||||||
@if (session(SESSION_USER_ACCOUNTS) && count(session(SESSION_USER_ACCOUNTS)))
|
@if (session(SESSION_USER_ACCOUNTS) && count(session(SESSION_USER_ACCOUNTS)))
|
||||||
{{ Auth::user()->account->getDisplayName() }}
|
{{ Auth::user()->account->getDisplayName() }}
|
||||||
@else
|
@else
|
||||||
@ -726,8 +726,8 @@
|
|||||||
<center>
|
<center>
|
||||||
<h2>{{ trans('texts.pro_plan_title') }}</h2>
|
<h2>{{ trans('texts.pro_plan_title') }}</h2>
|
||||||
<img class="img-responsive price" alt="Only $50 Per Year" src="{{ asset('images/pro_plan/price.png') }}"/>
|
<img class="img-responsive price" alt="Only $50 Per Year" src="{{ asset('images/pro_plan/price.png') }}"/>
|
||||||
@if (Auth::user()->isEligibleForTrial())
|
@if (Auth::user()->isEligibleForTrial(PLAN_PRO))
|
||||||
<a class="button" href="{{ URL::to('start_trial') }}">{{ trans('texts.trial_call_to_action') }}</a>
|
<a class="button" href="{{ URL::to('start_trial/'.PLAN_PRO) }}">{{ trans('texts.trial_call_to_action') }}</a>
|
||||||
@else
|
@else
|
||||||
<a class="button" href="#" onclick="submitProPlan()">{{ trans('texts.pro_plan_call_to_action') }}</a>
|
<a class="button" href="#" onclick="submitProPlan()">{{ trans('texts.pro_plan_call_to_action') }}</a>
|
||||||
@endif
|
@endif
|
||||||
@ -769,7 +769,7 @@
|
|||||||
{{-- Per our license, please do not remove or modify this section. --}}
|
{{-- Per our license, please do not remove or modify this section. --}}
|
||||||
{!! link_to('https://www.invoiceninja.com/?utm_source=powered_by', 'InvoiceNinja.com', ['target' => '_blank', 'title' => 'invoiceninja.com']) !!} -
|
{!! link_to('https://www.invoiceninja.com/?utm_source=powered_by', 'InvoiceNinja.com', ['target' => '_blank', 'title' => 'invoiceninja.com']) !!} -
|
||||||
{!! link_to(RELEASES_URL, 'v' . NINJA_VERSION, ['target' => '_blank', 'title' => trans('texts.trello_roadmap')]) !!} |
|
{!! link_to(RELEASES_URL, 'v' . NINJA_VERSION, ['target' => '_blank', 'title' => trans('texts.trello_roadmap')]) !!} |
|
||||||
@if (Auth::user()->account->isWhiteLabel())
|
@if (Auth::user()->account->hasFeature(FEATURE_WHITE_LABEL))
|
||||||
{{ trans('texts.white_labeled') }}
|
{{ trans('texts.white_labeled') }}
|
||||||
@else
|
@else
|
||||||
<a href="#" onclick="loadImages('#whiteLabelModal');$('#whiteLabelModal').modal('show');">{{ trans('texts.white_label_link') }}</a>
|
<a href="#" onclick="loadImages('#whiteLabelModal');$('#whiteLabelModal').modal('show');">{{ trans('texts.white_label_link') }}</a>
|
||||||
|
@ -296,7 +296,7 @@
|
|||||||
<li role="presentation" class="active"><a href="#notes" aria-controls="notes" role="tab" data-toggle="tab">{{ trans('texts.note_to_client') }}</a></li>
|
<li role="presentation" class="active"><a href="#notes" aria-controls="notes" role="tab" data-toggle="tab">{{ trans('texts.note_to_client') }}</a></li>
|
||||||
<li role="presentation"><a href="#terms" aria-controls="terms" role="tab" data-toggle="tab">{{ trans("texts.terms") }}</a></li>
|
<li role="presentation"><a href="#terms" aria-controls="terms" role="tab" data-toggle="tab">{{ trans("texts.terms") }}</a></li>
|
||||||
<li role="presentation"><a href="#footer" aria-controls="footer" role="tab" data-toggle="tab">{{ trans("texts.footer") }}</a></li>
|
<li role="presentation"><a href="#footer" aria-controls="footer" role="tab" data-toggle="tab">{{ trans("texts.footer") }}</a></li>
|
||||||
@if ($account->isPro())
|
@if ($account->hasFeature(FEATURE_DOCUMENTS))
|
||||||
<li role="presentation"><a href="#attached-documents" aria-controls="attached-documents" role="tab" data-toggle="tab">{{ trans("texts.invoice_documents") }}</a></li>
|
<li role="presentation"><a href="#attached-documents" aria-controls="attached-documents" role="tab" data-toggle="tab">{{ trans("texts.invoice_documents") }}</a></li>
|
||||||
@endif
|
@endif
|
||||||
</ul>
|
</ul>
|
||||||
@ -330,7 +330,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>') !!}
|
</div>') !!}
|
||||||
</div>
|
</div>
|
||||||
@if ($account->isPro())
|
@if ($account->hasFeature(FEATURE_DOCUMENTS))
|
||||||
<div role="tabpanel" class="tab-pane" id="attached-documents" style="position:relative;z-index:9">
|
<div role="tabpanel" class="tab-pane" id="attached-documents" style="position:relative;z-index:9">
|
||||||
<div id="document-upload">
|
<div id="document-upload">
|
||||||
<div class="dropzone">
|
<div class="dropzone">
|
||||||
@ -493,7 +493,7 @@
|
|||||||
{!! Former::text('pdfupload') !!}
|
{!! Former::text('pdfupload') !!}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (!Utils::isPro() || \App\Models\InvoiceDesign::count() == COUNT_FREE_DESIGNS_SELF_HOST)
|
@if (!Utils::hasFeature(FEATURE_MORE_INVOICE_DESIGNS) || \App\Models\InvoiceDesign::count() == COUNT_FREE_DESIGNS_SELF_HOST)
|
||||||
{!! Former::select('invoice_design_id')->style('display:inline;width:150px;background-color:white !important')->raw()->fromQuery($invoiceDesigns, 'name', 'id')->data_bind("value: invoice_design_id")->addOption(trans('texts.more_designs') . '...', '-1') !!}
|
{!! Former::select('invoice_design_id')->style('display:inline;width:150px;background-color:white !important')->raw()->fromQuery($invoiceDesigns, 'name', 'id')->data_bind("value: invoice_design_id")->addOption(trans('texts.more_designs') . '...', '-1') !!}
|
||||||
@else
|
@else
|
||||||
{!! Former::select('invoice_design_id')->style('display:inline;width:150px;background-color:white !important')->raw()->fromQuery($invoiceDesigns, 'name', 'id')->data_bind("value: invoice_design_id") !!}
|
{!! Former::select('invoice_design_id')->style('display:inline;width:150px;background-color:white !important')->raw()->fromQuery($invoiceDesigns, 'name', 'id')->data_bind("value: invoice_design_id") !!}
|
||||||
@ -565,7 +565,7 @@
|
|||||||
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@if (Auth::user()->isPro())
|
@if (Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS))
|
||||||
@if ($account->custom_client_label1)
|
@if ($account->custom_client_label1)
|
||||||
{!! Former::text('client[custom_value1]')
|
{!! Former::text('client[custom_value1]')
|
||||||
->label($account->custom_client_label1)
|
->label($account->custom_client_label1)
|
||||||
@ -620,7 +620,7 @@
|
|||||||
->addClass('client-email') !!}
|
->addClass('client-email') !!}
|
||||||
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown',
|
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown',
|
||||||
attr: {name: 'client[contacts][' + \$index() + '][phone]'}") !!}
|
attr: {name: 'client[contacts][' + \$index() + '][phone]'}") !!}
|
||||||
@if ($account->isPro() && $account->enable_portal_password)
|
@if ($account->hasFeature(FEATURE_CLIENT_PORTAL_PASSWORD) && $account->enable_portal_password)
|
||||||
{!! Former::password('password')->data_bind("value: (typeof password=='function'?password():null)?'-%unchanged%-':'', valueUpdate: 'afterkeydown',
|
{!! Former::password('password')->data_bind("value: (typeof password=='function'?password():null)?'-%unchanged%-':'', valueUpdate: 'afterkeydown',
|
||||||
attr: {name: 'client[contacts][' + \$index() + '][password]'}") !!}
|
attr: {name: 'client[contacts][' + \$index() + '][password]'}") !!}
|
||||||
@endif
|
@endif
|
||||||
@ -960,7 +960,7 @@
|
|||||||
|
|
||||||
applyComboboxListeners();
|
applyComboboxListeners();
|
||||||
|
|
||||||
@if (Auth::user()->account->isPro())
|
@if (Auth::user()->account->hasFeature(FEATURE_DOCUMENTS))
|
||||||
$('.main-form').submit(function(){
|
$('.main-form').submit(function(){
|
||||||
if($('#document-upload .dropzone .fallback input').val())$(this).attr('enctype', 'multipart/form-data')
|
if($('#document-upload .dropzone .fallback input').val())$(this).attr('enctype', 'multipart/form-data')
|
||||||
else $(this).removeAttr('enctype')
|
else $(this).removeAttr('enctype')
|
||||||
@ -1056,7 +1056,11 @@
|
|||||||
var model = ko.toJS(window.model);
|
var model = ko.toJS(window.model);
|
||||||
if(!model)return;
|
if(!model)return;
|
||||||
var invoice = model.invoice;
|
var invoice = model.invoice;
|
||||||
invoice.is_pro = {{ Auth::user()->isPro() ? 'true' : 'false' }};
|
invoice.features = {
|
||||||
|
customize_invoice_design:{{ Auth::user()->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN) ? 'true' : 'false' }},
|
||||||
|
remove_created_by:{{ Auth::user()->hasFeature(FEATURE_REMOVE_CREATED_BY) ? 'true' : 'false' }},
|
||||||
|
invoice_settings:{{ Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS) ? 'true' : 'false' }}
|
||||||
|
};
|
||||||
invoice.is_quote = {{ $entityType == ENTITY_QUOTE ? 'true' : 'false' }};
|
invoice.is_quote = {{ $entityType == ENTITY_QUOTE ? 'true' : 'false' }};
|
||||||
invoice.contact = _.findWhere(invoice.client.contacts, {send_invoice: true});
|
invoice.contact = _.findWhere(invoice.client.contacts, {send_invoice: true});
|
||||||
|
|
||||||
@ -1369,7 +1373,7 @@
|
|||||||
model.invoice().invoice_number(number);
|
model.invoice().invoice_number(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
@if ($account->isPro())
|
@if ($account->hasFeature(FEATURE_DOCUMENTS))
|
||||||
function handleDocumentAdded(file){
|
function handleDocumentAdded(file){
|
||||||
if(file.mock)return;
|
if(file.mock)return;
|
||||||
file.index = model.invoice().documents().length;
|
file.index = model.invoice().documents().length;
|
||||||
@ -1393,7 +1397,7 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@if ($account->isPro() && $account->invoice_embed_documents)
|
@if ($account->hasFeature(FEATURE_DOCUMENTS) && $account->invoice_embed_documents)
|
||||||
@foreach ($invoice->documents as $document)
|
@foreach ($invoice->documents as $document)
|
||||||
@if($document->isPDFEmbeddable())
|
@if($document->isPDFEmbeddable())
|
||||||
<script src="{{ $document->getVFSJSUrl() }}" type="text/javascript" async></script>
|
<script src="{{ $document->getVFSJSUrl() }}" type="text/javascript" async></script>
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
|
|
||||||
@include('invoices.pdf', ['account' => Auth::user()->account, 'pdfHeight' => 800])
|
@include('invoices.pdf', ['account' => Auth::user()->account, 'pdfHeight' => 800])
|
||||||
|
|
||||||
@if (Utils::isPro() && $invoice->account->invoice_embed_documents)
|
@if (Utils::hasFeature(FEATURE_DOCUMENTS) && $invoice->account->invoice_embed_documents)
|
||||||
@foreach ($invoice->documents as $document)
|
@foreach ($invoice->documents as $document)
|
||||||
@if($document->isPDFEmbeddable())
|
@if($document->isPDFEmbeddable())
|
||||||
<script src="{{ $document->getVFSJSUrl() }}" type="text/javascript" async></script>
|
<script src="{{ $document->getVFSJSUrl() }}" type="text/javascript" async></script>
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
var NINJA = NINJA || {};
|
var NINJA = NINJA || {};
|
||||||
@if ($account->isPro())
|
@if ($account->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN))
|
||||||
NINJA.primaryColor = "{{ $account->primary_color }}";
|
NINJA.primaryColor = "{{ $account->primary_color }}";
|
||||||
NINJA.secondaryColor = "{{ $account->secondary_color }}";
|
NINJA.secondaryColor = "{{ $account->secondary_color }}";
|
||||||
NINJA.fontSize = {{ $account->font_size }};
|
NINJA.fontSize = {{ $account->font_size }};
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if ($account->isPro() && $account->invoice_embed_documents)
|
@if ($account->hasFeature(FEATURE_DOCUMENTS) && $account->invoice_embed_documents)
|
||||||
@foreach ($invoice->documents as $document)
|
@foreach ($invoice->documents as $document)
|
||||||
@if($document->isPDFEmbeddable())
|
@if($document->isPDFEmbeddable())
|
||||||
<script src="{{ $document->getClientVFSJSUrl() }}" type="text/javascript" async></script>
|
<script src="{{ $document->getClientVFSJSUrl() }}" type="text/javascript" async></script>
|
||||||
@ -82,7 +82,11 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
window.invoice = {!! $invoice->toJson() !!};
|
window.invoice = {!! $invoice->toJson() !!};
|
||||||
invoice.is_pro = {{ $invoice->client->account->isPro() ? 'true' : 'false' }};
|
invoice.features = {
|
||||||
|
customize_invoice_design:{{ $invoice->client->account->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN) ? 'true' : 'false' }},
|
||||||
|
remove_created_by:{{ $invoice->client->account)->hasFeature(FEATURE_REMOVE_CREATED_BY) ? 'true' : 'false' }},
|
||||||
|
invoice_settings:{{ $invoice->client->account->hasFeature(FEATURE_INVOICE_SETTINGS) ? 'true' : 'false' }}
|
||||||
|
};
|
||||||
invoice.is_quote = {{ $invoice->is_quote ? 'true' : 'false' }};
|
invoice.is_quote = {{ $invoice->is_quote ? 'true' : 'false' }};
|
||||||
invoice.contact = {!! $contact->toJson() !!};
|
invoice.contact = {!! $contact->toJson() !!};
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
<div id="top_right_buttons" class="pull-right">
|
<div id="top_right_buttons" class="pull-right">
|
||||||
<input id="tableFilter" type="text" style="width:140px;margin-right:17px;background-color: white !important"
|
<input id="tableFilter" type="text" style="width:140px;margin-right:17px;background-color: white !important"
|
||||||
class="form-control pull-left" placeholder="{{ trans('texts.filter') }}" value="{{ Input::get('filter') }}"/>
|
class="form-control pull-left" placeholder="{{ trans('texts.filter') }}" value="{{ Input::get('filter') }}"/>
|
||||||
@if (Auth::user()->isPro() && $entityType == ENTITY_INVOICE)
|
@if (Auth::user()->hasFeature(FEATURE_QUOTES) && $entityType == ENTITY_INVOICE)
|
||||||
{!! Button::normal(trans('texts.quotes'))->asLinkTo(URL::to('/quotes'))->appendIcon(Icon::create('list')) !!}
|
{!! Button::normal(trans('texts.quotes'))->asLinkTo(URL::to('/quotes'))->appendIcon(Icon::create('list')) !!}
|
||||||
{!! Button::normal(trans('texts.recurring'))->asLinkTo(URL::to('/recurring_invoices'))->appendIcon(Icon::create('list')) !!}
|
{!! Button::normal(trans('texts.recurring'))->asLinkTo(URL::to('/recurring_invoices'))->appendIcon(Icon::create('list')) !!}
|
||||||
@elseif ($entityType == ENTITY_EXPENSE)
|
@elseif ($entityType == ENTITY_EXPENSE)
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
Button::success(trans('texts.run'))->withAttributes(array('id' => 'submitButton'))->submit()->appendIcon(Icon::create('play'))
|
Button::success(trans('texts.run'))->withAttributes(array('id' => 'submitButton'))->submit()->appendIcon(Icon::create('play'))
|
||||||
) !!}
|
) !!}
|
||||||
|
|
||||||
@if (!Auth::user()->isPro())
|
@if (!Auth::user()->hasFeature(FEATURE_REPORTS))
|
||||||
<script>
|
<script>
|
||||||
$(function() {
|
$(function() {
|
||||||
$('form.warn-on-exit').find('input, button').prop('disabled', true);
|
$('form.warn-on-exit').find('input, button').prop('disabled', true);
|
||||||
|
@ -268,7 +268,7 @@
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
var dayInSeconds = 1000*60*60*24;
|
var dayInSeconds = 1000*60*60*24;
|
||||||
@if (Auth::user()->account->isPro())
|
@if (Auth::user()->account->hasFeature(FEATURE_REPORTS))
|
||||||
var date = convertToJsDate(invoice.created_at);
|
var date = convertToJsDate(invoice.created_at);
|
||||||
@else
|
@else
|
||||||
var date = new Date().getTime() - (dayInSeconds * Math.random() * 100);
|
var date = new Date().getTime() - (dayInSeconds * Math.random() * 100);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if (Utils::hasFeature(FEATURE_USER_PERMISSIONS))
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h3 class="panel-title">{!! trans('texts.permissions') !!}</h3>
|
<h3 class="panel-title">{!! trans('texts.permissions') !!}</h3>
|
||||||
@ -59,6 +60,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
{!! Former::actions(
|
{!! Former::actions(
|
||||||
Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/settings/user_management'))->appendIcon(Icon::create('remove-circle'))->large(),
|
Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/settings/user_management'))->appendIcon(Icon::create('remove-circle'))->large(),
|
||||||
|
38
resources/views/vendors/edit.blade.php
vendored
38
resources/views/vendors/edit.blade.php
vendored
@ -114,15 +114,43 @@
|
|||||||
{!! Former::textarea('private_notes')->rows(6) !!}
|
{!! Former::textarea('private_notes')->rows(6) !!}
|
||||||
|
|
||||||
|
|
||||||
@if (isset($proPlanPaid))
|
@if (Auth::user()->account->isNinjaAccount())
|
||||||
{!! Former::populateField('pro_plan_paid', $proPlanPaid) !!}
|
@if (isset($planDetails))
|
||||||
{!! Former::text('pro_plan_paid')
|
{!! Former::populateField('plan', $planDetails['plan']) !!}
|
||||||
|
{!! Former::populateField('plan_term', $planDetails['term']) !!}
|
||||||
|
@if (!empty($planDetails['paid']))
|
||||||
|
{!! Former::populateField('plan_paid', $planDetails['paid']->format('Y-m-d')) !!}
|
||||||
|
@endif
|
||||||
|
@if (!empty($planDetails['expires']))
|
||||||
|
{!! Former::populateField('plan_expires', $planDetails['expires']->format('Y-m-d')) !!}
|
||||||
|
@endif
|
||||||
|
@if (!empty($planDetails['started']))
|
||||||
|
{!! Former::populateField('plan_started', $planDetails['started']->format('Y-m-d')) !!}
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
{!! Former::select('plan')
|
||||||
|
->addOption(trans('texts.plan_free'), PLAN_FREE)
|
||||||
|
->addOption(trans('texts.plan_pro'), PLAN_PRO)
|
||||||
|
->addOption(trans('texts.plan_enterprise'), PLAN_ENTERPRISE)!!}
|
||||||
|
{!! Former::select('plan_term')
|
||||||
|
->addOption()
|
||||||
|
->addOption(trans('texts.plan_term_yearly'), PLAN_TERM_YEARLY)
|
||||||
|
->addOption(trans('texts.plan_term_monthly'), PLAN_TERM_MONTHLY)!!}
|
||||||
|
{!! Former::text('plan_started')
|
||||||
->data_date_format('yyyy-mm-dd')
|
->data_date_format('yyyy-mm-dd')
|
||||||
->addGroupClass('pro_plan_paid_date')
|
->addGroupClass('plan_start_date')
|
||||||
|
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
|
||||||
|
{!! Former::text('plan_paid')
|
||||||
|
->data_date_format('yyyy-mm-dd')
|
||||||
|
->addGroupClass('plan_paid_date')
|
||||||
|
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
|
||||||
|
{!! Former::text('plan_expires')
|
||||||
|
->data_date_format('yyyy-mm-dd')
|
||||||
|
->addGroupClass('plan_expire_date')
|
||||||
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
|
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function() {
|
$(function() {
|
||||||
$('#pro_plan_paid').datepicker();
|
$('#plan_started, #plan_paid, #plan_expires').datepicker();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endif
|
@endif
|
||||||
|
Loading…
Reference in New Issue
Block a user