mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Fixed money format in PDF for EU
This commit is contained in:
parent
6b063abe9a
commit
4268c18f8a
@ -1,34 +1,51 @@
|
|||||||
<?php namespace App\Console;
|
<?php namespace app\Console;
|
||||||
|
|
||||||
|
use Utils;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
|
|
||||||
class Kernel extends ConsoleKernel {
|
class Kernel extends ConsoleKernel
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* The Artisan commands provided by your application.
|
* The Artisan commands provided by your application.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $commands = [
|
protected $commands = [
|
||||||
'App\Console\Commands\SendRecurringInvoices',
|
'App\Console\Commands\SendRecurringInvoices',
|
||||||
'App\Console\Commands\CreateRandomData',
|
'App\Console\Commands\CreateRandomData',
|
||||||
'App\Console\Commands\ResetData',
|
'App\Console\Commands\ResetData',
|
||||||
'App\Console\Commands\CheckData',
|
'App\Console\Commands\CheckData',
|
||||||
'App\Console\Commands\SendRenewalInvoices',
|
'App\Console\Commands\SendRenewalInvoices',
|
||||||
'App\Console\Commands\SendReminders',
|
'App\Console\Commands\SendReminders',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the application's command schedule.
|
* Define the application's command schedule.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function schedule(Schedule $schedule)
|
protected function schedule(Schedule $schedule)
|
||||||
{
|
{
|
||||||
// $schedule->command('inspire')
|
$logFile = storage_path() . '/logs/cron.log';
|
||||||
// ->hourly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
$schedule
|
||||||
|
->command('ninja:send-invoices --force')
|
||||||
|
->sendOutputTo($logFile)
|
||||||
|
->withoutOverlapping()
|
||||||
|
->hourly();
|
||||||
|
|
||||||
|
$schedule
|
||||||
|
->command('ninja:send-reminders --force')
|
||||||
|
->sendOutputTo($logFile)
|
||||||
|
->daily();
|
||||||
|
|
||||||
|
if (Utils::isNinja()) {
|
||||||
|
$schedule
|
||||||
|
->command('ninja:send-renewals --force')
|
||||||
|
->sendOutputTo($logFile)
|
||||||
|
->daily();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
21
app/Events/UserSignedUp.php
Normal file
21
app/Events/UserSignedUp.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php namespace App\Events;
|
||||||
|
|
||||||
|
use App\Events\Event;
|
||||||
|
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class UserSignedUp extends Event {
|
||||||
|
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -27,11 +27,13 @@ class Handler extends ExceptionHandler {
|
|||||||
*/
|
*/
|
||||||
public function report(Exception $e)
|
public function report(Exception $e)
|
||||||
{
|
{
|
||||||
Utils::logError(Utils::getErrorString($e));
|
if (Utils::isNinja()) {
|
||||||
return false;
|
Utils::logError(Utils::getErrorString($e));
|
||||||
|
return false;
|
||||||
//return parent::report($e);
|
} else {
|
||||||
}
|
return parent::report($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render an exception into an HTTP response.
|
* Render an exception into an HTTP response.
|
||||||
@ -42,7 +44,6 @@ class Handler extends ExceptionHandler {
|
|||||||
*/
|
*/
|
||||||
public function render($request, Exception $e)
|
public function render($request, Exception $e)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ($e instanceof ModelNotFoundException) {
|
if ($e instanceof ModelNotFoundException) {
|
||||||
return Redirect::to('/');
|
return Redirect::to('/');
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ use App\Models\InvoiceDesign;
|
|||||||
use App\Ninja\Repositories\AccountRepository;
|
use App\Ninja\Repositories\AccountRepository;
|
||||||
use App\Ninja\Mailers\UserMailer;
|
use App\Ninja\Mailers\UserMailer;
|
||||||
use App\Ninja\Mailers\ContactMailer;
|
use App\Ninja\Mailers\ContactMailer;
|
||||||
|
use App\Events\UserSignedUp;
|
||||||
use App\Events\UserLoggedIn;
|
use App\Events\UserLoggedIn;
|
||||||
use App\Events\UserSettingsChanged;
|
use App\Events\UserSettingsChanged;
|
||||||
|
|
||||||
@ -109,7 +110,8 @@ class AccountController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
Auth::login($user, true);
|
Auth::login($user, true);
|
||||||
Event::fire(new UserLoggedIn());
|
event(new UserSignedUp());
|
||||||
|
event(new UserLoggedIn());
|
||||||
|
|
||||||
$redirectTo = Input::get('redirect_to', 'invoices/create');
|
$redirectTo = Input::get('redirect_to', 'invoices/create');
|
||||||
return Redirect::to($redirectTo)->with('sign_up', Input::get('sign_up'));
|
return Redirect::to($redirectTo)->with('sign_up', Input::get('sign_up'));
|
||||||
@ -151,7 +153,7 @@ class AccountController extends BaseController
|
|||||||
public function showSection($section = ACCOUNT_DETAILS, $subSection = false)
|
public function showSection($section = ACCOUNT_DETAILS, $subSection = false)
|
||||||
{
|
{
|
||||||
if ($section == ACCOUNT_DETAILS) {
|
if ($section == ACCOUNT_DETAILS) {
|
||||||
$primaryUser = Auth::user()->account->getPrimaryUser();
|
$primaryUser = Auth::user()->account->users()->orderBy('id')->first();
|
||||||
$data = [
|
$data = [
|
||||||
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
|
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
|
||||||
'countries' => Cache::get('countries'),
|
'countries' => Cache::get('countries'),
|
||||||
@ -721,6 +723,7 @@ class AccountController extends BaseController
|
|||||||
$account->save();
|
$account->save();
|
||||||
|
|
||||||
if (Auth::user()->id === $user->id) {
|
if (Auth::user()->id === $user->id) {
|
||||||
|
$user = Auth::user();
|
||||||
$user->first_name = trim(Input::get('first_name'));
|
$user->first_name = trim(Input::get('first_name'));
|
||||||
$user->last_name = trim(Input::get('last_name'));
|
$user->last_name = trim(Input::get('last_name'));
|
||||||
$user->username = trim(Input::get('email'));
|
$user->username = trim(Input::get('email'));
|
||||||
@ -837,11 +840,10 @@ class AccountController extends BaseController
|
|||||||
public function doRegister()
|
public function doRegister()
|
||||||
{
|
{
|
||||||
$affiliate = Affiliate::where('affiliate_key', '=', SELF_HOST_AFFILIATE_KEY)->first();
|
$affiliate = Affiliate::where('affiliate_key', '=', SELF_HOST_AFFILIATE_KEY)->first();
|
||||||
|
|
||||||
$email = trim(Input::get('email'));
|
$email = trim(Input::get('email'));
|
||||||
|
|
||||||
if (!$email || $email == 'user@example.com') {
|
if (!$email || $email == TEST_USERNAME) {
|
||||||
return '';
|
return RESULT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
$license = new License();
|
$license = new License();
|
||||||
@ -855,7 +857,7 @@ class AccountController extends BaseController
|
|||||||
$license->is_claimed = 1;
|
$license->is_claimed = 1;
|
||||||
$license->save();
|
$license->save();
|
||||||
|
|
||||||
return '';
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cancelAccount()
|
public function cancelAccount()
|
||||||
|
@ -90,7 +90,8 @@ class AppController extends BaseController
|
|||||||
"MAIL_HOST={$mail['host']}\n".
|
"MAIL_HOST={$mail['host']}\n".
|
||||||
"MAIL_USERNAME={$mail['username']}\n".
|
"MAIL_USERNAME={$mail['username']}\n".
|
||||||
"MAIL_FROM_NAME={$mail['from']['name']}\n".
|
"MAIL_FROM_NAME={$mail['from']['name']}\n".
|
||||||
"MAIL_PASSWORD={$mail['password']}";
|
"MAIL_PASSWORD={$mail['password']}\n\n".
|
||||||
|
"PHANTOMJS_CLOUD_KEY='a-demo-key-with-low-quota-per-ip-address'";
|
||||||
|
|
||||||
// Write Config Settings
|
// Write Config Settings
|
||||||
$fp = fopen(base_path()."/.env", 'w');
|
$fp = fopen(base_path()."/.env", 'w');
|
||||||
|
@ -12,7 +12,6 @@ use DB;
|
|||||||
use Event;
|
use Event;
|
||||||
use URL;
|
use URL;
|
||||||
use Datatable;
|
use Datatable;
|
||||||
use finfo;
|
|
||||||
use Request;
|
use Request;
|
||||||
use DropdownButton;
|
use DropdownButton;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
|
@ -216,6 +216,14 @@ class TaskController extends BaseController
|
|||||||
return self::bulk();
|
return self::bulk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($validator = $this->taskRepo->getErrors(Input::all())) {
|
||||||
|
$url = $publicId ? 'tasks/'.$publicId.'/edit' : 'tasks/create';
|
||||||
|
Session::flash('error', trans('texts.task_errors'));
|
||||||
|
return Redirect::to($url)
|
||||||
|
->withErrors($validator)
|
||||||
|
->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
$task = $this->taskRepo->save($publicId, Input::all());
|
$task = $this->taskRepo->save($publicId, Input::all());
|
||||||
Session::flash('message', trans($publicId ? 'texts.updated_task' : 'texts.created_task'));
|
Session::flash('message', trans($publicId ? 'texts.updated_task' : 'texts.created_task'));
|
||||||
|
|
||||||
|
@ -26,10 +26,8 @@ class StartupCheck
|
|||||||
public function handle($request, Closure $next)
|
public function handle($request, Closure $next)
|
||||||
{
|
{
|
||||||
// Ensure all request are over HTTPS in production
|
// Ensure all request are over HTTPS in production
|
||||||
if (App::environment() == ENV_PRODUCTION) {
|
if (App::environment() == ENV_PRODUCTION && !Request::secure()) {
|
||||||
if (!Request::secure()) {
|
return Redirect::secure(Request::getRequestUri());
|
||||||
return Redirect::secure(Request::getRequestUri());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the database doens't yet exist we'll skip the rest
|
// If the database doens't yet exist we'll skip the rest
|
||||||
@ -37,7 +35,19 @@ class StartupCheck
|
|||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the application is up to date and for any news feed messages
|
// Check if a new version was installed
|
||||||
|
if (!Utils::isNinja()) {
|
||||||
|
$file = storage_path() . '/version.txt';
|
||||||
|
$version = @file_get_contents($file);
|
||||||
|
if ($version != NINJA_VERSION) {
|
||||||
|
$handle = fopen($file, 'w');
|
||||||
|
fwrite($handle, NINJA_VERSION);
|
||||||
|
fclose($handle);
|
||||||
|
return Redirect::to('/update');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the application is up to date and for any news feed messages
|
||||||
if (Auth::check()) {
|
if (Auth::check()) {
|
||||||
$count = Session::get(SESSION_COUNTER, 0);
|
$count = Session::get(SESSION_COUNTER, 0);
|
||||||
Session::put(SESSION_COUNTER, ++$count);
|
Session::put(SESSION_COUNTER, ++$count);
|
||||||
@ -161,7 +171,7 @@ class StartupCheck
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show message to IE 8 and before users
|
||||||
if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT'])) {
|
if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT'])) {
|
||||||
Session::flash('error', trans('texts.old_browser'));
|
Session::flash('error', trans('texts.old_browser'));
|
||||||
}
|
}
|
||||||
|
@ -391,6 +391,7 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('OUTDATE_BROWSER_URL', 'http://browsehappy.com/');
|
define('OUTDATE_BROWSER_URL', 'http://browsehappy.com/');
|
||||||
define('PDFMAKE_DOCS', 'http://pdfmake.org/playground.html');
|
define('PDFMAKE_DOCS', 'http://pdfmake.org/playground.html');
|
||||||
define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/single/browser/v1/');
|
define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/single/browser/v1/');
|
||||||
|
define('GITHUB_RELEASES', 'https://github.com/hillelcoren/invoice-ninja/releases');
|
||||||
define('REFERRAL_PROGRAM_URL', false);
|
define('REFERRAL_PROGRAM_URL', false);
|
||||||
|
|
||||||
define('COUNT_FREE_DESIGNS', 4);
|
define('COUNT_FREE_DESIGNS', 4);
|
||||||
@ -460,7 +461,6 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Log all SQL queries to laravel.log
|
// Log all SQL queries to laravel.log
|
||||||
Event::listen('illuminate.query', function($query, $bindings, $time, $name)
|
Event::listen('illuminate.query', function($query, $bindings, $time, $name)
|
||||||
{
|
{
|
||||||
@ -485,7 +485,7 @@ Event::listen('illuminate.query', function($query, $bindings, $time, $name)
|
|||||||
|
|
||||||
Log::info($query, $data);
|
Log::info($query, $data);
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (Auth::check() && Auth::user()->id === 1)
|
if (Auth::check() && Auth::user()->id === 1)
|
||||||
|
@ -5,6 +5,7 @@ use Auth;
|
|||||||
use Carbon;
|
use Carbon;
|
||||||
use Session;
|
use Session;
|
||||||
use App\Events\UserLoggedIn;
|
use App\Events\UserLoggedIn;
|
||||||
|
use App\Events\UserSignedUp;
|
||||||
use App\Ninja\Repositories\AccountRepository;
|
use App\Ninja\Repositories\AccountRepository;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Contracts\Queue\ShouldBeQueued;
|
use Illuminate\Contracts\Queue\ShouldBeQueued;
|
||||||
@ -33,8 +34,8 @@ class HandleUserLoggedIn {
|
|||||||
{
|
{
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
|
|
||||||
if (!Utils::isNinja() && Auth::user()->id == 1 && empty($account->last_login)) {
|
if (empty($account->last_login)) {
|
||||||
$this->accountRepo->registerUser(Auth::user());
|
event(new UserSignedUp());
|
||||||
}
|
}
|
||||||
|
|
||||||
$account->last_login = Carbon::now()->toDateTimeString();
|
$account->last_login = Carbon::now()->toDateTimeString();
|
||||||
|
37
app/Listeners/HandleUserSignedUp.php
Normal file
37
app/Listeners/HandleUserSignedUp.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php namespace App\Listeners;
|
||||||
|
|
||||||
|
use Utils;
|
||||||
|
use Auth;
|
||||||
|
use App\Events\UserSignedUp;
|
||||||
|
use App\Ninja\Repositories\AccountRepository;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldBeQueued;
|
||||||
|
|
||||||
|
class HandleUserSignedUp {
|
||||||
|
|
||||||
|
protected $accountRepo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the event handler.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(AccountRepository $accountRepo)
|
||||||
|
{
|
||||||
|
$this->accountRepo = $accountRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param UserSignedUp $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(UserSignedUp $event)
|
||||||
|
{
|
||||||
|
if (!Utils::isNinjaProd()) {
|
||||||
|
$this->accountRepo->registerUser(Auth::user());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -25,13 +25,6 @@ class Account extends Eloquent
|
|||||||
return $this->hasMany('App\Models\User');
|
return $this->hasMany('App\Models\User');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPrimaryUser()
|
|
||||||
{
|
|
||||||
return $this->hasMany('App\Models\User')
|
|
||||||
->whereRaw('public_id = 0 OR public_id IS NULL')
|
|
||||||
->first();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function clients()
|
public function clients()
|
||||||
{
|
{
|
||||||
return $this->hasMany('App\Models\Client');
|
return $this->hasMany('App\Models\Client');
|
||||||
|
@ -21,7 +21,7 @@ class Invoice extends EntityModel
|
|||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\Models\User');
|
return $this->belongsTo('App\Models\User')->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function client()
|
public function client()
|
||||||
|
@ -5,4 +5,9 @@ use Eloquent;
|
|||||||
class Language extends Eloquent
|
class Language extends Eloquent
|
||||||
{
|
{
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ use Auth;
|
|||||||
use Event;
|
use Event;
|
||||||
use App\Libraries\Utils;
|
use App\Libraries\Utils;
|
||||||
use App\Events\UserSettingsChanged;
|
use App\Events\UserSettingsChanged;
|
||||||
|
use App\Events\UserSignedUp;
|
||||||
use Illuminate\Auth\Authenticatable;
|
use Illuminate\Auth\Authenticatable;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Auth\Passwords\CanResetPassword;
|
use Illuminate\Auth\Passwords\CanResetPassword;
|
||||||
@ -35,7 +36,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $hidden = ['password', 'remember_token'];
|
protected $hidden = ['password', 'remember_token', 'confirmation_code'];
|
||||||
|
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
protected $dates = ['deleted_at'];
|
protected $dates = ['deleted_at'];
|
||||||
@ -203,20 +204,30 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function updateUser($user)
|
public static function onUpdatingUser($user)
|
||||||
{
|
{
|
||||||
if ($user->password != !$user->getOriginal('password')) {
|
if ($user->password != $user->getOriginal('password')) {
|
||||||
$user->failed_logins = 0;
|
$user->failed_logins = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function onUpdatedUser($user)
|
||||||
|
{
|
||||||
|
if (!$user->getOriginal('email')
|
||||||
|
|| $user->getOriginal('email') == TEST_USERNAME
|
||||||
|
|| $user->getOriginal('username') == TEST_USERNAME) {
|
||||||
|
event(new UserSignedUp());
|
||||||
|
}
|
||||||
|
|
||||||
|
event(new UserSettingsChanged());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
User::updating(function ($user) {
|
User::updating(function ($user) {
|
||||||
User::updateUser($user);
|
User::onUpdatingUser($user);
|
||||||
});
|
});
|
||||||
|
|
||||||
User::updated(function ($user) {
|
User::updated(function ($user) {
|
||||||
Event::fire(new UserSettingsChanged());
|
User::onUpdatedUser($user);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ class ContactMailer extends Mailer
|
|||||||
} else {
|
} else {
|
||||||
$user = $invitation->user;
|
$user = $invitation->user;
|
||||||
if ($invitation->user->trashed()) {
|
if ($invitation->user->trashed()) {
|
||||||
$user = $account->getPrimaryUser();
|
$user = $account->users()->orderBy('id')->first();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +233,11 @@ class AccountRepository
|
|||||||
|
|
||||||
public function registerUser($user)
|
public function registerUser($user)
|
||||||
{
|
{
|
||||||
$url = (Utils::isNinjaDev() ? '' : NINJA_APP_URL) . '/signup/register';
|
if ($user->email == TEST_USERNAME) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = (Utils::isNinjaDev() ? SITE_URL : NINJA_APP_URL) . '/signup/register';
|
||||||
$data = '';
|
$data = '';
|
||||||
$fields = [
|
$fields = [
|
||||||
'first_name' => urlencode($user->first_name),
|
'first_name' => urlencode($user->first_name),
|
||||||
@ -250,6 +254,7 @@ class AccountRepository
|
|||||||
curl_setopt($ch, CURLOPT_URL, $url);
|
curl_setopt($ch, CURLOPT_URL, $url);
|
||||||
curl_setopt($ch, CURLOPT_POST, count($fields));
|
curl_setopt($ch, CURLOPT_POST, count($fields));
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
curl_exec($ch);
|
curl_exec($ch);
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,20 @@ class TaskRepository
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getErrors($input)
|
||||||
|
{
|
||||||
|
$rules = [
|
||||||
|
'time_log' => 'time_log',
|
||||||
|
];
|
||||||
|
$validator = \Validator::make($input, $rules);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return $validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public function save($publicId, $data)
|
public function save($publicId, $data)
|
||||||
{
|
{
|
||||||
if ($publicId) {
|
if ($publicId) {
|
||||||
|
@ -116,6 +116,26 @@ class AppServiceProvider extends ServiceProvider {
|
|||||||
return $credit >= $amount;
|
return $credit >= $amount;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// check that the time log elements don't overlap
|
||||||
|
Validator::extend('time_log', function($attribute, $value, $parameters) {
|
||||||
|
$lastTime = 0;
|
||||||
|
$value = json_decode($value);
|
||||||
|
array_multisort($value);
|
||||||
|
foreach ($value as $timeLog) {
|
||||||
|
list($startTime, $endTime) = $timeLog;
|
||||||
|
if (!$endTime) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($startTime < $lastTime || $startTime > $endTime) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($endTime < min($startTime, $lastTime)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$lastTime = max($lastTime, $endTime);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
Validator::extend('less_than', function($attribute, $value, $parameters) {
|
Validator::extend('less_than', function($attribute, $value, $parameters) {
|
||||||
return floatval($value) <= floatval($parameters[0]);
|
return floatval($value) <= floatval($parameters[0]);
|
||||||
|
@ -11,6 +11,9 @@ class EventServiceProvider extends ServiceProvider {
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $listen = [
|
protected $listen = [
|
||||||
|
'App\Events\UserSignedUp' => [
|
||||||
|
'App\Listeners\HandleUserSignedUp',
|
||||||
|
],
|
||||||
'App\Events\UserLoggedIn' => [
|
'App\Events\UserLoggedIn' => [
|
||||||
'App\Listeners\HandleUserLoggedIn',
|
'App\Listeners\HandleUserLoggedIn',
|
||||||
],
|
],
|
||||||
|
@ -29,7 +29,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'lifetime' => env('SESSION_LIFETIME', 120),
|
'lifetime' => env('SESSION_LIFETIME', 1),
|
||||||
|
|
||||||
'expire_on_close' => false,
|
'expire_on_close' => false,
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class SupportTokenBilling extends Migration {
|
|||||||
{
|
{
|
||||||
Schema::table('accounts', function($table)
|
Schema::table('accounts', function($table)
|
||||||
{
|
{
|
||||||
$table->smallInteger('token_billing_type_id')->default(TOKEN_BILLING_OPT_IN);
|
$table->smallInteger('token_billing_type_id')->default(TOKEN_BILLING_ALWAYS);
|
||||||
});
|
});
|
||||||
|
|
||||||
Schema::create('account_gateway_tokens', function($table)
|
Schema::create('account_gateway_tokens', function($table)
|
||||||
@ -35,7 +35,7 @@ class SupportTokenBilling extends Migration {
|
|||||||
$table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
|
$table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
|
||||||
});
|
});
|
||||||
|
|
||||||
DB::table('accounts')->update(['token_billing_type_id' => TOKEN_BILLING_OPT_IN]);
|
DB::table('accounts')->update(['token_billing_type_id' => TOKEN_BILLING_ALWAYS]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,27 +70,27 @@ class PaymentLibrariesSeeder extends Seeder
|
|||||||
$currencies = [
|
$currencies = [
|
||||||
['name' => 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
['name' => 'South African Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'South African Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
['name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
['name' => 'Israeli Shekel', 'code' => 'ILS', 'symbol' => 'NIS ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Israeli Shekel', 'code' => 'ILS', 'symbol' => 'NIS ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
['name' => 'Kenyan Shilling', 'code' => 'KES', 'symbol' => 'KSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Kenyan Shilling', 'code' => 'KES', 'symbol' => 'KSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Canadian Dollar', 'code' => 'CAD', 'symbol' => 'C$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Canadian Dollar', 'code' => 'CAD', 'symbol' => 'C$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Philippine Peso', 'code' => 'PHP', 'symbol' => 'P ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Philippine Peso', 'code' => 'PHP', 'symbol' => 'P ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Indian Rupee', 'code' => 'INR', 'symbol' => 'Rs. ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Indian Rupee', 'code' => 'INR', 'symbol' => 'Rs. ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Australian Dollar', 'code' => 'AUD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Australian Dollar', 'code' => 'AUD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Singapore Dollar', 'code' => 'SGD', 'symbol' => 'SGD ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Singapore Dollar', 'code' => 'SGD', 'symbol' => 'SGD ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Norske Kroner', 'code' => 'NOK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Norske Kroner', 'code' => 'NOK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
['name' => 'New Zealand Dollar', 'code' => 'NZD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'New Zealand Dollar', 'code' => 'NZD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Vietnamese Dong', 'code' => 'VND', 'symbol' => 'VND ', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Vietnamese Dong', 'code' => 'VND', 'symbol' => 'VND ', 'precision' => '0', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
['name' => 'Swiss Franc', 'code' => 'CHF', 'symbol' => 'CHF ', 'precision' => '2', 'thousand_separator' => '\'', 'decimal_separator' => '.'],
|
['name' => 'Swiss Franc', 'code' => 'CHF', 'symbol' => 'CHF ', 'precision' => '2', 'thousand_separator' => '\'', 'decimal_separator' => ','],
|
||||||
['name' => 'Guatemalan Quetzal', 'code' => 'GTQ', 'symbol' => 'Q', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Guatemalan Quetzal', 'code' => 'GTQ', 'symbol' => 'Q', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Malaysian Ringgit', 'code' => 'MYR', 'symbol' => 'RM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Malaysian Ringgit', 'code' => 'MYR', 'symbol' => 'RM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Brazilian Real', 'code' => 'BRL', 'symbol' => 'R$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Brazilian Real', 'code' => 'BRL', 'symbol' => 'R$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
['name' => 'Thai baht', 'code' => 'THB', 'symbol' => 'THB ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Thai baht', 'code' => 'THB', 'symbol' => 'THB ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => 'NGN ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => 'NGN ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
['name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -98,6 +98,8 @@ class PaymentLibrariesSeeder extends Seeder
|
|||||||
$record = Currency::whereCode($currency['code'])->first();
|
$record = Currency::whereCode($currency['code'])->first();
|
||||||
if ($record) {
|
if ($record) {
|
||||||
$record->name = $currency['name'];
|
$record->name = $currency['name'];
|
||||||
|
$record->thousand_separator = $currency['thousand_separator'];
|
||||||
|
$record->decimal_separator = $currency['decimal_separator'];
|
||||||
$record->save();
|
$record->save();
|
||||||
} else {
|
} else {
|
||||||
Currency::create($currency);
|
Currency::create($currency);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
|
use App\Models\Affiliate;
|
||||||
|
|
||||||
class UserTableSeeder extends Seeder
|
class UserTableSeeder extends Seeder
|
||||||
{
|
{
|
||||||
@ -26,6 +27,11 @@ class UserTableSeeder extends Seeder
|
|||||||
'registered' => true,
|
'registered' => true,
|
||||||
'confirmed' => true,
|
'confirmed' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
Affiliate::create([
|
||||||
|
'affiliate_key' => SELF_HOST_AFFILIATE_KEY
|
||||||
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -31834,7 +31834,7 @@ NINJA.invoiceLines = function(invoice) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// show at most one blank line
|
// show at most one blank line
|
||||||
if (shownItem && (!cost || cost == '0.00') && !notes && !productKey) {
|
if (shownItem && (!cost || cost == '0.00' || cost == '0,00') && !notes && !productKey) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ NINJA.invoiceLines = function(invoice) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// show at most one blank line
|
// show at most one blank line
|
||||||
if (shownItem && (!cost || cost == '0.00') && !notes && !productKey) {
|
if (shownItem && (!cost || cost == '0.00' || cost == '0,00') && !notes && !productKey) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,9 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if ($gateway->id == GATEWAY_STRIPE)
|
@if ($gateway->id == GATEWAY_STRIPE)
|
||||||
{!! Former::select('token_billing_type_id')->options($tokenBillingOptions)->help(trans('texts.token_billing_help')) !!}
|
{!! Former::select('token_billing_type_id')
|
||||||
|
->options($tokenBillingOptions)
|
||||||
|
->help(trans('texts.token_billing_help')) !!}
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -637,7 +637,8 @@
|
|||||||
@if (!Utils::isNinjaProd())
|
@if (!Utils::isNinjaProd())
|
||||||
<p> </p>
|
<p> </p>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{ trans('texts.powered_by') }} <a href="https://www.invoiceninja.com/?utm_source=powered_by" target="_blank">InvoiceNinja.com</a> |
|
{{ trans('texts.powered_by') }} <a href="https://www.invoiceninja.com/?utm_source=powered_by" target="_blank">InvoiceNinja.com</a> -
|
||||||
|
{!! link_to(GITHUB_RELEASES, 'v' . NINJA_VERSION, ['target' => '_blank']) !!} |
|
||||||
@if (Auth::user()->account->isWhiteLabel())
|
@if (Auth::user()->account->isWhiteLabel())
|
||||||
{{ trans('texts.white_labeled') }}
|
{{ trans('texts.white_labeled') }}
|
||||||
@else
|
@else
|
||||||
|
@ -180,14 +180,6 @@
|
|||||||
if (!timeLog.isEmpty()) {
|
if (!timeLog.isEmpty()) {
|
||||||
data.push([timeLog.startTime(),timeLog.endTime()]);
|
data.push([timeLog.startTime(),timeLog.endTime()]);
|
||||||
}
|
}
|
||||||
@if ($task && !$task->is_running)
|
|
||||||
if (!timeLog.isStartValid() || !timeLog.isEndValid()) {
|
|
||||||
alert("{!! trans('texts.task_errors') !!}");
|
|
||||||
showTimeDetails();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
$('#invoice_id').val(invoice_id);
|
$('#invoice_id').val(invoice_id);
|
||||||
$('#time_log').val(JSON.stringify(data));
|
$('#time_log').val(JSON.stringify(data));
|
||||||
@ -279,6 +271,15 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadTimeLog(data) {
|
||||||
|
model.time_log.removeAll();
|
||||||
|
data = JSON.parse(data);
|
||||||
|
for (var i=0; i<data.length; i++) {
|
||||||
|
model.time_log.push(new TimeModel(data[i]));
|
||||||
|
}
|
||||||
|
model.time_log.push(new TimeModel());
|
||||||
|
}
|
||||||
|
|
||||||
function ViewModel(data) {
|
function ViewModel(data) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.time_log = ko.observableArray();
|
self.time_log = ko.observableArray();
|
||||||
@ -299,19 +300,24 @@
|
|||||||
self.refresh = function() {
|
self.refresh = function() {
|
||||||
var hasEmpty = false;
|
var hasEmpty = false;
|
||||||
var lastTime = 0;
|
var lastTime = 0;
|
||||||
self.time_log.sort(function(left, right) {
|
for (var i=0; i<self.time_log().length; i++) {
|
||||||
if (left.isEmpty() || right.isEmpty()) {
|
var timeLog = self.time_log()[i];
|
||||||
return -1;
|
if (timeLog.isEmpty()) {
|
||||||
|
hasEmpty = true;
|
||||||
}
|
}
|
||||||
return left.startTime() - right.startTime();
|
}
|
||||||
});
|
if (!hasEmpty) {
|
||||||
|
self.addItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.showTimeOverlaps = function() {
|
||||||
|
var lastTime = 0;
|
||||||
for (var i=0; i<self.time_log().length; i++) {
|
for (var i=0; i<self.time_log().length; i++) {
|
||||||
var timeLog = self.time_log()[i];
|
var timeLog = self.time_log()[i];
|
||||||
var startValid = true;
|
var startValid = true;
|
||||||
var endValid = true;
|
var endValid = true;
|
||||||
if (timeLog.isEmpty()) {
|
if (!timeLog.isEmpty()) {
|
||||||
hasEmpty = true;
|
|
||||||
} else {
|
|
||||||
if (timeLog.startTime() < lastTime || timeLog.startTime() > timeLog.endTime()) {
|
if (timeLog.startTime() < lastTime || timeLog.startTime() > timeLog.endTime()) {
|
||||||
startValid = false;
|
startValid = false;
|
||||||
}
|
}
|
||||||
@ -323,9 +329,6 @@
|
|||||||
timeLog.isStartValid(startValid);
|
timeLog.isStartValid(startValid);
|
||||||
timeLog.isEndValid(endValid);
|
timeLog.isEndValid(endValid);
|
||||||
}
|
}
|
||||||
if (!hasEmpty) {
|
|
||||||
self.addItem();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addItem = function() {
|
self.addItem = function() {
|
||||||
@ -384,6 +387,12 @@
|
|||||||
tock({{ $duration }});
|
tock({{ $duration }});
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if (Session::has('error'))
|
||||||
|
loadTimeLog({!! json_encode(Input::old('time_log')) !!});
|
||||||
|
model.showTimeOverlaps();
|
||||||
|
showTimeDetails();
|
||||||
|
@endif
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user