1
0
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:
David Bomba 2020-03-16 21:12:10 +11:00 committed by GitHub
parent aad9f81e93
commit 0e12b63c95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1017 additions and 1078 deletions

View 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();
}
}
}

View File

@ -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));

View File

@ -24,5 +24,4 @@ abstract class AbstractDesign
abstract public function task();
abstract public function footer();
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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;
}
// }
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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);
}

View File

@ -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'),

View File

@ -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

View File

@ -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 ?: '&nbsp;', 'label' => ctrans('texts.date')];
$data['$invoice_date'] = ['value' => $this->date ?: '&nbsp;', 'label' => ctrans('texts.invoice_date')];
$data['$invoice.date'] = &$data['$date'];
$data['$due_date'] = ['value' => $this->due_date ?: '&nbsp;', 'label' => ctrans('texts.due_date')];
$data['$invoice.due_date'] = &$data['$due_date'];
$data['$invoice.number'] = ['value' => $this->number ?: '&nbsp;', '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 ?: '&nbsp;', 'label' => ctrans('texts.po_number')];
$data['$invoice.po_number'] = &$data['$po_number'];
$data['$line_taxes'] = ['value' => $this->makeLineTaxes() ?: '&nbsp;', 'label' => ctrans('texts.taxes')];
$data['$invoice.line_taxes'] = &$data['$line_taxes'];
$data['$total_taxes'] = ['value' => $this->makeTotalTaxes() ?: '&nbsp;', '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 ?: '&nbsp;', 'label' => ctrans('texts.invoice_number')];
$data['$entity.terms'] = ['value' => $this->terms ?: '&nbsp;', 'label' => ctrans('texts.invoice_terms')];
$data['$terms'] = &$data['$entity.terms'];
}
$data['$date'] = $this->date ?: '&nbsp;';
$data['$invoice.date'] = &$data['$date'];
$data['$due_date'] = $this->due_date ?: '&nbsp;';
$data['$invoice.due_date'] = &$data['$due_date'];
$data['$number'] = $this->number ?: '&nbsp;';
$data['$invoice.number'] = &$data['$number'];
$data['$invoice_number'] = &$data['$number'];
$data['$entity_number'] = &$data['$number'];
$data['$po_number'] = $this->po_number ?: '&nbsp;';
$data['$invoice.po_number'] = &$data['$po_number'];
$data['$line_taxes'] = $this->makeLineTaxes() ?: '&nbsp;';
$data['$invoice.line_taxes'] = &$data['$line_taxes'];
$data['$total_taxes'] = $this->makeTotalTaxes() ?: '&nbsp;';
$data['$invoice.total_taxes'] = &$data['$total_taxes'];
if($this instanceof Quote){
$data['$entity_label'] = ['value' => '', 'label' => ctrans('texts.quote')];
$data['$number'] = ['value' => $this->number ?: '&nbsp;', 'label' => ctrans('texts.quote_number')];
$data['$entity.terms'] = ['value' => $this->terms ?: '&nbsp;', '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 ?: '&nbsp;', 'label' => ctrans('texts.credit_number')];
$data['$entity.terms'] = ['value' => $this->terms ?: '&nbsp;', '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) ?: '&nbsp;', 'label' => ctrans('texts.discount')];
$data['$invoice.discount'] = &$data['$discount'];
$data['$subtotal'] = ['value' => Number::formatMoney($this->calc()->getSubTotal(), $this->client) ?: '&nbsp;', 'label' => ctrans('texts.subtotal')];
$data['$invoice.subtotal'] = &$data['$subtotal'];
$data['$balance_due'] = ['value' => Number::formatMoney($this->balance, $this->client) ?: '&nbsp;', 'label' => ctrans('texts.balance_due')];
$data['$invoice.balance_due'] = &$data['$balance_due'];
$data['$partial_due'] = ['value' => Number::formatMoney($this->partial, $this->client) ?: '&nbsp;', 'label' => ctrans('texts.partial_due')];
$data['$invoice.partial_due'] = &$data['$partial_due'];
$data['$total'] = ['value' => Number::formatMoney($this->calc()->getTotal(), $this->client) ?: '&nbsp;', 'label' => ctrans('texts.total')];
$data['$invoice.total'] = ['value' => Number::formatMoney($this->calc()->getTotal(), $this->client) ?: '&nbsp;', '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) ?: '&nbsp;', 'label' => ctrans('texts.quote_total')];
$data['$quote.amount'] = &$data['$quote_total'];
$data['$credit_total'] = ['value' => Number::formatMoney($this->calc()->getTotal(), $this->client) ?: '&nbsp;', '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) ?: '&nbsp;';
$data['$invoice.discount'] = &$data['$discount'];
$data['$subtotal'] = Number::formatMoney($this->calc()->getSubTotal(), $this->client) ?: '&nbsp;';
$data['$invoice.subtotal'] = &$data['$subtotal'];
$data['$balance_due'] = Number::formatMoney($this->balance, $this->client) ?: '&nbsp;';
$data['$invoice.balance_due'] = &$data['$balance_due'];
$data['$partial_due'] = Number::formatMoney($this->partial, $this->client) ?: '&nbsp;';
$data['$invoice.partial_due'] = &$data['$partial_due'];
$data['$total'] = Number::formatMoney($this->calc()->getTotal(), $this->client) ?: '&nbsp;';
$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) ?: '&nbsp;';
$data['$invoice.balance'] = &$data['$balance'];
$data['$taxes'] = Number::formatMoney($this->calc()->getItemTotalTaxes(), $this->client) ?: '&nbsp;';
$data['$invoice.taxes'] = &$data['$taxes'];
$data['$terms'] = $this->terms ?: '&nbsp;';
$data['$invoice.terms'] = &$data['$terms'];
$data['$invoice1'] = $this->custom_value1 ?: '&nbsp;';
$data['$invoice2'] = $this->custom_value2 ?: '&nbsp;';
$data['$invoice3'] = $this->custom_value3 ?: '&nbsp;';
$data['$invoice4'] = $this->custom_value4 ?: '&nbsp;';
$data['$invoice.public_notes'] = $this->public_notes ?: '&nbsp;';
$data['$entity.public_notes'] = &$data['$invoice.public_notes'];
$data['$balance'] = ['value' => Number::formatMoney($this->calc()->getBalance(), $this->client) ?: '&nbsp;', 'label' => ctrans('texts.balance')];
$data['$invoice.balance'] = &$data['$balance'];
$data['$taxes'] = ['value' => Number::formatMoney($this->calc()->getItemTotalTaxes(), $this->client) ?: '&nbsp;', 'label' => ctrans('texts.taxes')];
$data['$invoice.taxes'] = &$data['$taxes'];
$data['$invoice1'] = ['value' => $this->custom_value1 ?: '&nbsp;', 'label' => $this->makeCustomField('invoice1')];
$data['$invoice2'] = ['value' => $this->custom_value2 ?: '&nbsp;', 'label' => $this->makeCustomField('invoice2')];
$data['$invoice3'] = ['value' => $this->custom_value3 ?: '&nbsp;', 'label' => $this->makeCustomField('invoice3')];
$data['$invoice4'] = ['value' => $this->custom_value4 ?: '&nbsp;', 'label' => $this->makeCustomField('invoice4')];
$data['$invoice.public_notes'] = ['value' => $this->public_notes ?: '&nbsp;', '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 ?: '&nbsp;', 'label' => ctrans('texts.quote_date')];
$data['$quote_number'] = ['value' => $this->number ?: '&nbsp;', '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) ?: '&nbsp;', 'label' => ctrans('texts.quote_total')];
$data['$credit_amount'] = ['value' => Number::formatMoney($this->calc()->getTotal(), $this->client) ?: '&nbsp;', 'label' => ctrans('texts.credit_amount')];
$data['$credit_balance'] = ['value' => Number::formatMoney($this->balance, $this->client) ?: '&nbsp;', '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 ?: '&nbsp;';
$data['$invoice.invoice_no'] = &$data['$invoice_no'];
$data['$client1'] = $this->client->custom_value1 ?: '&nbsp;';
$data['$client2'] = $this->client->custom_value2 ?: '&nbsp;';
$data['$client3'] = $this->client->custom_value3 ?: '&nbsp;';
$data['$client4'] = $this->client->custom_value4 ?: '&nbsp;';
$data['$client_name'] = $this->present()->clientName() ?: '&nbsp;';
$data['$client.name'] = &$data['$client_name'];
$data['$address1'] = $this->client->address1 ?: '&nbsp;';
$data['$address2'] = $this->client->address2 ?: '&nbsp;';
$data['$client.address2'] = &$data['$address2'];
$data['$client.address1'] = &$data['$address1'];
$data['$client.address'] = &$data['$client_address'];
$data['$client_address'] = $this->present()->address() ?: '&nbsp;';
$data['$id_number'] = $this->client->id_number ?: '&nbsp;';
$data['$client.id_number'] = &$data['$id_number'];
$data['$vat_number'] = $this->client->vat_number ?: '&nbsp;';
$data['$client.vat_number'] = &$data['$vat_number'];
$data['$website'] = $this->client->present()->website() ?: '&nbsp;';
$data['$client.website'] = &$data['$website'];
$data['$phone'] = $this->client->present()->phone() ?: '&nbsp;';
$data['$client.phone'] = &$data['$phone'];
$data['$city_state_postal'] = $this->present()->cityStateZip($this->client->city, $this->client->state, $this->client->postal_code, false) ?: '&nbsp;';
$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) ?: '&nbsp;';
$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 ?: '&nbsp;', 'label' => $this->makeCustomField('client1')];
$data['$client2'] = ['value' => $this->client->custom_value2 ?: '&nbsp;', 'label' => $this->makeCustomField('client2')];
$data['$client3'] = ['value' => $this->client->custom_value3 ?: '&nbsp;', 'label' => $this->makeCustomField('client3')];
$data['$client4'] = ['value' => $this->client->custom_value4 ?: '&nbsp;', 'label' => $this->makeCustomField('client4')];
$data['$address1'] = ['value' => $this->client->address1 ?: '&nbsp;', 'label' => ctrans('texts.address1')];
$data['$address2'] = ['value' => $this->client->address2 ?: '&nbsp;', 'label' => ctrans('texts.address2')];
$data['$id_number'] = ['value' => $this->client->id_number ?: '&nbsp;', 'label' => ctrans('texts.id_number')];
$data['$vat_number'] = ['value' => $this->client->vat_number ?: '&nbsp;', 'label' => ctrans('texts.vat_number')];
$data['$website'] = ['value' => $this->client->present()->website() ?: '&nbsp;', 'label' => ctrans('texts.website')];
$data['$phone'] = ['value' => $this->client->present()->phone() ?: '&nbsp;', '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() ?: '&nbsp;', '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() ?: '&nbsp;', '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) ?: '&nbsp;', '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) ?: '&nbsp;', '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 : '&nbsp;';
$data['$contact2'] = isset($contact) ? $contact->custom_value2 : '&nbsp;';
$data['$contact3'] = isset($contact) ? $contact->custom_value3 : '&nbsp;';
$data['$contact4'] = isset($contact) ? $contact->custom_value4 : '&nbsp;';
$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 : '&nbsp;', 'label' => $this->makeCustomField('contact1')];
$data['$contact2'] = ['value' => isset($contact) ? $contact->custom_value2 : '&nbsp;', 'label' => $this->makeCustomField('contact1')];
$data['$contact3'] = ['value' => isset($contact) ? $contact->custom_value3 : '&nbsp;', 'label' => $this->makeCustomField('contact1')];
$data['$contact4'] = ['value' => isset($contact) ? $contact->custom_value4 : '&nbsp;', 'label' => $this->makeCustomField('contact1')];
$data['$company.city_state_postal'] = $this->company->present()->cityStateZip($settings->city, $settings->state, $settings->postal_code, false) ?: '&nbsp;';
$data['$company.postal_city_state'] = $this->company->present()->cityStateZip($settings->city, $settings->state, $settings->postal_code, true) ?: '&nbsp;';
$data['$company.name'] = $this->company->present()->name() ?: '&nbsp;';
$data['$company.company_name'] = &$data['$company.name'];
$data['$company.address1'] = $settings->address1 ?: '&nbsp;';
$data['$company.address2'] = $settings->address2 ?: '&nbsp;';
$data['$company.city'] = $settings->city ?: '&nbsp;';
$data['$company.state'] = $settings->state ?: '&nbsp;';
$data['$company.postal_code'] = $settings->postal_code ?: '&nbsp;';
$data['$company.country'] = Country::find($settings->country_id)->first()->name ?: '&nbsp;';
$data['$company.phone'] = $settings->phone ?: '&nbsp;';
$data['$company.email'] = $settings->email ?: '&nbsp;';
$data['$company.vat_number'] = $settings->vat_number ?: '&nbsp;';
$data['$company.id_number'] = $settings->id_number ?: '&nbsp;';
$data['$company.website'] = $settings->website ?: '&nbsp;';
$data['$company.address'] = $this->company->present()->address($settings) ?: '&nbsp;';
$data['$company.city_state_postal'] = ['value' => $this->company->present()->cityStateZip($settings->city, $settings->state, $settings->postal_code, false) ?: '&nbsp;', 'label' => ctrans('texts.city_state_postal')];
$data['$company.postal_city_state'] = ['value' => $this->company->present()->cityStateZip($settings->city, $settings->state, $settings->postal_code, true) ?: '&nbsp;', 'label' => ctrans('texts.postal_city_state')];
$data['$company.name'] = ['value' => $this->company->present()->name() ?: '&nbsp;', 'label' => ctrans('texts.company_name')];
$data['$company.company_name'] = &$data['$company.name'];
$data['$company.address1'] = ['value' => $settings->address1 ?: '&nbsp;', 'label' => ctrans('texts.address1')];
$data['$company.address2'] = ['value' => $settings->address2 ?: '&nbsp;', 'label' => ctrans('texts.address2')];
$data['$company.city'] = ['value' => $settings->city ?: '&nbsp;', 'label' => ctrans('texts.city')];
$data['$company.state'] = ['value' => $settings->state ?: '&nbsp;', 'label' => ctrans('texts.state')];
$data['$company.postal_code'] = ['value' => $settings->postal_code ?: '&nbsp;', 'label' => ctrans('texts.postal_code')];
$data['$company.country'] = ['value' => Country::find($settings->country_id)->first()->name ?: '&nbsp;', 'label' => ctrans('texts.country')];
$data['$company.phone'] = ['value' => $settings->phone ?: '&nbsp;', 'label' => ctrans('texts.phone')];
$data['$company.email'] = ['value' => $settings->email ?: '&nbsp;', 'label' => ctrans('texts.email')];
$data['$company.vat_number'] = ['value' => $settings->vat_number ?: '&nbsp;', 'label' => ctrans('texts.vat_number')];
$data['$company.id_number'] = ['value' => $settings->id_number ?: '&nbsp;', 'label' => ctrans('texts.id_number')];
$data['$company.website'] = ['value' => $settings->website ?: '&nbsp;', 'label' => ctrans('texts.website')];
$data['$company.address'] = ['value' => $this->company->present()->address($settings) ?: '&nbsp;', 'label' => ctrans('texts.address')];
$logo = $this->company->present()->logo($settings);
$data['$company.logo'] = "<img src='{$logo}' class='w-48' alt='logo'>" ?: '&nbsp;';
$data['$company_logo'] = &$data['$company.logo'];
$data['$company1'] = $settings->custom_value1 ?: '&nbsp;';
$data['$company2'] = $settings->custom_value2 ?: '&nbsp;';
$data['$company3'] = $settings->custom_value3 ?: '&nbsp;';
$data['$company4'] = $settings->custom_value4 ?: '&nbsp;';
$data['$company.logo'] = ['value' => "<img src='{$logo}' class='w-48' alt='logo'>" ?: '&nbsp;', 'label' => ctrans('texts.logo')];
$data['$company_logo'] = &$data['$company.logo'];
$data['$company1'] = ['value' => $settings->custom_value1 ?: '&nbsp;', 'label' => $this->makeCustomField('company1')];
$data['$company2'] = ['value' => $settings->custom_value2 ?: '&nbsp;', 'label' => $this->makeCustomField('company2')];
$data['$company3'] = ['value' => $settings->custom_value3 ?: '&nbsp;', 'label' => $this->makeCustomField('company3')];
$data['$company4'] = ['value' => $settings->custom_value4 ?: '&nbsp;', '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'),"/");
}
}

View File

@ -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

File diff suppressed because one or more lines are too long

View File

@ -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',
];

View File

@ -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>

View File

@ -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>

View File

@ -1,23 +1,9 @@
<!DOCTYPE html>
<html lang="{!! $lang !!}">
{!! $includes !!}
<body>
{!! $header !!}
{!! $body !!}
@if($product)
{!! $product !!}
@endif
@if($task)
{!! $task !!}
@endif
{!! $footer !!}
</body>
</html>

View File

@ -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')

View File

@ -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()

View File

@ -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
];

View File

@ -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();

View File

@ -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();

View File

@ -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);
}
//
}

View 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>');
}
}