Merge pull request #3972 from beganovich/v2-0708-pdfmaker-integration

(wip) End-to-end PDF Maker integration
This commit is contained in:
David Bomba 2020-08-14 06:53:00 +10:00 committed by GitHub
commit 5bfcdc80b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 848 additions and 351 deletions

View File

@ -39,16 +39,17 @@ class DesignUpdate extends Command
public function handle()
{
foreach (Design::whereIsCustom(false)->get() as $design) {
$class = 'App\Designs\\'.$design->name;
$class = 'App\Services\PdfMaker\Designs\\'.$design->name;
$invoice_design = new $class();
$invoice_design->document();
$design_object = new \stdClass;
$design_object->includes = $invoice_design->includes() ?: '';
$design_object->header = $invoice_design->header() ?: '';
$design_object->body = $invoice_design->body() ?: '';
$design_object->product = $invoice_design->product() ?: '';
$design_object->task = $invoice_design->task() ?: '';
$design_object->footer = $invoice_design->footer() ?: '';
$design_object->includes = $invoice_design->getSectionHTML('includes');
$design_object->header = $invoice_design->getSectionHTML('head', false);
$design_object->body = $invoice_design->getSectionHTML('body', false);
$design_object->product = $invoice_design->getSectionHTML('product-table');
$design_object->task = $invoice_design->getSectionHTML('task-table');
$design_object->footer = $invoice_design->getSectionHTML('footer', false);
$design->design = $design_object;
$design->save();

View File

@ -553,20 +553,20 @@ class CompanySettings extends BaseSettings
'$company.country',
],
'invoice_details' => [
'$invoice.invoice_number',
'$invoice.number',
'$invoice.po_number',
'$invoice.invoice_date',
'$invoice.date',
'$invoice.due_date',
'$invoice.balance_due',
'$invoice.invoice_total',
'$invoice.total',
],
'quote_details' => [
'$quote.quote_number',
'$quote.number',
'$quote.po_number',
'$quote.quote_date',
'$quote.date',
'$quote.valid_until',
'$quote.balance_due',
'$quote.quote_total',
'$quote.total',
],
'credit_details' => [
'$credit.credit_number',

View File

@ -1,4 +1,5 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
@ -19,6 +20,7 @@ use App\Models\ClientContact;
use App\Models\Company;
use App\Models\Design;
use App\Models\Invoice;
use App\Services\PdfMaker\PdfMaker as PdfMakerService;
use App\Utils\HtmlEngine;
use App\Utils\PhantomJS\Phantom;
use App\Utils\Traits\MakesHash;
@ -68,8 +70,9 @@ class CreateInvoicePdf implements ShouldQueue
public function handle()
{
if(config('ninja.phantomjs_key'))
if (config('ninja.phantomjs_key')) {
return (new Phantom)->generate($this->invitation);
}
App::setLocale($this->contact->preferredLocale());
@ -81,14 +84,33 @@ class CreateInvoicePdf implements ShouldQueue
$design = Design::find($invoice_design_id);
$designer = new Designer($this->invoice, $design, $this->invoice->client->getSetting('pdf_variables'), 'invoice');
$html = new HtmlEngine(null, $this->invitation, 'invoice');
$html = (new HtmlEngine($designer, $this->invitation, 'invoice'))->build();
$design_namespace = 'App\Services\PdfMaker\Designs\\' . $design->name;
$design_class = new $design_namespace();
$pdf_variables = json_decode(json_encode($this->invoice->company->settings->pdf_variables), 1);
$state = [
'template' => $design_class->elements([
'client' => $this->invoice->client,
'entity' => $this->invoice,
'product-table-columns' => $pdf_variables['product_columns'],
]),
'variables' => $html->generateLabelsAndValues(),
];
$maker = new PdfMakerService($state);
$maker
->design($design_namespace)
->build();
//todo - move this to the client creation stage so we don't keep hitting this unnecessarily
Storage::makeDirectory($path, 0775);
$pdf = $this->makePdf(null, null, $html);
$pdf = $this->makePdf(null, null, $maker->getCompiledHTML());
$instance = Storage::disk($this->disk)->put($file_path, $pdf);

View File

@ -19,6 +19,7 @@ use App\Models\ClientContact;
use App\Models\Company;
use App\Models\Design;
use App\Models\Invoice;
use App\Services\PdfMaker\PdfMaker as PdfMakerService;
use App\Utils\HtmlEngine;
use App\Utils\PhantomJS\Phantom;
use App\Utils\Traits\MakesHash;
@ -81,14 +82,33 @@ class CreateQuotePdf implements ShouldQueue
$design = Design::find($quote_design_id);
$designer = new Designer($this->quote, $design, $this->quote->client->getSetting('pdf_variables'), 'quote');
$html = new HtmlEngine(null, $this->invitation, 'quote');
$design_namespace = 'App\Services\PdfMaker\Designs\\' . $design->name;
$design_class = new $design_namespace();
$pdf_variables = json_decode(json_encode($this->quote->company->settings->pdf_variables), 1);
$state = [
'template' => $design_class->elements([
'client' => $this->quote->client,
'entity' => $this->quote,
'product-table-columns' => $pdf_variables['product_columns'],
]),
'variables' => $html->generateLabelsAndValues(),
];
$maker = new PdfMakerService($state);
$maker
->design($design_namespace)
->build();
//todo - move this to the client creation stage so we don't keep hitting this unnecessarily
Storage::makeDirectory($path, 0775);
$html = (new HtmlEngine($designer, $this->invitation, 'quote'))->build();
$pdf = $this->makePdf(null, null, $html);
$pdf = $this->makePdf(null, null, $maker->getCompiledHTML());
$file_path = $path . $this->quote->number . '.pdf';

View File

@ -13,12 +13,12 @@
namespace App\Services\PdfMaker\Designs;
use App\Services\PdfMaker\Designs\Utilities\BaseDesign;
use App\Services\PdfMaker\Designs\Utilities\BuildTableHeader;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
use App\Utils\Traits\MakesInvoiceValues;
class Bold extends BaseDesign
{
use MakesInvoiceValues, BuildTableHeader;
use MakesInvoiceValues, DesignHelpers;
/** Global list of table elements, @var array */
public $elements;
@ -32,19 +32,20 @@ class Bold extends BaseDesign
/** Global state of the design, @var array */
public $context;
/** Type of entity => invoice||quote */
/** Type of entity => product||task */
public $type;
public function html()
{
return file_get_contents(
base_path('resources/views/pdf-designs//bold.html')
base_path('resources/views/pdf-designs/bold.html')
);
}
public function elements(array $context, string $type = 'invoice'): array
public function elements(array $context, string $type = 'product'): array
{
$this->context = $context;
$this->type = $type;
$this->setup();
@ -70,6 +71,12 @@ class Bold extends BaseDesign
'id' => 'product-table',
'elements' => $this->productTable(),
],
'footer-elements' => [
'id' => 'footer',
'elements' => [
$this->sharedFooterElements(),
],
],
];
}
@ -116,6 +123,10 @@ class Bold extends BaseDesign
{
$variables = $this->entity->company->settings->pdf_variables->invoice_details;
if ($this->entity instanceof \App\Models\Quote) {
$variables = $this->entity->company->settings->pdf_variables->quote_details;
}
$elements = [];
foreach ($variables as $variable) {
@ -133,21 +144,7 @@ class Bold extends BaseDesign
return [
['element' => 'thead', 'content' => '', 'properties' => ['class' => 'text-left rounded-t-lg'], 'elements' => $this->buildTableHeader()],
['element' => 'tbody', 'content' => '', 'elements' => $this->buildTableBody()],
['element' => 'tfoot', 'content' => '', 'elements' => [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '4']],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right text-xl text-teal-600 font-semibold', 'colspan' => '6']],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
]],
['element' => 'tfoot', 'content' => '', 'elements' => $this->tableFooter()],
];
}
@ -157,7 +154,7 @@ class Bold extends BaseDesign
$elements = [];
foreach ($this->context['product-table-columns'] as $column) {
foreach ($this->context["{$this->type}-table-columns"] as $column) {
$elements[] = ['element' => 'th', 'content' => $column . '_label', 'properties' => ['class' => 'text-xl px-4 py-2']];
}
@ -186,4 +183,31 @@ class Bold extends BaseDesign
return $elements;
}
public function tableFooter()
{
return [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(3)]],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotalDiscount())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->partial)], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$partial_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$partial_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotal())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$total_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$total', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->balance), 'class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right text-xl text-teal-600 font-semibold', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
];
}
}

View File

@ -13,12 +13,12 @@
namespace App\Services\PdfMaker\Designs;
use App\Services\PdfMaker\Designs\Utilities\BaseDesign;
use App\Services\PdfMaker\Designs\Utilities\BuildTableHeader;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
use App\Utils\Traits\MakesInvoiceValues;
class Business extends BaseDesign
{
use MakesInvoiceValues, BuildTableHeader;
use MakesInvoiceValues, DesignHelpers;
/** Global list of table elements, @var array */
public $elements;
@ -32,19 +32,20 @@ class Business extends BaseDesign
/** Global state of the design, @var array */
public $context;
/** Type of entity => invoice||quote */
/** Type of entity => product||task */
public $type;
public function html()
{
return file_get_contents(
base_path('resources/views/pdf-designs//business.html')
base_path('resources/views/pdf-designs/business.html')
);
}
public function elements(array $context, string $type = 'invoice'): array
public function elements(array $context, string $type = 'product'): array
{
$this->context = $context;
$this->type = $type;
$this->setup();
@ -70,6 +71,12 @@ class Business extends BaseDesign
'id' => 'product-table',
'elements' => $this->productTable(),
],
'footer-elements' => [
'id' => 'footer',
'elements' => [
$this->sharedFooterElements(),
],
],
];
}
@ -116,6 +123,10 @@ class Business extends BaseDesign
{
$variables = $this->entity->company->settings->pdf_variables->invoice_details;
if ($this->entity instanceof \App\Models\Quote) {
$variables = $this->entity->company->settings->pdf_variables->quote_details;
}
$elements = [];
foreach ($variables as $variable) {
@ -133,21 +144,7 @@ class Business extends BaseDesign
return [
['element' => 'thead', 'content' => '', 'properties' => ['class' => 'text-left rounded-t-lg'], 'elements' => $this->buildTableHeader()],
['element' => 'tbody', 'content' => '', 'elements' => $this->buildTableBody()],
['element' => 'tfoot', 'content' => '', 'elements' => [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '4']],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right text-xl text-blue-900 font-semibold', 'colspan' => '6']],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right text-blue-900 font-semibold']],
]],
]],
['element' => 'tfoot', 'content' => '', 'elements' => $this->tableFooter()],
];
}
@ -186,4 +183,31 @@ class Business extends BaseDesign
return $elements;
}
public function tableFooter()
{
return [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(3)]],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotalDiscount())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->partial)], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$partial_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$partial_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotal())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$total_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$total', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->balance), 'class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right text-xl text-blue-900 font-semibold', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right text-blue-900 font-semibold']],
]],
];
}
}

View File

@ -13,12 +13,12 @@
namespace App\Services\PdfMaker\Designs;
use App\Services\PdfMaker\Designs\Utilities\BaseDesign;
use App\Services\PdfMaker\Designs\Utilities\BuildTableHeader;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
use App\Utils\Traits\MakesInvoiceValues;
class Clean extends BaseDesign
{
use MakesInvoiceValues, BuildTableHeader;
use MakesInvoiceValues, DesignHelpers;
/** Global list of table elements, @var array */
public $elements;
@ -32,7 +32,7 @@ class Clean extends BaseDesign
/** Global state of the design, @var array */
public $context;
/** Type of entity => invoice||quote */
/** Type of entity => product||task */
public $type;
public function html()
@ -42,9 +42,10 @@ class Clean extends BaseDesign
);
}
public function elements(array $context, string $type = 'invoice'): array
public function elements(array $context, string $type = 'product'): array
{
$this->context = $context;
$this->type = $type;
$this->setup();
@ -69,7 +70,13 @@ class Clean extends BaseDesign
'product-table' => [
'id' => 'product-table',
'elements' => $this->productTable(),
]
],
'footer-elements' => [
'id' => 'footer',
'elements' => [
$this->sharedFooterElements(),
],
],
];
}
@ -103,6 +110,10 @@ class Clean extends BaseDesign
{
$variables = $this->entity->company->settings->pdf_variables->invoice_details;
if ($this->entity instanceof \App\Models\Quote) {
$variables = $this->entity->company->settings->pdf_variables->quote_details;
}
$elements = [];
foreach ($variables as $variable) {
@ -133,21 +144,7 @@ class Clean extends BaseDesign
return [
['element' => 'thead', 'content' => '', 'properties' => ['class' => 'text-left rounded-t-lg'], 'elements' => $this->buildTableHeader()],
['element' => 'tbody', 'content' => '', 'elements' => $this->buildTableBody()],
['element' => 'tfoot', 'content' => '', 'elements' => [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '4']],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right font-semibold', 'colspan' => '6']],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
]],
['element' => 'tfoot', 'content' => '', 'elements' => $this->tableFooter()],
];
}
@ -186,4 +183,31 @@ class Clean extends BaseDesign
return $elements;
}
public function tableFooter()
{
return [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(3)]],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotalDiscount())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->partial), 'class' => 'mt-8 px-4 py-2'], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$partial_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$partial_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotal())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$total_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$total', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->balance), 'class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right font-semibold', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
];
}
}

View File

@ -13,12 +13,12 @@
namespace App\Services\PdfMaker\Designs;
use App\Services\PdfMaker\Designs\Utilities\BaseDesign;
use App\Services\PdfMaker\Designs\Utilities\BuildTableHeader;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
use App\Utils\Traits\MakesInvoiceValues;
class Creative extends BaseDesign
{
use MakesInvoiceValues, BuildTableHeader;
use MakesInvoiceValues, DesignHelpers;
/** Global list of table elements, @var array */
public $elements;
@ -32,19 +32,20 @@ class Creative extends BaseDesign
/** Global state of the design, @var array */
public $context;
/** Type of entity => invoice||quote */
/** Type of entity => product||task */
public $type;
public function html()
{
return file_get_contents(
base_path('resources/views/pdf-designs//creative.html')
base_path('resources/views/pdf-designs/creative.html')
);
}
public function elements(array $context, string $type = 'invoice'): array
public function elements(array $context, string $type = 'product'): array
{
$this->context = $context;
$this->type = $type;
$this->setup();
@ -70,6 +71,12 @@ class Creative extends BaseDesign
'id' => 'product-table',
'elements' => $this->productTable(),
],
'footer-elements' => [
'id' => 'footer',
'elements' => [
$this->sharedFooterElements(),
],
],
];
}
@ -116,6 +123,10 @@ class Creative extends BaseDesign
{
$variables = $this->entity->company->settings->pdf_variables->invoice_details;
if ($this->entity instanceof \App\Models\Quote) {
$variables = $this->entity->company->settings->pdf_variables->quote_details;
}
$elements = [];
foreach ($variables as $variable) {
@ -133,21 +144,7 @@ class Creative extends BaseDesign
return [
['element' => 'thead', 'content' => '', 'properties' => ['class' => 'text-left'], 'elements' => $this->buildTableHeader()],
['element' => 'tbody', 'content' => '', 'elements' => $this->buildTableBody()],
['element' => 'tfoot', 'content' => '', 'elements' => [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '4']],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2 border-t-4 border-pink-700'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right font-semibold text-pink-700']],
]],
]],
['element' => 'tfoot', 'content' => '', 'elements' => $this->tableFooter()],
];
}
@ -186,4 +183,31 @@ class Creative extends BaseDesign
return $elements;
}
public function tableFooter()
{
return [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(3)]],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotalDiscount()), 'class' => 'mt-8 px-4 py-2'], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->partial), 'class' => 'mt-8 px-4 py-2'], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$partial_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$partial_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotal())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$total_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$total', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->balance), 'class' => 'mt-8 px-4 py-2 border-t-4 border-pink-700'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right font-semibold text-pink-700']],
]],
];
}
}

View File

@ -13,12 +13,12 @@
namespace App\Services\PdfMaker\Designs;
use App\Services\PdfMaker\Designs\Utilities\BaseDesign;
use App\Services\PdfMaker\Designs\Utilities\BuildTableHeader;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
use App\Utils\Traits\MakesInvoiceValues;
class Elegant extends BaseDesign
{
use MakesInvoiceValues, BuildTableHeader;
use MakesInvoiceValues, DesignHelpers;
/** Global list of table elements, @var array */
public $elements;
@ -32,7 +32,7 @@ class Elegant extends BaseDesign
/** Global state of the design, @var array */
public $context;
/** Type of entity => invoice||quote */
/** Type of entity => product||task */
public $type;
public function html()
@ -42,9 +42,10 @@ class Elegant extends BaseDesign
);
}
public function elements(array $context, string $type = 'invoice'): array
public function elements(array $context, string $type = 'product'): array
{
$this->context = $context;
$this->type = $type;
$this->setup();
@ -70,6 +71,12 @@ class Elegant extends BaseDesign
'id' => 'product-table',
'elements' => $this->productTable(),
],
'footer-elements' => [
'id' => 'footer',
'elements' => [
$this->sharedFooterElements(),
],
],
];
}
@ -77,6 +84,10 @@ class Elegant extends BaseDesign
{
$variables = $this->entity->company->settings->pdf_variables->invoice_details;
if ($this->entity instanceof \App\Models\Quote) {
$variables = $this->entity->company->settings->pdf_variables->quote_details;
}
$elements = [];
foreach ($variables as $variable) {
@ -134,21 +145,7 @@ class Elegant extends BaseDesign
return [
['element' => 'thead', 'content' => '', 'properties' => ['class' => 'text-left border-dashed border-b border-black'], 'elements' => $this->buildTableHeader()],
['element' => 'tbody', 'content' => '', 'elements' => $this->buildTableBody()],
['element' => 'tfoot', 'content' => '', 'elements' => [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '4']],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'px-4 text-right text-xl text-green-600 font-semibold', 'colspan' => '6']],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right text-green-600']],
]],
]],
['element' => 'tfoot', 'content' => '', 'elements' => $this->tableFooter()],
];
}
@ -176,7 +173,7 @@ class Elegant extends BaseDesign
}
foreach ($items as $row) {
$element = ['element' => 'tr', 'properties' => ['class' => 'border-dashed border-b border-black'] ,'content' => '', 'elements' => []];
$element = ['element' => 'tr', 'properties' => ['class' => 'border-dashed border-b border-black'], 'content' => '', 'elements' => []];
foreach ($this->context['product-table-columns'] as $key => $cell) {
$element['elements'][] = ['element' => 'td', 'content' => $row[$cell], 'properties' => ['class' => 'px-4 py-3']];
@ -187,4 +184,31 @@ class Elegant extends BaseDesign
return $elements;
}
public function tableFooter()
{
return [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(3)]],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotalDiscount())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->partial), 'class' => 'mt-8 px-4 py-2'], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$partial_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$partial_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotal())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$total_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$total', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->balance), 'class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'px-4 text-right text-xl text-green-600 font-semibold', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right text-green-600']],
]],
];
}
}

View File

@ -13,12 +13,12 @@
namespace App\Services\PdfMaker\Designs;
use App\Services\PdfMaker\Designs\Utilities\BaseDesign;
use App\Services\PdfMaker\Designs\Utilities\BuildTableHeader;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
use App\Utils\Traits\MakesInvoiceValues;
class Hipster extends BaseDesign
{
use MakesInvoiceValues, BuildTableHeader;
use MakesInvoiceValues, DesignHelpers;
/** Global list of table elements, @var array */
public $elements;
@ -32,7 +32,7 @@ class Hipster extends BaseDesign
/** Global state of the design, @var array */
public $context;
/** Type of entity => invoice||quote */
/** Type of entity => product||task */
public $type;
public function html()
@ -42,9 +42,10 @@ class Hipster extends BaseDesign
);
}
public function elements(array $context, string $type = 'invoice'): array
public function elements(array $context, string $type = 'product'): array
{
$this->context = $context;
$this->type = $type;
$this->setup();
@ -70,6 +71,12 @@ class Hipster extends BaseDesign
'id' => 'product-table',
'elements' => $this->productTable(),
],
'footer-elements' => [
'id' => 'footer',
'elements' => [
$this->sharedFooterElements(),
],
],
];
}
@ -116,6 +123,10 @@ class Hipster extends BaseDesign
{
$variables = $this->entity->company->settings->pdf_variables->invoice_details;
if ($this->entity instanceof \App\Models\Quote) {
$variables = $this->entity->company->settings->pdf_variables->quote_details;
}
$elements = [];
foreach ($variables as $variable) {
@ -133,21 +144,7 @@ class Hipster extends BaseDesign
return [
['element' => 'thead', 'content' => '', 'properties' => ['class' => 'text-left'], 'elements' => $this->buildTableHeader()],
['element' => 'tbody', 'content' => '', 'elements' => $this->buildTableBody()],
['element' => 'tfoot', 'content' => '', 'elements' => [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'px-4 py-4 text-rightt', 'colspan' => '4']],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['class' => 'border-l-2 border-black px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'border-l-2 border-black px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'border-l-2 border-black px-4 py-2 text-right']],
]],
]],
['element' => 'tfoot', 'content' => '', 'elements' => $this->tableFooter()],
];
}
@ -186,4 +183,31 @@ class Hipster extends BaseDesign
return $elements;
}
public function tableFooter()
{
return [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'px-4 py-4 text-rightt', 'colspan' => $this->calculateColspan(3)]],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'border-l-2 border-black px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotalDiscount())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'border-l-2 border-black px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->partial), 'class' => 'mt-8 px-4 py-2'], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$partial_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$partial_due', 'properties' => ['class' => 'border-l-2 border-black px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotal())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$total_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$total', 'properties' => ['class' => 'border-l-2 border-black px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->balance), 'class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'border-l-2 border-black px-4 py-2 text-right']],
]],
];
}
}

View File

@ -13,12 +13,12 @@
namespace App\Services\PdfMaker\Designs;
use App\Services\PdfMaker\Designs\Utilities\BaseDesign;
use App\Services\PdfMaker\Designs\Utilities\BuildTableHeader;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
use App\Utils\Traits\MakesInvoiceValues;
class Modern extends BaseDesign
{
use MakesInvoiceValues, BuildTableHeader;
use MakesInvoiceValues, DesignHelpers;
/** Global list of table elements, @var array */
public $elements;
@ -32,7 +32,7 @@ class Modern extends BaseDesign
/** Global state of the design, @var array */
public $context;
/** Type of entity => invoice||quote */
/** Type of entity => product||task */
public $type;
public function html()
@ -42,9 +42,10 @@ class Modern extends BaseDesign
);
}
public function elements(array $context, string $type = 'invoice'): array
public function elements(array $context, string $type = 'product'): array
{
$this->context = $context;
$this->type = $type;
$this->setup();
@ -70,6 +71,12 @@ class Modern extends BaseDesign
'id' => 'company-address',
'elements' => $this->companyAddress(),
],
'footer-elements' => [
'id' => 'footer',
'elements' => [
$this->sharedFooterElements(),
],
],
];
}
@ -77,6 +84,10 @@ class Modern extends BaseDesign
{
$variables = $this->entity->company->settings->pdf_variables->invoice_details;
if ($this->entity instanceof \App\Models\Quote) {
$variables = $this->entity->company->settings->pdf_variables->quote_details;
}
$elements = [];
foreach ($variables as $variable) {
@ -107,21 +118,7 @@ class Modern extends BaseDesign
return [
['element' => 'thead', 'content' => '', 'properties' => ['class' => 'text-left text-white bg-gray-900'], 'elements' => $this->buildTableHeader()],
['element' => 'tbody', 'content' => '', 'elements' => $this->buildTableBody()],
['element' => 'tfoot', 'content' => '', 'elements' => [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '4']],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2 bg-gray-900 text-white text-xl'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right font-semibold', 'colspan' => '6']],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
]],
['element' => 'tfoot', 'content' => '', 'elements' => $this->tableFooter()],
];
}
@ -161,6 +158,33 @@ class Modern extends BaseDesign
return $elements;
}
public function tableFooter()
{
return [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(3)]],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotalDiscount())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->partial)], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$partial_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$partial_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotal())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$total_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$total', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->balance), 'class' => 'mt-8 px-4 py-2 bg-gray-900 text-white text-xl'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right font-semibold', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
];
}
public function companyDetails()
{
$variables = $this->entity->company->settings->pdf_variables->company_details;

View File

@ -0,0 +1,45 @@
<?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\PdfMaker\Designs;
use App\Services\PdfMaker\Designs\Utilities\BaseDesign;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
use App\Utils\Traits\MakesInvoiceValues;
/** @deprecated */
class Photo extends BaseDesign
{
use MakesInvoiceValues, DesignHelpers;
/** Global list of table elements, @var array */
public $elements;
/** @var App\Models\Client */
public $client;
/** @var App\Models\Invoice || @var App\Models\Quote */
public $entity;
/** Global state of the design, @var array */
public $context;
/** Type of entity => product||task */
public $type;
public function html()
{
return file_get_contents(
base_path('resources/views/pdf-designs/bold.html')
);
}
}

View File

@ -13,12 +13,12 @@
namespace App\Services\PdfMaker\Designs;
use App\Services\PdfMaker\Designs\Utilities\BaseDesign;
use App\Services\PdfMaker\Designs\Utilities\BuildTableHeader;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
use App\Utils\Traits\MakesInvoiceValues;
class Plain extends BaseDesign
{
use MakesInvoiceValues, BuildTableHeader;
use MakesInvoiceValues, DesignHelpers;
/** Global list of table elements, @var array */
public $elements;
@ -32,7 +32,7 @@ class Plain extends BaseDesign
/** Global state of the design, @var array */
public $context;
/** Type of entity => invoice||quote */
/** Type of entity => product||task */
public $type;
public function html(): ?string
@ -42,9 +42,10 @@ class Plain extends BaseDesign
);
}
public function elements(array $context, string $type = 'invoice'): array
public function elements(array $context, string $type = 'product'): array
{
$this->context = $context;
$this->type = $type;
$this->setup();
@ -66,6 +67,12 @@ class Plain extends BaseDesign
'id' => 'product-table',
'elements' => $this->productTable(),
],
'footer-elements' => [
'id' => 'footer',
'elements' => [
$this->sharedFooterElements(),
],
],
];
}
@ -86,6 +93,10 @@ class Plain extends BaseDesign
{
$variables = $this->entity->company->settings->pdf_variables->invoice_details;
if ($this->entity instanceof \App\Models\Quote) {
$variables = $this->entity->company->settings->pdf_variables->quote_details;
}
$elements = [];
foreach ($variables as $variable) {
@ -116,20 +127,33 @@ class Plain extends BaseDesign
return [
['element' => 'thead', 'content' => '', 'properties' => ['class' => 'text-left bg-gray-200'], 'elements' => $this->buildTableHeader()],
['element' => 'tbody', 'content' => '', 'elements' => $this->buildTableBody()],
['element' => 'tfoot', 'content' => '', 'elements' => [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 py-4', 'colspan' => '4']],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2 bg-gray-300'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tfoot', 'content' => '', 'elements' => $this->tableFooter()],
];
}
public function tableFooter()
{
return [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 py-4', 'colspan' => $this->calculateColspan(3)]],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotalDiscount())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->partial)], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$partial_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$partial_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotal())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$total_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$total', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->balance), 'class' => 'mt-8 px-4 py-2 bg-gray-300'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
];
}

View File

@ -13,12 +13,12 @@
namespace App\Services\PdfMaker\Designs;
use App\Services\PdfMaker\Designs\Utilities\BaseDesign;
use App\Services\PdfMaker\Designs\Utilities\BuildTableHeader;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
use App\Utils\Traits\MakesInvoiceValues;
class Playful extends BaseDesign
{
use MakesInvoiceValues, BuildTableHeader;
use MakesInvoiceValues, DesignHelpers;
/** Global list of table elements, @var array */
public $elements;
@ -32,7 +32,7 @@ class Playful extends BaseDesign
/** Global state of the design, @var array */
public $context;
/** Type of entity => invoice||quote */
/** Type of entity => product||task */
public $type;
public function html()
@ -42,9 +42,10 @@ class Playful extends BaseDesign
);
}
public function elements(array $context, string $type = 'invoice'): array
public function elements(array $context, string $type = 'product'): array
{
$this->context = $context;
$this->type = $type;
$this->setup();
@ -70,6 +71,12 @@ class Playful extends BaseDesign
'id' => 'product-table',
'elements' => $this->productTable(),
],
'footer-elements' => [
'id' => 'footer',
'elements' => [
$this->sharedFooterElements(),
],
],
];
}
@ -77,6 +84,10 @@ class Playful extends BaseDesign
{
$variables = $this->entity->company->settings->pdf_variables->invoice_details;
if ($this->entity instanceof \App\Models\Quote) {
$variables = $this->entity->company->settings->pdf_variables->quote_details;
}
$elements = [];
foreach ($variables as $variable) {
@ -133,21 +144,7 @@ class Playful extends BaseDesign
return [
['element' => 'thead', 'content' => '', 'properties' => ['class' => 'text-left bg-teal-600'], 'elements' => $this->buildTableHeader()],
['element' => 'tbody', 'content' => '', 'elements' => $this->buildTableBody()],
['element' => 'tfoot', 'content' => '', 'elements' => [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '4']],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '6']],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right font-semibold text-teal-600', 'colspan' => '6']],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
]],
['element' => 'tfoot', 'content' => '', 'elements' => $this->tableFooter()],
];
}
@ -186,4 +183,31 @@ class Playful extends BaseDesign
return $elements;
}
public function tableFooter()
{
return [
['element' => 'tr', 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(3)]],
['element' => 'td', 'content' => '$subtotal_label', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-4 text-right', 'colspan' => '2']],
['element' => 'td', 'content' => '$subtotal', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getSubTotal()), 'class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotalDiscount())], 'content' => '', 'elements' => [
['element' => 'td', 'content' => '$discount_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$discount', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->partial), 'class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$partial_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$partial_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->calc()->getTotal())], 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$total_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$total', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['hidden' => $this->toggleHiddenProperty($this->entity->balance), 'class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => '$balance_due_label', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right font-semibold text-teal-600', 'colspan' => $this->calculateColspan(1)]],
['element' => 'td', 'content' => '$balance_due', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
];
}
}

View File

@ -14,14 +14,5 @@ namespace App\Services\PdfMaker\Designs\Utilities;
class BaseDesign
{
public function setup(): void
{
if (isset($this->context['client'])) {
$this->client = $this->context['client'];
}
if (isset($this->context['entity'])) {
$this->entity = $this->context['entity'];
}
}
// ..
}

View File

@ -1,55 +0,0 @@
<?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\PdfMaker\Designs\Utilities;
trait BuildTableHeader
{
/**
* This method will help us decide either we show
* one "tax rate" column in the table or 3 custom tax rates.
*
* Logic below will help us calculate that & inject the result in the
* global state of the $context (design state).
*
* @return void
*/
public function processTaxColumns(): void
{
if (in_array('$product.tax', $this->context['product-table-columns'])) {
$line_items = collect($this->entity->line_items);
$tax1 = $line_items->where('tax_name1', '<>', '')->where('type_id', 1)->count();
$tax2 = $line_items->where('tax_name2', '<>', '')->where('type_id', 1)->count();
$tax3 = $line_items->where('tax_name3', '<>', '')->where('type_id', 1)->count();
$taxes = [];
if ($tax1 > 0) {
array_push($taxes, '$product.tax_rate1');
}
if ($tax2 > 0) {
array_push($taxes, '$product.tax_rate2');
}
if ($tax3 > 0) {
array_push($taxes, '$product.tax_rate3');
}
$key = array_search('$product.tax', $this->context['product-table-columns'], true);
if ($key) {
array_splice($this->context['product-table-columns'], $key, 1, $taxes);
}
}
}
}

View File

@ -0,0 +1,167 @@
<?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\PdfMaker\Designs\Utilities;
use DOMDocument;
use DOMXPath;
trait DesignHelpers
{
public $document;
public $xpath;
public function setup(): self
{
if (isset($this->context['client'])) {
$this->client = $this->context['client'];
}
if (isset($this->context['entity'])) {
$this->entity = $this->context['entity'];
}
$this->document();
return $this;
}
/**
* Initialize local dom document instance. Used for getting raw HTML out of template.
*
* @return $this
*/
public function document(): self
{
$document = new DOMDocument();
$document->validateOnParse = true;
@$document->loadHTML($this->html());
$this->document = $document;
$this->xpath = new DOMXPath($document);
return $this;
}
/**
* Get specific section HTML.
*
* @param string $section
* @param bool $id
* @return null|string
*/
public function getSectionHTML(string $section, $id = true): ?string
{
if ($id) {
$element = $this->document->getElementById($section);
} else {
$elements = $this->document->getElementsByTagName($section);
$element = $elements[0];
}
$document = new DOMDocument();
$document->preserveWhiteSpace = false;
$document->formatOutput = true;
if ($element) {
$document->appendChild(
$document->importNode($element, true)
);
return $document->saveHTML();
}
return null;
}
/**
* This method will help us decide either we show
* one "tax rate" column in the table or 3 custom tax rates.
*
* Logic below will help us calculate that & inject the result in the
* global state of the $context (design state).
*
* @return void
*/
public function processTaxColumns(): void
{
if (in_array('$product.tax', $this->context['product-table-columns'])) {
$line_items = collect($this->entity->line_items);
$tax1 = $line_items->where('tax_name1', '<>', '')->where('type_id', 1)->count();
$tax2 = $line_items->where('tax_name2', '<>', '')->where('type_id', 1)->count();
$tax3 = $line_items->where('tax_name3', '<>', '')->where('type_id', 1)->count();
$taxes = [];
if ($tax1 > 0) {
array_push($taxes, '$product.tax_rate1');
}
if ($tax2 > 0) {
array_push($taxes, '$product.tax_rate2');
}
if ($tax3 > 0) {
array_push($taxes, '$product.tax_rate3');
}
$key = array_search('$product.tax', $this->context['product-table-columns'], true);
if ($key) {
array_splice($this->context['product-table-columns'], $key, 1, $taxes);
}
}
}
/**
* Calculates the remaining colspans.
*
* @param int $taken
* @return int
*/
public function calculateColspan(int $taken): int
{
$total = (int) count($this->context['product-table-columns']);
return (int)$total - $taken;
}
/**
* Return "true" or "false" based on null or empty check.
* We need to return false as string because of HTML parsing.
*
* @param mixed $property
* @return string
*/
public function toggleHiddenProperty($property): string
{
if (is_null($property)) {
return 'false';
}
if (empty($property)) {
return 'false';
}
return 'true';
}
public function sharedFooterElements()
{
return ['element' => 'div', 'properties' => ['class' => 'flex items-center justify-between mt-10'], 'content' => '', 'elements' => [
['element' => 'img', 'content' => '', 'properties' => ['src' => '$contact.signature', 'class' => 'h-32']],
['element' => 'img', 'content' => '', 'properties' => ['src' => '$app_url/images/created-by-invoiceninja-new.png', 'class' => 'h-24', 'hidden' => $this->entity->user->account->isPaid() ? 'true' : 'false']],
]];
}
}

View File

@ -67,7 +67,7 @@ trait PdfMakerUtilities
{
$processed = [];
foreach($children as $child) {
foreach ($children as $child) {
if (!isset($child['order'])) {
$child['order'] = 0;
}
@ -84,6 +84,14 @@ trait PdfMakerUtilities
public function updateElementProperty($element, string $attribute, string $value)
{
// We have exception for "hidden" property.
// hidden="true" or hidden="false" will both hide the element,
// that's why we have to create an exception here for this rule.
if ($attribute == 'hidden' && ($value == false || $value == "false")) {
return $element;
}
$element->setAttribute($attribute, $value);
if ($element->getAttribute($attribute) === $value) {
@ -117,10 +125,10 @@ trait PdfMakerUtilities
public function updateVariables(array $variables)
{
$html = strtr($this->getCompiledHTML(), $variables['labels']);
$html = strtr($html, $variables['values']);
$this->document->loadHTML($html);
@$this->document->loadHTML($html);
$this->document->saveHTML();
}

View File

@ -96,6 +96,7 @@ class HtmlEngine
$data = [];
$data['$global-margin'] = ['value' => 'm-12', 'label' => ''];
$data['$global-padding'] = ['value' => 'p-12', 'label' => ''];
$data['$tax'] = ['value' => '', 'label' => ctrans('texts.tax')];
$data['$app_url'] = ['value' => $this->generateAppUrl(), 'label' => ''];
$data['$from'] = ['value' => '', 'label' => ctrans('texts.from')];
@ -107,8 +108,8 @@ class HtmlEngine
$data['$date'] = ['value' => $this->entity->date ?: '&nbsp;', 'label' => ctrans('texts.date')];
//$data['$invoice_date'] = ['value' => $this->date ?: '&nbsp;', 'label' => ctrans('texts.invoice_date')];
$data['$invoice.date'] = &$data['$date'];
$data['$invoice.due_date'] = ['value' => $this->entity->due_date ?: '&nbsp;', 'label' => ctrans('texts.due_date')];
$data['$due_date'] = &$data['$invoice.due_date'];
$data['$due_date'] = ['value' => $this->entity->due_date ?: '&nbsp;', 'label' => ctrans('texts.' . $this->entity_string . '_due_date')];
$data['$invoice.due_date'] = &$data['$due_date'];
$data['$invoice.number'] = ['value' => $this->entity->number ?: '&nbsp;', 'label' => ctrans('texts.invoice_number')];
$data['$invoice.po_number'] = ['value' => $this->entity->po_number ?: '&nbsp;', 'label' => ctrans('texts.po_number')];
$data['$line_taxes'] = ['value' => $this->makeLineTaxes() ?: '&nbsp;', 'label' => ctrans('texts.taxes')];
@ -117,7 +118,7 @@ class HtmlEngine
$data['$invoice.total_taxes'] = &$data['$total_taxes'];
if ($this->entity_string == 'invoice') {
$data['$entity_label'] = ['value' => '', 'label' => ctrans('texts.invoice')];
$data['$entity'] = ['value' => '', 'label' => ctrans('texts.invoice')];
$data['$number'] = ['value' => $this->entity->number ?: '&nbsp;', 'label' => ctrans('texts.invoice_number')];
$data['$entity.terms'] = ['value' => $this->entity->terms ?: '&nbsp;', 'label' => ctrans('texts.invoice_terms')];
$data['$terms'] = &$data['$entity.terms'];
@ -125,7 +126,7 @@ class HtmlEngine
}
if ($this->entity_string == 'quote') {
$data['$entity_label'] = ['value' => '', 'label' => ctrans('texts.quote')];
$data['$entity'] = ['value' => '', 'label' => ctrans('texts.quote')];
$data['$number'] = ['value' => $this->entity->number ?: '&nbsp;', 'label' => ctrans('texts.quote_number')];
$data['$entity.terms'] = ['value' => $this->entity->terms ?: '&nbsp;', 'label' => ctrans('texts.quote_terms')];
$data['$terms'] = &$data['$entity.terms'];
@ -133,7 +134,7 @@ class HtmlEngine
}
if ($this->entity_string == 'credit') {
$data['$entity_label'] = ['value' => '', 'label' => ctrans('texts.credit')];
$data['$entity'] = ['value' => '', 'label' => ctrans('texts.credit')];
$data['$number'] = ['value' => $this->entity->number ?: '&nbsp;', 'label' => ctrans('texts.credit_number')];
$data['$entity.terms'] = ['value' => $this->entity->terms ?: '&nbsp;', 'label' => ctrans('texts.credit_terms')];
$data['$terms'] = &$data['$entity.terms'];
@ -147,10 +148,12 @@ class HtmlEngine
$data['$discount'] = &$data['$invoice.discount'];
$data['$subtotal'] = ['value' => Number::formatMoney($this->entity_calc->getSubTotal(), $this->client) ?: '&nbsp;', 'label' => ctrans('texts.subtotal')];
$data['$invoice.subtotal'] = &$data['$subtotal'];
$data['$invoice.balance_due'] = ['value' => Number::formatMoney($this->entity->balance, $this->client) ?: '&nbsp;', 'label' => ctrans('texts.balance_due')];
$data['$quote.balance_due'] = &$data['$invoice.balance_due'];
$data['$balance_due'] = &$data['$invoice.balance_due'];
$data['$invoice.partial_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->client) ?: '&nbsp;', 'label' => ctrans('texts.partial_due')];
$data['$balance_due'] = ['value' => Number::formatMoney($this->entity->balance, $this->client) ?: '&nbsp;', 'label' => ctrans('texts.balance_due')];
$data['$quote.balance_due'] = &$data['$balance_due'];
$data['$invoice.balance_due'] = &$data['$balance_due'];
$data['$balance_due'] = &$data['$balance_due'];
$data['$outstanding'] = &$data['$balance_due'];
$data['$partial_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->client) ?: '&nbsp;', 'label' => ctrans('texts.partial_due')];
$data['$total'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->client) ?: '&nbsp;', 'label' => ctrans('texts.total')];
$data['$amount'] = &$data['$total'];
$data['$quote.total'] = &$data['$total'];
@ -175,11 +178,10 @@ class HtmlEngine
$data['$invoice.custom4'] = ['value' => $this->entity->custom_value4 ?: '&nbsp;', 'label' => $this->makeCustomField('invoice4')];
$data['$invoice.public_notes'] = ['value' => $this->entity->public_notes ?: '&nbsp;', 'label' => ctrans('texts.public_notes')];
$data['$entity.public_notes'] = &$data['$invoice.public_notes'];
// $data['$your_invoice'] = ;
// $data['$quote'] = ;
// $data['$your_quote'] = ;
//
$data['$entity_issued_to'] = ['value' => '', 'label' => ctrans("texts.{$this->entity_string}_issued_to")];
$data['$your_entity'] = ['value' => '', 'label' => ctrans("texts.your_{$this->entity_string}")];
$data['$quote.date'] = ['value' => $this->entity->date ?: '&nbsp;', 'label' => ctrans('texts.quote_date')];
$data['$quote.number'] = ['value' => $this->entity->number ?: '&nbsp;', 'label' => ctrans('texts.quote_number')];
$data['$quote.po_number'] = &$data['$invoice.po_number'];
@ -297,6 +299,14 @@ class HtmlEngine
$data['$task.line_total'] = ['value' => '', 'label' => ctrans('texts.line_total')];
$data['$contact.signature'] = ['value' => $this->invitation->signature_base64, 'label' => ctrans('texts.signature')];
$data['$thanks'] = ['value' => '', 'label' => ctrans('texts.thanks')];
$data['$from'] = ['value' => '', 'label' => ctrans('texts.from')];
$data['$to'] = ['value' => '', 'label' => ctrans('texts.to')];
$data['_rate1'] = ['value' => '', 'label' => ctrans('texts.tax')];
$data['_rate2'] = ['value' => '', 'label' => ctrans('texts.tax')];
$data['_rate3'] = ['value' => '', 'label' => ctrans('texts.tax')];
// $data['custom_label1'] = ['value' => '', 'label' => ctrans('texts.')];
// $data['custom_label2'] = ['value' => '', 'label' => ctrans('texts.')];
// $data['custom_label3'] = ['value' => '', 'label' => ctrans('texts.')];

View File

@ -8,7 +8,7 @@
/>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="stylesheet" href="$css" />
<link rel="stylesheet" href="$app_url/css/tailwindcss@1.4.6.css" />
</head>
<style>
@ -44,7 +44,7 @@
<h2
class="text-2xl font-semibold tracking-tight text-teal-600 uppercase"
>
$your-invoice
$your_entity_label
</h2>
<div id="client-details" class="mt-4"></div>
</div>
@ -63,4 +63,6 @@
<table id="product-table" class="w-full mt-8 table-auto"></table>
</div>
</body>
<footer id="footer"></footer>
</html>

View File

@ -8,7 +8,7 @@
/>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="stylesheet" href="$css" />
<link rel="stylesheet" href="$app_url/css/tailwindcss@1.4.6.css" />
</head>
<style>
@ -52,7 +52,7 @@
<!-- Client details, entity details -->
<div class="grid grid-cols-12 gap-4 my-12">
<div class="col-span-6">
<p>$invoice-issued-to</p>
<p>$entity_issued_to_label</p>
<div id="client-details" class="mt-4 text-orange-600"></div>
</div>
<div class="col-span-6">
@ -70,21 +70,7 @@
id="product-table"
class="w-full mt-20 rounded table-auto"
></table>
<!-- Balance due card -->
<!-- <div class="grid grid-cols-12 my-12">
<div class="col-span-6">
<p class="font-semibold">$terms-label</p>
<p>$terms</p>
</div>
<div class="col-span-5 col-start-8 lg:col-start-9 lg:col-span-4">
<div class="h-auto px-4 py-4 bg-orange-600 rounded-lg">
<div class="flex justify-between text-white">
<p>$balance-due-label</p>
<p>$balance-due</p>
</div>
</div>
</div>
</div> -->
</body>
<footer id="footer"></footer>
</html>

View File

@ -8,7 +8,7 @@
/>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="stylesheet" href="$css" />
<link rel="stylesheet" href="$app_url/css/tailwindcss@1.4.6.css" />
</head>
<style>
@ -34,7 +34,7 @@
</div>
<!-- Entity labels, client details -->
<p class="mt-10 text-xl text-blue-500 uppercase">$entity</p>
<p class="mt-10 px-2 text-xl text-blue-500 uppercase">$entity_label</p>
<div class="grid grid-cols-12 px-2 py-3 mt-4 border-t border-b">
<div class="col-span-6">
<table id="entity-details"></table>
@ -45,4 +45,6 @@
<!-- Product table -->
<table id="product-table" class="table-auto mt-12 w-full"></table>
</body>
<footer id="footer"></footer>
</html>

View File

@ -8,7 +8,7 @@
/>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="stylesheet" href="$css" />
<link rel="stylesheet" href="$app_url/css/tailwindcss@1.4.6.css" />
</head>
<style>
@ -49,8 +49,8 @@
<div class="grid grid-cols-12 mt-10">
<!-- Entity number -->
<div class="col-span-4 text-3xl font-semibold uppercase">
<span>$entity</span>
<i class="text-pink-700">#$entity-number</i>
<span>$entity_label</span>
<i class="text-pink-700">#$entity_number</i>
</div>
<!-- Entity labels -->
@ -64,4 +64,6 @@
class="w-full mt-10 border-t-4 border-pink-700 table-auto"
></table>
</body>
<footer id="footer"></footer>
</html>

View File

@ -8,7 +8,7 @@
/>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="stylesheet" href="$css" />
<link rel="stylesheet" href="$app_url/css/tailwindcss@1.4.6.css" />
</head>
<body class="$global-margin antialiased bg-white break-words">
@ -24,6 +24,11 @@
<div class="flex flex-col items-end col-span-6">
<table id="entity-details"></table>
</div>
<div class="col-span-6">
<p class="text-xl font-semibold uppercase">
$your_entity_label
</p>
</div>
</div>
<!-- Client details, company details -->
@ -42,7 +47,13 @@
<table id="product-table" class="w-full mt-10 table-auto"></table>
<!-- Thanks label -->
<p class="w-full pb-4 mt-10 text-2xl font-semibold text-center border-b-4 border-black">$thanks</p>
<p
class="w-full pb-4 mt-10 text-2xl font-semibold text-center border-b-4 border-black"
>
$thanks_label
</p>
<div class="w-full border-black order-b wpy-1"></div>
</body>
<footer id="footer"></footer>
</html>

View File

@ -8,7 +8,7 @@
/>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="stylesheet" href="$css" />
<link rel="stylesheet" href="$app_url/css/tailwindcss@1.4.6.css" />
</head>
<body class="$global-margin antialiased break-words bg-white">
@ -17,7 +17,7 @@
<div class="col-span-4 pl-4 border-l border-black">
<div id="company-details">
<p class="font-semibold text-yellow-600 uppercase">
$from:
$from_label:
</p>
</div>
<div id="company-address" class="mt-4"></div>
@ -26,7 +26,9 @@
class="col-span-5 pl-4 border-l border-black"
id="client-details"
>
<p class="font-semibold text-yellow-600 uppercase">$to:</p>
<p class="font-semibold text-yellow-600 uppercase">
$to_label:
</p>
</div>
<div class="col-span-3">
<img
@ -39,7 +41,7 @@
<!-- Entity details -->
<h1 class="mt-6 text-4xl font-semibold uppercase lg:text-5xl">
$entity
$entity_label
</h1>
<div
id="entity-details"
@ -49,4 +51,6 @@
<!-- Product table -->
<table id="product-table" class="w-full mt-10 table-auto"></table>
</body>
<footer id="footer"></footer>
</html>

View File

@ -8,7 +8,7 @@
/>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="stylesheet" href="$css" />
<link rel="stylesheet" href="$app_url/css/tailwindcss@1.4.6.css" />
</head>
<body class="antialiased break-words bg-white">
@ -30,6 +30,11 @@
<div class="$global-margin">
<!-- Company logo, client details -->
<div class="col-span-12 mb-10">
<p class="text-xl text-orange-600 font-semibold uppercase">
$your_entity_label
</p>
</div>
<div class="grid grid-cols-12">
<img
src="$company.logo"
@ -57,4 +62,6 @@
</div>
</div>
</body>
<footer id="footer"></footer>
</html>

View File

@ -8,7 +8,7 @@
/>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="stylesheet" href="$css" />
<link rel="stylesheet" href="$app_url/css/tailwindcss@1.4.6.css" />
</head>
<body class="$global-margin antialiased break-words bg-white">
@ -34,10 +34,17 @@
<!-- Client details -->
<div class="grid grid-cols-12 mt-12">
<div class="col-span-12 mb-10">
<p class="text-xl text-black font-semibold uppercase">
$your_entity_label
</p>
</div>
<div class="col-span-6" id="client-details"></div>
</div>
<!-- Product table -->
<table id="product-table" class="w-full mt-8 table-auto"></table>
</body>
<footer id="footer"></footer>
</html>

View File

@ -8,14 +8,14 @@
/>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="stylesheet" href="$css" />
<link rel="stylesheet" href="$app_url/css/tailwindcss@1.4.6.css" />
</head>
<style>
#product-table tbody > tr > td:first-child {
color: #9b2c2c;
}
#product-table tbody > tr > td:last-child {
color: #9b2c2c;
font-weight: bold;
@ -39,8 +39,13 @@
<!-- Company details, client details -->
<div class="grid grid-cols-12 gap-12 mt-12">
<div class="col-span-12">
<p class="text-xl text-teal-600 font-semibold uppercase">
$your_entity_label
</p>
</div>
<div class="col-span-6">
<p class="px-4 font-semibold text-teal-600">$to:</p>
<p class="px-4 font-semibold text-teal-600">$to_label:</p>
<div
class="p-4 mt-4 border-t-4 border-b-4 border-teal-600 border-dashed"
>
@ -48,7 +53,7 @@
</div>
</div>
<div class="col-span-6">
<p class="px-4 font-semibold text-teal-600">$from:</p>
<p class="px-4 font-semibold text-teal-600">$from_label:</p>
<div
class="flex p-4 mt-4 space-x-4 border-t-4 border-b-4 border-teal-600 border-dashed"
>
@ -61,4 +66,6 @@
<!-- Product table -->
<table id="product-table" class="w-full mt-10 table-auto"></table>
</body>
<footer id="footer"></footer>
</html>

View File

@ -2,8 +2,18 @@
namespace Tests\Feature\PdfMaker;
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
class ExampleDesign
{
use DesignHelpers;
public $client;
public $entity;
public $context;
public function html()
{
return file_get_contents(

View File

@ -7,21 +7,26 @@ use App\Services\PdfMaker\Designs\Playful;
use App\Services\PdfMaker\PdfMaker;
use App\Utils\HtmlEngine;
use App\Utils\Traits\MakesInvoiceValues;
use Tests\MockAccountData;
use Tests\TestCase;
class ExampleIntegrationTest extends TestCase
{
use MakesInvoiceValues;
use MakesInvoiceValues, MockAccountData;
public function setUp(): void
{
parent::setUp();
$this->makeTestData();
}
public function testExample()
{
$this->markTestSkipped('WIP');
$invoice = Invoice::first();
$invoice = $this->invoice;
$invitation = $invoice->invitations()->first();
$engine = new HtmlEngine($invitation, 'invoice');
$engine = new HtmlEngine(null, $invitation, 'invoice');
$design = new Playful();
$product_table_columns = json_decode(
@ -38,7 +43,7 @@ class ExampleIntegrationTest extends TestCase
'variables' => $engine->generateLabelsAndValues(),
];
$maker = new PdfMaker($state, 'invoice');
$maker = new PdfMaker($state);
$maker
->design(Playful::class)

View File

@ -24,27 +24,30 @@ class PdfMakerDesignsTest extends TestCase
$this->state = [
'variables' => [
'$css' => asset('css/tailwindcss@1.4.6.css'),
'$global-margin' => 'm-12',
'$global-padding' => 'p-12',
'labels' => [],
'values' => [
'$css' => asset('css/tailwindcss@1.4.6.css'),
'$global-margin' => 'm-12',
'$global-padding' => 'p-12',
'$company-logo' => 'https://invoiceninja-invoice-templates.netlify.app/assets/images/invoiceninja-logo.png',
'$company-name' => 'Invoice Ninja',
'$entity-number-label' => 'Invoice number',
'$entity-number' => '10000',
'$entity-date-label' => 'Invoice date',
'$entity-date' => '3th of June, 2025.',
'$due-date-label' => 'Due date',
'$due-date' => '5th of June, 2025.',
'$balance-due-label' => 'Balance due',
'$balance-due' => '$800.50',
'$company-logo' => 'https://invoiceninja-invoice-templates.netlify.app/assets/images/invoiceninja-logo.png',
'$company-name' => 'Invoice Ninja',
'$entity-number-label' => 'Invoice number',
'$entity-number' => '10000',
'$entity-date-label' => 'Invoice date',
'$entity-date' => '3th of June, 2025.',
'$due-date-label' => 'Due date',
'$due-date' => '5th of June, 2025.',
'$balance-due-label' => 'Balance due',
'$balance-due' => '$800.50',
'$terms-label' => 'Terms',
'$terms' => 'Trend and SEO report has been sent via email. This is really long text just to test the width of the elements.',
'$terms-label' => 'Terms',
'$terms' => 'Trend and SEO report has been sent via email. This is really long text just to test the width of the elements.',
'$invoice-issued-to' => 'Invoice issued to:',
'$invoice-issued-to' => 'Invoice issued to:',
'$entity' => 'Invoice',
'$entity' => 'Invoice',
],
],
];
}
@ -720,7 +723,7 @@ class PdfMakerDesignsTest extends TestCase
$this->assertTrue(true);
}
public function testElegant()
public function testElegant()
{
$state = [
'template' => [
@ -812,7 +815,7 @@ public function testElegant()
['element' => 'td', 'content' => '$2.00', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
['element' => 'tr', 'content' => '', 'properties' => ['class' => 'mt-8 px-4 py-2'], 'elements' => [
['element' => 'td', 'content' => 'Balance due', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '4']],
['element' => 'td', 'content' => 'Balance due', 'properties' => ['class' => 'border-l-4 border-white px-4 text-right', 'colspan' => '4']],
['element' => 'td', 'content' => '$2.00', 'properties' => ['class' => 'px-4 py-2 text-right']],
]],
]],

View File

@ -2,15 +2,18 @@
namespace Tests\Feature\PdfMaker;
use App\Services\PdfMaker\Designs\Plain;
use App\Services\PdfMaker\PdfMaker;
use Spatie\Browsershot\Browsershot;
use Tests\TestCase;
class PdfMakerTest extends TestCase
{
public $state = [
'template' => [],
'variables' => [],
'variables' => [
'labels' => [],
'values' => [],
],
];
public function testDesignLoadsCorrectly()
@ -71,7 +74,10 @@ class PdfMakerTest extends TestCase
],
],
],
'variables' => [],
'variables' => [
'labels' => [],
'values' => [],
],
];
$maker = new PdfMaker($state);
@ -108,7 +114,10 @@ class PdfMakerTest extends TestCase
],
],
'variables' => [
'$title' => 'Invoice Ninja',
'labels' => [],
'values' => [
'$title' => 'Invoice Ninja',
],
],
];
@ -153,9 +162,12 @@ class PdfMakerTest extends TestCase
],
],
'variables' => [
'$company' => 'Invoice Ninja',
'$email' => 'contact@invoiceninja.com',
'$country' => 'UK',
'labels' => [],
'values' => [
'$company' => 'Invoice Ninja',
'$email' => 'contact@invoiceninja.com',
'$country' => 'UK',
],
],
];
@ -317,8 +329,11 @@ class PdfMakerTest extends TestCase
],
]
],
'variables' =>[
'$title' => 'Invoice Ninja',
'variables' => [
'labels' => [],
'values' => [
'$title' => 'Invoice Ninja',
],
]
];
@ -330,4 +345,15 @@ class PdfMakerTest extends TestCase
$this->assertTrue(true);
}
public function testGetSectionHTMLWorks()
{
$design = new ExampleDesign();
$html = $design
->document()
->getSectionHTML('product-table');
$this->assertStringContainsString('id="product-table"', $html);
}
}