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:
parent
ea07174df6
commit
e60bcf2d23
@ -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();
|
||||
|
@ -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 ?: '';
|
||||
}
|
||||
}
|
||||
|
@ -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 : '',
|
||||
|
@ -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 . '%';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user