From ae0ff13e92f35a04c7a928f92fd294c51632afde Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 5 Jan 2022 10:02:46 +1100 Subject: [PATCH 1/6] Handle negative payments - update client.paid_to_date --- app/Repositories/PaymentRepository.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/Repositories/PaymentRepository.php b/app/Repositories/PaymentRepository.php index 4ea1e65340e3..a4a70c834cfe 100644 --- a/app/Repositories/PaymentRepository.php +++ b/app/Repositories/PaymentRepository.php @@ -47,9 +47,13 @@ class PaymentRepository extends BaseRepository { */ public function save(array $data, Payment $payment): ?Payment { - if ($payment->amount >= 0) { + // if ($payment->amount >= 0) { + // return $this->applyPayment($data, $payment); + // } + + return $this->applyPayment($data, $payment); - } + return $payment; } @@ -80,8 +84,8 @@ class PaymentRepository extends BaseRepository { $client->service()->updatePaidToDate($data['amount'])->save(); } - elseif($data['amount'] >0){ - + // elseif($data['amount'] >0){ + else{ //this fixes an edge case with unapplied payments $client->service()->updatePaidToDate($data['amount'])->save(); } From 1efdd262fe764d69ce1b72a7f712c76705d418db Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 5 Jan 2022 14:41:57 +1100 Subject: [PATCH 2/6] Slack notifications for bounce/spam emails --- app/Http/Controllers/PostMarkController.php | 10 +++ app/Jobs/Company/CompanyImport.php | 3 +- app/Jobs/RecurringInvoice/SendRecurring.php | 2 +- .../Ninja/EmailBounceNotification.php | 88 +++++++++++++++++++ .../Ninja/EmailSpamNotification.php | 88 +++++++++++++++++++ app/Services/Invoice/AutoBillInvoice.php | 3 +- 6 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 app/Notifications/Ninja/EmailBounceNotification.php create mode 100644 app/Notifications/Ninja/EmailSpamNotification.php diff --git a/app/Http/Controllers/PostMarkController.php b/app/Http/Controllers/PostMarkController.php index 60bb918e688a..5401808119a0 100644 --- a/app/Http/Controllers/PostMarkController.php +++ b/app/Http/Controllers/PostMarkController.php @@ -20,6 +20,8 @@ use App\Models\InvoiceInvitation; use App\Models\QuoteInvitation; use App\Models\RecurringInvoiceInvitation; use App\Models\SystemLog; +use App\Notifications\Ninja\EmailBounceNotification; +use App\Notifications\Ninja\EmailSpamNotification; use Illuminate\Http\Request; use Turbo124\Beacon\Facades\LightLogs; @@ -173,6 +175,10 @@ class PostMarkController extends BaseController LightLogs::create($bounce)->queue(); SystemLogger::dispatch($request->all(), SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company); + + if(config('ninja.notification.slack')) + $this->invitation->company->notification(new EmailBounceNotification($this->invitation->company->account))->ninja(); + } // { @@ -215,6 +221,10 @@ class PostMarkController extends BaseController LightLogs::create($spam)->queue(); SystemLogger::dispatch($request->all(), SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company); + + if(config('ninja.notification.slack')) + $this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja(); + } private function discoverInvitation($message_id) diff --git a/app/Jobs/Company/CompanyImport.php b/app/Jobs/Company/CompanyImport.php index 52fbdb5b949d..88ee380f3cfc 100644 --- a/app/Jobs/Company/CompanyImport.php +++ b/app/Jobs/Company/CompanyImport.php @@ -335,11 +335,12 @@ class CompanyImport implements ShouldQueue } } - if($this->company->account->isFreeHostedClient() && $client_count = count($this->getObject('clients', true)) > config('ninja.quotas.free.clients')){ + if($this->company->account->isFreeHostedClient() && (count($this->getObject('clients', true)) > config('ninja.quotas.free.clients')) ){ nlog("client quota busted"); $client_limit = config('ninja.quotas.free.clients'); + $client_count = count($this->getObject('clients', true)); $this->message = "You are attempting to import ({$client_count}) clients, your current plan allows a total of ({$client_limit})"; diff --git a/app/Jobs/RecurringInvoice/SendRecurring.php b/app/Jobs/RecurringInvoice/SendRecurring.php index 4d992607a054..8db0d968c122 100644 --- a/app/Jobs/RecurringInvoice/SendRecurring.php +++ b/app/Jobs/RecurringInvoice/SendRecurring.php @@ -135,7 +135,7 @@ class SendRecurring implements ShouldQueue if ($invitation->contact && !$invitation->contact->trashed() && strlen($invitation->contact->email) >=1 && $invoice->client->getSetting('auto_email_invoice')) { try{ - EmailEntity::dispatch($invitation, $invoice->company)->delay(now()->addSeconds(1)); + EmailEntity::dispatch($invitation, $invoice->company); } catch(\Exception $e) { nlog($e->getMessage()); diff --git a/app/Notifications/Ninja/EmailBounceNotification.php b/app/Notifications/Ninja/EmailBounceNotification.php new file mode 100644 index 000000000000..91ba5576150c --- /dev/null +++ b/app/Notifications/Ninja/EmailBounceNotification.php @@ -0,0 +1,88 @@ +account = $account; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['slack']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + public function toSlack($notifiable) + { + + $content = "Email bounce notification for Account {$this->account->key} \n"; + + $owner = $this->account->companies()->first()->owner(); + + $content .= "Owner {$owner->present()->name() } | {$owner->email}"; + + return (new SlackMessage) + ->success() + ->from(ctrans('texts.notification_bot')) + ->image('https://app.invoiceninja.com/favicon.png') + ->content($content); + } +} diff --git a/app/Notifications/Ninja/EmailSpamNotification.php b/app/Notifications/Ninja/EmailSpamNotification.php new file mode 100644 index 000000000000..2044a870a1bd --- /dev/null +++ b/app/Notifications/Ninja/EmailSpamNotification.php @@ -0,0 +1,88 @@ +account = $account; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['slack']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + public function toSlack($notifiable) + { + + $content = "Email SPAM notification for Account {$this->account->key} \n"; + + $owner = $this->account->companies()->first()->owner(); + + $content .= "Owner {$owner->present()->name() } | {$owner->email}"; + + return (new SlackMessage) + ->success() + ->from(ctrans('texts.notification_bot')) + ->image('https://app.invoiceninja.com/favicon.png') + ->content($content); + } +} diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index 2771c3409a2a..43878f421c92 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -123,7 +123,8 @@ class AutoBillInvoice extends AbstractService ->tokenBilling($gateway_token, $payment_hash); } catch(\Exception $e){ - nlog($e->getMessage()); + nlog("payment NOT captured for ". $this->invoice->number . " with error " . $e->getMessage()); + // nlog($e->getMessage()); } if($payment){ From 2362ecb137b2040b923f6a920aa6fed0be515899 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 5 Jan 2022 15:32:07 +1100 Subject: [PATCH 3/6] Minor Fixes --- app/Models/Invoice.php | 1 + app/Services/Invoice/AutoBillInvoice.php | 1 + 2 files changed, 2 insertions(+) diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index a6297b7034d0..7d2257c6b19a 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -101,6 +101,7 @@ class Invoice extends BaseModel 'updated_at' => 'timestamp', 'created_at' => 'timestamp', 'deleted_at' => 'timestamp', + 'is_deleted' => 'bool', ]; protected $with = []; diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index 43878f421c92..025e9dcec957 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -105,6 +105,7 @@ class AutoBillInvoice extends AbstractService $fee = 0; /* Build payment hash */ + $payment_hash = PaymentHash::create([ 'hash' => Str::random(64), 'data' => ['invoices' => [['invoice_id' => $this->invoice->hashed_id, 'amount' => $amount, 'invoice_number' => $this->invoice->number]]], From 66843e6397ab2fe1e8cb49bed347c05d6b01a676 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 5 Jan 2022 17:12:10 +1100 Subject: [PATCH 4/6] Set locale for migrated companies --- app/Http/Controllers/MigrationController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/MigrationController.php b/app/Http/Controllers/MigrationController.php index 57abd6fb4f45..0b04cc504ea5 100644 --- a/app/Http/Controllers/MigrationController.php +++ b/app/Http/Controllers/MigrationController.php @@ -304,6 +304,7 @@ class MigrationController extends BaseController App::forgetInstance('translator'); $t = app('translator'); $t->replace(Ninja::transformTranslations($user->account->companies()->first()->settings)); + App::setLocale($user->account->companies()->first()->getLocale()); if(!$existing_company && $company_count >=10) { From 8bb0445725bcbea59da9b6ca455e21f8f9dee014 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 5 Jan 2022 17:26:23 +1100 Subject: [PATCH 5/6] Obfuscate tokens --- app/Http/Controllers/TokenController.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/Http/Controllers/TokenController.php b/app/Http/Controllers/TokenController.php index f095ca2070fe..aacdc145b84c 100644 --- a/app/Http/Controllers/TokenController.php +++ b/app/Http/Controllers/TokenController.php @@ -21,6 +21,7 @@ use App\Http\Requests\Token\StoreTokenRequest; use App\Http\Requests\Token\UpdateTokenRequest; use App\Models\CompanyToken; use App\Repositories\TokenRepository; +use App\Transformers\CompanyTokenHashedTransformer; use App\Transformers\CompanyTokenTransformer; use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\MakesHash; @@ -93,6 +94,8 @@ class TokenController extends BaseController */ public function index(TokenFilters $filters) { + $this->entity_transformer = CompanyTokenHashedTransformer::class; + $tokens = CompanyToken::filter($filters); return $this->listResponse($tokens); @@ -205,6 +208,8 @@ class TokenController extends BaseController */ public function edit(EditTokenRequest $request, CompanyToken $token) { + $this->entity_transformer = CompanyTokenHashedTransformer::class; + return $this->itemResponse($token); } @@ -265,6 +270,8 @@ class TokenController extends BaseController return $request->disallowUpdate(); } + $this->entity_transformer = CompanyTokenHashedTransformer::class; + $token = $this->token_repo->save($request->all(), $token); return $this->itemResponse($token->fresh()); @@ -419,6 +426,8 @@ class TokenController extends BaseController //may not need these destroy routes as we are using actions to 'archive/delete' $token->delete(); + $this->entity_transformer = CompanyTokenHashedTransformer::class; + return $this->itemResponse($token); } @@ -475,6 +484,9 @@ class TokenController extends BaseController */ public function bulk() { + + $this->entity_transformer = CompanyTokenHashedTransformer::class; + $action = request()->input('action'); $ids = request()->input('ids'); From 11d12b26663d996535097b987def6674d08ae344 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 5 Jan 2022 17:30:18 +1100 Subject: [PATCH 6/6] Update lang for bank transfer --- resources/lang/en/texts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 762ca47142bb..aeefce8f7cd6 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -4342,7 +4342,7 @@ $LANG = array( 'payment_type_instant_bank_pay' => 'Instant Bank Pay', 'payment_type_iDEAL' => 'iDEAL', 'payment_type_Przelewy24' => 'Przelewy24', - 'payment_type_Mollie Bank Transfer' => 'Bank Transfer', + 'payment_type_Mollie Bank Transfer' => 'Mollie Bank Transfer', 'payment_type_KBC/CBC' => 'KBC/CBC', 'payment_type_Instant Bank Pay' => 'Instant Bank Pay', 'payment_type_Hosted Page' => 'Hosted Page',