mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-09 20:52:56 +01:00
Add payment failure emails
This commit is contained in:
parent
e2365ee0f9
commit
6eaf3632d9
@ -518,7 +518,12 @@ class CompanySettings extends BaseSettings
|
||||
|
||||
public string $payment_flow = 'default'; //smooth
|
||||
|
||||
public string $email_subject_payment_failed = '';
|
||||
public string $email_template_payment_failed = '';
|
||||
|
||||
public static $casts = [
|
||||
'email_template_payment_failed' => 'string',
|
||||
'email_subject_payment_failed' => 'string',
|
||||
'payment_flow' => 'string',
|
||||
'enable_quote_reminder1' => 'bool',
|
||||
'quote_num_days_reminder1' => 'int',
|
||||
|
@ -30,6 +30,7 @@ class EmailTemplateDefaults
|
||||
'email_template_custom2',
|
||||
'email_template_custom3',
|
||||
'email_template_purchase_order',
|
||||
'email_template_payment_failed'
|
||||
];
|
||||
|
||||
public static function getDefaultTemplate($template, $locale)
|
||||
@ -39,6 +40,8 @@ class EmailTemplateDefaults
|
||||
switch ($template) {
|
||||
/* Template */
|
||||
|
||||
case 'email_template_payment_failed':
|
||||
return self::emailPaymentFailedTemplate();
|
||||
case 'email_template_invoice':
|
||||
return self::emailInvoiceTemplate();
|
||||
case 'email_template_quote':
|
||||
@ -73,6 +76,9 @@ class EmailTemplateDefaults
|
||||
case 'email_subject_invoice':
|
||||
return self::emailInvoiceSubject();
|
||||
|
||||
case 'email_subject_payment_failed':
|
||||
return self::emailPaymentFailedSubject();
|
||||
|
||||
case 'email_subject_quote':
|
||||
return self::emailQuoteSubject();
|
||||
|
||||
@ -127,6 +133,16 @@ class EmailTemplateDefaults
|
||||
}
|
||||
}
|
||||
|
||||
public static function emailPaymentFailedSubject()
|
||||
{
|
||||
return ctrans('texts.notification_invoice_payment_failed_subject', ['invoice' => '$number']);
|
||||
}
|
||||
|
||||
public static function emailPaymentFailedTemplate()
|
||||
{
|
||||
return '<p>$client<br><br>'.ctrans('texts.client_payment_failure_body', ['invoice' => '$number', 'amount' => '$amount']).'</p><div class="center">$gateway_payment_error</div><br><div class="center">$payment_button</div>';
|
||||
}
|
||||
|
||||
public static function emailQuoteReminder1Subject()
|
||||
{
|
||||
return ctrans('texts.quote_reminder_subject', ['quote' => '$number', 'company' => '$company.name']);
|
||||
@ -135,9 +151,7 @@ class EmailTemplateDefaults
|
||||
public static function emailQuoteReminder1Body()
|
||||
{
|
||||
|
||||
$invoice_message = '<p>$client<br><br>'.self::transformText('quote_reminder_message').'</p><div class="center">$view_button</div>';
|
||||
|
||||
return $invoice_message;
|
||||
return '<p>$client<br><br>'.self::transformText('quote_reminder_message').'</p><div class="center">$view_button</div>';
|
||||
|
||||
}
|
||||
|
||||
|
35
app/Events/Invoice/InvoiceAutoBillFailed.php
Normal file
35
app/Events/Invoice/InvoiceAutoBillFailed.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\Invoice;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class InvoiceAutoBillFailed.
|
||||
*/
|
||||
class InvoiceAutoBillFailed
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Invoice $invoice
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(public Invoice $invoice, public Company $company, public array $event_vars, public ?string $notes)
|
||||
{
|
||||
}
|
||||
}
|
35
app/Events/Invoice/InvoiceAutoBillSuccess.php
Normal file
35
app/Events/Invoice/InvoiceAutoBillSuccess.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\Invoice;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class InvoiceAutoBillSuccess.
|
||||
*/
|
||||
class InvoiceAutoBillSuccess
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Invoice $invoice
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(public Invoice $invoice, public Company $company, public array $event_vars)
|
||||
{
|
||||
}
|
||||
}
|
@ -35,7 +35,7 @@ class PrePaymentController extends Controller
|
||||
/**
|
||||
* Show the list of payments.
|
||||
*
|
||||
* @return Factory|View
|
||||
* @return Factory|View|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
@ -84,7 +84,7 @@ class PaymentFailedMailer implements ShouldQueue
|
||||
$invoice = false;
|
||||
|
||||
if ($this->payment_hash) {
|
||||
// $amount = array_sum(array_column($this->payment_hash->invoices(), 'amount')) + $this->payment_hash->fee_total;
|
||||
|
||||
$amount = $this->payment_hash?->amount_with_fee() ?: 0;
|
||||
$invoice = Invoice::query()->whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->first();
|
||||
}
|
||||
|
59
app/Listeners/Invoice/InvoiceAutoBillFailedActivity.php
Normal file
59
app/Listeners/Invoice/InvoiceAutoBillFailedActivity.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\Invoice;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class InvoiceAutoBillFailedActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 10;
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDB($event->company->db);
|
||||
|
||||
$fields = new stdClass();
|
||||
|
||||
$user_id = isset($event->event_vars['user_id']) ? $event->event_vars['user_id'] : $event->invoice->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->client_id = $event->invoice->client_id;
|
||||
$fields->company_id = $event->invoice->company_id;
|
||||
$fields->activity_type_id = Activity::AUTOBILL_FAILURE;
|
||||
$fields->invoice_id = $event->invoice->id;
|
||||
$fields->notes = $event->notes ?? '';
|
||||
|
||||
$this->activity_repo->save($fields, $event->invoice, $event->event_vars);
|
||||
|
||||
}
|
||||
}
|
58
app/Listeners/Invoice/InvoiceAutoBillSuccessActivity.php
Normal file
58
app/Listeners/Invoice/InvoiceAutoBillSuccessActivity.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\Invoice;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class InvoiceAutoBillSuccessActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 10;
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDB($event->company->db);
|
||||
|
||||
$fields = new stdClass();
|
||||
|
||||
$user_id = isset($event->event_vars['user_id']) ? $event->event_vars['user_id'] : $event->invoice->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->client_id = $event->invoice->client_id;
|
||||
$fields->company_id = $event->invoice->company_id;
|
||||
$fields->activity_type_id = Activity::AUTOBILL_SUCCESS;
|
||||
$fields->invoice_id = $event->invoice->id;
|
||||
|
||||
$this->activity_repo->save($fields, $event->invoice, $event->event_vars);
|
||||
|
||||
}
|
||||
}
|
@ -11,12 +11,14 @@
|
||||
|
||||
namespace App\Mail\Admin;
|
||||
|
||||
use stdClass;
|
||||
use App\Utils\Ninja;
|
||||
use App\Models\Invoice;
|
||||
use App\Utils\HtmlEngine;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use stdClass;
|
||||
use App\DataMapper\EmailTemplateDefaults;
|
||||
use App\Utils\Number;
|
||||
|
||||
class ClientPaymentFailureObject
|
||||
{
|
||||
@ -60,20 +62,20 @@ class ClientPaymentFailureObject
|
||||
}
|
||||
|
||||
App::forgetInstance('translator');
|
||||
/* Init a new copy of the translator*/
|
||||
$t = app('translator');
|
||||
/* Set the locale*/
|
||||
App::setLocale($this->client->locale());
|
||||
/* Set customized translations _NOW_ */
|
||||
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||
|
||||
$this->invoices = Invoice::withTrashed()->whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->get();
|
||||
|
||||
$data = $this->getData();
|
||||
|
||||
$mail_obj = new stdClass();
|
||||
$mail_obj->amount = $this->getAmount();
|
||||
$mail_obj->subject = $this->getSubject();
|
||||
$mail_obj->subject = $data['subject'];
|
||||
$mail_obj->data = $this->getData();
|
||||
$mail_obj->markdown = 'email.client.generic';
|
||||
|
||||
$mail_obj->markdown = 'email.template.client';
|
||||
$mail_obj->tag = $this->company->company_key;
|
||||
$mail_obj->text_view = 'email.template.text';
|
||||
|
||||
@ -82,16 +84,32 @@ class ClientPaymentFailureObject
|
||||
|
||||
private function getAmount()
|
||||
{
|
||||
return array_sum(array_column($this->payment_hash->invoices(), 'amount')) + $this->payment_hash->fee_total;
|
||||
$amount = array_sum(array_column($this->payment_hash->invoices(), 'amount')) + $this->payment_hash->fee_total;
|
||||
|
||||
return Number::formatMoney($amount, $this->client);
|
||||
}
|
||||
|
||||
private function getSubject()
|
||||
{
|
||||
return
|
||||
ctrans(
|
||||
'texts.notification_invoice_payment_failed_subject',
|
||||
['invoice' => implode(',', $this->invoices->pluck('number')->toArray())]
|
||||
);
|
||||
|
||||
if(strlen($this->client->getSetting('email_subject_payment_failed') ?? '') > 2){
|
||||
return $this->client->getSetting('email_subject_payment_failed');
|
||||
}
|
||||
else {
|
||||
return EmailTemplateDefaults::getDefaultTemplate('email_subject_payment_failed', $this->client->locale());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function getBody()
|
||||
{
|
||||
|
||||
if(strlen($this->client->getSetting('email_template_payment_failed') ?? '') > 2) {
|
||||
return $this->client->getSetting('email_template_payment_failed');
|
||||
} else {
|
||||
return EmailTemplateDefaults::getDefaultTemplate('email_template_payment_failed', $this->client->locale());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function getData()
|
||||
@ -104,17 +122,17 @@ class ClientPaymentFailureObject
|
||||
|
||||
$signature = $this->client->getSetting('email_signature');
|
||||
$html_variables = (new HtmlEngine($invitation))->makeValues();
|
||||
|
||||
$html_variables['$gateway_payment_error'] = $this->error ?? '';
|
||||
$html_variables['$total'] = $this->getAmount();
|
||||
|
||||
$signature = str_replace(array_keys($html_variables), array_values($html_variables), $signature);
|
||||
$subject = str_replace(array_keys($html_variables), array_values($html_variables), $this->getSubject());
|
||||
$content = str_replace(array_keys($html_variables), array_values($html_variables), $this->getBody());
|
||||
|
||||
$data = [
|
||||
'title' => ctrans(
|
||||
'texts.notification_invoice_payment_failed_subject',
|
||||
[
|
||||
'invoice' => $this->invoices->first()->number,
|
||||
]
|
||||
),
|
||||
'greeting' => ctrans('texts.email_salutation', ['name' => $this->client->present()->name()]),
|
||||
'content' => ctrans('texts.client_payment_failure_body', ['invoice' => implode(',', $this->invoices->pluck('number')->toArray()), 'amount' => $this->getAmount()]),
|
||||
'subject' => $subject,
|
||||
'body' => $content,
|
||||
'signature' => $signature,
|
||||
'logo' => $this->company->present()->logo(),
|
||||
'settings' => $this->client->getMergedSettings(),
|
||||
|
@ -265,6 +265,10 @@ class Activity extends StaticModel
|
||||
|
||||
public const QUOTE_REMINDER1_SENT = 142;
|
||||
|
||||
public const AUTOBILL_SUCCESS = 143; //:invoice auto billing succeeded
|
||||
|
||||
public const AUTOBILL_FAILURE = 144; //:invoice autobilling failed :note
|
||||
|
||||
protected $casts = [
|
||||
'is_system' => 'boolean',
|
||||
'updated_at' => 'timestamp',
|
||||
@ -286,7 +290,6 @@ class Activity extends StaticModel
|
||||
return $this->encodePrimaryKey($this->id);
|
||||
}
|
||||
|
||||
|
||||
public function getEntityType()
|
||||
{
|
||||
return self::class;
|
||||
|
@ -31,6 +31,7 @@ use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundExceptio
|
||||
* @package App\Models
|
||||
* @property-read mixed $hashed_id
|
||||
* @property string $number
|
||||
* @property object|null $e_invoice
|
||||
* @property int $company_id
|
||||
* @property int $id
|
||||
* @property int $user_id
|
||||
@ -296,17 +297,12 @@ class BaseModel extends Model
|
||||
}
|
||||
|
||||
// special catch here for einvoicing eventing
|
||||
if($event_id == Webhook::EVENT_SENT_INVOICE && $this->e_invoice){
|
||||
$this->handleEinvoiceSending();
|
||||
if($event_id == Webhook::EVENT_SENT_INVOICE && ($this instanceof Invoice) && $this->e_invoice){
|
||||
// Einvoice
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function handleEinvoiceSending()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base64 encoded PDF string of the entity
|
||||
* @deprecated - unused implementation
|
||||
|
@ -49,6 +49,18 @@ class UpdatePaymentMethods
|
||||
$this->addOrUpdateCard($method, $customer->id, $client, GatewayType::CREDIT_CARD);
|
||||
}
|
||||
|
||||
$link_methods = PaymentMethod::all(
|
||||
[
|
||||
'customer' => $customer->id,
|
||||
'type' => 'link',
|
||||
],
|
||||
$this->stripe->stripe_connect_auth
|
||||
);
|
||||
|
||||
foreach ($link_methods as $method) {
|
||||
$this->addOrUpdateCard($method, $customer->id, $client, GatewayType::CREDIT_CARD);
|
||||
}
|
||||
|
||||
$alipay_methods = PaymentMethod::all(
|
||||
[
|
||||
'customer' => $customer->id,
|
||||
@ -217,9 +229,14 @@ class UpdatePaymentMethods
|
||||
|
||||
private function buildPaymentMethodMeta(PaymentMethod $method, $type_id)
|
||||
{
|
||||
nlog($method->type);
|
||||
|
||||
switch ($type_id) {
|
||||
case GatewayType::CREDIT_CARD:
|
||||
|
||||
if($method->type == 'link')
|
||||
return new \stdClass();
|
||||
|
||||
/**
|
||||
* @class \Stripe\PaymentMethod $method
|
||||
* @property \Stripe\StripeObject $card
|
||||
|
@ -155,6 +155,8 @@ use App\Listeners\Activity\TaskUpdatedActivity;
|
||||
use App\Listeners\Invoice\InvoiceEmailActivity;
|
||||
use App\Listeners\SendVerificationNotification;
|
||||
use App\Events\Credit\CreditWasEmailedAndFailed;
|
||||
use App\Events\Invoice\InvoiceAutoBillFailed;
|
||||
use App\Events\Invoice\InvoiceAutoBillSuccess;
|
||||
use App\Listeners\Activity\CreatedQuoteActivity;
|
||||
use App\Listeners\Activity\DeleteClientActivity;
|
||||
use App\Listeners\Activity\DeleteCreditActivity;
|
||||
@ -250,6 +252,8 @@ use App\Events\RecurringExpense\RecurringExpenseWasArchived;
|
||||
use App\Events\RecurringExpense\RecurringExpenseWasRestored;
|
||||
use App\Events\RecurringInvoice\RecurringInvoiceWasArchived;
|
||||
use App\Events\RecurringInvoice\RecurringInvoiceWasRestored;
|
||||
use App\Listeners\Invoice\InvoiceAutoBillFailedActivity;
|
||||
use App\Listeners\Invoice\InvoiceAutoBillSuccessActivity;
|
||||
use App\Listeners\PurchaseOrder\CreatePurchaseOrderActivity;
|
||||
use App\Listeners\PurchaseOrder\PurchaseOrderViewedActivity;
|
||||
use App\Listeners\PurchaseOrder\UpdatePurchaseOrderActivity;
|
||||
@ -426,6 +430,12 @@ class EventServiceProvider extends ServiceProvider
|
||||
ExpenseRestoredActivity::class,
|
||||
],
|
||||
//Invoices
|
||||
InvoiceAutoBillSuccess::class => [
|
||||
InvoiceAutoBillSuccessActivity::class,
|
||||
],
|
||||
InvoiceAutoBillFailed::class => [
|
||||
InvoiceAutoBillFailedActivity::class,
|
||||
],
|
||||
InvoiceWasMarkedSent::class => [
|
||||
],
|
||||
InvoiceWasUpdated::class => [
|
||||
|
@ -222,6 +222,10 @@ class StaticServiceProvider extends ServiceProvider
|
||||
'subject' => EmailTemplateDefaults::emailPaymentSubject(),
|
||||
'body' => EmailTemplateDefaults::emailPaymentTemplate(),
|
||||
],
|
||||
'payment_failed' => [
|
||||
'subject' => EmailTemplateDefaults::emailPaymentFailedSubject(),
|
||||
'body' => EmailTemplateDefaults::emailPaymentFailedTemplate(),
|
||||
],
|
||||
'quote_reminder1' => [
|
||||
'subject' => EmailTemplateDefaults::emailQuoteReminder1Subject(),
|
||||
'body' => EmailTemplateDefaults::emailQuoteReminder1Body(),
|
||||
|
@ -23,6 +23,8 @@ use App\Models\PaymentHash;
|
||||
use App\Models\PaymentType;
|
||||
use Illuminate\Support\Str;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\Events\Invoice\InvoiceAutoBillFailed;
|
||||
use App\Events\Invoice\InvoiceAutoBillSuccess;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Services\AbstractService;
|
||||
use App\Models\ClientGatewayToken;
|
||||
@ -157,6 +159,8 @@ class AutoBillInvoice extends AbstractService
|
||||
} catch (\Exception $e) {
|
||||
|
||||
nlog('payment NOT captured for '.$this->invoice->number.' with error '.$e->getMessage());
|
||||
event(new InvoiceAutoBillFailed($this->invoice, $this->invoice->company, Ninja::eventVars(), $e->getMessage()));
|
||||
|
||||
}
|
||||
|
||||
$this->invoice->auto_bill_tries += 1;
|
||||
@ -170,6 +174,7 @@ class AutoBillInvoice extends AbstractService
|
||||
|
||||
if ($payment) {
|
||||
info('Auto Bill payment captured for '.$this->invoice->number);
|
||||
event(new InvoiceAutoBillSuccess($this->invoice, $this->invoice->company, Ninja::eventVars()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -733,6 +733,7 @@ class HtmlEngine
|
||||
$data['$payment.number'] = ['value' => '', 'label' => ctrans('texts.payment_number')];
|
||||
$data['$payment.transaction_reference'] = ['value' => '', 'label' => ctrans('texts.transaction_reference')];
|
||||
$data['$payment.refunded'] = ['value' => '', 'label' => ctrans('texts.refund')];
|
||||
$data['$gateway_payment_error'] = ['value' => '', 'label' => ctrans('texts.error')];
|
||||
|
||||
if ($this->entity_string == 'invoice' && $this->entity->net_payments()->exists()) {
|
||||
$payment_list = '<br><br>';
|
||||
|
@ -5321,6 +5321,9 @@ $lang = array(
|
||||
'applies_to' => 'Applies To',
|
||||
'accept_purchase_order' => 'Accept Purchase Order',
|
||||
'round_to_seconds' => 'Round To Seconds',
|
||||
'activity_142' => 'Quote :number Reminder 1 Sent',
|
||||
'activity_143' => 'Auto Bill succeeded for Invoice :invoice',
|
||||
'activity_144' => 'Auto Bill failed for Invoice :invoice. :notes',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
Loading…
Reference in New Issue
Block a user