Merge pull request #4292 from turbo124/v5-stable

Fixes for Stripe, PDF Creation, Docker compatiblity
This commit is contained in:
David Bomba 2020-11-11 11:16:11 +11:00 committed by GitHub
commit 3fde3f4035
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
208 changed files with 16821 additions and 13721 deletions

View File

@ -3,7 +3,6 @@ APP_DEBUG=true
APP_LOCALE=en APP_LOCALE=en
APP_URL=http://127.0.0.1:8000 APP_URL=http://127.0.0.1:8000
APP_KEY=s7epnjtomsdond5zgfqgaqmwhhcjct02 APP_KEY=s7epnjtomsdond5zgfqgaqmwhhcjct02
APP_CIPHER=AES-256-CBC
REQUIRE_HTTPS=false REQUIRE_HTTPS=false
NINJA_ENVIRONMENT=development NINJA_ENVIRONMENT=development
@ -26,4 +25,3 @@ MAIL_FROM_ADDRESS=
MAIL_PASSWORD= MAIL_PASSWORD=
MAILGUN_DOMAIN= MAILGUN_DOMAIN=
MAILGUN_SECRET= MAILGUN_SECRET=
AUTH_PROVIDER=users

View File

@ -1 +1 @@
5.0.23 5.0.24

View File

@ -355,8 +355,6 @@ class CheckData extends Command
$wrong_balances = 0; $wrong_balances = 0;
$wrong_paid_to_dates = 0; $wrong_paid_to_dates = 0;
//todo reversing an invoice breaks the check data at this point;
Client::cursor()->each(function ($client) use ($wrong_balances) { Client::cursor()->each(function ($client) use ($wrong_balances) {
$client->invoices->where('is_deleted', false)->each(function ($invoice) use ($wrong_balances, $client) { $client->invoices->where('is_deleted', false)->each(function ($invoice) use ($wrong_balances, $client) {
$total_amount = $invoice->payments->sum('pivot.amount'); $total_amount = $invoice->payments->sum('pivot.amount');

View File

@ -340,10 +340,6 @@ class CreateSingleAccount extends Command
$this->invoice_repo->markSent($invoice); $this->invoice_repo->markSent($invoice);
// if (rand(0, 1)) {
// $invoice = $invoice->service()->markPaid()->save();
// }
//@todo this slow things down, but gives us PDFs of the invoices for inspection whilst debugging.
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars())); event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars()));
} }
@ -516,8 +512,8 @@ class CreateSingleAccount extends Command
$cg->user_id = $user->id; $cg->user_id = $user->id;
$cg->gateway_key = 'd14dd26a37cecc30fdd65700bfb55b23'; $cg->gateway_key = 'd14dd26a37cecc30fdd65700bfb55b23';
$cg->require_cvv = true; $cg->require_cvv = true;
$cg->show_billing_address = true; $cg->require_billing_address = true;
$cg->show_shipping_address = true; $cg->require_shipping_address = true;
$cg->update_details = true; $cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.stripe')); $cg->config = encrypt(config('ninja.testvars.stripe'));
$cg->save(); $cg->save();
@ -527,8 +523,8 @@ class CreateSingleAccount extends Command
// $cg->user_id = $user->id; // $cg->user_id = $user->id;
// $cg->gateway_key = 'd14dd26a37cecc30fdd65700bfb55b23'; // $cg->gateway_key = 'd14dd26a37cecc30fdd65700bfb55b23';
// $cg->require_cvv = true; // $cg->require_cvv = true;
// $cg->show_billing_address = true; // $cg->require_billing_address = true;
// $cg->show_shipping_address = true; // $cg->require_shipping_address = true;
// $cg->update_details = true; // $cg->update_details = true;
// $cg->config = encrypt(config('ninja.testvars.stripe')); // $cg->config = encrypt(config('ninja.testvars.stripe'));
// $cg->save(); // $cg->save();
@ -540,8 +536,8 @@ class CreateSingleAccount extends Command
$cg->user_id = $user->id; $cg->user_id = $user->id;
$cg->gateway_key = '38f2c48af60c7dd69e04248cbb24c36e'; $cg->gateway_key = '38f2c48af60c7dd69e04248cbb24c36e';
$cg->require_cvv = true; $cg->require_cvv = true;
$cg->show_billing_address = true; $cg->require_billing_address = true;
$cg->show_shipping_address = true; $cg->require_shipping_address = true;
$cg->update_details = true; $cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.paypal')); $cg->config = encrypt(config('ninja.testvars.paypal'));
$cg->save(); $cg->save();
@ -553,8 +549,8 @@ class CreateSingleAccount extends Command
$cg->user_id = $user->id; $cg->user_id = $user->id;
$cg->gateway_key = '3758e7f7c6f4cecf0f4f348b9a00f456'; $cg->gateway_key = '3758e7f7c6f4cecf0f4f348b9a00f456';
$cg->require_cvv = true; $cg->require_cvv = true;
$cg->show_billing_address = true; $cg->require_billing_address = true;
$cg->show_shipping_address = true; $cg->require_shipping_address = true;
$cg->update_details = true; $cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.checkout')); $cg->config = encrypt(config('ninja.testvars.checkout'));
$cg->save(); $cg->save();
@ -566,8 +562,8 @@ class CreateSingleAccount extends Command
$cg->user_id = $user->id; $cg->user_id = $user->id;
$cg->gateway_key = '3b6621f970ab18887c4f6dca78d3f8bb'; $cg->gateway_key = '3b6621f970ab18887c4f6dca78d3f8bb';
$cg->require_cvv = true; $cg->require_cvv = true;
$cg->show_billing_address = true; $cg->require_billing_address = true;
$cg->show_shipping_address = true; $cg->require_shipping_address = true;
$cg->update_details = true; $cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.authorize')); $cg->config = encrypt(config('ninja.testvars.authorize'));
$cg->save(); $cg->save();

View File

@ -516,7 +516,7 @@ class CreateTestData extends Command
if (rand(0, 1)) { if (rand(0, 1)) {
$invoice = $invoice->service()->markPaid()->save(); $invoice = $invoice->service()->markPaid()->save();
} }
//@todo this slow things down, but gives us PDFs of the invoices for inspection whilst debugging.
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars())); event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars()));
} }

View File

@ -364,10 +364,14 @@ class DemoMode extends Command
private function createProject($client, $assigned_user_id = null) private function createProject($client, $assigned_user_id = null)
{ {
$vendor = Project::factory()->create([ $project = Project::factory()->create([
'user_id' => $client->user->id, 'user_id' => $client->user->id,
'company_id' => $client->company_id, 'company_id' => $client->company_id,
'client_id' => $client->id,
]); ]);
$project->number = $this->getNextProjectNumber($project);
$project->save();
} }
private function createInvoice($client, $assigned_user_id = null) private function createInvoice($client, $assigned_user_id = null)
@ -431,7 +435,7 @@ class DemoMode extends Command
$payment->save(); $payment->save();
}); });
} }
//@todo this slow things down, but gives us PDFs of the invoices for inspection whilst debugging.
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars())); event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars()));
} }

View File

@ -0,0 +1,85 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Console\Commands;
use App\Jobs\Ninja\SendReminders;
use App\Jobs\Util\WebHookHandler;
use App\Models\Invoice;
use App\Models\Quote;
use App\Models\Webhook;
use Illuminate\Console\Command;
class SendRemindersCron extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'ninja:send-reminders';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Force send all reminders';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
SendReminders::dispatchNow();
$this->webHookOverdueInvoices();
$this->webHookExpiredQuotes();
}
private function webHookOverdueInvoices()
{
$invoices = Invoice::where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('balance', '>', 0)
->whereDate('due_date', now()->subDays(1)->startOfDay())
->cursor();
$invoices->each(function ($invoice){
WebHookHandler::dispatch(Webhook::EVENT_LATE_INVOICE, $invoice);
});
}
private function webHookExpiredQuotes()
{
$quotes = Quote::where('is_deleted', 0)
->where('status_id', Quote::STATUS_SENT)
->whereDate('due_date', now()->subDays(1)->startOfDay())
->cursor();
$quotes->each(function ($quote){
WebHookHandler::dispatch(Webhook::EVENT_EXPIRED_QUOTE, $quote);
});
}
}

View File

@ -17,7 +17,6 @@ use App\Factory\ClientFactory;
use App\Factory\CompanyUserFactory; use App\Factory\CompanyUserFactory;
use App\Factory\InvoiceFactory; use App\Factory\InvoiceFactory;
use App\Factory\InvoiceInvitationFactory; use App\Factory\InvoiceInvitationFactory;
use App\Helpers\Email\InvoiceEmail;
use App\Jobs\Invoice\CreateEntityPdf; use App\Jobs\Invoice\CreateEntityPdf;
use App\Mail\TemplateEmail; use App\Mail\TemplateEmail;
use App\Models\Account; use App\Models\Account;
@ -155,16 +154,15 @@ class SendTestEmails extends Command
$cc_emails = [config('ninja.testvars.test_email')]; $cc_emails = [config('ninja.testvars.test_email')];
$bcc_emails = [config('ninja.testvars.test_email')]; $bcc_emails = [config('ninja.testvars.test_email')];
$email_builder = (new InvoiceEmail())->build($ii, 'invoice');
$email_builder->setFooter($message['footer']) $email_builder->setFooter($message['footer'])
->setSubject($message['subject']) ->setSubject($message['subject'])
->setBody($message['body']); ->setBody($message['body']);
Mail::to(config('ninja.testvars.test_email'), 'Mr Test') // Mail::to(config('ninja.testvars.test_email'), 'Mr Test')
->cc($cc_emails) // ->cc($cc_emails)
->bcc($bcc_emails) // ->bcc($bcc_emails)
//->replyTo(also_available_if_needed) //->replyTo(also_available_if_needed)
->send(new TemplateEmail($email_builder, $user, $client)); //->send(new TemplateEmail($email_builder, $user, $client));
} }
} }

View File

@ -11,7 +11,6 @@
namespace App\DataMapper; namespace App\DataMapper;
use App\DataMapper\CompanySettings;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use stdClass; use stdClass;
@ -24,177 +23,176 @@ class CompanySettings extends BaseSettings
/*Group settings based on functionality*/ /*Group settings based on functionality*/
/*Invoice*/ /*Invoice*/
public $auto_archive_invoice = false; public $auto_archive_invoice = false; // @implemented
public $lock_invoices = 'off'; //off,when_sent,when_paid public $lock_invoices = 'off'; //off,when_sent,when_paid //@implemented
public $enable_client_portal_tasks = false; public $enable_client_portal_tasks = false; //@ben to implement
public $enable_client_portal_password = false; public $enable_client_portal_password = false; //@implemented
public $enable_client_portal = true; //implemented public $enable_client_portal = true; //@implemented
public $enable_client_portal_dashboard = true; //implemented public $enable_client_portal_dashboard = true; // @TODO There currently is no dashboard so this is pending
public $signature_on_pdf = false; public $signature_on_pdf = false; //@implemented
public $document_email_attachment = false; public $document_email_attachment = false; //@TODO I assume this is 3rd party attachments on the entity to be included
//public $send_portal_password = false;
public $portal_design_id = '1'; public $portal_design_id = '1'; //?@deprecated
public $timezone_id = ''; public $timezone_id = ''; //@implemented
public $date_format_id = ''; public $date_format_id = ''; //@implemented
public $military_time = false; public $military_time = false; // @TODOImplemented in Tasks only?
public $language_id = ''; public $language_id = ''; //@implemented
public $show_currency_code = false; public $show_currency_code = false; //@implemented
public $company_gateway_ids = ''; public $company_gateway_ids = ''; //@implemented
public $currency_id = '1'; public $currency_id = '1'; //@implemented
public $custom_value1 = ''; public $custom_value1 = ''; //@implemented
public $custom_value2 = ''; public $custom_value2 = ''; //@implemented
public $custom_value3 = ''; public $custom_value3 = ''; //@implemented
public $custom_value4 = ''; public $custom_value4 = ''; //@implemented
public $default_task_rate = 0; public $default_task_rate = 0; // @TODO Where do we inject this?
public $payment_terms = ''; public $payment_terms = ''; //@implemented
public $send_reminders = false; public $send_reminders = false; //@TODO
public $custom_message_dashboard = ''; public $custom_message_dashboard = ''; // @TODO There currently is no dashboard so this is pending
public $custom_message_unpaid_invoice = ''; public $custom_message_unpaid_invoice = ''; //@ben to implement
public $custom_message_paid_invoice = ''; public $custom_message_paid_invoice = ''; //@ben to implement
public $custom_message_unapproved_quote = ''; public $custom_message_unapproved_quote = ''; //@ben to implement
public $auto_archive_quote = false; public $auto_archive_quote = false; //@implemented
public $auto_convert_quote = true; public $auto_convert_quote = true; //@implemented
public $auto_email_invoice = true; public $auto_email_invoice = true; //@only used for Recurring Invoices, if set to false, we never send?
public $inclusive_taxes = false; public $inclusive_taxes = false; //@implemented
public $quote_footer = ''; public $quote_footer = ''; //@implmented
public $translations; public $translations; //@TODO not used anywhere
public $counter_number_applied = 'when_saved'; // when_saved , when_sent public $counter_number_applied = 'when_saved'; // when_saved , when_sent //@implemented
public $quote_number_applied = 'when_saved'; // when_saved , when_sent public $quote_number_applied = 'when_saved'; // when_saved , when_sent //@implemented
/* Counters */ /* Counters */
public $invoice_number_pattern = ''; public $invoice_number_pattern = ''; //@implemented
public $invoice_number_counter = 1; public $invoice_number_counter = 1; //@implemented
public $recurring_invoice_number_pattern = ''; public $recurring_invoice_number_pattern = ''; //@implemented
public $recurring_invoice_number_counter = 1; public $recurring_invoice_number_counter = 1; //@implemented
public $quote_number_pattern = ''; public $quote_number_pattern = ''; //@implemented
public $quote_number_counter = 1; public $quote_number_counter = 1; //@implemented
public $client_number_pattern = ''; public $client_number_pattern = ''; //@implemented
public $client_number_counter = 1; public $client_number_counter = 1; //@implemented
public $credit_number_pattern = ''; public $credit_number_pattern = ''; //@implemented
public $credit_number_counter = 1; public $credit_number_counter = 1; //@implemented
public $task_number_pattern = ''; public $task_number_pattern = ''; //@implemented
public $task_number_counter = 1; public $task_number_counter = 1; //@implemented
public $expense_number_pattern = ''; public $expense_number_pattern = ''; //@implemented
public $expense_number_counter = 1; public $expense_number_counter = 1; //@implemented
public $vendor_number_pattern = ''; public $vendor_number_pattern = ''; //@implemented
public $vendor_number_counter = 1; public $vendor_number_counter = 1; //@implemented
public $ticket_number_pattern = ''; public $ticket_number_pattern = ''; //@implemented
public $ticket_number_counter = 1; public $ticket_number_counter = 1; //@implemented
public $payment_number_pattern = ''; public $payment_number_pattern = ''; //@implemented
public $payment_number_counter = 1; public $payment_number_counter = 1; //@implemented
public $project_number_pattern = ''; public $project_number_pattern = ''; //@implemented
public $project_number_counter = 1; public $project_number_counter = 1; //@implemented
public $shared_invoice_quote_counter = false; public $shared_invoice_quote_counter = false; //@implemented
public $recurring_number_prefix = 'R'; public $recurring_number_prefix = 'R'; //@implemented
public $reset_counter_frequency_id = '0'; public $reset_counter_frequency_id = '0'; //@implemented
public $reset_counter_date = ''; public $reset_counter_date = ''; //@implemented
public $counter_padding = 4; public $counter_padding = 4; //@implemented
public $auto_bill = 'off'; //off,always,optin,optout public $auto_bill = 'off'; //off,always,optin,optout //@implemented
public $auto_bill_date = 'on_due_date'; // on_due_date , on_send_date public $auto_bill_date = 'on_due_date'; // on_due_date , on_send_date //@implemented
public $design = 'views/pdf/design1.blade.php'; //public $design = 'views/pdf/design1.blade.php'; //@deprecated - never used
public $invoice_terms = ''; public $invoice_terms = ''; //@implemented
public $quote_terms = ''; public $quote_terms = ''; //@implemented
public $invoice_taxes = 0; public $invoice_taxes = 0; // ? used in AP only?
// public $enabled_item_tax_rates = 0; // public $enabled_item_tax_rates = 0;
public $invoice_design_id = 'VolejRejNm'; public $invoice_design_id = 'VolejRejNm'; //@implemented
public $quote_design_id = 'VolejRejNm'; public $quote_design_id = 'VolejRejNm'; //@implemented
public $credit_design_id = 'VolejRejNm'; public $credit_design_id = 'VolejRejNm'; //@implemented
public $invoice_footer = ''; public $invoice_footer = ''; //@implemented
public $credit_footer = ''; public $credit_footer = ''; //@implemented
public $credit_terms = ''; public $credit_terms = ''; //@implemented
public $invoice_labels = ''; public $invoice_labels = ''; //@TODO used in AP only?
public $tax_name1 = ''; public $tax_name1 = ''; //@TODO where do we use this?
public $tax_rate1 = 0; public $tax_rate1 = 0; //@TODO where do we use this?
public $tax_name2 = ''; public $tax_name2 = ''; //@TODO where do we use this?
public $tax_rate2 = 0; public $tax_rate2 = 0; //@TODO where do we use this?
public $tax_name3 = ''; public $tax_name3 = ''; //@TODO where do we use this?
public $tax_rate3 = 0; public $tax_rate3 = 0; //@TODO where do we use this?
public $payment_type_id = '0'; public $payment_type_id = '0'; //@TODO where do we use this?
public $invoice_fields = ''; public $invoice_fields = ''; //@TODO is this redundant, we store this in the custom_fields on the company?
public $show_accept_invoice_terms = false; public $show_accept_invoice_terms = false; //@TODO ben to confirm
public $show_accept_quote_terms = false; public $show_accept_quote_terms = false; //@TODO ben to confirm
public $require_invoice_signature = false; public $require_invoice_signature = false; //@TODO ben to confirm
public $require_quote_signature = false; public $require_quote_signature = false; //@TODO ben to confirm
//email settings //email settings
public $email_sending_method = 'default'; //enum 'default','gmail' public $email_sending_method = 'default'; //enum 'default','gmail' //@implemented
public $gmail_sending_user_id = '0'; public $gmail_sending_user_id = '0'; //@implemented
public $reply_to_email = ''; public $reply_to_email = ''; //@TODO
public $bcc_email = ''; public $bcc_email = ''; //@TODO
public $pdf_email_attachment = false; public $pdf_email_attachment = false; //@implemented
public $ubl_email_attachment = false; public $ubl_email_attachment = false; //@implemented
public $email_style = 'light'; //plain, light, dark, custom public $email_style = 'light'; //plain, light, dark, custom //@implemented
public $email_style_custom = ''; //the template itself public $email_style_custom = ''; //the template itself //@implemented
public $email_subject_invoice = ''; public $email_subject_invoice = ''; //@implemented
public $email_subject_quote = ''; public $email_subject_quote = ''; //@implemented
public $email_subject_credit = ''; public $email_subject_credit = ''; //@implemented
public $email_subject_payment = ''; public $email_subject_payment = ''; //@implemented
public $email_subject_payment_partial = ''; public $email_subject_payment_partial = ''; //@implemented
public $email_subject_statement = ''; public $email_subject_statement = ''; //@implemented
public $email_template_invoice = ''; public $email_template_invoice = ''; //@implemented
public $email_template_credit = ''; public $email_template_credit = ''; //@implemented
public $email_template_quote = ''; public $email_template_quote = ''; //@implemented
public $email_template_payment = ''; public $email_template_payment = ''; //@implemented
public $email_template_payment_partial = ''; public $email_template_payment_partial = ''; //@implemented
public $email_template_statement = ''; public $email_template_statement = ''; //@implemented
public $email_subject_reminder1 = ''; public $email_subject_reminder1 = ''; //@implemented
public $email_subject_reminder2 = ''; public $email_subject_reminder2 = ''; //@implemented
public $email_subject_reminder3 = ''; public $email_subject_reminder3 = ''; //@implemented
public $email_subject_reminder_endless = ''; public $email_subject_reminder_endless = ''; //@implemented
public $email_template_reminder1 = ''; public $email_template_reminder1 = ''; //@implemented
public $email_template_reminder2 = ''; public $email_template_reminder2 = ''; //@implemented
public $email_template_reminder3 = ''; public $email_template_reminder3 = ''; //@implemented
public $email_template_reminder_endless = ''; public $email_template_reminder_endless = ''; //@implemented
public $email_signature = ''; public $email_signature = ''; //@implemented
public $enable_email_markup = true; public $enable_email_markup = true; //@TODO
public $email_subject_custom1 = ''; public $email_subject_custom1 = ''; //@TODO
public $email_subject_custom2 = ''; public $email_subject_custom2 = ''; //@TODO
public $email_subject_custom3 = ''; public $email_subject_custom3 = ''; //@TODO
public $email_template_custom1 = ''; public $email_template_custom1 = ''; //@TODO
public $email_template_custom2 = ''; public $email_template_custom2 = ''; //@TODO
public $email_template_custom3 = ''; public $email_template_custom3 = ''; //@TODO
public $enable_reminder1 = false; public $enable_reminder1 = false; //@partially implmemented
public $enable_reminder2 = false; public $enable_reminder2 = false; //@partially implmemented
public $enable_reminder3 = false; public $enable_reminder3 = false; //@partially implmemented
public $enable_reminder_endless = false; public $enable_reminder_endless = false; //@partially implmemented
public $num_days_reminder1 = 0; public $num_days_reminder1 = 0;//@partially implmemented
public $num_days_reminder2 = 0; public $num_days_reminder2 = 0;//@partially implmemented
public $num_days_reminder3 = 0; public $num_days_reminder3 = 0;//@partially implmemented
public $schedule_reminder1 = ''; // (enum: after_invoice_date, before_due_date, after_due_date) public $schedule_reminder1 = ''; // (enum: after_invoice_date, before_due_date, after_due_date)
public $schedule_reminder2 = ''; // (enum: after_invoice_date, before_due_date, after_due_date) public $schedule_reminder2 = ''; // (enum: after_invoice_date, before_due_date, after_due_date)
@ -202,32 +200,36 @@ class CompanySettings extends BaseSettings
public $reminder_send_time = 32400; //number of seconds from UTC +0 to send reminders public $reminder_send_time = 32400; //number of seconds from UTC +0 to send reminders
public $late_fee_amount1 = 0; public $late_fee_amount1 = 0; //@TODO
public $late_fee_amount2 = 0; public $late_fee_amount2 = 0; //@TODO
public $late_fee_amount3 = 0; public $late_fee_amount3 = 0; //@TODO
public $endless_reminder_frequency_id = '0'; public $late_fee_percent1 = 0; //@TODO
public $late_fee_endless_amount = 0; public $late_fee_percent2 = 0; //@TODO
public $late_fee_endless_percent = 0; public $late_fee_percent3 = 0; //@TODO
public $endless_reminder_frequency_id = '0'; //@implemented
public $late_fee_endless_amount = 0; //@TODO
public $late_fee_endless_percent = 0; //@TODO
public $client_online_payment_notification = true; //@todo implement in notifications public $client_online_payment_notification = true; //@todo implement in notifications
public $client_manual_payment_notification = true; //@todo implement in notifications public $client_manual_payment_notification = true; //@todo implement in notifications
/* Company Meta data that we can use to build sub companies*/ /* Company Meta data that we can use to build sub companies*/
public $name = ''; public $name = ''; //@implemented
public $company_logo = ''; public $company_logo = ''; //@implemented
public $website = ''; public $website = ''; //@implemented
public $address1 = ''; public $address1 = ''; //@implemented
public $address2 = ''; public $address2 = ''; //@implemented
public $city = ''; public $city = ''; //@implemented
public $state = ''; public $state = ''; //@implemented
public $postal_code = ''; public $postal_code = ''; //@implemented
public $phone = ''; public $phone = ''; //@implemented
public $email = ''; public $email = ''; //@implemented
public $country_id; public $country_id; //@implemented
public $vat_number = ''; public $vat_number = ''; //@implemented
public $id_number = ''; public $id_number = ''; //@implemented
public $page_size = 'A4'; //Letter, Legal, Tabloid, Ledger, A0, A1, A2, A3, A4, A5, A6 public $page_size = 'A4'; //Letter, Legal, Tabloid, Ledger, A0, A1, A2, A3, A4, A5, A6
public $font_size = 9; public $font_size = 9;
@ -236,26 +238,26 @@ class CompanySettings extends BaseSettings
public $primary_color = '#4caf50'; public $primary_color = '#4caf50';
public $secondary_color = '#2196f3'; public $secondary_color = '#2196f3';
public $hide_paid_to_date = false; public $hide_paid_to_date = false; //@TODO where?
public $embed_documents = false; public $embed_documents = false; //@TODO
public $all_pages_header = false; public $all_pages_header = false; //@implemented
public $all_pages_footer = false; public $all_pages_footer = false; //@implemented
public $pdf_variables = ''; public $pdf_variables = ''; //@implemented
public $portal_custom_head = ''; public $portal_custom_head = ''; //@TODO
public $portal_custom_css = ''; public $portal_custom_css = ''; //@TODO
public $portal_custom_footer = ''; public $portal_custom_footer = ''; //@TODO
public $portal_custom_js = ''; public $portal_custom_js = ''; //@TODO
public $client_can_register = false; public $client_can_register = false; //@implemented
public $client_portal_terms = ''; public $client_portal_terms = ''; //@TODO
public $client_portal_privacy_policy = ''; public $client_portal_privacy_policy = ''; //@TODO
public $client_portal_enable_uploads = false; public $client_portal_enable_uploads = false; //@implemented
public $client_portal_allow_under_payment = false; public $client_portal_allow_under_payment = false; //@implemented
public $client_portal_under_payment_minimum = 0; public $client_portal_under_payment_minimum = 0; //@implemented
public $client_portal_allow_over_payment = false; public $client_portal_allow_over_payment = false; //@implemented
public $use_credits_payment = 'off'; //always, option, off public $use_credits_payment = 'off'; //always, option, off //@implemented
public static $casts = [ public static $casts = [
'enable_reminder_endless' => 'bool', 'enable_reminder_endless' => 'bool',
@ -301,6 +303,9 @@ class CompanySettings extends BaseSettings
'late_fee_amount1' => 'float', 'late_fee_amount1' => 'float',
'late_fee_amount2' => 'float', 'late_fee_amount2' => 'float',
'late_fee_amount3' => 'float', 'late_fee_amount3' => 'float',
'late_fee_percent1' => 'float',
'late_fee_percent2' => 'float',
'late_fee_percent3' => 'float',
'endless_reminder_frequency_id' => 'integer', 'endless_reminder_frequency_id' => 'integer',
'client_online_payment_notification' => 'bool', 'client_online_payment_notification' => 'bool',
'client_manual_payment_notification' => 'bool', 'client_manual_payment_notification' => 'bool',
@ -312,7 +317,6 @@ class CompanySettings extends BaseSettings
'email_template_statement' => 'string', 'email_template_statement' => 'string',
'email_subject_statement' => 'string', 'email_subject_statement' => 'string',
'signature_on_pdf' => 'bool', 'signature_on_pdf' => 'bool',
// 'send_portal_password' => 'bool',
'quote_footer' => 'string', 'quote_footer' => 'string',
'page_size' => 'string', 'page_size' => 'string',
'font_size' => 'int', 'font_size' => 'int',
@ -431,7 +435,7 @@ class CompanySettings extends BaseSettings
'auto_convert_quote' => 'bool', 'auto_convert_quote' => 'bool',
'shared_invoice_quote_counter' => 'bool', 'shared_invoice_quote_counter' => 'bool',
'counter_padding' => 'integer', 'counter_padding' => 'integer',
'design' => 'string', //'design' => 'string',
'website' => 'string', 'website' => 'string',
'pdf_variables' => 'object', 'pdf_variables' => 'object',
'portal_custom_head' => 'string', 'portal_custom_head' => 'string',
@ -624,8 +628,8 @@ class CompanySettings extends BaseSettings
'task_columns' =>[ 'task_columns' =>[
'$task.product_key', '$task.product_key',
'$task.notes', '$task.notes',
'$task.cost', '$task.rate',
'$task.quantity', '$task.hours',
'$task.discount', '$task.discount',
'$task.tax', '$task.tax',
'$task.line_total', '$task.line_total',

View File

@ -28,7 +28,6 @@ class DefaultSettings extends BaseSettings
/** /**
* @return stdClass * @return stdClass
* *
* //todo user specific settings / preferences.
*/ */
public static function userSettings() : stdClass public static function userSettings() : stdClass
{ {

View File

@ -178,6 +178,7 @@ class EmailTemplateDefaults
public static function emailReminder1Subject() public static function emailReminder1Subject()
{ {
info("reminder 1 subject");
return ctrans('texts.reminder_subject', ['invoice'=>'$invoice.number', 'account'=>'$company.name']); return ctrans('texts.reminder_subject', ['invoice'=>'$invoice.number', 'account'=>'$company.name']);
} }

View File

@ -51,7 +51,7 @@ class InvoiceItem
public $custom_value4 = ''; public $custom_value4 = '';
public $type_id = 1; //1 = product, 2 = service, 3 unpaid gateway fee, 4 paid gateway fee public $type_id = 1; //1 = product, 2 = service, 3 unpaid gateway fee, 4 paid gateway fee, 5 late fee
public static $casts = [ public static $casts = [
'type_id' => 'string', 'type_id' => 'string',

View File

@ -12,6 +12,7 @@
namespace App\Events\Client; namespace App\Events\Client;
use App\Models\Client; use App\Models\Client;
use App\Models\Company;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
/** /**

View File

@ -12,6 +12,7 @@
namespace App\Events\Client; namespace App\Events\Client;
use App\Models\Client; use App\Models\Client;
use App\Models\Company;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
/** /**
@ -26,6 +27,8 @@ class ClientWasRestored
*/ */
public $client; public $client;
public $fromDeleted;
public $company; public $company;
public $event_vars; public $event_vars;
@ -37,9 +40,10 @@ class ClientWasRestored
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(Client $client, Company $company, array $event_vars) public function __construct(Client $client, $fromDeleted, Company $company, array $event_vars)
{ {
$this->client = $client; $this->client = $client;
$this->fromDeleted = $fromDeleted;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -12,6 +12,7 @@
namespace App\Events\Client; namespace App\Events\Client;
use App\Models\Client; use App\Models\Client;
use App\Models\Company;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
/** /**

View File

@ -11,6 +11,7 @@
namespace App\Events\Credit; namespace App\Events\Credit;
use App\Models\Company;
use App\Models\Credit; use App\Models\Credit;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
@ -30,6 +31,7 @@ class CreditWasRestored
public $event_vars; public $event_vars;
public $fromDeleted;
/** /**
* Create a new event instance. * Create a new event instance.
* *
@ -37,9 +39,10 @@ class CreditWasRestored
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(Credit $credit, Company $company, array $event_vars) public function __construct(Credit $credit, $fromDeleted, Company $company, array $event_vars)
{ {
$this->credit = $credit; $this->credit = $credit;
$this->fromDeleted = $fromDeleted;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -32,6 +32,7 @@ class DesignWasRestored
public $event_vars; public $event_vars;
public $fromDeleted;
/** /**
* Create a new event instance. * Create a new event instance.
* *
@ -39,10 +40,12 @@ class DesignWasRestored
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(Design $design, Company $company, array $event_vars) public function __construct(Design $design, $fromDeleted, Company $company, array $event_vars)
{ {
$this->design = $design; $this->design = $design;
$this->fromDeleted = $fromDeleted;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;

View File

@ -31,6 +31,7 @@ class DocumentWasRestored
public $event_vars; public $event_vars;
public $fromDeleted;
/** /**
* Create a new event instance. * Create a new event instance.
* *
@ -38,9 +39,10 @@ class DocumentWasRestored
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(Document $document, Company $company, array $event_vars) public function __construct(Document $document, $fromDeleted, Company $company, array $event_vars)
{ {
$this->document = $document; $this->document = $document;
$this->fromDeleted = $fromDeleted;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -31,6 +31,7 @@ class ExpenseWasRestored
public $event_vars; public $event_vars;
public $fromDeleted;
/** /**
* Create a new event instance. * Create a new event instance.
* *
@ -38,9 +39,10 @@ class ExpenseWasRestored
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(Expense $expense, Company $company, array $event_vars) public function __construct(Expense $expense, $fromDeleted, Company $company, array $event_vars)
{ {
$this->expense = $expense; $this->expense = $expense;
$this->fromDeleted = $fromDeleted;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -0,0 +1,50 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Events\Invoice;
use App\Models\Company;
use App\Models\InvoiceInvitation;
use Illuminate\Queue\SerializesModels;
/**
* Class InvoiceReminderWasEmailed.
*/
class InvoiceReminderWasEmailed
{
use SerializesModels;
/**
* @var Invoice
*/
public $invitation;
public $reminder;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param InvoiceInvitation $invitation
* @param Company $company
* @param array $event_vars
*/
public function __construct(InvoiceInvitation $invitation, Company $company, array $event_vars, string $reminder)
{
$this->invitation = $invitation;
$this->company = $company;
$this->event_vars = $event_vars;
$this->reminder = $reminder;
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Events\Product;
use App\Models\Company;
use App\Models\Invoice;
use Illuminate\Queue\SerializesModels;
/**
* Class ProductWasRestored.
*/
class ProductWasRestored
{
use SerializesModels;
/**
* @var Product
*/
public $invoice;
public $company;
public $event_vars;
public $fromDeleted;
/**
* Create a new event instance.
*
* @param Product $invoice
* @param Company $company
* @param array $event_vars
*/
public function __construct(Product $product, $fromDeleted, Company $company, array $event_vars)
{
$this->product = $product;
$this->fromDeleted = $fromDeleted;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -12,6 +12,7 @@
namespace App\Events\Quote; namespace App\Events\Quote;
use App\Models\Company; use App\Models\Company;
use App\Models\Quote;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class QuoteWasArchived class QuoteWasArchived

View File

@ -12,6 +12,7 @@
namespace App\Events\Quote; namespace App\Events\Quote;
use App\Models\Company; use App\Models\Company;
use App\Models\Quote;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
/** /**

View File

@ -12,6 +12,7 @@
namespace App\Events\Quote; namespace App\Events\Quote;
use App\Models\Company; use App\Models\Company;
use App\Models\Quote;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
/** /**

View File

@ -12,6 +12,7 @@
namespace App\Events\Quote; namespace App\Events\Quote;
use App\Models\Company; use App\Models\Company;
use App\Models\Quote;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
/** /**
@ -27,6 +28,7 @@ class QuoteWasRestored
public $event_vars; public $event_vars;
public $fromDeleted;
/** /**
* Create a new event instance. * Create a new event instance.
* *
@ -34,9 +36,10 @@ class QuoteWasRestored
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(Quote $quote, Company $company, array $event_vars) public function __construct(Quote $quote, $fromDeleted, Company $company, array $event_vars)
{ {
$this->quote = $quote; $this->quote = $quote;
$this->fromDeleted = $fromDeleted;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -31,6 +31,7 @@ class TaskWasRestored
public $event_vars; public $event_vars;
public $fromDeleted;
/** /**
* Create a new event instance. * Create a new event instance.
* *
@ -38,9 +39,10 @@ class TaskWasRestored
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(Task $task, Company $company, array $event_vars) public function __construct(Task $task, $fromDeleted, Company $company, array $event_vars)
{ {
$this->task = $task; $this->task = $task;
$this->fromDeleted = $fromDeleted;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -31,6 +31,7 @@ class VendorWasRestored
public $event_vars; public $event_vars;
public $fromDeleted;
/** /**
* Create a new event instance. * Create a new event instance.
* *
@ -38,9 +39,10 @@ class VendorWasRestored
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(Vendor $vendor, Company $company, array $event_vars) public function __construct(Vendor $vendor, $fromDeleted, Company $company, array $event_vars)
{ {
$this->vendor = $vendor; $this->vendor = $vendor;
$this->fromDeleted = $fromDeleted;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -27,6 +27,7 @@ class CloneQuoteToInvoiceFactory
unset($quote_array['hashed_id']); unset($quote_array['hashed_id']);
unset($quote_array['invoice_id']); unset($quote_array['invoice_id']);
unset($quote_array['id']); unset($quote_array['id']);
unset($quote_array['invitations']);
foreach ($quote_array as $key => $value) { foreach ($quote_array as $key => $value) {
$invoice->{$key} = $value; $invoice->{$key} = $value;

View File

@ -25,7 +25,6 @@ class CreditFilters extends QueryFilters
* Filter based on client status. * Filter based on client status.
* *
* Statuses we need to handle * Statuses we need to handle
* //todo ?partials as a status?
* - all * - all
* - paid * - paid
* - unpaid * - unpaid

View File

@ -26,7 +26,6 @@ class InvoiceFilters extends QueryFilters
* Filter based on client status. * Filter based on client status.
* *
* Statuses we need to handle * Statuses we need to handle
* //todo ?partials as a status?
* - all * - all
* - paid * - paid
* - unpaid * - unpaid

View File

@ -1,5 +1,4 @@
<?php <?php
/** /**
* Invoice Ninja (https://invoiceninja.com). * Invoice Ninja (https://invoiceninja.com).
* *

View File

@ -1,173 +0,0 @@
<?php
namespace App\Helpers\Email;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\Quote;
use League\CommonMark\CommonMarkConverter;
class EmailBuilder
{
public $subject;
public $body;
public $recipients;
public $attachments;
public $footer;
public $template_style;
public $variables = [];
public $contact = null;
public $view_link;
public $view_text;
/**
* @param $footer
* @return $this
*/
public function setFooter($footer)
{
$this->footer = $footer;
return $this;
}
public function setVariables($variables)
{
$this->variables = $variables;
return $this;
}
/**
* @param $contact
* @return $this
*/
public function setContact($contact)
{
$this->contact = $contact;
return $this;
}
/**
* @param $subject
* @return $this
*/
public function setSubject($subject)
{
if (! empty($this->variables)) {
$subject = str_replace(array_keys($this->variables), array_values($this->variables), $subject);
}
$this->subject = $subject;
return $this;
}
/**
* @param $body
* @return $this
*/
public function setBody($body)
{
//todo move this to use HTMLEngine
if (! empty($this->variables)) {
$body = str_replace(array_keys($this->variables), array_values($this->variables), $body);
}
$this->body = $body;
return $this;
}
/**
* @param $template_style
* @return $this
*/
public function setTemplate($template_style)
{
$this->template_style = $template_style;
return $this;
}
public function setAttachments($attachments)
{
$this->attachments[] = $attachments;
return $this;
}
public function setViewLink($link)
{
$this->view_link = $link;
return $this;
}
public function setViewText($text)
{
$this->view_text = $text;
return $this;
}
/**
* @return mixed
*/
public function getSubject()
{
return $this->subject;
}
/**
* @return mixed
*/
public function getBody()
{
return $this->body;
}
/**
* @return mixed
*/
public function getRecipients()
{
return $this->recipients;
}
/**
* @return mixed
*/
public function getAttachments()
{
return $this->attachments;
}
/**
* @return mixed
*/
public function getFooter()
{
return $this->footer;
}
/**
* @return mixed
*/
public function getTemplate()
{
return $this->template_style;
}
public function getViewLink()
{
return $this->view_link;
}
public function getViewText()
{
return $this->view_text;
}
}

View File

@ -1,86 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: michael.hampton
* Date: 14/02/2020
* Time: 19:51.
*/
namespace App\Helpers\Email;
use App\Helpers\Email\EntityEmailInterface;
use App\Models\Invoice;
use App\Models\InvoiceInvitation;
use App\Utils\HtmlEngine;
use App\Utils\Number;
class InvoiceEmail extends EmailBuilder
{
public function build(InvoiceInvitation $invitation, $reminder_template = null)
{
$client = $invitation->contact->client;
$invoice = $invitation->invoice;
$contact = $invitation->contact;
if (! $reminder_template) {
$reminder_template = $invoice->calculateTemplate('invoice');
}
$body_template = $client->getSetting('email_template_'.$reminder_template);
/* Use default translations if a custom message has not been set*/
if (iconv_strlen($body_template) == 0) {
$body_template = trans(
'texts.invoice_message',
[
'invoice' => $invoice->number,
'company' => $invoice->company->present()->name(),
'amount' => Number::formatMoney($invoice->balance, $invoice->client),
],
null,
$invoice->client->locale()
);
}
$subject_template = $client->getSetting('email_subject_'.$reminder_template);
if (iconv_strlen($subject_template) == 0) {
if ($reminder_template == 'quote') {
$subject_template = trans(
'texts.quote_subject',
[
'number' => $invoice->number,
'account' => $invoice->company->present()->name(),
],
null,
$invoice->client->locale()
);
} else {
$subject_template = trans(
'texts.invoice_subject',
[
'number' => $invoice->number,
'account' => $invoice->company->present()->name(),
],
null,
$invoice->client->locale()
);
}
}
$this->setTemplate($client->getSetting('email_style'))
->setContact($contact)
->setVariables((new HtmlEngine($invitation))->makeValues())
->setSubject($subject_template)
->setBody($body_template)
->setFooter("<a href='{$invitation->getLink()}'>".ctrans('texts.view_invoice').'</a>')
->setViewLink($invitation->getLink())
->setViewText(ctrans('texts.view_invoice'));
if ($client->getSetting('pdf_email_attachment') !== false) {
$this->setAttachments($invitation->pdf_file_path());
}
return $this;
}
}

View File

@ -1,48 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: michael.hampton
* Date: 14/02/2020
* Time: 19:51.
*/
namespace App\Helpers\Email;
use App\Models\Payment;
class PaymentEmail extends EmailBuilder
{
public function build(Payment $payment, $contact = null)
{
$client = $payment->client;
$body_template = $client->getSetting('email_template_payment');
/* Use default translations if a custom message has not been set*/
if (iconv_strlen($body_template) == 0) {
$body_template = trans(
'texts.payment_message',
['amount' => $payment->amount, 'company' => $payment->company->present()->name()],
null,
$this->client->locale()
);
}
$subject_template = $client->getSetting('email_subject_payment');
if (iconv_strlen($subject_template) == 0) {
$subject_template = trans(
'texts.payment_subject',
['number' => $payment->number, 'company' => $payment->company->present()->name()],
null,
$payment->client->locale()
);
}
$this->setTemplate($payment->client->getSetting('email_style'))
->setSubject($subject_template)
->setBody($body_template);
return $this;
}
}

View File

@ -1,70 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: michael.hampton
* Date: 14/02/2020
* Time: 19:51.
*/
namespace App\Helpers\Email;
use App\Models\Quote;
use App\Models\QuoteInvitation;
use App\Utils\HtmlEngine;
class QuoteEmail extends EmailBuilder
{
public function build(QuoteInvitation $invitation, $reminder_template)
{
$client = $invitation->contact->client;
$quote = $invitation->quote;
$contact = $invitation->contact;
$this->template_style = $client->getSetting('email_style');
$body_template = $client->getSetting('email_template_'.$reminder_template);
/* Use default translations if a custom message has not been set*/
if (iconv_strlen($body_template) == 0) {
$body_template = trans(
'texts.quote_message',
['amount' => $quote->amount, 'company' => $quote->company->present()->name()],
null,
$quote->client->locale()
);
}
$subject_template = $client->getSetting('email_subject_'.$reminder_template);
if (iconv_strlen($subject_template) == 0) {
if ($reminder_template == 'quote') {
$subject_template = trans(
'texts.quote_subject',
['number' => $quote->number, 'company' => $quote->company->present()->name()],
null,
$quote->client->locale()
);
} else {
$subject_template = trans(
'texts.reminder_subject',
['number' => $quote->number, 'company' => $quote->company->present()->name()],
null,
$quote->client->locale()
);
}
}
$this->setTemplate($quote->client->getSetting('email_style'))
->setContact($contact)
->setFooter("<a href='{$invitation->getLink()}'>Quote Link</a>")
->setVariables((new HtmlEngine($invitation))->makeValues())
->setSubject($subject_template)
->setBody($body_template);
if ($client->getSetting('pdf_email_attachment') !== false) {
$this->attachments = $invitation->pdf_file_path();
}
return $this;
}
}

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Helpers\Language; namespace App\Helpers\Language;

View File

@ -63,7 +63,7 @@ class GmailTransport extends Transport
$this->gmail->cc($message->getCc()); $this->gmail->cc($message->getCc());
$this->gmail->bcc($message->getBcc()); $this->gmail->bcc($message->getBcc());
Log::error(print_r($message->getChildren(), 1)); info(print_r($message->getChildren(), 1));
foreach ($message->getChildren() as $child) { foreach ($message->getChildren() as $child) {
$this->gmail->attach($child); $this->gmail->attach($child);

View File

@ -22,7 +22,5 @@
*/ */
function ctrans(string $string, $replace = [], $locale = null) : string function ctrans(string $string, $replace = [], $locale = null) : string
{ {
//todo pass through the cached version of the custom strings here else return trans();
return trans($string, $replace, $locale); return trans($string, $replace, $locale);
} }

View File

@ -13,6 +13,7 @@ namespace App\Http\Controllers;
use App\DataMapper\ClientSettings; use App\DataMapper\ClientSettings;
use App\Events\Client\ClientWasCreated; use App\Events\Client\ClientWasCreated;
use App\Events\Client\ClientWasUpdated;
use App\Factory\ClientFactory; use App\Factory\ClientFactory;
use App\Filters\ClientFilters; use App\Filters\ClientFilters;
use App\Http\Requests\Client\BulkClientRequest; use App\Http\Requests\Client\BulkClientRequest;
@ -288,6 +289,8 @@ class ClientController extends BaseController
$this->uploadLogo($request->file('company_logo'), $client->company, $client); $this->uploadLogo($request->file('company_logo'), $client->company, $client);
event(new ClientWasUpdated($client, $client->company, Ninja::eventVars()));
return $this->itemResponse($client->fresh()); return $this->itemResponse($client->fresh());
} }

View File

@ -40,7 +40,7 @@ class InvitationController extends Controller
$key = $entity.'_id'; $key = $entity.'_id';
$entity_obj = 'App\Models\\'.ucfirst(Str::camel($entity)).'Invitation'; //todo sensitive to the route parameters here $entity_obj = 'App\Models\\'.ucfirst(Str::camel($entity)).'Invitation';
$invitation = $entity_obj::whereRaw('BINARY `key`= ?', [$invitation_key]) $invitation = $entity_obj::whereRaw('BINARY `key`= ?', [$invitation_key])
->with('contact.client') ->with('contact.client')

View File

@ -218,8 +218,9 @@ class PaymentController extends Controller
'amount_with_fee' => $invoice_totals + $fee_totals, 'amount_with_fee' => $invoice_totals + $fee_totals,
]; ];
if($is_credit_payment) if($is_credit_payment) {
return $this->processCreditPayment($request, $data); return $this->processCreditPayment($request, $data);
}
return $gateway return $gateway
->driver(auth()->user()->client) ->driver(auth()->user()->client)

View File

@ -109,8 +109,8 @@ class QuoteController extends Controller
if ($process) { if ($process) {
foreach ($quotes as $quote) { foreach ($quotes as $quote) {
$quote->service()->approve()->save(); $quote->service()->approve(auth()->user())->save();
event(new QuoteWasApproved(auth()->user(), $quote, $quote->company, Ninja::eventVars())); event(new QuoteWasApproved(auth('contact')->user(), $quote, $quote->company, Ninja::eventVars()));
} }
return redirect() return redirect()

View File

@ -408,6 +408,10 @@ class CompanyController extends BaseController
*/ */
public function update(UpdateCompanyRequest $request, Company $company) public function update(UpdateCompanyRequest $request, Company $company)
{ {
if($request->hasFile('company_logo') || (is_array($request->input('settings')) && !array_key_exists('company_logo', $request->input('settings'))))
$this->removeLogo($company);
$company = $this->company_repo->save($request->all(), $company); $company = $this->company_repo->save($request->all(), $company);
$company->saveSettings($request->input('settings'), $company); $company->saveSettings($request->input('settings'), $company);

View File

@ -16,7 +16,6 @@ use App\Http\Requests\Credit\ShowCreditRequest;
use App\Http\Requests\Credit\StoreCreditRequest; use App\Http\Requests\Credit\StoreCreditRequest;
use App\Http\Requests\Credit\UpdateCreditRequest; use App\Http\Requests\Credit\UpdateCreditRequest;
use App\Http\Requests\Invoice\EditInvoiceRequest; use App\Http\Requests\Invoice\EditInvoiceRequest;
use App\Jobs\Credit\StoreCredit;
use App\Jobs\Entity\EmailEntity; use App\Jobs\Entity\EmailEntity;
use App\Jobs\Invoice\EmailCredit; use App\Jobs\Invoice\EmailCredit;
use App\Jobs\Invoice\MarkInvoicePaid; use App\Jobs\Invoice\MarkInvoicePaid;
@ -188,7 +187,9 @@ class CreditController extends BaseController
$credit = $this->credit_repository->save($request->all(), CreditFactory::create(auth()->user()->company()->id, auth()->user()->id)); $credit = $this->credit_repository->save($request->all(), CreditFactory::create(auth()->user()->company()->id, auth()->user()->id));
$credit = StoreCredit::dispatchNow($credit, $request->all(), $credit->company); $credit = $credit->service()
->fillDefaults()
->save();
event(new CreditWasCreated($credit, $credit->company, Ninja::eventVars())); event(new CreditWasCreated($credit, $credit->company, Ninja::eventVars()));
@ -553,7 +554,7 @@ class CreditController extends BaseController
// EmailCredit::dispatch($credit, $credit->company); // EmailCredit::dispatch($credit, $credit->company);
$credit->invitations->load('contact.client.country', 'credit.client.country', 'credit.company')->each(function ($invitation) use ($credit) { $credit->invitations->load('contact.client.country', 'credit.client.country', 'credit.company')->each(function ($invitation) use ($credit) {
EmailEntity::dispatch($invitation, $credit->company); EmailEntity::dispatch($invitation, $credit->company, 'credit');
}); });
@ -571,10 +572,10 @@ class CreditController extends BaseController
public function downloadPdf($invitation_key) public function downloadPdf($invitation_key)
{ {
$invitation = $this->credit_repository->getInvitationByKey($invitation_key); $invitation = $this->credit_repository->getInvitationByKey($invitation_key);
$contact = $invitation->contact; // $contact = $invitation->contact;
$credit = $invitation->credit; $credit = $invitation->credit;
$file_path = $credit->service()->getCreditPdf($contact); $file_path = $credit->service()->getCreditPdf($invitation);
return response()->download($file_path); return response()->download($file_path);
} }

View File

@ -11,7 +11,6 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Helpers\Email\InvoiceEmail;
use App\Http\Requests\Email\SendEmailRequest; use App\Http\Requests\Email\SendEmailRequest;
use App\Jobs\Entity\EmailEntity; use App\Jobs\Entity\EmailEntity;
use App\Jobs\Invoice\EmailInvoice; use App\Jobs\Invoice\EmailInvoice;
@ -117,22 +116,30 @@ class EmailController extends BaseController
$subject = $request->input('subject'); $subject = $request->input('subject');
$body = $request->input('body'); $body = $request->input('body');
$entity_string = strtolower(class_basename($entity_obj)); $entity_string = strtolower(class_basename($entity_obj));
$template = $request->input('template');
$template = str_replace("email_template_", "", $template);
$entity_obj->invitations->each(function ($invitation) use ($subject, $body, $entity_string, $entity_obj, $template) {
$entity_obj->invitations->each(function ($invitation) use ($subject, $body, $entity_string, $entity_obj) {
if ($invitation->contact->send_email && $invitation->contact->email) { if ($invitation->contact->send_email && $invitation->contact->email) {
EmailEntity::dispatchNow($invitation, $invitation->company); $data = [
//$invitation->contact->notify((new SendGenericNotification($invitation, $entity_string, $subject, $body))->delay($when)); 'subject' => $subject,
'body' => $body
];
EmailEntity::dispatchNow($invitation, $invitation->company, $template, $data);
} }
}); });
$entity_obj->last_sent_date = now(); $entity_obj->last_sent_date = now();
$entity_obj->save(); $entity_obj->save();
/*Only notify the admin ONCE, not once per contact/invite*/ /*Only notify the admin ONCE, not once per contact/invite*/
$invitation = $entity_obj->invitations->first(); // $invitation = $entity_obj->invitations->first();
// EntitySentMailer::dispatch($invitation, $entity_string, $entity_obj->user, $invitation->company);
EntitySentMailer::dispatch($invitation, $entity_string, $entity_obj->user, $invitation->company);
if ($entity_obj instanceof Invoice) { if ($entity_obj instanceof Invoice) {
$this->entity_type = Invoice::class; $this->entity_type = Invoice::class;

View File

@ -11,6 +11,8 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Events\Expense\ExpenseWasCreated;
use App\Events\Expense\ExpenseWasUpdated;
use App\Factory\ExpenseFactory; use App\Factory\ExpenseFactory;
use App\Filters\ExpenseFilters; use App\Filters\ExpenseFilters;
use App\Http\Requests\Expense\CreateExpenseRequest; use App\Http\Requests\Expense\CreateExpenseRequest;
@ -29,6 +31,7 @@ use App\Models\Size;
use App\Repositories\BaseRepository; use App\Repositories\BaseRepository;
use App\Repositories\ExpenseRepository; use App\Repositories\ExpenseRepository;
use App\Transformers\ExpenseTransformer; use App\Transformers\ExpenseTransformer;
use App\Utils\Ninja;
use App\Utils\Traits\BulkOptions; use App\Utils\Traits\BulkOptions;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Utils\Traits\Uploadable; use App\Utils\Traits\Uploadable;
@ -281,6 +284,8 @@ class ExpenseController extends BaseController
$this->uploadLogo($request->file('company_logo'), $expense->company, $expense); $this->uploadLogo($request->file('company_logo'), $expense->company, $expense);
event(new ExpenseWasUpdated($expense, $expense->company, Ninja::eventVars()));
return $this->itemResponse($expense->fresh()); return $this->itemResponse($expense->fresh());
} }
@ -373,6 +378,8 @@ class ExpenseController extends BaseController
{ {
$expense = $this->expense_repo->save($request->all(), ExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id)); $expense = $this->expense_repo->save($request->all(), ExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id));
event(new ExpenseWasCreated($expense, $expense->company, Ninja::eventVars()));
return $this->itemResponse($expense); return $this->itemResponse($expense);
} }

View File

@ -20,7 +20,6 @@ use App\Factory\CloneInvoiceFactory;
use App\Factory\CloneInvoiceToQuoteFactory; use App\Factory\CloneInvoiceToQuoteFactory;
use App\Factory\InvoiceFactory; use App\Factory\InvoiceFactory;
use App\Filters\InvoiceFilters; use App\Filters\InvoiceFilters;
use App\Helpers\Email\InvoiceEmail;
use App\Http\Requests\Invoice\ActionInvoiceRequest; use App\Http\Requests\Invoice\ActionInvoiceRequest;
use App\Http\Requests\Invoice\CreateInvoiceRequest; use App\Http\Requests\Invoice\CreateInvoiceRequest;
use App\Http\Requests\Invoice\DestroyInvoiceRequest; use App\Http\Requests\Invoice\DestroyInvoiceRequest;
@ -35,8 +34,10 @@ use App\Jobs\Util\UnlinkFile;
use App\Models\Client; use App\Models\Client;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\InvoiceInvitation; use App\Models\InvoiceInvitation;
use App\Models\Quote;
use App\Repositories\InvoiceRepository; use App\Repositories\InvoiceRepository;
use App\Transformers\InvoiceTransformer; use App\Transformers\InvoiceTransformer;
use App\Transformers\QuoteTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\TempFile; use App\Utils\TempFile;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
@ -213,7 +214,10 @@ class InvoiceController extends BaseController
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars())); event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars()));
$invoice = $invoice->service()->triggeredActions($request)->save(); $invoice = $invoice->service()
->fillDefaults()
->triggeredActions($request)
->save();
return $this->itemResponse($invoice); return $this->itemResponse($invoice);
} }
@ -637,7 +641,12 @@ class InvoiceController extends BaseController
break; break;
case 'clone_to_quote': case 'clone_to_quote':
$quote = CloneInvoiceToQuoteFactory::create($invoice, auth()->user()->id); $quote = CloneInvoiceToQuoteFactory::create($invoice, auth()->user()->id);
// todo build the quote transformer and return response here
$this->entity_transformer = QuoteTransformer::class;
$this->entity_type = Quote::class;
return $this->itemResponse($quote);
break; break;
case 'history': case 'history':
// code... // code...
@ -720,9 +729,8 @@ class InvoiceController extends BaseController
$invoice->service()->touchReminder($this->reminder_template)->save(); $invoice->service()->touchReminder($this->reminder_template)->save();
$invoice->invitations->load('contact.client.country', 'invoice.client.country', 'invoice.company')->each(function ($invitation) use ($invoice) { $invoice->invitations->load('contact.client.country', 'invoice.client.country', 'invoice.company')->each(function ($invitation) use ($invoice) {
$email_builder = (new InvoiceEmail())->build($invitation, $this->reminder_template); EmailEntity::dispatch($invitation, $invoice->company, $this->reminder_template);
EmailEntity::dispatch($invitation, $invoice->company);
}); });
if (! $bulk) { if (! $bulk) {
@ -790,4 +798,57 @@ class InvoiceController extends BaseController
return response()->download($file_path, basename($file_path)); return response()->download($file_path, basename($file_path));
} }
/**
* @OA\Get(
* path="/api/v1/invoices/{id}/delivery_note",
* operationId="deliveryNote",
* tags={"invoices"},
* summary="Download a specific invoice delivery notes",
* description="Downloads a specific invoice delivery notes",
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Parameter(
* name="id",
* in="path",
* description="The Invoice Hahsed Id",
* example="D2J234DFA",
* required=true,
* @OA\Schema(
* type="string",
* format="string",
* ),
* ),
* @OA\Response(
* response=200,
* description="Returns the invoice delivery note pdf",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
* @param $invoice
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function deliveryNote(ShowInvoiceRequest $request, Invoice $invoice)
{
$file_path = $invoice->service()->getInvoiceDeliveryNote($invoice, $invoice->invitations->first()->contact);
$file = base_path("storage/app/public/{$file_path}");
return response()->download($file, basename($file));
}
} }

View File

@ -7,8 +7,8 @@
* @OA\Property(property="company_id", type="string", example="2", description="______"), * @OA\Property(property="company_id", type="string", example="2", description="______"),
* @OA\Property(property="gateway_key", type="string", example="2", description="______"), * @OA\Property(property="gateway_key", type="string", example="2", description="______"),
* @OA\Property(property="accepted_credit_cards", type="integer", example="32", description="Bitmask representation of cards"), * @OA\Property(property="accepted_credit_cards", type="integer", example="32", description="Bitmask representation of cards"),
* @OA\Property(property="show_billing_address", type="boolean", example=true, description="______"), * @OA\Property(property="require_billing_address", type="boolean", example=true, description="______"),
* @OA\Property(property="show_shipping_address", type="boolean", example=true, description="______"), * @OA\Property(property="require_shipping_address", type="boolean", example=true, description="______"),
* @OA\Property(property="config", type="string", example="dfadsfdsafsafd", description="The configuration map for the gateway"), * @OA\Property(property="config", type="string", example="dfadsfdsafsafd", description="The configuration map for the gateway"),
* @OA\Property(property="update_details", type="boolean", example=true, description="______"), * @OA\Property(property="update_details", type="boolean", example=true, description="______"),
* @OA\Property( * @OA\Property(

View File

@ -12,15 +12,15 @@
* @OA\License( * @OA\License(
* name="Attribution Assurance License", * name="Attribution Assurance License",
* url="https://opensource.org/licenses/AAL" * url="https://opensource.org/licenses/AAL"
* ) * ),
* ), * ),
* @OA\Server( * @OA\Server(
* description="Example InvoiceNinja base url", * description="Example InvoiceNinja base url",
* url="https://ninja.test" * url="https://ninja.test",
* ), * ),
* @OA\ExternalDocumentation( * @OA\ExternalDocumentation(
* description="http://docs.invoiceninja.com", * description="http://docs.invoiceninja.com",
* url="http://docs.invoiceninja.com" * url="http://docs.invoiceninja.com"
* ) * ),
* ) * ),
*/ */

View File

@ -29,8 +29,10 @@ use App\Repositories\BaseRepository;
use App\Repositories\PaymentRepository; use App\Repositories\PaymentRepository;
use App\Transformers\PaymentTransformer; use App\Transformers\PaymentTransformer;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Events\Payment\PaymentWasUpdated;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use App\Utils\Ninja;
/** /**
* Class PaymentController. * Class PaymentController.
@ -379,6 +381,7 @@ class PaymentController extends BaseController
$payment = $this->payment_repo->save($request->all(), $payment); $payment = $this->payment_repo->save($request->all(), $payment);
event(new PaymentWasUpdated($payment, $payment->company, Ninja::eventVars()));
return $this->itemResponse($payment); return $this->itemResponse($payment);
} }
@ -506,7 +509,7 @@ class PaymentController extends BaseController
$payments->each(function ($payment, $key) use ($action) { $payments->each(function ($payment, $key) use ($action) {
if (auth()->user()->can('edit', $payment)) { if (auth()->user()->can('edit', $payment)) {
$this->payment_repo->{$action}($payment); $this->performAction($payment, $action, true);
} }
}); });
@ -584,30 +587,31 @@ class PaymentController extends BaseController
* @param Payment $payment * @param Payment $payment
* @param $action * @param $action
*/ */
public function action(ActionPaymentRequest $request, Payment $payment, $action) public function performAction(Payment $payment, $action, $bulk = false)
{ {
switch ($action) { switch ($action) {
case 'clone_to_invoice': case 'restore':
//$payment = CloneInvoiceFactory::create($payment, auth()->user()->id); $this->payment_repo->restore($payment);
//return $this->itemResponse($payment);
break; if (! $bulk) {
case 'clone_to_quote': return $this->listResponse($payment);
//$quote = CloneInvoiceToQuoteFactory::create($payment, auth()->user()->id); }
// todo build the quote transformer and return response here
break;
case 'history':
// code...
break;
case 'delivery_note':
// code...
break;
case 'mark_paid':
// code...
break; break;
case 'archive': case 'archive':
$this->payment_repo->archive($payment);
if (! $bulk) {
return $this->listResponse($payment);
}
// code... // code...
break; break;
case 'delete': case 'delete':
$this->payment_repo->delete($payment);
if (! $bulk) {
return $this->listResponse($payment);
}
// code... // code...
break; break;
case 'email': case 'email':

View File

@ -11,6 +11,8 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Events\Quote\QuoteWasCreated;
use App\Events\Quote\QuoteWasUpdated;
use App\Factory\CloneInvoiceFactory; use App\Factory\CloneInvoiceFactory;
use App\Factory\CloneInvoiceToQuoteFactory; use App\Factory\CloneInvoiceToQuoteFactory;
use App\Factory\CloneQuoteFactory; use App\Factory\CloneQuoteFactory;
@ -31,6 +33,7 @@ use App\Models\Quote;
use App\Repositories\QuoteRepository; use App\Repositories\QuoteRepository;
use App\Transformers\InvoiceTransformer; use App\Transformers\InvoiceTransformer;
use App\Transformers\QuoteTransformer; use App\Transformers\QuoteTransformer;
use App\Utils\Ninja;
use App\Utils\TempFile; use App\Utils\TempFile;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -79,8 +82,8 @@ class QuoteController extends BaseController
* tags={"quotes"}, * tags={"quotes"},
* summary="Gets a list of quotes", * summary="Gets a list of quotes",
* description="Lists quotes, search and filters allow fine grained lists to be generated. * description="Lists quotes, search and filters allow fine grained lists to be generated.
*
Query parameters can be added to performed more fine grained filtering of the quotes, these are handled by the QuoteFilters class which defines the methods available", * Query parameters can be added to performed more fine grained filtering of the quotes, these are handled by the QuoteFilters class which defines the methods available",
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"), * @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"), * @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
@ -204,6 +207,10 @@ class QuoteController extends BaseController
$quote = $this->quote_repo->save($request->all(), QuoteFactory::create(auth()->user()->company()->id, auth()->user()->id)); $quote = $this->quote_repo->save($request->all(), QuoteFactory::create(auth()->user()->company()->id, auth()->user()->id));
$quote = $quote->service()->fillDefaults()->save();
event(new QuoteWasCreated($quote, $quote->company, Ninja::eventVars()));
return $this->itemResponse($quote); return $this->itemResponse($quote);
} }
@ -378,6 +385,8 @@ class QuoteController extends BaseController
$quote = $this->quote_repo->save($request->all(), $quote); $quote = $this->quote_repo->save($request->all(), $quote);
event(new QuoteWasUpdated($quote, $quote->company, Ninja::eventVars()));
return $this->itemResponse($quote); return $this->itemResponse($quote);
} }
@ -658,15 +667,26 @@ class QuoteController extends BaseController
}, basename($quote->pdf_file_path())); }, basename($quote->pdf_file_path()));
//return response()->download(TempFile::path($quote->pdf_file_path()), basename($quote->pdf_file_path())); //return response()->download(TempFile::path($quote->pdf_file_path()), basename($quote->pdf_file_path()));
break; break;
case 'restore':
$this->quote_repo->restore($quote);
if (!$bulk)
return $this->listResponse($quote);
break;
case 'archive': case 'archive':
$this->quote_repo->archive($quote); $this->quote_repo->archive($quote);
if (!$bulk)
return $this->listResponse($quote); return $this->listResponse($quote);
break; break;
case 'delete': case 'delete':
$this->quote_repo->delete($quote); $this->quote_repo->delete($quote);
if (!$bulk)
return $this->listResponse($quote); return $this->listResponse($quote);
break; break;
case 'email': case 'email':
$quote->service()->sendEmail(); $quote->service()->sendEmail();
@ -679,6 +699,7 @@ class QuoteController extends BaseController
if (! $bulk) { if (! $bulk) {
return $this->itemResponse($quote); return $this->itemResponse($quote);
} }
break;
// no break // no break
default: default:
return response()->json(['message' => "The requested action `{$action}` is not available."], 400); return response()->json(['message' => "The requested action `{$action}` is not available."], 400);

View File

@ -23,9 +23,11 @@ use App\Http\Requests\RecurringQuote\ShowRecurringQuoteRequest;
use App\Http\Requests\RecurringQuote\StoreRecurringQuoteRequest; use App\Http\Requests\RecurringQuote\StoreRecurringQuoteRequest;
use App\Http\Requests\RecurringQuote\UpdateRecurringQuoteRequest; use App\Http\Requests\RecurringQuote\UpdateRecurringQuoteRequest;
use App\Jobs\Entity\ActionEntity; use App\Jobs\Entity\ActionEntity;
use App\Models\Quote;
use App\Models\RecurringQuote; use App\Models\RecurringQuote;
use App\Repositories\BaseRepository; use App\Repositories\BaseRepository;
use App\Repositories\RecurringQuoteRepository; use App\Repositories\RecurringQuoteRepository;
use App\Transformers\QuoteTransformer;
use App\Transformers\RecurringQuoteTransformer; use App\Transformers\RecurringQuoteTransformer;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -583,8 +585,11 @@ class RecurringQuoteController extends BaseController
// return $this->itemResponse($recurring_invoice); // return $this->itemResponse($recurring_invoice);
break; break;
case 'clone_to_quote': case 'clone_to_quote':
// $quote = CloneRecurringQuoteToQuoteFactory::create($recurring_invoice, auth()->user()->id); $quote = CloneRecurringQuoteToQuoteFactory::create($recurring_invoice, auth()->user()->id);
// todo build the quote transformer and return response here $this->entity_transformer = QuoteTransformer::class;
$this->entity_type = Quote::class;
return $this->itemResponse($quote);
break; break;
case 'history': case 'history':
// code... // code...

View File

@ -84,4 +84,9 @@ class SelfUpdateController extends BaseController
return response()->json(['message' => ''], 200); return response()->json(['message' => ''], 200);
} }
public function checkVersion()
{
return trim(file_get_contents(config('ninja.version_url')));
}
} }

View File

@ -11,6 +11,8 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Events\Task\TaskWasCreated;
use App\Events\Task\TaskWasUpdated;
use App\Factory\TaskFactory; use App\Factory\TaskFactory;
use App\Filters\TaskFilters; use App\Filters\TaskFilters;
use App\Http\Requests\Task\CreateTaskRequest; use App\Http\Requests\Task\CreateTaskRequest;
@ -24,11 +26,12 @@ use App\Jobs\Util\ProcessBulk;
use App\Jobs\Util\UploadAvatar; use App\Jobs\Util\UploadAvatar;
use App\Models\Country; use App\Models\Country;
use App\Models\Currency; use App\Models\Currency;
use App\Models\Task;
use App\Models\Size; use App\Models\Size;
use App\Models\Task;
use App\Repositories\BaseRepository; use App\Repositories\BaseRepository;
use App\Repositories\TaskRepository; use App\Repositories\TaskRepository;
use App\Transformers\TaskTransformer; use App\Transformers\TaskTransformer;
use App\Utils\Ninja;
use App\Utils\Traits\BulkOptions; use App\Utils\Traits\BulkOptions;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Utils\Traits\Uploadable; use App\Utils\Traits\Uploadable;
@ -278,6 +281,8 @@ class TaskController extends BaseController
$task = $this->task_repo->save($request->all(), $task); $task = $this->task_repo->save($request->all(), $task);
event(new TaskWasUpdated($task, $task->company, Ninja::eventVars()));
return $this->itemResponse($task->fresh()); return $this->itemResponse($task->fresh());
} }
@ -370,6 +375,8 @@ class TaskController extends BaseController
{ {
$task = $this->task_repo->save($request->all(), TaskFactory::create(auth()->user()->company()->id, auth()->user()->id)); $task = $this->task_repo->save($request->all(), TaskFactory::create(auth()->user()->company()->id, auth()->user()->id));
event(new TaskWasCreated($task, $task->company, Ninja::eventVars()));
return $this->itemResponse($task); return $this->itemResponse($task);
} }

View File

@ -11,6 +11,8 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Events\Vendor\VendorWasCreated;
use App\Events\Vendor\VendorWasUpdated;
use App\Factory\VendorFactory; use App\Factory\VendorFactory;
use App\Filters\VendorFilters; use App\Filters\VendorFilters;
use App\Http\Requests\Vendor\CreateVendorRequest; use App\Http\Requests\Vendor\CreateVendorRequest;
@ -29,6 +31,7 @@ use App\Models\Vendor;
use App\Repositories\BaseRepository; use App\Repositories\BaseRepository;
use App\Repositories\VendorRepository; use App\Repositories\VendorRepository;
use App\Transformers\VendorTransformer; use App\Transformers\VendorTransformer;
use App\Utils\Ninja;
use App\Utils\Traits\BulkOptions; use App\Utils\Traits\BulkOptions;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Utils\Traits\Uploadable; use App\Utils\Traits\Uploadable;
@ -280,6 +283,8 @@ class VendorController extends BaseController
$this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor); $this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor);
event(new VendorWasUpdated($vendor, $vendor->company, Ninja::eventVars()));
return $this->itemResponse($vendor->fresh()); return $this->itemResponse($vendor->fresh());
} }
@ -376,6 +381,8 @@ class VendorController extends BaseController
$this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor); $this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor);
event(new VendorWasCreated($vendor, $vendor->company, Ninja::eventVars()));
return $this->itemResponse($vendor); return $this->itemResponse($vendor);
} }

View File

@ -380,7 +380,7 @@ class WebhookController extends BaseController
* *
* @throws \Exception * @throws \Exception
* @OA\Delete( * @OA\Delete(
* path="/api/v1/Webhooks/{id}", * path="/api/v1/webhooks/{id}",
* operationId="deleteWebhook", * operationId="deleteWebhook",
* tags={"Webhooks"}, * tags={"Webhooks"},
* summary="Deletes a Webhook", * summary="Deletes a Webhook",

View File

@ -55,7 +55,7 @@ class ContactTokenAuth
//stateless, don't remember the contact. //stateless, don't remember the contact.
auth()->guard('contact')->login($client_contact, false); auth()->guard('contact')->login($client_contact, false);
event(new ContactLoggedIn($client_contact, $client_contact->company, Ninja::eventVars())); //todo event(new ContactLoggedIn($client_contact, $client_contact->company, Ninja::eventVars()));
} else { } else {
$error = [ $error = [
'message' => 'Invalid token', 'message' => 'Invalid token',

View File

@ -75,7 +75,7 @@ class StoreClientRequest extends Request
$input = $this->all(); $input = $this->all();
//@todo implement feature permissions for > 100 clients //@todo implement feature permissions for > 100 clients
//
$settings = ClientSettings::defaults(); $settings = ClientSettings::defaults();
if (array_key_exists('settings', $input) && ! empty($input['settings'])) { if (array_key_exists('settings', $input) && ! empty($input['settings'])) {

View File

@ -28,7 +28,7 @@ class ShowDocumentRequest extends FormRequest
*/ */
public function authorize() public function authorize()
{ {
return auth()->user('contact')->client->id === $this->document->documentable->id; return auth()->user('contact')->client->id == $this->document->documentable_id;
} }
/** /**

View File

@ -77,7 +77,7 @@ class StorePaymentRequest extends Request
} }
if (! isset($input['amount']) || $input['amount'] == 0) { if (! isset($input['amount']) || $input['amount'] == 0) {
$input['amount'] = $invoices_total - $credits_total; //todo the payment amount is always less the credit amount applied $input['amount'] = $invoices_total - $credits_total;
} }
$input['is_manual'] = true; $input['is_manual'] = true;

View File

@ -109,19 +109,17 @@ class StoreRecurringInvoiceRequest extends Request
} }
$this->replace($input); $this->replace($input);
} }
private function setAutoBillFlag($auto_bill) private function setAutoBillFlag($auto_bill)
{ {
if($auto_bill == 'always') if($auto_bill == 'always')
return true; return true;
if($auto_bill == 'off') if($auto_bill == 'off')
return false; return false;
//todo do we need to handle optin / optout here? }
}
public function messages() public function messages()
{ {

View File

@ -46,14 +46,26 @@ class ValidCreditsPresentRule implements Rule
{ {
//todo need to ensure the clients credits are here not random ones! //todo need to ensure the clients credits are here not random ones!
if (request()->input('credits') && is_array(request()->input('credits'))) { // if (request()->input('credits') && is_array(request()->input('credits'))) {
foreach (request()->input('credits') as $credit) { // foreach (request()->input('credits') as $credit) {
$cred = Credit::find($this->decodePrimaryKey($credit['credit_id'])); // $cred = Credit::find($this->decodePrimaryKey($credit['credit_id']));
if (! $cred || $cred->balance == 0) { // if (! $cred || $cred->balance == 0) {
return false; // return false;
} // }
} // }
// }
// return true;
if (request()->input('credits') && is_array(request()->input('credits'))) {
$credit_collection = Credit::whereIn('id', $this->transformKeys(array_column(request()->input('credits'), 'credit_id')))
->where('balance', '>', 0)
->get();
return $credit_collection->count() == count(request()->input('credits'));
} }
return true; return true;

View File

@ -12,7 +12,9 @@
namespace App\Http\ViewComposers; namespace App\Http\ViewComposers;
use App\Models\ClientContact; use App\Models\ClientContact;
use App\Utils\Ninja;
use App\Utils\TranslationHelper; use App\Utils\TranslationHelper;
use Illuminate\Support\Facades\Lang;
use Illuminate\View\View; use Illuminate\View\View;
/** /**
@ -29,6 +31,9 @@ class PortalComposer
public function compose(View $view) :void public function compose(View $view) :void
{ {
$view->with($this->portalData()); $view->with($this->portalData());
if(auth()->user())
Lang::replace(Ninja::transformTranslations(auth()->user()->client->getMergedSettings()));
} }
/** /**

View File

@ -1,55 +0,0 @@
<?php
namespace App\Jobs\Credit;
use App\Jobs\Payment\PaymentNotification;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Credit;
use App\Repositories\CreditRepository;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class StoreCredit implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $credit;
protected $data;
/**
* Create a new job instance.
*
* @param Credit $credit
* @param array $data
*/
public function __construct(Credit $credit, array $data)
{
$this->credit = $credit;
$this->data = $data;
}
/**
* Execute the job.
*
* @param CreditRepository $credit_repository
* @return Credit|null
*/
public function handle(CreditRepository $credit_repository): ?Credit
{
// MultiDB::setDB($this->company->db);
// $payment = false;
// if ($payment) {
// PaymentNotification::dispatch($payment, $payment->company);
// }
return $this->credit;
}
}

View File

@ -31,6 +31,7 @@ use App\Services\PdfMaker\Design as PdfDesignModel;
use App\Services\PdfMaker\Design as PdfMakerDesign; use App\Services\PdfMaker\Design as PdfMakerDesign;
use App\Services\PdfMaker\PdfMaker as PdfMakerService; use App\Services\PdfMaker\PdfMaker as PdfMakerService;
use App\Utils\HtmlEngine; use App\Utils\HtmlEngine;
use App\Utils\Ninja;
use App\Utils\PhantomJS\Phantom; use App\Utils\PhantomJS\Phantom;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Utils\Traits\MakesInvoiceHtml; use App\Utils\Traits\MakesInvoiceHtml;
@ -42,6 +43,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Spatie\Browsershot\Browsershot; use Spatie\Browsershot\Browsershot;
@ -102,6 +104,7 @@ class CreateEntityPdf implements ShouldQueue
} }
App::setLocale($this->contact->preferredLocale()); App::setLocale($this->contact->preferredLocale());
App::forgetInstance('translator');
$entity_design_id = ''; $entity_design_id = '';
@ -118,6 +121,8 @@ class CreateEntityPdf implements ShouldQueue
$entity_design_id = 'credit_design_id'; $entity_design_id = 'credit_design_id';
} }
Lang::replace(Ninja::transformTranslations($this->entity->client->getMergedSettings()));
$file_path = $path.$this->entity->number.'.pdf'; $file_path = $path.$this->entity->number.'.pdf';
$entity_design_id = $this->entity->design_id ? $this->entity->design_id : $this->decodePrimaryKey($this->entity->client->getSetting($entity_design_id)); $entity_design_id = $this->entity->design_id ? $this->entity->design_id : $this->decodePrimaryKey($this->entity->client->getSetting($entity_design_id));
@ -139,7 +144,7 @@ class CreateEntityPdf implements ShouldQueue
'client' => $this->entity->client, 'client' => $this->entity->client,
'entity' => $this->entity, 'entity' => $this->entity,
'pdf_variables' => (array) $this->entity->company->settings->pdf_variables, 'pdf_variables' => (array) $this->entity->company->settings->pdf_variables,
'products' => $design->design->product, '$product' => $design->design->product,
]), ]),
'variables' => $html->generateLabelsAndValues(), 'variables' => $html->generateLabelsAndValues(),
'options' => [ 'options' => [

View File

@ -12,13 +12,14 @@
namespace App\Jobs\Entity; namespace App\Jobs\Entity;
use App\DataMapper\Analytics\EmailInvoiceFailure; use App\DataMapper\Analytics\EmailInvoiceFailure;
use App\Events\Invoice\InvoiceReminderWasEmailed;
use App\Events\Invoice\InvoiceWasEmailed; use App\Events\Invoice\InvoiceWasEmailed;
use App\Events\Invoice\InvoiceWasEmailedAndFailed; use App\Events\Invoice\InvoiceWasEmailedAndFailed;
use App\Helpers\Email\InvoiceEmail;
use App\Jobs\Mail\BaseMailerJob; use App\Jobs\Mail\BaseMailerJob;
use App\Jobs\Utils\SystemLogger; use App\Jobs\Utils\SystemLogger;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Mail\TemplateEmail; use App\Mail\TemplateEmail;
use App\Models\Activity;
use App\Models\Company; use App\Models\Company;
use App\Models\CreditInvitation; use App\Models\CreditInvitation;
use App\Models\Invoice; use App\Models\Invoice;
@ -61,13 +62,14 @@ class EmailEntity extends BaseMailerJob implements ShouldQueue
public $email_entity_builder; public $email_entity_builder;
public $template_data;
/** /**
* EmailEntity constructor. * EmailEntity constructor.
* @param Invitation $invitation * @param Invitation $invitation
* @param Company $company * @param Company $company
* @param ?string $reminder_template * @param ?string $reminder_template
*/ */
public function __construct($invitation, Company $company, ?string $reminder_template = null) public function __construct($invitation, Company $company, ?string $reminder_template = null, $template_data = null)
{ {
$this->company = $company; $this->company = $company;
@ -79,11 +81,14 @@ class EmailEntity extends BaseMailerJob implements ShouldQueue
$this->entity = $invitation->{$this->entity_string}; $this->entity = $invitation->{$this->entity_string};
$this->reminder_template = $reminder_template ?: $this->findReminderTemplate(); $this->reminder_template = $reminder_template ?: $this->entity->calculateTemplate($this->entity_string);
$this->html_engine = new HtmlEngine($invitation); $this->html_engine = new HtmlEngine($invitation);
$this->template_data = $template_data;
$this->email_entity_builder = $this->resolveEmailBuilder(); $this->email_entity_builder = $this->resolveEmailBuilder();
} }
/** /**
@ -166,26 +171,32 @@ class EmailEntity extends BaseMailerJob implements ShouldQueue
private function entityEmailSucceeded() private function entityEmailSucceeded()
{ {
switch ($this->entity_string) { switch ($this->reminder_template) {
case 'invoice': case 'invoice':
event(new InvoiceWasEmailed($this->invitation, $this->company, Ninja::eventVars())); event(new InvoiceWasEmailed($this->invitation, $this->company, Ninja::eventVars()));
break; break;
case 'reminder1':
event(new InvoiceReminderWasEmailed($this->invitation, $this->company, Ninja::eventVars(), Activity::INVOICE_REMINDER1_SENT));
break;
case 'reminder2':
event(new InvoiceReminderWasEmailed($this->invitation, $this->company, Ninja::eventVars(), Activity::INVOICE_REMINDER2_SENT));
break;
case 'reminder3':
event(new InvoiceReminderWasEmailed($this->invitation, $this->company, Ninja::eventVars(), Activity::INVOICE_REMINDER3_SENT));
break;
case 'reminder_endless':
event(new InvoiceReminderWasEmailed($this->invitation, $this->company, Ninja::eventVars(), Activity::INVOICE_REMINDER_ENDLESS_SENT));
break;
default: default:
# code... # code...
break; break;
} }
} }
private function findReminderTemplate()
{
}
private function resolveEmailBuilder() private function resolveEmailBuilder()
{ {
$class = 'App\Mail\Engine\\' . ucfirst(Str::camel($this->entity_string)) . "EmailEngine"; $class = 'App\Mail\Engine\\' . ucfirst(Str::camel($this->entity_string)) . "EmailEngine";
return (new $class($this->invitation, $this->reminder_template))->build(); return (new $class($this->invitation, $this->reminder_template, $this->template_data))->build();
} }
} }

View File

@ -16,12 +16,15 @@ use App\Libraries\Google\Google;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\User; use App\Models\User;
use App\Providers\MailServiceProvider; use App\Providers\MailServiceProvider;
use App\Utils\Ninja;
use Illuminate\Bus\Queueable; 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 Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Lang;
use Turbo124\Beacon\Facades\LightLogs; use Turbo124\Beacon\Facades\LightLogs;
/*Multi Mailer implemented*/ /*Multi Mailer implemented*/
@ -32,6 +35,9 @@ class BaseMailerJob implements ShouldQueue
public function setMailDriver() public function setMailDriver()
{ {
App::forgetInstance('translator');
Lang::replace(Ninja::transformTranslations($this->settings));
switch ($this->settings->email_sending_method) { switch ($this->settings->email_sending_method) {
case 'default': case 'default':
break; break;
@ -69,7 +75,7 @@ class BaseMailerJob implements ShouldQueue
} }
public function logMailError($errors, $recipient_object) public function logMailError($errors, $recipient_object)
{ {info(print_r($errors,1));
SystemLogger::dispatch( SystemLogger::dispatch(
$errors, $errors,
SystemLog::CATEGORY_MAIL, SystemLog::CATEGORY_MAIL,

View File

@ -53,11 +53,11 @@ class EntityPaidMailer extends BaseMailerJob implements ShouldQueue
* @param $user * @param $user
* @param $company * @param $company
*/ */
public function __construct($payment, $company) public function __construct($payment, $company, $user)
{ {
$this->company = $company; $this->company = $company;
$this->user = $payment->user; $this->user = $user;
$this->payment = $payment; $this->payment = $payment;
@ -84,7 +84,7 @@ class EntityPaidMailer extends BaseMailerJob implements ShouldQueue
try { try {
$mail_obj = (new EntityPaidObject($this->payment))->build(); $mail_obj = (new EntityPaidObject($this->payment))->build();
$mail_obj->from = [$this->payment->user->email, $this->payment->user->present()->name()]; $mail_obj->from = [$this->user->email, $this->user->present()->name()];
//send email //send email
Mail::to($this->user->email) Mail::to($this->user->email)
@ -96,7 +96,7 @@ class EntityPaidMailer extends BaseMailerJob implements ShouldQueue
} }
if (count(Mail::failures()) > 0) { if (count(Mail::failures()) > 0) {
$this->logMailError(Mail::failures(), $this->entity->client); $this->logMailError(Mail::failures(), $this->payment->client);
} else { } else {
// $this->entityEmailSucceeded(); // $this->entityEmailSucceeded();
} }

View File

@ -11,7 +11,6 @@
namespace App\Jobs\Ninja; namespace App\Jobs\Ninja;
use App\Helpers\Email\InvoiceEmail;
use App\Jobs\Invoice\EmailInvoice; use App\Jobs\Invoice\EmailInvoice;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Account; use App\Models\Account;

View File

@ -11,7 +11,6 @@
namespace App\Jobs\Ninja; namespace App\Jobs\Ninja;
use App\Helpers\Email\InvoiceEmail;
use App\Jobs\Invoice\EmailInvoice; use App\Jobs\Invoice\EmailInvoice;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Account; use App\Models\Account;

View File

@ -11,7 +11,6 @@
namespace App\Jobs\Ninja; namespace App\Jobs\Ninja;
use App\Helpers\Email\InvoiceEmail;
use App\Jobs\Invoice\EmailInvoice; use App\Jobs\Invoice\EmailInvoice;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Account; use App\Models\Account;

View File

@ -0,0 +1,327 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Jobs\Ninja;
use App\DataMapper\InvoiceItem;
use App\Events\Invoice\InvoiceWasEmailed;
use App\Jobs\Entity\EmailEntity;
use App\Libraries\MultiDB;
use App\Models\Invoice;
use App\Utils\Ninja;
use App\Utils\Traits\MakesDates;
use App\Utils\Traits\MakesReminders;
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\Carbon;
class SendReminders implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MakesDates, MakesReminders;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
info("Sending reminders ".Carbon::now()->format('Y-m-d h:i:s'));
if (! config('ninja.db.multi_db_enabled')) {
$this->sendReminderEmails();
} else {
//multiDB environment, need to
foreach (MultiDB::$dbs as $db)
{
MultiDB::setDB($db);
$this->sendReminderEmails();
}
}
}
private function sendReminderEmails()
{
$invoices = Invoice::where('is_deleted', 0)
->where('balance', '>', 0)
->whereDate('next_send_date', '<=', now()->startOfDay())
->whereNotNull('next_send_date')
->with('client')
->cursor();
//we only need invoices that are payable
$invoices->filter(function ($invoice){
return $invoice->isPayable();
})->each(function ($invoice){
$reminder_template = $invoice->calculateTemplate('invoice');
info("hitting a reminder for {$invoice->number} with template {$reminder_template}");
if(in_array($reminder_template, ['reminder1', 'reminder2', 'reminder3', 'endless_reminder']))
$this->sendReminder($invoice, $reminder_template);
});
}
private function checkSendSetting($invoice, $template)
{
switch ($template) {
case 'reminder1':
return $invoice->client->getSetting('enable_reminder1');
break;
case 'reminder2':
return $invoice->client->getSetting('enable_reminder2');
break;
case 'reminder3':
return $invoice->client->getSetting('enable_reminder3');
break;
case 'endless_reminder':
return $invoice->client->getSetting('enable_reminder_endless');
break;
default:
return false;
break;
}
}
/**
* Create a collection of all possible reminder dates
* and pass back the first one in chronology
*
* @param Invoice $invoice
* @return Carbon $date
*/
private function calculateNextSendDate($invoice)
{
$dates = collect();
$settings = $invoice->client->getMergedSettings();
$set_reminder1 = false;
$set_reminder2 = false;
$set_reminder3 = false;
if((int)$settings->schedule_reminder1 > 0){
$next_reminder_date = $this->calculateScheduledDate($invoice, (int)$settings->schedule_reminder1, (int)$settings->num_days_reminder1);
if($next_reminder_date->gt(Carbon::parse($invoice->last_sent_date)));
$dates->push($next_reminder_date);
if(!$invoice->reminder1_sent)
$set_reminder1 = true;
}
if((int)$settings->num_days_reminder2 > 0){
$next_reminder_date = $this->calculateScheduledDate($invoice, (int)$settings->schedule_reminder2, (int)$settings->num_days_reminder2);
if($next_reminder_date->gt(Carbon::parse($invoice->last_sent_date)));
$dates->push($next_reminder_date);
if(!$invoice->reminder2_sent)
$set_reminder3 = true;
}
if((int)$settings->num_days_reminder3 > 0){
$next_reminder_date = $this->calculateScheduledDate($invoice, (int)$settings->schedule_reminder3, (int)$settings->num_days_reminder3);
if($next_reminder_date->gt(Carbon::parse($invoice->last_sent_date)));
$dates->push($next_reminder_date);
if(!$invoice->reminder3_sent)
$set_reminder3 = true;
}
//If all the available reminders have fired, we then start to fire the endless reminders
if((int)$settings->endless_reminder_frequency_id > 0 && !$set_reminder1 && !$set_reminder2 && !$set_reminder3) {
$dates->push($this->addTimeInterval($invoice->last_sent_date, (int)$settings->endless_reminder_frequency_id));
}
//order the dates ascending and get first one
return $dates->sort()->first();
}
/**
* Helper method which switches values based on the $schedule_reminder
* @param Invoice $invoice
* @param string $schedule_reminder
* @param int $num_days_reminder
* @return Carbon $date
*/
private function calculateScheduledDate($invoice, $schedule_reminder, $num_days_reminder) :?Carbon
{
switch ($schedule_reminder) {
case 'after_invoice_date':
return Carbon::parse($invoice->date)->addDays($num_days_reminder)->startOfDay();
break;
case 'before_due_date':
return Carbon::parse($invoice->due_date)->subDays($num_days_reminder)->startOfDay();
break;
case 'after_due_date':
return Carbon::parse($invoice->due_date)->addDays($num_days_reminder)->startOfDay();
break;
default:
return null;
break;
}
}
/**
* Sends the reminder and/or late fee for the invoice.
*
* @param Invoice $invoice
* @param string $template
* @return void
*/
private function sendReminder($invoice, $template) :void
{
$invoice = $this->calcLateFee($invoice, $template);
$invoice->invitations->each(function ($invitation) use($template, $invoice){
//only send if enable_reminder setting is toggled to yes
if($this->checkSendSetting($invoice, $template)) {
info("firing email");
EmailEntity::dispatchNow($invitation, $invitation->company, $template);
}
});
if($this->checkSendSetting($invoice, $template))
event(new InvoiceWasEmailed($invoice->invitations->first(), $invoice->company, Ninja::eventVars()));
$invoice->last_sent_date = now();
$invoice->next_send_date = $this->calculateNextSendDate($invoice);
if(in_array($template, ['reminder1', 'reminder2', 'reminder3']))
$invoice->{$template."_sent"} = now();
$invoice->save();
}
/**
* Calculates the late if - if any - and rebuilds the invoice
*
* @param Invoice $invoice
* @param string $template
* @return Invoice
*/
private function calcLateFee($invoice, $template) :Invoice
{
$late_fee_amount = 0;
$late_fee_percent = 0;
switch ($template) {
case 'reminder1':
$late_fee_amount = $invoice->client->getSetting('late_fee_amount1');
$late_fee_percent = $invoice->client->getSetting('late_fee_percent1');
break;
case 'reminder2':
$late_fee_amount = $invoice->client->getSetting('late_fee_amount2');
$late_fee_percent = $invoice->client->getSetting('late_fee_percent2');
break;
case 'reminder3':
$late_fee_amount = $invoice->client->getSetting('late_fee_amount3');
$late_fee_percent = $invoice->client->getSetting('late_fee_percent3');
break;
case 'endless_reminder':
$late_fee_amount = $invoice->client->getSetting('late_fee_endless_amount');
$late_fee_percent = $invoice->client->getSetting('late_fee_endless_percent');
break;
default:
$late_fee_amount = 0;
$late_fee_percent = 0;
break;
}
return $this->setLateFee($invoice, $late_fee_amount, $late_fee_percent);
}
/**
* Applies the late fee to the invoice line items
*
* @param Invoice $invoice
* @param float $amount The fee amount
* @param float $percent The fee percentage amount
*
* @return Invoice
*/
private function setLateFee($invoice, $amount, $percent) :Invoice
{
$temp_invoice_balance = $invoice->balance;
if ($amount <= 0 && $percent <= 0)
return $invoice;
$fee = $amount;
if ($invoice->partial > 0)
$fee += round($invoice->partial * $percent / 100, 2);
else
$fee += round($invoice->balance * $percent / 100, 2);
$invoice_item = new InvoiceItem;
$invoice_item->type_id = '5';
$invoice_item->product_key = trans('texts.fee');
$invoice_item->notes = ctrans('texts.late_fee_added', ['date' => $this->formatDate(now()->startOfDay(), $invoice->client->date_format())]);
$invoice_item->quantity = 1;
$invoice_item->cost = $fee;
$invoice_items = $invoice->line_items;
$invoice_items[] = $invoice_item;
$invoice->line_items = $invoice_items;
/**Refresh Invoice values*/
$invoice = $invoice->calc()->getInvoice();
$this->invoice->client->service()->updateBalance($this->invoice->balance - $temp_invoice_balance)->save();
$this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance - $temp_invoice_balance);
return $invoice;
}
}

View File

@ -2,6 +2,7 @@
namespace App\Jobs\Payment; namespace App\Jobs\Payment;
use App\DataMapper\Analytics\EmailInvoiceFailure;
use App\Events\Invoice\InvoiceWasEmailed; use App\Events\Invoice\InvoiceWasEmailed;
use App\Events\Invoice\InvoiceWasEmailedAndFailed; use App\Events\Invoice\InvoiceWasEmailedAndFailed;
use App\Events\Payment\PaymentWasEmailed; use App\Events\Payment\PaymentWasEmailed;
@ -10,7 +11,9 @@ use App\Helpers\Email\BuildEmail;
use App\Jobs\Mail\BaseMailerJob; use App\Jobs\Mail\BaseMailerJob;
use App\Jobs\Utils\SystemLogger; use App\Jobs\Utils\SystemLogger;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Mail\Engine\PaymentEmailEngine;
use App\Mail\TemplateEmail; use App\Mail\TemplateEmail;
use App\Models\ClientContact;
use App\Models\Company; use App\Models\Company;
use App\Models\Payment; use App\Models\Payment;
use App\Models\SystemLog; use App\Models\SystemLog;
@ -21,6 +24,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use Turbo124\Beacon\Facades\LightLogs;
class EmailPayment extends BaseMailerJob implements ShouldQueue class EmailPayment extends BaseMailerJob implements ShouldQueue
{ {
@ -33,6 +37,9 @@ class EmailPayment extends BaseMailerJob implements ShouldQueue
private $contact; private $contact;
private $company; private $company;
public $settings;
/** /**
* Create a new job instance. * Create a new job instance.
* *
@ -41,12 +48,12 @@ class EmailPayment extends BaseMailerJob implements ShouldQueue
* @param $contact * @param $contact
* @param $company * @param $company
*/ */
public function __construct(Payment $payment, $email_builder, $contact, company) public function __construct(Payment $payment, Company $company, ClientContact $contact)
{ {
$this->payment = $payment; $this->payment = $payment;
$this->email_builder = $email_builder;
$this->contact = $contact; $this->contact = $contact;
$this->company = $company; $this->company = $company;
$this->settings = $payment->client->getMergedSettings();
} }
/** /**
@ -62,14 +69,15 @@ class EmailPayment extends BaseMailerJob implements ShouldQueue
if ($this->contact->email) { if ($this->contact->email) {
MultiDB::setDb($this->payment->company->db); //this may fail if we don't pass the serialized object with the company record MultiDB::setDb($this->company->db);
//todo fix!!
//if we need to set an email driver do it now //if we need to set an email driver do it now
$this->setMailDriver(); $this->setMailDriver();
$email_builder = (new PaymentEmailEngine($this->payment, $this->contact))->build();
Mail::to($this->contact->email, $this->contact->present()->name()) Mail::to($this->contact->email, $this->contact->present()->name())
->send(new TemplateEmail($this->email_builder, $this->contact->user, $this->contact->customer)); ->send(new TemplateEmail($email_builder, $this->contact->user, $this->contact->client));
if (count(Mail::failures()) > 0) { if (count(Mail::failures()) > 0) {
event(new PaymentWasEmailedAndFailed($this->payment, Mail::failures(), Ninja::eventVars())); event(new PaymentWasEmailedAndFailed($this->payment, Mail::failures(), Ninja::eventVars()));
@ -77,21 +85,22 @@ class EmailPayment extends BaseMailerJob implements ShouldQueue
return $this->logMailError(Mail::failures()); return $this->logMailError(Mail::failures());
} }
//fire any events
event(new PaymentWasEmailed($this->payment, $this->payment->company, Ninja::eventVars())); event(new PaymentWasEmailed($this->payment, $this->payment->company, Ninja::eventVars()));
//sleep(5);
} }
} }
private function logMailError($errors) public function failed($exception = null)
{ {
SystemLogger::dispatch( info('the job failed');
$errors,
SystemLog::CATEGORY_MAIL, $job_failure = new EmailInvoiceFailure();
SystemLog::EVENT_MAIL_SEND, $job_failure->string_metric5 = 'payment';
SystemLog::TYPE_FAILURE, $job_failure->string_metric6 = $exception->getMessage();
$this->payment->client
); LightLogs::create($job_failure)
->batch();
} }
} }

View File

@ -18,7 +18,6 @@ use App\Models\Product;
use App\Repositories\InvoiceRepository; use App\Repositories\InvoiceRepository;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Capsule\Eloquent;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
@ -27,11 +26,11 @@ class UpdateOrCreateProduct implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $products; public $products;
private $invoice; public $invoice;
private $company; public $company;
/** /**
* Create a new job instance. * Create a new job instance.
@ -59,7 +58,14 @@ class UpdateOrCreateProduct implements ShouldQueue
{ {
MultiDB::setDB($this->company->db); MultiDB::setDB($this->company->db);
foreach ($this->products as $item) { //only update / create products - not tasks or gateway fees
$updateable_products = collect($this->products)->filter(function ($item) {
return $item->type_id == 1;
});
foreach ($updateable_products as $item) {
if (empty($item->product_key)) { if (empty($item->product_key)) {
continue; continue;
} }

View File

@ -14,7 +14,6 @@ namespace App\Jobs\RecurringInvoice;
use App\DataMapper\Analytics\SendRecurringFailure; use App\DataMapper\Analytics\SendRecurringFailure;
use App\Events\Invoice\InvoiceWasEmailed; use App\Events\Invoice\InvoiceWasEmailed;
use App\Factory\RecurringInvoiceToInvoiceFactory; use App\Factory\RecurringInvoiceToInvoiceFactory;
use App\Helpers\Email\InvoiceEmail;
use App\Jobs\Entity\EmailEntity; use App\Jobs\Entity\EmailEntity;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\RecurringInvoice; use App\Models\RecurringInvoice;
@ -74,8 +73,6 @@ class SendRecurring implements ShouldQueue
$invoice->invitations->each(function ($invitation) use ($invoice) { $invoice->invitations->each(function ($invitation) use ($invoice) {
$email_builder = (new InvoiceEmail())->build($invitation);
if($invitation->contact && strlen($invitation->contact->email) >=1){ if($invitation->contact && strlen($invitation->contact->email) >=1){
EmailEntity::dispatch($invitation, $invoice->company); EmailEntity::dispatch($invitation, $invoice->company);
info("Firing email for invoice {$invoice->number}"); info("Firing email for invoice {$invoice->number}");

View File

@ -74,6 +74,7 @@ use App\Repositories\VendorRepository;
use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\CleanLineItems;
use App\Utils\Traits\CompanyGatewayFeesAndLimitsSaver; use App\Utils\Traits\CompanyGatewayFeesAndLimitsSaver;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Utils\Traits\Uploadable;
use Exception; use Exception;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@ -91,7 +92,7 @@ class Import implements ShouldQueue
use CompanyGatewayFeesAndLimitsSaver; use CompanyGatewayFeesAndLimitsSaver;
use MakesHash; use MakesHash;
use CleanLineItems; use CleanLineItems;
use Uploadable;
/** /**
* @var array * @var array
*/ */
@ -260,6 +261,14 @@ class Import implements ShouldQueue
$company_repository = new CompanyRepository(); $company_repository = new CompanyRepository();
$company_repository->save($data, $this->company); $company_repository->save($data, $this->company);
if(isset($data['settings']->company_logo) && strlen($data['settings']->company_logo) > 0) {
$tempImage = tempnam(sys_get_temp_dir(), basename($data['settings']->company_logo));
copy($data['settings']->company_logo, $tempImage);
$this->uploadLogo($tempImage, $this->company, $this->company);
}
Company::reguard(); Company::reguard();
/*Improve memory handling by setting everything to null when we have finished*/ /*Improve memory handling by setting everything to null when we have finished*/
@ -963,6 +972,7 @@ class Import implements ShouldQueue
$modified['company_id'] = $this->company->id; $modified['company_id'] = $this->company->id;
$modified['client_id'] = $this->transformId('clients', $resource['client_id']); $modified['client_id'] = $this->transformId('clients', $resource['client_id']);
$modified['user_id'] = $this->processUserId($resource);
$cgt = ClientGatewayToken::Create($modified); $cgt = ClientGatewayToken::Create($modified);
@ -992,7 +1002,7 @@ class Import implements ShouldQueue
unset($modified['id']); unset($modified['id']);
$modified['company_id'] = $this->company->id; $modified['company_id'] = $this->company->id;
$modified['user_id'] = $this->transformId('users', $resource['user_id']); $modified['user_id'] = $this->processUserId($resource);
$task_status = TaskStatus::Create($modified); $task_status = TaskStatus::Create($modified);
@ -1022,7 +1032,7 @@ class Import implements ShouldQueue
unset($modified['id']); unset($modified['id']);
$modified['company_id'] = $this->company->id; $modified['company_id'] = $this->company->id;
$modified['user_id'] = $this->transformId('users', $resource['user_id']); $modified['user_id'] = $this->processUserId($resource);
$expense_category = ExpenseCategory::Create($modified); $expense_category = ExpenseCategory::Create($modified);
@ -1051,7 +1061,7 @@ class Import implements ShouldQueue
unset($modified['id']); unset($modified['id']);
$modified['company_id'] = $this->company->id; $modified['company_id'] = $this->company->id;
$modified['user_id'] = $this->transformId('users', $resource['user_id']); $modified['user_id'] = $this->processUserId($resource);
if(isset($modified['client_id'])) if(isset($modified['client_id']))
$modified['client_id'] = $this->transformId('clients', $resource['client_id']); $modified['client_id'] = $this->transformId('clients', $resource['client_id']);
@ -1092,7 +1102,7 @@ class Import implements ShouldQueue
unset($modified['id']); unset($modified['id']);
$modified['company_id'] = $this->company->id; $modified['company_id'] = $this->company->id;
$modified['user_id'] = $this->transformId('users', $resource['user_id']); $modified['user_id'] = $this->processUserId($resource);
if(isset($modified['client_id'])) if(isset($modified['client_id']))
$modified['client_id'] = $this->transformId('clients', $resource['client_id']); $modified['client_id'] = $this->transformId('clients', $resource['client_id']);
@ -1125,7 +1135,7 @@ class Import implements ShouldQueue
unset($modified['id']); unset($modified['id']);
$modified['company_id'] = $this->company->id; $modified['company_id'] = $this->company->id;
$modified['user_id'] = $this->transformId('users', $resource['user_id']); $modified['user_id'] = $this->processUserId($resource);
if(isset($resource['client_id'])) if(isset($resource['client_id']))
$modified['client_id'] = $this->transformId('clients', $resource['client_id']); $modified['client_id'] = $this->transformId('clients', $resource['client_id']);

View File

@ -12,7 +12,6 @@
namespace App\Jobs\Util; namespace App\Jobs\Util;
use App\Events\Invoice\InvoiceWasEmailed; use App\Events\Invoice\InvoiceWasEmailed;
use App\Helpers\Email\InvoiceEmail;
use App\Jobs\Invoice\EmailInvoice; use App\Jobs\Invoice\EmailInvoice;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Account; use App\Models\Account;
@ -69,11 +68,9 @@ class ReminderJob implements ShouldQueue
$reminder_template = $invoice->calculateTemplate('invoice'); $reminder_template = $invoice->calculateTemplate('invoice');
$invoice->service()->touchReminder($this->reminder_template)->save(); $invoice->service()->touchReminder($this->reminder_template)->save();
$invoice->invitations->each(function ($invitation) use ($invoice) { $invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) {
$email_builder = (new InvoiceEmail())->build($invitation);
EmailInvoice::dispatch($email_builder, $invitation, $invoice->company);
EmailEntity::dispatch($invitation, $invitation->company, $reminder_template);
info("Firing email for invoice {$invoice->number}"); info("Firing email for invoice {$invoice->number}");
}); });

View File

@ -11,9 +11,7 @@
namespace App\Jobs\Util; namespace App\Jobs\Util;
use App\Helpers\Email\InvoiceEmail;
use App\Jobs\Entity\EmailEntity; use App\Jobs\Entity\EmailEntity;
use App\Jobs\Invoice\EmailInvoice;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\SystemLog; use App\Models\SystemLog;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
@ -66,10 +64,9 @@ class SendFailedEmails implements ShouldQueue
$invitation = $job_meta_array['entity_name']::where('key', $job_meta_array['invitation_key'])->with('contact')->first(); $invitation = $job_meta_array['entity_name']::where('key', $job_meta_array['invitation_key'])->with('contact')->first();
if ($invitation->invoice) { if ($invitation->invoice) {
$email_builder = (new InvoiceEmail())->build($invitation, $job_meta_array['reminder_template']);
if ($invitation->contact->send_email && $invitation->contact->email) { if ($invitation->contact->send_email && $invitation->contact->email) {
EmailEntity::dispatch($invitation, $invitation->company); EmailEntity::dispatch($invitation, $invitation->company, $job_meta_array['reminder_template']);
} }
} }
}); });

View File

@ -1,5 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Jobs\Util; namespace App\Jobs\Util;
use App\Models\Webhook; use App\Models\Webhook;
@ -40,7 +48,7 @@ class WebhookHandler implements ShouldQueue
* @return bool * @return bool
*/ */
public function handle() :bool public function handle() :bool
{ {//todo set multidb here
if (! $this->entity->company || $this->entity->company->is_disabled) { if (! $this->entity->company || $this->entity->company->is_disabled) {
return true; return true;
} }

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\Invoice;
use App\Models\Payment;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use stdClass;
class ClientUpdatedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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);
$client = $event->client;
$fields = new stdClass;
$fields->client_id = $client->id;
$fields->user_id = $client->user_id;
$fields->company_id = $client->company_id;
$fields->activity_type_id = Activity::UPDATE_CLIENT;
$this->activity_repo->save($fields, $client, $event->event_vars);
}
}

View File

@ -0,0 +1,54 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use stdClass;
class CreatedExpenseActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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;
$fields->expense_id = $event->expense->id;
$fields->user_id = $event->expense->user_id;
$fields->company_id = $event->expense->company_id;
$fields->activity_type_id = Activity::CREATE_EXPENSE;
$this->activity_repo->save($fields, $event->expense, $event->event_vars);
}
}

View File

@ -0,0 +1,54 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use stdClass;
class CreatedTaskActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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;
$fields->task_id = $event->task->id;
$fields->user_id = $event->task->user_id;
$fields->company_id = $event->task->company_id;
$fields->activity_type_id = Activity::CREATE_TASK;
$this->activity_repo->save($fields, $event->task, $event->event_vars);
}
}

View File

@ -0,0 +1,54 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use stdClass;
class CreatedVendorActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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;
$fields->vendor_id = $event->vendor->id;
$fields->user_id = $event->vendor->user_id;
$fields->company_id = $event->vendor->company_id;
$fields->activity_type_id = Activity::CREATE_VENDOR;
$this->activity_repo->save($fields, $event->vendor, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\Invoice;
use App\Models\Payment;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use stdClass;
class ExpenseArchivedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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);
$expense = $event->expense;
$fields = new stdClass;
$fields->expense_id = $expense->id;
$fields->user_id = $expense->user_id;
$fields->company_id = $expense->company_id;
$fields->activity_type_id = Activity::ARCHIVE_EXPENSE;
$this->activity_repo->save($fields, $expense, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\ClientContact;
use App\Models\InvoiceInvitation;
use App\Repositories\ActivityRepository;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use stdClass;
class ExpenseDeletedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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;
$fields->expense_id = $event->expense->id;
$fields->user_id = $event->expense->user_id;
$fields->company_id = $event->expense->company_id;
$fields->activity_type_id = Activity::DELETE_VENDOR;
$this->activity_repo->save($fields, $event->expense, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\ClientContact;
use App\Models\InvoiceInvitation;
use App\Repositories\ActivityRepository;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use stdClass;
class ExpenseRestoredActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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;
$fields->expense_id = $event->expense->id;
$fields->user_id = $event->expense->user_id;
$fields->company_id = $event->expense->company_id;
$fields->activity_type_id = Activity::RESTORE_EXPENSE;
$this->activity_repo->save($fields, $event->expense, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\Invoice;
use App\Models\Payment;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use stdClass;
class ExpenseUpdatedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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);
$expense = $event->expense;
$fields = new stdClass;
$fields->expense_id = $expense->id;
$fields->user_id = $expense->user_id;
$fields->company_id = $expense->company_id;
$fields->activity_type_id = Activity::UPDATE_EXPENSE;
$this->activity_repo->save($fields, $expense, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\Invoice;
use App\Models\Payment;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use stdClass;
class TaskArchivedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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);
$task = $event->task;
$fields = new stdClass;
$fields->task_id = $task->id;
$fields->user_id = $task->user_id;
$fields->company_id = $task->company_id;
$fields->activity_type_id = Activity::ARCHIVE_TASK;
$this->activity_repo->save($fields, $task, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\ClientContact;
use App\Models\InvoiceInvitation;
use App\Repositories\ActivityRepository;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use stdClass;
class TaskDeletedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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;
$fields->task_id = $event->task->id;
$fields->user_id = $event->task->user_id;
$fields->company_id = $event->task->company_id;
$fields->activity_type_id = Activity::DELETE_TASK;
$this->activity_repo->save($fields, $event->task, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\ClientContact;
use App\Models\InvoiceInvitation;
use App\Repositories\ActivityRepository;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use stdClass;
class TaskRestoredActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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;
$fields->task_id = $event->task->id;
$fields->user_id = $event->task->user_id;
$fields->company_id = $event->task->company_id;
$fields->activity_type_id = Activity::RESTORE_TASK;
$this->activity_repo->save($fields, $event->task, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\Invoice;
use App\Models\Payment;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use stdClass;
class TaskUpdatedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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);
$task = $event->task;
$fields = new stdClass;
$fields->task_id = $task->id;
$fields->user_id = $task->user_id;
$fields->company_id = $task->company_id;
$fields->activity_type_id = Activity::UPDATE_TASK;
$this->activity_repo->save($fields, $task, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\Invoice;
use App\Models\Payment;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use stdClass;
class VendorArchivedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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);
$vendor = $event->vendor;
$fields = new stdClass;
$fields->vendor_id = $vendor->id;
$fields->user_id = $vendor->user_id;
$fields->company_id = $vendor->company_id;
$fields->activity_type_id = Activity::ARCHIVE_VENDOR;
$this->activity_repo->save($fields, $vendor, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\ClientContact;
use App\Models\InvoiceInvitation;
use App\Repositories\ActivityRepository;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use stdClass;
class VendorDeletedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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;
$fields->vendor_id = $event->vendor->id;
$fields->user_id = $event->vendor->user_id;
$fields->company_id = $event->vendor->company_id;
$fields->activity_type_id = Activity::DELETE_VENDOR;
$this->activity_repo->save($fields, $event->vendor, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\ClientContact;
use App\Models\InvoiceInvitation;
use App\Repositories\ActivityRepository;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use stdClass;
class VendorRestoredActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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;
$fields->vendor_id = $event->vendor->id;
$fields->user_id = $event->vendor->user_id;
$fields->company_id = $event->vendor->company_id;
$fields->activity_type_id = Activity::RESTORE_VENDOR;
$this->activity_repo->save($fields, $event->vendor, $event->event_vars);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Activity;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\Invoice;
use App\Models\Payment;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use stdClass;
class VendorUpdatedActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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);
$vendor = $event->vendor;
$fields = new stdClass;
$fields->vendor_id = $vendor->id;
$fields->user_id = $vendor->user_id;
$fields->company_id = $vendor->company_id;
$fields->activity_type_id = Activity::UPDATE_VENDOR;
$this->activity_repo->save($fields, $vendor, $event->event_vars);
}
}

View File

@ -0,0 +1,59 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Invoice;
use App\Libraries\MultiDB;
use App\Models\Activity;
use App\Models\ClientContact;
use App\Models\InvoiceInvitation;
use App\Repositories\ActivityRepository;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use stdClass;
class InvoiceReminderEmailActivity implements ShouldQueue
{
protected $activity_repo;
/**
* 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;
$fields->invoice_id = $event->invitation->invoice->id;
$fields->user_id = $event->invitation->invoice->user_id;
$fields->company_id = $event->invitation->invoice->company_id;
$fields->client_contact_id = $event->invitation->invoice->client_contact_id;
$fields->activity_type_id = $event->reminder;
$this->activity_repo->save($fields, $event->invitation->invoice, $event->event_vars);
}
}

View File

@ -63,7 +63,7 @@ class PaymentNotification implements ShouldQueue
if (($key = array_search('mail', $methods)) !== false) { if (($key = array_search('mail', $methods)) !== false) {
unset($methods[$key]); unset($methods[$key]);
EntityPaidMailer::dispatch($payment, $payment->company); EntityPaidMailer::dispatch($payment, $payment->company, $user);
} }

View File

@ -54,6 +54,9 @@ class BaseEmailEngine implements EngineInterface
public function setSubject($subject) public function setSubject($subject)
{ {
if (! empty($this->variables))
$subject = str_replace(array_keys($this->variables), array_values($this->variables), $subject);
$this->subject = $subject; $this->subject = $subject;
return $this; return $this;
@ -61,6 +64,9 @@ class BaseEmailEngine implements EngineInterface
public function setBody($body) public function setBody($body)
{ {
if (! empty($this->variables))
$body = str_replace(array_keys($this->variables), array_values($this->variables), $body);
$this->body = $body; $this->body = $body;
return $this; return $this;

View File

@ -26,18 +26,24 @@ class CreditEmailEngine extends BaseEmailEngine
public $reminder_template; public $reminder_template;
public function __construct($invitation, $reminder_template) public $template_data;
public function __construct($invitation, $reminder_template, $template_data)
{ {
$this->invitation = $invitation; $this->invitation = $invitation;
$this->reminder_template = $reminder_template; $this->reminder_template = $reminder_template;
$this->client = $invitation->contact->client; $this->client = $invitation->contact->client;
$this->credit = $invitation->credit; $this->credit = $invitation->credit;
$this->contact = $invitation->contact; $this->contact = $invitation->contact;
$this->template_data = $template_data;
} }
public function build() public function build()
{ {
if(is_array($this->template_data) && array_key_exists('body', $this->template_data) && strlen($this->template_data['body']) > 0)
$body_template = $this->template_data['body'];
else
$body_template = $this->client->getSetting('email_template_'.$this->reminder_template); $body_template = $this->client->getSetting('email_template_'.$this->reminder_template);
/* Use default translations if a custom message has not been set*/ /* Use default translations if a custom message has not been set*/
@ -54,6 +60,9 @@ class CreditEmailEngine extends BaseEmailEngine
); );
} }
if(is_array($this->template_data) && array_key_exists('subject', $this->template_data) && strlen($this->template_data['subject']) > 0)
$subject_template = $this->template_data['subject'];
else
$subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template); $subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template);
if (iconv_strlen($subject_template) == 0) { if (iconv_strlen($subject_template) == 0) {

View File

@ -11,6 +11,7 @@
namespace App\Mail\Engine; namespace App\Mail\Engine;
use App\DataMapper\EmailTemplateDefaults;
use App\Utils\HtmlEngine; use App\Utils\HtmlEngine;
use App\Utils\Number; use App\Utils\Number;
@ -26,19 +27,28 @@ class InvoiceEmailEngine extends BaseEmailEngine
public $reminder_template; public $reminder_template;
public function __construct($invitation, $reminder_template) public $template_data;
public function __construct($invitation, $reminder_template, $template_data)
{ {
$this->invitation = $invitation; $this->invitation = $invitation;
$this->reminder_template = $reminder_template; $this->reminder_template = $reminder_template;
$this->client = $invitation->contact->client; $this->client = $invitation->contact->client;
$this->invoice = $invitation->invoice; $this->invoice = $invitation->invoice;
$this->contact = $invitation->contact; $this->contact = $invitation->contact;
$this->template_data = $template_data;
} }
public function build() public function build()
{ {
if(is_array($this->template_data) && array_key_exists('body', $this->template_data) && strlen($this->template_data['body']) > 0)
$body_template = $this->template_data['body'];
elseif(strlen($this->client->getSetting('email_template_'.$this->reminder_template)) > 0)
$body_template = $this->client->getSetting('email_template_'.$this->reminder_template); $body_template = $this->client->getSetting('email_template_'.$this->reminder_template);
else{
$body_template = EmailTemplateDefaults::getDefaultTemplate('email_template_'.$this->reminder_template, $this->client->locale());
}
/* Use default translations if a custom message has not been set*/ /* Use default translations if a custom message has not been set*/
if (iconv_strlen($body_template) == 0) { if (iconv_strlen($body_template) == 0) {
@ -54,7 +64,19 @@ class InvoiceEmailEngine extends BaseEmailEngine
); );
} }
if(is_array($this->template_data) && array_key_exists('subject', $this->template_data) && strlen($this->template_data['subject']) > 0){
$subject_template = $this->template_data['subject'];
info("subject = template data");
}
elseif(strlen($this->client->getSetting('email_subject_'.$this->reminder_template)) > 0){
$subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template); $subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template);
info("subject = settings var");
}
else{
info("subject = default template " . 'email_subject_'.$this->reminder_template);
$subject_template = EmailTemplateDefaults::getDefaultTemplate('email_subject_'.$this->reminder_template, $this->client->locale());
// $subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template);
}
if (iconv_strlen($subject_template) == 0) { if (iconv_strlen($subject_template) == 0) {
@ -80,7 +102,7 @@ class InvoiceEmailEngine extends BaseEmailEngine
->setViewText(ctrans('texts.view_invoice')); ->setViewText(ctrans('texts.view_invoice'));
if ($this->client->getSetting('pdf_email_attachment') !== false) { if ($this->client->getSetting('pdf_email_attachment') !== false) {
$this->setAttachments($invitation->pdf_file_path()); $this->setAttachments($this->invoice->pdf_file_path());
} }
return $this; return $this;

Some files were not shown because too many files have changed in this diff Show More