mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-04 00:17:34 -05:00 
			
		
		
		
	Merge pull request #4820 from turbo124/v5-develop
Generic payment failure notifications.
This commit is contained in:
		
						commit
						7711a21429
					
				@ -53,6 +53,7 @@ class PostUpdate extends Command
 | 
			
		||||
        nlog("finished migrating");
 | 
			
		||||
 | 
			
		||||
        exec('vendor/bin/composer install --no-dev');
 | 
			
		||||
        exec('vendor/bin/composer dump');
 | 
			
		||||
 | 
			
		||||
        nlog("finished running composer install ");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -111,7 +111,7 @@ class EmailEntity extends BaseMailerJob implements ShouldQueue
 | 
			
		||||
                ->send(
 | 
			
		||||
                    new TemplateEmail(
 | 
			
		||||
                        $this->email_entity_builder,
 | 
			
		||||
                        $this->invitation->contact->client
 | 
			
		||||
                        $this->invitation->contact
 | 
			
		||||
                    )
 | 
			
		||||
                );
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										111
									
								
								app/Jobs/Mail/ClientPaymentFailureMailer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								app/Jobs/Mail/ClientPaymentFailureMailer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,111 @@
 | 
			
		||||
<?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\Jobs\Mail;
 | 
			
		||||
 | 
			
		||||
use App\Libraries\MultiDB;
 | 
			
		||||
use App\Mail\Admin\ClientPaymentFailureObject;
 | 
			
		||||
use App\Mail\Admin\EntityNotificationMailer;
 | 
			
		||||
use App\Mail\Admin\PaymentFailureObject;
 | 
			
		||||
use App\Models\Invoice;
 | 
			
		||||
use App\Models\User;
 | 
			
		||||
use App\Utils\Traits\MakesHash;
 | 
			
		||||
use App\Utils\Traits\Notifications\UserNotifies;
 | 
			
		||||
use Illuminate\Bus\Queueable;
 | 
			
		||||
use Illuminate\Contracts\Queue\ShouldQueue;
 | 
			
		||||
use Illuminate\Foundation\Bus\Dispatchable;
 | 
			
		||||
use Illuminate\Queue\InteractsWithQueue;
 | 
			
		||||
use Illuminate\Queue\SerializesModels;
 | 
			
		||||
use Illuminate\Support\Facades\Mail;
 | 
			
		||||
 | 
			
		||||
/*Multi Mailer implemented*/
 | 
			
		||||
 | 
			
		||||
class ClientPaymentFailureMailer extends BaseMailerJob implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, UserNotifies, MakesHash;
 | 
			
		||||
 | 
			
		||||
    public $client;
 | 
			
		||||
 | 
			
		||||
    public $error;
 | 
			
		||||
 | 
			
		||||
    public $company;
 | 
			
		||||
 | 
			
		||||
    public $payment_hash;
 | 
			
		||||
 | 
			
		||||
    public $settings;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new job instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @param $client
 | 
			
		||||
     * @param $message
 | 
			
		||||
     * @param $company
 | 
			
		||||
     * @param $amount
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($client, $error, $company, $payment_hash)
 | 
			
		||||
    {
 | 
			
		||||
        $this->company = $company;
 | 
			
		||||
 | 
			
		||||
        $this->error = $error;
 | 
			
		||||
 | 
			
		||||
        $this->client = $client;
 | 
			
		||||
 | 
			
		||||
        $this->payment_hash = $payment_hash;
 | 
			
		||||
 | 
			
		||||
        $this->company = $company;
 | 
			
		||||
 | 
			
		||||
        $this->settings = $client->getMergedSettings();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the job.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        /*If we are migrating data we don't want to fire these notification*/
 | 
			
		||||
        if ($this->company->is_disabled) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        //Set DB
 | 
			
		||||
        MultiDB::setDb($this->company->db);
 | 
			
		||||
 | 
			
		||||
        //if we need to set an email driver do it now
 | 
			
		||||
        $this->setMailDriver();
 | 
			
		||||
 | 
			
		||||
        $this->invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->get();
 | 
			
		||||
 | 
			
		||||
        $this->invoices->first()->invitations->each(function ($invitation) {
 | 
			
		||||
 | 
			
		||||
            if ($invitation->contact->send_email && $invitation->contact->email) {
 | 
			
		||||
 | 
			
		||||
                $mail_obj = (new ClientPaymentFailureObject($this->client, $this->error, $this->company, $this->payment_hash))->build();
 | 
			
		||||
                $mail_obj->from = [config('mail.from.address'), config('mail.from.name')];
 | 
			
		||||
 | 
			
		||||
                //send email
 | 
			
		||||
                try {
 | 
			
		||||
                    Mail::to($invitation->contact->email)
 | 
			
		||||
                        ->send(new EntityNotificationMailer($mail_obj));
 | 
			
		||||
                } catch (\Exception $e) {
 | 
			
		||||
 | 
			
		||||
                    $this->logMailError($e->getMessage(), $this->client);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -31,11 +31,11 @@ class PaymentFailureMailer extends BaseMailerJob implements ShouldQueue
 | 
			
		||||
 | 
			
		||||
    public $client;
 | 
			
		||||
 | 
			
		||||
    public $message;
 | 
			
		||||
    public $error;
 | 
			
		||||
 | 
			
		||||
    public $company;
 | 
			
		||||
 | 
			
		||||
    public $amount;
 | 
			
		||||
    public $payment_hash;
 | 
			
		||||
 | 
			
		||||
    public $settings;
 | 
			
		||||
 | 
			
		||||
@ -47,15 +47,15 @@ class PaymentFailureMailer extends BaseMailerJob implements ShouldQueue
 | 
			
		||||
     * @param $company
 | 
			
		||||
     * @param $amount
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($client, $message, $company, $amount)
 | 
			
		||||
    public function __construct($client, $error, $company, $payment_hash)
 | 
			
		||||
    {
 | 
			
		||||
        $this->company = $company;
 | 
			
		||||
 | 
			
		||||
        $this->message = $message;
 | 
			
		||||
        $this->error = $error;
 | 
			
		||||
 | 
			
		||||
        $this->client = $client;
 | 
			
		||||
 | 
			
		||||
        $this->amount = $amount;
 | 
			
		||||
        $this->payment_hash = $payment_hash;
 | 
			
		||||
 | 
			
		||||
        $this->company = $company;
 | 
			
		||||
 | 
			
		||||
@ -92,7 +92,7 @@ class PaymentFailureMailer extends BaseMailerJob implements ShouldQueue
 | 
			
		||||
            if (($key = array_search('mail', $methods)) !== false) {
 | 
			
		||||
                unset($methods[$key]);
 | 
			
		||||
 | 
			
		||||
                $mail_obj = (new PaymentFailureObject($this->client, $this->message, $this->amount, $this->company))->build();
 | 
			
		||||
                $mail_obj = (new PaymentFailureObject($this->client, $this->error, $this->company, $this->payment_hash))->build();
 | 
			
		||||
                $mail_obj->from = [config('mail.from.address'), config('mail.from.name')];
 | 
			
		||||
 | 
			
		||||
                //send email
 | 
			
		||||
 | 
			
		||||
@ -80,7 +80,7 @@ class EmailPayment extends BaseMailerJob implements ShouldQueue
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                $mail = Mail::to($this->contact->email, $this->contact->present()->name());
 | 
			
		||||
                $mail->send(new TemplateEmail($email_builder, $this->contact->client));
 | 
			
		||||
                $mail->send(new TemplateEmail($email_builder, $this->contact));
 | 
			
		||||
            } catch (\Exception $e) {
 | 
			
		||||
                nlog("mailing failed with message " . $e->getMessage());
 | 
			
		||||
                event(new PaymentWasEmailedAndFailed($this->payment, $this->company, Mail::failures(), Ninja::eventVars()));
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@ class AutoBillingFailureObject
 | 
			
		||||
 | 
			
		||||
    public $payment_hash;
 | 
			
		||||
 | 
			
		||||
    private $invoice;
 | 
			
		||||
    private $invoices;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new job instance.
 | 
			
		||||
@ -54,8 +54,7 @@ class AutoBillingFailureObject
 | 
			
		||||
 | 
			
		||||
    public function build()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $this->invoice = Invoice::where('id', $this->decodePrimarykey($this->payment_hash->invoices()[0]->invoice_id))->first();
 | 
			
		||||
        $this->$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->get();
 | 
			
		||||
 | 
			
		||||
        $mail_obj = new stdClass;
 | 
			
		||||
        $mail_obj->amount = $this->getAmount();
 | 
			
		||||
@ -78,7 +77,7 @@ class AutoBillingFailureObject
 | 
			
		||||
        return
 | 
			
		||||
            ctrans(
 | 
			
		||||
                'texts.auto_bill_failed',
 | 
			
		||||
                ['invoice_number' => $this->invoice->number]
 | 
			
		||||
                ['invoice_number' => $this->invoices->first()->number]
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -89,7 +88,7 @@ class AutoBillingFailureObject
 | 
			
		||||
        $data = [
 | 
			
		||||
            'title' => ctrans(
 | 
			
		||||
                'texts.auto_bill_failed',
 | 
			
		||||
                ['invoice_number' => $this->invoice->number]
 | 
			
		||||
                ['invoice_number' => $this->invoices->first()->number]
 | 
			
		||||
            ),
 | 
			
		||||
            'message' => $this->error,
 | 
			
		||||
            'signature' => $signature,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										114
									
								
								app/Mail/Admin/ClientPaymentFailureObject.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								app/Mail/Admin/ClientPaymentFailureObject.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,114 @@
 | 
			
		||||
<?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\Models\Invoice;
 | 
			
		||||
use App\Utils\Number;
 | 
			
		||||
use App\Utils\Traits\MakesHash;
 | 
			
		||||
use stdClass;
 | 
			
		||||
 | 
			
		||||
class ClientPaymentFailureObject
 | 
			
		||||
{
 | 
			
		||||
     use MakesHash;
 | 
			
		||||
 | 
			
		||||
    public $client;
 | 
			
		||||
 | 
			
		||||
    public $error;
 | 
			
		||||
 | 
			
		||||
    public $company;
 | 
			
		||||
 | 
			
		||||
    public $payment_hash;
 | 
			
		||||
 | 
			
		||||
    private $invoices;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new job instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @param $client
 | 
			
		||||
     * @param $message
 | 
			
		||||
     * @param $company
 | 
			
		||||
     * @param $amount
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($client, $error, $company, $payment_hash)
 | 
			
		||||
    {
 | 
			
		||||
        $this->client = $client;
 | 
			
		||||
 | 
			
		||||
        $this->error = $error;
 | 
			
		||||
 | 
			
		||||
        $this->company = $company;
 | 
			
		||||
 | 
			
		||||
        $this->payment_hash = $payment_hash;
 | 
			
		||||
 | 
			
		||||
        $this->company = $company;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function build()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $this->invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->get();
 | 
			
		||||
 | 
			
		||||
        $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 getAmount()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
       return array_sum(array_column($this->payment_hash->invoices(), 'amount')) + $this->payment_hash->fee_total;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getSubject()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
            ctrans(
 | 
			
		||||
                'texts.notification_invoice_payment_failed_subject',
 | 
			
		||||
                ['invoice' => $this->client->present()->name()]
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getData()
 | 
			
		||||
    {
 | 
			
		||||
        $signature = $this->client->getSetting('email_signature');
 | 
			
		||||
 | 
			
		||||
        $data = [
 | 
			
		||||
            'title' => ctrans(
 | 
			
		||||
                'texts.notification_invoice_payment_failed_subject',
 | 
			
		||||
                [
 | 
			
		||||
                    'invoice' => $this->invoices->first()->number
 | 
			
		||||
                ]
 | 
			
		||||
            ),
 | 
			
		||||
            'greeting' => ctrans('texts.email_salutation', ['name' => $this->client->present()->name]),
 | 
			
		||||
            'message' => $this->error,
 | 
			
		||||
            'signature' => $signature,
 | 
			
		||||
            'logo' => $this->company->present()->logo(),
 | 
			
		||||
            'settings' => $this->client->getMergedSettings(),
 | 
			
		||||
            'whitelabel' => $this->company->account->isPaid() ? true : false,
 | 
			
		||||
            'url' => route('client.login'),
 | 
			
		||||
            'button' => ctrans('texts.login'),
 | 
			
		||||
            'additional_info' => false
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        return $data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -11,29 +11,52 @@
 | 
			
		||||
 | 
			
		||||
namespace App\Mail\Admin;
 | 
			
		||||
 | 
			
		||||
use App\Models\Invoice;
 | 
			
		||||
use App\Utils\Number;
 | 
			
		||||
use App\Utils\Traits\MakesHash;
 | 
			
		||||
use stdClass;
 | 
			
		||||
 | 
			
		||||
class PaymentFailureObject
 | 
			
		||||
{
 | 
			
		||||
    use MakesHash;
 | 
			
		||||
 | 
			
		||||
    public $client;
 | 
			
		||||
 | 
			
		||||
    public $message;
 | 
			
		||||
    public $error;
 | 
			
		||||
 | 
			
		||||
    public $company;
 | 
			
		||||
 | 
			
		||||
    public $amount;
 | 
			
		||||
    public $payment_hash;
 | 
			
		||||
 | 
			
		||||
    public function __construct($client, $message, $amount, $company)
 | 
			
		||||
    private $invoices;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new job instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @param $client
 | 
			
		||||
     * @param $message
 | 
			
		||||
     * @param $company
 | 
			
		||||
     * @param $amount
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($client, $error, $company, $payment_hash)
 | 
			
		||||
    {
 | 
			
		||||
        $this->client = $client;
 | 
			
		||||
        $this->message = $message;
 | 
			
		||||
        $this->amount = $amount;
 | 
			
		||||
 | 
			
		||||
        $this->error = $error;
 | 
			
		||||
 | 
			
		||||
        $this->company = $company;
 | 
			
		||||
 | 
			
		||||
        $this->payment_hash = $payment_hash;
 | 
			
		||||
 | 
			
		||||
        $this->company = $company;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function build()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $this->invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->get();
 | 
			
		||||
 | 
			
		||||
        $mail_obj = new stdClass;
 | 
			
		||||
        $mail_obj->amount = $this->getAmount();
 | 
			
		||||
        $mail_obj->subject = $this->getSubject();
 | 
			
		||||
@ -46,16 +69,20 @@ class PaymentFailureObject
 | 
			
		||||
 | 
			
		||||
    private function getAmount()
 | 
			
		||||
    {
 | 
			
		||||
        return Number::formatMoney($this->amount, $this->client);
 | 
			
		||||
 | 
			
		||||
       return array_sum(array_column($this->payment_hash->invoices(), 'amount')) + $this->payment_hash->fee_total;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getSubject()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
            ctrans(
 | 
			
		||||
                'texts.payment_failed_subject',
 | 
			
		||||
                ['client' => $this->client->present()->name()]
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getData()
 | 
			
		||||
@ -65,23 +92,36 @@ class PaymentFailureObject
 | 
			
		||||
        $data = [
 | 
			
		||||
            'title' => ctrans(
 | 
			
		||||
                'texts.payment_failed_subject',
 | 
			
		||||
                ['client' => $this->client->present()->name()]
 | 
			
		||||
            ),
 | 
			
		||||
            'message' => ctrans(
 | 
			
		||||
                'texts.notification_payment_paid',
 | 
			
		||||
                ['amount' => $this->getAmount(),
 | 
			
		||||
                'client' => $this->client->present()->name(),
 | 
			
		||||
                'message' => $this->message,
 | 
			
		||||
            ]
 | 
			
		||||
                [
 | 
			
		||||
                    'client' => $this->client->present()->name()
 | 
			
		||||
                ]
 | 
			
		||||
            ),
 | 
			
		||||
            'message' => $this->error,
 | 
			
		||||
            'signature' => $signature,
 | 
			
		||||
            'logo' => $this->company->present()->logo(),
 | 
			
		||||
            'settings' => $this->client->getMergedSettings(),
 | 
			
		||||
            'whitelabel' => $this->company->account->isPaid() ? true : false,
 | 
			
		||||
            'url' => config('ninja.app_url'),
 | 
			
		||||
            'button' => ctrans('texts.login'),
 | 
			
		||||
            'additional_info' => $this->buildFailedInvoices()
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        return $data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function buildFailedInvoices()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $text = '';
 | 
			
		||||
 | 
			
		||||
        foreach($this->invoices as $invoice)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            $text .= ctrans('texts.notification_invoice_payment_failed_subject', ['invoice' => $invoice->number]) . "\n";
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $text;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -31,14 +31,14 @@ class DownloadInvoices extends Mailable
 | 
			
		||||
    public function build()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->from(config('mail.from.address'), config('mail.from.name'))
 | 
			
		||||
 | 
			
		||||
            ->subject(ctrans('texts.download_files'))
 | 
			
		||||
            ->markdown(
 | 
			
		||||
                'email.admin.download_files',
 | 
			
		||||
                [
 | 
			
		||||
                    'url' => $this->file_path,
 | 
			
		||||
                    'logo' => $this->company->present()->logo,
 | 
			
		||||
                ]
 | 
			
		||||
            );
 | 
			
		||||
                    ->subject(ctrans('texts.download_files'))
 | 
			
		||||
                    ->markdown(
 | 
			
		||||
                        'email.admin.download_files',
 | 
			
		||||
                        [
 | 
			
		||||
                            'url' => $this->file_path,
 | 
			
		||||
                            'logo' => $this->company->present()->logo,
 | 
			
		||||
                            'whitelabel' => $this->company->account->isPaid() ? true : false,
 | 
			
		||||
                        ]
 | 
			
		||||
                    );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -32,6 +32,7 @@ class MigrationCompleted extends Mailable
 | 
			
		||||
    {
 | 
			
		||||
        $data['settings'] = $this->company->settings;
 | 
			
		||||
        $data['company'] = $this->company;
 | 
			
		||||
        $data['whitelabel'] = $this->company->account->isPaid() ? true : false;
 | 
			
		||||
        
 | 
			
		||||
        return $this->from(config('mail.from.address'), config('mail.from.name'))
 | 
			
		||||
                    ->view('email.import.completed', $data)
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,6 @@ class MigrationFailed extends Mailable
 | 
			
		||||
    public function build()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->from(config('mail.from.address'), config('mail.from.name'))
 | 
			
		||||
 | 
			
		||||
                    ->view('email.migration.failed');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,7 @@
 | 
			
		||||
namespace App\Mail;
 | 
			
		||||
 | 
			
		||||
use App\Models\Client;
 | 
			
		||||
use App\Models\ClientContact;
 | 
			
		||||
use App\Models\User;
 | 
			
		||||
use Illuminate\Bus\Queueable;
 | 
			
		||||
use Illuminate\Mail\Mailable;
 | 
			
		||||
@ -25,11 +26,15 @@ class TemplateEmail extends Mailable
 | 
			
		||||
 | 
			
		||||
    private $client;
 | 
			
		||||
 | 
			
		||||
    public function __construct($build_email, Client $client)
 | 
			
		||||
    private $contact;
 | 
			
		||||
 | 
			
		||||
    public function __construct($build_email, ClientContact $contact)
 | 
			
		||||
    {
 | 
			
		||||
        $this->build_email = $build_email;
 | 
			
		||||
 | 
			
		||||
        $this->client = $client;
 | 
			
		||||
        $this->contact = $contact;
 | 
			
		||||
 | 
			
		||||
        $this->client = $contact->client;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -64,12 +69,12 @@ class TemplateEmail extends Mailable
 | 
			
		||||
                'settings' => $settings,
 | 
			
		||||
            ])
 | 
			
		||||
            ->view($template_name, [
 | 
			
		||||
                'greeting' => ctrans('texts.email_salutation', ['name' => $this->contact->present()->name()]),
 | 
			
		||||
                'body' => $this->build_email->getBody(),
 | 
			
		||||
                'footer' => $this->build_email->getFooter(),
 | 
			
		||||
                'view_link' => $this->build_email->getViewLink(),
 | 
			
		||||
                'view_text' => $this->build_email->getViewText(),
 | 
			
		||||
                'title' => '',
 | 
			
		||||
                // 'title' => $this->build_email->getSubject(),
 | 
			
		||||
                'signature' => $settings->email_signature,
 | 
			
		||||
                'settings' => $settings,
 | 
			
		||||
                'company' => $company,
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@ use App\Exceptions\PaymentFailed;
 | 
			
		||||
use App\Factory\PaymentFactory;
 | 
			
		||||
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
 | 
			
		||||
use App\Jobs\Mail\AutoBillingFailureMailer;
 | 
			
		||||
use App\Jobs\Mail\ClientPaymentFailureMailer;
 | 
			
		||||
use App\Jobs\Mail\PaymentFailureMailer;
 | 
			
		||||
use App\Jobs\Util\SystemLogger;
 | 
			
		||||
use App\Models\Client;
 | 
			
		||||
@ -335,6 +336,8 @@ class BaseDriver extends AbstractPaymentDriver
 | 
			
		||||
    public function processInternallyFailedPayment($gateway, $e)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $this->unWindGatewayFees($this->payment_hash);
 | 
			
		||||
 | 
			
		||||
        if ($e instanceof CheckoutHttpException) {
 | 
			
		||||
            $error = $e->getBody();
 | 
			
		||||
        }
 | 
			
		||||
@ -344,7 +347,14 @@ class BaseDriver extends AbstractPaymentDriver
 | 
			
		||||
        else 
 | 
			
		||||
            $error = $e->getMessage();
 | 
			
		||||
 | 
			
		||||
        AutoBillingFailureMailer::dispatch(
 | 
			
		||||
        PaymentFailureMailer::dispatch(
 | 
			
		||||
            $gateway->client,
 | 
			
		||||
            $error,
 | 
			
		||||
            $gateway->client->company,
 | 
			
		||||
            $this->payment_hash
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        ClientPaymentFailureMailer::dispatch(
 | 
			
		||||
            $gateway->client,
 | 
			
		||||
            $error,
 | 
			
		||||
            $gateway->client->company,
 | 
			
		||||
@ -362,36 +372,6 @@ class BaseDriver extends AbstractPaymentDriver
 | 
			
		||||
        throw new PaymentFailed($error, $e->getCode());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function tokenBillingFailed($gateway, $e)
 | 
			
		||||
    {
 | 
			
		||||
        $this->unWindGatewayFees($this->payment_hash);
 | 
			
		||||
 | 
			
		||||
        if ($e instanceof CheckoutHttpException) {
 | 
			
		||||
            $error = $e->getBody();
 | 
			
		||||
        }
 | 
			
		||||
        else if ($e instanceof Exception) {
 | 
			
		||||
            $error = $e->getMessage();
 | 
			
		||||
        }   
 | 
			
		||||
        else 
 | 
			
		||||
            $error = $e->getMessage();
 | 
			
		||||
 | 
			
		||||
        AutoBillingFailureMailer::dispatch(
 | 
			
		||||
            $gateway->client,
 | 
			
		||||
            $error,
 | 
			
		||||
            $gateway->client->company,
 | 
			
		||||
            $this->payment_hash
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        SystemLogger::dispatch(
 | 
			
		||||
            $gateway->payment_hash,
 | 
			
		||||
            SystemLog::CATEGORY_GATEWAY_RESPONSE,
 | 
			
		||||
            SystemLog::EVENT_GATEWAY_ERROR,
 | 
			
		||||
            $gateway::SYSTEM_LOG_TYPE,
 | 
			
		||||
            $gateway->client,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Wrapper method for checking if resource is good.
 | 
			
		||||
     *
 | 
			
		||||
 | 
			
		||||
@ -79,99 +79,44 @@ class Charge
 | 
			
		||||
            ]);
 | 
			
		||||
 | 
			
		||||
            SystemLogger::dispatch($response, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_STRIPE, $this->stripe->client);
 | 
			
		||||
        } catch (CardException $e) {
 | 
			
		||||
            // Since it's a decline, \Stripe\Exception\CardException will be caught
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
 | 
			
		||||
            $data = [
 | 
			
		||||
            'status' => $e->getHttpStatus(),
 | 
			
		||||
            'error_type' => $e->getError()->type,
 | 
			
		||||
            'error_code' => $e->getError()->code,
 | 
			
		||||
            'param' => $e->getError()->param,
 | 
			
		||||
            'message' => $e->getError()->message,
 | 
			
		||||
          ];
 | 
			
		||||
            $this->stripe->tokenBillingFailed($this->stripe, $e);
 | 
			
		||||
            $data =[
 | 
			
		||||
                'status' => '',
 | 
			
		||||
                'error_type' => '',
 | 
			
		||||
                'error_code' => '',
 | 
			
		||||
                'param' => '',
 | 
			
		||||
                'message' => '',
 | 
			
		||||
            ];
 | 
			
		||||
 | 
			
		||||
            SystemLogger::dispatch($data, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->stripe->client);
 | 
			
		||||
        } catch (RateLimitException $e) {
 | 
			
		||||
            // Too many requests made to the API too quickly
 | 
			
		||||
            switch ($e) {
 | 
			
		||||
                case ($e instanceof CardException):
 | 
			
		||||
                    $data['status'] = $e->getHttpStatus();
 | 
			
		||||
                    $data['error_type'] = $e->getError()->type;
 | 
			
		||||
                    $data['error_code'] = $e->getError()->code;
 | 
			
		||||
                    $data['param'] = $e->getError()->param;
 | 
			
		||||
                    $data['message'] = $e->getError()->message;
 | 
			
		||||
                break;
 | 
			
		||||
                case ($e instanceof RateLimitException):
 | 
			
		||||
                    $data['message'] = 'Too many requests made to the API too quickly';
 | 
			
		||||
                break;
 | 
			
		||||
                case ($e instanceof InvalidRequestException):
 | 
			
		||||
                    $data['message'] = 'Invalid parameters were supplied to Stripe\'s API';
 | 
			
		||||
                break;
 | 
			
		||||
                case ($e instanceof AuthenticationException):
 | 
			
		||||
                    $data['message'] = 'Authentication with Stripe\'s API failed';
 | 
			
		||||
                break;
 | 
			
		||||
                case ($e instanceof ApiErrorException):
 | 
			
		||||
                    $data['message'] = 'Network communication with Stripe failed';
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            $data = [
 | 
			
		||||
            'status' => '',
 | 
			
		||||
            'error_type' => '',
 | 
			
		||||
            'error_code' => '',
 | 
			
		||||
            'param' => '',
 | 
			
		||||
            'message' => 'Too many requests made to the API too quickly',
 | 
			
		||||
          ];
 | 
			
		||||
                default:
 | 
			
		||||
                    $data['message'] = $e->getMessage();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
                
 | 
			
		||||
            $this->stripe->tokenBillingFailed($this->stripe, $e);
 | 
			
		||||
 | 
			
		||||
            SystemLogger::dispatch($data, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->stripe->client);
 | 
			
		||||
        } catch (InvalidRequestException $e) {
 | 
			
		||||
            // Invalid parameters were supplied to Stripe's API
 | 
			
		||||
            //
 | 
			
		||||
            $data = [
 | 
			
		||||
            'status' => '',
 | 
			
		||||
            'error_type' => '',
 | 
			
		||||
            'error_code' => '',
 | 
			
		||||
            'param' => '',
 | 
			
		||||
            'message' => 'Invalid parameters were supplied to Stripe\'s API',
 | 
			
		||||
          ];
 | 
			
		||||
 | 
			
		||||
            $this->stripe->tokenBillingFailed($this->stripe, $e);
 | 
			
		||||
            
 | 
			
		||||
            SystemLogger::dispatch($data, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->stripe->client);
 | 
			
		||||
        } catch (AuthenticationException $e) {
 | 
			
		||||
            // Authentication with Stripe's API failed
 | 
			
		||||
 | 
			
		||||
            $data = [
 | 
			
		||||
            'status' => '',
 | 
			
		||||
            'error_type' => '',
 | 
			
		||||
            'error_code' => '',
 | 
			
		||||
            'param' => '',
 | 
			
		||||
            'message' => 'Authentication with Stripe\'s API failed',
 | 
			
		||||
          ];
 | 
			
		||||
 | 
			
		||||
            $this->stripe->tokenBillingFailed($this->stripe, $e);
 | 
			
		||||
            
 | 
			
		||||
            SystemLogger::dispatch($data, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->stripe->client);
 | 
			
		||||
        } catch (ApiConnectionException $e) {
 | 
			
		||||
            // Network communication with Stripe failed
 | 
			
		||||
 | 
			
		||||
            $data = [
 | 
			
		||||
            'status' => '',
 | 
			
		||||
            'error_type' => '',
 | 
			
		||||
            'error_code' => '',
 | 
			
		||||
            'param' => '',
 | 
			
		||||
            'message' => 'Network communication with Stripe failed',
 | 
			
		||||
          ];
 | 
			
		||||
 | 
			
		||||
            $this->stripe->tokenBillingFailed($this->stripe, $e);
 | 
			
		||||
            
 | 
			
		||||
            SystemLogger::dispatch($data, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->stripe->client);
 | 
			
		||||
        } catch (ApiErrorException $e) {
 | 
			
		||||
            $data = [
 | 
			
		||||
            'status' => '',
 | 
			
		||||
            'error_type' => '',
 | 
			
		||||
            'error_code' => '',
 | 
			
		||||
            'param' => '',
 | 
			
		||||
            'message' => 'API Error',
 | 
			
		||||
          ];
 | 
			
		||||
 | 
			
		||||
            $this->stripe->tokenBillingFailed($this->stripe, $e);
 | 
			
		||||
            
 | 
			
		||||
            SystemLogger::dispatch($data, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->stripe->client);
 | 
			
		||||
        } catch (Exception $e) {
 | 
			
		||||
            // Something else happened, completely unrelated to Stripe
 | 
			
		||||
            //
 | 
			
		||||
            $data = [
 | 
			
		||||
            'status' => '',
 | 
			
		||||
            'error_type' => '',
 | 
			
		||||
            'error_code' => '',
 | 
			
		||||
            'param' => '',
 | 
			
		||||
            'message' => $e->getMessage(),
 | 
			
		||||
          ];
 | 
			
		||||
 | 
			
		||||
            $this->stripe->tokenBillingFailed($this->stripe, $e);
 | 
			
		||||
            $this->stripe->processInternallyFailedPayment($this->stripe, $e);
 | 
			
		||||
 | 
			
		||||
            SystemLogger::dispatch($data, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->stripe->client);
 | 
			
		||||
        }  
 | 
			
		||||
 | 
			
		||||
@ -193,6 +193,9 @@ class Phantom
 | 
			
		||||
                              ->build()
 | 
			
		||||
                              ->getCompiledHTML(true);
 | 
			
		||||
 | 
			
		||||
        if (config('ninja.log_pdf_html')) {
 | 
			
		||||
            info($data['html']);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return view('pdf.html', $data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -16,10 +16,11 @@
 | 
			
		||||
    InvoiceNinja (contact@invoiceninja.com)
 | 
			
		||||
@endslot
 | 
			
		||||
 | 
			
		||||
@slot('footer')
 | 
			
		||||
    @component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja'])
 | 
			
		||||
        For any info, please visit InvoiceNinja.
 | 
			
		||||
    @endcomponent
 | 
			
		||||
@endslot
 | 
			
		||||
 | 
			
		||||
@if(!$whitelabel)
 | 
			
		||||
	@slot('footer')
 | 
			
		||||
	    @component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja'])
 | 
			
		||||
	        For any info, please visit InvoiceNinja.
 | 
			
		||||
	    @endcomponent
 | 
			
		||||
	@endslot
 | 
			
		||||
@endif
 | 
			
		||||
@endcomponent
 | 
			
		||||
@ -1,14 +1,23 @@
 | 
			
		||||
@component('email.template.master', ['design' => 'light', 'settings' => $settings])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @slot('header')
 | 
			
		||||
        @include('email.components.header', ['logo' => $logo])
 | 
			
		||||
    @endslot
 | 
			
		||||
 | 
			
		||||
    @if(isset($greeting))
 | 
			
		||||
    <p>{{ $greeting }}</p>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    <p>{{ $title }}</p>
 | 
			
		||||
 | 
			
		||||
    <p>{{ $message }}</p>
 | 
			
		||||
 | 
			
		||||
    @if(isset($additional_info))
 | 
			
		||||
 | 
			
		||||
        <p> {{ $additional_info }}</p>
 | 
			
		||||
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    @component('email.components.button', ['url' => $url])
 | 
			
		||||
        @lang($button)
 | 
			
		||||
    @endcomponent
 | 
			
		||||
@ -17,9 +26,11 @@
 | 
			
		||||
        {{ $signature }}
 | 
			
		||||
    @endslot
 | 
			
		||||
 | 
			
		||||
    @slot('footer')
 | 
			
		||||
        @component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja'])
 | 
			
		||||
            For any info, please visit InvoiceNinja.
 | 
			
		||||
        @endcomponent
 | 
			
		||||
    @endslot
 | 
			
		||||
    @if(!$whitelabel)
 | 
			
		||||
        @slot('footer')
 | 
			
		||||
            @component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja'])
 | 
			
		||||
                For any info, please visit InvoiceNinja.
 | 
			
		||||
            @endcomponent
 | 
			
		||||
        @endslot
 | 
			
		||||
    @endif
 | 
			
		||||
@endcomponent
 | 
			
		||||
 | 
			
		||||
@ -76,4 +76,12 @@
 | 
			
		||||
    <a href="{{ url('/') }}" target="_blank" class="button">{{ ctrans('texts.account_login')}}</a>
 | 
			
		||||
 | 
			
		||||
    <p>{{ ctrans('texts.email_signature')}}<br/> {{ ctrans('texts.email_from') }}</p>
 | 
			
		||||
 | 
			
		||||
@if(!$whitelabel)
 | 
			
		||||
    @slot('footer')
 | 
			
		||||
        @component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja'])
 | 
			
		||||
            For any info, please visit InvoiceNinja.
 | 
			
		||||
        @endcomponent
 | 
			
		||||
    @endslot
 | 
			
		||||
@endif
 | 
			
		||||
@endcomponent
 | 
			
		||||
@ -51,7 +51,7 @@ class CompanyLedgerTest extends TestCase
 | 
			
		||||
 | 
			
		||||
        $this->withoutExceptionHandling();
 | 
			
		||||
 | 
			
		||||
        $this->artisan('db:seed');
 | 
			
		||||
        $this->artisan('db:seed --force');
 | 
			
		||||
 | 
			
		||||
        /* Warm up the cache !*/
 | 
			
		||||
        $cached_tables = config('ninja.cached_tables');
 | 
			
		||||
 | 
			
		||||
@ -131,7 +131,7 @@ trait MockAccountData
 | 
			
		||||
        /* Warm up the cache !*/
 | 
			
		||||
        $cached_tables = config('ninja.cached_tables');
 | 
			
		||||
 | 
			
		||||
        $this->artisan('db:seed');
 | 
			
		||||
        $this->artisan('db:seed --force');
 | 
			
		||||
 | 
			
		||||
        foreach ($cached_tables as $name => $class) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user