1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-05 18:52:44 +01:00

Dynamic invoice tables for PDF generation

This commit is contained in:
David Bomba 2019-09-04 09:16:23 +10:00
parent ea07174df6
commit e60bcf2d23
6 changed files with 102 additions and 344 deletions

View File

@ -45,7 +45,7 @@ class InvoiceItemCalc
public function process()
{
$this->line_total = $this->formatValue($this->item->cost, $this->settings->precision) * $this->formatValue($this->item->qty, $this->settings->precision);
$this->line_total = $this->formatValue($this->item->cost, $this->settings->precision) * $this->formatValue($this->item->quantity, $this->settings->precision);
$this->setDiscount()
->calcTaxes();

View File

@ -28,7 +28,7 @@ class ClientPresenter extends EntityPresenter
public function primary_contact_name()
{
return $this->entity->primary_contact->first()->first_name . ' '. $this->entity->primary_contact->first()->last_name;;
return $this->entity->primary_contact->first() !== null ? $this->entity->primary_contact->first()->first_name . ' '. $this->entity->primary_contact->first()->last_name : 'No primary contact set';
}
public function address()
@ -73,6 +73,13 @@ class ClientPresenter extends EntityPresenter
return $str;
}
public function phone()
{
return $this->entity->phone ?: '';
}
public function website()
{
return $this->entity->website ?: '';
}
}

View File

@ -23,7 +23,7 @@ class InvoiceItemTransformer extends EntityTransformer
'archived_at' => $item->deleted_at,
'notes' => $item->notes,
'cost' => (float) $item->cost,
'qty' => (float) ($item->qty ?: 0.0),
'quantity' => (float) ($item->quantity ?: 0.0),
'tax_name1' => $item->tax_name1 ? $item->tax_name1 : '',
'tax_rate1' => (float) ($item->tax_rate1 ?: 0.0),
'tax_name2' => $item->tax_name2 ? $item->tax_name2 : '',

View File

@ -20,6 +20,24 @@ use Illuminate\Support\Facades\Log;
*/
trait MakesInvoiceValues
{
private static $master_columns = [
'date',
'discount',
'product_key',
'notes',
'cost',
'quantity',
'tax_name1',
'tax_name2',
'line_total',
'custom_label1',
'custom_label2',
'custom_label3',
'custom_label4',
];
private static $labels = [
'invoice',
'invoice_date',
@ -115,7 +133,7 @@ trait MakesInvoiceValues
$data = [];
foreach(self::$labels as $label)
$data[][$label . '_label'] = ctrans('texts'.$label);
$data[$label . '_label'] = ctrans('texts.'.$label);
return $data;
}
@ -177,8 +195,8 @@ trait MakesInvoiceValues
$data['email'] = isset($this->client->primary_contact()->first()->email) ?: 'no primary contact set';
$data['contact_name'] = $this->client->present()->primary_contact_name();
$data['company_name'] = $this->company->name;
$data['website'] = $this->client->website;
$data['phone'] = $this->client->primary_contact->first()->phone;
$data['website'] = $this->client->present()->website();
$data['phone'] = $this->client->present()->phone();
//$data['blank'] = ;
//$data['surcharge'] = ;
/*
@ -224,45 +242,82 @@ trait MakesInvoiceValues
*
* @return string[HTML string
*/
public function table(array $columns) :string
public function table(array $columns) :?string
{
$data = '<table class="table table-hover table-striped">';
$data .= '<thead><tr class="heading">';
foreach($columns as $column)
$data .= '<td>' . ctrans('texts.column') . '</td>';
$column_headers = $this->transformColumnsForHeader($columns);
foreach($column_headers as $column)
$data .= '<td>' . ctrans('texts.'.$column.'') . '</td>';
$data .= '</tr></thead>';
$columns = $this->transformColumns($columns);
$columns = $this->transformColumnsForLineItems($columns);
$items = $this->transformLineItems($this->line_items);
foreach($items as $item)
{
$data .= '<tr class="item">';
foreach($columns as $column)
$data .= '<td>'. $item->{$column} . '</td>';
$data .= '<tr class="item">';
$data .= '</tr>';
foreach($columns as $column)
{
$data .= '<td>'. $item->{$column} . '</td>';
}
$data .= '</tr>';
}
$data .= '</table>';
return $data;
}
/**
*
* Transform the column headers into translated header values
*
* @param array $columns The column header values
* @return array The new column header variables
*/
private function transformColumnsForHeader(array $columns) :array
{
$columns = array_intersect(self::$master_columns, $columns);
return str_replace([
'tax_name1',
'tax_name2'
],
[
'tax',
'tax',
],
$columns);
}
/**
*
* Transform the column headers into invoice variables
*
* @param array $columns The column header values
* @return array The invoice variables
*/
private function transformColumns(array $columns) :array
private function transformColumnsForLineItems(array $columns) :array
{
/* Removes any invalid columns the user has entered. */
$columns = array_intersect(self::$master_columns, $columns);
return str_replace([
'custom_invoice_label1',
'custom_invoice_label2',
@ -294,18 +349,18 @@ trait MakesInvoiceValues
foreach($items as $item)
{
$item->cost = Number::formatMoney($item->cost, $this->client->currency(), $this->client->country, $this->client->getMergedSettings);
$item->line_total = Number::formatMoney($item->line_total, $this->client->currency(), $this->client->country, $this->client->getMergedSettings);
$item->cost = Number::formatMoney($item->cost, $this->client->currency(), $this->client->country, $this->client->getMergedSettings());
$item->line_total = Number::formatMoney($item->line_total, $this->client->currency(), $this->client->country, $this->client->getMergedSettings());
if(isset($item->discount) && $item->discount > 0)
{
if($item->is_amount_discount)
$item->discount = Number::formatMoney($item->discount, $this->client->currency(), $this->client->country, $this->client->getMergedSettings);
$item->discount = Number::formatMoney($item->discount, $this->client->currency(), $this->client->country, $this->client->getMergedSettings());
else
$item->discount = $item->discount . '%';
}
}

View File

@ -115,9 +115,9 @@
</td>
<td>
Invoice #: {{ $invoice->invoice_number }}<br>
Created: {{ $invoice->invoice_date }}<br>
Due: {{ $invoice->due_date }}
{{$invoice_number_label}}: {{ $invoice->invoice_number }}<br>
{{$invoice_date_label}}: {{ $invoice->invoice_date }}<br>
{{$invoice_due_date_label}}: {{ $invoice->due_date }}
</td>
</tr>
</table>
@ -129,33 +129,21 @@
<table>
<tr>
<td>
Sparksuite, Inc.<br>
12345 Sunny Road<br>
Sunnyville, CA 12345
{{$client_name}}<br>
{{$address1}}<br>
{{$address2}}<br>
{{$city_state_postal}}<br>
{{$country}}<br>
{{$vat_number}}<br>
</td>
<td>
Acme Corp.<br>
John Doe<br>
john@example.com
{{$company_name}}<br>
{{$phone}}<br>
{{$email}}<br>
</td>
<td>
{{$client_name}}<br>
{{$address1}}<br>
{{$address2}}<br>
{{$id_number}}<br>
{{$vat_number}}<br>
{{$city_state_postal}}<br>
{{$postal_city_state}}<br>
{{$country}}<br>
{{$email}}<br>
{{$contact_name}}<br>
{{$company_name}}<br>
{{$website}}<br>
{{$phone}}<br>
{{$terms}}<br>
</td>
</tr>
</table>
</td>
@ -167,7 +155,6 @@
date
discount
product_key
item
notes
cost
quantity
@ -179,301 +166,10 @@
custom_label3 ( will show as the following parameter as its value -> custom_invoice_value3 )
custom_label4 ( will show as the following parameter as its value -> custom_invoice_value4 )
--}}
{{ $invoice->table(['item','description','cost','quantity', 'tax_name1', 'line_total']) }}
{!! $invoice->table(['product_key', 'notes', 'cost','quantity', 'line_total']) !!}
<table cellpadding="0" cellspacing="0">
<thead>
<tr class="heading">
<td>
Item
</td>
<td>
Price
</td>
</tr>
</thead>
<tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr>
<tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr> <tr class="item">
<td>
Website design
</td>
<td>
$300.00
</td>
</tr>
<tr class="item">
<td>
Hosting (3 months)
</td>
<td>
$75.00
</td>
</tr>
<tr class="item last">
<td>
Domain name (1 year)
</td>
<td>
$10.00
</td>
</tr>
<table>
<tr class="total">
<td></td>

View File

@ -46,8 +46,8 @@ class InvoiceTest extends TestCase
$data = [
'first_name' => $this->faker->firstName,
'last_name' => $this->faker->lastName,
'name' => $this->faker->company,
'email' => $this->faker->unique()->safeEmail,
'name' => $this->faker->company,
'email' => $this->faker->unique()->safeEmail,
'password' => 'ALongAndBrilliantPassword123',
'_token' => csrf_token(),
'privacy_policy' => 1,