mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 05:02:36 +01:00
Fixes and Refactors for Invoice Emails. (#3339)
* Working on emailing invoices * Working on emailing and displaying email * Working on emailing and displaying email * Email invoices * Fixes for html emails * Ensure valid client prior to store * Ensure client exists when storing an entity * Update variable name send -> send_email for client_contacts * Mailable download files * Extend timeouts of password protected routes when a protected route is hit * Add default portal design to company settings * Minor fixes * Fixes for Tests * Fixes for invoicing emails * Refactors for InvoiceEmail * Implement abstractservice * Refactors for services * Refactors for emails * Fixes for Invoice Emails
This commit is contained in:
parent
c148157bac
commit
f57339f185
@ -2,10 +2,13 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\DataMapper\DefaultSettings;
|
||||
use App\Factory\ClientFactory;
|
||||
use App\Factory\CompanyUserFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\InvoiceInvitationFactory;
|
||||
use App\Helpers\Email\InvoiceEmail;
|
||||
use App\Jobs\Invoice\CreateInvoicePdf;
|
||||
use App\Mail\TemplateEmail;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
@ -49,9 +52,7 @@ class SendTestEmails extends Command
|
||||
public function handle()
|
||||
{
|
||||
$this->sendTemplateEmails('plain');
|
||||
sleep(5);
|
||||
$this->sendTemplateEmails('light');
|
||||
sleep(5);
|
||||
$this->sendTemplateEmails('dark');
|
||||
}
|
||||
|
||||
@ -68,24 +69,46 @@ class SendTestEmails extends Command
|
||||
|
||||
$user = User::whereEmail('user@example.com')->first();
|
||||
|
||||
$account = factory(\App\Models\Account::class)->create();
|
||||
|
||||
$company = factory(\App\Models\Company::class)->create([
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
|
||||
$client = Client::all()->first();
|
||||
|
||||
if (!$user) {
|
||||
|
||||
$user = factory(\App\Models\User::class)->create([
|
||||
'confirmation_code' => '123',
|
||||
'email' => $faker->safeEmail,
|
||||
'first_name' => 'John',
|
||||
'last_name' => 'Doe',
|
||||
]);
|
||||
|
||||
$account = factory(\App\Models\Account::class)->create();
|
||||
|
||||
|
||||
$company = factory(\App\Models\Company::class)->create([
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
|
||||
$user->companies()->attach($company->id, [
|
||||
'account_id' => $account->id,
|
||||
'is_owner' => 1,
|
||||
'is_admin' => 1,
|
||||
'is_locked' => 0,
|
||||
'permissions' => '',
|
||||
'settings' => DefaultSettings::userSettings(),
|
||||
]);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$company = $user->company_users->first()->company;
|
||||
$account = $company->account;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$client = Client::all()->first();
|
||||
|
||||
|
||||
if (!$client) {
|
||||
|
||||
$client = ClientFactory::create($company->id, $user->id);
|
||||
$client->save();
|
||||
|
||||
@ -118,13 +141,18 @@ class SendTestEmails extends Command
|
||||
$ii->save();
|
||||
|
||||
$invoice->setRelation('invitations', $ii);
|
||||
$invoice->service()->markSent()->save();
|
||||
|
||||
$invoice->save();
|
||||
CreateInvoicePdf::dispatch($invoice, $company, $client->primary_contact()->first());
|
||||
|
||||
$cc_emails = [config('ninja.testvars.test_email')];
|
||||
$bcc_emails = [config('ninja.testvars.test_email')];
|
||||
|
||||
$email_builder = (new InvoiceEmail())->build($invoice, null, $client->primary_contact()->first());
|
||||
$email_builder = (new InvoiceEmail())->build($ii, 'invoice');
|
||||
|
||||
$email_builder->setFooter($message['footer'])
|
||||
->setSubject($message['subject'])
|
||||
->setBody($message['body']);
|
||||
|
||||
Mail::to(config('ninja.testvars.test_email'), 'Mr Test')
|
||||
->cc($cc_emails)
|
||||
|
@ -33,6 +33,8 @@ class CompanySettings extends BaseSettings {
|
||||
public $document_email_attachment = false;
|
||||
public $send_portal_password = false;
|
||||
|
||||
public $portal_design_id = '1';
|
||||
|
||||
public $timezone_id = '';
|
||||
public $date_format_id = '';
|
||||
public $military_time = false;
|
||||
@ -218,6 +220,7 @@ class CompanySettings extends BaseSettings {
|
||||
public $invoice_variables = [];
|
||||
|
||||
public static $casts = [
|
||||
'portal_design_id' => 'string',
|
||||
'late_fee_endless_percent' => 'float',
|
||||
'late_fee_endless_amount' => 'float',
|
||||
'auto_email_invoice' => 'bool',
|
||||
|
@ -1,15 +1,13 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Helpers\Email;
|
||||
|
||||
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Quote;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
abstract class EmailBuilder
|
||||
class EmailBuilder
|
||||
{
|
||||
protected $subject;
|
||||
protected $body;
|
||||
@ -84,7 +82,7 @@ abstract class EmailBuilder
|
||||
*/
|
||||
public function setBody($body)
|
||||
{
|
||||
$this->parseTemplate($body, true);
|
||||
$this->body = $this->parseTemplate($body, true);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -10,23 +10,27 @@ namespace App\Helpers\Email;
|
||||
|
||||
|
||||
use App\Models\Invoice;
|
||||
use App\Models\InvoiceInvitation;
|
||||
|
||||
class InvoiceEmail extends EmailBuilder
|
||||
{
|
||||
|
||||
public function build(Invoice $invoice, $reminder_template, $contact = null)
|
||||
public function build(InvoiceInvitation $invitation, $reminder_template)
|
||||
{
|
||||
$client = $invoice->client;
|
||||
$client = $invitation->contact->client;
|
||||
$invoice = $invitation->invoice;
|
||||
$contact = $invitation->contact;
|
||||
|
||||
if(!$reminder_template)
|
||||
$reminder_template = $invoice->calculateTemplate();
|
||||
|
||||
$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',
|
||||
['amount' => $invoice->present()->amount(), 'company' => $invoice->company->present()->name()], null,
|
||||
['invoice' => $invoice->number, 'company' => $invoice->company->present()->name()], null,
|
||||
$invoice->client->locale());
|
||||
}
|
||||
|
||||
@ -36,15 +40,15 @@ class InvoiceEmail extends EmailBuilder
|
||||
if ($reminder_template == 'quote') {
|
||||
$subject_template = trans('texts.invoice_subject',
|
||||
[
|
||||
'number' => $invoice->present()->invoice_number(),
|
||||
'company' => $invoice->company->present()->name()
|
||||
'invoice' => $invoice->present()->invoice_number(),
|
||||
'account' => $invoice->company->present()->name()
|
||||
],
|
||||
null, $invoice->client->locale());
|
||||
} else {
|
||||
$subject_template = trans('texts.reminder_subject',
|
||||
[
|
||||
'number' => $invoice->present()->invoice_number(),
|
||||
'company' => $invoice->company->present()->name()
|
||||
'invoice' => $invoice->present()->invoice_number(),
|
||||
'account' => $invoice->company->present()->name()
|
||||
],
|
||||
null, $invoice->client->locale());
|
||||
}
|
||||
@ -55,7 +59,7 @@ class InvoiceEmail extends EmailBuilder
|
||||
->setVariables($invoice->makeValues($contact))
|
||||
->setSubject($subject_template)
|
||||
->setBody($body_template)
|
||||
->setFooter("<a href='{$invoice->invitations->first()->getLink()}'>Invoice Link</a>");
|
||||
->setFooter("<a href='{$invitation->getLink()}'>{$invitation->getLink()}</a>");
|
||||
|
||||
if ($client->getSetting('pdf_email_attachment') !== false) {
|
||||
$this->setAttachments($invoice->pdf_file_path());
|
||||
|
@ -9,15 +9,19 @@
|
||||
namespace App\Helpers\Email;
|
||||
|
||||
use App\Models\Quote;
|
||||
use App\Models\QuoteInvitation;
|
||||
|
||||
|
||||
class QuoteEmail extends EmailBuilder
|
||||
{
|
||||
|
||||
public function build(Quote $quote, $reminder_template, $contact = null)
|
||||
public function build(QuoteInvitation $invitation, $reminder_template)
|
||||
{
|
||||
$client = $quote->client;
|
||||
$this->template_style = $quote->client->getSetting('email_style');
|
||||
$client = $invitation->client;
|
||||
$quote = $invitation->quote;
|
||||
$contact = $invitation->contact;
|
||||
|
||||
$this->template_style = $client->getSetting('email_style');
|
||||
|
||||
$body_template = $client->getSetting('email_template_' . $reminder_template);
|
||||
|
||||
@ -44,7 +48,7 @@ class QuoteEmail extends EmailBuilder
|
||||
|
||||
$this->setTemplate($quote->client->getSetting('email_style'))
|
||||
->setContact($contact)
|
||||
->setFooter("<a href='{$quote->invitations->first()->getLink()}'>Invoice Link</a>")
|
||||
->setFooter("<a href='{$invitation->getLink()}'>Quote Link</a>")
|
||||
->setVariables($quote->makeValues($contact))
|
||||
->setSubject($subject_template)
|
||||
->setBody($body_template);
|
||||
|
@ -666,7 +666,9 @@ class InvoiceController extends BaseController {
|
||||
case 'email':
|
||||
$invoice->invitations->each(function ($invitation) use($invoice){
|
||||
|
||||
EmailInvoice::dispatch((new InvoiceEmail)->build($invoice, null, null), $invitation, $invoice->company);
|
||||
$email_builder = (new InvoiceEmail())->build($invitation, $this->reminder_template);
|
||||
|
||||
EmailInvoice::dispatch($email_builder, $invitation, $invoice->company);
|
||||
|
||||
});
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="_________"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="client_id", type="string", example="", description="________"),
|
||||
* @OA\Property(
|
||||
* property="contacts",
|
||||
* type="array",
|
||||
|
@ -36,7 +36,7 @@ class Cors
|
||||
|
||||
$response->headers->set('Access-Control-Allow-Origin', '*');
|
||||
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
||||
$response->headers->set('Access-Control-Allow-Headers', 'X-API-SECRET,X-API-TOKEN,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range');
|
||||
$response->headers->set('Access-Control-Allow-Headers', 'X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ class PasswordProtection
|
||||
return response()->json($error, 403);
|
||||
}
|
||||
} elseif (Cache::get(auth()->user()->email."_logged_in")) {
|
||||
|
||||
Cache::pull(auth()->user()->email."_logged_in");
|
||||
Cache::add(auth()->user()->email."_logged_in", Str::random(64), now()->addMinutes(10));
|
||||
|
||||
return $next($request);
|
||||
} else {
|
||||
$error = [
|
||||
|
@ -40,7 +40,9 @@ class StoreCreditRequest extends FormRequest
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if($input['client_id'])
|
||||
$input['client_id'] = $this->decodePrimaryKey($input['client_id']);
|
||||
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
//$input['line_items'] = json_encode($input['line_items']);
|
||||
$this->replace($input);
|
||||
|
@ -46,7 +46,9 @@ class StoreInvoiceRequest extends Request
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if($input['client_id'])
|
||||
$input['client_id'] = $this->decodePrimaryKey($input['client_id']);
|
||||
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
//$input['line_items'] = json_encode($input['line_items']);
|
||||
$this->replace($input);
|
||||
|
@ -45,7 +45,9 @@ class StoreRecurringInvoiceRequest extends Request
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if($input['client_id'])
|
||||
$input['client_id'] = $this->decodePrimaryKey($input['client_id']);
|
||||
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
//$input['line_items'] = json_encode($input['line_items']);
|
||||
$this->replace($input);
|
||||
|
@ -45,7 +45,9 @@ class StoreRecurringQuoteRequest extends Request
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if($input['client_id'])
|
||||
$input['client_id'] = $this->decodePrimaryKey($input['client_id']);
|
||||
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
//$input['line_items'] = json_encode($input['line_items']);
|
||||
$this->replace($input);
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Jobs\Invoice;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\DownloadInvoices;
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Bus\Queueable;
|
||||
@ -19,15 +20,16 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use ZipStream\Option\Archive;
|
||||
use ZipStream\ZipStream;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class ZipInvoices implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $invoice;
|
||||
public $invoices;
|
||||
|
||||
private $company;
|
||||
|
||||
@ -66,7 +68,7 @@ class ZipInvoices implements ShouldQueue
|
||||
|
||||
$zip = new ZipStream($file_name, $options);
|
||||
|
||||
foreach ($invoices as $invoice) {
|
||||
foreach ($this->invoices as $invoice) {
|
||||
$zip->addFileFromPath(basename($invoice->pdf_file_path()), public_path($invoice->pdf_file_path()));
|
||||
}
|
||||
|
||||
@ -76,9 +78,9 @@ class ZipInvoices implements ShouldQueue
|
||||
|
||||
fclose($tempStream);
|
||||
|
||||
|
||||
//fire email here
|
||||
return Storage::disk(config('filesystems.default'))->url($path . $file_name);
|
||||
Mail::to(config('ninja.contact.ninja_official_contact'))
|
||||
->send(new DownloadInvoices(Storage::disk(config('filesystems.default'))->url($path . $file_name)));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ class CreateInvoiceHtmlBackup implements ShouldQueue
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
|
||||
MultiDB::setDB($event->company->db);
|
||||
|
||||
$fields = new \stdClass;
|
||||
|
36
app/Mail/DownloadInvoices.php
Normal file
36
app/Mail/DownloadInvoices.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class DownloadInvoices extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public $file_path;
|
||||
|
||||
public function __construct($file_path)
|
||||
{
|
||||
$this->file_path = $file_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
|
||||
return $this->from(config('mail.from.address')) //todo this needs to be fixed to handle the hosted version
|
||||
->subject(ctrans('texts.download_documents',['size'=>'']))
|
||||
->markdown('email.admin.download_files', [
|
||||
'file_path' => $this->file_path
|
||||
]);
|
||||
}
|
||||
}
|
@ -56,7 +56,7 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
'user_id',
|
||||
'company_id',
|
||||
'backup',
|
||||
'settings',
|
||||
// 'settings',
|
||||
'last_login',
|
||||
'private_notes'
|
||||
];
|
||||
@ -245,6 +245,7 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
*/
|
||||
public function getMergedSettings() :object
|
||||
{
|
||||
|
||||
if ($this->group_settings !== null) {
|
||||
$group_settings = ClientSettings::buildClientSettings($this->group_settings->settings, $this->settings);
|
||||
|
||||
@ -431,7 +432,7 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
$languages = Cache::get('languages');
|
||||
|
||||
return $languages->filter(function ($item) {
|
||||
return $item->id == $this->client->getSetting('language_id');
|
||||
return $item->id == $this->getSetting('language_id');
|
||||
})->first()->locale;
|
||||
|
||||
//$lang = Language::find($this->client->getSetting('language_id'));
|
||||
|
19
app/Services/AbstractService.php
Normal file
19
app/Services/AbstractService.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?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\Services;
|
||||
|
||||
abstract class AbstractService
|
||||
{
|
||||
|
||||
abstract public function run();
|
||||
|
||||
}
|
@ -5,34 +5,36 @@ namespace App\Services\Credit;
|
||||
use App\Credit;
|
||||
use App\Events\Payment\PaymentWasCreated;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Jobs\Company\UpdateCompanyLedgerWithPayment;
|
||||
use App\Jobs\Customer\UpdateCustomerBalance;
|
||||
use App\Jobs\Customer\UpdateCustomerPaidToDate;
|
||||
use App\Jobs\Company\UpdateCompanyLedgerWithPayment;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Services\AbstractService;
|
||||
use App\Services\Customer\CustomerService;
|
||||
use App\Services\Payment\PaymentService;
|
||||
use App\Traits\GeneratesCounter;
|
||||
|
||||
class ApplyNumber
|
||||
class ApplyNumber extends AbstractService
|
||||
{
|
||||
use GeneratesCounter;
|
||||
|
||||
private $customer;
|
||||
|
||||
public function __construct($customer)
|
||||
public function __construct(Client $client)
|
||||
{
|
||||
$this->customer = $customer;
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
public function __invoke($credit)
|
||||
public function run($credit)
|
||||
{
|
||||
|
||||
if ($credit->number != '') {
|
||||
return $credit;
|
||||
}
|
||||
|
||||
$credit->number = $this->getNextCreditNumber($this->customer);
|
||||
$credit->number = $this->getNextCreditNumber($this->client);
|
||||
|
||||
|
||||
return $credit;
|
||||
|
@ -3,18 +3,19 @@ namespace App\Services\Credit;
|
||||
|
||||
use App\Factory\CreditInvitationFactory;
|
||||
use App\Models\CreditInvitation;
|
||||
use App\Services\AbstractService;
|
||||
|
||||
class CreateInvitations
|
||||
class CreateInvitations extends AbstractService
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke($credit)
|
||||
public function run($credit)
|
||||
{
|
||||
|
||||
$contacts = $credit->customer->contacts;
|
||||
$contacts = $credit->client->contacts;
|
||||
|
||||
$contacts->each(function ($contact) use($credit){
|
||||
$invitation = CreditInvitation::whereCompanyId($credit->account_id)
|
||||
@ -23,11 +24,11 @@ class CreateInvitations
|
||||
->first();
|
||||
|
||||
if (!$invitation) {
|
||||
$ii = CreditInvitationFactory::create($credit->account_id, $credit->user_id);
|
||||
$ii = CreditInvitationFactory::create($credit->company_id, $credit->user_id);
|
||||
$ii->credit_id = $credit->id;
|
||||
$ii->client_contact_id = $contact->id;
|
||||
$ii->save();
|
||||
} elseif ($invitation && !$contact->send_credit) {
|
||||
} elseif ($invitation && !$contact->send_email) {
|
||||
$invitation->delete();
|
||||
}
|
||||
});
|
||||
|
@ -3,9 +3,10 @@
|
||||
namespace App\Services\Credit;
|
||||
|
||||
use App\Jobs\Invoice\CreateInvoicePdf;
|
||||
use App\Services\AbstractService;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class GetCreditPdf
|
||||
class GetCreditPdf extends AbstractService
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
@ -15,16 +16,16 @@ class GetCreditPdf
|
||||
public function __invoke($credit, $contact = null)
|
||||
{
|
||||
if (!$contact) {
|
||||
$contact = $credit->customer->primary_contact()->first();
|
||||
$contact = $credit->client->primary_contact()->first();
|
||||
}
|
||||
|
||||
$path = 'public/' . $credit->customer->id . '/credits/';
|
||||
$path = 'public/' . $credit->client->id . '/credits/';
|
||||
$file_path = $path . $credit->number . '.pdf';
|
||||
$disk = config('filesystems.default');
|
||||
$file = Storage::disk($disk)->exists($file_path);
|
||||
|
||||
if (!$file) {
|
||||
$file_path = CreateInvoicePdf::dispatchNow($this, $credit->account, $contact);
|
||||
$file_path = CreateInvoicePdf::dispatchNow($this, $credit->company, $contact);
|
||||
}
|
||||
|
||||
return Storage::disk($disk)->url($file_path);
|
||||
|
@ -14,35 +14,41 @@ namespace App\Services\Invoice;
|
||||
use App\Events\Payment\PaymentWasCreated;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Jobs\Company\UpdateCompanyLedgerWithPayment;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Services\AbstractService;
|
||||
use App\Services\Client\ClientService;
|
||||
use App\Services\Payment\PaymentService;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
|
||||
class ApplyNumber
|
||||
class ApplyNumber extends AbstractService
|
||||
{
|
||||
use GeneratesCounter;
|
||||
|
||||
private $client;
|
||||
|
||||
public function __construct($client)
|
||||
private $invoice;
|
||||
|
||||
public function __construct(Client $client, Invoice $invoice)
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
$this->invoice = $invoice;
|
||||
}
|
||||
|
||||
public function run($invoice)
|
||||
public function run()
|
||||
{
|
||||
if ($invoice->number != '')
|
||||
return $invoice;
|
||||
if ($this->invoice->number != '')
|
||||
return $this->invoice;
|
||||
|
||||
switch ($this->client->getSetting('counter_number_applied')) {
|
||||
case 'when_saved':
|
||||
$invoice->number = $this->getNextInvoiceNumber($this->client);
|
||||
$this->invoice->number = $this->getNextInvoiceNumber($this->client);
|
||||
break;
|
||||
case 'when_sent':
|
||||
if ($invoice->status_id == Invoice::STATUS_SENT) {
|
||||
$invoice->number = $this->getNextInvoiceNumber($this->client);
|
||||
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
|
||||
$this->invoice->number = $this->getNextInvoiceNumber($this->client);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -51,6 +57,6 @@ class ApplyNumber
|
||||
break;
|
||||
}
|
||||
|
||||
return $invoice;
|
||||
return $this->invoice;
|
||||
}
|
||||
}
|
||||
|
@ -14,46 +14,53 @@ namespace App\Services\Invoice;
|
||||
use App\Jobs\Company\UpdateCompanyLedgerWithPayment;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Services\AbstractService;
|
||||
use App\Services\Client\ClientService;
|
||||
|
||||
class ApplyPayment
|
||||
class ApplyPayment extends AbstractService
|
||||
{
|
||||
|
||||
private $invoice;
|
||||
|
||||
public function __construct($invoice)
|
||||
private $payment;
|
||||
|
||||
private $payment_amount;
|
||||
|
||||
public function __construct($invoice, $payment, $payment_amount)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
$this->payment = $payment;
|
||||
$this->payment_amount = $payment_amount;
|
||||
}
|
||||
|
||||
public function run($payment, $payment_amount)
|
||||
public function run()
|
||||
{
|
||||
|
||||
UpdateCompanyLedgerWithPayment::dispatchNow($payment, ($payment_amount*-1), $payment->company);
|
||||
UpdateCompanyLedgerWithPayment::dispatchNow($this->payment, ($this->payment_amount*-1), $this->payment->company);
|
||||
|
||||
$payment->client->service()->updateBalance($payment_amount*-1)->save();
|
||||
$this->payment->client->service()->updateBalance($this->payment_amount*-1)->save();
|
||||
|
||||
/* Update Pivot Record amount */
|
||||
$payment->invoices->each(function ($inv) use($payment_amount){
|
||||
$this->payment->invoices->each(function ($inv){
|
||||
if ($inv->id == $this->invoice->id) {
|
||||
$inv->pivot->amount = $payment_amount;
|
||||
$inv->pivot->amount = $this->payment_amount;
|
||||
$inv->pivot->save();
|
||||
}
|
||||
});
|
||||
|
||||
if ($this->invoice->hasPartial()) {
|
||||
//is partial and amount is exactly the partial amount
|
||||
if ($this->invoice->partial == $payment_amount) {
|
||||
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($payment_amount*-1);
|
||||
} elseif ($this->invoice->partial > 0 && $this->invoice->partial > $payment_amount) { //partial amount exists, but the amount is less than the partial amount
|
||||
$this->invoice->service()->updatePartial($payment_amount*-1)->updateBalance($payment_amount*-1);
|
||||
} elseif ($this->invoice->partial > 0 && $this->invoice->partial < $payment_amount) { //partial exists and the amount paid is GREATER than the partial amount
|
||||
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($payment_amount*-1);
|
||||
if ($this->invoice->partial == $this->payment_amount) {
|
||||
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($this->payment_amount*-1);
|
||||
} elseif ($this->invoice->partial > 0 && $this->invoice->partial > $this->payment_amount) { //partial amount exists, but the amount is less than the partial amount
|
||||
$this->invoice->service()->updatePartial($this->payment_amount*-1)->updateBalance($this->payment_amount*-1);
|
||||
} elseif ($this->invoice->partial > 0 && $this->invoice->partial < $this->payment_amount) { //partial exists and the amount paid is GREATER than the partial amount
|
||||
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($this->payment_amount*-1);
|
||||
}
|
||||
} elseif ($payment_amount == $this->invoice->balance) { //total invoice paid.
|
||||
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($payment_amount*-1);
|
||||
} elseif($payment_amount < $this->invoice->balance) { //partial invoice payment made
|
||||
$this->invoice->service()->clearPartial()->updateBalance($payment_amount*-1);
|
||||
} elseif ($this->payment_amount == $this->invoice->balance) { //total invoice paid.
|
||||
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($this->payment_amount*-1);
|
||||
} elseif($this->payment_amount < $this->invoice->balance) { //partial invoice payment made
|
||||
$this->invoice->service()->clearPartial()->updateBalance($this->payment_amount*-1);
|
||||
}
|
||||
|
||||
return $this->invoice;
|
||||
|
@ -15,29 +15,31 @@ namespace App\Services\Invoice;
|
||||
use App\Factory\InvoiceInvitationFactory;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\Services\AbstractService;
|
||||
|
||||
class CreateInvitations
|
||||
class CreateInvitations extends AbstractService
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
private $invoice;
|
||||
|
||||
public function __construct(Invoice $invoice)
|
||||
{
|
||||
// ..
|
||||
$this->invoice = $invoice;
|
||||
}
|
||||
|
||||
public function run($invoice)
|
||||
public function run()
|
||||
{
|
||||
|
||||
$contacts = $invoice->client->contacts;
|
||||
$this->invoice->client->contacts->each(function ($contact){
|
||||
|
||||
$contacts->each(function ($contact) use($invoice){
|
||||
$invitation = InvoiceInvitation::whereCompanyId($invoice->company_id)
|
||||
$invitation = InvoiceInvitation::whereCompanyId($this->invoice->company_id)
|
||||
->whereClientContactId($contact->id)
|
||||
->whereInvoiceId($invoice->id)
|
||||
->whereInvoiceId($this->invoice->id)
|
||||
->first();
|
||||
|
||||
if (!$invitation && $contact->send) {
|
||||
$ii = InvoiceInvitationFactory::create($invoice->company_id, $invoice->user_id);
|
||||
$ii->invoice_id = $invoice->id;
|
||||
$ii = InvoiceInvitationFactory::create($this->invoice->company_id, $this->invoice->user_id);
|
||||
$ii->invoice_id = $this->invoice->id;
|
||||
$ii->client_contact_id = $contact->id;
|
||||
$ii->save();
|
||||
} elseif ($invitation && !$contact->send) {
|
||||
@ -45,6 +47,6 @@ class CreateInvitations
|
||||
}
|
||||
});
|
||||
|
||||
return $invoice;
|
||||
return $this->invoice;
|
||||
}
|
||||
}
|
||||
|
@ -12,20 +12,32 @@
|
||||
namespace App\Services\Invoice;
|
||||
|
||||
use App\Jobs\Invoice\CreateInvoicePdf;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Invoice;
|
||||
use App\Services\AbstractService;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class GetInvoicePdf
|
||||
class GetInvoicePdf extends AbstractService
|
||||
{
|
||||
|
||||
public function run($invoice, $contact = null)
|
||||
public function __construct(Invoice $invoice, ClientContact $contact = null)
|
||||
{
|
||||
|
||||
if(!$contact)
|
||||
$contact = $invoice->client->primary_contact()->first();
|
||||
$this->invoice = $invoice;
|
||||
|
||||
$path = $invoice->client->invoice_filepath();
|
||||
$this->contact = $contact;
|
||||
|
||||
$file_path = $path . $invoice->number . '.pdf';
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
|
||||
if(!$this->contact)
|
||||
$this->contact = $this->invoice->client->primary_contact()->first();
|
||||
|
||||
$path = $this->invoice->client->invoice_filepath();
|
||||
|
||||
$file_path = $path . $this->invoice->number . '.pdf';
|
||||
|
||||
$disk = config('filesystems.default');
|
||||
|
||||
@ -34,7 +46,7 @@ class GetInvoicePdf
|
||||
if(!$file)
|
||||
{
|
||||
|
||||
$file_path = CreateInvoicePdf::dispatchNow($invoice, $invoice->company, $contact);
|
||||
$file_path = CreateInvoicePdf::dispatchNow($this->invoice, $this->invoice->company, $this->contact);
|
||||
|
||||
}
|
||||
|
||||
|
@ -44,9 +44,9 @@ class InvoiceService
|
||||
*/
|
||||
public function markPaid()
|
||||
{
|
||||
$mark_invoice_paid = new MarkPaid($this->client_service);
|
||||
$mark_invoice_paid = new MarkPaid($this->client_service, $this->invoice);
|
||||
|
||||
$this->invoice = $mark_invoice_paid->run($this->invoice);
|
||||
$this->invoice = $mark_invoice_paid->run();
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -57,9 +57,9 @@ class InvoiceService
|
||||
*/
|
||||
public function applyNumber()
|
||||
{
|
||||
$apply_number = new ApplyNumber($this->invoice->client);
|
||||
$apply_number = new ApplyNumber($this->invoice->client, $this->invoice);
|
||||
|
||||
$this->invoice = $apply_number->run($this->invoice);
|
||||
$this->invoice = $apply_number->run();
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -72,9 +72,9 @@ class InvoiceService
|
||||
*/
|
||||
public function applyPayment(Payment $payment, float $payment_amount)
|
||||
{
|
||||
$apply_payment = new ApplyPayment($this->invoice);
|
||||
$apply_payment = new ApplyPayment($this->invoice, $payment, $payment_amount);
|
||||
|
||||
$this->invoice = $apply_payment->run($payment, $payment_amount);
|
||||
$this->invoice = $apply_payment->run();
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -88,27 +88,27 @@ class InvoiceService
|
||||
*/
|
||||
public function updateBalance($balance_adjustment)
|
||||
{
|
||||
$update_balance = new UpdateBalance($this->invoice);
|
||||
$update_balance = new UpdateBalance($this->invoice, $balance_adjustment);
|
||||
|
||||
$this->invoice = $update_balance->run($balance_adjustment);
|
||||
$this->invoice = $update_balance->run();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function createInvitations()
|
||||
{
|
||||
$create_invitation = new CreateInvitations();
|
||||
$create_invitation = new CreateInvitations($this->invoice);
|
||||
|
||||
$this->invoice = $create_invitation->run($this->invoice);
|
||||
$this->invoice = $create_invitation->run();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function markSent()
|
||||
{
|
||||
$mark_sent = new MarkSent($this->invoice->client);
|
||||
$mark_sent = new MarkSent($this->invoice->client, $this->invoice);
|
||||
|
||||
$this->invoice = $mark_sent->run($this->invoice);
|
||||
$this->invoice = $mark_sent->run();
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -116,16 +116,16 @@ class InvoiceService
|
||||
|
||||
public function getInvoicePdf($contact)
|
||||
{
|
||||
$get_invoice_pdf = new GetInvoicePdf();
|
||||
$get_invoice_pdf = new GetInvoicePdf($this->invoice, $contact);
|
||||
|
||||
return $get_invoice_pdf->run($this->invoice, $contact);
|
||||
return $get_invoice_pdf->run();
|
||||
}
|
||||
|
||||
public function sendEmail($contact)
|
||||
{
|
||||
$send_email = new SendEmail($this->invoice);
|
||||
$send_email = new SendEmail($this->invoice, null, $contact);
|
||||
|
||||
return $send_email->run(null, $contact);
|
||||
return $send_email->run();
|
||||
}
|
||||
|
||||
public function markViewed()
|
||||
|
@ -16,39 +16,44 @@ use App\Factory\PaymentFactory;
|
||||
use App\Jobs\Company\UpdateCompanyLedgerWithPayment;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Services\AbstractService;
|
||||
use App\Services\Client\ClientService;
|
||||
use App\Services\Payment\PaymentService;
|
||||
|
||||
class MarkPaid
|
||||
class MarkPaid extends AbstractService
|
||||
{
|
||||
private $client_service;
|
||||
|
||||
public function __construct($client_service)
|
||||
private $invoice;
|
||||
|
||||
public function __construct(ClientService $client_service, Invoice $invoice)
|
||||
{
|
||||
$this->client_service = $client_service;
|
||||
|
||||
$this->invoice = $invoice;
|
||||
}
|
||||
|
||||
public function run($invoice)
|
||||
public function run()
|
||||
{
|
||||
|
||||
if($invoice->status_id == Invoice::STATUS_DRAFT)
|
||||
$invoice->service()->markSent();
|
||||
if($this->invoice->status_id == Invoice::STATUS_DRAFT)
|
||||
$this->invoice->service()->markSent();
|
||||
|
||||
/* Create Payment */
|
||||
$payment = PaymentFactory::create($invoice->company_id, $invoice->user_id);
|
||||
$payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
|
||||
|
||||
$payment->amount = $invoice->balance;
|
||||
$payment->amount = $this->invoice->balance;
|
||||
$payment->status_id = Payment::STATUS_COMPLETED;
|
||||
$payment->client_id = $invoice->client_id;
|
||||
$payment->client_id = $this->invoice->client_id;
|
||||
$payment->transaction_reference = ctrans('texts.manual_entry');
|
||||
/* Create a payment relationship to the invoice entity */
|
||||
$payment->save();
|
||||
|
||||
$payment->invoices()->attach($invoice->id, [
|
||||
$payment->invoices()->attach($this->invoice->id, [
|
||||
'amount' => $payment->amount
|
||||
]);
|
||||
|
||||
$invoice->service()
|
||||
$this->invoice->service()
|
||||
->updateBalance($payment->amount*-1)
|
||||
->setStatus(Invoice::STATUS_PAID)
|
||||
->save();
|
||||
@ -63,7 +68,7 @@ class MarkPaid
|
||||
->updatePaidToDate($payment->amount)
|
||||
->save();
|
||||
|
||||
return $invoice;
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,38 +14,42 @@ namespace App\Services\Invoice;
|
||||
use App\Events\Invoice\InvoiceWasMarkedSent;
|
||||
use App\Jobs\Company\UpdateCompanyLedgerWithInvoice;
|
||||
use App\Models\Invoice;
|
||||
use App\Services\AbstractService;
|
||||
|
||||
class MarkSent
|
||||
class MarkSent extends AbstractService
|
||||
{
|
||||
|
||||
private $client;
|
||||
|
||||
public function __construct($client)
|
||||
private $invoice;
|
||||
|
||||
public function __construct($client, $invoice)
|
||||
{
|
||||
$this->client = $client;
|
||||
$this->invoice = $invoice;
|
||||
}
|
||||
|
||||
public function run($invoice)
|
||||
public function run()
|
||||
{
|
||||
|
||||
/* Return immediately if status is not draft */
|
||||
if ($invoice->status_id != Invoice::STATUS_DRAFT) {
|
||||
return $invoice;
|
||||
if ($this->invoice->status_id != Invoice::STATUS_DRAFT) {
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
$invoice->markInvitationsSent();
|
||||
$this->invoice->markInvitationsSent();
|
||||
|
||||
$invoice->setReminder();
|
||||
$this->invoice->setReminder();
|
||||
|
||||
event(new InvoiceWasMarkedSent($invoice, $invoice->company));
|
||||
event(new InvoiceWasMarkedSent($this->invoice, $this->invoice->company));
|
||||
|
||||
$this->client->service()->updateBalance($invoice->balance)->save();
|
||||
$this->client->service()->updateBalance($this->invoice->balance)->save();
|
||||
|
||||
$invoice->service()->setStatus(Invoice::STATUS_SENT)->applyNumber()->save();
|
||||
$this->invoice->service()->setStatus(Invoice::STATUS_SENT)->applyNumber()->save();
|
||||
|
||||
UpdateCompanyLedgerWithInvoice::dispatchNow($invoice, $invoice->balance, $invoice->company);
|
||||
UpdateCompanyLedgerWithInvoice::dispatchNow($this->invoice, $this->invoice->balance, $this->invoice->company);
|
||||
|
||||
return $invoice;
|
||||
return $this->invoice;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -13,17 +13,23 @@ namespace App\Services\Invoice;
|
||||
|
||||
use App\Helpers\Email\InvoiceEmail;
|
||||
use App\Jobs\Invoice\EmailInvoice;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Invoice;
|
||||
use App\Services\AbstractService;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class SendEmail
|
||||
class SendEmail extends AbstractService
|
||||
{
|
||||
|
||||
protected $invoice;
|
||||
|
||||
public function __construct(Invoice $invoice)
|
||||
public function __construct(Invoice $invoice, $reminder_template = null, ClientContact $contact = null)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
|
||||
$this->reminder_template = $reminder_template;
|
||||
|
||||
$this->contact = $contact;
|
||||
}
|
||||
|
||||
|
||||
@ -32,15 +38,17 @@ class SendEmail
|
||||
* @param string $reminder_template The template name ie reminder1
|
||||
* @return array
|
||||
*/
|
||||
public function run($reminder_template = null, $contact = null): array
|
||||
public function run()
|
||||
{
|
||||
if (!$reminder_template) {
|
||||
$reminder_template = $this->invoice->status_id == Invoice::STATUS_DRAFT || Carbon::parse($this->invoice->due_date) > now() ? 'invoice' : $this->invoice->calculateTemplate();
|
||||
|
||||
if (!$this->reminder_template) {
|
||||
$this->reminder_template = $this->invoice->calculateTemplate();
|
||||
}
|
||||
|
||||
$email_builder = (new InvoiceEmail())->build($this->invoice, $reminder_template, $contact);
|
||||
$this->invoice->invitations->each(function ($invitation){
|
||||
|
||||
$email_builder = (new InvoiceEmail())->build($invitation, $this->reminder_template);
|
||||
|
||||
$this->invoice->invitations->each(function ($invitation) use ($email_builder) {
|
||||
if ($invitation->contact->send && $invitation->contact->email) {
|
||||
EmailInvoice::dispatch($email_builder, $invitation, $invitation->company);
|
||||
}
|
||||
|
@ -12,31 +12,33 @@
|
||||
namespace App\Services\Invoice;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use App\Services\AbstractService;
|
||||
|
||||
class UpdateBalance
|
||||
class UpdateBalance extends AbstractService
|
||||
{
|
||||
|
||||
private $invoice;
|
||||
|
||||
public function __construct($invoice)
|
||||
private $balance_adjustment;
|
||||
|
||||
public function __construct($invoice, $balance_adjustment)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
$this->balance_adjustment = $balance_adjustment;
|
||||
}
|
||||
|
||||
|
||||
public function run($balance_adjustment)
|
||||
public function run()
|
||||
{
|
||||
|
||||
if ($this->invoice->is_deleted) {
|
||||
return;
|
||||
}
|
||||
|
||||
$balance_adjustment = floatval($balance_adjustment);
|
||||
|
||||
$this->invoice->balance += $balance_adjustment;
|
||||
$this->invoice->balance += floatval($this->balance_adjustment);
|
||||
|
||||
if ($this->invoice->balance == 0) {
|
||||
$this->status_id = Invoice::STATUS_PAID;
|
||||
$this->invoice->status_id = Invoice::STATUS_PAID;
|
||||
// $this->save();
|
||||
// event(new InvoiceWasPaid($this, $this->company));
|
||||
|
||||
|
@ -27,10 +27,13 @@ class SendEmail
|
||||
$reminder_template = $this->quote->status_id == Quote::STATUS_DRAFT || Carbon::parse($this->quote->due_date) > now() ? 'invoice' : $this->quote->calculateTemplate();
|
||||
}
|
||||
|
||||
$email_builder = (new QuoteEmail())->build($this->quote, $reminder_template, $contact);
|
||||
$this->quote->invitations->each(function ($invitation){
|
||||
|
||||
if ($invitation->contact->send && $invitation->contact->email)
|
||||
{
|
||||
|
||||
$email_builder = (new QuoteEmail())->build($invitation, $reminder_template);
|
||||
|
||||
$this->quote->invitations->each(function ($invitation) use ($email_builder) {
|
||||
if ($invitation->contact->send && $invitation->contact->email) {
|
||||
EmailQuote::dispatchNow($email_builder, $invitation);
|
||||
}
|
||||
});
|
||||
|
@ -34,10 +34,11 @@ trait MakesInvoiceHtml
|
||||
{
|
||||
//$variables = array_merge($invoice->makeLabels(), $invoice->makeValues());
|
||||
//$design = str_replace(array_keys($variables), array_values($variables), $design);
|
||||
if(!$contact)
|
||||
$contact = $invoice->client->primary_contact()->first();
|
||||
$invoice->load('client');
|
||||
|
||||
App::setLocale($contact->preferredLocale());
|
||||
$client = $invoice->client;
|
||||
|
||||
App::setLocale($client->preferredLocale());
|
||||
|
||||
$labels = $invoice->makeLabels();
|
||||
$values = $invoice->makeValues($contact);
|
||||
|
@ -576,8 +576,11 @@ trait MakesInvoiceValues
|
||||
* @param array $items The array of invoice items
|
||||
* @return array The formatted array of invoice items
|
||||
*/
|
||||
private function transformLineItems(array $items) :array
|
||||
private function transformLineItems($items) :array
|
||||
{
|
||||
if(!is_array($items))
|
||||
return [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$item->cost = Number::formatMoney($item->cost, $this->client);
|
||||
$item->line_total = Number::formatMoney($item->line_total, $this->client);
|
||||
|
@ -378,7 +378,7 @@ class CreateUsersTable extends Migration
|
||||
$table->string('password');
|
||||
$table->string('token')->nullable();
|
||||
$table->boolean('is_locked')->default(false);
|
||||
$table->boolean('send')->default(true);
|
||||
$table->boolean('send_email')->default(true);
|
||||
$table->string('contact_key')->nullable();
|
||||
$table->rememberToken();
|
||||
$table->timestamps(6);
|
||||
|
20
resources/views/email/admin/download_files.blade.php
Normal file
20
resources/views/email/admin/download_files.blade.php
Normal file
@ -0,0 +1,20 @@
|
||||
@component('mail::layout')
|
||||
|
||||
{{-- Header --}}
|
||||
@slot('header')
|
||||
@component('mail::header', ['url' => config('app.url')])
|
||||
Download
|
||||
@endcomponent
|
||||
@endslot
|
||||
|
||||
{{-- Body --}}
|
||||
{{ $file_path }}
|
||||
|
||||
{{-- Footer --}}
|
||||
@slot('footer')
|
||||
@component('mail::footer')
|
||||
© {{ date('Y') }} {{ config('ninja.app_name') }}.
|
||||
@endcomponent
|
||||
@endslot
|
||||
|
||||
@endcomponent
|
@ -4,10 +4,9 @@
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{!! $body !!}
|
||||
|
||||
|
||||
{!! $footer !!}
|
||||
</body>
|
||||
<footer>
|
||||
{!! $footer !!}
|
||||
</footer>
|
||||
</html>
|
@ -87,7 +87,7 @@
|
||||
<div>
|
||||
<h2>trans('texts.sign_up_now')</h2>
|
||||
<p>trans('texts.not_a_member_yet')</p>
|
||||
<a class="btn btn-primary active mt-3" href="{{route('signup') }}">trans('texts.login_create_an_account')</a>
|
||||
<a class="btn btn-primary active mt-3" href=" route('signup') ">trans('texts.login_create_an_account')</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -41,7 +41,7 @@ class InvoiceEmailTest extends TestCase
|
||||
$this->makeTestData();
|
||||
}
|
||||
|
||||
public function test_initial_email_sends()
|
||||
public function test_initial_email_send_emails()
|
||||
{
|
||||
|
||||
$this->invoice->date = now();
|
||||
@ -50,15 +50,14 @@ class InvoiceEmailTest extends TestCase
|
||||
|
||||
$this->invoice->client_id = $this->client->id;
|
||||
$this->invoice->setRelation('client', $this->client);
|
||||
|
||||
$this->invoice->save();
|
||||
|
||||
$invitations = InvoiceInvitation::whereInvoiceId($this->invoice->id)->get();
|
||||
$this->invoice->invitations->each(function ($invitation) {
|
||||
|
||||
$email_builder = (new InvoiceEmail())->build($this->invoice, null, null);
|
||||
if ($invitation->contact->send_email && $invitation->contact->email) {
|
||||
|
||||
$invitations->each(function ($invitation) use ($email_builder) {
|
||||
|
||||
if ($invitation->contact->send && $invitation->contact->email) {
|
||||
$email_builder = (new InvoiceEmail())->build($invitation, null);
|
||||
|
||||
EmailInvoice::dispatch($email_builder, $invitation, $invitation->company);
|
||||
|
||||
|
@ -364,8 +364,18 @@ class PaymentTest extends TestCase
|
||||
$this->invoice = null;
|
||||
|
||||
$client = ClientFactory::create($this->company->id, $this->user->id);
|
||||
$client->setRelation('company', $this->company);
|
||||
$client->save();
|
||||
|
||||
$client_contact = factory(\App\Models\ClientContact::class, 1)->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1
|
||||
]);
|
||||
|
||||
$client->setRelation('contacts', $client_contact);
|
||||
|
||||
$this->invoice = InvoiceFactory::create($this->company->id,$this->user->id);//stub the company and user_id
|
||||
$this->invoice->client_id = $client->id;
|
||||
|
||||
@ -379,6 +389,8 @@ class PaymentTest extends TestCase
|
||||
$this->invoice_calc->build();
|
||||
|
||||
$this->invoice = $this->invoice_calc->getInvoice();
|
||||
$this->invoice->company->setRelation('company', $this->company);
|
||||
$this->invoice->company->setRelation('client', $client);
|
||||
$this->invoice->save();
|
||||
$this->invoice->service()->markSent()->save();
|
||||
$this->invoice->is_deleted = false;
|
||||
|
@ -139,14 +139,14 @@ trait MockAccountData
|
||||
'client_id' => $this->client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1,
|
||||
'send' => true,
|
||||
'send_email' => true,
|
||||
]);
|
||||
|
||||
factory(\App\Models\ClientContact::class,1)->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $this->client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'send' => true
|
||||
'send_email' => true
|
||||
]);
|
||||
|
||||
|
||||
@ -176,6 +176,9 @@ trait MockAccountData
|
||||
|
||||
$this->invoice = $this->invoice_calc->getInvoice();
|
||||
|
||||
$this->invoice->setRelation('client', $this->client);
|
||||
$this->invoice->setRelation('company', $this->company);
|
||||
|
||||
$this->invoice->save();
|
||||
|
||||
$this->invoice->service()->markSent();
|
||||
@ -200,13 +203,13 @@ trait MockAccountData
|
||||
->whereInvoiceId($this->invoice->id)
|
||||
->first();
|
||||
|
||||
if(!$invitation && $contact->send) {
|
||||
if(!$invitation && $contact->send_email) {
|
||||
$ii = InvoiceInvitationFactory::create($this->invoice->company_id, $this->invoice->user_id);
|
||||
$ii->invoice_id = $this->invoice->id;
|
||||
$ii->client_contact_id = $contact->id;
|
||||
$ii->save();
|
||||
}
|
||||
else if($invitation && !$contact->send) {
|
||||
else if($invitation && !$contact->send_email) {
|
||||
$invitation->delete();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user