mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-05 07:14:37 -04:00
Alpha testing on tasks:
- Change 'products' to '$product' with design within: CreateEntityPdf, ActivityRepository, HtmlGenerationTest, Phantom - New 'task-table' element in the Services\PdfMaker\Design.php - buildTableHeader & buildTableBody are now more generic - processTaxColumns() now requires $type to be specified
This commit is contained in:
parent
a01c57bd61
commit
5c2bfaa8ce
@ -139,7 +139,7 @@ class CreateEntityPdf implements ShouldQueue
|
|||||||
'client' => $this->entity->client,
|
'client' => $this->entity->client,
|
||||||
'entity' => $this->entity,
|
'entity' => $this->entity,
|
||||||
'pdf_variables' => (array) $this->entity->company->settings->pdf_variables,
|
'pdf_variables' => (array) $this->entity->company->settings->pdf_variables,
|
||||||
'products' => $design->design->product,
|
'$product' => $design->design->product,
|
||||||
]),
|
]),
|
||||||
'variables' => $html->generateLabelsAndValues(),
|
'variables' => $html->generateLabelsAndValues(),
|
||||||
'options' => [
|
'options' => [
|
||||||
|
@ -133,7 +133,7 @@ class ActivityRepository extends BaseRepository
|
|||||||
'client' => $entity->client,
|
'client' => $entity->client,
|
||||||
'entity' => $entity,
|
'entity' => $entity,
|
||||||
'pdf_variables' => (array) $entity->company->settings->pdf_variables,
|
'pdf_variables' => (array) $entity->company->settings->pdf_variables,
|
||||||
'products' => $design->design->product,
|
'$product' => $design->design->product,
|
||||||
]),
|
]),
|
||||||
'variables' => $html->generateLabelsAndValues(),
|
'variables' => $html->generateLabelsAndValues(),
|
||||||
'options' => [
|
'options' => [
|
||||||
|
@ -106,6 +106,10 @@ class Design extends BaseDesign
|
|||||||
'id' => 'product-table',
|
'id' => 'product-table',
|
||||||
'elements' => $this->productTable(),
|
'elements' => $this->productTable(),
|
||||||
],
|
],
|
||||||
|
'task-table' => [
|
||||||
|
'id' => 'task-table',
|
||||||
|
'elements' => $this->taskTable(),
|
||||||
|
],
|
||||||
'table-totals' => [
|
'table-totals' => [
|
||||||
'id' => 'table-totals',
|
'id' => 'table-totals',
|
||||||
'elements' => $this->tableTotals(),
|
'elements' => $this->tableTotals(),
|
||||||
@ -188,47 +192,95 @@ class Design extends BaseDesign
|
|||||||
return $elements;
|
return $elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent method for building products table.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function productTable(): 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 [
|
return [
|
||||||
['element' => 'thead', 'elements' => $this->buildTableHeader()],
|
['element' => 'thead', 'elements' => $this->buildTableHeader('product')],
|
||||||
['element' => 'tbody', 'elements' => $this->buildTableBody()],
|
['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. (<thead/>)
|
||||||
|
*
|
||||||
|
* @param string $type "product" or "task"
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function buildTableHeader(string $type): array
|
||||||
|
{
|
||||||
|
$this->processTaxColumns($type);
|
||||||
|
|
||||||
$elements = [];
|
$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'];
|
$elements[] = ['element' => 'th', 'content' => $column . '_label'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $elements;
|
return $elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildTableBody(): array
|
/**
|
||||||
|
* Generate the structure of table body. (<tbody/>)
|
||||||
|
*
|
||||||
|
* @param string $type "$product" or "$task"
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function buildTableBody(string $type): array
|
||||||
{
|
{
|
||||||
$elements = [];
|
$elements = [];
|
||||||
|
|
||||||
$items = $this->transformLineItems($this->entity->line_items);
|
$items = $this->transformLineItems($this->entity->line_items, $type);
|
||||||
|
|
||||||
if (count($items) == 0) {
|
if (count($items) == 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info($this->context);
|
||||||
|
|
||||||
foreach ($items as $row) {
|
foreach ($items as $row) {
|
||||||
$element = ['element' => 'tr', 'elements' => []];
|
$element = ['element' => 'tr', 'elements' => []];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isset($this->context['products']) &&
|
array_key_exists($type, $this->context) &&
|
||||||
!empty($this->context['products']) &&
|
!empty($this->context[$type]) &&
|
||||||
!is_null($this->context['products'])
|
!is_null($this->context[$type])
|
||||||
) {
|
) {
|
||||||
$document = new DOMDocument();
|
$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);
|
$td = $document->getElementsByTagName('tr')->item(0);
|
||||||
|
|
||||||
@ -246,10 +298,22 @@ class Design extends BaseDesign
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
foreach ($this->context['pdf_variables']["{$this->type}_columns"] as $key => $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]];
|
$element['elements'][] = ['element' => 'td', 'content' => $row[$cell]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$elements[] = $element;
|
$elements[] = $element;
|
||||||
}
|
}
|
||||||
|
@ -95,34 +95,51 @@ trait DesignHelpers
|
|||||||
* Logic below will help us calculate that & inject the result in the
|
* Logic below will help us calculate that & inject the result in the
|
||||||
* global state of the $context (design state).
|
* global state of the $context (design state).
|
||||||
*
|
*
|
||||||
|
* @param string $type "product" or "task"
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function processTaxColumns(): void
|
public function processTaxColumns(string $type): void
|
||||||
{
|
{
|
||||||
if (in_array('$product.tax', (array) $this->context['pdf_variables']['product_columns'])) {
|
if ($type == 'product') {
|
||||||
$line_items = collect($this->entity->line_items);
|
$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 = [];
|
$taxes = [];
|
||||||
|
|
||||||
if ($tax1 > 0) {
|
if ($tax1 > 0) {
|
||||||
array_push($taxes, '$product.tax_rate1');
|
array_push($taxes, sprintf('%s%s.tax_rate1', '$', $type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tax2 > 0) {
|
if ($tax2 > 0) {
|
||||||
array_push($taxes, '$product.tax_rate2');
|
array_push($taxes, sprintf('%s%s.tax_rate2', '$', $type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tax3 > 0) {
|
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) {
|
if ($key) {
|
||||||
array_splice($this->context['pdf_variables']['product_columns'], $key, 1, $taxes);
|
array_splice($this->context['pdf_variables']["{$type}_columns"], $key, 1, $taxes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ class Phantom
|
|||||||
'client' => $this->entity->client,
|
'client' => $this->entity->client,
|
||||||
'entity' => $this->entity,
|
'entity' => $this->entity,
|
||||||
'pdf_variables' => (array) $this->entity->company->settings->pdf_variables,
|
'pdf_variables' => (array) $this->entity->company->settings->pdf_variables,
|
||||||
'products' => $design->design->product,
|
'$product' => $design->design->product,
|
||||||
]),
|
]),
|
||||||
'variables' => $html->generateLabelsAndValues(),
|
'variables' => $html->generateLabelsAndValues(),
|
||||||
'options' => [
|
'options' => [
|
||||||
|
@ -80,7 +80,7 @@ class HtmlGenerationTest extends TestCase
|
|||||||
'client' => $entity->client,
|
'client' => $entity->client,
|
||||||
'entity' => $entity,
|
'entity' => $entity,
|
||||||
'pdf_variables' => (array) $entity->company->settings->pdf_variables,
|
'pdf_variables' => (array) $entity->company->settings->pdf_variables,
|
||||||
'products' => $design->design->product,
|
'$product' => $design->design->product,
|
||||||
]),
|
]),
|
||||||
'variables' => $html->generateLabelsAndValues(),
|
'variables' => $html->generateLabelsAndValues(),
|
||||||
'options' => [
|
'options' => [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user