mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-05 18:52:44 +01:00
Design Changes (#3504)
* Fixes for tests * Working on PDF tables * Fixes for null values in designs * Refactoring entity variables for PDF * Fixes for pdf variables * Minor fixes for designs * Working on variable replacement for tables * Refactoring designs * Refactoring designs * Refactoring design implementation * Working on refactoring designs * Serve tailwind locally * Design changes
This commit is contained in:
parent
aad9f81e93
commit
0e12b63c95
61
app/Console/Commands/DesignUpdate.php
Normal file
61
app/Console/Commands/DesignUpdate.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Design;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class DesignUpdate extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'ninja:design-update';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Update the system designs when changes are made.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
foreach(Design::whereIsCustom(false)->get() as $design){
|
||||
|
||||
$class = 'App\Designs\\'.$design->name;
|
||||
$invoice_design = new $class();
|
||||
|
||||
$design_object = new \stdClass;
|
||||
$design_object->includes = $invoice_design->includes() ?: '';
|
||||
$design_object->header = $invoice_design->header() ?: '';
|
||||
$design_object->body = $invoice_design->body() ?: '';
|
||||
$design_object->product = $invoice_design->product() ?: '';
|
||||
$design_object->task = $invoice_design->task() ?: '';
|
||||
$design_object->footer = $invoice_design->footer() ?: '';
|
||||
|
||||
$design->design = $design_object;
|
||||
$design->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -55,7 +55,7 @@ class CompanySettings extends BaseSettings {
|
||||
|
||||
public $default_task_rate = 0;
|
||||
|
||||
public $payment_terms = 1;
|
||||
public $payment_terms = -1;
|
||||
public $send_reminders = false;
|
||||
|
||||
public $custom_message_dashboard = '';
|
||||
@ -431,23 +431,6 @@ class CompanySettings extends BaseSettings {
|
||||
$data->translations = (object) [];
|
||||
$data->pdf_variables = (object) self::getEntityVariableDefaults();
|
||||
|
||||
// $data->email_subject_invoice = EmailTemplateDefaults::emailInvoiceSubject();
|
||||
// $data->email_template_invoice = EmailTemplateDefaults:: emailInvoiceTemplate();
|
||||
// $data->email_subject_quote = EmailTemplateDefaults::emailQuoteSubject();
|
||||
// $data->email_subject_payment = EmailTemplateDefaults::emailPaymentSubject();
|
||||
// $data->email_subject_statement = EmailTemplateDefaults::emailStatementSubject();
|
||||
// $data->email_template_quote = EmailTemplateDefaults::emailQuoteTemplate();
|
||||
// $data->email_template_payment = EmailTemplateDefaults::emailPaymentTemplate();
|
||||
// $data->email_template_statement = EmailTemplateDefaults::emailStatementTemplate();
|
||||
// $data->email_subject_reminder1 = EmailTemplateDefaults::emailReminder1Subject();
|
||||
// $data->email_subject_reminder2 = EmailTemplateDefaults::emailReminder2Subject();
|
||||
// $data->email_subject_reminder3 = EmailTemplateDefaults::emailReminder3Subject();
|
||||
// $data->email_subject_reminder_endless = EmailTemplateDefaults::emailReminderEndlessSubject();
|
||||
// $data->email_template_reminder1 = EmailTemplateDefaults::emailReminder1Template();
|
||||
// $data->email_template_reminder2 = EmailTemplateDefaults::emailReminder2Template();
|
||||
// $data->email_template_reminder3 = EmailTemplateDefaults::emailReminder3Template();
|
||||
// $data->email_template_reminder_endless = EmailTemplateDefaults::emailReminderEndlessTemplate();
|
||||
|
||||
return self::setCasts($data, self::$casts);
|
||||
}
|
||||
|
||||
@ -482,70 +465,70 @@ class CompanySettings extends BaseSettings {
|
||||
|
||||
$variables = [
|
||||
'client_details' => [
|
||||
'name',
|
||||
'id_number',
|
||||
'vat_number',
|
||||
'address1',
|
||||
'address2',
|
||||
'city_state_postal',
|
||||
'country',
|
||||
'email',
|
||||
'$client.name' => ctrans('texts.client_name'),
|
||||
'$client.id_number' => ctrans('texts.id_number'),
|
||||
'$client.vat_number' => ctrans('texts.vat_number'),
|
||||
'$client.address1' => ctrans('texts.address1'),
|
||||
'$client.address2' => ctrans('texts.address2'),
|
||||
'$client.city_state_postal' => ctrans('texts.city_state_postal'),
|
||||
'$client.country' => ctrans('texts.country'),
|
||||
'$client.email' => ctrans('texts.email'),
|
||||
],
|
||||
'company_details' => [
|
||||
'company_name',
|
||||
'id_number',
|
||||
'vat_number',
|
||||
'website',
|
||||
'email',
|
||||
'phone',
|
||||
'$company.company_name' => ctrans('texts.company_name'),
|
||||
'$company.id_number' => ctrans('texts.id_number'),
|
||||
'$company.vat_number' => ctrans('texts.vat_number'),
|
||||
'$company.website' => ctrans('texts.website'),
|
||||
'$company.email' => ctrans('texts.email'),
|
||||
'$company.phone' => ctrans('texts.phone'),
|
||||
],
|
||||
'company_address' => [
|
||||
'address1',
|
||||
'address2',
|
||||
'city_state_postal',
|
||||
'country',
|
||||
'$company.address1' => ctrans('texts.address1'),
|
||||
'$company.address2' => ctrans('texts.address2'),
|
||||
'$company.city_state_postal' => ctrans('texts.city_state_postal'),
|
||||
'$company.country' => ctrans('texts.country'),
|
||||
],
|
||||
'invoice_details' => [
|
||||
'invoice_number',
|
||||
'po_number',
|
||||
'date',
|
||||
'due_date',
|
||||
'balance_due',
|
||||
'invoice_total',
|
||||
'$invoice.invoice_number' => ctrans('texts.invoice_number'),
|
||||
'$invoice.po_number' => ctrans('texts.po_number'),
|
||||
'$invoice.invoice_date' => ctrans('texts.invoice_date'),
|
||||
'$invoice.due_date' => ctrans('texts.due_date'),
|
||||
'$invoice.balance_due' => ctrans('texts.balance_due'),
|
||||
'$invoice.invoice_total' => ctrans('texts.invoice_total'),
|
||||
],
|
||||
'quote_details' => [
|
||||
'quote_number',
|
||||
'po_number',
|
||||
'date',
|
||||
'valid_until',
|
||||
'balance_due',
|
||||
'quote_total',
|
||||
'$quote.quote_number' => ctrans('texts.quote_number'),
|
||||
'$quote.po_number' => ctrans('texts.po_number'),
|
||||
'$quote.quote_date' => ctrans('texts.quote_date'),
|
||||
'$quote.valid_until' => ctrans('texts.valid_until'),
|
||||
'$quote.balance_due' => ctrans('texts.balance_due'),
|
||||
'$quote.quote_total' => ctrans('texts.quote_total'),
|
||||
],
|
||||
'credit_details' => [
|
||||
'credit_number',
|
||||
'po_number',
|
||||
'date',
|
||||
'credit_balance',
|
||||
'credit_amount',
|
||||
'$credit.credit_number' => ctrans('texts.credit_number'),
|
||||
'$credit.po_number' => ctrans('texts.po_number'),
|
||||
'$credit.credit_date' => ctrans('texts.credit_date'),
|
||||
'$credit.credit_balance' => ctrans('texts.credit_balance'),
|
||||
'$credit.credit_amount' => ctrans('texts.credit_amount'),
|
||||
],
|
||||
'product_columns' => [
|
||||
'product_key',
|
||||
'notes',
|
||||
'cost',
|
||||
'quantity',
|
||||
'discount',
|
||||
'tax_name1',
|
||||
'line_total'
|
||||
'$product.product_key' => ctrans('texts.product_key'),
|
||||
'$product.notes' => ctrans('texts.notes'),
|
||||
'$product.cost' => ctrans('texts.cost'),
|
||||
'$product.quantity' => ctrans('texts.quantity'),
|
||||
'$product.discount' => ctrans('texts.discount'),
|
||||
'$product.tax_name1' => ctrans('texts.tax_name1'),
|
||||
'$product.line_total' => ctrans('texts.line_total'),
|
||||
],
|
||||
'task_columns' => [
|
||||
'product_key',
|
||||
'notes',
|
||||
'cost',
|
||||
'quantity',
|
||||
'discount',
|
||||
'tax_name1',
|
||||
'line_total'
|
||||
],
|
||||
'$task.product_key' => ctrans('texts.product_key'),
|
||||
'$task.notes' => ctrans('texts.notes'),
|
||||
'$task.cost' => ctrans('texts.cost'),
|
||||
'$task.quantity' => ctrans('texts.quantity'),
|
||||
'$task.discount' => ctrans('texts.discount'),
|
||||
'$task.tax_name1' => ctrans('texts.tax_name1'),
|
||||
'$task.line_total' => ctrans('texts.line_total'),
|
||||
],
|
||||
];
|
||||
|
||||
return json_decode(json_encode($variables));
|
||||
|
@ -24,5 +24,4 @@ abstract class AbstractDesign
|
||||
abstract public function task();
|
||||
|
||||
abstract public function footer();
|
||||
|
||||
}
|
@ -25,7 +25,7 @@ class Bold extends AbstractDesign
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link href="$app_url/css/tailwind-1.2.0.css" rel="stylesheet">
|
||||
<style>
|
||||
body {font-size:90%}
|
||||
@page: not(:first-of-type) { size: auto; margin-top: 5mm; }
|
||||
@ -78,16 +78,14 @@ class Bold extends AbstractDesign
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
|
||||
}
|
||||
|
||||
public function task() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function task_table() {
|
||||
return '
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left">
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left">
|
||||
$task_table_header
|
||||
@ -97,26 +95,17 @@ class Bold extends AbstractDesign
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
|
||||
}
|
||||
|
||||
public function task() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_table() {
|
||||
|
||||
return '
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left">
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
}
|
||||
|
||||
public function footer() {
|
||||
|
||||
return '
|
||||
@ -126,10 +115,10 @@ class Bold extends AbstractDesign
|
||||
</div>
|
||||
<div class="w-1/2 flex">
|
||||
<div class="w-1/2 text-right flex flex-col">
|
||||
$total_tax_labels $line_tax_labels
|
||||
$subtotal_label $discount_label $total_tax_labels $line_tax_labels
|
||||
</div>
|
||||
<div class="w-1/2 text-right flex flex-col">
|
||||
$total_tax_values $line_tax_values
|
||||
$subtotal $discount $total_tax_values $line_tax_values
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -26,7 +26,7 @@ class Business extends AbstractDesign
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link href="$app_url/css/tailwind-1.2.0.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body { font-size:90% }
|
||||
@ -95,6 +95,22 @@ class Business extends AbstractDesign
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="w-full table-auto mt-20">
|
||||
<thead class="text-left">
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="w-full table-auto mt-20">
|
||||
<thead class="text-left">
|
||||
$task_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
|
||||
}
|
||||
@ -104,43 +120,11 @@ class Business extends AbstractDesign
|
||||
return '';
|
||||
}
|
||||
|
||||
public function task_table()
|
||||
{
|
||||
return '
|
||||
<table class="w-full table-auto mt-20">
|
||||
<thead class="text-left">
|
||||
<tr>
|
||||
$task_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_table()
|
||||
{
|
||||
return '
|
||||
<table class="w-full table-auto mt-20">
|
||||
<thead class="text-left">
|
||||
<tr>
|
||||
$product_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
|
||||
@ -154,10 +138,12 @@ class Business extends AbstractDesign
|
||||
<div class="w-1/3 flex flex-col">
|
||||
<div class="flex px-3 mt-2">
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount_label
|
||||
$total_tax_labels
|
||||
$line_tax_labels
|
||||
</section>
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount
|
||||
$total_tax_values
|
||||
$line_tax_values
|
||||
</section>
|
||||
|
@ -26,7 +26,7 @@ class Clean extends AbstractDesign
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link href="$app_url/css/tailwind-1.2.0.css" rel="stylesheet">
|
||||
<style>
|
||||
body {font-size:90%}
|
||||
@page
|
||||
@ -85,8 +85,23 @@ class Clean extends AbstractDesign
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-b border-gray-400"></div>
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left">
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left">
|
||||
$task_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
|
||||
}
|
||||
@ -96,42 +111,11 @@ class Clean extends AbstractDesign
|
||||
return '';
|
||||
}
|
||||
|
||||
public function task_table()
|
||||
{
|
||||
return '
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left">
|
||||
<tr>
|
||||
$task_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_table() {
|
||||
return '
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left">
|
||||
<tr>
|
||||
$product_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
}
|
||||
|
||||
public function footer() {
|
||||
|
||||
return '
|
||||
@ -141,10 +125,12 @@ class Clean extends AbstractDesign
|
||||
</div>
|
||||
<div class="w-1/2 flex">
|
||||
<div class="w-1/2 text-right flex flex-col">
|
||||
$discount_label
|
||||
$total_tax_labels
|
||||
$line_tax_labels
|
||||
</div>
|
||||
<div class="w-1/2 text-right flex flex-col">
|
||||
$discount
|
||||
$total_tax_values
|
||||
$line_tax_values
|
||||
</div>
|
||||
|
@ -24,14 +24,12 @@ class Creative extends AbstractDesign
|
||||
public function includes()
|
||||
{
|
||||
return '
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>$number</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link href="$app_url/css/tailwind-1.2.0.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
@ -53,7 +51,6 @@ class Creative extends AbstractDesign
|
||||
public function header() {
|
||||
|
||||
return '
|
||||
|
||||
<div class="py-16 mx-16">
|
||||
<div class="flex justify-between">
|
||||
<div class="w-2/3 flex">
|
||||
@ -90,50 +87,35 @@ class Creative extends AbstractDesign
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function task() {
|
||||
}
|
||||
|
||||
public function task_table()
|
||||
{
|
||||
return '
|
||||
<table class="w-full table-auto mt-12 border-t-4 border-pink-700 bg-white">
|
||||
<table class="w-full table-auto mt-12 border-t-4 border-pink-700 bg-white">
|
||||
<thead class="text-left rounded-lg">
|
||||
<tr>
|
||||
$task_table_header
|
||||
</tr>
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
</table>
|
||||
<table class="w-full table-auto mt-12 border-t-4 border-pink-700 bg-white">
|
||||
<thead class="text-left rounded-lg">
|
||||
$task_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
}
|
||||
|
||||
public function task() {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_table() {
|
||||
|
||||
return '
|
||||
<table class="w-full table-auto mt-12 border-t-4 border-pink-700 bg-white">
|
||||
<thead class="text-left rounded-lg">
|
||||
<tr>
|
||||
$product_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function footer() {
|
||||
|
||||
return '
|
||||
@ -141,20 +123,20 @@ class Creative extends AbstractDesign
|
||||
<div class="flex items-center justify-between mt-2 px-4 pb-4">
|
||||
<div class="w-1/2">
|
||||
<div class="flex flex-col">
|
||||
<p>Wedding photos will be available approximately 1 month after the wedding date. Thank you for your patience!</p>
|
||||
<p>$entity.public_notes</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-1/3 flex flex-col">
|
||||
<div class="flex px-3 mt-2">
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
<span>Subtotal</span>
|
||||
<span>Discount</span>
|
||||
<span>Paid To Date</span>
|
||||
<span>$subtotal_label</span>
|
||||
<span>$discount_label</span>
|
||||
<span>$paid_to_date_label</span>
|
||||
</section>
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
<span>$0</span>
|
||||
<span>$0</span>
|
||||
<span>$0</span>
|
||||
<span>$subtotal</span>
|
||||
<span>$discount</span>
|
||||
<span>$paid_to_date</span>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
@ -162,7 +144,7 @@ class Creative extends AbstractDesign
|
||||
<div class="flex items-center justify-between mt-4 pb-4 px-4">
|
||||
<div class="w-1/2">
|
||||
<div class="flex flex-col">
|
||||
<p class="font-semibold">Terms</p>
|
||||
<p class="font-semibold">$terms_label</p>
|
||||
<p>N21</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -170,8 +152,8 @@ class Creative extends AbstractDesign
|
||||
</div>
|
||||
|
||||
<div class="w-full flex justify-end mt-4">
|
||||
<p>Balance Due</p>
|
||||
<p class="ml-8 text-pink-700 font-semibold">$5,280.00</p>
|
||||
<p>$balance_due_label</p>
|
||||
<p class="ml-8 text-pink-700 font-semibold">$balance</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -42,50 +42,6 @@ class Custom extends AbstractDesign
|
||||
$this->task = $design->design->task;
|
||||
|
||||
$this->footer = $design->design->footer;
|
||||
|
||||
}
|
||||
|
||||
public function name()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function includes()
|
||||
{
|
||||
return $this->includes;
|
||||
}
|
||||
|
||||
public function header()
|
||||
{
|
||||
|
||||
return $this->header;
|
||||
|
||||
}
|
||||
|
||||
public function body()
|
||||
{
|
||||
|
||||
return $this->body;
|
||||
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
|
||||
return $this->product;
|
||||
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
|
||||
return $this->footer;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -57,7 +57,7 @@ class Designer {
|
||||
|
||||
$this->design = $design->design;
|
||||
|
||||
$this->input_variables = (array) $input_variables;
|
||||
$this->input_variables = json_decode(json_encode($input_variables),1);
|
||||
|
||||
$this->entity_string = $entity_string;
|
||||
|
||||
@ -76,7 +76,6 @@ class Designer {
|
||||
->setDesign($this->getSection('includes'))
|
||||
->setDesign($this->getSection('header'))
|
||||
->setDesign($this->getSection('body'))
|
||||
->setDesign($this->getProductTable($this->entity))
|
||||
->setDesign($this->getSection('footer'));
|
||||
|
||||
return $this;
|
||||
@ -86,7 +85,7 @@ class Designer {
|
||||
public function init()
|
||||
{
|
||||
$this->setHtml()
|
||||
->exportVariables();
|
||||
->exportVariables();
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -122,32 +121,6 @@ class Designer {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProductTable():string
|
||||
{
|
||||
|
||||
$table_header = $this->entity->table_header($this->input_variables['product_columns']);
|
||||
$table_body = $this->entity->table_body($this->input_variables['product_columns']);
|
||||
|
||||
$data = str_replace('$product_table_header', $table_header, $this->getSection('product'));
|
||||
$data = str_replace('$product_table_body', $table_body, $data);
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
public function getTaskTable():string
|
||||
{
|
||||
|
||||
$table_header = $this->entity->table_header($this->input_variables['task_columns']);
|
||||
$table_body = $this->entity->table_body($this->input_variables['task_columns']);
|
||||
|
||||
$data = str_replace('$task_table_header', $table_header, $this->getSection('task'));
|
||||
$data = str_replace('$task_table_body', $table_body, $data);
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
public function getHtml():string
|
||||
{
|
||||
return $this->html;
|
||||
@ -184,36 +157,48 @@ class Designer {
|
||||
{
|
||||
|
||||
$company = $this->entity->company;
|
||||
|
||||
$this->exported_variables['$client_details'] = $this->processVariables($this->processInputVariables($company, $this->input_variables['client_details']), $this->clientDetails($company));
|
||||
$this->exported_variables['$company_details'] = $this->processVariables($this->processInputVariables($company, $this->input_variables['company_details']), $this->companyDetails($company));
|
||||
$this->exported_variables['$company_address'] = $this->processVariables($this->processInputVariables($company, $this->input_variables['company_address']), $this->companyAddress($company));
|
||||
|
||||
$this->exported_variables['$app_url'] = $this->entity->generateAppUrl();
|
||||
$this->exported_variables['$client_details'] = $this->processVariables($this->input_variables['client_details'], $this->clientDetails($company));
|
||||
$this->exported_variables['$company_details'] = $this->processVariables($this->input_variables['company_details'], $this->companyDetails($company));
|
||||
$this->exported_variables['$company_address'] = $this->processVariables($this->input_variables['company_address'], $this->companyAddress($company));
|
||||
|
||||
if($this->entity_string == 'invoice')
|
||||
{
|
||||
$this->exported_variables['$entity_labels'] = $this->processLabels($this->processInputVariables($company, $this->input_variables['invoice_details']), $this->invoiceDetails($company));
|
||||
$this->exported_variables['$entity_details'] = $this->processVariables($this->processInputVariables($company, $this->input_variables['invoice_details']), $this->invoiceDetails($company));
|
||||
$this->exported_variables['$entity_labels'] = $this->processLabels($this->input_variables['invoice_details'], $this->invoiceDetails($company));
|
||||
$this->exported_variables['$entity_details'] = $this->processVariables($this->input_variables['invoice_details'], $this->invoiceDetails($company));
|
||||
}
|
||||
elseif($this->entity_string == 'credit')
|
||||
{
|
||||
$this->exported_variables['$entity_labels'] = $this->processLabels($this->processInputVariables($company, $this->input_variables['credit_details']), $this->creditDetails($company));
|
||||
$this->exported_variables['$entity_details'] = $this->processVariables($this->processInputVariables($company, $this->input_variables['credit_details']), $this->creditDetails($company));
|
||||
$this->exported_variables['$entity_labels'] = $this->processLabels($this->input_variables['credit_details'], $this->creditDetails($company));
|
||||
$this->exported_variables['$entity_details'] = $this->processVariables($this->input_variables['credit_details'], $this->creditDetails($company));
|
||||
}
|
||||
elseif($this->entity_string == 'quote')
|
||||
{
|
||||
$this->exported_variables['$entity_labels'] = $this->processLabels($this->processInputVariables($company, $this->input_variables['quote_details']), $this->quoteDetails($company));
|
||||
$this->exported_variables['$entity_details'] = $this->processVariables($this->processInputVariables($company, $this->input_variables['quote_details']), $this->quoteDetails($company));
|
||||
$this->exported_variables['$entity_labels'] = $this->processLabels($this->input_variables['quote_details'], $this->quoteDetails($company));
|
||||
$this->exported_variables['$entity_details'] = $this->processVariables($this->input_variables['quote_details'], $this->quoteDetails($company));
|
||||
}
|
||||
|
||||
$this->exported_variables['$product_table_header']= $this->entity->buildTableHeader($this->input_variables['product_columns']);
|
||||
$this->exported_variables['$product_table_body'] = $this->entity->buildTableBody($this->input_variables['product_columns'], $this->design->product, '$product');
|
||||
$this->exported_variables['$task_table_header'] = $this->entity->buildTableHeader($this->input_variables['task_columns']);
|
||||
$this->exported_variables['$task_table_body'] = $this->entity->buildTableBody($this->input_variables['task_columns'], $this->design->task, '$task');
|
||||
|
||||
if(strlen($this->exported_variables['$task_table_body']) == 0)
|
||||
$this->exported_variables['$task_table_header'] = '';
|
||||
|
||||
if(strlen($this->exported_variables['$product_table_body']) == 0)
|
||||
$this->exported_variables['$product_table_header'] = '';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function processVariables($input_variables, $variables):string
|
||||
{
|
||||
|
||||
$output = '';
|
||||
|
||||
foreach ($input_variables as $value)
|
||||
$output .= $variables[$value];
|
||||
foreach (array_keys($input_variables) as $value)
|
||||
$output .= $variables[$value];
|
||||
|
||||
return $output;
|
||||
|
||||
@ -221,12 +206,13 @@ class Designer {
|
||||
|
||||
private function processLabels($input_variables, $variables):string
|
||||
{
|
||||
|
||||
$output = '';
|
||||
|
||||
foreach ($input_variables as $value) {
|
||||
foreach (array_keys($input_variables) as $value) {
|
||||
|
||||
$tmp = str_replace("</span>", "_label</span>", $variables[$value]);
|
||||
|
||||
//$output .= $variables[$value];
|
||||
$output .= $tmp;
|
||||
}
|
||||
|
||||
@ -237,23 +223,23 @@ class Designer {
|
||||
{
|
||||
|
||||
$data = [
|
||||
'name' => '<p>$client.name</p>',
|
||||
'id_number' => '<p>$client.id_number</p>',
|
||||
'vat_number' => '<p>$client.vat_number</p>',
|
||||
'address1' => '<p>$client.address1</p>',
|
||||
'address2' => '<p>$client.address2</p>',
|
||||
'city_state_postal' => '<p>$client.city_state_postal</p>',
|
||||
'postal_city_state' => '<p>$client.postal_city_state</p>',
|
||||
'country' => '<p>$client.country</p>',
|
||||
'email' => '<p>$client.email</p>',
|
||||
'client1' => '<p>$client1</p>',
|
||||
'client2' => '<p>$client2</p>',
|
||||
'client3' => '<p>$client3</p>',
|
||||
'client4' => '<p>$client4</p>',
|
||||
'contact1' => '<p>$contact1</p>',
|
||||
'contact2' => '<p>$contact2</p>',
|
||||
'contact3' => '<p>$contact3</p>',
|
||||
'contact4' => '<p>$contact4</p>',
|
||||
'$client.name' => '<p>$client.name</p>',
|
||||
'$client.id_number' => '<p>$client.id_number</p>',
|
||||
'$client.vat_number' => '<p>$client.vat_number</p>',
|
||||
'$client.address1' => '<p>$client.address1</p>',
|
||||
'$client.address2' => '<p>$client.address2</p>',
|
||||
'$client.city_state_postal' => '<p>$client.city_state_postal</p>',
|
||||
'$client.postal_city_state' => '<p>$client.postal_city_state</p>',
|
||||
'$client.country' => '<p>$client.country</p>',
|
||||
'$client.email' => '<p>$client.email</p>',
|
||||
'$client.client1' => '<p>$client1</p>',
|
||||
'$client.client2' => '<p>$client2</p>',
|
||||
'$client.client3' => '<p>$client3</p>',
|
||||
'$client.client4' => '<p>$client4</p>',
|
||||
'$client.contact1' => '<p>$contact1</p>',
|
||||
'$client.contact2' => '<p>$contact2</p>',
|
||||
'$client.contact3' => '<p>$contact3</p>',
|
||||
'$client.contact4' => '<p>$contact4</p>',
|
||||
];
|
||||
|
||||
return $this->processCustomFields($company, $data);
|
||||
@ -263,16 +249,16 @@ class Designer {
|
||||
{
|
||||
|
||||
$data = [
|
||||
'company_name' => '<span>$company.company_name</span>',
|
||||
'id_number' => '<span>$company.id_number</span>',
|
||||
'vat_number' => '<span>$company.vat_number</span>',
|
||||
'website' => '<span>$company.website</span>',
|
||||
'email' => '<span>$company.email</span>',
|
||||
'phone' => '<span>$company.phone</span>',
|
||||
'company1' => '<span>$company1</span>',
|
||||
'company2' => '<span>$company2</span>',
|
||||
'company3' => '<span>$company3</span>',
|
||||
'company4' => '<span>$company4</span>',
|
||||
'$company.company_name' => '<span>$company.company_name</span>',
|
||||
'$company.id_number' => '<span>$company.id_number</span>',
|
||||
'$company.vat_number' => '<span>$company.vat_number</span>',
|
||||
'$company.website' => '<span>$company.website</span>',
|
||||
'$company.email' => '<span>$company.email</span>',
|
||||
'$company.phone' => '<span>$company.phone</span>',
|
||||
'$company.company1' => '<span>$company1</span>',
|
||||
'$company.company2' => '<span>$company2</span>',
|
||||
'$company.company3' => '<span>$company3</span>',
|
||||
'$company.company4' => '<span>$company4</span>',
|
||||
];
|
||||
|
||||
return $this->processCustomFields($company, $data);
|
||||
@ -283,15 +269,15 @@ class Designer {
|
||||
{
|
||||
|
||||
$data = [
|
||||
'address1' => '<span>$company.address1</span>',
|
||||
'address2' => '<span>$company.address1</span>',
|
||||
'city_state_postal' => '<span>$company.city_state_postal</span>',
|
||||
'postal_city_state' => '<span>$company.postal_city_state</span>',
|
||||
'country' => '<span>$company.country</span>',
|
||||
'company1' => '<span>$company1</span>',
|
||||
'company2' => '<span>$company2</span>',
|
||||
'company3' => '<span>$company3</span>',
|
||||
'company4' => '<span>$company4</span>',
|
||||
'$company.address1' => '<span>$company.address1</span>',
|
||||
'$company.address2' => '<span>$company.address2</span>',
|
||||
'$company.city_state_postal' => '<span>$company.city_state_postal</span>',
|
||||
'$company.postal_city_state' => '<span>$company.postal_city_state</span>',
|
||||
'$company.country' => '<span>$company.country</span>',
|
||||
'$company.company1' => '<span>$company1</span>',
|
||||
'$company.company2' => '<span>$company2</span>',
|
||||
'$company.company3' => '<span>$company3</span>',
|
||||
'$company.company4' => '<span>$company4</span>',
|
||||
];
|
||||
|
||||
return $this->processCustomFields($company, $data);
|
||||
@ -302,21 +288,21 @@ class Designer {
|
||||
{
|
||||
|
||||
$data = [
|
||||
'invoice_number' => '<span>$invoice_number</span>',
|
||||
'po_number' => '<span>$po_number</span>',
|
||||
'date' => '<span>$date</span>',
|
||||
'due_date' => '<span>$due_date</span>',
|
||||
'balance_due' => '<span>$balance_due</span>',
|
||||
'invoice_total' => '<span>$invoice_total</span>',
|
||||
'partial_due' => '<span>$partial_due</span>',
|
||||
'invoice1' => '<span>$invoice1</span>',
|
||||
'invoice2' => '<span>$invoice2</span>',
|
||||
'invoice3' => '<span>$invoice3</span>',
|
||||
'invoice4' => '<span>$invoice4</span>',
|
||||
'surcharge1' => '<span>$surcharge1</span>',
|
||||
'surcharge2' => '<span>$surcharge2</span>',
|
||||
'surcharge3' => '<span>$surcharge3</span>',
|
||||
'surcharge4' => '<span>$surcharge4</span>',
|
||||
'$invoice.invoice_number' => '<span>$invoice_number_label</span><span>$invoice_number</span>',
|
||||
'$invoice.po_number' => '<span>$po_number_label</span><span>$po_number</span>',
|
||||
'$invoice.invoice_date' => '<span>$invoice_date_label</span><span>$invoice_date</span>',
|
||||
'$invoice.due_date' => '<span>$due_date_label</span><span>$due_date</span>',
|
||||
'$invoice.balance_due' => '<span>$balance_due_label</span><span>$balance_due</span>',
|
||||
'$invoice.invoice_total' => '<span>$invoice_total_label</span><span>$invoice_total</span>',
|
||||
'$invoice.partial_due' => '<span>$partial_due_label</span><span>$partial_due</span>',
|
||||
'$invoice.invoice1' => '<span>$invoice1_label</span><span>$invoice1</span>',
|
||||
'$invoice.invoice2' => '<span>$invoice2_label</span><span>$invoice2</span>',
|
||||
'$invoice.invoice3' => '<span>$invoice3_label</span><span>$invoice3</span>',
|
||||
'$invoice.invoice4' => '<span>$invoice4_label</span><span>$invoice4</span>',
|
||||
'$invoice.surcharge1' => '<span>$surcharge1_label</span><span>$surcharge1</span>',
|
||||
'$invoice.surcharge2' => '<span>$surcharge2_label</span><span>$surcharge2</span>',
|
||||
'$invoice.surcharge3' => '<span>$surcharge3_label</span><span>$surcharge3</span>',
|
||||
'$invoice.surcharge4' => '<span>$surcharge4_label</span><span>$surcharge4</span>',
|
||||
];
|
||||
|
||||
return $this->processCustomFields($company, $data);
|
||||
@ -327,21 +313,21 @@ class Designer {
|
||||
{
|
||||
|
||||
$data = [
|
||||
'quote_number' => '<span>$quote_number</span>',
|
||||
'po_number' => '<span>$po_number</span>',
|
||||
'date' => '<span>$date</span>',
|
||||
'valid_until' => '<span>$valid_until</span>',
|
||||
'balance_due' => '<span>$balance_due</span>',
|
||||
'quote_total' => '<span>$quote_total</span>',
|
||||
'partial_due' => '<span>$partial_due</span>',
|
||||
'quote1' => '<span>$quote1</span>',
|
||||
'quote2' => '<span>$quote2</span>',
|
||||
'quote3' => '<span>$quote3</span>',
|
||||
'quote4' => '<span>$quote4</span>',
|
||||
'surcharge1' => '<span>$surcharge1</span>',
|
||||
'surcharge2' => '<span>$surcharge2</span>',
|
||||
'surcharge3' => '<span>$surcharge3</span>',
|
||||
'surcharge4' => '<span>$surcharge4</span>',
|
||||
'$quote.quote_number' => '<span>$quote_number</span>',
|
||||
'$quote.po_number' => '<span>$po_number</span>',
|
||||
'$quote.quote_date' => '<span>$date</span>',
|
||||
'$quote.valid_until' => '<span>$valid_until</span>',
|
||||
'$quote.balance_due' => '<span>$balance_due</span>',
|
||||
'$quote.quote_total' => '<span>$quote_total</span>',
|
||||
'$quote.partial_due' => '<span>$partial_due</span>',
|
||||
'$quote.quote1' => '<span>$quote1</span>',
|
||||
'$quote.quote2' => '<span>$quote2</span>',
|
||||
'$quote.quote3' => '<span>$quote3</span>',
|
||||
'$quote.quote4' => '<span>$quote4</span>',
|
||||
'$quote.surcharge1' => '<span>$surcharge1</span>',
|
||||
'$quote.surcharge2' => '<span>$surcharge2</span>',
|
||||
'$quote.surcharge3' => '<span>$surcharge3</span>',
|
||||
'$quote.surcharge4' => '<span>$surcharge4</span>',
|
||||
];
|
||||
|
||||
return $this->processCustomFields($company, $data);
|
||||
@ -352,20 +338,20 @@ class Designer {
|
||||
{
|
||||
|
||||
$data = [
|
||||
'credit_number' => '<span>$credit_number</span>',
|
||||
'po_number' => '<span>$po_number</span>',
|
||||
'date' => '<span>$date</span>',
|
||||
'credit_balance' => '<span>$credit_balance</span>',
|
||||
'credit_amount' => '<span>$credit_amount</span>',
|
||||
'partial_due' => '<span>$partial_due</span>',
|
||||
'invoice1' => '<span>$invoice1</span>',
|
||||
'invoice2' => '<span>$invoice2</span>',
|
||||
'invoice3' => '<span>$invoice3</span>',
|
||||
'invoice4' => '<span>$invoice4</span>',
|
||||
'surcharge1' => '<span>$surcharge1</span>',
|
||||
'surcharge2' => '<span>$surcharge2</span>',
|
||||
'surcharge3' => '<span>$surcharge3</span>',
|
||||
'surcharge4' => '<span>$surcharge4</span>',
|
||||
'$credit.credit_number' => '<span>$credit_number</span>',
|
||||
'$credit.po_number' => '<span>$po_number</span>',
|
||||
'$credit.credit_date' => '<span>$date</span>',
|
||||
'$credit.credit_balance' => '<span>$credit_balance</span>',
|
||||
'$credit.credit_amount' => '<span>$credit_amount</span>',
|
||||
'$credit.partial_due' => '<span>$partial_due</span>',
|
||||
'$credit.invoice1' => '<span>$invoice1</span>',
|
||||
'$credit.invoice2' => '<span>$invoice2</span>',
|
||||
'$credit.invoice3' => '<span>$invoice3</span>',
|
||||
'$credit.invoice4' => '<span>$invoice4</span>',
|
||||
'$credit.surcharge1' => '<span>$surcharge1</span>',
|
||||
'$credit.surcharge2' => '<span>$surcharge2</span>',
|
||||
'$credit.surcharge3' => '<span>$surcharge3</span>',
|
||||
'$credit.surcharge4' => '<span>$surcharge4</span>',
|
||||
];
|
||||
|
||||
return $this->processCustomFields($company, $data);
|
||||
@ -393,27 +379,29 @@ class Designer {
|
||||
|
||||
}
|
||||
|
||||
private function processInputVariables($company, $variables)
|
||||
{
|
||||
// private function processInputVariables($company, $variables)
|
||||
// {
|
||||
// if(is_object($variables))
|
||||
// $variables = json_decode(json_encode($variables),true);
|
||||
|
||||
$custom_fields = $company->custom_fields;
|
||||
// $custom_fields = $company->custom_fields;
|
||||
|
||||
$matches = array_intersect(self::$custom_fields, $variables);
|
||||
// $matches = array_intersect(self::$custom_fields, $variables);
|
||||
|
||||
foreach ($matches as $match) {
|
||||
// foreach ($matches as $match) {
|
||||
|
||||
if (!property_exists($custom_fields, $match) || (strlen($custom_fields->{$match}) == 0)) {
|
||||
foreach ($variables as $key => $value) {
|
||||
if ($value == $match) {
|
||||
unset($variables[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (!property_exists($custom_fields, $match) || (strlen($custom_fields->{$match}) == 0)) {
|
||||
// foreach ($variables as $key => $value) {
|
||||
// if ($value == $match) {
|
||||
// unset($variables[$key]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
return $variables;
|
||||
// return $variables;
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
}
|
@ -26,7 +26,7 @@ class Elegant extends AbstractDesign
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link href="$app_url/css/tailwind-1.2.0.css" rel="stylesheet">
|
||||
<style>
|
||||
body {font-size:90%}
|
||||
@page
|
||||
@ -46,7 +46,6 @@ class Elegant extends AbstractDesign
|
||||
public function header() {
|
||||
|
||||
return '
|
||||
|
||||
<div class="py-16 px-8">
|
||||
<div class="flex flex justify-between border-b-4 border-black">
|
||||
<div style="margin-bottom: 15px">
|
||||
@ -79,7 +78,24 @@ class Elegant extends AbstractDesign
|
||||
<div class="flex flex-col">
|
||||
$company_address
|
||||
</div>
|
||||
</div>';
|
||||
</div>
|
||||
<table class="w-full table-auto mb-6 mt-16">
|
||||
<thead class="text-left border-dashed border-b border-black">
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="w-full table-auto mb-6 mt-16">
|
||||
<thead class="text-left border-dashed border-b border-black">
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
|
||||
}
|
||||
|
||||
@ -87,40 +103,11 @@ class Elegant extends AbstractDesign
|
||||
return '';
|
||||
}
|
||||
|
||||
public function task_table()
|
||||
{
|
||||
return '
|
||||
<table class="w-full table-auto mb-6 mt-16">
|
||||
<thead class="text-left border-dashed border-b border-black">
|
||||
<tr>
|
||||
$product_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_table() {
|
||||
return '
|
||||
<table class="w-full table-auto mb-6 mt-16">
|
||||
<thead class="text-left border-dashed border-b border-black">
|
||||
<tr>
|
||||
$product_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function footer() {
|
||||
|
||||
return '
|
||||
@ -133,10 +120,12 @@ class Elegant extends AbstractDesign
|
||||
<div class="w-1/3 flex flex-col">
|
||||
<div class="flex px-3 mt-2">
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount_label
|
||||
$total_tax_labels
|
||||
$line_tax_labels
|
||||
</section>
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount
|
||||
$total_tax_values
|
||||
$line_tax_values
|
||||
</section>
|
||||
|
@ -26,7 +26,7 @@ class Hipster extends AbstractDesign
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link href="$app_url/css/tailwind-1.2.0.css" rel="stylesheet">
|
||||
<style>
|
||||
body {font-size:90%}
|
||||
@page
|
||||
@ -47,7 +47,6 @@ class Hipster extends AbstractDesign
|
||||
public function header() {
|
||||
|
||||
return '
|
||||
|
||||
<div class="px-12 py-16">
|
||||
<div class="flex">
|
||||
<div class="w-1/2 border-l pl-4 border-black mr-4">
|
||||
@ -94,6 +93,22 @@ class Hipster extends AbstractDesign
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="w-full table-auto mt-24">
|
||||
<thead class="text-left">
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="w-full table-auto mt-24">
|
||||
<thead class="text-left">
|
||||
$task_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
|
||||
}
|
||||
@ -102,42 +117,11 @@ class Hipster extends AbstractDesign
|
||||
return '';
|
||||
}
|
||||
|
||||
public function task_table()
|
||||
{
|
||||
return '
|
||||
<table class="w-full table-auto mt-24">
|
||||
<thead class="text-left">
|
||||
<tr>
|
||||
$task_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '
|
||||
';
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_table() {
|
||||
return '
|
||||
<table class="w-full table-auto mt-24">
|
||||
<thead class="text-left">
|
||||
<tr>
|
||||
$product_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function footer() {
|
||||
|
||||
return '
|
||||
@ -154,10 +138,12 @@ class Hipster extends AbstractDesign
|
||||
<div class="w-1/3 flex flex-col">
|
||||
<div class="flex px-3 mt-6">
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount_label
|
||||
$total_tax_labels
|
||||
$line_tax_labels
|
||||
</section>
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount
|
||||
$total_tax_values
|
||||
$line_tax_values
|
||||
</section>
|
||||
|
@ -21,14 +21,12 @@ class Modern extends AbstractDesign
|
||||
public function includes()
|
||||
{
|
||||
return '
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>$number</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link href="$app_url/css/tailwind-1.2.0.css" rel="stylesheet">
|
||||
<style>
|
||||
body {font-size:90%}
|
||||
.table_header_thead_class {text-align:left; text-align:left; color:#fff; background-color:#1a202c;}
|
||||
@ -104,27 +102,28 @@ class Modern extends AbstractDesign
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-12 pt-5 pb-20">
|
||||
';
|
||||
|
||||
}
|
||||
|
||||
public function task() {
|
||||
}
|
||||
|
||||
public function task_table()
|
||||
{
|
||||
return '
|
||||
<table class="w-full table-auto mt-8">
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left text-white bg-gray-900 display: table-header-group;">
|
||||
<tr>
|
||||
$task_table_header
|
||||
</tr>
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left text-white bg-gray-900 display: table-header-group;">
|
||||
$task_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
';
|
||||
|
||||
}
|
||||
|
||||
public function task() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
@ -132,21 +131,6 @@ class Modern extends AbstractDesign
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_table() {
|
||||
return '
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left text-white bg-gray-900 display: table-header-group;">
|
||||
<tr>
|
||||
$product_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
}
|
||||
|
||||
public function footer() {
|
||||
|
||||
return '
|
||||
@ -156,10 +140,12 @@ class Modern extends AbstractDesign
|
||||
</div>
|
||||
<div class="w-1/2 flex" style="page-break-inside: avoid;">
|
||||
<div class="w-1/2 text-right flex flex-col" style="page-break-inside: avoid;">
|
||||
$discount_label
|
||||
$total_tax_labels
|
||||
$line_tax_labels
|
||||
</div>
|
||||
<div class="w-1/2 text-right flex flex-col" style="page-break-inside: avoid;">
|
||||
$discount
|
||||
$total_tax_values
|
||||
$line_tax_values
|
||||
</div>
|
||||
|
@ -21,14 +21,12 @@ class Photo extends AbstractDesign
|
||||
public function includes()
|
||||
{
|
||||
return '
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>$number</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link href="$app_url/css/tailwind-1.2.0.css" rel="stylesheet">
|
||||
<style>
|
||||
body {font-size:90%}
|
||||
@page {
|
||||
@ -91,26 +89,29 @@ class Photo extends AbstractDesign
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-16 py-16">';
|
||||
|
||||
}
|
||||
|
||||
public function task() {
|
||||
}
|
||||
|
||||
public function task_table()
|
||||
{
|
||||
return '
|
||||
<div class="px-16 py-16">
|
||||
<table class="w-full table-auto">
|
||||
<thead class="text-left border-b-4 border-black">
|
||||
<tr>
|
||||
$task_table_header
|
||||
</tr>
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="w-full table-auto">
|
||||
<thead class="text-left border-b-4 border-black">
|
||||
$task_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
</table>
|
||||
';
|
||||
|
||||
}
|
||||
|
||||
public function task() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
@ -118,25 +119,10 @@ class Photo extends AbstractDesign
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_table() {
|
||||
return '
|
||||
<table class="w-full table-auto">
|
||||
<thead class="text-left border-b-4 border-black">
|
||||
<tr>
|
||||
$product_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
}
|
||||
|
||||
public function footer() {
|
||||
|
||||
return '
|
||||
<div class="flex items-center justify-between mt-2 px-4 pb-4">
|
||||
<div class="flex items-center justify-between mt-2 px-4 pb-4">
|
||||
<div class="w-1/2">
|
||||
<div class="flex flex-col">
|
||||
<p>$entity.public_notes</p>
|
||||
@ -145,10 +131,12 @@ class Photo extends AbstractDesign
|
||||
<div class="w-1/3 flex flex-col">
|
||||
<div class="flex px-3 mt-2">
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount_label
|
||||
$total_tax_labels
|
||||
$line_tax_labels
|
||||
</section>
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount
|
||||
$total_tax_values
|
||||
$line_tax_values
|
||||
</section>
|
||||
|
@ -26,7 +26,7 @@ class Plain extends AbstractDesign
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link href="$app_url/css/tailwind-1.2.0.css" rel="stylesheet">
|
||||
<style>
|
||||
body {font-size:90%}
|
||||
@page {
|
||||
@ -45,7 +45,6 @@ class Plain extends AbstractDesign
|
||||
public function header() {
|
||||
|
||||
return '
|
||||
|
||||
<div class="px-12 py-8">
|
||||
<div class="flex justify-between">
|
||||
$company_logo
|
||||
@ -54,15 +53,12 @@ class Plain extends AbstractDesign
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex px-3">
|
||||
<section class="w-1/2 flex flex-col mr-4">
|
||||
$entity_labels
|
||||
</section>
|
||||
<section class="flex align-end flex-col">
|
||||
$entity_details
|
||||
</section>
|
||||
</div>
|
||||
<section class="flex bg-gray-300 px-3">
|
||||
<p class="w-1/2 mr-4">Balance Due</p>
|
||||
<p class="w-1/2 mr-4">$balance_due_label</p>
|
||||
<p>$0.00</p>
|
||||
</section>
|
||||
</div>
|
||||
@ -77,6 +73,22 @@ class Plain extends AbstractDesign
|
||||
<div class="flex flex-col mt-8">
|
||||
$client_details
|
||||
</div>
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left bg-gray-300">
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left bg-gray-300">
|
||||
$task_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
|
||||
}
|
||||
@ -85,40 +97,11 @@ class Plain extends AbstractDesign
|
||||
return '';
|
||||
}
|
||||
|
||||
public function task_table()
|
||||
{
|
||||
return '
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left bg-gray-300">
|
||||
<tr>
|
||||
$task_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_table() {
|
||||
return '
|
||||
<table class="w-full table-auto mt-8">
|
||||
<thead class="text-left bg-gray-300">
|
||||
<tr>
|
||||
$product_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function footer() {
|
||||
|
||||
return '
|
||||
@ -135,10 +118,12 @@ class Plain extends AbstractDesign
|
||||
<div class="w-1/3 flex flex-col">
|
||||
<div class="flex px-3 mt-6">
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount_label
|
||||
$total_tax_labels
|
||||
$line_tax_labels
|
||||
</section>
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount
|
||||
$total_tax_values
|
||||
$line_tax_values
|
||||
</section>
|
||||
|
@ -21,12 +21,12 @@ class Playful extends AbstractDesign
|
||||
public function includes()
|
||||
{
|
||||
return '
|
||||
<head>
|
||||
<title>$number</title>
|
||||
<head>
|
||||
<title>$number</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link href="$app_url/css/tailwind-1.2.0.css" rel="stylesheet">
|
||||
<style>
|
||||
body {font-size:90%}
|
||||
@page
|
||||
@ -68,48 +68,50 @@ class Playful extends AbstractDesign
|
||||
public function body() {
|
||||
|
||||
return '
|
||||
<div class="flex mt-16">
|
||||
<div class="w-1/2">
|
||||
<div class="flex flex-col">
|
||||
<p class="font-semibold text-teal-600 pl-4">$entity_label</p>
|
||||
<div class="flex border-dashed border-t-4 border-b-4 border-teal-600 py-4 mt-4 pl-4">
|
||||
<section class="flex flex-col">
|
||||
$client_details
|
||||
</section>
|
||||
<div class="flex mt-16">
|
||||
<div class="w-1/2">
|
||||
<div class="flex flex-col">
|
||||
<p class="font-semibold text-teal-600 pl-4">$entity_label</p>
|
||||
<div class="flex border-dashed border-t-4 border-b-4 border-teal-600 py-4 mt-4 pl-4">
|
||||
<section class="flex flex-col">
|
||||
$client_details
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-1/2 ml-24">
|
||||
<div class="flex flex-col">
|
||||
<p class="font-semibold text-teal-600 pl-4">$from_label:</p>
|
||||
<div class="flex border-dashed border-t-4 border-b-4 border-teal-600 py-4 mt-4 pl-4">
|
||||
<section class="flex flex-col">
|
||||
$company_details
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-1/2 ml-24">
|
||||
<div class="flex flex-col">
|
||||
<p class="font-semibold text-teal-600 pl-4">$from_label:</p>
|
||||
<div class="flex border-dashed border-t-4 border-b-4 border-teal-600 py-4 mt-4 pl-4">
|
||||
<section class="flex flex-col">
|
||||
$company_details
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
<table class="w-full table-auto mt-20 mb-8">
|
||||
<thead class="text-left bg-teal-600 rounded-lg">
|
||||
$product_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="w-full table-auto mt-20 mb-8">
|
||||
<thead class="text-left bg-teal-600 rounded-lg">
|
||||
$task_table_header
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
|
||||
}
|
||||
|
||||
public function task() {
|
||||
}
|
||||
|
||||
public function task_table()
|
||||
{
|
||||
return '
|
||||
<table class="w-full table-auto mt-20 mb-8">
|
||||
<thead class="text-left bg-teal-600 rounded-lg">
|
||||
<tr>
|
||||
$task_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
@ -117,20 +119,6 @@ class Playful extends AbstractDesign
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_table() {
|
||||
return '
|
||||
<table class="w-full table-auto mt-20 mb-8">
|
||||
<thead class="text-left bg-teal-600 rounded-lg">
|
||||
<tr>
|
||||
$product_table_header
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$product_table_body
|
||||
</tbody>
|
||||
</table> ';
|
||||
}
|
||||
|
||||
public function footer() {
|
||||
|
||||
return '
|
||||
@ -143,10 +131,12 @@ class Playful extends AbstractDesign
|
||||
<div class="w-1/3 flex flex-col">
|
||||
<div class="flex px-3 mt-2">
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount_label
|
||||
$total_tax_labels
|
||||
$line_tax_labels
|
||||
</section>
|
||||
<section class="w-1/2 text-right flex flex-col">
|
||||
$discount
|
||||
$total_tax_values
|
||||
$line_tax_values
|
||||
</section>
|
||||
|
@ -35,4 +35,17 @@ class StoreDesignRequest extends Request
|
||||
'design' => 'required',
|
||||
];
|
||||
}
|
||||
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if(!array_key_exists('product', $input['design']) || is_null($input['design']['product']))
|
||||
$input['design']['product'] = '';
|
||||
|
||||
if(!array_key_exists('task', $input['design']) || is_null($input['design']['task']))
|
||||
$input['design']['task'] = '';
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,19 @@ class UpdateDesignRequest extends Request
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
// 'name' => 'unique:designs,name,'.$this->designs->name.',id,company_id,'.auth()->user()->companyId(),
|
||||
];
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if(!array_key_exists('product', $input['design']) || is_null($input['design']['product']))
|
||||
$input['design']['product'] = '';
|
||||
|
||||
if(!array_key_exists('task', $input['design']) || is_null($input['design']['task']))
|
||||
$input['design']['task'] = '';
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,14 @@ namespace App\Models;
|
||||
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
|
||||
use App\Designs\Designer;
|
||||
use App\Filters\QueryFilters;
|
||||
use App\Models\Design;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\UserSessionAttributes;
|
||||
use Hashids\Hashids;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@ -161,4 +163,13 @@ class BaseModel extends Model
|
||||
->withTrashed()
|
||||
->where('id', $this->decodePrimaryKey($value))->firstOrFail();
|
||||
}
|
||||
|
||||
public function getEntityDesigner()
|
||||
{
|
||||
$design = Design::find($this->decodePrimaryKey($this->client->getSetting('invoice_design_id')));
|
||||
|
||||
$entity = strtolower(class_basename($this));
|
||||
|
||||
return new Designer($this, $design, $this->client->getSetting('pdf_variables'), $entity);
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ class InvoiceSentNotification extends Notification implements ShouldQueue
|
||||
'client' => $this->contact->present()->name(),
|
||||
'invoice' => $this->invoice->number,
|
||||
]),
|
||||
'url' => config('ninja.site_url') . '/invoices/' . $this->invoice->hashed_id,
|
||||
'url' => config('ninja.app_url') . '/invoices/' . $this->invoice->hashed_id,
|
||||
'button' => ctrans('texts.view_invoice'),
|
||||
'signature' => $this->settings->email_signature,
|
||||
'logo' => $this->company->present()->logo(),
|
||||
|
@ -79,7 +79,7 @@ class InvoiceViewedNotification extends Notification implements ShouldQueue
|
||||
'client' => $this->contact->present()->name(),
|
||||
'invoice' => $this->invoice->number,
|
||||
]),
|
||||
'url' => config('ninja.site_url') . '/invoices/' . $this->invoice->hashed_id,
|
||||
'url' => config('ninja.app_url') . '/invoices/' . $this->invoice->hashed_id,
|
||||
'button' => ctrans('texts.view_invoice'),
|
||||
'signature' => $this->settings->email_signature,
|
||||
'logo' => $this->company->present()->logo(),
|
||||
|
@ -76,7 +76,7 @@ class NewPartialPaymentNotification extends Notification implements ShouldQueue
|
||||
'client' => $this->payment->client->present()->name(),
|
||||
'invoice' => $invoice_texts,
|
||||
]),
|
||||
'url' => config('ninja.site_url') . '/payments/' . $this->payment->hashed_id,
|
||||
'url' => config('ninja.app_url') . '/payments/' . $this->payment->hashed_id,
|
||||
'button' => ctrans('texts.view_payment'),
|
||||
'signature' => $this->settings->email_signature,
|
||||
'logo' => $this->company->present()->logo(),
|
||||
|
@ -76,7 +76,7 @@ class NewPaymentNotification extends Notification implements ShouldQueue
|
||||
'client' => $this->payment->client->present()->name(),
|
||||
'invoice' => $invoice_texts,
|
||||
]),
|
||||
'url' => config('ninja.site_url') . '/payments/' . $this->payment->hashed_id,
|
||||
'url' => config('ninja.app_url') . '/payments/' . $this->payment->hashed_id,
|
||||
'button' => ctrans('texts.view_payment'),
|
||||
'signature' => $this->settings->email_signature,
|
||||
'logo' => $this->company->present()->logo(),
|
||||
|
@ -70,7 +70,8 @@ class ActivityRepository extends BaseRepository
|
||||
|
||||
|
||||
if (get_class($entity) == Invoice::class && ($activity->activity_type_id == Activity::MARK_SENT_INVOICE || $activity->activity_type_id == Activity::PAID_INVOICE)) {
|
||||
$backup->html_backup = $this->generateInvoiceHtml($entity->design(), $entity);
|
||||
//$backup->html_backup = $this->generateInvoiceHtml($entity->design(), $entity);
|
||||
$backup->html_backup = $this->generateEntityHtml($entity->getEntityDesigner(), $entity);
|
||||
}
|
||||
|
||||
|
||||
|
@ -58,7 +58,7 @@ class AccountTransformer extends EntityTransformer
|
||||
{
|
||||
return [
|
||||
'id' => (string)$this->encodePrimaryKey($account->id),
|
||||
'default_url' => config('ninja.site_url'),
|
||||
'default_url' => config('ninja.app_url'),
|
||||
'plan' => $account->getPlan(),
|
||||
'latest_version' => (string)$account->latest_version,
|
||||
'current_version' => (string)config('ninja.app_version'),
|
||||
|
@ -28,33 +28,11 @@ trait MakesInvoiceHtml
|
||||
*
|
||||
* @param string $design either the path to the design template, OR the full design template string
|
||||
* @param Collection $invoice The invoice object
|
||||
*
|
||||
*
|
||||
* @deprecated replaced by generateEntityHtml
|
||||
*
|
||||
* @return string The invoice string in HTML format
|
||||
*/
|
||||
public function generateInvoiceHtml($design, $invoice, $contact = null) :string
|
||||
{
|
||||
//$variables = array_merge($invoice->makeLabels(), $invoice->makeValues());
|
||||
//$design = str_replace(array_keys($variables), array_values($variables), $design);
|
||||
$invoice->load('client');
|
||||
|
||||
$client = $invoice->client;
|
||||
|
||||
App::setLocale($client->preferredLocale());
|
||||
|
||||
$labels = $invoice->makeLabels();
|
||||
$values = $invoice->makeValues($contact);
|
||||
|
||||
$design = str_replace(array_keys($labels), array_values($labels), $design);
|
||||
$design = str_replace(array_keys($values), array_values($values), $design);
|
||||
|
||||
$data['invoice'] = $invoice;
|
||||
$data['lang'] = $client->preferredLocale();
|
||||
|
||||
return $this->renderView($design, $data);
|
||||
|
||||
//return view($design, $data)->render();
|
||||
}
|
||||
|
||||
public function generateEntityHtml(Designer $designer, $entity, $contact = null) :string
|
||||
{
|
||||
|
||||
@ -73,12 +51,13 @@ trait MakesInvoiceHtml
|
||||
$data['includes'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getIncludes()->getHtml());
|
||||
$data['header'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getHeader()->getHtml());
|
||||
$data['body'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getBody()->getHtml());
|
||||
$data['product'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getProductTable());
|
||||
$data['task'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getTaskTable());
|
||||
$data['footer'] = $this->parseLabelsAndValues($labels, $values, $designer->init()->getFooter()->getHtml());
|
||||
|
||||
return view('pdf.stub', $data)->render();
|
||||
$html = view('pdf.stub', $data)->render();
|
||||
|
||||
// \Log::error($html);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function parseLabelsAndValues($labels, $values, $section) :string
|
||||
|
@ -45,119 +45,6 @@ trait MakesInvoiceValues
|
||||
'custom_label4',
|
||||
];
|
||||
|
||||
/**
|
||||
* Master list of invoice labels
|
||||
* @var array
|
||||
*/
|
||||
private static $labels = [
|
||||
'credit_balance',
|
||||
'credit_amount',
|
||||
'quote_total',
|
||||
'invoice',
|
||||
'date',
|
||||
'due_date',
|
||||
'invoice_number',
|
||||
'po_number',
|
||||
'discount',
|
||||
'taxes',
|
||||
'tax',
|
||||
'item',
|
||||
'description',
|
||||
'unit_cost',
|
||||
'quantity',
|
||||
'line_total',
|
||||
'subtotal',
|
||||
'paid_to_date',
|
||||
'balance_due',
|
||||
'partial_due',
|
||||
'terms',
|
||||
'your_invoice',
|
||||
'quote',
|
||||
'your_quote',
|
||||
'quote_date',
|
||||
'quote_number',
|
||||
'total',
|
||||
'invoice_issued_to',
|
||||
'quote_issued_to',
|
||||
'rate',
|
||||
'hours',
|
||||
'balance',
|
||||
'from',
|
||||
'to',
|
||||
'invoice_to',
|
||||
'quote_to',
|
||||
'details',
|
||||
'invoice_no',
|
||||
'quote_no',
|
||||
'valid_until',
|
||||
'client_name',
|
||||
'address1',
|
||||
'address2',
|
||||
'id_number',
|
||||
'vat_number',
|
||||
'city_state_postal',
|
||||
'postal_city_state',
|
||||
'country',
|
||||
'email',
|
||||
'contact_name',
|
||||
'company_name',
|
||||
'website',
|
||||
'phone',
|
||||
'blank',
|
||||
'surcharge',
|
||||
'tax_invoice',
|
||||
'tax_quote',
|
||||
'statement',
|
||||
'statement_date',
|
||||
'your_statement',
|
||||
'statement_issued_to',
|
||||
'statement_to',
|
||||
'credit_note',
|
||||
'credit_date',
|
||||
'credit_number',
|
||||
'credit_issued_to',
|
||||
'credit_to',
|
||||
'your_credit',
|
||||
'phone',
|
||||
'invoice_total',
|
||||
'outstanding',
|
||||
'invoice_due_date',
|
||||
'quote_due_date',
|
||||
'service',
|
||||
'product_key',
|
||||
'unit_cost',
|
||||
// 'custom_value1',
|
||||
// 'custom_value2',
|
||||
// 'custom_value3',
|
||||
// 'custom_value4',
|
||||
'delivery_note',
|
||||
'date',
|
||||
'method',
|
||||
'payment_date',
|
||||
'reference',
|
||||
'amount',
|
||||
'amount_paid',
|
||||
'invoice1',
|
||||
'invoice2',
|
||||
'invoice3',
|
||||
'invoice4',
|
||||
'surcharge1',
|
||||
'surcharge2',
|
||||
'surcharge3',
|
||||
'surcharge4',
|
||||
'client1',
|
||||
'client2',
|
||||
'client3',
|
||||
'client4',
|
||||
'contact1',
|
||||
'contact2',
|
||||
'contact3',
|
||||
'contact4',
|
||||
'company1',
|
||||
'company2',
|
||||
'company3',
|
||||
'company4',
|
||||
];
|
||||
|
||||
private static $custom_label_fields = [
|
||||
'invoice1',
|
||||
@ -182,40 +69,45 @@ trait MakesInvoiceValues
|
||||
'company4',
|
||||
];
|
||||
|
||||
/**
|
||||
* Iterates and translates all labels
|
||||
*
|
||||
* @return array returns an array of
|
||||
* keyed labels (appended with _label)
|
||||
*/
|
||||
public function makeLabels() :array
|
||||
public function makeCustomField($field) :string
|
||||
{
|
||||
$custom_fields = $this->company->custom_fields;
|
||||
|
||||
//todo we might want to translate like this
|
||||
//trans('texts.labe', [], null, $this->client->locale());
|
||||
$data = [];
|
||||
if(property_exists($custom_fields, $field)){
|
||||
|
||||
foreach (self::$labels as $label) {
|
||||
$data['$'.$label . '_label'] = ctrans('texts.'.$label);
|
||||
}
|
||||
$custom_field = $custom_fields->{$field};
|
||||
$custom_field_parts = explode("|", $custom_field);
|
||||
|
||||
if($custom_fields)
|
||||
{
|
||||
|
||||
foreach($custom_fields as $key => $value)
|
||||
{
|
||||
|
||||
if(strpos($value, '|') !== false)
|
||||
{
|
||||
$value = explode("|", $value);
|
||||
$value = $value[0];
|
||||
}
|
||||
|
||||
$data['$'.$key.'_label'] = $value;
|
||||
}
|
||||
return $custom_field_parts[0];
|
||||
|
||||
}
|
||||
|
||||
return '';
|
||||
|
||||
// //todo we might want to translate like this
|
||||
// //trans('texts.labe', [], null, $this->client->locale());
|
||||
// $data = [];
|
||||
|
||||
// foreach (self::$labels as $label) {
|
||||
// $data['$'.$label . '_label'] = ctrans('texts.'.$label);
|
||||
// }
|
||||
|
||||
// if($custom_fields)
|
||||
// {
|
||||
|
||||
// foreach($custom_fields as $key => $value)
|
||||
// {
|
||||
|
||||
// if(strpos($value, '|') !== false)
|
||||
// {
|
||||
// $value = explode("|", $value);
|
||||
// $value = $value[0];
|
||||
// }
|
||||
|
||||
// $data['$'.$key.'_label'] = $value;
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
|
||||
/*
|
||||
@ -241,8 +133,22 @@ trait MakesInvoiceValues
|
||||
contact4
|
||||
*/
|
||||
|
||||
$arrKeysLength = array_map('strlen', array_keys($data));
|
||||
array_multisort($arrKeysLength, SORT_DESC, $data);
|
||||
// $arrKeysLength = array_map('strlen', array_keys($data));
|
||||
// array_multisort($arrKeysLength, SORT_DESC, $data);
|
||||
|
||||
// return $data;
|
||||
}
|
||||
|
||||
public function makeLabels($contact = null) :array
|
||||
{
|
||||
$data = [];
|
||||
|
||||
$values = $this->makeLabelsAndValues($contact);
|
||||
|
||||
foreach($values as $key => $value)
|
||||
{
|
||||
$data[$key.'_label'] = $value['label'];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
@ -255,6 +161,20 @@ trait MakesInvoiceValues
|
||||
* of keyed labels (appended with _label)
|
||||
*/
|
||||
public function makeValues($contact = null) :array
|
||||
{
|
||||
$data = [];
|
||||
|
||||
$values = $this->makeLabelsAndValues($contact);
|
||||
|
||||
foreach($values as $key => $value)
|
||||
{
|
||||
$data[$key] = $value['value'];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function makeLabelsAndValues($contact = null) :array
|
||||
{
|
||||
if (!$this->client->currency() || !$this->client) {
|
||||
throw new \Exception(debug_backtrace()[1]['function'], 1);
|
||||
@ -264,89 +184,99 @@ trait MakesInvoiceValues
|
||||
$settings = $this->client->getMergedSettings();
|
||||
|
||||
$data = [];
|
||||
$data['$tax'] = ['value' => '', 'label' => ctrans('texts.tax')];
|
||||
$data['$app_url'] = ['value' => $this->generateAppUrl(), 'label' => ''];
|
||||
$data['$from'] = ['value' => '', 'label' => ctrans('texts.from')];
|
||||
$data['$to'] = ['value' => '', 'label' => ctrans('texts.to')];
|
||||
$data['$total_tax_labels'] = ['value' => $this->totalTaxLabels(), 'label' => ctrans('texts.taxes')];
|
||||
$data['$total_tax_values'] = ['value' => $this->totalTaxValues(), 'label' => ctrans('texts.taxes')];
|
||||
$data['$line_tax_labels'] = ['value' => $this->lineTaxLabels(), 'label' => ctrans('texts.taxes')];
|
||||
$data['$line_tax_values'] = ['value' => $this->lineTaxValues(), 'label' => ctrans('texts.taxes')];
|
||||
$data['$date'] = ['value' => $this->date ?: ' ', 'label' => ctrans('texts.date')];
|
||||
$data['$invoice_date'] = ['value' => $this->date ?: ' ', 'label' => ctrans('texts.invoice_date')];
|
||||
$data['$invoice.date'] = &$data['$date'];
|
||||
$data['$due_date'] = ['value' => $this->due_date ?: ' ', 'label' => ctrans('texts.due_date')];
|
||||
$data['$invoice.due_date'] = &$data['$due_date'];
|
||||
$data['$invoice.number'] = ['value' => $this->number ?: ' ', 'label' => ctrans('texts.invoice_number')];
|
||||
$data['$invoice.invoice_number'] = &$data['$invoice.number'];
|
||||
$data['$invoice_number'] = &$data['$invoice.number'];
|
||||
$data['$po_number'] = ['value' => $this->po_number ?: ' ', 'label' => ctrans('texts.po_number')];
|
||||
$data['$invoice.po_number'] = &$data['$po_number'];
|
||||
$data['$line_taxes'] = ['value' => $this->makeLineTaxes() ?: ' ', 'label' => ctrans('texts.taxes')];
|
||||
$data['$invoice.line_taxes'] = &$data['$line_taxes'];
|
||||
$data['$total_taxes'] = ['value' => $this->makeTotalTaxes() ?: ' ', 'label' => ctrans('texts.taxes')];
|
||||
$data['$invoice.total_taxes'] = &$data['$total_taxes'];
|
||||
|
||||
$data['$total_tax_labels'] = $this->totalTaxLabels();
|
||||
$data['$total_tax_values'] = $this->totalTaxValues();
|
||||
$data['$line_tax_labels'] = $this->lineTaxLabels();
|
||||
$data['$line_tax_values'] = $this->lineTaxValues();
|
||||
if($this instanceof Invoice){
|
||||
$data['$entity_label'] = ['value' => '', 'label' => ctrans('texts.invoice')];
|
||||
$data['$number'] = ['value' => $this->number ?: ' ', 'label' => ctrans('texts.invoice_number')];
|
||||
$data['$entity.terms'] = ['value' => $this->terms ?: ' ', 'label' => ctrans('texts.invoice_terms')];
|
||||
$data['$terms'] = &$data['$entity.terms'];
|
||||
}
|
||||
|
||||
$data['$date'] = $this->date ?: ' ';
|
||||
$data['$invoice.date'] = &$data['$date'];
|
||||
$data['$due_date'] = $this->due_date ?: ' ';
|
||||
$data['$invoice.due_date'] = &$data['$due_date'];
|
||||
$data['$number'] = $this->number ?: ' ';
|
||||
$data['$invoice.number'] = &$data['$number'];
|
||||
$data['$invoice_number'] = &$data['$number'];
|
||||
$data['$entity_number'] = &$data['$number'];
|
||||
$data['$po_number'] = $this->po_number ?: ' ';
|
||||
$data['$invoice.po_number'] = &$data['$po_number'];
|
||||
$data['$line_taxes'] = $this->makeLineTaxes() ?: ' ';
|
||||
$data['$invoice.line_taxes'] = &$data['$line_taxes'];
|
||||
$data['$total_taxes'] = $this->makeTotalTaxes() ?: ' ';
|
||||
$data['$invoice.total_taxes'] = &$data['$total_taxes'];
|
||||
if($this instanceof Quote){
|
||||
$data['$entity_label'] = ['value' => '', 'label' => ctrans('texts.quote')];
|
||||
$data['$number'] = ['value' => $this->number ?: ' ', 'label' => ctrans('texts.quote_number')];
|
||||
$data['$entity.terms'] = ['value' => $this->terms ?: ' ', 'label' => ctrans('texts.quote_terms')];
|
||||
$data['$terms'] = &$data['$entity.terms'];
|
||||
}
|
||||
|
||||
if($this instanceof Invoice)
|
||||
$data['$entity_label'] = ctrans('texts.invoice');
|
||||
if($this instanceof Credit){
|
||||
$data['$entity_label'] = ['value' => '', 'label' => ctrans('texts.credit')];
|
||||
$data['$number'] = ['value' => $this->number ?: ' ', 'label' => ctrans('texts.credit_number')];
|
||||
$data['$entity.terms'] = ['value' => $this->terms ?: ' ', 'label' => ctrans('texts.credit_terms')];
|
||||
$data['$terms'] = &$data['$entity.terms'];
|
||||
}
|
||||
|
||||
if($this instanceof Quote)
|
||||
$data['$entity_label'] = ctrans('texts.quote');
|
||||
$data['$entity_number'] = &$data['$number'];
|
||||
|
||||
if($this instanceof Credit)
|
||||
$data['$entity_label'] = ctrans('texts.credit');
|
||||
//$data['$paid_to_date'] = ;
|
||||
$data['$discount'] = ['value' => Number::formatMoney($this->calc()->getTotalDiscount(), $this->client) ?: ' ', 'label' => ctrans('texts.discount')];
|
||||
$data['$invoice.discount'] = &$data['$discount'];
|
||||
$data['$subtotal'] = ['value' => Number::formatMoney($this->calc()->getSubTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.subtotal')];
|
||||
$data['$invoice.subtotal'] = &$data['$subtotal'];
|
||||
$data['$balance_due'] = ['value' => Number::formatMoney($this->balance, $this->client) ?: ' ', 'label' => ctrans('texts.balance_due')];
|
||||
$data['$invoice.balance_due'] = &$data['$balance_due'];
|
||||
$data['$partial_due'] = ['value' => Number::formatMoney($this->partial, $this->client) ?: ' ', 'label' => ctrans('texts.partial_due')];
|
||||
$data['$invoice.partial_due'] = &$data['$partial_due'];
|
||||
$data['$total'] = ['value' => Number::formatMoney($this->calc()->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.total')];
|
||||
$data['$invoice.total'] = ['value' => Number::formatMoney($this->calc()->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.invoice_total')];
|
||||
$data['$amount'] = &$data['$total'];
|
||||
$data['$invoice_total'] = &$data['$total'];
|
||||
$data['$invoice.amount'] = &$data['$total'];
|
||||
$data['$quote_total'] = ['value' => Number::formatMoney($this->calc()->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.quote_total')];
|
||||
$data['$quote.amount'] = &$data['$quote_total'];
|
||||
$data['$credit_total'] = ['value' => Number::formatMoney($this->calc()->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.credit_total')];
|
||||
$data['$credit.amount'] = &$data['$credit_total'];
|
||||
|
||||
|
||||
|
||||
// $data['$tax'] = ;
|
||||
// $data['$item'] = ;
|
||||
// $data['$description'] = ;
|
||||
// $data['$unit_cost'] = ;
|
||||
// $data['$quantity'] = ;
|
||||
// $data['$line_total'] = ;
|
||||
// $data['$paid_to_date'] = ;
|
||||
$data['$discount'] = Number::formatMoney($this->calc()->getTotalDiscount(), $this->client) ?: ' ';
|
||||
$data['$invoice.discount'] = &$data['$discount'];
|
||||
$data['$subtotal'] = Number::formatMoney($this->calc()->getSubTotal(), $this->client) ?: ' ';
|
||||
$data['$invoice.subtotal'] = &$data['$subtotal'];
|
||||
$data['$balance_due'] = Number::formatMoney($this->balance, $this->client) ?: ' ';
|
||||
$data['$invoice.balance_due'] = &$data['$balance_due'];
|
||||
$data['$partial_due'] = Number::formatMoney($this->partial, $this->client) ?: ' ';
|
||||
$data['$invoice.partial_due'] = &$data['$partial_due'];
|
||||
$data['$total'] = Number::formatMoney($this->calc()->getTotal(), $this->client) ?: ' ';
|
||||
$data['$invoice.total'] = &$data['$total'];
|
||||
$data['$amount'] = &$data['$total'];
|
||||
$data['$invoice_total'] = &$data['$total'];
|
||||
$data['$invoice.amount'] = &$data['$total'];
|
||||
|
||||
$data['$balance'] = Number::formatMoney($this->calc()->getBalance(), $this->client) ?: ' ';
|
||||
$data['$invoice.balance'] = &$data['$balance'];
|
||||
$data['$taxes'] = Number::formatMoney($this->calc()->getItemTotalTaxes(), $this->client) ?: ' ';
|
||||
$data['$invoice.taxes'] = &$data['$taxes'];
|
||||
$data['$terms'] = $this->terms ?: ' ';
|
||||
$data['$invoice.terms'] = &$data['$terms'];
|
||||
$data['$invoice1'] = $this->custom_value1 ?: ' ';
|
||||
$data['$invoice2'] = $this->custom_value2 ?: ' ';
|
||||
$data['$invoice3'] = $this->custom_value3 ?: ' ';
|
||||
$data['$invoice4'] = $this->custom_value4 ?: ' ';
|
||||
$data['$invoice.public_notes'] = $this->public_notes ?: ' ';
|
||||
$data['$entity.public_notes'] = &$data['$invoice.public_notes'];
|
||||
$data['$balance'] = ['value' => Number::formatMoney($this->calc()->getBalance(), $this->client) ?: ' ', 'label' => ctrans('texts.balance')];
|
||||
$data['$invoice.balance'] = &$data['$balance'];
|
||||
$data['$taxes'] = ['value' => Number::formatMoney($this->calc()->getItemTotalTaxes(), $this->client) ?: ' ', 'label' => ctrans('texts.taxes')];
|
||||
$data['$invoice.taxes'] = &$data['$taxes'];
|
||||
|
||||
$data['$invoice1'] = ['value' => $this->custom_value1 ?: ' ', 'label' => $this->makeCustomField('invoice1')];
|
||||
$data['$invoice2'] = ['value' => $this->custom_value2 ?: ' ', 'label' => $this->makeCustomField('invoice2')];
|
||||
$data['$invoice3'] = ['value' => $this->custom_value3 ?: ' ', 'label' => $this->makeCustomField('invoice3')];
|
||||
$data['$invoice4'] = ['value' => $this->custom_value4 ?: ' ', 'label' => $this->makeCustomField('invoice4')];
|
||||
$data['$invoice.public_notes'] = ['value' => $this->public_notes ?: ' ', 'label' => ctrans('texts.public_notes')];
|
||||
$data['$entity.public_notes'] = &$data['$invoice.public_notes'];
|
||||
|
||||
// $data['$your_invoice'] = ;
|
||||
// $data['$quote'] = ;
|
||||
// $data['$your_quote'] = ;
|
||||
$data['$quote_date'] = &$data['$date'];
|
||||
$data['$quote_number'] = &$data['$number'];
|
||||
$data['$quote_no'] = &$data['$quote_number'];
|
||||
$data['$quote.quote_no'] = &$data['$quote_number'];
|
||||
$data['$valid_until'] = $this->due_date;
|
||||
$data['$quote_total'] = &$data['$total'];
|
||||
|
||||
|
||||
$data['$credit_amount'] = &$data['$total'];
|
||||
$data['$credit_balance'] = &$data['$balance'];
|
||||
$data['$credit.amount'] = &$data['$total'];
|
||||
$data['$credit_number'] = &$data['$number'];
|
||||
$data['$credit_no'] = &$data['$number'];
|
||||
$data['$credit.credit_no'] = &$data['$number'];
|
||||
//
|
||||
$data['$quote_date'] = ['value' => $this->date ?: ' ', 'label' => ctrans('texts.quote_date')];
|
||||
$data['$quote_number'] = ['value' => $this->number ?: ' ', 'label' => ctrans('texts.quote_number')];
|
||||
$data['$quote.quote_number'] = &$data['$quote_number'];
|
||||
$data['$quote_no'] = &$data['$quote_number'];
|
||||
$data['$quote.quote_no'] = &$data['$quote_number'];
|
||||
$data['$valid_until'] = ['value' => $this->due_date, 'label' => ctrans('texts.valid_until')];
|
||||
$data['$quote_total'] = ['value' => Number::formatMoney($this->calc()->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.quote_total')];
|
||||
$data['$credit_amount'] = ['value' => Number::formatMoney($this->calc()->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.credit_amount')];
|
||||
$data['$credit_balance'] = ['value' => Number::formatMoney($this->balance, $this->client) ?: ' ', 'label' => ctrans('texts.credit_balance')];;
|
||||
$data['$credit_number'] = &$data['$number'];
|
||||
$data['$credit_no'] = &$data['$number'];
|
||||
$data['$credit.credit_no'] = &$data['$number'];
|
||||
|
||||
// $data['$invoice_issued_to'] = ;
|
||||
// $data['$quote_issued_to'] = ;
|
||||
@ -357,73 +287,100 @@ trait MakesInvoiceValues
|
||||
// $data['$invoice_to'] = ;
|
||||
// $data['$quote_to'] = ;
|
||||
// $data['$details'] = ;
|
||||
$data['$invoice_no'] = $this->number ?: ' ';
|
||||
|
||||
$data['$invoice.invoice_no'] = &$data['$invoice_no'];
|
||||
$data['$client1'] = $this->client->custom_value1 ?: ' ';
|
||||
$data['$client2'] = $this->client->custom_value2 ?: ' ';
|
||||
$data['$client3'] = $this->client->custom_value3 ?: ' ';
|
||||
$data['$client4'] = $this->client->custom_value4 ?: ' ';
|
||||
$data['$client_name'] = $this->present()->clientName() ?: ' ';
|
||||
$data['$client.name'] = &$data['$client_name'];
|
||||
$data['$address1'] = $this->client->address1 ?: ' ';
|
||||
$data['$address2'] = $this->client->address2 ?: ' ';
|
||||
$data['$client.address2'] = &$data['$address2'];
|
||||
$data['$client.address1'] = &$data['$address1'];
|
||||
$data['$client.address'] = &$data['$client_address'];
|
||||
$data['$client_address'] = $this->present()->address() ?: ' ';
|
||||
$data['$id_number'] = $this->client->id_number ?: ' ';
|
||||
$data['$client.id_number'] = &$data['$id_number'];
|
||||
$data['$vat_number'] = $this->client->vat_number ?: ' ';
|
||||
$data['$client.vat_number'] = &$data['$vat_number'];
|
||||
$data['$website'] = $this->client->present()->website() ?: ' ';
|
||||
$data['$client.website'] = &$data['$website'];
|
||||
$data['$phone'] = $this->client->present()->phone() ?: ' ';
|
||||
$data['$client.phone'] = &$data['$phone'];
|
||||
$data['$city_state_postal'] = $this->present()->cityStateZip($this->client->city, $this->client->state, $this->client->postal_code, false) ?: ' ';
|
||||
$data['$client.city_state_postal'] = &$data['$city_state_postal'];
|
||||
$data['$postal_city_state'] = $this->present()->cityStateZip($this->client->city, $this->client->state, $this->client->postal_code, true) ?: ' ';
|
||||
$data['$client.postal_city_state'] = &$data['$postal_city_state'];
|
||||
$data['$country'] = isset($this->client->country->name) ? $this->client->country->name : 'No Country Set';
|
||||
$data['$client.country'] = &$data['$country'];
|
||||
$data['$email'] = isset($this->client->primary_contact()->first()->email) ? $this->client->primary_contact()->first()->email : 'no contact email on record';
|
||||
$data['$client.email'] = &$data['$email'];
|
||||
$data['$invoice_no'] = &$data['$number'];
|
||||
$data['$invoice.invoice_no'] = &$data['$number'];
|
||||
$data['$client1'] = ['value' => $this->client->custom_value1 ?: ' ', 'label' => $this->makeCustomField('client1')];
|
||||
$data['$client2'] = ['value' => $this->client->custom_value2 ?: ' ', 'label' => $this->makeCustomField('client2')];
|
||||
$data['$client3'] = ['value' => $this->client->custom_value3 ?: ' ', 'label' => $this->makeCustomField('client3')];
|
||||
$data['$client4'] = ['value' => $this->client->custom_value4 ?: ' ', 'label' => $this->makeCustomField('client4')];
|
||||
$data['$address1'] = ['value' => $this->client->address1 ?: ' ', 'label' => ctrans('texts.address1')];
|
||||
$data['$address2'] = ['value' => $this->client->address2 ?: ' ', 'label' => ctrans('texts.address2')];
|
||||
$data['$id_number'] = ['value' => $this->client->id_number ?: ' ', 'label' => ctrans('texts.id_number')];
|
||||
$data['$vat_number'] = ['value' => $this->client->vat_number ?: ' ', 'label' => ctrans('texts.vat_number')];
|
||||
$data['$website'] = ['value' => $this->client->present()->website() ?: ' ', 'label' => ctrans('texts.website')];
|
||||
$data['$phone'] = ['value' => $this->client->present()->phone() ?: ' ', 'label' => ctrans('texts.phone')];
|
||||
$data['$country'] = ['value' => isset($this->client->country->name) ? $this->client->country->name : 'No Country Set', 'label' => ctrans('texts.country')];
|
||||
$data['$email'] = ['value' => isset($this->client->primary_contact()->first()->email) ? $this->client->primary_contact()->first()->email : 'no contact email on record', 'label' => ctrans('texts.email')];
|
||||
$data['$client_name'] = ['value' => $this->present()->clientName() ?: ' ', 'label' => ctrans('texts.client_name')];
|
||||
$data['$client.name'] = &$data['$client_name'];
|
||||
$data['$client.address1'] = &$data['$address1'];
|
||||
$data['$client.address2'] = &$data['$address2'];
|
||||
$data['$client_address'] = ['value' => $this->present()->address() ?: ' ', 'label' => ctrans('texts.address')];
|
||||
$data['$client.address'] = &$data['$client_address'];
|
||||
$data['$client.id_number'] = &$data['$id_number'];
|
||||
$data['$client.vat_number'] = &$data['$vat_number'];
|
||||
$data['$client.website'] = &$data['$website'];
|
||||
$data['$client.phone'] = &$data['$phone'];
|
||||
$data['$city_state_postal'] = ['value' => $this->present()->cityStateZip($this->client->city, $this->client->state, $this->client->postal_code, false) ?: ' ', 'label' => ctrans('texts.city_state_postal')];
|
||||
$data['$client.city_state_postal'] = &$data['$city_state_postal'];
|
||||
$data['$postal_city_state'] = ['value' => $this->present()->cityStateZip($this->client->city, $this->client->state, $this->client->postal_code, true) ?: ' ', 'label' => ctrans('texts.postal_city_state')];
|
||||
$data['$client.postal_city_state'] = &$data['$postal_city_state'];
|
||||
$data['$client.country'] = &$data['$country'];
|
||||
$data['$client.email'] = &$data['$email'];
|
||||
|
||||
if(!$contact)
|
||||
$contact = $this->client->primary_contact()->first();
|
||||
|
||||
$data['$contact_name'] = isset($contact) ? $contact->present()->name() : 'no contact name on record';
|
||||
$data['$contact.name'] = &$data['$contact_name'];
|
||||
$data['$contact1'] = isset($contact) ? $contact->custom_value1 : ' ';
|
||||
$data['$contact2'] = isset($contact) ? $contact->custom_value2 : ' ';
|
||||
$data['$contact3'] = isset($contact) ? $contact->custom_value3 : ' ';
|
||||
$data['$contact4'] = isset($contact) ? $contact->custom_value4 : ' ';
|
||||
$data['$contact_name'] = ['value' => isset($contact) ? $contact->present()->name() : 'no contact name on record', 'label' => ctrans('texts.contact_name')];
|
||||
$data['$contact.name'] = &$data['$contact_name'];
|
||||
$data['$contact1'] = ['value' => isset($contact) ? $contact->custom_value1 : ' ', 'label' => $this->makeCustomField('contact1')];
|
||||
$data['$contact2'] = ['value' => isset($contact) ? $contact->custom_value2 : ' ', 'label' => $this->makeCustomField('contact1')];
|
||||
$data['$contact3'] = ['value' => isset($contact) ? $contact->custom_value3 : ' ', 'label' => $this->makeCustomField('contact1')];
|
||||
$data['$contact4'] = ['value' => isset($contact) ? $contact->custom_value4 : ' ', 'label' => $this->makeCustomField('contact1')];
|
||||
|
||||
$data['$company.city_state_postal'] = $this->company->present()->cityStateZip($settings->city, $settings->state, $settings->postal_code, false) ?: ' ';
|
||||
$data['$company.postal_city_state'] = $this->company->present()->cityStateZip($settings->city, $settings->state, $settings->postal_code, true) ?: ' ';
|
||||
$data['$company.name'] = $this->company->present()->name() ?: ' ';
|
||||
$data['$company.company_name'] = &$data['$company.name'];
|
||||
$data['$company.address1'] = $settings->address1 ?: ' ';
|
||||
$data['$company.address2'] = $settings->address2 ?: ' ';
|
||||
$data['$company.city'] = $settings->city ?: ' ';
|
||||
$data['$company.state'] = $settings->state ?: ' ';
|
||||
$data['$company.postal_code'] = $settings->postal_code ?: ' ';
|
||||
$data['$company.country'] = Country::find($settings->country_id)->first()->name ?: ' ';
|
||||
$data['$company.phone'] = $settings->phone ?: ' ';
|
||||
$data['$company.email'] = $settings->email ?: ' ';
|
||||
$data['$company.vat_number'] = $settings->vat_number ?: ' ';
|
||||
$data['$company.id_number'] = $settings->id_number ?: ' ';
|
||||
$data['$company.website'] = $settings->website ?: ' ';
|
||||
$data['$company.address'] = $this->company->present()->address($settings) ?: ' ';
|
||||
$data['$company.city_state_postal'] = ['value' => $this->company->present()->cityStateZip($settings->city, $settings->state, $settings->postal_code, false) ?: ' ', 'label' => ctrans('texts.city_state_postal')];
|
||||
$data['$company.postal_city_state'] = ['value' => $this->company->present()->cityStateZip($settings->city, $settings->state, $settings->postal_code, true) ?: ' ', 'label' => ctrans('texts.postal_city_state')];
|
||||
$data['$company.name'] = ['value' => $this->company->present()->name() ?: ' ', 'label' => ctrans('texts.company_name')];
|
||||
$data['$company.company_name'] = &$data['$company.name'];
|
||||
$data['$company.address1'] = ['value' => $settings->address1 ?: ' ', 'label' => ctrans('texts.address1')];
|
||||
$data['$company.address2'] = ['value' => $settings->address2 ?: ' ', 'label' => ctrans('texts.address2')];
|
||||
$data['$company.city'] = ['value' => $settings->city ?: ' ', 'label' => ctrans('texts.city')];
|
||||
$data['$company.state'] = ['value' => $settings->state ?: ' ', 'label' => ctrans('texts.state')];
|
||||
$data['$company.postal_code'] = ['value' => $settings->postal_code ?: ' ', 'label' => ctrans('texts.postal_code')];
|
||||
$data['$company.country'] = ['value' => Country::find($settings->country_id)->first()->name ?: ' ', 'label' => ctrans('texts.country')];
|
||||
$data['$company.phone'] = ['value' => $settings->phone ?: ' ', 'label' => ctrans('texts.phone')];
|
||||
$data['$company.email'] = ['value' => $settings->email ?: ' ', 'label' => ctrans('texts.email')];
|
||||
$data['$company.vat_number'] = ['value' => $settings->vat_number ?: ' ', 'label' => ctrans('texts.vat_number')];
|
||||
$data['$company.id_number'] = ['value' => $settings->id_number ?: ' ', 'label' => ctrans('texts.id_number')];
|
||||
$data['$company.website'] = ['value' => $settings->website ?: ' ', 'label' => ctrans('texts.website')];
|
||||
$data['$company.address'] = ['value' => $this->company->present()->address($settings) ?: ' ', 'label' => ctrans('texts.address')];
|
||||
|
||||
$logo = $this->company->present()->logo($settings);
|
||||
|
||||
$data['$company.logo'] = "<img src='{$logo}' class='w-48' alt='logo'>" ?: ' ';
|
||||
$data['$company_logo'] = &$data['$company.logo'];
|
||||
$data['$company1'] = $settings->custom_value1 ?: ' ';
|
||||
$data['$company2'] = $settings->custom_value2 ?: ' ';
|
||||
$data['$company3'] = $settings->custom_value3 ?: ' ';
|
||||
$data['$company4'] = $settings->custom_value4 ?: ' ';
|
||||
$data['$company.logo'] = ['value' => "<img src='{$logo}' class='w-48' alt='logo'>" ?: ' ', 'label' => ctrans('texts.logo')];
|
||||
$data['$company_logo'] = &$data['$company.logo'];
|
||||
$data['$company1'] = ['value' => $settings->custom_value1 ?: ' ', 'label' => $this->makeCustomField('company1')];
|
||||
$data['$company2'] = ['value' => $settings->custom_value2 ?: ' ', 'label' => $this->makeCustomField('company2')];
|
||||
$data['$company3'] = ['value' => $settings->custom_value3 ?: ' ', 'label' => $this->makeCustomField('company3')];
|
||||
$data['$company4'] = ['value' => $settings->custom_value4 ?: ' ', 'label' => $this->makeCustomField('company4')];
|
||||
|
||||
$data['$product.date'] = ['value' => '', 'label' => ctrans('texts.date')];
|
||||
$data['$product.discount'] = ['value' => '', 'label' => ctrans('texts.discount')];
|
||||
$data['$product.product_key'] = ['value' => '', 'label' => ctrans('texts.product_key')];
|
||||
$data['$product.notes'] = ['value' => '', 'label' => ctrans('texts.notes')];
|
||||
$data['$product.cost'] = ['value' => '', 'label' => ctrans('texts.cost')];
|
||||
$data['$product.quantity'] = ['value' => '', 'label' => ctrans('texts.quantity')];
|
||||
$data['$product.tax_name1'] = ['value' => '', 'label' => ctrans('texts.tax')];
|
||||
$data['$product.tax_name2'] = ['value' => '', 'label' => ctrans('texts.tax')];
|
||||
$data['$product.tax_name3'] = ['value' => '', 'label' => ctrans('texts.tax')];
|
||||
$data['$product.line_total'] = ['value' => '', 'label' => ctrans('texts.line_total')];
|
||||
|
||||
$data['$task.date'] = ['value' => '', 'label' => ctrans('texts.date')];
|
||||
$data['$task.discount'] = ['value' => '', 'label' => ctrans('texts.discount')];
|
||||
$data['$task.product_key'] = ['value' => '', 'label' => ctrans('texts.product_key')];
|
||||
$data['$task.notes'] = ['value' => '', 'label' => ctrans('texts.notes')];
|
||||
$data['$task.cost'] = ['value' => '', 'label' => ctrans('texts.cost')];
|
||||
$data['$task.quantity'] = ['value' => '', 'label' => ctrans('texts.quantity')];
|
||||
$data['$task.tax_name1'] = ['value' => '', 'label' => ctrans('texts.tax')];
|
||||
$data['$task.tax_name2'] = ['value' => '', 'label' => ctrans('texts.tax')];
|
||||
$data['$task.tax_name3'] = ['value' => '', 'label' => ctrans('texts.tax')];
|
||||
$data['$task.line_total'] = ['value' => '', 'label' => ctrans('texts.line_total')];
|
||||
|
||||
|
||||
// $data['custom_label1'] = ['value' => '', 'label' => ctrans('texts.')];
|
||||
// $data['custom_label2'] = ['value' => '', 'label' => ctrans('texts.')];
|
||||
// $data['custom_label3'] = ['value' => '', 'label' => ctrans('texts.')];
|
||||
// $data['custom_label4'] = ['value' => '', 'label' => ctrans('texts.')];
|
||||
//$data['$blank'] = ;
|
||||
//$data['$surcharge'] = ;
|
||||
/*
|
||||
@ -460,94 +417,82 @@ trait MakesInvoiceValues
|
||||
|
||||
$arrKeysLength = array_map('strlen', array_keys($data));
|
||||
array_multisort($arrKeysLength, SORT_DESC, $data);
|
||||
// \Log::error('woop');
|
||||
//\Log::error(print_r($data,1));
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted HTML table of invoice line items
|
||||
*
|
||||
* @param array $columns The columns to be displayed
|
||||
*
|
||||
* @return string[HTML string
|
||||
* V2 of building a table header for PDFs
|
||||
* @param array $columns The array (or string of column headers)
|
||||
* @return string injectable HTML string
|
||||
*/
|
||||
public function table(array $columns) :?string
|
||||
{
|
||||
$data = '<table class="table table-striped items">';
|
||||
$data .= '<thead><tr class="heading">';
|
||||
|
||||
$column_headers = $this->transformColumnsForHeader($columns);
|
||||
|
||||
foreach ($column_headers as $column) {
|
||||
$data .= '<td>' . ctrans('texts.'.$column.'') . '</td>';
|
||||
}
|
||||
|
||||
$data .= '</tr></thead>';
|
||||
|
||||
$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>';
|
||||
}
|
||||
|
||||
$data .= '</table>';
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
public function table_header($columns) :?string
|
||||
public function buildTableHeader($columns) :?string
|
||||
{
|
||||
|
||||
/* Table Header */
|
||||
//$table_header = '<thead><tr class="'.$css['table_header_thead_class'].'">';
|
||||
$data = $this->makeLabels();
|
||||
|
||||
$table_header = '<tr>';
|
||||
|
||||
$column_headers = $this->transformColumnsForHeader($columns);
|
||||
|
||||
foreach ($column_headers as $column)
|
||||
$table_header .= '<td class="table_header_td_class">' . ctrans('texts.'.$column.'') . '</td>';
|
||||
foreach ($columns as $key => $column) {
|
||||
|
||||
$table_header .= '<td class="table_header_td_class">' . $key . '_label</td>';
|
||||
}
|
||||
|
||||
$table_header .= '</tr>';
|
||||
|
||||
$table_header = str_replace(array_keys($data), array_values($data), $table_header);
|
||||
|
||||
return $table_header;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo need to differentiate here between products and tasks - need to filter by invoice_type_id
|
||||
* V2 of building a table body for PDFs
|
||||
* @param array $columns The array (or string of column headers)
|
||||
* @return string injectable HTML string
|
||||
*/
|
||||
public function table_body($columns) :?string
|
||||
public function buildTableBody(array $default_columns, string $user_columns, string $table_prefix) :?string
|
||||
{
|
||||
$table_body = '';
|
||||
$items = $this->transformLineItems($this->line_items, $table_prefix);
|
||||
|
||||
/* Table Body */
|
||||
$columns = $this->transformColumnsForLineItems($columns);
|
||||
if(count($items) == 0)
|
||||
return '';
|
||||
|
||||
$items = $this->transformLineItems($this->line_items);
|
||||
$data = $this->makeValues();
|
||||
|
||||
foreach ($items as $item) {
|
||||
$output = '';
|
||||
|
||||
$table_body .= '<tr class="">';
|
||||
if(strlen($user_columns) > 1) {
|
||||
|
||||
foreach ($columns as $column) {
|
||||
$table_body .= '<td class="table_body_td_class">'. $item->{$column} . '</td>';
|
||||
foreach($items as $key => $item){
|
||||
$tmp = str_replace(array_keys($data), array_values($data), $user_columns);
|
||||
$tmp = str_replace(array_keys($item), array_values($item), $tmp);
|
||||
|
||||
$output .= $tmp;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
$table_body .= '</tr>';
|
||||
$table_row = '<tr>';
|
||||
|
||||
foreach ($default_columns as $key => $column) {
|
||||
|
||||
$table_row .= '<td class="table_header_td_class">' . $key . '</td>';
|
||||
}
|
||||
|
||||
$table_row .= '</tr>';
|
||||
|
||||
foreach($items as $key => $item){
|
||||
|
||||
$tmp = str_replace(array_keys($item), array_values($item), $table_row);
|
||||
$tmp = str_replace(array_keys($data), array_values($data), $tmp);
|
||||
|
||||
$output .= $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return $table_body;
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -619,46 +564,75 @@ trait MakesInvoiceValues
|
||||
* @param array $items The array of invoice items
|
||||
* @return array The formatted array of invoice items
|
||||
*/
|
||||
private function transformLineItems($items) :array
|
||||
private function transformLineItems($items, $table_type = '$product') :array
|
||||
{
|
||||
$data = [];
|
||||
|
||||
if(!is_array($items))
|
||||
return [];
|
||||
$data;
|
||||
|
||||
foreach ($items as $item) {
|
||||
$item->cost = Number::formatMoney($item->cost, $this->client);
|
||||
$item->line_total = Number::formatMoney($item->line_total, $this->client);
|
||||
foreach ($items as $key => $item) {
|
||||
|
||||
if($table_type == '$product' && $item->type_id != 1)
|
||||
continue;
|
||||
|
||||
if($table_type == '$task' && $item->type_id != 2)
|
||||
continue;
|
||||
|
||||
$data[$key][$table_type.'.product_key'] = $item->product_key;
|
||||
$data[$key][$table_type.'.notes'] = $item->notes;
|
||||
$data[$key][$table_type.'.custom_value1'] = $item->custom_value1;
|
||||
$data[$key][$table_type.'.custom_value2'] = $item->custom_value2;
|
||||
$data[$key][$table_type.'.custom_value3'] = $item->custom_value3;
|
||||
$data[$key][$table_type.'.custom_value4'] = $item->custom_value4;
|
||||
$data[$key][$table_type.'.quantity'] = $item->quantity;
|
||||
|
||||
$data[$key][$table_type.'.cost'] = Number::formatMoney($item->cost, $this->client);
|
||||
$data[$key][$table_type.'.line_total'] = Number::formatMoney($item->line_total, $this->client);
|
||||
|
||||
if (isset($item->discount) && $item->discount > 0) {
|
||||
if ($item->is_amount_discount) {
|
||||
$item->discount = Number::formatMoney($item->discount, $this->client);
|
||||
$data[$key][$table_type.'.discount'] = Number::formatMoney($item->discount, $this->client);
|
||||
} else {
|
||||
$item->discount = $item->discount . '%';
|
||||
$data[$key][$table_type.'.discount'] = $item->discount . '%';
|
||||
}
|
||||
}
|
||||
else
|
||||
$item->discount = '';
|
||||
$data[$key][$table_type.'.discount'] = '';
|
||||
|
||||
if(isset($item->tax_rate1) && $item->tax_rate1 > 0)
|
||||
$item->tax_rate1 = $item->tax_rate1."%";
|
||||
if(isset($item->tax_rate1) && $item->tax_rate1 > 0){
|
||||
$data[$key][$table_type.'.tax_rate1'] = round($item->tax_rate1,2) . "%";
|
||||
$data[$key][$table_type.'.tax1'] = &$data[$key][$table_type.'.tax_rate1'];
|
||||
}
|
||||
|
||||
if(isset($item->tax_rate2) && $item->tax_rate2 > 0)
|
||||
$item->tax_rate2 = $item->tax_rate2."%";
|
||||
if(isset($item->tax_rate2) && $item->tax_rate2 > 0){
|
||||
$data[$key][$table_type.'.tax_rate2'] = round($item->tax_rate2,2) . "%";
|
||||
$data[$key][$table_type.'.tax2'] = &$data[$key][$table_type.'.tax_rate2'];
|
||||
}
|
||||
|
||||
if(isset($item->tax_rate2) && $item->tax_rate2 > 0)
|
||||
$item->tax_rate2 = $item->tax_rate2."%";
|
||||
if(isset($item->tax_rate3) && $item->tax_rate3 > 0){
|
||||
$data[$key][$table_type.'.tax_rate3'] = round($item->tax_rate3,2) . "%";
|
||||
$data[$key][$table_type.'.tax3'] = &$data[$key][$table_type.'.tax_rate3'];
|
||||
}
|
||||
|
||||
if(isset($item->tax_rate1) && $item->tax_rate1 == 0)
|
||||
$item->tax_rate1 = '';
|
||||
if(isset($item->tax_rate1) && $item->tax_rate1 == 0){
|
||||
$data[$key][$table_type.'.tax_rate1'] = '';
|
||||
$data[$key][$table_type.'.tax1'] = &$data[$key][$table_type.'.tax_rate1'];
|
||||
}
|
||||
|
||||
if(isset($item->tax_rate2) && $item->tax_rate2 == 0)
|
||||
$item->tax_rate2 = '';
|
||||
if(isset($item->tax_rate2) && $item->tax_rate2 == 0){
|
||||
$data[$key][$table_type.'.tax_rate2'] = '';
|
||||
$data[$key][$table_type.'.tax2'] = &$data[$key][$table_type.'.tax_rate2'];
|
||||
}
|
||||
|
||||
if(isset($item->tax_rate2) && $item->tax_rate2 == 0)
|
||||
$item->tax_rate2 = '';
|
||||
if(isset($item->tax_rate3) && $item->tax_rate3 == 0){
|
||||
$data[$key][$table_type.'.tax_rate3'] = '';
|
||||
$data[$key][$table_type.'.tax3'] = &$data[$key][$table_type.'.tax_rate3'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $items;
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -760,4 +734,12 @@ trait MakesInvoiceValues
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/*
|
||||
| Ensures the URL doesn't have duplicated trailing slash
|
||||
*/
|
||||
public function generateAppUrl()
|
||||
{
|
||||
return rtrim(config('ninja.app_url'),"/");
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ return [
|
||||
'license' => env('NINJA_LICENSE', ''),
|
||||
'app_name' => env('APP_NAME'),
|
||||
'version_url' => 'https://raw.githubusercontent.com/invoiceninja/invoiceninja/v2/VERSION.txt',
|
||||
'site_url' => env('APP_URL', ''),
|
||||
'app_url' => env('APP_URL', ''),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => '0.0.1',
|
||||
'api_version' => '0.0.1',
|
||||
|
1
public/css/tailwind-1.2.0.css
vendored
Normal file
1
public/css/tailwind-1.2.0.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -3140,4 +3140,5 @@ return [
|
||||
'invoice_number_placeholder' => 'Invoice # :invoice',
|
||||
'entity_number_placeholder' => ':entity # :entity_number',
|
||||
'email_link_not_working' => 'If button above isn\'t working for you, please click on the link',
|
||||
'credit_terms' => 'Credit Terms',
|
||||
];
|
||||
|
@ -36,7 +36,7 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.4.1/css/simple-line-icons.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
|
||||
<link rel="canonical" href="{{ config('ninja.site_url') }}/{{ request()->path() }}"/>
|
||||
<link rel="canonical" href="{{ config('ninja.app_url') }}/{{ request()->path() }}"/>
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
|
||||
|
@ -33,9 +33,9 @@
|
||||
<!--
|
||||
TODO Setup social sharing info
|
||||
<meta property="og:site_name" content="Invoice Ninja"/>
|
||||
<meta property="og:url" content="{{ config('ninja.site_url') }}"/>
|
||||
<meta property="og:url" content="{{ config('ninja.app_url') }}"/>
|
||||
<meta property="og:title" content="Invoice Ninja"/>
|
||||
<meta property="og:image" content="{{ config('ninja.site_url') }}/images/logo.png"/>
|
||||
<meta property="og:image" content="{{ config('ninja.app_url') }}/images/logo.png"/>
|
||||
<meta property="og:description" content="Create. Send. Get Paid."/>
|
||||
--/>
|
||||
<!-- http://realfavicongenerator.net -->
|
||||
@ -57,7 +57,7 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.4.1/css/simple-line-icons.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
|
||||
<link rel="canonical" href="{{ config('ninja.site_url') }}/{{ request()->path() }}"/>
|
||||
<link rel="canonical" href="{{ config('ninja.app_url') }}/{{ request()->path() }}"/>
|
||||
<link rel="stylesheet" href="{{ mix('/css/ninja.min.css') }}">
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
|
||||
|
@ -1,23 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{!! $lang !!}">
|
||||
|
||||
{!! $includes !!}
|
||||
<body>
|
||||
|
||||
{!! $header !!}
|
||||
|
||||
{!! $body !!}
|
||||
|
||||
@if($product)
|
||||
{!! $product !!}
|
||||
@endif
|
||||
|
||||
@if($task)
|
||||
{!! $task !!}
|
||||
@endif
|
||||
|
||||
{!! $footer !!}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -53,7 +53,7 @@
|
||||
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
|
||||
{{-- <link href="{{ mix('favicon.png') }}" rel="shortcut icon" type="image/png"> --}}
|
||||
|
||||
<link rel="canonical" href="{{ config('ninja.site_url') }}/{{ request()->path() }}"/>
|
||||
<link rel="canonical" href="{{ config('ninja.app_url') }}/{{ request()->path() }}"/>
|
||||
|
||||
{{-- Feel free to push anything to header using @push('header') --}}
|
||||
@stack('head')
|
||||
|
@ -21,6 +21,7 @@ use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Tests\TestCase;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -45,6 +46,10 @@ class ClientTest extends TestCase
|
||||
|
||||
Client::reguard();
|
||||
ClientContact::reguard();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
}
|
||||
|
||||
public function testClientList()
|
||||
|
@ -50,9 +50,18 @@ class DesignApiTest extends TestCase
|
||||
|
||||
public function testDesignPost()
|
||||
{
|
||||
$design = [
|
||||
'body' => 'body',
|
||||
'includes' => 'includes',
|
||||
'product' => 'product',
|
||||
'task' => 'task',
|
||||
'footer' => 'footer',
|
||||
'header' => 'header'
|
||||
];
|
||||
|
||||
$data = [
|
||||
'name' => $this->faker->firstName,
|
||||
'design' => '<HTML></HTML'
|
||||
'design' => $design
|
||||
];
|
||||
|
||||
|
||||
@ -92,7 +101,7 @@ class DesignApiTest extends TestCase
|
||||
|
||||
$data = [
|
||||
'name' => $this->faker->firstName,
|
||||
'design' => 'changed'
|
||||
'design' => $design
|
||||
];
|
||||
|
||||
|
||||
|
@ -143,7 +143,7 @@ class LoginTest extends TestCase
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
|
||||
$account->default_company_id = $account->id;
|
||||
$account->default_company_id = $company->id;
|
||||
$account->save();
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Tests\TestCase;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -36,6 +37,9 @@ class ProductTest extends TestCase
|
||||
|
||||
Model::reguard();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
}
|
||||
|
||||
public function testProductList()
|
||||
@ -52,12 +56,10 @@ class ProductTest extends TestCase
|
||||
'terms_of_service' => 1
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
])->post('/api/v1/signup?include=account', $data);
|
||||
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$acc = $response->json();
|
||||
|
@ -104,6 +104,89 @@ class DesignTest extends TestCase
|
||||
|
||||
CreateQuotePdf::dispatchNow($this->quote, $this->quote->company, $this->quote->client->primary_contact()->first());
|
||||
}
|
||||
|
||||
|
||||
public function testCreditDesignExists()
|
||||
{
|
||||
|
||||
$design = Design::find(3);
|
||||
|
||||
$designer = new Designer($this->credit, $design, $this->company->settings->pdf_variables, 'credit');
|
||||
|
||||
$html = $designer->build()->getHtml();
|
||||
|
||||
$this->assertNotNull($html);
|
||||
|
||||
$settings = $this->invoice->client->settings;
|
||||
$settings->quote_design_id = "4";
|
||||
|
||||
$this->credit->client_id = $this->client->id;
|
||||
$this->credit->setRelation('client', $this->client);
|
||||
$this->credit->save();
|
||||
|
||||
$this->client->settings = $settings;
|
||||
$this->client->save();
|
||||
|
||||
CreateCreditPdf::dispatchNow($this->credit, $this->credit->company, $this->credit->client->primary_contact()->first());
|
||||
}
|
||||
|
||||
public function testAllDesigns()
|
||||
{
|
||||
|
||||
for($x=1; $x<=10; $x++)
|
||||
{
|
||||
|
||||
$settings = $this->invoice->client->settings;
|
||||
$settings->quote_design_id = (string)$this->encodePrimaryKey($x);
|
||||
|
||||
$this->quote->client_id = $this->client->id;
|
||||
$this->quote->setRelation('client', $this->client);
|
||||
$this->quote->save();
|
||||
|
||||
$this->client->settings = $settings;
|
||||
$this->client->save();
|
||||
|
||||
CreateQuotePdf::dispatchNow($this->quote, $this->quote->company, $this->quote->client->primary_contact()->first());
|
||||
|
||||
$this->quote->number = $this->getNextQuoteNumber($this->quote->client);
|
||||
$this->quote->save();
|
||||
|
||||
}
|
||||
|
||||
$this->assertTrue(true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// public function testQuoteDesignWithRepeatingHeader()
|
||||
// {
|
||||
@ -186,57 +269,6 @@ class DesignTest extends TestCase
|
||||
|
||||
// CreateQuotePdf::dispatchNow($this->quote, $this->quote->company, $this->quote->client->primary_contact()->first());
|
||||
// }
|
||||
|
||||
public function testCreditDesignExists()
|
||||
{
|
||||
|
||||
$design = Design::find(3);
|
||||
|
||||
$designer = new Designer($this->credit, $design, $this->company->settings->pdf_variables, 'credit');
|
||||
|
||||
$html = $designer->build()->getHtml();
|
||||
|
||||
$this->assertNotNull($html);
|
||||
|
||||
$settings = $this->invoice->client->settings;
|
||||
$settings->quote_design_id = "4";
|
||||
|
||||
$this->credit->client_id = $this->client->id;
|
||||
$this->credit->setRelation('client', $this->client);
|
||||
$this->credit->save();
|
||||
|
||||
$this->client->settings = $settings;
|
||||
$this->client->save();
|
||||
|
||||
CreateCreditPdf::dispatchNow($this->credit, $this->credit->company, $this->credit->client->primary_contact()->first());
|
||||
}
|
||||
|
||||
public function testAllDesigns()
|
||||
{
|
||||
|
||||
for($x=1; $x<=10; $x++)
|
||||
{
|
||||
|
||||
$settings = $this->invoice->client->settings;
|
||||
$settings->quote_design_id = (string)$this->encodePrimaryKey($x);
|
||||
|
||||
$this->quote->client_id = $this->client->id;
|
||||
$this->quote->setRelation('client', $this->client);
|
||||
$this->quote->save();
|
||||
|
||||
$this->client->settings = $settings;
|
||||
$this->client->save();
|
||||
|
||||
CreateQuotePdf::dispatchNow($this->quote, $this->quote->company, $this->quote->client->primary_contact()->first());
|
||||
|
||||
$this->quote->number = $this->getNextQuoteNumber($this->quote->client);
|
||||
$this->quote->save();
|
||||
|
||||
}
|
||||
|
||||
$this->assertTrue(true);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
|
52
tests/Unit/PdfVariablesTest.php
Normal file
52
tests/Unit/PdfVariablesTest.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
class PdfVariablesTest extends TestCase
|
||||
{
|
||||
|
||||
public function setUp() :void
|
||||
{
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$this->settings = CompanySettings::defaults();
|
||||
|
||||
}
|
||||
|
||||
public function testPdfVariableDefaults()
|
||||
{
|
||||
$pdf_variables = $this->settings->pdf_variables;
|
||||
|
||||
$this->assertEquals(ctrans('texts.client_name'), $pdf_variables->client_details->{'$client.name'});
|
||||
}
|
||||
|
||||
public function testPdfVariablesConvertedToArray()
|
||||
{
|
||||
$pdf_variables = json_decode(json_encode($this->settings->pdf_variables),true);
|
||||
|
||||
$this->assertEquals(ctrans('texts.client_name'), $pdf_variables['client_details']['$client.name']);
|
||||
}
|
||||
|
||||
public function testReplaceSampleHeaderText()
|
||||
{
|
||||
/* this flattens the multi dimensional array so we can do a single str_replace */
|
||||
$pdf_variables = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveArrayIterator($this->settings->pdf_variables)));
|
||||
|
||||
//\Log::error(print_r($pdf_variables,1));
|
||||
|
||||
$sample_header_text = '<tr><td>$client.name</td><td>$product.product_key</td><td>$product.line_total</td></tr>';
|
||||
|
||||
$replaced_header_text = str_replace(array_keys($pdf_variables), array_values($pdf_variables), $sample_header_text);
|
||||
|
||||
$this->assertEquals($replaced_header_text, '<tr><td>Client Name</td><td>Product</td><td>Line Total</td></tr>');
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user