mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-10-25 23:02:52 -04: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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user