Merge remote-tracking branch 'upstream/develop' into develop

This commit is contained in:
David Bomba 2016-11-03 19:40:25 +11:00
commit 293811d5ca
30 changed files with 262 additions and 205 deletions

View File

@ -10,6 +10,8 @@
## [Hosted](https://www.invoiceninja.com) | [Self-hosted](https://www.invoiceninja.org) ## [Hosted](https://www.invoiceninja.com) | [Self-hosted](https://www.invoiceninja.org)
**We're starting work on custom modules, join the discussion [here](https://github.com/invoiceninja/invoiceninja/issues/1131).**
All Pro and Enterprise features from our hosted app are included in both the [self-host zip](https://www.invoiceninja.com/self-host/) and the GitHub repository. All Pro and Enterprise features from our hosted app are included in both the [self-host zip](https://www.invoiceninja.com/self-host/) and the GitHub repository.
Our [iPhone app](https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=1072566815&mt=8) is now available, our Android app is up next... Our [iPhone app](https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=1072566815&mt=8) is now available, our Android app is up next...

View File

@ -429,6 +429,7 @@ class AccountController extends BaseController
'currencies' => Cache::get('currencies'), 'currencies' => Cache::get('currencies'),
'title' => trans('texts.localization'), 'title' => trans('texts.localization'),
'weekdays' => Utils::getTranslatedWeekdayNames(), 'weekdays' => Utils::getTranslatedWeekdayNames(),
'months' => Utils::getMonthOptions(),
]; ];
return View::make('accounts.localization', $data); return View::make('accounts.localization', $data);
@ -674,11 +675,9 @@ class AccountController extends BaseController
* @param $section * @param $section
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function doSection($section = ACCOUNT_COMPANY_DETAILS) public function doSection($section)
{ {
if ($section === ACCOUNT_COMPANY_DETAILS) { if ($section === ACCOUNT_LOCALIZATION) {
return AccountController::saveDetails();
} elseif ($section === ACCOUNT_LOCALIZATION) {
return AccountController::saveLocalization(); return AccountController::saveLocalization();
} elseif ($section == ACCOUNT_PAYMENTS) { } elseif ($section == ACCOUNT_PAYMENTS) {
return self::saveOnlinePayments(); return self::saveOnlinePayments();
@ -1225,6 +1224,7 @@ class AccountController extends BaseController
$account->military_time = Input::get('military_time') ? true : false; $account->military_time = Input::get('military_time') ? true : false;
$account->show_currency_code = Input::get('show_currency_code') ? true : false; $account->show_currency_code = Input::get('show_currency_code') ? true : false;
$account->start_of_week = Input::get('start_of_week') ? Input::get('start_of_week') : 0; $account->start_of_week = Input::get('start_of_week') ? Input::get('start_of_week') : 0;
$account->financial_year_start = Input::get('financial_year_start') ? Input::get('financial_year_start') : null;
$account->save(); $account->save();
event(new UserSettingsChanged()); event(new UserSettingsChanged());

View File

@ -211,6 +211,8 @@ class ClientPortalController extends BaseController
$client = $contact->client; $client = $contact->client;
$account = $client->account; $account = $client->account;
$account->loadLocalizationSettings($client);
$color = $account->primary_color ? $account->primary_color : '#0b4d78'; $color = $account->primary_color ? $account->primary_color : '#0b4d78';
$customer = false; $customer = false;
@ -277,6 +279,7 @@ class ClientPortalController extends BaseController
} }
$account = $contact->account; $account = $contact->account;
$account->loadLocalizationSettings($contact->client);
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
@ -304,6 +307,7 @@ class ClientPortalController extends BaseController
} }
$account = $contact->account; $account = $contact->account;
$account->loadLocalizationSettings($contact->client);
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
@ -350,12 +354,14 @@ class ClientPortalController extends BaseController
} }
$account = $contact->account; $account = $contact->account;
$account->loadLocalizationSettings($contact->client);
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
} }
$color = $account->primary_color ? $account->primary_color : '#0b4d78'; $color = $account->primary_color ? $account->primary_color : '#0b4d78';
$data = [ $data = [
'color' => $color, 'color' => $color,
'account' => $account, 'account' => $account,
@ -420,12 +426,14 @@ class ClientPortalController extends BaseController
} }
$account = $contact->account; $account = $contact->account;
$account->loadLocalizationSettings($contact->client);
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
} }
$color = $account->primary_color ? $account->primary_color : '#0b4d78'; $color = $account->primary_color ? $account->primary_color : '#0b4d78';
$data = [ $data = [
'color' => $color, 'color' => $color,
'account' => $account, 'account' => $account,
@ -455,12 +463,14 @@ class ClientPortalController extends BaseController
} }
$account = $contact->account; $account = $contact->account;
$account->loadLocalizationSettings($contact->client);
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
} }
$color = $account->primary_color ? $account->primary_color : '#0b4d78'; $color = $account->primary_color ? $account->primary_color : '#0b4d78';
$data = [ $data = [
'color' => $color, 'color' => $color,
'account' => $account, 'account' => $account,
@ -489,12 +499,14 @@ class ClientPortalController extends BaseController
} }
$account = $contact->account; $account = $contact->account;
$account->loadLocalizationSettings($contact->client);
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
} }
$color = $account->primary_color ? $account->primary_color : '#0b4d78'; $color = $account->primary_color ? $account->primary_color : '#0b4d78';
$data = [ $data = [
'color' => $color, 'color' => $color,
'account' => $account, 'account' => $account,

View File

@ -23,8 +23,8 @@ class DashboardApiController extends BaseAPIController
$dashboardRepo = $this->dashboardRepo; $dashboardRepo = $this->dashboardRepo;
$metrics = $dashboardRepo->totals($accountId, $userId, $viewAll); $metrics = $dashboardRepo->totals($accountId, $userId, $viewAll);
$paidToDate = $dashboardRepo->paidToDate($accountId, $userId, $viewAll); $paidToDate = $dashboardRepo->paidToDate($account, $userId, $viewAll);
$averageInvoice = $dashboardRepo->averages($accountId, $userId, $viewAll); $averageInvoice = $dashboardRepo->averages($account, $userId, $viewAll);
$balances = $dashboardRepo->balances($accountId, $userId, $viewAll); $balances = $dashboardRepo->balances($accountId, $userId, $viewAll);
$activities = $dashboardRepo->activities($accountId, $userId, $viewAll); $activities = $dashboardRepo->activities($accountId, $userId, $viewAll);
$pastDue = $dashboardRepo->pastDue($accountId, $userId, $viewAll); $pastDue = $dashboardRepo->pastDue($accountId, $userId, $viewAll);

View File

@ -33,9 +33,9 @@ class DashboardController extends BaseController
$dashboardRepo = $this->dashboardRepo; $dashboardRepo = $this->dashboardRepo;
$metrics = $dashboardRepo->totals($accountId, $userId, $viewAll); $metrics = $dashboardRepo->totals($accountId, $userId, $viewAll);
$paidToDate = $dashboardRepo->paidToDate($accountId, $userId, $viewAll); $paidToDate = $dashboardRepo->paidToDate($account, $userId, $viewAll);
$averageInvoice = $dashboardRepo->averages($accountId, $userId, $viewAll); $averageInvoice = $dashboardRepo->averages($account, $userId, $viewAll);
$balances = $dashboardRepo->balances($accountId, $userId, $viewAll); $balances = $dashboardRepo->balances($accountId, $userId, $viewAll);
$activities = $dashboardRepo->activities($accountId, $userId, $viewAll); $activities = $dashboardRepo->activities($accountId, $userId, $viewAll);
$pastDue = $dashboardRepo->pastDue($accountId, $userId, $viewAll); $pastDue = $dashboardRepo->pastDue($accountId, $userId, $viewAll);
$upcoming = $dashboardRepo->upcoming($accountId, $userId, $viewAll); $upcoming = $dashboardRepo->upcoming($accountId, $userId, $viewAll);

View File

@ -70,11 +70,13 @@ class OnlinePaymentController extends BaseController
]); ]);
} }
if ( ! floatval($invitation->invoice->balance)) { if ( ! $invitation->invoice->canBePaid()) {
return redirect()->to('view/' . $invitation->invitation_key); return redirect()->to('view/' . $invitation->invitation_key);
} }
$invitation = $invitation->load('invoice.client.account.account_gateways.gateway'); $invitation = $invitation->load('invoice.client.account.account_gateways.gateway');
$account = $invitation->account;
$account->loadLocalizationSettings($invitation->invoice->client);
if ( ! $gatewayTypeAlias) { if ( ! $gatewayTypeAlias) {
$gatewayTypeId = Session::get($invitation->id . 'gateway_type'); $gatewayTypeId = Session::get($invitation->id . 'gateway_type');
@ -84,7 +86,7 @@ class OnlinePaymentController extends BaseController
$gatewayTypeId = $gatewayTypeAlias; $gatewayTypeId = $gatewayTypeAlias;
} }
$paymentDriver = $invitation->account->paymentDriver($invitation, $gatewayTypeId); $paymentDriver = $account->paymentDriver($invitation, $gatewayTypeId);
try { try {
return $paymentDriver->startPurchase(Input::all(), $sourceId); return $paymentDriver->startPurchase(Input::all(), $sourceId);
@ -103,6 +105,10 @@ class OnlinePaymentController extends BaseController
$gatewayTypeId = Session::get($invitation->id . 'gateway_type'); $gatewayTypeId = Session::get($invitation->id . 'gateway_type');
$paymentDriver = $invitation->account->paymentDriver($invitation, $gatewayTypeId); $paymentDriver = $invitation->account->paymentDriver($invitation, $gatewayTypeId);
if ( ! $invitation->invoice->canBePaid()) {
return redirect()->to('view/' . $invitation->invitation_key);
}
try { try {
$paymentDriver->completeOnsitePurchase($request->all()); $paymentDriver->completeOnsitePurchase($request->all());

View File

@ -18,7 +18,6 @@ class Kernel extends HttpKernel {
'App\Http\Middleware\VerifyCsrfToken', 'App\Http\Middleware\VerifyCsrfToken',
'App\Http\Middleware\DuplicateSubmissionCheck', 'App\Http\Middleware\DuplicateSubmissionCheck',
'App\Http\Middleware\QueryLogging', 'App\Http\Middleware\QueryLogging',
'App\Http\Middleware\SessionDataCheckMiddleware',
'App\Http\Middleware\StartupCheck', 'App\Http\Middleware\StartupCheck',
]; ];

View File

@ -1,31 +0,0 @@
<?php namespace App\Http\Middleware;
use Closure;
use Auth;
use Session;
// https://arjunphp.com/laravel5-inactivity-idle-session-logout/
class SessionDataCheckMiddleware {
/**
* Check session data, if role is not valid logout the request
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$bag = Session::getMetadataBag();
$max = env('IDLE_TIMEOUT_MINUTES', 6 * 60) * 60; // minute to second conversion
$elapsed = time() - $bag->getLastUsed();
if ( ! $bag || $elapsed > $max) {
$request->session()->flush();
Auth::logout();
$request->session()->flash('warning', trans('texts.inactive_logout'));
}
return $next($request);
}
}

View File

@ -13,7 +13,7 @@ use Event;
use Schema; use Schema;
use App\Models\Language; use App\Models\Language;
use App\Models\InvoiceDesign; use App\Models\InvoiceDesign;
use App\Events\UserSettingsChanged; use App\Events\UserLoggedIn;
use App\Libraries\CurlUtils; use App\Libraries\CurlUtils;
/** /**
@ -118,7 +118,7 @@ class StartupCheck
// Make sure the account/user localization settings are in the session // Make sure the account/user localization settings are in the session
if (Auth::check() && !Session::has(SESSION_TIMEZONE)) { if (Auth::check() && !Session::has(SESSION_TIMEZONE)) {
Event::fire(new UserSettingsChanged()); Event::fire(new UserLoggedIn());
} }
// Check if the user is claiming a license (ie, additional invoices, white label, etc.) // Check if the user is claiming a license (ie, additional invoices, white label, etc.)

View File

@ -1,21 +1,21 @@
<?php <?php
class parseCSV { class parseCSV {
/* /*
Class: parseCSV v0.3.2 Class: parseCSV v0.3.2
http://code.google.com/p/parsecsv-for-php/ http://code.google.com/p/parsecsv-for-php/
Fully conforms to the specifications lined out on wikipedia: Fully conforms to the specifications lined out on wikipedia:
- http://en.wikipedia.org/wiki/Comma-separated_values - http://en.wikipedia.org/wiki/Comma-separated_values
Based on the concept of Ming Hong Ng's CsvFileParser class: Based on the concept of Ming Hong Ng's CsvFileParser class:
- http://minghong.blogspot.com/2006/07/csv-parser-for-php.html - http://minghong.blogspot.com/2006/07/csv-parser-for-php.html
Copyright (c) 2007 Jim Myhrberg (jim@zydev.info). Copyright (c) 2007 Jim Myhrberg (jim@zydev.info).
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
@ -35,9 +35,9 @@ class parseCSV {
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
Code Examples Code Examples
---------------- ----------------
# general usage # general usage
@ -74,7 +74,7 @@ class parseCSV {
$csv = new parseCSV(); $csv = new parseCSV();
$csv->output (true, 'movies.csv', $array); $csv->output (true, 'movies.csv', $array);
---------------- ----------------
*/ */
@ -83,87 +83,87 @@ class parseCSV {
* Configuration * Configuration
* - set these options with $object->var_name = 'value'; * - set these options with $object->var_name = 'value';
*/ */
# use first line/entry as field names # use first line/entry as field names
var $heading = true; var $heading = true;
# override field names # override field names
var $fields = []; var $fields = [];
# sort entries by this field # sort entries by this field
var $sort_by = null; var $sort_by = null;
var $sort_reverse = false; var $sort_reverse = false;
# delimiter (comma) and enclosure (double quote) # delimiter (comma) and enclosure (double quote)
var $delimiter = ','; var $delimiter = ',';
var $enclosure = '"'; var $enclosure = '"';
# basic SQL-like conditions for row matching # basic SQL-like conditions for row matching
var $conditions = null; var $conditions = null;
# number of rows to ignore from beginning of data # number of rows to ignore from beginning of data
var $offset = null; var $offset = null;
# limits the number of returned rows to specified amount # limits the number of returned rows to specified amount
var $limit = null; var $limit = null;
# number of rows to analyze when attempting to auto-detect delimiter # number of rows to analyze when attempting to auto-detect delimiter
var $auto_depth = 15; var $auto_depth = 15;
# characters to ignore when attempting to auto-detect delimiter # characters to ignore when attempting to auto-detect delimiter
var $auto_non_chars = "a-zA-Z0-9\n\r"; var $auto_non_chars = "a-zA-Z0-9\n\r";
# preferred delimiter characters, only used when all filtering method # preferred delimiter characters, only used when all filtering method
# returns multiple possible delimiters (happens very rarely) # returns multiple possible delimiters (happens very rarely)
var $auto_preferred = ",;\t.:|"; var $auto_preferred = ",;\t.:|";
# character encoding options # character encoding options
var $convert_encoding = false; var $convert_encoding = false;
var $input_encoding = 'ISO-8859-1'; var $input_encoding = 'ISO-8859-1';
var $output_encoding = 'ISO-8859-1'; var $output_encoding = 'ISO-8859-1';
# used by unparse(), save(), and output() functions # used by unparse(), save(), and output() functions
var $linefeed = "\r\n"; var $linefeed = "\r\n";
# only used by output() function # only used by output() function
var $output_delimiter = ','; var $output_delimiter = ',';
var $output_filename = 'data.csv'; var $output_filename = 'data.csv';
/** /**
* Internal variables * Internal variables
*/ */
# current file # current file
var $file; var $file;
# loaded file contents # loaded file contents
var $file_data; var $file_data;
# array of field values in data parsed # array of field values in data parsed
var $titles = []; var $titles = [];
# two dimentional array of CSV data # two dimentional array of CSV data
var $data = []; var $data = [];
/** /**
* Constructor * Constructor
* @param input CSV file or string * @param input CSV file or string
* @return nothing * @return nothing
*/ */
function parseCSV ($input = null, $offset = null, $limit = null, $conditions = null) { function __construct ($input = null, $offset = null, $limit = null, $conditions = null) {
if ( $offset !== null ) $this->offset = $offset; if ( $offset !== null ) $this->offset = $offset;
if ( $limit !== null ) $this->limit = $limit; if ( $limit !== null ) $this->limit = $limit;
if ( count($conditions) > 0 ) $this->conditions = $conditions; if ( count($conditions) > 0 ) $this->conditions = $conditions;
if ( !empty($input) ) $this->parse($input); if ( !empty($input) ) $this->parse($input);
} }
// ============================================== // ==============================================
// ----- [ Main Functions ] --------------------- // ----- [ Main Functions ] ---------------------
// ============================================== // ==============================================
/** /**
* Parse CSV file or string * Parse CSV file or string
* @param input CSV file or string * @param input CSV file or string
@ -184,7 +184,7 @@ class parseCSV {
} }
return true; return true;
} }
/** /**
* Save changes, or new file and/or data * Save changes, or new file and/or data
* @param file file to save to * @param file file to save to
@ -199,7 +199,7 @@ class parseCSV {
$is_php = ( preg_match('/\.php$/i', $file) ) ? true : false ; $is_php = ( preg_match('/\.php$/i', $file) ) ? true : false ;
return $this->_wfile($file, $this->unparse($data, $fields, $append, $is_php), $mode); return $this->_wfile($file, $this->unparse($data, $fields, $append, $is_php), $mode);
} }
/** /**
* Generate CSV based string for output * Generate CSV based string for output
* @param output if true, prints headers and strings to browser * @param output if true, prints headers and strings to browser
@ -220,7 +220,7 @@ class parseCSV {
} }
return $data; return $data;
} }
/** /**
* Convert character encoding * Convert character encoding
* @param input input character encoding, uses default if left blank * @param input input character encoding, uses default if left blank
@ -232,7 +232,7 @@ class parseCSV {
if ( $input !== null ) $this->input_encoding = $input; if ( $input !== null ) $this->input_encoding = $input;
if ( $output !== null ) $this->output_encoding = $output; if ( $output !== null ) $this->output_encoding = $output;
} }
/** /**
* Auto-Detect Delimiter: Find delimiter by analyzing a specific number of * Auto-Detect Delimiter: Find delimiter by analyzing a specific number of
* rows to determine most probable delimiter character * rows to determine most probable delimiter character
@ -244,13 +244,13 @@ class parseCSV {
* @return delimiter character * @return delimiter character
*/ */
function auto ($file = null, $parse = true, $search_depth = null, $preferred = null, $enclosure = null) { function auto ($file = null, $parse = true, $search_depth = null, $preferred = null, $enclosure = null) {
if ( $file === null ) $file = $this->file; if ( $file === null ) $file = $this->file;
if ( empty($search_depth) ) $search_depth = $this->auto_depth; if ( empty($search_depth) ) $search_depth = $this->auto_depth;
if ( $enclosure === null ) $enclosure = $this->enclosure; if ( $enclosure === null ) $enclosure = $this->enclosure;
if ( $preferred === null ) $preferred = $this->auto_preferred; if ( $preferred === null ) $preferred = $this->auto_preferred;
if ( empty($this->file_data) ) { if ( empty($this->file_data) ) {
if ( $this->_check_data($file) ) { if ( $this->_check_data($file) ) {
$data = &$this->file_data; $data = &$this->file_data;
@ -258,24 +258,24 @@ class parseCSV {
} else { } else {
$data = &$this->file_data; $data = &$this->file_data;
} }
$chars = []; $chars = [];
$strlen = strlen($data); $strlen = strlen($data);
$enclosed = false; $enclosed = false;
$n = 1; $n = 1;
$to_end = true; $to_end = true;
// walk specific depth finding posssible delimiter characters // walk specific depth finding posssible delimiter characters
for ( $i=0; $i < $strlen; $i++ ) { for ( $i=0; $i < $strlen; $i++ ) {
$ch = $data{$i}; $ch = $data{$i};
$nch = ( isset($data{$i+1}) ) ? $data{$i+1} : false ; $nch = ( isset($data{$i+1}) ) ? $data{$i+1} : false ;
$pch = ( isset($data{$i-1}) ) ? $data{$i-1} : false ; $pch = ( isset($data{$i-1}) ) ? $data{$i-1} : false ;
// open and closing quotes // open and closing quotes
if ( $ch == $enclosure && (!$enclosed || $nch != $enclosure) ) { if ( $ch == $enclosure && (!$enclosed || $nch != $enclosure) ) {
$enclosed = ( $enclosed ) ? false : true ; $enclosed = ( $enclosed ) ? false : true ;
// inline quotes // inline quotes
} elseif ( $ch == $enclosure && $enclosed ) { } elseif ( $ch == $enclosure && $enclosed ) {
$i++; $i++;
@ -287,7 +287,7 @@ class parseCSV {
} else { } else {
$n++; $n++;
} }
// count character // count character
} elseif (!$enclosed) { } elseif (!$enclosed) {
if ( !preg_match('/['.preg_quote($this->auto_non_chars, '/').']/i', $ch) ) { if ( !preg_match('/['.preg_quote($this->auto_non_chars, '/').']/i', $ch) ) {
@ -299,7 +299,7 @@ class parseCSV {
} }
} }
} }
// filtering // filtering
$depth = ( $to_end ) ? $n-1 : $n ; $depth = ( $to_end ) ? $n-1 : $n ;
$filtered = []; $filtered = [];
@ -308,24 +308,24 @@ class parseCSV {
$filtered[$match] = $char; $filtered[$match] = $char;
} }
} }
// capture most probable delimiter // capture most probable delimiter
ksort($filtered); ksort($filtered);
$delimiter = reset($filtered); $delimiter = reset($filtered);
$this->delimiter = $delimiter; $this->delimiter = $delimiter;
// parse data // parse data
if ( $parse ) $this->data = $this->parse_string(); if ( $parse ) $this->data = $this->parse_string();
return $delimiter; return $delimiter;
} }
// ============================================== // ==============================================
// ----- [ Core Functions ] --------------------- // ----- [ Core Functions ] ---------------------
// ============================================== // ==============================================
/** /**
* Read file to string and call parse_string() * Read file to string and call parse_string()
* @param file local CSV file * @param file local CSV file
@ -336,7 +336,7 @@ class parseCSV {
if ( empty($this->file_data) ) $this->load_data($file); if ( empty($this->file_data) ) $this->load_data($file);
return ( !empty($this->file_data) ) ? $this->parse_string() : false ; return ( !empty($this->file_data) ) ? $this->parse_string() : false ;
} }
/** /**
* Parse CSV strings to arrays * Parse CSV strings to arrays
* @param data CSV string * @param data CSV string
@ -348,7 +348,7 @@ class parseCSV {
$data = &$this->file_data; $data = &$this->file_data;
} else return false; } else return false;
} }
$rows = []; $rows = [];
$row = []; $row = [];
$row_count = 0; $row_count = 0;
@ -358,19 +358,19 @@ class parseCSV {
$enclosed = false; $enclosed = false;
$was_enclosed = false; $was_enclosed = false;
$strlen = strlen($data); $strlen = strlen($data);
// walk through each character // walk through each character
for ( $i=0; $i < $strlen; $i++ ) { for ( $i=0; $i < $strlen; $i++ ) {
$ch = $data{$i}; $ch = $data{$i};
$nch = ( isset($data{$i+1}) ) ? $data{$i+1} : false ; $nch = ( isset($data{$i+1}) ) ? $data{$i+1} : false ;
$pch = ( isset($data{$i-1}) ) ? $data{$i-1} : false ; $pch = ( isset($data{$i-1}) ) ? $data{$i-1} : false ;
// open and closing quotes // open and closing quotes
if ( $ch == $this->enclosure && (!$enclosed || $nch != $this->enclosure) ) { if ( $ch == $this->enclosure && (!$enclosed || $nch != $this->enclosure) ) {
$enclosed = ( $enclosed ) ? false : true ; $enclosed = ( $enclosed ) ? false : true ;
if ( $enclosed ) $was_enclosed = true; if ( $enclosed ) $was_enclosed = true;
// inline quotes // inline quotes
} elseif ( $ch == $this->enclosure && $enclosed ) { } elseif ( $ch == $this->enclosure && $enclosed ) {
$current .= $ch; $current .= $ch;
$i++; $i++;
@ -382,7 +382,7 @@ class parseCSV {
$row[$key] = $current; $row[$key] = $current;
$current = ''; $current = '';
$col++; $col++;
// end of row // end of row
if ( $ch == "\n" || $ch == "\r" ) { if ( $ch == "\n" || $ch == "\r" ) {
if ( $this->_validate_offset($row_count) && $this->_validate_row_conditions($row, $this->conditions) ) { if ( $this->_validate_offset($row_count) && $this->_validate_row_conditions($row, $this->conditions) ) {
@ -406,7 +406,7 @@ class parseCSV {
$i = $strlen; $i = $strlen;
} }
} }
// append character to current field // append character to current field
} else { } else {
$current .= $ch; $current .= $ch;
@ -421,7 +421,7 @@ class parseCSV {
} }
return $rows; return $rows;
} }
/** /**
* Create CSV data from array * Create CSV data from array
* @param data 2D array with data * @param data 2D array with data
@ -436,10 +436,10 @@ class parseCSV {
if ( !is_array($data) || empty($data) ) $data = &$this->data; if ( !is_array($data) || empty($data) ) $data = &$this->data;
if ( !is_array($fields) || empty($fields) ) $fields = &$this->titles; if ( !is_array($fields) || empty($fields) ) $fields = &$this->titles;
if ( $delimiter === null ) $delimiter = $this->delimiter; if ( $delimiter === null ) $delimiter = $this->delimiter;
$string = ( $is_php ) ? "<?php header('Status: 403'); die(' '); ?>".$this->linefeed : '' ; $string = ( $is_php ) ? "<?php header('Status: 403'); die(' '); ?>".$this->linefeed : '' ;
$entry = []; $entry = [];
// create heading // create heading
if ( $this->heading && !$append ) { if ( $this->heading && !$append ) {
foreach( $fields as $key => $value ) { foreach( $fields as $key => $value ) {
@ -448,7 +448,7 @@ class parseCSV {
$string .= implode($delimiter, $entry).$this->linefeed; $string .= implode($delimiter, $entry).$this->linefeed;
$entry = []; $entry = [];
} }
// create data // create data
foreach( $data as $key => $row ) { foreach( $data as $key => $row ) {
foreach( $row as $field => $value ) { foreach( $row as $field => $value ) {
@ -457,10 +457,10 @@ class parseCSV {
$string .= implode($delimiter, $entry).$this->linefeed; $string .= implode($delimiter, $entry).$this->linefeed;
$entry = []; $entry = [];
} }
return $string; return $string;
} }
/** /**
* Load local file or string * Load local file or string
* @param input local CSV file * @param input local CSV file
@ -488,16 +488,16 @@ class parseCSV {
} }
return false; return false;
} }
// ============================================== // ==============================================
// ----- [ Internal Functions ] ----------------- // ----- [ Internal Functions ] -----------------
// ============================================== // ==============================================
/** /**
* Validate a row against specified conditions * Validate a row against specified conditions
* @param row array with values from a row * @param row array with values from a row
* @param conditions specified conditions that the row must match * @param conditions specified conditions that the row must match
* @return true of false * @return true of false
*/ */
function _validate_row_conditions ($row = [], $conditions = null) { function _validate_row_conditions ($row = [], $conditions = null) {
@ -523,11 +523,11 @@ class parseCSV {
} }
return false; return false;
} }
/** /**
* Validate a row against a single condition * Validate a row against a single condition
* @param row array with values from a row * @param row array with values from a row
* @param condition specified condition that the row must match * @param condition specified condition that the row must match
* @return true of false * @return true of false
*/ */
function _validate_row_condition ($row, $condition) { function _validate_row_condition ($row, $condition) {
@ -583,7 +583,7 @@ class parseCSV {
} }
return '1'; return '1';
} }
/** /**
* Validates if the row is within the offset or not if sorting is disabled * Validates if the row is within the offset or not if sorting is disabled
* @param current_row the current row number being processed * @param current_row the current row number being processed
@ -593,7 +593,7 @@ class parseCSV {
if ( $this->sort_by === null && $this->offset !== null && $current_row < $this->offset ) return false; if ( $this->sort_by === null && $this->offset !== null && $current_row < $this->offset ) return false;
return true; return true;
} }
/** /**
* Enclose values if needed * Enclose values if needed
* - only used by unparse() * - only used by unparse()
@ -611,7 +611,7 @@ class parseCSV {
} }
return $value; return $value;
} }
/** /**
* Check file data * Check file data
* @param file local filename * @param file local filename
@ -624,8 +624,8 @@ class parseCSV {
} }
return true; return true;
} }
/** /**
* Check if passed info might be delimiter * Check if passed info might be delimiter
* - only used by find_delimiter() * - only used by find_delimiter()
@ -656,7 +656,7 @@ class parseCSV {
} else return false; } else return false;
} }
} }
/** /**
* Read local file * Read local file
* @param file local filename * @param file local filename
@ -689,7 +689,7 @@ class parseCSV {
} }
return false; return false;
} }
} }
?> ?>

View File

@ -22,6 +22,9 @@ class Utils
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",
]; ];
public static $months = [
'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december',
];
public static function isRegistered() public static function isRegistered()
{ {
@ -92,6 +95,15 @@ class Utils
return Utils::getResllerType() ? true : false; return Utils::getResllerType() ? true : false;
} }
public static function isWhiteLabel()
{
if (Utils::isNinjaProd()) {
return false;
}
return \App\Models\Account::first()->hasFeature(FEATURE_WHITE_LABEL);
}
public static function getResllerType() public static function getResllerType()
{ {
return isset($_ENV['RESELLER_TYPE']) ? $_ENV['RESELLER_TYPE'] : false; return isset($_ENV['RESELLER_TYPE']) ? $_ENV['RESELLER_TYPE'] : false;
@ -151,6 +163,11 @@ class Utils
return Auth::check() && Auth::user()->isTrial(); return Auth::check() && Auth::user()->isTrial();
} }
public static function isPaidPro()
{
return static::isPro() && ! static::isTrial();
}
public static function isEnglish() public static function isEnglish()
{ {
return App::getLocale() == 'en'; return App::getLocale() == 'en';
@ -641,11 +658,22 @@ class Utils
} }
} }
public static function getMonthOptions()
{
$months = [];
for ($i=1; $i<=count(static::$months); $i++) {
$month = static::$months[$i-1];
$number = $i < 10 ? '0' . $i : $i;
$months["2000-{$number}-01"] = trans("texts.{$month}");
}
return $months;
}
private static function getMonth($offset) private static function getMonth($offset)
{ {
$months = ['january', 'february', 'march', 'april', 'may', 'june', $months = static::$months;
'july', 'august', 'september', 'october', 'november', 'december', ];
$month = intval(date('n')) - 1; $month = intval(date('n')) - 1;
$month += $offset; $month += $offset;

View File

@ -69,6 +69,7 @@ class Account extends Eloquent
'enable_second_tax_rate', 'enable_second_tax_rate',
'include_item_taxes_inline', 'include_item_taxes_inline',
'start_of_week', 'start_of_week',
'financial_year_start',
]; ];
/** /**

View File

@ -345,7 +345,7 @@ class Client extends EntityModel
$contact = $this->contacts[0]; $contact = $this->contacts[0];
return $contact->getDisplayName() ?: trans('texts.unnamed_client'); return $contact->getDisplayName();
} }
/** /**

View File

@ -514,6 +514,11 @@ class Invoice extends EntityModel implements BalanceAffecting
return storage_path() . '/pdfcache/cache-' . $this->id . '.pdf'; return storage_path() . '/pdfcache/cache-' . $this->id . '.pdf';
} }
public function canBePaid()
{
return floatval($this->balance) > 0 && ! $this->is_deleted;
}
/** /**
* @param $invoice * @param $invoice
* @return string * @return string

View File

@ -175,29 +175,39 @@ class DashboardRepository
return $metrics->groupBy('accounts.id')->first(); return $metrics->groupBy('accounts.id')->first();
} }
public function paidToDate($accountId, $userId, $viewAll) public function paidToDate($account, $userId, $viewAll)
{ {
$accountId = $account->id;
$select = DB::raw( $select = DB::raw(
'SUM('.DB::getQueryGrammar()->wrap('clients.paid_to_date', true).') as value,' 'SUM('.DB::getQueryGrammar()->wrap('payments.amount', true).' - '.DB::getQueryGrammar()->wrap('payments.refunded', true).') as value,'
.DB::getQueryGrammar()->wrap('clients.currency_id', true).' as currency_id' .DB::getQueryGrammar()->wrap('clients.currency_id', true).' as currency_id'
); );
$paidToDate = DB::table('accounts') $paidToDate = DB::table('payments')
->select($select) ->select($select)
->leftJoin('clients', 'accounts.id', '=', 'clients.account_id') ->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id')
->where('accounts.id', '=', $accountId) ->leftJoin('clients', 'clients.id', '=', 'invoices.client_id')
->where('clients.is_deleted', '=', false); ->where('payments.account_id', '=', $accountId)
->where('clients.is_deleted', '=', false)
->where('invoices.is_deleted', '=', false)
->whereNotIn('payments.payment_status_id', [PAYMENT_STATUS_VOIDED, PAYMENT_STATUS_FAILED]);
if (!$viewAll){ if (!$viewAll){
$paidToDate = $paidToDate->where('clients.user_id', '=', $userId); $paidToDate->where('invoices.user_id', '=', $userId);
} }
return $paidToDate->groupBy('accounts.id') if ($account->financial_year_start) {
->groupBy(DB::raw('CASE WHEN '.DB::getQueryGrammar()->wrap('clients.currency_id', true).' IS NULL THEN CASE WHEN '.DB::getQueryGrammar()->wrap('accounts.currency_id', true).' IS NULL THEN 1 ELSE '.DB::getQueryGrammar()->wrap('accounts.currency_id', true).' END ELSE '.DB::getQueryGrammar()->wrap('clients.currency_id', true).' END')) $yearStart = str_replace('2000', date('Y'), $account->financial_year_start);
$paidToDate->where('payments.payment_date', '>=', $yearStart);
}
return $paidToDate->groupBy('payments.account_id')
->groupBy(DB::raw('CASE WHEN '.DB::getQueryGrammar()->wrap('clients.currency_id', true).' IS NULL THEN '.($account->currency_id ?: DEFAULT_CURRENCY).' ELSE '.DB::getQueryGrammar()->wrap('clients.currency_id', true).' END'))
->get(); ->get();
} }
public function averages($accountId, $userId, $viewAll) public function averages($account, $userId, $viewAll)
{ {
$accountId = $account->id;
$select = DB::raw( $select = DB::raw(
'AVG('.DB::getQueryGrammar()->wrap('invoices.amount', true).') as invoice_avg, ' 'AVG('.DB::getQueryGrammar()->wrap('invoices.amount', true).') as invoice_avg, '
.DB::getQueryGrammar()->wrap('clients.currency_id', true).' as currency_id' .DB::getQueryGrammar()->wrap('clients.currency_id', true).' as currency_id'
@ -213,7 +223,12 @@ class DashboardRepository
->where('invoices.is_recurring', '=', false); ->where('invoices.is_recurring', '=', false);
if (!$viewAll){ if (!$viewAll){
$averageInvoice = $averageInvoice->where('invoices.user_id', '=', $userId); $averageInvoice->where('invoices.user_id', '=', $userId);
}
if ($account->financial_year_start) {
$yearStart = str_replace('2000', date('Y'), $account->financial_year_start);
$averageInvoice->where('invoices.invoice_date', '>=', $yearStart);
} }
return $averageInvoice->groupBy('accounts.id') return $averageInvoice->groupBy('accounts.id')
@ -252,7 +267,7 @@ class DashboardRepository
} }
return $activities->orderBy('activities.created_at', 'desc') return $activities->orderBy('activities.created_at', 'desc')
->with('client.contacts', 'user', 'invoice', 'payment', 'credit', 'account', 'task', 'expense') ->with('client.contacts', 'user', 'invoice', 'payment', 'credit', 'account', 'task', 'expense', 'contact')
->take(50) ->take(50)
->get(); ->get();
} }

View File

@ -86,11 +86,16 @@ class InvoiceService extends BaseService
$sendInvoiceIds = []; $sendInvoiceIds = [];
foreach ($client->contacts as $contact) { foreach ($client->contacts as $contact) {
if ($contact->send_invoice || count($client->contacts) == 1) { if ($contact->send_invoice) {
$sendInvoiceIds[] = $contact->id; $sendInvoiceIds[] = $contact->id;
} }
} }
// if no contacts are selected auto-select the first to enusre there's an invitation
if ( ! count($sendInvoiceIds)) {
$sendInvoiceIds[] = $client->contacts[0]->id;
}
foreach ($client->contacts as $contact) { foreach ($client->contacts as $contact) {
$invitation = Invitation::scope()->whereContactId($contact->id)->whereInvoiceId($invoice->id)->first(); $invitation = Invitation::scope()->whereContactId($contact->id)->whereInvoiceId($invoice->id)->first();

View File

@ -77,7 +77,7 @@
"gatepay/FedACHdir": "dev-master@dev", "gatepay/FedACHdir": "dev-master@dev",
"websight/l5-google-cloud-storage": "^1.0", "websight/l5-google-cloud-storage": "^1.0",
"wepay/php-sdk": "^0.2", "wepay/php-sdk": "^0.2",
"collizo4sky/omnipay-wepay": "dev-additional-calls", "collizo4sky/omnipay-wepay": "dev-address-fix",
"barryvdh/laravel-ide-helper": "~2.2", "barryvdh/laravel-ide-helper": "~2.2",
"barryvdh/laravel-debugbar": "~2.2", "barryvdh/laravel-debugbar": "~2.2",
"fzaninotto/faker": "^1.5", "fzaninotto/faker": "^1.5",

39
composer.lock generated
View File

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "f61ec0361b0757ca0cade78837862d39", "hash": "cf642e3384eec7504bcdace749d2bb88",
"content-hash": "37549f849d74405b68eb7e2df64dfb43", "content-hash": "c0a5b571bc2305c4b0d9eae18bf5011b",
"packages": [ "packages": [
{ {
"name": "agmscode/omnipay-agms", "name": "agmscode/omnipay-agms",
@ -1081,16 +1081,16 @@
}, },
{ {
"name": "collizo4sky/omnipay-wepay", "name": "collizo4sky/omnipay-wepay",
"version": "dev-additional-calls", "version": "dev-address-fix",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/hillelcoren/omnipay-wepay.git", "url": "https://github.com/hillelcoren/omnipay-wepay.git",
"reference": "a341b9997d71803d0f774d86908cb49a8bc4c405" "reference": "916785146c5433e9216f295d09d1cbcec2fdf33a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/hillelcoren/omnipay-wepay/zipball/a341b9997d71803d0f774d86908cb49a8bc4c405", "url": "https://api.github.com/repos/hillelcoren/omnipay-wepay/zipball/916785146c5433e9216f295d09d1cbcec2fdf33a",
"reference": "a341b9997d71803d0f774d86908cb49a8bc4c405", "reference": "916785146c5433e9216f295d09d1cbcec2fdf33a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1120,9 +1120,9 @@
"wepay" "wepay"
], ],
"support": { "support": {
"source": "https://github.com/sometechie/omnipay-wepay/tree/additional-calls" "source": "https://github.com/hillelcoren/omnipay-wepay/tree/address-fix"
}, },
"time": "2016-05-25 19:18:42" "time": "2016-11-01 10:54:54"
}, },
{ {
"name": "container-interop/container-interop", "name": "container-interop/container-interop",
@ -2184,7 +2184,7 @@
"shasum": null "shasum": null
}, },
"type": "library", "type": "library",
"time": "2016-06-03 12:00:26" "time": "2016-10-12 12:00:38"
}, },
{ {
"name": "google/apiclient", "name": "google/apiclient",
@ -3091,6 +3091,7 @@
"purchase", "purchase",
"wechat" "wechat"
], ],
"abandoned": "lokielse/omnipay-wechatpay",
"time": "2016-05-10 08:43:41" "time": "2016-05-10 08:43:41"
}, },
{ {
@ -7211,16 +7212,16 @@
}, },
{ {
"name": "symfony/event-dispatcher", "name": "symfony/event-dispatcher",
"version": "v2.8.9", "version": "v2.8.13",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/event-dispatcher.git", "url": "https://github.com/symfony/event-dispatcher.git",
"reference": "889983a79a043dfda68f38c38b6dba092dd49cd8" "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/889983a79a043dfda68f38c38b6dba092dd49cd8", "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/25c576abd4e0f212e678fe8b2bd9a9a98c7ea934",
"reference": "889983a79a043dfda68f38c38b6dba092dd49cd8", "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7267,7 +7268,7 @@
], ],
"description": "Symfony EventDispatcher Component", "description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2016-07-28 16:56:28" "time": "2016-10-13 01:43:15"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
@ -7320,16 +7321,16 @@
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v2.8.9", "version": "v2.8.13",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "f20bea598906c990eebe3c70a63ca5ed18cdbc11" "reference": "a6e6c34d337f3c74c39b29c5f54d33023de8897c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/f20bea598906c990eebe3c70a63ca5ed18cdbc11", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a6e6c34d337f3c74c39b29c5f54d33023de8897c",
"reference": "f20bea598906c990eebe3c70a63ca5ed18cdbc11", "reference": "a6e6c34d337f3c74c39b29c5f54d33023de8897c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7371,7 +7372,7 @@
], ],
"description": "Symfony HttpFoundation Component", "description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2016-07-30 07:20:35" "time": "2016-10-24 15:52:36"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -534,7 +534,7 @@ NINJA.subtotals = function(invoice, hideBalance)
} }
var paid = invoice.amount - invoice.balance; var paid = invoice.amount - invoice.balance;
if (invoice.account.hide_paid_to_date != '1' || paid) { if (!invoice.is_quote && (invoice.account.hide_paid_to_date != '1' || paid)) {
data.push([{text:invoiceLabels.paid_to_date, style: ['subtotalsLabel', 'paidToDateLabel']}, {text:formatMoneyInvoice(paid, invoice), style: ['subtotals', 'paidToDate']}]); data.push([{text:invoiceLabels.paid_to_date, style: ['subtotalsLabel', 'paidToDateLabel']}, {text:formatMoneyInvoice(paid, invoice), style: ['subtotals', 'paidToDate']}]);
} }
@ -542,7 +542,7 @@ NINJA.subtotals = function(invoice, hideBalance)
if (!hideBalance || isPartial) { if (!hideBalance || isPartial) {
data.push([ data.push([
{ text: invoiceLabels.balance_due, style: ['subtotalsLabel', isPartial ? '' : 'balanceDueLabel'] }, { text: invoice.is_quote ? invoiceLabels.total : invoiceLabels.balance_due, style: ['subtotalsLabel', isPartial ? '' : 'balanceDueLabel'] },
{ text: formatMoneyInvoice(invoice.total_amount, invoice), style: ['subtotals', isPartial ? '' : 'balanceDue'] } { text: formatMoneyInvoice(invoice.total_amount, invoice), style: ['subtotals', isPartial ? '' : 'balanceDue'] }
]); ]);
} }
@ -562,7 +562,7 @@ NINJA.subtotals = function(invoice, hideBalance)
NINJA.subtotalsBalance = function(invoice) { NINJA.subtotalsBalance = function(invoice) {
var isPartial = NINJA.parseFloat(invoice.partial); var isPartial = NINJA.parseFloat(invoice.partial);
return [[ return [[
{text: isPartial ? invoiceLabels.partial_due : invoiceLabels.balance_due, style:['subtotalsLabel', 'balanceDueLabel']}, {text: isPartial ? invoiceLabels.partial_due : (invoice.is_quote ? invoiceLabels.total : invoiceLabels.balance_due), style:['subtotalsLabel', 'balanceDueLabel']},
{text: formatMoneyInvoice(invoice.balance_amount, invoice), style:['subtotals', 'balanceDue']} {text: formatMoneyInvoice(invoice.balance_amount, invoice), style:['subtotals', 'balanceDue']}
]]; ]];
} }
@ -667,7 +667,7 @@ NINJA.renderInvoiceField = function(invoice, field) {
} }
} else if (field == 'invoice.balance_due') { } else if (field == 'invoice.balance_due') {
return [ return [
{text: invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, {text: invoice.is_quote ? invoiceLabels.total : invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']},
{text: formatMoneyInvoice(invoice.total_amount, invoice), style: ['invoiceDetailBalanceDue']} {text: formatMoneyInvoice(invoice.total_amount, invoice), style: ['invoiceDetailBalanceDue']}
]; ];
} else if (field == invoice.partial_due) { } else if (field == invoice.partial_due) {

View File

@ -1369,7 +1369,7 @@ $LANG = array(
'failed_remove_payment_method' => 'Failed to remove the payment method', 'failed_remove_payment_method' => 'Failed to remove the payment method',
'gateway_exists' => 'This gateway already exists', 'gateway_exists' => 'This gateway already exists',
'manual_entry' => 'Manual entry', 'manual_entry' => 'Manual entry',
'start_of_week' => 'First day of the week', 'start_of_week' => 'First Day of the Week',
// Frequencies // Frequencies
'freq_weekly' => 'Weekly', 'freq_weekly' => 'Weekly',
@ -2174,6 +2174,7 @@ $LANG = array(
'invalid_white_label_license' => 'The white label license is not valid', 'invalid_white_label_license' => 'The white label license is not valid',
'created_by' => 'Created by :name', 'created_by' => 'Created by :name',
'modules' => 'Modules', 'modules' => 'Modules',
'financial_year_start' => 'First Month of the Year',
); );

View File

@ -185,7 +185,6 @@
<script> <script>
var products = {!! $products !!}; var products = {!! $products !!};
console.log(products);
$(function() { $(function() {
var $productSelect = $('select#product'); var $productSelect = $('select#product');

View File

@ -42,7 +42,7 @@
{!! Former::select('language_id')->addOption('','') {!! Former::select('language_id')->addOption('','')
->fromQuery($languages, 'name', 'id') ->fromQuery($languages, 'name', 'id')
->help(trans('texts.translate_app', ['link' => link_to(TRANSIFEX_URL, 'Transifex.com', ['target' => '_blank'])])) !!} ->help(trans('texts.translate_app', ['link' => link_to(TRANSIFEX_URL, 'Transifex.com', ['target' => '_blank'])])) !!}
<br/> <br/>&nbsp;<br/>
{!! Former::select('timezone_id')->addOption('','') {!! Former::select('timezone_id')->addOption('','')
->fromQuery($timezones, 'location', 'id') !!} ->fromQuery($timezones, 'location', 'id') !!}
@ -50,9 +50,16 @@
->fromQuery($dateFormats) !!} ->fromQuery($dateFormats) !!}
{!! Former::select('datetime_format_id')->addOption('','') {!! Former::select('datetime_format_id')->addOption('','')
->fromQuery($datetimeFormats) !!} ->fromQuery($datetimeFormats) !!}
{!! Former::checkbox('military_time')->text(trans('texts.enable')) !!}
<br/>&nbsp;<br/>
{!! Former::select('start_of_week')->addOption('','') {!! Former::select('start_of_week')->addOption('','')
->fromQuery($weekdays) !!} ->fromQuery($weekdays) !!}
{!! Former::checkbox('military_time')->text(trans('texts.enable')) !!} {!! Former::select('financial_year_start')
->addOption('','')
->options($months) !!}
</div> </div>
</div> </div>

View File

@ -16,7 +16,7 @@
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading" style="color:white"> <div class="panel-heading" style="color:white">
{{ trans("texts.{$type}") }} {{ trans("texts.{$type}") }}
@if ($type === ADVANCED_SETTINGS && !Utils::isPro()) @if ($type === ADVANCED_SETTINGS && ! Utils::isPaidPro())
<sup>{{ strtoupper(trans('texts.pro')) }}</sup> <sup>{{ strtoupper(trans('texts.pro')) }}</sup>
@endif @endif
</div> </div>

View File

@ -17,6 +17,7 @@
} }
.modal-header h4 { .modal-header h4 {
margin:0; margin:0;
color:#fff;
} }
.modal-header img { .modal-header img {
float: left; float: left;
@ -89,10 +90,14 @@
{{ Former::populateField('remember', 'true') }} {{ Former::populateField('remember', 'true') }}
<div class="modal-header"> <div class="modal-header">
<a href="{{ NINJA_WEB_URL }}" target="_blank"> @if (Utils::isWhiteLabel())
<img src="{{ asset('images/icon-login.png') }}" /> <h4>{{ trans('texts.account_login') }}</h4>
<h4>Invoice Ninja | {{ trans('texts.account_login') }}</h4> @else
</a> <a href="{{ NINJA_WEB_URL }}" target="_blank">
<img src="{{ asset('images/icon-login.png') }}" />
<h4>Invoice Ninja | {{ trans('texts.account_login') }}</h4>
</a>
@endif
</div> </div>
<div class="inner"> <div class="inner">
<p> <p>

View File

@ -76,8 +76,15 @@
{!! Former::open('recover_password')->rules(['email' => 'required|email'])->addClass('form-signin') !!} {!! Former::open('recover_password')->rules(['email' => 'required|email'])->addClass('form-signin') !!}
<div class="modal-header"> <div class="modal-header">
<img src="{{ asset('images/icon-login.png') }}" /> @if (Utils::isWhiteLabel())
<h4>Invoice Ninja | {{ trans('texts.password_recovery') }}</h4></div> <h4>{{ trans('texts.password_recovery') }}</h4>
@else
<a href="{{ NINJA_WEB_URL }}" target="_blank">
<img src="{{ asset('images/icon-login.png') }}" />
</a>
<h4>Invoice Ninja | {{ trans('texts.password_recovery') }}</h4>
@endif
</div>
<div class="inner"> <div class="inner">
<p> <p>

View File

@ -62,18 +62,11 @@
<div class="container"> <div class="container">
<div class="form-signin"> <div class="form-signin">
<div class="modal-header"> <div class="modal-header">
@if (!isset($account) || !$account->hasFeature(FEATURE_WHITE_LABEL)) <h4>{{ trans('texts.session_expired') }}</h4>
<a href="{{ NINJA_WEB_URL }}" target="_blank">
<img src="{{ asset('images/icon-login.png') }}" />
<h4>Invoice Ninja | {{ trans('texts.client_session_expired') }}</h4>
</a>
@else
<h4>{{ trans('texts.session_expired') }}</h4>
@endif
</div> </div>
<div class="inner"> <div class="inner">
<div class="alert alert-info">{{ trans('texts.client_session_expired_message') }}</div> <div class="alert alert-info">{{ trans('texts.client_session_expired_message') }}</div>
</div> </div>
</div> </div>
</div> </div>
@endsection @endsection

View File

@ -341,11 +341,11 @@
<div class="tab-content"> <div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="notes" style="padding-bottom:44px"> <div role="tabpanel" class="tab-pane active" id="notes" style="padding-bottom:44px">
{!! Former::textarea('public_notes')->data_bind("value: public_notes, valueUpdate: 'afterkeydown'") {!! Former::textarea('public_notes')->data_bind("value: public_notes, valueUpdate: 'afterkeydown'")
->label(null)->style('resize: none; width: 500px;')->rows(4) !!} ->label(null)->style('width: 500px;')->rows(4) !!}
</div> </div>
<div role="tabpanel" class="tab-pane" id="terms"> <div role="tabpanel" class="tab-pane" id="terms">
{!! Former::textarea('terms')->data_bind("value:terms, placeholder: terms_placeholder, valueUpdate: 'afterkeydown'") {!! Former::textarea('terms')->data_bind("value:terms, placeholder: terms_placeholder, valueUpdate: 'afterkeydown'")
->label(false)->style('resize: none; width: 500px')->rows(4) ->label(false)->style('width: 500px')->rows(4)
->help('<div class="checkbox"> ->help('<div class="checkbox">
<label> <label>
<input name="set_default_terms" type="checkbox" style="width: 24px" data-bind="checked: set_default_terms"/>'.trans('texts.save_as_default_terms').' <input name="set_default_terms" type="checkbox" style="width: 24px" data-bind="checked: set_default_terms"/>'.trans('texts.save_as_default_terms').'
@ -357,7 +357,7 @@
</div> </div>
<div role="tabpanel" class="tab-pane" id="footer"> <div role="tabpanel" class="tab-pane" id="footer">
{!! Former::textarea('invoice_footer')->data_bind("value:invoice_footer, placeholder: footer_placeholder, valueUpdate: 'afterkeydown'") {!! Former::textarea('invoice_footer')->data_bind("value:invoice_footer, placeholder: footer_placeholder, valueUpdate: 'afterkeydown'")
->label(false)->style('resize: none; width: 500px')->rows(4) ->label(false)->style('width: 500px')->rows(4)
->help('<div class="checkbox"> ->help('<div class="checkbox">
<label> <label>
<input name="set_default_footer" type="checkbox" style="width: 24px" data-bind="checked: set_default_footer"/>'.trans('texts.save_as_default_footer').' <input name="set_default_footer" type="checkbox" style="width: 24px" data-bind="checked: set_default_footer"/>'.trans('texts.save_as_default_footer').'
@ -563,7 +563,14 @@
</div> </div>
<p>&nbsp;</p> <p>&nbsp;</p>
@include('invoices.pdf', ['account' => Auth::user()->account]) @if (Auth::user()->account->live_preview))
@include('invoices.pdf', ['account' => Auth::user()->account])
@else
<script type="text/javascript">
var invoiceLabels = {!! json_encode($account->getInvoiceLabels()) !!};
function refreshPDF() {}
</script>
@endif
@if (!Auth::user()->account->isPro()) @if (!Auth::user()->account->isPro())
<div style="font-size:larger"> <div style="font-size:larger">
@ -1118,7 +1125,7 @@
refreshPDF(true); refreshPDF(true);
}); });
$('textarea').on('keyup focus', function(e) { $('textarea.word-wrap').on('keyup focus', function(e) {
$(this).height(0).height(this.scrollHeight-18); $(this).height(0).height(this.scrollHeight-18);
}); });
@ -1167,11 +1174,6 @@
window.generatedPDF = false; window.generatedPDF = false;
function getPDFString(cb, force) { function getPDFString(cb, force) {
@if (!$account->live_preview)
if (window.generatedPDF) {
return;
}
@endif
var invoice = createInvoiceModel(); var invoice = createInvoiceModel();
var design = getDesignJavascript(); var design = getDesignJavascript();
if (!design) return; if (!design) return;

View File

@ -58,7 +58,7 @@
"type": "rect", "type": "rect",
"x": 0, "x": 0,
"y": 0, "y": 0,
"w": 515, "w": 532,
"h": 26, "h": 26,
"r": 0, "r": 0,
"lineWidth": 1, "lineWidth": 1,
@ -260,4 +260,4 @@
} }
}, },
"pageMargins": [40, 120, 40, 50] "pageMargins": [40, 120, 40, 50]
} }