mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 13:12:50 +01:00
Refactor Designs (#3449)
* Refactor custom invoice HTML generation * remove table_styles() method from designs * Refactor designs * Clean up designs
This commit is contained in:
parent
e095b8538f
commit
d13ab48d86
@ -13,18 +13,16 @@ namespace App\Designs;
|
||||
|
||||
abstract class AbstractDesign
|
||||
{
|
||||
abstract public function include();
|
||||
abstract public function includes();
|
||||
|
||||
abstract public function header();
|
||||
|
||||
abstract public function body();
|
||||
|
||||
abstract public function product_table();
|
||||
abstract public function product();
|
||||
|
||||
abstract public function task_table();
|
||||
abstract public function task();
|
||||
|
||||
abstract public function footer();
|
||||
|
||||
abstract public function table_styles();
|
||||
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -13,41 +13,37 @@ namespace App\Designs;
|
||||
|
||||
class Custom extends AbstractDesign
|
||||
{
|
||||
private $include;
|
||||
private $includes;
|
||||
|
||||
private $header;
|
||||
|
||||
private $body;
|
||||
|
||||
private $product_table;
|
||||
private $product;
|
||||
|
||||
private $task_table;
|
||||
private $task;
|
||||
|
||||
private $footer;
|
||||
|
||||
private $table_styles;
|
||||
|
||||
public function __construct($design)
|
||||
{
|
||||
$this->include = $design->include;
|
||||
$this->includes = $design->includes;
|
||||
|
||||
$this->header = $design->header;
|
||||
|
||||
$this->body = $design->body;
|
||||
|
||||
$this->product_table = $design->product_table;
|
||||
$this->product = $design->product;
|
||||
|
||||
$this->task_table = $design->task_table;
|
||||
$this->task = $design->task;
|
||||
|
||||
$this->footer = $design->footer;
|
||||
|
||||
$this->table_styles = $design->table_styles;
|
||||
|
||||
}
|
||||
|
||||
public function include()
|
||||
public function includes()
|
||||
{
|
||||
return $this->include;
|
||||
return $this->includes;
|
||||
}
|
||||
|
||||
public function header()
|
||||
@ -64,23 +60,16 @@ class Custom extends AbstractDesign
|
||||
|
||||
}
|
||||
|
||||
public function table_styles()
|
||||
public function product()
|
||||
{
|
||||
|
||||
return $this->table_styles;
|
||||
return $this->product;
|
||||
|
||||
}
|
||||
|
||||
public function product_table()
|
||||
public function task()
|
||||
{
|
||||
|
||||
return $this->product_table;
|
||||
|
||||
}
|
||||
|
||||
public function task_table()
|
||||
{
|
||||
return $this->task_table;
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
public function footer()
|
||||
|
@ -16,7 +16,9 @@ use App\Models\Invoice;
|
||||
|
||||
class Designer {
|
||||
|
||||
protected $design;
|
||||
public $design;
|
||||
|
||||
public $design_name;
|
||||
|
||||
protected $input_variables;
|
||||
|
||||
@ -55,7 +57,9 @@ class Designer {
|
||||
{
|
||||
$this->entity = $entity;
|
||||
|
||||
$this->design = $design;
|
||||
$this->design = $design->design;
|
||||
|
||||
$this->design_name = lcfirst($design->name);
|
||||
|
||||
$this->input_variables = (array) $input_variables;
|
||||
|
||||
@ -73,7 +77,7 @@ class Designer {
|
||||
|
||||
$this->setHtml()
|
||||
->exportVariables()
|
||||
->setDesign($this->getSection('include'))
|
||||
->setDesign($this->getSection('includes'))
|
||||
->setDesign($this->getSection('header'))
|
||||
->setDesign($this->getSection('body'))
|
||||
->setDesign($this->getProductTable($this->entity))
|
||||
@ -91,11 +95,17 @@ class Designer {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIncludes()
|
||||
{
|
||||
$this->setDesign($this->getSection('includes'));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHeader()
|
||||
{
|
||||
|
||||
$this->setDesign($this->getSection('include'))
|
||||
->setDesign($this->getSection('header'));
|
||||
$this->setDesign($this->getSection('header'));
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -111,9 +121,7 @@ class Designer {
|
||||
public function getBody()
|
||||
{
|
||||
|
||||
$this->setDesign($this->getSection('include'))
|
||||
->setDesign($this->getSection('body'))
|
||||
->setDesign($this->getProductTable());
|
||||
$this->setDesign($this->getSection('body'));
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -121,11 +129,24 @@ class Designer {
|
||||
public function getProductTable():string
|
||||
{
|
||||
|
||||
$table_header = $this->entity->table_header($this->input_variables['product_columns'], $this->design->table_styles());
|
||||
$table_body = $this->entity->table_body($this->input_variables['product_columns'], $this->design->table_styles());
|
||||
$table_header = $this->entity->table_header($this->input_variables['product_columns']);
|
||||
$table_body = $this->entity->table_body($this->input_variables['product_columns']);
|
||||
|
||||
$data = str_replace('$table_header', $table_header, $this->getSection('product_table'));
|
||||
$data = str_replace('$table_body', $table_body, $data);
|
||||
$data = str_replace('$product_table_header', $table_header, $this->getSection('product'));
|
||||
$data = str_replace('$product_table_body', $table_body, $data);
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
public function getTaskTable():string
|
||||
{
|
||||
|
||||
$table_header = $this->entity->table_header($this->input_variables['task_columns']);
|
||||
$table_body = $this->entity->table_body($this->input_variables['task_columns']);
|
||||
|
||||
$data = str_replace('$task_table_header', $table_header, $this->getSection('task'));
|
||||
$data = str_replace('$task_table_body', $table_body, $data);
|
||||
|
||||
return $data;
|
||||
|
||||
@ -160,7 +181,7 @@ class Designer {
|
||||
*/
|
||||
public function getSection($section):string
|
||||
{
|
||||
return str_replace(array_keys($this->exported_variables), array_values($this->exported_variables), $this->design->{$section}());
|
||||
return str_replace(array_keys($this->exported_variables), array_values($this->exported_variables), $this->design->{$section});
|
||||
}
|
||||
|
||||
private function exportVariables()
|
||||
@ -366,7 +387,7 @@ class Designer {
|
||||
|
||||
foreach (self::$custom_fields as $cf) {
|
||||
|
||||
if (!property_exists($custom_fields, $cf) || (strlen($custom_fields->{ $cf}) == 0)) {
|
||||
if (!property_exists($custom_fields, $cf) || (strlen($custom_fields->{$cf}) == 0)) {
|
||||
unset($data[$cf]);
|
||||
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -186,7 +186,7 @@ class CreditController extends BaseController
|
||||
{
|
||||
$client = Client::find($request->input('client_id'));
|
||||
|
||||
$credit = $this->credit_repository->save($request->all(), $client->setCreditDefaults());
|
||||
$credit = $this->credit_repository->save($request->all(), CreditFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
|
||||
$credit = StoreCredit::dispatchNow($credit, $request->all(), $credit->company);
|
||||
|
||||
|
@ -205,7 +205,7 @@ class QuoteController extends BaseController
|
||||
{
|
||||
$client = Client::find($request->input('client_id'));
|
||||
|
||||
$quote = $this->quote_repo->save($request->all(), $client->setQuoteDefaults());
|
||||
$quote = $this->quote_repo->save($request->all(), QuoteFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
|
||||
return $this->itemResponse($quote);
|
||||
}
|
||||
|
@ -79,18 +79,11 @@ class CreateCreditPdf implements ShouldQueue {
|
||||
|
||||
$design = Design::find($this->decodePrimaryKey($this->credit->client->getSetting('credit_design_id')));
|
||||
|
||||
if($design->is_custom){
|
||||
$credit_design = new Custom($design->design);
|
||||
}
|
||||
else{
|
||||
$class = 'App\Designs\\'.$design->name;
|
||||
$credit_design = new $class();
|
||||
}
|
||||
|
||||
$designer = new Designer($this->credit, $credit_design, $this->credit->client->getSetting('pdf_variables'), 'credit');
|
||||
$designer = new Designer($this->credit, $design, $this->credit->client->getSetting('pdf_variables'), 'credit');
|
||||
|
||||
//get invoice design
|
||||
$html = $this->generateInvoiceHtml($designer->build()->getHtml(), $this->credit, $this->contact);
|
||||
// $html = $this->generateInvoiceHtml($designer->build()->getHtml(), $this->credit, $this->contact);
|
||||
$html = $this->generateEntityHtml($designer, $this->credit, $this->contact);
|
||||
|
||||
//todo - move this to the client creation stage so we don't keep hitting this unnecessarily
|
||||
Storage::makeDirectory($path, 0755);
|
||||
|
@ -77,18 +77,12 @@ class CreateInvoicePdf implements ShouldQueue {
|
||||
|
||||
$design = Design::find($this->decodePrimaryKey($this->invoice->client->getSetting('invoice_design_id')));
|
||||
|
||||
if($design->is_custom){
|
||||
$invoice_design = new Custom($design->design);
|
||||
}
|
||||
else{
|
||||
$class = 'App\Designs\\'.$design->name;
|
||||
$invoice_design = new $class();
|
||||
}
|
||||
|
||||
$designer = new Designer($this->invoice, $invoice_design, $this->invoice->client->getSetting('pdf_variables'), 'invoice');
|
||||
$designer = new Designer($this->invoice, $design, $this->invoice->client->getSetting('pdf_variables'), 'invoice');
|
||||
|
||||
//get invoice design
|
||||
$html = $this->generateInvoiceHtml($designer->build()->getHtml(), $this->invoice, $this->contact);
|
||||
//$html = $this->generateInvoiceHtml($designer->build()->getHtml(), $this->invoice, $this->contact);
|
||||
$html = $this->generateEntityHtml($designer, $this->invoice, $this->contact);
|
||||
|
||||
|
||||
//todo - move this to the client creation stage so we don't keep hitting this unnecessarily
|
||||
Storage::makeDirectory($path, 0755);
|
||||
|
@ -79,15 +79,7 @@ class CreateQuotePdf implements ShouldQueue {
|
||||
|
||||
$design = Design::find($this->decodePrimaryKey($this->quote->client->getSetting('quote_design_id')));
|
||||
|
||||
if($design->is_custom){
|
||||
$quote_design = new Custom($design->design);
|
||||
}
|
||||
else{
|
||||
$class = 'App\Designs\\'.$design->name;
|
||||
$quote_design = new $class();
|
||||
}
|
||||
|
||||
$designer = new Designer($this->quote, $quote_design, $this->quote->client->getSetting('pdf_variables'), 'quote');
|
||||
$designer = new Designer($this->quote, $design, $this->quote->client->getSetting('pdf_variables'), 'quote');
|
||||
|
||||
//todo - move this to the client creation stage so we don't keep hitting this unnecessarily
|
||||
Storage::makeDirectory($path, 0755);
|
||||
@ -123,7 +115,8 @@ class CreateQuotePdf implements ShouldQueue {
|
||||
|
||||
|
||||
//get invoice design
|
||||
$html = $this->generateInvoiceHtml($design_body, $this->quote, $this->contact);
|
||||
// $html = $this->generateInvoiceHtml($design_body, $this->quote, $this->contact);
|
||||
$html = $this->generateEntityHtml($designer, $this->quote, $this->contact);
|
||||
|
||||
$pdf = $this->makePdf($all_pages_header, $all_pages_footer, $html);
|
||||
$file_path = $path . $quote_number . '.pdf';
|
||||
|
@ -134,8 +134,6 @@ class Import implements ShouldQueue
|
||||
throw new ResourceNotAvailableForMigration("Resource {$key} is not available for migration.");
|
||||
}
|
||||
|
||||
\Log::error($key);
|
||||
|
||||
$method = sprintf("process%s", Str::ucfirst(Str::camel($key)));
|
||||
|
||||
$this->{$method}($resource);
|
||||
|
@ -468,10 +468,10 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
|
||||
public function setCompanyDefaults($data, $entity_name)
|
||||
{
|
||||
if(strlen($data['terms']) == 0)
|
||||
if(isset($data['terms']) && strlen($data['terms']) == 0)
|
||||
$data['terms'] = $this->getSetting($entity_name.'_terms');
|
||||
|
||||
if(strlen($data['footer']) == 0)
|
||||
if(isset($data['footer']) && strlen($data['footer']) == 0)
|
||||
$data['footer'] = $this->getSetting($entity_name.'_footer');
|
||||
|
||||
if(strlen($this->public_notes) >=1)
|
||||
|
@ -188,7 +188,10 @@ class BaseRepository
|
||||
{
|
||||
$class = new ReflectionClass($model);
|
||||
|
||||
if(array_key_exists('client_id', $data))
|
||||
$client = Client::find($data['client_id']);
|
||||
else
|
||||
$client = Client::find($model->client_id);
|
||||
|
||||
$state = [];
|
||||
$resource = explode('\\', $class->name)[2]; /** This will extract 'Invoice' from App\Models\Invoice */
|
||||
@ -202,8 +205,6 @@ class BaseRepository
|
||||
$model->uses_inclusive_taxes = $client->getSetting('inclusive_taxes');
|
||||
}
|
||||
|
||||
\Log::error(print_r($data,1));
|
||||
|
||||
$model->fill($data);
|
||||
$model->save();
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace App\Utils\Traits;
|
||||
|
||||
use App\Designs\Designer;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||
@ -47,12 +48,51 @@ trait MakesInvoiceHtml
|
||||
$design = str_replace(array_keys($values), array_values($values), $design);
|
||||
|
||||
$data['invoice'] = $invoice;
|
||||
$data['lang'] = $client->preferredLocale();
|
||||
|
||||
return $this->renderView($design, $data);
|
||||
|
||||
//return view($design, $data)->render();
|
||||
}
|
||||
|
||||
public function generateEntityHtml(Designer $designer, $entity, $contact = null) :string
|
||||
{
|
||||
|
||||
$entity->load('client');
|
||||
|
||||
$client = $entity->client;
|
||||
|
||||
App::setLocale($client->preferredLocale());
|
||||
|
||||
$labels = $entity->makeLabels();
|
||||
$values = $entity->makeValues($contact);
|
||||
|
||||
$css_url = url('').'/css/design/'.$designer->design_name.'.css';
|
||||
$css_url = "<link href=\"{$css_url}\" rel=\"stylesheet\">";
|
||||
|
||||
$data = [];
|
||||
$data['entity'] = $entity;
|
||||
$data['lang'] = $client->preferredLocale();
|
||||
$data['includes'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getIncludes()->getHtml());
|
||||
$data['includes'] = str_replace('$css_url', $css_url, $data['includes']);
|
||||
$data['header'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getHeader()->getHtml());
|
||||
$data['body'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getBody()->getHtml());
|
||||
$data['product'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getProductTable());
|
||||
$data['task'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getTaskTable());
|
||||
$data['footer'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getFooter()->getHtml());
|
||||
|
||||
|
||||
|
||||
return view('pdf.stub', $data)->render();
|
||||
}
|
||||
|
||||
private function parseLabelsAndValues($labels, $values, $section) :string
|
||||
{
|
||||
$section = str_replace(array_keys($labels), array_values($labels), $section);
|
||||
$section = str_replace(array_keys($values), array_values($values), $section);
|
||||
return $section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the blade file string and processes the template variables
|
||||
*
|
||||
@ -61,11 +101,8 @@ trait MakesInvoiceHtml
|
||||
* @return string The return HTML string
|
||||
*
|
||||
*/
|
||||
public function renderView($string, $data) :string
|
||||
public function renderView($string, $data = []) :string
|
||||
{
|
||||
if (!$data) {
|
||||
$data = [];
|
||||
}
|
||||
|
||||
$data['__env'] = app(\Illuminate\View\Factory::class);
|
||||
|
||||
|
@ -505,7 +505,7 @@ trait MakesInvoiceValues
|
||||
}
|
||||
|
||||
|
||||
public function table_header($columns, $css) :?string
|
||||
public function table_header($columns) :?string
|
||||
{
|
||||
|
||||
/* Table Header */
|
||||
@ -524,7 +524,10 @@ trait MakesInvoiceValues
|
||||
|
||||
}
|
||||
|
||||
public function table_body($columns, $css) :?string
|
||||
/**
|
||||
* @todo need to differentiate here between products and tasks - need to filter by invoice_type_id
|
||||
*/
|
||||
public function table_body($columns) :?string
|
||||
{
|
||||
$table_body = '';
|
||||
|
||||
|
@ -42,11 +42,11 @@ class DesignSeeder extends Seeder
|
||||
$invoice_design = new $class();
|
||||
|
||||
$design_object = new \stdClass;
|
||||
$design_object->include = $invoice_design->include() ?: '';
|
||||
$design_object->includes = $invoice_design->includes() ?: '';
|
||||
$design_object->header = $invoice_design->header() ?: '';
|
||||
$design_object->body = $invoice_design->body() ?: '';
|
||||
$design_object->product_table = $invoice_design->product_table() ?: '';
|
||||
$design_object->task_table = $invoice_design->task_table() ?: '';
|
||||
$design_object->product = $invoice_design->product() ?: '';
|
||||
$design_object->task = $invoice_design->task() ?: '';
|
||||
$design_object->footer = $invoice_design->footer() ?: '';
|
||||
|
||||
$design->design = $design_object;
|
||||
|
1
public/css/design/bold.css
vendored
Normal file
1
public/css/design/bold.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/design/business.css
vendored
Normal file
1
public/css/design/business.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/design/clean.css
vendored
Normal file
1
public/css/design/clean.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/design/creative.css
vendored
Normal file
1
public/css/design/creative.css
vendored
Normal file
File diff suppressed because one or more lines are too long
0
public/css/design/custom.css
vendored
Normal file
0
public/css/design/custom.css
vendored
Normal file
1
public/css/design/elegant.css
vendored
Normal file
1
public/css/design/elegant.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/design/hipster.css
vendored
Normal file
1
public/css/design/hipster.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/design/modern.css
vendored
Normal file
1
public/css/design/modern.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/design/photo.css
vendored
Normal file
1
public/css/design/photo.css
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/css/design/plain.css
vendored
Normal file
2
public/css/design/plain.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/design/playful.css
vendored
Normal file
1
public/css/design/playful.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1 +1,23 @@
|
||||
{!! $pdf !!}
|
||||
<!DOCTYPE html>
|
||||
<html lang="{!! $lang !!}">
|
||||
|
||||
{!! $includes !!}
|
||||
<body>
|
||||
|
||||
{!! $header !!}
|
||||
|
||||
{!! $body !!}
|
||||
|
||||
@if($product)
|
||||
{!! $product !!}
|
||||
@endif
|
||||
|
||||
@if($task)
|
||||
{!! $task !!}
|
||||
@endif
|
||||
|
||||
{!! $footer !!}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -80,7 +80,6 @@ class QuoteTest extends TestCase
|
||||
|
||||
$message = json_decode($e->validator->getMessageBag(),1);
|
||||
|
||||
\Log::error($message);
|
||||
}
|
||||
|
||||
if($response)
|
||||
|
@ -7,6 +7,7 @@ use App\Designs\Modern;
|
||||
use App\Jobs\Credit\CreateCreditPdf;
|
||||
use App\Jobs\Invoice\CreateInvoicePdf;
|
||||
use App\Jobs\Quote\CreateQuotePdf;
|
||||
use App\Models\Design;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Tests\MockAccountData;
|
||||
@ -32,9 +33,9 @@ class DesignTest extends TestCase
|
||||
public function testInvoiceDesignExists()
|
||||
{
|
||||
|
||||
$modern = new Modern();
|
||||
$design = Design::find(3);
|
||||
|
||||
$designer = new Designer($this->invoice, $modern, $this->company->settings->pdf_variables, 'quote');
|
||||
$designer = new Designer($this->invoice, $design, $this->company->settings->pdf_variables, 'quote');
|
||||
|
||||
$html = $designer->build()->getHtml();
|
||||
|
||||
@ -61,9 +62,9 @@ class DesignTest extends TestCase
|
||||
public function testQuoteDesignExists()
|
||||
{
|
||||
|
||||
$modern = new Modern();
|
||||
$design = Design::find(3);
|
||||
|
||||
$designer = new Designer($this->quote, $modern, $this->company->settings->pdf_variables, 'quote');
|
||||
$designer = new Designer($this->quote, $design, $this->company->settings->pdf_variables, 'quote');
|
||||
|
||||
$html = $designer->build()->getHtml();
|
||||
|
||||
@ -169,9 +170,9 @@ class DesignTest extends TestCase
|
||||
public function testCreditDesignExists()
|
||||
{
|
||||
|
||||
$modern = new Modern();
|
||||
$design = Design::find(3);
|
||||
|
||||
$designer = new Designer($this->credit, $modern, $this->company->settings->pdf_variables, 'credit');
|
||||
$designer = new Designer($this->credit, $design, $this->company->settings->pdf_variables, 'credit');
|
||||
|
||||
$html = $designer->build()->getHtml();
|
||||
|
||||
|
41
tests/Integration/HtmlGenerationTest.php
Normal file
41
tests/Integration/HtmlGenerationTest.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Integration;
|
||||
|
||||
use App\Designs\Bold;
|
||||
use App\Designs\Designer;
|
||||
use App\Models\Design;
|
||||
use App\Utils\Traits\MakesInvoiceHtml;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
class HtmlGenerationTest extends TestCase
|
||||
{
|
||||
use MockAccountData;
|
||||
use MakesInvoiceHtml;
|
||||
|
||||
public function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->makeTestData();
|
||||
}
|
||||
|
||||
public function testHtmlOutput()
|
||||
{
|
||||
$design = Design::find(3);
|
||||
|
||||
$designer = new Designer($this->invoice, $design, $this->invoice->client->getSetting('pdf_variables'), 'invoice');
|
||||
|
||||
$html = $this->generateEntityHtml($designer, $this->invoice);
|
||||
|
||||
\Log::error($html);
|
||||
|
||||
$this->assertNotNull($html);
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user