1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 13:12:50 +01:00

Merge pull request #3920 from turbo124/v2

Update enabled_modules
This commit is contained in:
David Bomba 2020-07-21 21:52:37 +10:00 committed by GitHub
commit 5191d1617a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 665 additions and 82 deletions

View File

@ -112,6 +112,8 @@ class CreateTestData extends Command
$company_token->account_id = $account->id;
$company_token->name = 'test token';
$company_token->token = Str::random(64);
$company_token->is_system = true;
$company_token->save();
$user->companies()->attach($company->id, [
@ -207,6 +209,7 @@ class CreateTestData extends Command
$company_token->account_id = $account->id;
$company_token->name = 'test token';
$company_token->token = Str::random(64);
$company_token->is_system = true;
$company_token->save();
$user->companies()->attach($company->id, [
@ -304,6 +307,7 @@ class CreateTestData extends Command
$company_token->account_id = $account->id;
$company_token->name = 'test token';
$company_token->token = Str::random(64);
$company_token->is_system = true;
$company_token->save();
$user->companies()->attach($company->id, [

View File

@ -100,7 +100,7 @@ class DemoMode extends Command
$company = factory(\App\Models\Company::class)->create([
'account_id' => $account->id,
'slack_webhook_url' => config('ninja.notification.slack'),
'enabled_modules' => 8191,
'enabled_modules' => 32767,
]);
$settings = $company->settings;
@ -137,6 +137,8 @@ class DemoMode extends Command
$company_token->account_id = $account->id;
$company_token->name = 'test token';
$company_token->token = Str::random(64);
$company_token->is_system = true;
$company_token->save();
$user->companies()->attach($company->id, [
@ -190,10 +192,8 @@ class DemoMode extends Command
$z = $x+1;
$this->info("Creating client # ".$z);
if(rand(0,1))
$this->createClient($company, $user);
else
$this->createClient($company, $u2);
$this->createClient($company, $user, $u2->id);
}
for($x=0; $x<$this->count; $x++)
@ -201,50 +201,50 @@ class DemoMode extends Command
$client = $company->clients->random();
$this->info('creating entities for client #'.$client->id);
$this->createInvoice($client);
$this->createInvoice($client, $u2->id);
// for($y=0; $y<($this->count); $y++){
// $this->info("creating invoice #{$y} for client #".$client->id);
// }
$client = $company->clients->random();
$this->createCredit($client);
$this->createCredit($client, $u2->id);
// for($y=0; $y<($this->count); $y++){
// $this->info("creating credit #{$y} for client #".$client->id);
// }
$client = $company->clients->random();
$this->createQuote($client);
$this->createQuote($client, $u2->id);
// for($y=0; $y<($this->count); $y++){
// $this->info("creating quote #{$y} for client #".$client->id);
// }
$client = $company->clients->random();
$this->createExpense($client);
$this->createExpense($client, $u2->id);
//$this->info("creating expense for client #".$client->id);
$client = $company->clients->random();
$this->createVendor($client);
$this->createVendor($client, $u2->id);
// $this->info("creating vendor for client #".$client->id);
$client = $company->clients->random();
$this->createTask($client);
$this->createTask($client, $u2->id);
// $this->info("creating task for client #".$client->id);
$client = $company->clients->random();
$this->createProject($client);
$this->createProject($client, $u2->id);
// $this->info("creating project for client #".$client->id);
}
}
private function createClient($company, $user)
private function createClient($company, $user, $assigned_user_id = null)
{
// dispatch(function () use ($company, $user) {
@ -274,6 +274,9 @@ class DemoMode extends Command
$settings->currency_id = (string)rand(1,3);
$client->settings = $settings;
if(rand(0,1))
$client->assigned_user_id = $assigned_user_id;
$client->country_id = array_rand([36,392,840,124,276,826]);
$client->save();
@ -288,7 +291,7 @@ class DemoMode extends Command
]);
}
private function createVendor($client)
private function createVendor($client, $assigned_user_id = null)
{
$vendor = factory(\App\Models\Vendor::class)->create([
'user_id' => $client->user_id,
@ -311,7 +314,7 @@ class DemoMode extends Command
]);
}
private function createTask($client)
private function createTask($client, $assigned_user_id = null)
{
$vendor = factory(\App\Models\Task::class)->create([
'user_id' => $client->user->id,
@ -319,7 +322,7 @@ class DemoMode extends Command
]);
}
private function createProject($client)
private function createProject($client, $assigned_user_id = null)
{
$vendor = factory(\App\Models\Project::class)->create([
'user_id' => $client->user->id,
@ -327,7 +330,7 @@ class DemoMode extends Command
]);
}
private function createInvoice($client)
private function createInvoice($client, $assigned_user_id = null)
{
// for($x=0; $x<$this->count; $x++){
// dispatch(new CreateTestInvoiceJob($client));
@ -373,6 +376,9 @@ class DemoMode extends Command
$invoice = $invoice_calc->getInvoice();
if(rand(0,1))
$invoice->assigned_user_id = $assigned_user_id;
$invoice->save();
$invoice->service()->createInvitations()->markSent();
@ -383,7 +389,7 @@ class DemoMode extends Command
$invoice = $invoice->service()->markPaid()->save();
$invoice->payments->each(function ($payment){
$payment->date = now()->addDays(rand(0,90));
$payment->date = now()->addDays(rand(-30,30));
$payment->save();
});
}
@ -391,7 +397,7 @@ class DemoMode extends Command
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars()));
}
private function createCredit($client)
private function createCredit($client, $assigned_user_id = null)
{
// for($x=0; $x<$this->count; $x++){
@ -434,12 +440,15 @@ class DemoMode extends Command
$credit = $invoice_calc->getCredit();
if(rand(0,1))
$credit->assigned_user_id = $assigned_user_id;
$credit->save();
$credit->service()->markSent()->save();
$credit->service()->createInvitations();
}
private function createQuote($client)
private function createQuote($client, $assigned_user_id = null)
{
$faker = \Faker\Factory::create();
@ -487,6 +496,9 @@ class DemoMode extends Command
$quote = $quote_calc->getQuote();
if(rand(0,1))
$quote->assigned_user_id = $assigned_user_id;
$quote->save();
$quote->service()->markSent()->save();

View File

@ -11,6 +11,7 @@
namespace App\Console;
use App\Console\Commands\CheckData;
use App\Jobs\Cron\RecurringInvoicesCron;
use App\Jobs\Ninja\AdjustEmailQuota;
use App\Jobs\Ninja\CheckDbStatus;
@ -46,6 +47,8 @@ class Kernel extends ConsoleKernel
//$schedule->job(new RecurringInvoicesCron)->hourly();
$schedule->job(new VersionCheck)->daily();
$schedule->command('ninja:check-data')->daily();
$schedule->job(new ReminderJob)->daily();
$schedule->job(new CompanySizeCheck)->daily();

View File

@ -45,7 +45,7 @@ class FreeCompanySettings extends BaseSettings
public $military_time = false;
public $payment_number_pattern = '';
public $payment_number_counter = 1;
public $payment_terms = -1;
public $payment_terms = "";
public $payment_type_id = '0';
public $portal_design_id = '1';
public $quote_design_id = 'VolejRejNm';
@ -112,7 +112,7 @@ class FreeCompanySettings extends BaseSettings
'custom_value4' => 'string',
'inclusive_taxes' => 'bool',
'name' => 'string',
'payment_terms' => 'integer',
'payment_terms' => 'string',
'payment_type_id' => 'string',
'phone' => 'string',
'postal_code' => 'string',

View File

@ -0,0 +1,41 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Events\Credit;
use App\Models\Company;
use App\Models\Credit;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class CreditWasDeleted
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $credit;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Credit $credit
*/
public function __construct(Credit $credit, Company $company, array $event_vars)
{
$this->credit = $credit;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -0,0 +1,37 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Events\Quote;
use App\Models\Company;
use App\Models\QuoteWasViewed;
use Illuminate\Queue\SerializesModels;
/**
* Class QuoteWasViewed.
*/
class QuoteWasViewed
{
use SerializesModels;
public $invitation;
public $company;
public $event_vars;
public function __construct(QuoteInvitation $invitation, Company $company, array $event_vars)
{
$this->invitation = $invitation;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -36,7 +36,7 @@ class Handler extends ExceptionHandler
* @var array
*/
protected $dontReport = [
//
\PDOException::class,
];
/**
@ -81,6 +81,7 @@ class Handler extends ExceptionHandler
}
});
// app('sentry')->setRelease(config('ninja.app_version'));
app('sentry')->captureException($exception);
}
@ -117,6 +118,7 @@ class Handler extends ExceptionHandler
} elseif ($exception instanceof MethodNotAllowedHttpException && $request->expectsJson()) {
return response()->json(['message'=>'Method not support for this route'], 404);
} elseif ($exception instanceof ValidationException && $request->expectsJson()) {
// info(print_r($exception->validator->getMessageBag(),1));
return response()->json(['message' => 'The given data was invalid.', 'errors' => $exception->validator->getMessageBag()], 422);
} elseif ($exception instanceof RelationNotFoundException && $request->expectsJson()) {
return response()->json(['message' => $exception->getMessage()], 400);

View File

@ -34,7 +34,7 @@ class CompanyFactory
//$company->custom_fields = (object) ['invoice1' => '1', 'invoice2' => '2', 'client1'=>'3'];
$company->custom_fields = (object) [];
$company->subdomain = '';
$company->enabled_modules = 8191; //4095
$company->enabled_modules = 32767;//8191; //4095
return $company;
}

View File

@ -137,36 +137,39 @@ class BaseController extends Controller
$transformer = new $this->entity_transformer(Input::get('serializer'));
$includes = $transformer->getDefaultIncludes();
$includes = $this->getRequestIncludes($includes);
//info(print_r($includes,1));
$updated_at = request()->has('updated_at') ? request()->input('updated_at') : 0;
$updated_at = date('Y-m-d H:i:s', $updated_at);
//info($updated_at);
$query->with(
[
'company' => function ($query) use($updated_at){$query->where('updated_at', '>=', 0);},
'company.activities' => function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.clients' =>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.tax_rates'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.groups'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.company_gateways'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.clients.contacts'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.products'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.invoices.invitations'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.invoices.invitations'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.invoices.documents'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.payments.paymentables'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.quotes.invitations'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.quotes.documents'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.credits.invitations'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.credits'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.payment_terms'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.vendors'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.expenses'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.tasks'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.projects'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.designs'=>function ($query) use($updated_at){$query->where('updated_at', '>', $updated_at);},
'company.clients' =>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.tax_rates'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.groups'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.company_gateways'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.clients.contacts'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.products'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.invoices.invitations.contact'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.invoices.invitations'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.invoices.documents'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.payments.paymentables'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.quotes.invitations'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.quotes.documents'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.credits.invitations'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.credits'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.payment_terms'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.vendors'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.expenses'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.tasks'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.projects'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.designs'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
]
);
@ -311,6 +314,7 @@ class BaseController extends Controller
'company.quotes.invitations.contact',
'company.quotes.invitations.company',
'company.quotes.documents',
'company.credits.invitations.contact',
'company.credits.invitations.company',
'company.credits.documents',
'company.payment_terms.company',
@ -340,7 +344,7 @@ class BaseController extends Controller
* Thresholds for displaying large account on first load
*/
if (request()->has('first_load') && request()->input('first_load') == 'true') {
if (auth()->user()->getCompany()->is_large) {
if (auth()->user()->getCompany()->is_large && request()->missing('updated_at')) {
$data = $mini_load;
} else {
$data = $first_load;

View File

@ -228,6 +228,7 @@ class MigrationController extends BaseController
$company_token->account_id = $account->id;
$company_token->name = $request->token_name ?? Str::random(12);
$company_token->token = $request->token ?? \Illuminate\Support\Str::random(64);
$company_token->is_system = true;
$company_token->save();
$user->companies()->attach($company->id, [
@ -287,6 +288,8 @@ class MigrationController extends BaseController
$company_token->account_id = $account->id;
$company_token->name = $request->token_name ?? Str::random(12);
$company_token->token = $request->token ?? \Illuminate\Support\Str::random(64);
$company_token->is_system = true;
$company_token->save();
$user->companies()->attach($company->id, [
@ -320,6 +323,8 @@ class MigrationController extends BaseController
$company_token->account_id = $account->id;
$company_token->name = $request->token_name ?? Str::random(12);
$company_token->token = $request->token ?? \Illuminate\Support\Str::random(64);
$company_token->is_system = true;
$company_token->save();
$user->companies()->attach($company->id, [
@ -346,6 +351,8 @@ class MigrationController extends BaseController
$company_token->account_id = $account->id;
$company_token->name = $request->token_name ?? Str::random(12);
$company_token->token = $request->token ?? \Illuminate\Support\Str::random(64);
$company_token->is_system = true;
$company_token->save();
$user->companies()->attach($company->id, [

View File

@ -15,6 +15,7 @@ use App\Utils\Ninja;
use Composer\Factory;
use Composer\IO\NullIO;
use Composer\Installer;
use Cz\Git\GitException;
use Cz\Git\GitRepository;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Support\Facades\Artisan;
@ -73,8 +74,12 @@ class SelfUpdateController extends BaseController
info("Are there changes to pull? " . $repo->hasChanges());
try{
$res = $repo->pull();
}
catch(GitException $e) {
info($e->getMessage());
}
info("Are there any changes to pull? " . $repo->hasChanges());
Artisan::call('ninja:post-update');

View File

@ -205,4 +205,6 @@ class SetupController extends Controller
return response([], 500);
}
}
}

View File

@ -48,7 +48,7 @@ class QueryLogging
$timeEnd = microtime(true);
$time = $timeEnd - $timeStart;
// Log::info($request->method() . ' - ' . $request->url() . ": $count queries - " . $time);
Log::info($request->method() . ' - ' . $request->url() . ": $count queries - " . $time);
//if($count > 10)
// Log::info($queries);

View File

@ -39,6 +39,8 @@ class StorePaymentRequest extends Request
{
$input = $this->all();
//info(print_r($input,1));
$invoices_total = 0;
$credits_total = 0;

View File

@ -78,6 +78,11 @@ class ValidCreditsRules implements Rule
}
if(count($this->input['credits']) >=1 && count($this->input['invoices']) == 0){
$this->error_msg = "You must have an invoice set when using a credit in a payment";
return false;
}
return true;
}

View File

@ -35,7 +35,7 @@ class CanAddUserRule implements Rule
*/
public function passes($attribute, $value)
{
return $this->account->num_users < $this->account->pending_num_users;
return $this->account->users->count() < $this->account->num_users;
}
/**
@ -43,7 +43,7 @@ class CanAddUserRule implements Rule
*/
public function message()
{
return ctrans('texts.limit_users', ['limit' => $this->account->pending_num_users]);
return ctrans('texts.limit_users', ['limit' => $this->account->num_users]);
}
}

View File

@ -59,6 +59,8 @@ class CreateCompanyToken implements ShouldQueue
$company_token->account_id = $this->user->account->id;
$company_token->name = $this->custom_token_name ?: $this->user->first_name. ' '. $this->user->last_name;
$company_token->token = Str::random(64);
$company_token->is_system = true;
$company_token->save();

View File

@ -0,0 +1,53 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class CreatedQuoteActivity implements ShouldQueue
{
protected $activity_repo;
/**
* Create the event listener.
*
* @return void
*/
public function __construct(ActivityRepository $activity_repo)
{
$this->activity_repo = $activity_repo;
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
MultiDB::setDb($event->company->db);
$fields = new \stdClass;
$fields->quote_id = $event->quote->id;
$fields->user_id = $event->quote->user_id;
$fields->company_id = $event->quote->company_id;
$fields->activity_type_id = Activity::CREATE_QUOTE;
$this->activity_repo->save($fields, $event->quote, $event->event_vars);
}
}

View File

@ -0,0 +1,54 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class DeleteCreditActivity implements ShouldQueue
{
protected $activity_repo;
/**
* Create the event listener.
*
* @return void
*/
public function __construct(ActivityRepository $activity_repo)
{
$this->activity_repo = $activity_repo;
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
MultiDB::setDb($event->company->db);
$fields = new \stdClass;
$fields->client_id = $event->credit->client_id;
$fields->credit_id = $event->credit->id;
$fields->user_id = $event->credit->user_id;
$fields->company_id = $event->credit->company_id;
$fields->activity_type_id = Activity::DELETE_CREDIT;
$this->activity_repo->save($fields, $event->credit, $event->event_vars);
}
}

View File

@ -0,0 +1,70 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\Invoice;
use App\Models\Payment;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class QuoteUpdatedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* Create the event listener.
*
* @return void
*/
public function __construct(ActivityRepository $activity_repo)
{
$this->activity_repo = $activity_repo;
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
MultiDB::setDb($event->company->db);
$quote = $event->quote;
$invoices = $payment->invoices;
$fields = new \stdClass;
$fields->payment_id = $quote->id;
$fields->user_id = $quote->user_id;
$fields->company_id = $quote->company_id;
$fields->activity_type_id = Activity::UPDATE_QUOTE;
$this->activity_repo->save($fields, $quote, $event->event_vars);
// foreach ($invoices as $invoice) {
// //todo we may need to add additional logic if in the future we apply payments to other entity Types, not just invoices
// $fields->invoice_id = $invoice->id;
// $this->activity_repo->save($fields, $invoice, $event->event_vars);
// }
// if (count($invoices) == 0) {
// $this->activity_repo->save($fields, $payment, $event->event_vars);
// }
}
}

View File

@ -0,0 +1,57 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Quote;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\ClientContact;
use App\Models\InvoiceInvitation;
use App\Repositories\ActivityRepository;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
class QuoteEmailActivity implements ShouldQueue
{
protected $activity_repo;
/**
* Create the event listener.
*
* @return void
*/
public function __construct(ActivityRepository $activity_repo)
{
$this->activity_repo = $activity_repo;
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
MultiDB::setDb($event->company->db);
$fields = new \stdClass;
$fields->quote_id = $event->invitation->quote->id;
$fields->user_id = $event->invitation->quote->user_id;
$fields->company_id = $event->invitation->quote->company_id;
$fields->client_contact_id = $event->invitation->quote->client_contact_id;
$fields->activity_type_id = Activity::EMAIL_QUOTE;
$this->activity_repo->save($fields, $event->invitation->quote, $event->event_vars);
}
}

View File

@ -0,0 +1,59 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Quote;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\ClientContact;
use App\Models\QuoteInvitation;
use App\Repositories\ActivityRepository;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
class QuoteViewedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* Create the event listener.
*
* @return void
*/
public function __construct(ActivityRepository $activity_repo)
{
$this->activity_repo = $activity_repo;
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
MultiDB::setDb($event->company->db);
$fields = new \stdClass;
$fields->user_id = $event->quote->user_id;
$fields->company_id = $event->quote->company_id;
$fields->activity_type_id = Activity::VIEW_QUOTE;
$fields->client_id = $event->invitation->client_id;
$fields->client_contact_id = $event->invitation->client_contact_id;
$fields->invitation_id = $event->invitation->id;
$fields->quote_id = $event->invitation->quote_id;
$this->activity_repo->save($fields, $event->quote, $event->event_vars);
}
}

View File

@ -30,12 +30,12 @@ class Activity extends StaticModel
const DELETE_PAYMENT=13; //
const CREATE_CREDIT=14; //
const UPDATE_CREDIT=15; //
const ARCHIVE_CREDIT=16;
const DELETE_CREDIT=17;
const CREATE_QUOTE=18;
const UPDATE_QUOTE=19;
const EMAIL_QUOTE=20;
const VIEW_QUOTE=21;
const ARCHIVE_CREDIT=16; //
const DELETE_CREDIT=17; //
const CREATE_QUOTE=18; //
const UPDATE_QUOTE=19; //
const EMAIL_QUOTE=20; //
const VIEW_QUOTE=21; //
const ARCHIVE_QUOTE=22;
const DELETE_QUOTE=23;
const RESTORE_QUOTE=24;

View File

@ -23,6 +23,7 @@ use App\Events\Company\CompanyDocumentsDeleted;
use App\Events\Contact\ContactLoggedIn;
use App\Events\Credit\CreditWasArchived;
use App\Events\Credit\CreditWasCreated;
use App\Events\Credit\CreditWasDeleted;
use App\Events\Credit\CreditWasEmailedAndFailed;
use App\Events\Credit\CreditWasMarkedSent;
use App\Events\Credit\CreditWasUpdated;
@ -45,19 +46,26 @@ use App\Events\Payment\PaymentWasRefunded;
use App\Events\Payment\PaymentWasUpdated;
use App\Events\Payment\PaymentWasVoided;
use App\Events\Quote\QuoteWasApproved;
use App\Events\Quote\QuoteWasCreated;
use App\Events\Quote\QuoteWasEmailed;
use App\Events\Quote\QuoteWasUpdated;
use App\Events\Quote\QuoteWasViewed;
use App\Events\User\UserLoggedIn;
use App\Events\User\UserWasCreated;
use App\Events\User\UserWasDeleted;
use App\Listeners\Activity\ArchivedClientActivity;
use App\Listeners\Activity\CreatedClientActivity;
use App\Listeners\Activity\CreatedCreditActivity;
use App\Listeners\Activity\CreatedQuoteActivity;
use App\Listeners\Activity\CreditArchivedActivity;
use App\Listeners\Activity\DeleteClientActivity;
use App\Listeners\Activity\DeleteCreditActivity;
use App\Listeners\Activity\PaymentCreatedActivity;
use App\Listeners\Activity\PaymentDeletedActivity;
use App\Listeners\Activity\PaymentRefundedActivity;
use App\Listeners\Activity\PaymentUpdatedActivity;
use App\Listeners\Activity\PaymentVoidedActivity;
use App\Listeners\Activity\QuoteUpdatedActivity;
use App\Listeners\Activity\RestoreClientActivity;
use App\Listeners\Activity\UpdatedCreditActivity;
use App\Listeners\Contact\UpdateContactLastLogin;
@ -76,6 +84,8 @@ use App\Listeners\Invoice\UpdateInvoiceActivity;
use App\Listeners\Invoice\UpdateInvoiceInvitations;
use App\Listeners\Misc\InvitationViewedListener;
use App\Listeners\Payment\PaymentNotification;
use App\Listeners\Quote\QuoteEmailActivity;
use App\Listeners\Quote\QuoteViewedActivity;
use App\Listeners\Quote\ReachWorkflowSettings;
use App\Listeners\SendVerificationNotification;
use App\Listeners\SetDBListener;
@ -151,6 +161,9 @@ class EventServiceProvider extends ServiceProvider
CreditWasCreated::class => [
CreatedCreditActivity::class,
],
CreditWasDeleted::class => [
DeleteCreditActivity::class,
],
CreditWasUpdated::class => [
UpdatedCreditActivity::class,
],
@ -216,6 +229,19 @@ class EventServiceProvider extends ServiceProvider
QuoteWasApproved::class => [
ReachWorkflowSettings::class,
],
QuoteWasCreated::class => [
CreatedQuoteActivity::class,
],
QuoteWasUpdated::class => [
QuoteUpdatedActivity::class,
],
QuoteWasEmailed::class => [
QuoteEmailActivity::class,
],
QuoteWasViewed::class => [
QuoteViewedActivity::class,
],
];
/**

View File

@ -178,7 +178,7 @@ class BaseRepository
public function getInvitation($invitation, $resource)
{
if (!array_key_exists('key', $invitation)) {
if (is_array($invitation) && !array_key_exists('key', $invitation)) {
return false;
}
@ -253,7 +253,15 @@ class BaseRepository
/* Get array of Keys which have been removed from the invitations array and soft delete each invitation */
$model->invitations->pluck('key')->diff($invitations->pluck('key'))->each(function ($invitation) use($resource){
$this->getInvitation($invitation, $resource)->delete();
// $this->getInvitation($invitation, $resource)->delete();
$invitation_class = sprintf("App\\Models\\%sInvitation", $resource);
$invitation = $invitation_class::whereRaw("BINARY `key`= ?", [$invitation])->first();
if($invitation)
$invitation->delete();
});
foreach ($data['invitations'] as $invitation) {

View File

@ -37,7 +37,7 @@ class TokenRepository extends BaseRepository
public function save(array $data, CompanyToken $company_token)
{
$company_token->fill($data);
$company_token->is_system = true;
$company_token->is_system = false;
$company_token->save();

View File

@ -161,11 +161,9 @@ class InvoiceService
/* One liners */
public function setDueDate()
{
if($this->invoice->due_date != '')
if($this->invoice->due_date != '' || $this->invoice->client->getSetting('payment_terms') == '')
return $this;
//$this->invoice->due_date = Carbon::now()->addDays($this->invoice->client->getSetting('payment_terms'));
$this->invoice->due_date = Carbon::parse($this->invoice->date)->addDays($this->invoice->client->getSetting('payment_terms'));
return $this;

View File

@ -68,19 +68,12 @@ class AccountTransformer extends EntityTransformer
'payment_id' => (string) $account->payment_id,
'trial_started' => (string) $account->trial_started,
'trial_plan' => (string) $account->trial_plan,
'pending_plan' => (string) $account->pending_plan,
'pending_term' => (string) $account->pending_term,
'plan_price' => (float) $account->plan_price,
'pending_plan_price' => (string) $account->pending_plan_price,
'num_users' => (int) $account->num_users,
'pending_num_users' => (int) $account->pending_num_users,
'utm_source' => (string) $account->utm_source,
'utm_medium' => (string) $account->utm_medium,
'utm_content' => (string) $account->utm_content,
'utm_term' => (string) $account->utm_term,
'discount' => (float) $account->discount,
'discount_expires' => (string) $account->discount_expires,
'bluevine_status' => (string) $account->bluevine_status,
'referral_code' => (string) $account->referral_code,
'latest_version' => (string)$account->latest_version,
'current_version' => (string)config('ninja.app_version'),

View File

@ -71,9 +71,43 @@ class SystemHealth
'env_writable' => self::checkEnvWritable(),
//'mail' => self::testMailServer(),
'simple_db_check' => (bool) self::simpleDbCheck(),
'npm_status' => self::checkNpm(),
'node_status' => self::checkNode(),
];
}
public static function checkNode()
{
try {
exec('node -v', $foo, $exitCode);
if ($exitCode === 0) {
return $foo[0];
}
} catch (\Exception $e) {
return false;
}
}
public static function checkNpm()
{
try {
exec('npm -v', $foo, $exitCode);
if ($exitCode === 0) {
return $foo[0];
}
}catch (\Exception $e) {
return false;
}
}
private static function simpleDbCheck() :bool
{
$result = true;

View File

@ -8,7 +8,7 @@ return [
'license' => env('NINJA_LICENSE', ''),
'version_url' => 'https://raw.githubusercontent.com/invoiceninja/invoiceninja/v2/VERSION.txt',
'app_name' => env('APP_NAME'),
'app_env' => env('APP_ENV', 'local'),
'app_env' => env('APP_ENV', 'selfhosted'),
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => env('APP_URL', ''),
'app_domain' => env('APP_DOMAIN', ''),
@ -56,7 +56,7 @@ return [
'datetime_format_id' => env('DEFAULT_DATETIME_FORMAT_ID', '1'),
'locale' => env('DEFAULT_LOCALE', 'en'),
'map_zoom' => env('DEFAULT_MAP_ZOOM', 10),
'payment_terms' => env('DEFAULT_PAYMENT_TERMS', "-1"),
'payment_terms' => env('DEFAULT_PAYMENT_TERMS', ""),
'military_time' => env('MILITARY_TIME', 0),
'first_day_of_week' => env('FIRST_DATE_OF_WEEK', 0),
'first_month_of_year' => env('FIRST_MONTH_OF_YEAR', '2000-01-01')

30
config/sentry.php Normal file
View File

@ -0,0 +1,30 @@
<?php
return [
'dsn' => env('SENTRY_LARAVEL_DSN', env('SENTRY_DSN')),
// capture release as git sha
// 'release' => trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')),
'breadcrumbs' => [
// Capture Laravel logs in breadcrumbs
'logs' => true,
// Capture SQL queries in breadcrumbs
'sql_queries' => true,
// Capture bindings on SQL queries logged in breadcrumbs
'sql_bindings' => true,
// Capture queue job information in breadcrumbs
'queue_info' => true,
// Capture command information in breadcrumbs
'command_info' => true,
],
// @see: https://docs.sentry.io/error-reporting/configuration/?platform=php#send-default-pii
'send_default_pii' => false,
'release' => config('ninja.app_version'),
];

View File

@ -112,13 +112,8 @@ class CreateUsersTable extends Migration
$table->date('trial_started')->nullable();
$table->enum('trial_plan', ['pro', 'enterprise'])->nullable();
$table->enum('pending_plan', ['pro', 'enterprise', 'free'])->nullable();
$table->enum('pending_term', ['month', 'year'])->nullable();
$table->decimal('plan_price', 7, 2)->nullable();
$table->decimal('pending_plan_price', 7, 2)->nullable();
$table->smallInteger('num_users')->default(1);
$table->smallInteger('pending_num_users')->default(1);
$table->string('utm_source')->nullable();
$table->string('utm_medium')->nullable();
@ -128,10 +123,6 @@ class CreateUsersTable extends Migration
$table->string('latest_version')->default('0.0.0');
$table->boolean('report_errors')->default(false);
$table->float('discount')->default(0);
$table->date('discount_expires')->nullable();
$table->enum('bluevine_status', ['ignored', 'signed_up'])->nullable();
$table->string('referral_code')->nullable();
$table->timestamps(6);

View File

@ -0,0 +1,32 @@
<?php
use App\Models\Company;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class UpdateEnabledModulesValue extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Company::cursor()->each(function ($company){
$company->enabled_modules = 32767;
$company->save();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -3238,5 +3238,7 @@ return [
'checkout_authorize_label' => 'Checkout.com can be can saved as payment method for future use, once you complete your first transaction. Don\'t forget to check "Save card" during payment process.',
'node_status_not_found' => 'I could not find Node anywhere. Is it installed?',
'npm_status_not_found' => 'I could not find NPM anywhere. Is it installed?',
];

View File

@ -61,6 +61,42 @@
@endif
</dd>
</div>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:flex sm:items-center">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.npm_status') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
@if($check['npm_status'])
<span class="alert alert-success block flex justify-between items-center">
<span>{{ $check['npm_status'] }} => {{ strtoupper(ctrans('texts.ok')) }}</span>
<span></span>
</span>
@else
<span class="alert alert-failure block flex justify-between items-center">
<span>{{ ctrans('texts.npm_status_not_found') }}</span>
<span></span>
</span>
@endif
</dd>
</div>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:flex sm:items-center">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.node_status') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
@if($check['node_status'])
<span class="alert alert-success block flex justify-between items-center">
<span>{{ $check['node_status'] }} => {{ strtoupper(ctrans('texts.ok')) }}</span>
<span></span>
</span>
@else
<span class="alert alert-failure block flex justify-between items-center">
<span>{{ ctrans('texts.node_status_not_found') }}</span>
<span></span>
</span>
@endif
</dd>
</div>
</dl>
</div>
</div>

View File

@ -34,6 +34,18 @@
@include('setup._issues')
@else
@if(!$check['npm_status'])
<div class="alert alert-success mt-4">
<p>NPM Version => {{$check['npm_status']}}</p>
</div>
@endif
@if(!$check['node_status'])
<div class="alert alert-success mt-4">
<p>Node Version => {{$check['node_status']}}</p>
</div>
@endif
@include('setup._application')
@include('setup._database')
@include('setup._mail')

View File

@ -142,6 +142,8 @@ trait MockAccountData
$company_token->account_id = $this->account->id;
$company_token->name = 'test token';
$company_token->token = $this->token;
$company_token->is_system = true;
$company_token->save();

View File

@ -41,7 +41,7 @@ class CompareObjectTest extends TestCase
$this->assertEquals($build_client_settings->timezone_id, 1);
$this->assertEquals($build_client_settings->language_id, 1);
$this->assertEquals($build_client_settings->payment_terms, -1);
$this->assertEquals($build_client_settings->payment_terms, '');
}
public function testDirectClientSettingsBuild()
@ -50,7 +50,7 @@ class CompareObjectTest extends TestCase
$this->assertEquals($settings->timezone_id, 1);
$this->assertEquals($settings->language_id, 1);
$this->assertEquals($settings->payment_terms, -1);
$this->assertEquals($settings->payment_terms, '');
$this->assertFalse($settings->auto_archive_invoice);
}
}