mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-07 21:44:29 -04:00
commit
676207479c
@ -36,7 +36,8 @@ We offer a $30 per year white-label license to remove the Invoice Ninja branding
|
|||||||
### Desktop Apps
|
### Desktop Apps
|
||||||
* [macOS](https://apps.apple.com/app/id1503970375?platform=mac)
|
* [macOS](https://apps.apple.com/app/id1503970375?platform=mac)
|
||||||
* [Windows](https://microsoft.com/en-us/p/invoice-ninja/9n3f2bbcfdr6)
|
* [Windows](https://microsoft.com/en-us/p/invoice-ninja/9n3f2bbcfdr6)
|
||||||
* [Linux](https://snapcraft.io/invoiceninja)
|
* [Linux - Snap](https://snapcraft.io/invoiceninja)
|
||||||
|
* [Linux - Flatpak](https://flathub.org/apps/com.invoiceninja.InvoiceNinja)
|
||||||
|
|
||||||
### Installation Options
|
### Installation Options
|
||||||
* [Docker File](https://hub.docker.com/r/invoiceninja/invoiceninja/)
|
* [Docker File](https://hub.docker.com/r/invoiceninja/invoiceninja/)
|
||||||
|
@ -15,6 +15,23 @@ use Illuminate\Support\Facades\App;
|
|||||||
|
|
||||||
class EmailTemplateDefaults
|
class EmailTemplateDefaults
|
||||||
{
|
{
|
||||||
|
public array $templates = [
|
||||||
|
'email_template_invoice',
|
||||||
|
'email_template_quote',
|
||||||
|
'email_template_credit',
|
||||||
|
'email_template_payment',
|
||||||
|
'email_template_payment_partial',
|
||||||
|
'email_template_statement',
|
||||||
|
'email_template_reminder1',
|
||||||
|
'email_template_reminder2',
|
||||||
|
'email_template_reminder3',
|
||||||
|
'email_template_reminder_endless',
|
||||||
|
'email_template_custom1',
|
||||||
|
'email_template_custom2',
|
||||||
|
'email_template_custom3',
|
||||||
|
'email_template_purchase_order',
|
||||||
|
];
|
||||||
|
|
||||||
public static function getDefaultTemplate($template, $locale)
|
public static function getDefaultTemplate($template, $locale)
|
||||||
{
|
{
|
||||||
App::setLocale($locale);
|
App::setLocale($locale);
|
||||||
|
@ -22,7 +22,10 @@ class BulkBankIntegrationRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function authorize() : bool
|
public function authorize() : bool
|
||||||
{
|
{
|
||||||
return auth()->user()->isAdmin();
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
return $user->isAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rules()
|
public function rules()
|
||||||
|
@ -11,17 +11,37 @@
|
|||||||
|
|
||||||
namespace App\Http\Requests\Email;
|
namespace App\Http\Requests\Email;
|
||||||
|
|
||||||
use App\Http\Requests\Request;
|
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use App\Utils\Traits\MakesHash;
|
|
||||||
use Illuminate\Auth\Access\AuthorizationException;
|
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use App\Http\Requests\Request;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
|
|
||||||
class SendEmailRequest extends Request
|
class SendEmailRequest extends Request
|
||||||
{
|
{
|
||||||
use MakesHash;
|
use MakesHash;
|
||||||
|
|
||||||
|
private string $entity_plural = '';
|
||||||
private string $error_message = '';
|
private string $error_message = '';
|
||||||
|
|
||||||
|
public array $templates = [
|
||||||
|
'email_template_invoice',
|
||||||
|
'email_template_quote',
|
||||||
|
'email_template_credit',
|
||||||
|
'email_template_payment',
|
||||||
|
'email_template_payment_partial',
|
||||||
|
'email_template_statement',
|
||||||
|
'email_template_reminder1',
|
||||||
|
'email_template_reminder2',
|
||||||
|
'email_template_reminder3',
|
||||||
|
'email_template_reminder_endless',
|
||||||
|
'email_template_custom1',
|
||||||
|
'email_template_custom2',
|
||||||
|
'email_template_custom3',
|
||||||
|
'email_template_purchase_order',
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the user is authorized to make this request.
|
* Determine if the user is authorized to make this request.
|
||||||
*
|
*
|
||||||
@ -39,14 +59,16 @@ class SendEmailRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'template' => 'bail|required',
|
'template' => 'bail|required|in:'.implode(',', $this->templates),
|
||||||
'entity' => 'bail|required',
|
'entity' => 'bail|required|in:App\Models\Invoice,App\Models\Quote,App\Models\Credit,App\Models\RecurringInvoice,App\Models\PurchaseOrder,App\Models\Payment',
|
||||||
'entity_id' => 'bail|required',
|
'entity_id' => ['bail', 'required', Rule::exists($this->entity_plural, 'id')->where('company_id', $user->company()->id)],
|
||||||
'cc_email.*' => 'bail|sometimes|email',
|
'cc_email.*' => 'bail|sometimes|email',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function prepareForValidation()
|
public function prepareForValidation()
|
||||||
@ -70,6 +92,8 @@ class SendEmailRequest extends Request
|
|||||||
$input['entity_id'] = $this->decodePrimaryKey($input['entity_id']);
|
$input['entity_id'] = $this->decodePrimaryKey($input['entity_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->entity_plural = Str::plural($input['entity']) ?? '';
|
||||||
|
|
||||||
if (isset($input['entity'])) {
|
if (isset($input['entity'])) {
|
||||||
$input['entity'] = "App\Models\\".ucfirst(Str::camel($input['entity']));
|
$input['entity'] = "App\Models\\".ucfirst(Str::camel($input['entity']));
|
||||||
}
|
}
|
||||||
|
@ -11,24 +11,25 @@
|
|||||||
|
|
||||||
namespace App\Jobs\PostMark;
|
namespace App\Jobs\PostMark;
|
||||||
|
|
||||||
use App\DataMapper\Analytics\Mail\EmailBounce;
|
use App\Models\Company;
|
||||||
use App\DataMapper\Analytics\Mail\EmailSpam;
|
use App\Models\SystemLog;
|
||||||
use App\Jobs\Util\SystemLogger;
|
|
||||||
use App\Libraries\MultiDB;
|
use App\Libraries\MultiDB;
|
||||||
|
use Postmark\PostmarkClient;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use App\Jobs\Util\SystemLogger;
|
||||||
|
use App\Models\QuoteInvitation;
|
||||||
use App\Models\CreditInvitation;
|
use App\Models\CreditInvitation;
|
||||||
use App\Models\InvoiceInvitation;
|
use App\Models\InvoiceInvitation;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Turbo124\Beacon\Facades\LightLogs;
|
||||||
use App\Models\PurchaseOrderInvitation;
|
use App\Models\PurchaseOrderInvitation;
|
||||||
use App\Models\QuoteInvitation;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use App\Models\RecurringInvoiceInvitation;
|
use App\Models\RecurringInvoiceInvitation;
|
||||||
use App\Models\SystemLog;
|
|
||||||
use App\Notifications\Ninja\EmailSpamNotification;
|
|
||||||
use Illuminate\Bus\Queueable;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use App\DataMapper\Analytics\Mail\EmailSpam;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use App\DataMapper\Analytics\Mail\EmailBounce;
|
||||||
use Postmark\PostmarkClient;
|
use App\Notifications\Ninja\EmailSpamNotification;
|
||||||
use Turbo124\Beacon\Facades\LightLogs;
|
|
||||||
|
|
||||||
class ProcessPostmarkWebhook implements ShouldQueue
|
class ProcessPostmarkWebhook implements ShouldQueue
|
||||||
{
|
{
|
||||||
@ -82,9 +83,14 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
MultiDB::findAndSetDbByCompanyKey($this->request['Tag']);
|
MultiDB::findAndSetDbByCompanyKey($this->request['Tag']);
|
||||||
|
$company = Company::where('company_key', $this->request['Tag'])->first();
|
||||||
|
|
||||||
$this->invitation = $this->discoverInvitation($this->request['MessageID']);
|
$this->invitation = $this->discoverInvitation($this->request['MessageID']);
|
||||||
|
|
||||||
|
if ($company && $this->request['RecordType'] == 'SpamComplaint' && config('ninja.notification.slack')) {
|
||||||
|
$company->notification(new EmailSpamNotification($company))->ninja();
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->invitation) {
|
if (!$this->invitation) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -305,20 +311,8 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
|
|
||||||
if($sl) {
|
if($sl) {
|
||||||
$this->updateSystemLog($sl, $data);
|
$this->updateSystemLog($sl, $data);
|
||||||
|
|
||||||
if (config('ninja.notification.slack')) {
|
|
||||||
$this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle();
|
|
||||||
|
|
||||||
if (config('ninja.notification.slack')) {
|
|
||||||
$this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function discoverInvitation($message_id)
|
private function discoverInvitation($message_id)
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace App\Notifications\Ninja;
|
namespace App\Notifications\Ninja;
|
||||||
|
|
||||||
|
use App\Models\Company;
|
||||||
use Illuminate\Notifications\Messages\SlackMessage;
|
use Illuminate\Notifications\Messages\SlackMessage;
|
||||||
use Illuminate\Notifications\Notification;
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
@ -21,11 +22,8 @@ class EmailSpamNotification extends Notification
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected $account;
|
public function __construct(protected Company $company)
|
||||||
|
|
||||||
public function __construct($account)
|
|
||||||
{
|
{
|
||||||
$this->account = $account;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,9 +61,9 @@ class EmailSpamNotification extends Notification
|
|||||||
|
|
||||||
public function toSlack($notifiable)
|
public function toSlack($notifiable)
|
||||||
{
|
{
|
||||||
$content = "Email SPAM notification for Account {$this->account->key} \n";
|
$content = "Email SPAM notification for Company {$this->company->company_key} \n";
|
||||||
|
|
||||||
$owner = $this->account->companies()->first()->owner();
|
$owner = $this->company->owner();
|
||||||
|
|
||||||
$content .= "Owner {$owner->present()->name() } | {$owner->email}";
|
$content .= "Owner {$owner->present()->name() } | {$owner->email}";
|
||||||
|
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => 'PayPal'])
|
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => ''])
|
||||||
|
|
||||||
@section('gateway_head')
|
@section('gateway_head')
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
type="text/css"
|
|
||||||
href="https://www.paypalobjects.com/webstatic/en_US/developer/docs/css/cardfields.css"
|
|
||||||
/>
|
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@ -20,7 +15,7 @@
|
|||||||
|
|
||||||
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
||||||
|
|
||||||
<div id="paypal-button-container" class="paypal-button-container"></div>
|
<div id="paypal-button-container" class="paypal-button-container"></div>
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@ -46,6 +41,9 @@
|
|||||||
createOrder: function(data, actions) {
|
createOrder: function(data, actions) {
|
||||||
return "{!! $order_id !!}"
|
return "{!! $order_id !!}"
|
||||||
},
|
},
|
||||||
|
onCancel: function() {
|
||||||
|
window.location.href = "/client/invoices/";
|
||||||
|
},
|
||||||
onApprove: function(data, actions) {
|
onApprove: function(data, actions) {
|
||||||
|
|
||||||
return actions.order.capture().then(function(details) {
|
return actions.order.capture().then(function(details) {
|
||||||
@ -58,6 +56,9 @@
|
|||||||
},
|
},
|
||||||
onError: function(err) {
|
onError: function(err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
},
|
||||||
|
onClick: function (){
|
||||||
|
document.getElementById('paypal-button-container').hidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}).render('#paypal-button-container').catch(function(err) {
|
}).render('#paypal-button-container').catch(function(err) {
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => 'PayPal'])
|
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => 'PayPal'])
|
||||||
|
|
||||||
@section('gateway_head')
|
@section('gateway_head')
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
type="text/css"
|
|
||||||
href="https://www.paypalobjects.com/webstatic/en_US/developer/docs/css/cardfields.css"
|
|
||||||
/>
|
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user