diff --git a/app/Jobs/Entity/CreateEntityPdf.php b/app/Jobs/Entity/CreateEntityPdf.php index 1b8e5f4a2d62..6d0a8f98806e 100644 --- a/app/Jobs/Entity/CreateEntityPdf.php +++ b/app/Jobs/Entity/CreateEntityPdf.php @@ -139,7 +139,7 @@ class CreateEntityPdf implements ShouldQueue 'client' => $this->entity->client, 'entity' => $this->entity, 'pdf_variables' => (array) $this->entity->company->settings->pdf_variables, - 'products' => $design->design->product, + '$product' => $design->design->product, ]), 'variables' => $html->generateLabelsAndValues(), 'options' => [ diff --git a/app/Repositories/ActivityRepository.php b/app/Repositories/ActivityRepository.php index fc0be7bbea77..78daafd6081c 100644 --- a/app/Repositories/ActivityRepository.php +++ b/app/Repositories/ActivityRepository.php @@ -133,7 +133,7 @@ class ActivityRepository extends BaseRepository 'client' => $entity->client, 'entity' => $entity, 'pdf_variables' => (array) $entity->company->settings->pdf_variables, - 'products' => $design->design->product, + '$product' => $design->design->product, ]), 'variables' => $html->generateLabelsAndValues(), 'options' => [ diff --git a/app/Services/PdfMaker/Design.php b/app/Services/PdfMaker/Design.php index 6c7d0563b875..b3404a053376 100644 --- a/app/Services/PdfMaker/Design.php +++ b/app/Services/PdfMaker/Design.php @@ -106,6 +106,10 @@ class Design extends BaseDesign 'id' => 'product-table', 'elements' => $this->productTable(), ], + 'task-table' => [ + 'id' => 'task-table', + 'elements' => $this->taskTable(), + ], 'table-totals' => [ 'id' => 'table-totals', 'elements' => $this->tableTotals(), @@ -188,47 +192,95 @@ class Design extends BaseDesign return $elements; } + /** + * Parent method for building products table. + * + * @return array + */ public function productTable(): array { + $product_items = collect($this->entity->line_items)->filter(function ($item) { + return $item->type_id == 1; + }); + + if ($product_items->count() == 0) { + return []; + } + return [ - ['element' => 'thead', 'elements' => $this->buildTableHeader()], - ['element' => 'tbody', 'elements' => $this->buildTableBody()], + ['element' => 'thead', 'elements' => $this->buildTableHeader('product')], + ['element' => 'tbody', 'elements' => $this->buildTableBody('$product')], ]; } - public function buildTableHeader(): array + /** + * Parent method for building tasks table. + * + * @return array + */ + public function taskTable(): array { - $this->processTaxColumns(); + $task_items = collect($this->entity->line_items)->filter(function ($item) { + return $item->type_id = 2; + }); + + if ($task_items->count() == 0) { + return []; + } + + return [ + ['element' => 'thead', 'elements' => $this->buildTableHeader('task')], + ['element' => 'tbody', 'elements' => $this->buildTableBody('$task')], + ]; + } + + /** + * Generate the structure of table headers. () + * + * @param string $type "product" or "task" + * @return array + */ + public function buildTableHeader(string $type): array + { + $this->processTaxColumns($type); $elements = []; - foreach ($this->context['pdf_variables']["{$this->type}_columns"] as $column) { + foreach ($this->context['pdf_variables']["{$type}_columns"] as $column) { $elements[] = ['element' => 'th', 'content' => $column . '_label']; } return $elements; } - public function buildTableBody(): array + /** + * Generate the structure of table body. (
) + * + * @param string $type "$product" or "$task" + * @return array + */ + public function buildTableBody(string $type): array { $elements = []; - $items = $this->transformLineItems($this->entity->line_items); + $items = $this->transformLineItems($this->entity->line_items, $type); if (count($items) == 0) { return []; } + info($this->context); + foreach ($items as $row) { $element = ['element' => 'tr', 'elements' => []]; if ( - isset($this->context['products']) && - !empty($this->context['products']) && - !is_null($this->context['products']) + array_key_exists($type, $this->context) && + !empty($this->context[$type]) && + !is_null($this->context[$type]) ) { $document = new DOMDocument(); - $document->loadHTML($this->context['products'], LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); + $document->loadHTML($this->context[$type], LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); $td = $document->getElementsByTagName('tr')->item(0); @@ -246,8 +298,20 @@ class Design extends BaseDesign } } } else { - foreach ($this->context['pdf_variables']["{$this->type}_columns"] as $key => $cell) { - $element['elements'][] = ['element' => 'td', 'content' => $row[$cell]]; + $_type = Str::startsWith($type, '$') ? ltrim($type, '$') : $type; + + foreach ($this->context['pdf_variables']["{$_type}_columns"] as $key => $cell) { + // We want to keep aliases like these: + // $task.cost => $task.rate + // $task.quantity => $task.hours + + if ($cell == '$task.rate') { + $element['elements'][] = ['element' => 'td', 'content' => $row['$task.cost']]; + } else if ($cell == '$task.hours') { + $element['elements'][] = ['element' => 'td', 'content' => $row['$task.quantity']]; + } else { + $element['elements'][] = ['element' => 'td', 'content' => $row[$cell]]; + } } } diff --git a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php index 5c9afc2670c2..7e2e98f0868c 100644 --- a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php +++ b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php @@ -94,35 +94,52 @@ trait DesignHelpers * * Logic below will help us calculate that & inject the result in the * global state of the $context (design state). - * + * + * @param string $type "product" or "task" * @return void */ - public function processTaxColumns(): void + public function processTaxColumns(string $type): void { - if (in_array('$product.tax', (array) $this->context['pdf_variables']['product_columns'])) { - $line_items = collect($this->entity->line_items); + if ($type == 'product') { + $type_id = 1; + } + + if ($type == 'task') { + $type_id = 2; + } + + // At the moment we pass "task" or "product" as type. + // However, "pdf_variables" contains "$task.tax" or "$product.tax" <-- Notice the dollar sign. + // This sprintf() will help us convert "task" or "product" into "$task" or "$product" without + // evaluating the variable. + + if (in_array(sprintf('%s%s.tax', '$', $type), (array) $this->context['pdf_variables']["{$type}_columns"])) { + $line_items = collect($this->entity->line_items)->filter(function ($item) use ($type_id) { + return $item->type_id = $type_id; + }); + + $tax1 = $line_items->where('tax_name1', '<>', '')->where('type_id', $type_id)->count(); + $tax2 = $line_items->where('tax_name2', '<>', '')->where('type_id', $type_id)->count(); + $tax3 = $line_items->where('tax_name3', '<>', '')->where('type_id', $type_id)->count(); - $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'); + array_push($taxes, sprintf('%s%s.tax_rate1', '$', $type)); } if ($tax2 > 0) { - array_push($taxes, '$product.tax_rate2'); + array_push($taxes, sprintf('%s%s.tax_rate2', '$', $type)); } if ($tax3 > 0) { - array_push($taxes, '$product.tax_rate3'); + array_push($taxes, sprintf('%s%s.tax_rate3', '$', $type)); } - $key = array_search('$product.tax', $this->context['pdf_variables']['product_columns'], true); + $key = array_search(sprintf('%s%s.tax', '$', $type), $this->context['pdf_variables']["{$type}_columns"], true); if ($key) { - array_splice($this->context['pdf_variables']['product_columns'], $key, 1, $taxes); + array_splice($this->context['pdf_variables']["{$type}_columns"], $key, 1, $taxes); } } } diff --git a/app/Utils/PhantomJS/Phantom.php b/app/Utils/PhantomJS/Phantom.php index 5dcd14d330c8..9c67bac1a6a4 100644 --- a/app/Utils/PhantomJS/Phantom.php +++ b/app/Utils/PhantomJS/Phantom.php @@ -117,7 +117,7 @@ class Phantom 'client' => $this->entity->client, 'entity' => $this->entity, 'pdf_variables' => (array) $this->entity->company->settings->pdf_variables, - 'products' => $design->design->product, + '$product' => $design->design->product, ]), 'variables' => $html->generateLabelsAndValues(), 'options' => [ diff --git a/tests/Integration/HtmlGenerationTest.php b/tests/Integration/HtmlGenerationTest.php index b8085eef52bc..1871425d3e85 100644 --- a/tests/Integration/HtmlGenerationTest.php +++ b/tests/Integration/HtmlGenerationTest.php @@ -80,7 +80,7 @@ class HtmlGenerationTest extends TestCase 'client' => $entity->client, 'entity' => $entity, 'pdf_variables' => (array) $entity->company->settings->pdf_variables, - 'products' => $design->design->product, + '$product' => $design->design->product, ]), 'variables' => $html->generateLabelsAndValues(), 'options' => [