1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-29 20:57:11 +02:00

Merge pull request #5545 from turbo124/v5-stable

v5.1.55
This commit is contained in:
David Bomba 2021-04-28 11:28:30 +10:00 committed by GitHub
commit 8b860f7314
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 572 additions and 19 deletions

View File

@ -2,6 +2,15 @@
## [Unreleased (daily channel)](https://github.com/invoiceninja/invoiceninja/tree/v5-develop) ## [Unreleased (daily channel)](https://github.com/invoiceninja/invoiceninja/tree/v5-develop)
## Fixed: ## Fixed:
- Fix User created/updated/deleted Actvity display format
- Fix for Stripe autobill / token regression
## Added:
- Invoice / Quote / Credit created notifications
- Logout route - deletes all auth tokens
## [v5.1.54-release](https://github.com/invoiceninja/invoiceninja/releases/tag/v5.1.50-release)
## Fixed:
- Fixes for e-mails, encoding & parsing invalid HTML - Fixes for e-mails, encoding & parsing invalid HTML
## [v5.1.50-release](https://github.com/invoiceninja/invoiceninja/releases/tag/v5.1.50-release) ## [v5.1.50-release](https://github.com/invoiceninja/invoiceninja/releases/tag/v5.1.50-release)

View File

@ -1 +1 @@
5.1.54 5.1.55

View File

@ -183,6 +183,16 @@ class InvoiceSum
return $this; return $this;
} }
/**
* Allow us to get the entity without persisting it
* @return Invoice the temp
*/
public function getTempEntity()
{
$this->setCalculatedAttributes();
return $this->invoice;
}
public function getInvoice() public function getInvoice()
{ {
//Build invoice values here and return Invoice //Build invoice values here and return Invoice

View File

@ -196,6 +196,12 @@ class InvoiceSumInclusive
return $this->invoice; return $this->invoice;
} }
public function getTempEntity()
{
$this->setCalculatedAttributes();
return $this->invoice;
}
public function getInvoice() public function getInvoice()
{ {
//Build invoice values here and return Invoice //Build invoice values here and return Invoice

View File

@ -16,6 +16,7 @@ use App\DataMapper\Analytics\LoginSuccess;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Jobs\Account\CreateAccount; use App\Jobs\Account\CreateAccount;
use App\Jobs\Company\CreateCompanyToken;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Libraries\OAuth\OAuth; use App\Libraries\OAuth\OAuth;
use App\Libraries\OAuth\Providers\Google; use App\Libraries\OAuth\Providers\Google;
@ -199,6 +200,15 @@ class LoginController extends BaseController
$cu = CompanyUser::query() $cu = CompanyUser::query()
->where('user_id', auth()->user()->id); ->where('user_id', auth()->user()->id);
$cu->first()->account->companies->each(function ($company) use($cu, $request){
if($company->tokens()->where('is_system', true)->count() == 0)
{
CreateCompanyToken::dispatchNow($company, $cu->first()->user, $request->server('HTTP_USER_AGENT'));
}
});
return $this->listResponse($cu); return $this->listResponse($cu);
} else { } else {
@ -262,9 +272,16 @@ class LoginController extends BaseController
$cu = CompanyUser::query() $cu = CompanyUser::query()
->where('user_id', $company_token->user_id); ->where('user_id', $company_token->user_id);
//->where('company_id', $company_token->company_id);
//$ct = CompanyUser::whereUserId(auth()->user()->id);
$cu->first()->account->companies->each(function ($company) use($cu, $request){
if($company->tokens()->where('is_system', true)->count() == 0)
{
CreateCompanyToken::dispatchNow($company, $cu->first()->user, $request->server('HTTP_USER_AGENT'));
}
});
return $this->refreshResponse($cu); return $this->refreshResponse($cu);
} }
@ -317,6 +334,14 @@ class LoginController extends BaseController
$cu = CompanyUser::query() $cu = CompanyUser::query()
->where('user_id', auth()->user()->id); ->where('user_id', auth()->user()->id);
$cu->first()->account->companies->each(function ($company) use($cu){
if($company->tokens()->where('is_system', true)->count() == 0)
{
CreateCompanyToken::dispatchNow($company, $cu->first()->user, request()->server('HTTP_USER_AGENT'));
}
});
return $this->listResponse($cu); return $this->listResponse($cu);
} }
@ -348,9 +373,17 @@ class LoginController extends BaseController
$timeout = auth()->user()->company()->default_password_timeout / 60000; $timeout = auth()->user()->company()->default_password_timeout / 60000;
Cache::put(auth()->user()->hashed_id.'_logged_in', Str::random(64), $timeout); Cache::put(auth()->user()->hashed_id.'_logged_in', Str::random(64), $timeout);
$ct = CompanyUser::whereUserId(auth()->user()->id); $cu = CompanyUser::whereUserId(auth()->user()->id);
return $this->listResponse($ct); $cu->first()->account->companies->each(function ($company) use($cu){
if($company->tokens()->where('is_system', true)->count() == 0)
{
CreateCompanyToken::dispatchNow($company, $cu->first()->user, request()->server('HTTP_USER_AGENT'));
}
});
return $this->listResponse($cu);
} }
return response() return response()

View File

@ -12,7 +12,9 @@
namespace App\Http\Requests\Invoice; namespace App\Http\Requests\Invoice;
use App\Http\Requests\Request; use App\Http\Requests\Request;
use App\Http\ValidationRules\Invoice\InvoiceBalanceSanity;
use App\Http\ValidationRules\Invoice\LockedInvoiceRule; use App\Http\ValidationRules\Invoice\LockedInvoiceRule;
use App\Models\Invoice;
use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\ChecksEntityStatus;
use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\CleanLineItems;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
@ -55,6 +57,9 @@ class UpdateInvoiceRequest extends Request
$rules['line_items'] = 'array'; $rules['line_items'] = 'array';
if($this->input('status_id') != Invoice::STATUS_DRAFT)
$rules['balance'] = new InvoiceBalanceSanity($this->invoice, $this->all());
return $rules; return $rules;
} }

View File

@ -0,0 +1,77 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\ValidationRules\Invoice;
use App\Models\Invoice;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\DB;
/**
* Class LockedInvoiceRule.
*/
class InvoiceBalanceSanity implements Rule
{
public $invoice;
public $input;
private $message;
public function __construct(Invoice $invoice, $input)
{
$this->invoice = $invoice;
$this->input = $input;
}
/**
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
return $this->checkIfInvoiceBalanceIsSane(); //if it exists, return false!
}
/**
* @return string
*/
public function message()
{
return $this->message;
}
/**
* @return bool
*/
private function checkIfInvoiceBalanceIsSane() : bool
{
$this->invoice->line_items = $this->input['line_items'];
DB::beginTransaction();
$temp_invoice = $this->invoice->calc()->getTempEntity();
DB::rollBack();
if($temp_invoice->balance < 0){
$this->message = 'Invoice balance cannot go negative';
return false;
}
return true;
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* Credit Ninja (https://creditninja.com).
*
* @link https://github.com/creditninja/creditninja source repository
*
* @copyright Copyright (c) 2021. Credit Ninja LLC (https://creditninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Credit;
use App\Jobs\Mail\NinjaMailer;
use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
use App\Libraries\MultiDB;
use App\Mail\Admin\EntityCreatedObject;
use App\Notifications\Admin\EntitySentNotification;
use App\Utils\Traits\Notifications\UserNotifies;
use Illuminate\Contracts\Queue\ShouldQueue;
class CreditCreatedNotification implements ShouldQueue
{
use UserNotifies;
public function __construct()
{
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
MultiDB::setDb($event->company->db);
$first_notification_sent = true;
$credit = $event->credit;
$nmo = new NinjaMailerObject;
$nmo->mailable = new NinjaMailer( (new EntityCreatedObject($credit, 'credit'))->build() );
$nmo->company = $credit->company;
$nmo->settings = $credit->company->settings;
/* We loop through each user and determine whether they need to be notified */
foreach ($event->company->company_users as $company_user) {
/* The User */
$user = $company_user->user;
/* This is only here to handle the alternate message channels - ie Slack */
// $notification = new EntitySentNotification($event->invitation, 'credit');
/* Returns an array of notification methods */
$methods = $this->findUserNotificationTypes($credit->invitations()->first(), $company_user, 'credit', ['all_notifications', 'credit_created', 'credit_created_all']);
/* If one of the methods is email then we fire the EntitySentMailer */
if (($key = array_search('mail', $methods)) !== false && $first_notification_sent === true) {
unset($methods[$key]);
$nmo->to_user = $user;
NinjaMailerJob::dispatch($nmo);
/* This prevents more than one notification being sent */
$first_notification_sent = false;
}
/* Override the methods in the Notification Class */
// $notification->method = $methods;
// Notify on the alternate channels
// $user->notify($notification);
}
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Invoice;
use App\Jobs\Mail\NinjaMailer;
use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
use App\Libraries\MultiDB;
use App\Mail\Admin\EntityCreatedObject;
use App\Notifications\Admin\EntitySentNotification;
use App\Utils\Traits\Notifications\UserNotifies;
use Illuminate\Contracts\Queue\ShouldQueue;
class InvoiceCreatedNotification implements ShouldQueue
{
use UserNotifies;
public function __construct()
{
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
MultiDB::setDb($event->company->db);
$first_notification_sent = true;
$invoice = $event->invoice;
$nmo = new NinjaMailerObject;
$nmo->mailable = new NinjaMailer( (new EntityCreatedObject($invoice, 'invoice'))->build() );
$nmo->company = $invoice->company;
$nmo->settings = $invoice->company->settings;
/* We loop through each user and determine whether they need to be notified */
foreach ($event->company->company_users as $company_user) {
/* The User */
$user = $company_user->user;
/* This is only here to handle the alternate message channels - ie Slack */
// $notification = new EntitySentNotification($event->invitation, 'invoice');
/* Returns an array of notification methods */
$methods = $this->findUserNotificationTypes($invoice->invitations()->first(), $company_user, 'invoice', ['all_notifications', 'invoice_created', 'invoice_created_all']);
/* If one of the methods is email then we fire the EntitySentMailer */
if (($key = array_search('mail', $methods)) !== false && $first_notification_sent === true) {
unset($methods[$key]);
$nmo->to_user = $user;
NinjaMailerJob::dispatch($nmo);
/* This prevents more than one notification being sent */
$first_notification_sent = false;
}
/* Override the methods in the Notification Class */
// $notification->method = $methods;
// Notify on the alternate channels
// $user->notify($notification);
}
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* Quote Ninja (https://quoteninja.com).
*
* @link https://github.com/quoteninja/quoteninja source repository
*
* @copyright Copyright (c) 2021. Quote Ninja LLC (https://quoteninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Quote;
use App\Jobs\Mail\NinjaMailer;
use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
use App\Libraries\MultiDB;
use App\Mail\Admin\EntityCreatedObject;
use App\Notifications\Admin\EntitySentNotification;
use App\Utils\Traits\Notifications\UserNotifies;
use Illuminate\Contracts\Queue\ShouldQueue;
class QuoteCreatedNotification implements ShouldQueue
{
use UserNotifies;
public function __construct()
{
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
MultiDB::setDb($event->company->db);
$first_notification_sent = true;
$quote = $event->quote;
$nmo = new NinjaMailerObject;
$nmo->mailable = new NinjaMailer( (new EntityCreatedObject($quote, 'quote'))->build() );
$nmo->company = $quote->company;
$nmo->settings = $quote->company->settings;
/* We loop through each user and determine whether they need to be notified */
foreach ($event->company->company_users as $company_user) {
/* The User */
$user = $company_user->user;
/* This is only here to handle the alternate message channels - ie Slack */
// $notification = new EntitySentNotification($event->invitation, 'quote');
/* Returns an array of notification methods */
$methods = $this->findUserNotificationTypes($quote->invitations()->first(), $company_user, 'quote', ['all_notifications', 'quote_created', 'quote_created_all']);
/* If one of the methods is email then we fire the EntitySentMailer */
if (($key = array_search('mail', $methods)) !== false && $first_notification_sent === true) {
unset($methods[$key]);
$nmo->to_user = $user;
NinjaMailerJob::dispatch($nmo);
/* This prevents more than one notification being sent */
$first_notification_sent = false;
}
/* Override the methods in the Notification Class */
// $notification->method = $methods;
// Notify on the alternate channels
// $user->notify($notification);
}
}
}

View File

@ -43,8 +43,8 @@ class ArchivedUserActivity implements ShouldQueue
$fields = new stdClass; $fields = new stdClass;
$fields->user_id = $event->user->id; $fields->user_id = $event->creating_user->id;
$fields->notes = $event->creating_user->present()->name . " Archived User"; $fields->notes = $event->creating_user->present()->name . " Archived User " . $event->user->present()->name();
$fields->company_id = $event->company->id; $fields->company_id = $event->company->id;
$fields->activity_type_id = Activity::ARCHIVE_USER; $fields->activity_type_id = Activity::ARCHIVE_USER;

View File

@ -43,8 +43,8 @@ class CreatedUserActivity implements ShouldQueue
$fields = new stdClass; $fields = new stdClass;
$fields->user_id = $event->user->id; $fields->user_id = $event->creating_user->id;
$fields->notes = $event->creating_user->present()->name() . " Created the user"; $fields->notes = $event->creating_user->present()->name() . " Created the user " . $event->user->present()->name();
$fields->company_id = $event->company->id; $fields->company_id = $event->company->id;
$fields->activity_type_id = Activity::CREATE_USER; $fields->activity_type_id = Activity::CREATE_USER;

View File

@ -48,8 +48,8 @@ class DeletedUserActivity implements ShouldQueue
$fields = new stdClass; $fields = new stdClass;
$fields->user_id = $event->user->id; $fields->user_id = $event->creating_user->id;
$fields->notes = $event->creating_user->present()->name . " Deleted User"; $fields->notes = $event->creating_user->present()->name() . " Deleted the user " . $event->user->present()->name();
$fields->company_id = $event->company->id; $fields->company_id = $event->company->id;
$fields->activity_type_id = Activity::DELETE_USER; $fields->activity_type_id = Activity::DELETE_USER;

View File

@ -43,8 +43,8 @@ class RestoredUserActivity implements ShouldQueue
$fields = new stdClass; $fields = new stdClass;
$fields->user_id = $event->user->id; $fields->user_id = $creating_user->user->id;
$fields->notes = $event->creating_user->present()->name() . " Restored user"; $fields->notes = $event->creating_user->present()->name() . " Restored user " . $event->user->present()->name();
$fields->company_id = $event->company->id; $fields->company_id = $event->company->id;
$fields->activity_type_id = Activity::RESTORE_USER; $fields->activity_type_id = Activity::RESTORE_USER;

View File

@ -42,8 +42,9 @@ class UpdatedUserActivity implements ShouldQueue
MultiDB::setDb($event->company->db); MultiDB::setDb($event->company->db);
$fields = new stdClass; $fields = new stdClass;
$fields->user_id = $event->user->id; $fields->user_id = $event->creating_user->id;
$fields->notes = $event->creating_user->present()->name . " Updated user"; $fields->notes = $event->creating_user->present()->name() . " Updated user " . $event->user->present()->name();
$fields->company_id = $event->company->id; $fields->company_id = $event->company->id;
$fields->activity_type_id = Activity::UPDATE_USER; $fields->activity_type_id = Activity::UPDATE_USER;

View File

@ -0,0 +1,127 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Mail\Admin;
use App\Utils\Number;
use stdClass;
class EntityCreatedObject
{
public $entity_type;
public $entity;
public $contact;
public $company;
public $settings;
private $template_subject;
private $template_body;
public function __construct($entity, $entity_type)
{
$this->entity_type = $entity_type;
$this->entity = $entity;
}
public function build()
{
$this->contact = $this->entity->invitations()->first()->contact;
$this->company = $this->entity->company;
$this->setTemplate();
$mail_obj = new stdClass;
$mail_obj->amount = $this->getAmount();
$mail_obj->subject = $this->getSubject();
$mail_obj->data = $this->getData();
$mail_obj->markdown = 'email.admin.generic';
$mail_obj->tag = $this->company->company_key;
return $mail_obj;
}
private function setTemplate()
{
// nlog($this->template);
switch ($this->entity_type) {
case 'invoice':
$this->template_subject = "texts.notification_invoice_created_subject";
$this->template_body = "texts.notification_invoice_sent";
break;
case 'quote':
$this->template_subject = "texts.notification_quote_created_subject";
$this->template_body = "texts.notification_quote_sent";
break;
case 'credit':
$this->template_subject = "texts.notification_credit_created_subject";
$this->template_body = "texts.notification_credit_sent";
break;
default:
$this->template_subject = "texts.notification_invoice_created_subject";
$this->template_body = "texts.notification_invoice_sent";
break;
}
}
private function getAmount()
{
return Number::formatMoney($this->entity->amount, $this->entity->client);
}
private function getSubject()
{
return
ctrans(
$this->template_subject,
[
'client' => $this->contact->present()->name(),
'invoice' => $this->entity->number,
]
);
}
private function getMessage()
{
return ctrans(
$this->template_body,
[
'amount' => $this->getAmount(),
'client' => $this->contact->present()->name(),
'invoice' => $this->entity->number,
]
);
}
private function getData()
{
$settings = $this->entity->client->getMergedSettings();
return [
'title' => $this->getSubject(),
'message' => $this->getMessage(),
'url' => $this->entity->invitations()->first()->getAdminLink(),
'button' => ctrans("texts.view_{$this->entity_type}"),
'signature' => $settings->email_signature,
'logo' => $this->company->present()->logo(),
'settings' => $settings,
'whitelabel' => $this->company->account->isPaid() ? true : false,
];
}
}

View File

@ -69,14 +69,18 @@ class Charge
$response = null; $response = null;
try { try {
$response = $local_stripe->paymentIntents->create([
$data = [
'amount' => $this->stripe->convertToStripeAmount($amount, $this->stripe->client->currency()->precision), 'amount' => $this->stripe->convertToStripeAmount($amount, $this->stripe->client->currency()->precision),
'currency' => $this->stripe->client->getCurrencyCode(), 'currency' => $this->stripe->client->getCurrencyCode(),
'payment_method' => $cgt->token, 'payment_method' => $cgt->token,
'customer' => $cgt->gateway_customer_reference, 'customer' => $cgt->gateway_customer_reference,
'confirm' => true, 'confirm' => true,
'description' => $description, 'description' => $description,
]); ];
$response = $this->stripe->createPaymentIntent($data);
// $response = $local_stripe->paymentIntents->create($data);
SystemLogger::dispatch($response, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_STRIPE, $this->stripe->client); SystemLogger::dispatch($response, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_STRIPE, $this->stripe->client);
} catch (\Exception $e) { } catch (\Exception $e) {

View File

@ -127,6 +127,7 @@ use App\Listeners\Activity\VendorDeletedActivity;
use App\Listeners\Activity\VendorRestoredActivity; use App\Listeners\Activity\VendorRestoredActivity;
use App\Listeners\Activity\VendorUpdatedActivity; use App\Listeners\Activity\VendorUpdatedActivity;
use App\Listeners\Contact\UpdateContactLastLogin; use App\Listeners\Contact\UpdateContactLastLogin;
use App\Listeners\Credit\CreditCreatedNotification;
use App\Listeners\Credit\CreditEmailedNotification; use App\Listeners\Credit\CreditEmailedNotification;
use App\Listeners\Credit\CreditRestoredActivity; use App\Listeners\Credit\CreditRestoredActivity;
use App\Listeners\Credit\CreditViewedActivity; use App\Listeners\Credit\CreditViewedActivity;
@ -136,6 +137,7 @@ use App\Listeners\Invoice\CreateInvoiceHtmlBackup;
use App\Listeners\Invoice\CreateInvoicePdf; use App\Listeners\Invoice\CreateInvoicePdf;
use App\Listeners\Invoice\InvoiceArchivedActivity; use App\Listeners\Invoice\InvoiceArchivedActivity;
use App\Listeners\Invoice\InvoiceCancelledActivity; use App\Listeners\Invoice\InvoiceCancelledActivity;
use App\Listeners\Invoice\InvoiceCreatedNotification;
use App\Listeners\Invoice\InvoiceDeletedActivity; use App\Listeners\Invoice\InvoiceDeletedActivity;
use App\Listeners\Invoice\InvoiceEmailActivity; use App\Listeners\Invoice\InvoiceEmailActivity;
use App\Listeners\Invoice\InvoiceEmailFailedActivity; use App\Listeners\Invoice\InvoiceEmailFailedActivity;
@ -155,6 +157,7 @@ use App\Listeners\Payment\PaymentNotification;
use App\Listeners\Payment\PaymentRestoredActivity; use App\Listeners\Payment\PaymentRestoredActivity;
use App\Listeners\Quote\QuoteApprovedActivity; use App\Listeners\Quote\QuoteApprovedActivity;
use App\Listeners\Quote\QuoteArchivedActivity; use App\Listeners\Quote\QuoteArchivedActivity;
use App\Listeners\Quote\QuoteCreatedNotification;
use App\Listeners\Quote\QuoteDeletedActivity; use App\Listeners\Quote\QuoteDeletedActivity;
use App\Listeners\Quote\QuoteEmailActivity; use App\Listeners\Quote\QuoteEmailActivity;
use App\Listeners\Quote\QuoteEmailedNotification; use App\Listeners\Quote\QuoteEmailedNotification;
@ -260,6 +263,7 @@ class EventServiceProvider extends ServiceProvider
], ],
CreditWasCreated::class => [ CreditWasCreated::class => [
CreatedCreditActivity::class, CreatedCreditActivity::class,
CreditCreatedNotification::class,
], ],
CreditWasDeleted::class => [ CreditWasDeleted::class => [
DeleteCreditActivity::class, DeleteCreditActivity::class,
@ -318,6 +322,7 @@ class EventServiceProvider extends ServiceProvider
], ],
InvoiceWasCreated::class => [ InvoiceWasCreated::class => [
CreateInvoiceActivity::class, CreateInvoiceActivity::class,
InvoiceCreatedNotification::class,
// CreateInvoicePdf::class, // CreateInvoicePdf::class,
], ],
InvoiceWasPaid::class => [ InvoiceWasPaid::class => [
@ -373,6 +378,7 @@ class EventServiceProvider extends ServiceProvider
], ],
QuoteWasCreated::class => [ QuoteWasCreated::class => [
CreatedQuoteActivity::class, CreatedQuoteActivity::class,
QuoteCreatedNotification::class,
], ],
QuoteWasUpdated::class => [ QuoteWasUpdated::class => [
QuoteUpdatedActivity::class, QuoteUpdatedActivity::class,

View File

@ -302,8 +302,14 @@ class BaseRepository
/* Perform model specific tasks */ /* Perform model specific tasks */
if ($model instanceof Invoice) { if ($model instanceof Invoice) {
nlog("in base");
nlog($state['finished_amount']);
nlog($state['starting_amount']);
nlog($model->status_id);
if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) { if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) {
$model->service()->updateStatus()->save();
$model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount']), "Update adjustment for invoice {$model->number}"); $model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount']), "Update adjustment for invoice {$model->number}");
$model->client->service()->updateBalance(($state['finished_amount'] - $state['starting_amount']))->save(); $model->client->service()->updateBalance(($state['finished_amount'] - $state['starting_amount']))->save();

View File

@ -14,8 +14,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', ''), 'app_domain' => env('APP_DOMAIN', ''),
'app_version' => '5.1.54', 'app_version' => '5.1.55',
'app_tag' => '5.1.54-release', 'app_tag' => '5.1.55-release',
'minimum_client_version' => '5.0.16', 'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1', 'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false), 'api_secret' => env('API_SECRET', false),

View File

@ -4204,6 +4204,22 @@ $LANG = array(
'promo_code' => 'Promo code', 'promo_code' => 'Promo code',
'recurring_invoice_issued_to' => 'Recurring invoice issued to', 'recurring_invoice_issued_to' => 'Recurring invoice issued to',
'subscription' => 'Subscription', 'subscription' => 'Subscription',
'new_subscription' => 'New Subscription',
'deleted_subscription' => 'Successfully deleted subscription',
'removed_subscription' => 'Successfully removed subscription',
'restored_subscription' => 'Successfully restored subscription',
'search_subscription' => 'Search 1 Subscription',
'search_subscriptions' => 'Search :count Subscriptions',
'subdomain_is_not_available' => 'Subdomain is not available',
'connect_gmail' => 'Connect Gmail',
'disconnect_gmail' => 'Disconnect Gmail',
'connected_gmail' => 'Successfully connected Gmail',
'disconnected_gmail' => 'Successfully disconnected Gmail',
'update_fail_help' => 'Changes to the codebase may be blocking the update, you can run this command to discard the changes:',
'client_id_number' => 'Client ID Number',
'count_minutes' => ':count Minutes',
'password_timeout' => 'Password Timeout',
'shared_invoice_credit_counter' => 'Shared Invoice/Credit Counter',
'activity_80' => ':user created subscription :subscription', 'activity_80' => ':user created subscription :subscription',
'activity_81' => ':user updated subscription :subscription', 'activity_81' => ':user updated subscription :subscription',
@ -4212,6 +4228,13 @@ $LANG = array(
'activity_84' => ':user restored subscription :subscription', 'activity_84' => ':user restored subscription :subscription',
'amount_greater_than_balance_v5' => 'The amount is greater than the invoice balance. You cannot overpay an invoice.', 'amount_greater_than_balance_v5' => 'The amount is greater than the invoice balance. You cannot overpay an invoice.',
'click_to_continue' => 'Click to continue', 'click_to_continue' => 'Click to continue',
'notification_invoice_created_subject' => 'Invoice :invoice was created to :client',
'notification_invoice_created_subject' => 'Invoice :invoice was created for :client',
'notification_quote_created_subject' => 'Quote :invoice was created to :client',
'notification_quote_created_subject' => 'Quote :invoice was created for :client',
'notification_credit_created_subject' => 'Credit :invoice was created to :client',
'notification_credit_created_subject' => 'Credit :invoice was created for :client',
); );
return $LANG; return $LANG;