diff --git a/.env.example b/.env.example index abc9da3a5254..643dda91d834 100644 --- a/.env.example +++ b/.env.example @@ -18,6 +18,4 @@ MAIL_HOST MAIL_USERNAME MAIL_FROM_ADDRESS MAIL_FROM_NAME -MAIL_PASSWORD - -ALLOW_NEW_ACCOUNTS \ No newline at end of file +MAIL_PASSWORD \ No newline at end of file diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index b781e41887d2..fea09ebf9f21 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -75,18 +75,18 @@ class AccountController extends BaseController public function getStarted() { - if (Auth::check()) { - return Redirect::to('invoices/create'); - } - - if (!Utils::isNinja() && !Utils::allowNewAccounts() && Account::count() > 0) { - return Redirect::to('/login'); - } - $user = false; $guestKey = Input::get('guest_key'); // local storage key to login until registered $prevUserId = Session::pull(PREV_USER_ID); // last user id used to link to new account + if (Auth::check()) { + return Redirect::to('invoices/create'); + } + + if (!Utils::isNinja() && (Account::count() > 0 && !$prevUserId)) { + return Redirect::to('/login'); + } + if ($guestKey && !$prevUserId) { $user = User::where('password', '=', $guestKey)->first(); @@ -149,6 +149,7 @@ class AccountController extends BaseController public function showSection($section = ACCOUNT_DETAILS, $subSection = false) { if ($section == ACCOUNT_DETAILS) { + $primaryUser = Auth::user()->account->users()->orderBy('id')->first(); $data = [ 'account' => Account::with('users')->findOrFail(Auth::user()->account_id), 'countries' => Cache::get('countries'), @@ -159,8 +160,9 @@ class AccountController extends BaseController 'datetimeFormats' => Cache::get('datetimeFormats'), 'currencies' => Cache::get('currencies'), 'languages' => Cache::get('languages'), - 'showUser' => Auth::user()->id === Auth::user()->account->users()->first()->id, + 'showUser' => Auth::user()->id === $primaryUser->id, 'title' => trans('texts.company_details'), + 'primaryUser' => $primaryUser, ]; return View::make('accounts.details', $data); @@ -639,7 +641,7 @@ class AccountController extends BaseController 'name' => 'required', ); - $user = Auth::user()->account->users()->first(); + $user = Auth::user()->account->users()->orderBy('id')->first(); if (Auth::user()->id === $user->id) { $rules['email'] = 'email|required|unique:users,email,'.$user->id.',id'; diff --git a/app/Http/Controllers/AppController.php b/app/Http/Controllers/AppController.php index 91d716cf253d..b135c045053e 100644 --- a/app/Http/Controllers/AppController.php +++ b/app/Http/Controllers/AppController.php @@ -88,9 +88,7 @@ class AppController extends BaseController "MAIL_HOST={$mail['host']}\n". "MAIL_USERNAME={$mail['username']}\n". "MAIL_FROM_NAME={$mail['from']['name']}\n". - "MAIL_PASSWORD={$mail['password']}\n\n". - "ADMIN_USER_ID=1\n". - "ALLOW_NEW_ACCOUNTS\n"; + "MAIL_PASSWORD={$mail['password']}"; // Write Config Settings $fp = fopen(base_path()."/.env", 'w'); @@ -178,7 +176,7 @@ class AppController extends BaseController public function update() { - if (!Utils::isNinja()) { + if (!Utils::isNinja() && Auth::check()) { try { Artisan::call('migrate', array('--force' => true)); Artisan::call('db:seed', array('--force' => true, '--class' => 'PaymentLibrariesSeeder')); diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 292f09336be2..6ac4de2a4039 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -110,7 +110,7 @@ class DashboardController extends BaseController ->where('contacts.deleted_at', '=', null) ->where('contacts.is_primary', '=', true) ->select(['payments.payment_date', 'payments.amount', 'invoices.public_id', 'invoices.invoice_number', 'clients.name as client_name', 'contacts.email', 'contacts.first_name', 'contacts.last_name', 'clients.currency_id', 'clients.public_id as client_public_id']) - ->orderBy('payments.payment_date', 'asc') + ->orderBy('payments.id', 'desc') ->take(50) ->get(); diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index a58245e0e25b..2645b0cbd98a 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -43,7 +43,7 @@ class HomeController extends BaseController public function invoiceNow() { - if (Auth::check() && Input::get('new_account')) { + if (Auth::check() && Input::get('new_company')) { Session::put(PREV_USER_ID, Auth::user()->id); Auth::user()->clearSession(); Auth::logout(); diff --git a/app/Http/Controllers/InvoiceApiController.php b/app/Http/Controllers/InvoiceApiController.php index 43911db7d8c3..02fb8e19bf9a 100644 --- a/app/Http/Controllers/InvoiceApiController.php +++ b/app/Http/Controllers/InvoiceApiController.php @@ -50,12 +50,14 @@ class InvoiceApiController extends Controller $error = null; // check if the invoice number is set and unique - if (!isset($data['invoice_number'])) { + if (!isset($data['invoice_number']) && !isset($data['id'])) { $data['invoice_number'] = Auth::user()->account->getNextInvoiceNumber(); - } else { + } else if (isset($data['invoice_number'])) { $invoice = Invoice::scope()->where('invoice_number', '=', $data['invoice_number'])->first(); if ($invoice) { $error = trans('validation.unique', ['attribute' => 'texts.invoice_number']); + } else { + $data['id'] = $invoice->public_id; } } @@ -98,13 +100,15 @@ class InvoiceApiController extends Controller } else { $data = self::prepareData($data); $data['client_id'] = $client->id; - $invoice = $this->invoiceRepo->save(false, $data, false); + $invoice = $this->invoiceRepo->save(isset($data['id']) ? $data['id'] : false, $data, false); - $invitation = Invitation::createNew(); - $invitation->invoice_id = $invoice->id; - $invitation->contact_id = $client->contacts[0]->id; - $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH); - $invitation->save(); + if (!isset($data['id'])) { + $invitation = Invitation::createNew(); + $invitation->invoice_id = $invoice->id; + $invitation->contact_id = $client->contacts[0]->id; + $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH); + $invitation->save(); + } if (isset($data['email_invoice']) && $data['email_invoice']) { $this->mailer->sendInvoice($invoice); diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 1939ce9c65da..d93e67300bc9 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -86,11 +86,12 @@ class InvoiceController extends BaseController } $invitation = Invitation::with('account')->where('invitation_key', '=', $invitationKey)->first(); - $color = $invitation->account->primary_color ? $invitation->account->primary_color : '#0b4d78'; + $account = $invitation->account; + $color = $account->primary_color ? $account->primary_color : '#0b4d78'; $data = [ 'color' => $color, - 'hideLogo' => Session::get('white_label'), + 'hideLogo' => $account->isWhiteLabel(), 'title' => trans('texts.invoices'), 'entityType' => ENTITY_INVOICE, 'columns' => Utils::trans(['invoice_number', 'invoice_date', 'invoice_total', 'balance_due', 'due_date']), @@ -205,7 +206,6 @@ class InvoiceController extends BaseController Session::set($invitationKey, true); Session::set('invitation_key', $invitationKey); - Session::set('white_label', $account->isWhiteLabel()); $account->loadLocalizationSettings(); diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 8b70a780bdfe..4b63aabc695c 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -61,11 +61,12 @@ class PaymentController extends BaseController } $invitation = Invitation::with('account')->where('invitation_key', '=', $invitationKey)->first(); - $color = $invitation->account->primary_color ? $invitation->account->primary_color : '#0b4d78'; + $account = $invitation->account; + $color = $account->primary_color ? $account->primary_color : '#0b4d78'; $data = [ 'color' => $color, - 'hideLogo' => Session::get('white_label'), + 'hideLogo' => $account->isWhiteLabel(), 'entityType' => ENTITY_PAYMENT, 'title' => trans('texts.payments'), 'columns' => Utils::trans(['invoice', 'transaction_reference', 'method', 'payment_amount', 'payment_date']) @@ -336,7 +337,7 @@ class PaymentController extends BaseController 'acceptedCreditCardTypes' => $acceptedCreditCardTypes, 'countries' => Cache::get('countries'), 'currencyId' => $client->getCurrencyId(), - 'currencyCode' => $client->currency->code, + 'currencyCode' => $client->currency ? $client->currency->code : ($account->currency ? $account->currency->code : 'USD'), 'account' => $client->account, 'hideLogo' => $account->isWhiteLabel(), 'showAddress' => $accountGateway->show_address, diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index b8dfd095e44b..bb8526c424e9 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -75,11 +75,12 @@ class QuoteController extends BaseController } $invitation = Invitation::with('account')->where('invitation_key', '=', $invitationKey)->first(); - $color = $invitation->account->primary_color ? $invitation->account->primary_color : '#0b4d78'; + $account = $invitation->account; + $color = $account->primary_color ? $account->primary_color : '#0b4d78'; $data = [ 'color' => $color, - 'hideLogo' => Session::get('white_label'), + 'hideLogo' => $account->isWhiteLabel(), 'title' => trans('texts.quotes'), 'entityType' => ENTITY_QUOTE, 'columns' => Utils::trans(['quote_number', 'quote_date', 'quote_total', 'due_date']), diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php index 184dd453e498..b38911371476 100644 --- a/app/Libraries/Utils.php +++ b/app/Libraries/Utils.php @@ -61,7 +61,7 @@ class Utils public static function allowNewAccounts() { - return Utils::isNinja() || (isset($_ENV['ALLOW_NEW_ACCOUNTS']) && $_ENV['ALLOW_NEW_ACCOUNTS'] == 'true'); + return Utils::isNinja() || Auth::check(); } public static function isPro() @@ -400,10 +400,12 @@ class Utils } $object = new stdClass(); + $object->accountId = Auth::user()->account_id; $object->url = $url; $object->name = ucwords($type).': '.$name; $data = []; + $counts = []; for ($i = 0; $iaccountId])) { + $counts[$item->accountId]++; + } else { + $counts[$item->accountId] = 1; + } } array_unshift($data, $object); - - if (count($data) > RECENTLY_VIEWED_LIMIT) { + + if (isset($counts[Auth::user()->account_id]) && $counts[Auth::user()->account_id] > RECENTLY_VIEWED_LIMIT) { array_pop($data); } diff --git a/app/Models/Account.php b/app/Models/Account.php index 10ba19d99ecd..5def5c6a999c 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -176,37 +176,36 @@ class Account extends Eloquent { $counter = $isQuote && !$this->share_counter ? $this->quote_number_counter : $this->invoice_number_counter; $prefix .= $isQuote ? $this->quote_number_prefix : $this->invoice_number_prefix; - + $counterOffset = 0; + // confirm the invoice number isn't already taken do { $number = $prefix.str_pad($counter, 4, "0", STR_PAD_LEFT); $check = Invoice::scope(false, $this->id)->whereInvoiceNumber($number)->withTrashed()->first(); $counter++; + $counterOffset++; } while ($check); + // update the invoice counter to be caught up + if ($counterOffset > 1) { + if ($isQuote && !$this->share_counter) { + $this->quote_number_counter += $counterOffset - 1; + } else { + $this->invoice_number_counter += $counterOffset - 1; + } + + $this->save(); + } + return $number; } - public function incrementCounter($invoiceNumber, $isQuote = false, $isRecurring) + public function incrementCounter($isQuote = false) { - // check if the user modified the invoice number - if (!$isRecurring && $invoiceNumber != $this->getNextInvoiceNumber($isQuote)) { - // remove the prefix - $prefix = $isQuote ? $this->quote_number_prefix : $this->invoice_number_prefix; - $invoiceNumber = preg_replace('/^'.$prefix.'/', '', $invoiceNumber); - $invoiceNumber = intval(preg_replace('/[^0-9]/', '', $invoiceNumber)); - if ($isQuote && !$this->share_counter) { - $this->quote_number_counter = $invoiceNumber + 1; - } else { - $this->invoice_number_counter = $invoiceNumber + 1; - } - // otherwise, just increment the counter + if ($isQuote && !$this->share_counter) { + $this->quote_number_counter += 1; } else { - if ($isQuote && !$this->share_counter) { - $this->quote_number_counter += 1; - } else { - $this->invoice_number_counter += 1; - } + $this->invoice_number_counter += 1; } $this->save(); @@ -315,11 +314,11 @@ class Account extends Eloquent public function isWhiteLabel() { - if (Utils::isNinjaProd()) { - return false; + if (Utils::isNinja()) { + return self::isPro(); + } else { + return $this->pro_plan_paid == NINJA_DATE; } - - return $this->pro_plan_paid == NINJA_DATE; } public function getSubscription($eventId) diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index a1f01a5b5040..63700410fa18 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -258,7 +258,7 @@ class Invoice extends EntityModel } Invoice::creating(function ($invoice) { - $invoice->account->incrementCounter($invoice->invoice_number, $invoice->is_quote, $invoice->recurring_invoice_id); + $invoice->account->incrementCounter($invoice->is_quote); }); Invoice::created(function ($invoice) { diff --git a/app/Ninja/Mailers/UserMailer.php b/app/Ninja/Mailers/UserMailer.php index 710e436c11e8..3f2b4290a7eb 100644 --- a/app/Ninja/Mailers/UserMailer.php +++ b/app/Ninja/Mailers/UserMailer.php @@ -47,7 +47,7 @@ class UserMailer extends Mailer 'clientName' => $invoice->client->getDisplayName(), 'accountName' => $invoice->account->getDisplayName(), 'userName' => $user->getDisplayName(), - 'invoiceAmount' => Utils::formatMoney($invoice->amount, $invoice->client->getCurrencyId()), + 'invoiceAmount' => Utils::formatMoney($invoice->getRequestedAmount(), $invoice->client->getCurrencyId()), 'invoiceNumber' => $invoice->invoice_number, 'invoiceLink' => SITE_URL."/{$entityType}s/{$invoice->public_id}", ]; diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index ce0397d64b4d..0d3b2e8ce565 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -266,15 +266,18 @@ class InvoiceRepository $account->save(); } - $invoice->client_id = $data['client_id']; + if (isset($data['invoice_number'])) { + $invoice->invoice_number = trim($data['invoice_number']); + } + $invoice->discount = round(Utils::parseFloat($data['discount']), 2); $invoice->is_amount_discount = $data['is_amount_discount'] ? true : false; - $invoice->invoice_number = trim($data['invoice_number']); $invoice->partial = round(Utils::parseFloat($data['partial']), 2); $invoice->invoice_date = isset($data['invoice_date_sql']) ? $data['invoice_date_sql'] : Utils::toSqlDate($data['invoice_date']); $invoice->has_tasks = isset($data['has_tasks']) ? $data['has_tasks'] : false; if (!$publicId) { + $invoice->client_id = $data['client_id']; $invoice->is_recurring = $data['is_recurring'] && !Utils::isDemo() ? true : false; } @@ -543,8 +546,9 @@ class InvoiceRepository ->whereClientId($clientId) ->whereIsQuote(false) ->whereIsRecurring(false) + ->whereDeletedAt(null) ->whereHasTasks(true) - ->where('balance', '>', 0) + ->where('invoice_status_id', '<', 5) ->select(['public_id', 'invoice_number']) ->get(); } diff --git a/public/js/built.js b/public/js/built.js index fc0fa403d399..0a22d2a5a35e 100644 --- a/public/js/built.js +++ b/public/js/built.js @@ -31599,7 +31599,10 @@ NINJA.decodeJavascript = function(invoice, javascript) field = match.substring(2, match.indexOf('Label')); field = toSnakeCase(field); var value = getDescendantProp(invoice, field); - if (match.indexOf('?') < 0) { + if (match.indexOf('?') < 0 || value) { + if (invoice.partial && field == 'balance_due') { + field = 'amount_due'; + } var label = invoiceLabels[field]; if (match.indexOf('UC') >= 0) { if (!label) console.log('match: ' + field); @@ -31663,14 +31666,14 @@ NINJA.invoiceColumns = function(invoice) NINJA.invoiceLines = function(invoice) { var grid = [ - [ - {text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']}, - {text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']}, - {text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}, - {text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']}, - {text: invoice.has_taxes ? invoiceLabels.tax : '', style: ['tableHeader', 'taxTableHeader']}, - {text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']} - ] + [ + {text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']}, + {text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']}, + {text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}, + {text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']}, + {text: invoice.has_taxes ? invoiceLabels.tax : '', style: ['tableHeader', 'taxTableHeader']}, + {text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']} + ] ]; var total = 0; @@ -31679,7 +31682,7 @@ NINJA.invoiceLines = function(invoice) { var hideQuantity = invoice.account.hide_quantity == '1'; for (var i = 0; i < invoice.invoice_items.length; i++) { - + var row = []; var item = invoice.invoice_items[i]; var cost = formatMoney(item.cost, currencyId, true); @@ -31767,16 +31770,17 @@ NINJA.subtotals = function(invoice, removeBalance) data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]); } - var paid = invoice.amount - invoice.balance; + var paid = invoice.amount - invoice.balance; if (invoice.account.hide_paid_to_date != '1' || paid) { data.push([{text:invoiceLabels.paid_to_date}, {text:formatMoney(paid, invoice.client.currency_id)}]); } if (!removeBalance) { + var isPartial = NINJA.parseFloat(invoice.partial); data.push([ - {text:invoice.is_quote ? invoiceLabels.balance_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, - {text:formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} - ]); + {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, + {text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} + ]); } return NINJA.prepareDataPairs(data, 'subtotals'); @@ -31785,11 +31789,11 @@ NINJA.subtotals = function(invoice, removeBalance) NINJA.accountDetails = function(invoice) { var account = invoice.account; var data = [ - {text:account.name, style: ['accountName']}, - {text:account.id_number}, - {text:account.vat_number}, - {text:account.work_email}, - {text:account.work_phone} + {text:account.name, style: ['accountName']}, + {text:account.id_number}, + {text:account.vat_number}, + {text:account.work_email}, + {text:account.work_phone} ]; return NINJA.prepareDataList(data, 'accountDetails'); } @@ -31801,11 +31805,11 @@ NINJA.accountAddress = function(invoice) { cityStatePostal = ((account.city ? account.city + ', ' : '') + account.state + ' ' + account.postal_code).trim(); } - var data = [ - {text: account.address1}, - {text: account.address2}, - {text: cityStatePostal}, - {text: account.country ? account.country.name : ''} + var data = [ + {text: account.address1}, + {text: account.address2}, + {text: cityStatePostal}, + {text: account.country ? account.country.name : ''} ]; return NINJA.prepareDataList(data, 'accountAddress'); @@ -31814,42 +31818,43 @@ NINJA.accountAddress = function(invoice) { NINJA.invoiceDetails = function(invoice) { var data = [ - [ - {text: (invoice.is_quote ? invoiceLabels.quote_number : invoiceLabels.invoice_number), style: ['invoiceNumberLabel']}, - {text: invoice.invoice_number, style: ['invoiceNumber']} - ], - [ - {text: invoiceLabels.po_number}, - {text: invoice.po_number} - ], - [ - {text: invoiceLabels.invoice_date}, - {text: invoice.invoice_date} - ], - [ - {text: invoiceLabels.due_date}, - {text: invoice.due_date} - ] + [ + {text: (invoice.is_quote ? invoiceLabels.quote_number : invoiceLabels.invoice_number), style: ['invoiceNumberLabel']}, + {text: invoice.invoice_number, style: ['invoiceNumber']} + ], + [ + {text: invoiceLabels.po_number}, + {text: invoice.po_number} + ], + [ + {text: (invoice.is_quote ? invoiceLabels.quote_date : invoiceLabels.invoice_date)}, + {text: invoice.invoice_date} + ], + [ + {text: invoiceLabels.due_date}, + {text: invoice.due_date} + ] ]; + + var isPartial = NINJA.parseFloat(invoice.partial); + if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) { data.push([ {text: invoiceLabels.total}, {text: formatMoney(invoice.amount, invoice.client.currency_id)} - ]); - } - - if (NINJA.parseFloat(invoice.partial)) { + ]); + } else if (isPartial) { data.push([ - {text: invoiceLabels.balance}, + {text: invoiceLabels.total}, {text: formatMoney(invoice.total_amount, invoice.client.currency_id)} - ]); + ]); } data.push([ - {text: invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, + {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, {text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style: ['invoiceDetailBalanceDue']} - ]) + ]) return NINJA.prepareDataPairs(data, 'invoiceDetails'); } @@ -31865,11 +31870,11 @@ NINJA.clientDetails = function(invoice) { var clientEmail = client.contacts[0].email == clientName ? '' : client.contacts[0].email; data = [ - {text:clientName || ' ', style: ['clientName']}, - {text:client.address1}, - {text:concatStrings(client.city, client.state, client.postal_code)}, - {text:client.country ? client.country.name : ''}, - {text:clientEmail} + {text:clientName || ' ', style: ['clientName']}, + {text:client.address1}, + {text:concatStrings(client.city, client.state, client.postal_code)}, + {text:client.country ? client.country.name : ''}, + {text:clientEmail} ]; return NINJA.prepareDataList(data, 'clientDetails'); diff --git a/public/js/pdf.pdfmake.js b/public/js/pdf.pdfmake.js index ad7ad654067b..168a8733567b 100644 --- a/public/js/pdf.pdfmake.js +++ b/public/js/pdf.pdfmake.js @@ -122,7 +122,10 @@ NINJA.decodeJavascript = function(invoice, javascript) field = match.substring(2, match.indexOf('Label')); field = toSnakeCase(field); var value = getDescendantProp(invoice, field); - if (match.indexOf('?') < 0) { + if (match.indexOf('?') < 0 || value) { + if (invoice.partial && field == 'balance_due') { + field = 'amount_due'; + } var label = invoiceLabels[field]; if (match.indexOf('UC') >= 0) { if (!label) console.log('match: ' + field); @@ -186,14 +189,14 @@ NINJA.invoiceColumns = function(invoice) NINJA.invoiceLines = function(invoice) { var grid = [ - [ - {text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']}, - {text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']}, - {text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}, - {text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']}, - {text: invoice.has_taxes ? invoiceLabels.tax : '', style: ['tableHeader', 'taxTableHeader']}, - {text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']} - ] + [ + {text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']}, + {text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']}, + {text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}, + {text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']}, + {text: invoice.has_taxes ? invoiceLabels.tax : '', style: ['tableHeader', 'taxTableHeader']}, + {text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']} + ] ]; var total = 0; @@ -202,7 +205,7 @@ NINJA.invoiceLines = function(invoice) { var hideQuantity = invoice.account.hide_quantity == '1'; for (var i = 0; i < invoice.invoice_items.length; i++) { - + var row = []; var item = invoice.invoice_items[i]; var cost = formatMoney(item.cost, currencyId, true); @@ -290,16 +293,17 @@ NINJA.subtotals = function(invoice, removeBalance) data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]); } - var paid = invoice.amount - invoice.balance; + var paid = invoice.amount - invoice.balance; if (invoice.account.hide_paid_to_date != '1' || paid) { data.push([{text:invoiceLabels.paid_to_date}, {text:formatMoney(paid, invoice.client.currency_id)}]); } if (!removeBalance) { + var isPartial = NINJA.parseFloat(invoice.partial); data.push([ - {text:invoice.is_quote ? invoiceLabels.balance_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, - {text:formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} - ]); + {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, + {text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} + ]); } return NINJA.prepareDataPairs(data, 'subtotals'); @@ -308,11 +312,11 @@ NINJA.subtotals = function(invoice, removeBalance) NINJA.accountDetails = function(invoice) { var account = invoice.account; var data = [ - {text:account.name, style: ['accountName']}, - {text:account.id_number}, - {text:account.vat_number}, - {text:account.work_email}, - {text:account.work_phone} + {text:account.name, style: ['accountName']}, + {text:account.id_number}, + {text:account.vat_number}, + {text:account.work_email}, + {text:account.work_phone} ]; return NINJA.prepareDataList(data, 'accountDetails'); } @@ -324,11 +328,11 @@ NINJA.accountAddress = function(invoice) { cityStatePostal = ((account.city ? account.city + ', ' : '') + account.state + ' ' + account.postal_code).trim(); } - var data = [ - {text: account.address1}, - {text: account.address2}, - {text: cityStatePostal}, - {text: account.country ? account.country.name : ''} + var data = [ + {text: account.address1}, + {text: account.address2}, + {text: cityStatePostal}, + {text: account.country ? account.country.name : ''} ]; return NINJA.prepareDataList(data, 'accountAddress'); @@ -337,42 +341,43 @@ NINJA.accountAddress = function(invoice) { NINJA.invoiceDetails = function(invoice) { var data = [ - [ - {text: (invoice.is_quote ? invoiceLabels.quote_number : invoiceLabels.invoice_number), style: ['invoiceNumberLabel']}, - {text: invoice.invoice_number, style: ['invoiceNumber']} - ], - [ - {text: invoiceLabels.po_number}, - {text: invoice.po_number} - ], - [ - {text: invoiceLabels.invoice_date}, - {text: invoice.invoice_date} - ], - [ - {text: invoiceLabels.due_date}, - {text: invoice.due_date} - ] + [ + {text: (invoice.is_quote ? invoiceLabels.quote_number : invoiceLabels.invoice_number), style: ['invoiceNumberLabel']}, + {text: invoice.invoice_number, style: ['invoiceNumber']} + ], + [ + {text: invoiceLabels.po_number}, + {text: invoice.po_number} + ], + [ + {text: (invoice.is_quote ? invoiceLabels.quote_date : invoiceLabels.invoice_date)}, + {text: invoice.invoice_date} + ], + [ + {text: invoiceLabels.due_date}, + {text: invoice.due_date} + ] ]; + + var isPartial = NINJA.parseFloat(invoice.partial); + if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) { data.push([ {text: invoiceLabels.total}, {text: formatMoney(invoice.amount, invoice.client.currency_id)} - ]); - } - - if (NINJA.parseFloat(invoice.partial)) { + ]); + } else if (isPartial) { data.push([ - {text: invoiceLabels.balance}, + {text: invoiceLabels.total}, {text: formatMoney(invoice.total_amount, invoice.client.currency_id)} - ]); + ]); } data.push([ - {text: invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, + {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, {text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style: ['invoiceDetailBalanceDue']} - ]) + ]) return NINJA.prepareDataPairs(data, 'invoiceDetails'); } @@ -388,11 +393,11 @@ NINJA.clientDetails = function(invoice) { var clientEmail = client.contacts[0].email == clientName ? '' : client.contacts[0].email; data = [ - {text:clientName || ' ', style: ['clientName']}, - {text:client.address1}, - {text:concatStrings(client.city, client.state, client.postal_code)}, - {text:client.country ? client.country.name : ''}, - {text:clientEmail} + {text:clientName || ' ', style: ['clientName']}, + {text:client.address1}, + {text:concatStrings(client.city, client.state, client.postal_code)}, + {text:client.country ? client.country.name : ''}, + {text:clientEmail} ]; return NINJA.prepareDataList(data, 'clientDetails'); diff --git a/resources/lang/da/texts.php b/resources/lang/da/texts.php index 429d778ca2e1..5a5b73b03582 100644 --- a/resources/lang/da/texts.php +++ b/resources/lang/da/texts.php @@ -698,9 +698,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php index e91162679c8b..03f8f773c770 100644 --- a/resources/lang/de/texts.php +++ b/resources/lang/de/texts.php @@ -688,9 +688,9 @@ return array( 'email_receipt' => 'Zahlungsbestätigung an Kunden per E-Mail senden', 'created_payment_emailed_client' => 'Zahlung erfolgreich erstellt und Kunde per E-Mail benachrichtigt', - 'add_account' => 'Konto hinzufügen', + 'add_company' => 'Konto hinzufügen', 'untitled' => 'Unbenannt', - 'new_account' => 'Neues Konto', + 'new_company' => 'Neues Konto', 'associated_accounts' => 'Konten erfolgreich verlinkt', 'unlinked_account' => 'Konten erfolgreich getrennt', 'login' => 'Login', diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 916aa7e40d5a..11092c957a16 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -696,9 +696,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/es/texts.php b/resources/lang/es/texts.php index f5ecb6107543..aa0273a47042 100644 --- a/resources/lang/es/texts.php +++ b/resources/lang/es/texts.php @@ -668,9 +668,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/es_ES/texts.php b/resources/lang/es_ES/texts.php index d8677edff31e..df7ec3c92535 100644 --- a/resources/lang/es_ES/texts.php +++ b/resources/lang/es_ES/texts.php @@ -697,9 +697,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/fr/texts.php b/resources/lang/fr/texts.php index bdbd4c505254..b401ea0d3076 100644 --- a/resources/lang/fr/texts.php +++ b/resources/lang/fr/texts.php @@ -689,9 +689,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Paiement crée avec succès et envoyé au client', - 'add_account' => 'Ajouter compte', + 'add_company' => 'Ajouter compte', 'untitled' => 'Sans titre', - 'new_account' => 'Nouveau compte', + 'new_company' => 'Nouveau compte', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Connexion', diff --git a/resources/lang/fr_CA/texts.php b/resources/lang/fr_CA/texts.php index eaf88d318209..2300badc12b2 100644 --- a/resources/lang/fr_CA/texts.php +++ b/resources/lang/fr_CA/texts.php @@ -690,9 +690,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/it/texts.php b/resources/lang/it/texts.php index b4cc4736638f..d12f6f2bcb94 100644 --- a/resources/lang/it/texts.php +++ b/resources/lang/it/texts.php @@ -692,9 +692,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/lt/texts.php b/resources/lang/lt/texts.php index a507fa01a433..b57bdc7cfc25 100644 --- a/resources/lang/lt/texts.php +++ b/resources/lang/lt/texts.php @@ -699,9 +699,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/nb_NO/texts.php b/resources/lang/nb_NO/texts.php index cda4b94fabff..18b88e16886e 100644 --- a/resources/lang/nb_NO/texts.php +++ b/resources/lang/nb_NO/texts.php @@ -697,9 +697,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/nl/texts.php b/resources/lang/nl/texts.php index 5118ac4fdd9a..27778af2b948 100644 --- a/resources/lang/nl/texts.php +++ b/resources/lang/nl/texts.php @@ -692,9 +692,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/pt_BR/texts.php b/resources/lang/pt_BR/texts.php index 0923299362e7..ea074e12d853 100644 --- a/resources/lang/pt_BR/texts.php +++ b/resources/lang/pt_BR/texts.php @@ -692,9 +692,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/sv/texts.php b/resources/lang/sv/texts.php index 4ac8dfb42977..295f596832d4 100644 --- a/resources/lang/sv/texts.php +++ b/resources/lang/sv/texts.php @@ -695,9 +695,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/views/accounts/details.blade.php b/resources/views/accounts/details.blade.php index 90475d384b75..89a2a179f94b 100644 --- a/resources/views/accounts/details.blade.php +++ b/resources/views/accounts/details.blade.php @@ -18,12 +18,12 @@ {{ Former::populate($account) }} @if ($showUser) - {{ Former::populateField('first_name', $account->users()->first()->first_name) }} - {{ Former::populateField('last_name', $account->users()->first()->last_name) }} - {{ Former::populateField('email', $account->users()->first()->email) }} - {{ Former::populateField('phone', $account->users()->first()->phone) }} + {{ Former::populateField('first_name', $primaryUser->first_name) }} + {{ Former::populateField('last_name', $primaryUser->last_name) }} + {{ Former::populateField('email', $primaryUser->email) }} + {{ Former::populateField('phone', $primaryUser->phone) }} @if (Utils::isNinja()) - {{ Former::populateField('dark_mode', intval($account->users()->first()->dark_mode)) }} + {{ Former::populateField('dark_mode', intval($primaryUser->dark_mode)) }} @endif @endif diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 76b315c84283..b3ac449db155 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -79,11 +79,11 @@ {!! Former::hidden('remember')->raw() !!}

-

{!! Button::success(trans(Input::get('new_account') && Utils::allowNewAccounts() ? 'texts.login' : 'texts.lets_go'))->large()->submit()->block() !!}

+

{!! Button::success(trans(Input::get('new_company') ? 'texts.login' : 'texts.lets_go'))->large()->submit()->block() !!}

- @if (Input::get('new_account') && Utils::allowNewAccounts()) + @if (Input::get('new_company') && Utils::allowNewAccounts())

- {{ trans('texts.or') }} -

-

{!! Button::primary(trans('texts.new_account'))->asLinkTo(URL::to('/invoice_now?new_account=true'))->large()->submit()->block() !!}

+

{!! Button::primary(trans('texts.new_company'))->asLinkTo(URL::to('/invoice_now?new_company=true&sign_up=true'))->large()->submit()->block() !!}

@endif diff --git a/resources/views/header.blade.php b/resources/views/header.blade.php index 64d1e6df225b..cc8a1f0eb6d5 100644 --- a/resources/views/header.blade.php +++ b/resources/views/header.blade.php @@ -427,7 +427,7 @@ @endif
  • @if (!session(SESSION_USER_ACCOUNTS) || count(session(SESSION_USER_ACCOUNTS)) < 5) -
  • {!! link_to('/login?new_account=true', trans('texts.add_account')) !!}
  • +
  • {!! link_to('/login?new_company=true', trans('texts.add_company')) !!}
  • @endif
  • {!! link_to('#', trans('texts.logout'), array('onclick'=>'logout()')) !!}
  • @@ -462,7 +462,9 @@
  • {{ trans('texts.no_items') }}
  • @else @foreach (Session::get(RECENTLY_VIEWED) as $link) -
  • {{ $link->name }}
  • + @if (property_exists($link, 'accountId') && $link->accountId == Auth::user()->account_id) +
  • {{ $link->name }}
  • + @endif @endforeach @endif diff --git a/resources/views/user_account.blade.php b/resources/views/user_account.blade.php index c3c2520aee0e..e9aad6d6abb0 100644 --- a/resources/views/user_account.blade.php +++ b/resources/views/user_account.blade.php @@ -6,7 +6,7 @@ @endif @if (isset($show_remove) && $show_remove) -
    +
    @endif @if (file_exists('logo/'.$account_key.'.jpg'))