mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-10-31 16:57:33 -04:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/develop' into develop
This commit is contained in:
		
						commit
						1bef3b0791
					
				| @ -1301,4 +1301,37 @@ class AccountController extends BaseController | ||||
| 
 | ||||
|         return Redirect::to("/settings/$section/", 301); | ||||
|     } | ||||
|      | ||||
|     public function previewEmail(\App\Services\TemplateService $templateService) | ||||
|     { | ||||
|         $template = Input::get('template'); | ||||
|         $invoice = Invoice::scope() | ||||
|                     ->invoices() | ||||
|                     ->withTrashed() | ||||
|                     ->first(); | ||||
|          | ||||
|         if ( ! $invoice) { | ||||
|             return trans('texts.create_invoice_for_sample'); | ||||
|         } | ||||
|          | ||||
|         $account = Auth::user()->account; | ||||
|          | ||||
|         // replace the variables with sample data
 | ||||
|         $data = [ | ||||
|             'account' => $account, | ||||
|             'invoice' => $invoice, | ||||
|             'invitation' => $invoice->invitations->first(), | ||||
|             'client' => $invoice->client, | ||||
|             'amount' => $invoice->amount  | ||||
|         ]; | ||||
|          | ||||
|         // create the email view 
 | ||||
|         $view = 'emails.' . $account->getTemplateView(ENTITY_INVOICE) . '_html'; | ||||
|         $data = array_merge($data, [ | ||||
|             'body' => $templateService->processVariables($template, $data), | ||||
|             'entityType' => ENTITY_INVOICE, | ||||
|         ]); | ||||
|          | ||||
|         return Response::view($view, $data); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -266,18 +266,7 @@ class AppController extends BaseController | ||||
|                 Cache::flush(); | ||||
|                 Session::flush(); | ||||
|                 Artisan::call('migrate', array('--force' => true)); | ||||
|                 foreach ([ | ||||
|                     'PaymentLibraries', | ||||
|                     'Fonts', | ||||
|                     'Banks', | ||||
|                     'InvoiceStatus', | ||||
|                     'Currencies', | ||||
|                     'DateFormats', | ||||
|                     'InvoiceDesigns', | ||||
|                     'PaymentTerms', | ||||
|                 ] as $seeder) { | ||||
|                     Artisan::call('db:seed', array('--force' => true, '--class' => "{$seeder}Seeder")); | ||||
|                 } | ||||
|                 Artisan::call('db:seed', array('--force' => true, '--class' => "UpdateSeeder")); | ||||
|                 Event::fire(new UserSettingsChanged()); | ||||
|                 Session::flash('message', trans('texts.processed_updates')); | ||||
|             } catch (Exception $e) { | ||||
|  | ||||
| @ -9,7 +9,7 @@ class ClientRequest extends EntityRequest { | ||||
|         $client = parent::entity(); | ||||
|          | ||||
|         // eager load the contacts
 | ||||
|         if ($client && ! count($client->contacts)) { | ||||
|         if ($client && ! $client->relationLoaded('contacts')) { | ||||
|             $client->load('contacts'); | ||||
|         } | ||||
|           | ||||
|  | ||||
| @ -8,8 +8,8 @@ class ExpenseRequest extends EntityRequest { | ||||
|     { | ||||
|         $expense = parent::entity(); | ||||
|          | ||||
|         // eager load the contacts
 | ||||
|         if ($expense && ! count($expense->documents)) { | ||||
|         // eager load the documents
 | ||||
|         if ($expense && ! $expense->relationLoaded('documents')) { | ||||
|             $expense->load('documents'); | ||||
|         } | ||||
|          | ||||
|  | ||||
| @ -8,8 +8,8 @@ class InvoiceRequest extends EntityRequest { | ||||
|     { | ||||
|         $invoice = parent::entity(); | ||||
|          | ||||
|         // eager load the contacts
 | ||||
|         if ($invoice && ! count($invoice->invoice_items)) { | ||||
|         // eager load the invoice items
 | ||||
|         if ($invoice && ! $invoice->relationLoaded('invoice_items')) { | ||||
|             $invoice->load('invoice_items'); | ||||
|         } | ||||
|           | ||||
|  | ||||
| @ -9,7 +9,7 @@ class VendorRequest extends EntityRequest { | ||||
|         $vendor = parent::entity(); | ||||
|          | ||||
|         // eager load the contacts
 | ||||
|         if ($vendor && ! count($vendor->vendor_contacts)) { | ||||
|         if ($vendor && ! $vendor->relationLoaded('vendor_contacts')) { | ||||
|             $vendor->load('vendor_contacts'); | ||||
|         } | ||||
|           | ||||
|  | ||||
| @ -208,6 +208,7 @@ Route::group([ | ||||
|     Route::resource('tax_rates', 'TaxRateController'); | ||||
|     Route::post('tax_rates/bulk', 'TaxRateController@bulk'); | ||||
| 
 | ||||
|     Route::get('settings/email_preview', 'AccountController@previewEmail'); | ||||
|     Route::get('company/{section}/{subSection?}', 'AccountController@redirectLegacy'); | ||||
|     Route::get('settings/data_visualizations', 'ReportController@d3'); | ||||
|     Route::get('settings/charts_and_reports', 'ReportController@showReports'); | ||||
|  | ||||
| @ -341,6 +341,7 @@ class Utils | ||||
|         $currency = self::getFromCache($currencyId, 'currencies'); | ||||
|         $thousand = $currency->thousand_separator; | ||||
|         $decimal = $currency->decimal_separator; | ||||
|         $precision = $currency->precision; | ||||
|         $code = $currency->code; | ||||
|         $swapSymbol = false; | ||||
| 
 | ||||
| @ -355,7 +356,7 @@ class Utils | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $value = number_format($value, $currency->precision, $decimal, $thousand); | ||||
|         $value = number_format($value, $precision, $decimal, $thousand); | ||||
|         $symbol = $currency->symbol; | ||||
| 
 | ||||
|         if ($showCode || !$symbol) { | ||||
|  | ||||
| @ -212,7 +212,9 @@ class Account extends Eloquent | ||||
| 
 | ||||
|     public function isGatewayConfigured($gatewayId = 0) | ||||
|     { | ||||
|         $this->load('account_gateways'); | ||||
|         if ( ! $this->relationLoaded('account_gateways')) { | ||||
|             $this->load('account_gateways'); | ||||
|         } | ||||
| 
 | ||||
|         if ($gatewayId) { | ||||
|             return $this->getGatewayConfig($gatewayId) != false; | ||||
| @ -241,7 +243,7 @@ class Account extends Eloquent | ||||
|             return $this->name; | ||||
|         } | ||||
| 
 | ||||
|         $this->load('users'); | ||||
|         //$this->load('users');
 | ||||
|         $user = $this->users()->first(); | ||||
| 
 | ||||
|         return $user->getDisplayName(); | ||||
| @ -1167,6 +1169,11 @@ class Account extends Eloquent | ||||
|         return str_replace('/>', ' />', $template); | ||||
|     } | ||||
| 
 | ||||
|     public function getTemplateView($view = '') | ||||
|     { | ||||
|         return $this->getEmailDesignId() == EMAIL_DESIGN_PLAIN ? $view : 'design' . $this->getEmailDesignId(); | ||||
|     } | ||||
| 
 | ||||
|     public function getEmailFooter() | ||||
|     { | ||||
|         if ($this->email_footer) { | ||||
|  | ||||
| @ -256,13 +256,17 @@ class Client extends EntityModel | ||||
| 
 | ||||
|     public function getGatewayToken() | ||||
|     { | ||||
|         $this->account->load('account_gateways'); | ||||
|         $account = $this->account; | ||||
|          | ||||
|         if (!count($this->account->account_gateways)) { | ||||
|         if ( ! $account->relationLoaded('account_gateways')) { | ||||
|             $account->load('account_gateways'); | ||||
|         } | ||||
| 
 | ||||
|         if (!count($account->account_gateways)) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         $accountGateway = $this->account->getGatewayConfig(GATEWAY_STRIPE); | ||||
|         $accountGateway = $account->getGatewayConfig(GATEWAY_STRIPE); | ||||
|          | ||||
|         if (!$accountGateway) { | ||||
|             return false; | ||||
|  | ||||
| @ -228,6 +228,12 @@ class Invoice extends EntityModel implements BalanceAffecting | ||||
|         return $this->hasMany('App\Models\Expense','invoice_id','id')->withTrashed(); | ||||
|     } | ||||
| 
 | ||||
|     public function scopeInvoices($query) | ||||
|     { | ||||
|         return $query->where('is_quote', '=', false) | ||||
|                      ->where('is_recurring', '=', false); | ||||
|     } | ||||
| 
 | ||||
|     public function markInvitationsSent($notify = false) | ||||
|     { | ||||
|         foreach ($this->invitations as $invitation) { | ||||
|  | ||||
| @ -1,17 +1,13 @@ | ||||
| <?php namespace App\Ninja\Mailers; | ||||
| 
 | ||||
| use Form; | ||||
| use HTML; | ||||
| use Utils; | ||||
| use Event; | ||||
| use URL; | ||||
| use Auth; | ||||
| 
 | ||||
| use App\Services\TemplateService; | ||||
| use App\Models\Invoice; | ||||
| use App\Models\Payment; | ||||
| use App\Models\Activity; | ||||
| use App\Models\Gateway; | ||||
| 
 | ||||
| use App\Events\InvoiceWasEmailed; | ||||
| use App\Events\QuoteWasEmailed; | ||||
| 
 | ||||
| @ -36,6 +32,11 @@ class ContactMailer extends Mailer | ||||
|         'paymentButton', | ||||
|     ]; | ||||
| 
 | ||||
|     public function __construct(TemplateService $templateService) | ||||
|     { | ||||
|         $this->templateService = $templateService; | ||||
|     } | ||||
| 
 | ||||
|     public function sendInvoice(Invoice $invoice, $reminder = false, $pdfString = false) | ||||
|     { | ||||
|         $invoice->load('invitations', 'client.language', 'account'); | ||||
| @ -144,7 +145,7 @@ class ContactMailer extends Mailer | ||||
|         } | ||||
| 
 | ||||
|         $data = [ | ||||
|             'body' => $this->processVariables($body, $variables), | ||||
|             'body' => $this->templateService->processVariables($body, $variables), | ||||
|             'link' => $invitation->getLink(), | ||||
|             'entityType' => $invoice->getEntityType(), | ||||
|             'invoiceId' => $invoice->id, | ||||
| @ -160,14 +161,9 @@ class ContactMailer extends Mailer | ||||
|             $data['pdfFileName'] = $invoice->getFileName(); | ||||
|         } | ||||
| 
 | ||||
|         $subject = $this->processVariables($subject, $variables); | ||||
|         $subject = $this->templateService->processVariables($subject, $variables); | ||||
|         $fromEmail = $user->email; | ||||
| 
 | ||||
|         if ($account->getEmailDesignId() == EMAIL_DESIGN_PLAIN) { | ||||
|             $view = ENTITY_INVOICE; | ||||
|         } else { | ||||
|             $view = 'design' . ($account->getEmailDesignId() - 1); | ||||
|         } | ||||
|         $view = $account->getTemplateView(ENTITY_INVOICE); | ||||
|          | ||||
|         $response = $this->sendTo($invitation->contact->email, $fromEmail, $account->getDisplayName(), $subject, $view, $data); | ||||
| 
 | ||||
| @ -230,7 +226,7 @@ class ContactMailer extends Mailer | ||||
|         ]; | ||||
| 
 | ||||
|         $data = [ | ||||
|             'body' => $this->processVariables($emailTemplate, $variables), | ||||
|             'body' => $this->templateService->processVariables($emailTemplate, $variables), | ||||
|             'link' => $invitation->getLink(), | ||||
|             'invoice' => $invoice, | ||||
|             'client' => $client, | ||||
| @ -244,14 +240,10 @@ class ContactMailer extends Mailer | ||||
|             $data['pdfFileName'] = $invoice->getFileName(); | ||||
|         } | ||||
| 
 | ||||
|         $subject = $this->processVariables($emailSubject, $variables); | ||||
|         $subject = $this->templateService->processVariables($emailSubject, $variables); | ||||
|         $data['invoice_id'] = $payment->invoice->id; | ||||
| 
 | ||||
|         if ($account->getEmailDesignId() == EMAIL_DESIGN_PLAIN) { | ||||
|             $view = 'payment_confirmation'; | ||||
|         } else { | ||||
|             $view = 'design' . ($account->getEmailDesignId() - 1); | ||||
|         } | ||||
|         $view = $account->getTemplateView('payment_confirmation'); | ||||
| 
 | ||||
|         if ($user->email && $contact->email) { | ||||
|             $this->sendTo($contact->email, $user->email, $accountName, $subject, $view, $data); | ||||
| @ -281,75 +273,4 @@ class ContactMailer extends Mailer | ||||
|          | ||||
|         $this->sendTo($email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data); | ||||
|     } | ||||
| 
 | ||||
|     private function processVariables($template, $data) | ||||
|     { | ||||
|         $account = $data['account']; | ||||
|         $client = $data['client']; | ||||
|         $invitation = $data['invitation']; | ||||
|         $invoice = $invitation->invoice; | ||||
|         $passwordHTML = isset($data['password'])?'<p>'.trans('texts.password').': '.$data['password'].'<p>':false; | ||||
|         $documentsHTML = ''; | ||||
| 
 | ||||
|         if($account->hasFeature(FEATURE_DOCUMENTS) && $invoice->hasDocuments()){ | ||||
|             $documentsHTML .= trans('texts.email_documents_header').'<ul>'; | ||||
|             foreach($invoice->documents as $document){ | ||||
|                 $documentsHTML .= '<li><a href="'.HTML::entities($document->getClientUrl($invitation)).'">'.HTML::entities($document->name).'</a></li>'; | ||||
|             } | ||||
|             foreach($invoice->expenses as $expense){ | ||||
|                 foreach($expense->documents as $document){ | ||||
|                     $documentsHTML .= '<li><a href="'.HTML::entities($document->getClientUrl($invitation)).'">'.HTML::entities($document->name).'</a></li>'; | ||||
|                 } | ||||
|             } | ||||
|             $documentsHTML .= '</ul>'; | ||||
|         } | ||||
|          | ||||
|         $variables = [ | ||||
|             '$footer' => $account->getEmailFooter(), | ||||
|             '$client' => $client->getDisplayName(), | ||||
|             '$account' => $account->getDisplayName(), | ||||
|             '$dueDate' => $account->formatDate($invoice->due_date), | ||||
|             '$invoiceDate' => $account->formatDate($invoice->invoice_date), | ||||
|             '$contact' => $invitation->contact->getDisplayName(), | ||||
|             '$firstName' => $invitation->contact->first_name, | ||||
|             '$amount' => $account->formatMoney($data['amount'], $client), | ||||
|             '$invoice' => $invoice->invoice_number, | ||||
|             '$quote' => $invoice->invoice_number, | ||||
|             '$link' => $invitation->getLink(), | ||||
|             '$password' => $passwordHTML, | ||||
|             '$viewLink' => $invitation->getLink().'$password', | ||||
|             '$viewButton' => Form::emailViewButton($invitation->getLink(), $invoice->getEntityType()).'$password', | ||||
|             '$paymentLink' => $invitation->getLink('payment').'$password', | ||||
|             '$paymentButton' => Form::emailPaymentButton($invitation->getLink('payment')).'$password', | ||||
|             '$customClient1' => $account->custom_client_label1, | ||||
|             '$customClient2' => $account->custom_client_label2, | ||||
|             '$customInvoice1' => $account->custom_invoice_text_label1, | ||||
|             '$customInvoice2' => $account->custom_invoice_text_label2, | ||||
|             '$documents' => $documentsHTML, | ||||
|         ]; | ||||
| 
 | ||||
|         // Add variables for available payment types
 | ||||
|         foreach (Gateway::$paymentTypes as $type) { | ||||
|             $camelType = Gateway::getPaymentTypeName($type); | ||||
|             $type = Utils::toSnakeCase($camelType); | ||||
|             $variables["\${$camelType}Link"] = $invitation->getLink('payment') . "/{$type}"; | ||||
|             $variables["\${$camelType}Button"] = Form::emailPaymentButton($invitation->getLink('payment')  . "/{$type}"); | ||||
|         } | ||||
|          | ||||
|         $includesPasswordPlaceholder = strpos($template, '$password') !== false; | ||||
|                  | ||||
|         $str = str_replace(array_keys($variables), array_values($variables), $template); | ||||
| 
 | ||||
|         if(!$includesPasswordPlaceholder && $passwordHTML){ | ||||
|             $pos = strrpos($str, '$password'); | ||||
|             if($pos !== false) | ||||
|             { | ||||
|                 $str = substr_replace($str, $passwordHTML, $pos, 9/* length of "$password" */); | ||||
|             } | ||||
|         }         | ||||
|         $str = str_replace('$password', '', $str); | ||||
|         $str = autolink($str, 100); | ||||
|          | ||||
|         return $str; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -18,7 +18,7 @@ class InvoicePresenter extends Presenter { | ||||
| 
 | ||||
|     public function balanceDueLabel() | ||||
|     { | ||||
|         if ($this->entity->partial) { | ||||
|         if ($this->entity->partial > 0) { | ||||
|             return 'partial_due'; | ||||
|         } elseif ($this->entity->is_quote) { | ||||
|             return 'total'; | ||||
|  | ||||
| @ -167,6 +167,7 @@ class AccountRepository | ||||
|             ENTITY_QUOTE, | ||||
|             ENTITY_TASK, | ||||
|             ENTITY_EXPENSE, | ||||
|             ENTITY_VENDOR, | ||||
|             ENTITY_RECURRING_INVOICE, | ||||
|             ENTITY_PAYMENT, | ||||
|             ENTITY_CREDIT | ||||
| @ -183,15 +184,22 @@ class AccountRepository | ||||
|             ]; | ||||
|         } | ||||
| 
 | ||||
|         $features[] = ['dashboard', '/dashboard']; | ||||
|         $features[] = ['customize_design', '/settings/customize_design']; | ||||
|         $features[] = ['new_tax_rate', '/tax_rates/create']; | ||||
|         $features[] = ['new_product', '/products/create']; | ||||
|         $features[] = ['new_user', '/users/create']; | ||||
|         $features[] = ['custom_fields', '/settings/invoice_settings'];	 | ||||
|         $features = array_merge($features, [ | ||||
|             ['dashboard', '/dashboard'], | ||||
|             ['customize_design', '/settings/customize_design'], | ||||
|             ['new_tax_rate', '/tax_rates/create'], | ||||
|             ['new_product', '/products/create'], | ||||
|             ['new_user', '/users/create'], | ||||
|             ['custom_fields', '/settings/invoice_settings'], | ||||
|             ['invoice_number', '/settings/invoice_settings'], | ||||
|         ]); | ||||
| 
 | ||||
|         $settings = array_merge(Account::$basicSettings, Account::$advancedSettings); | ||||
| 
 | ||||
|         if ( ! Utils::isNinjaProd()) { | ||||
|             $settings[] = ACCOUNT_SYSTEM_SETTINGS; | ||||
|         } | ||||
| 
 | ||||
|         foreach ($settings as $setting) { | ||||
|             $features[] = [ | ||||
|                 $setting, | ||||
| @ -332,7 +340,7 @@ class AccountRepository | ||||
|             $client->public_id = $account->id; | ||||
|             $client->user_id = $ninjaAccount->users()->first()->id; | ||||
|             $client->currency_id = 1; | ||||
|             foreach (['name', 'address1', 'address2', 'city', 'state', 'postal_code', 'country_id', 'work_phone', 'language_id'] as $field) { | ||||
|             foreach (['name', 'address1', 'address2', 'city', 'state', 'postal_code', 'country_id', 'work_phone', 'language_id', 'vat_number'] as $field) { | ||||
|                 $client->$field = $account->$field; | ||||
|             } | ||||
|             $ninjaAccount->clients()->save($client); | ||||
|  | ||||
| @ -105,7 +105,7 @@ class ClientRepository extends BaseRepository | ||||
| 
 | ||||
|         // If the primary is set ensure it's listed first
 | ||||
|         usort($contacts, function ($left, $right) { | ||||
|             return (isset($right['is_primary']) ? $right['is_primary'] : 0) - (isset($left['is_primary']) ? $left['is_primary'] : 0); | ||||
|             return (isset($right['is_primary']) ? $right['is_primary'] : 1) - (isset($left['is_primary']) ? $left['is_primary'] : 0); | ||||
|         }); | ||||
|          | ||||
|         foreach ($contacts as $contact) { | ||||
|  | ||||
							
								
								
									
										80
									
								
								app/Services/TemplateService.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								app/Services/TemplateService.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | ||||
| <?php namespace App\Services; | ||||
| 
 | ||||
| use Form; | ||||
| use HTML; | ||||
| use Utils; | ||||
| use App\Models\Gateway; | ||||
| 
 | ||||
| class TemplateService | ||||
| { | ||||
|     public function processVariables($template, $data) | ||||
|     { | ||||
|         $account = $data['account']; | ||||
|         $client = $data['client']; | ||||
|         $invitation = $data['invitation']; | ||||
|         $invoice = $invitation->invoice; | ||||
|         $passwordHTML = isset($data['password'])?'<p>'.trans('texts.password').': '.$data['password'].'<p>':false; | ||||
|         $documentsHTML = ''; | ||||
| 
 | ||||
|         if ($account->hasFeature(FEATURE_DOCUMENTS) && $invoice->hasDocuments()) { | ||||
|             $documentsHTML .= trans('texts.email_documents_header').'<ul>'; | ||||
|             foreach($invoice->documents as $document){ | ||||
|                 $documentsHTML .= '<li><a href="'.HTML::entities($document->getClientUrl($invitation)).'">'.HTML::entities($document->name).'</a></li>'; | ||||
|             } | ||||
|             foreach($invoice->expenses as $expense){ | ||||
|                 foreach($expense->documents as $document){ | ||||
|                     $documentsHTML .= '<li><a href="'.HTML::entities($document->getClientUrl($invitation)).'">'.HTML::entities($document->name).'</a></li>'; | ||||
|                 } | ||||
|             } | ||||
|             $documentsHTML .= '</ul>'; | ||||
|         } | ||||
|          | ||||
|         $variables = [ | ||||
|             '$footer' => $account->getEmailFooter(), | ||||
|             '$client' => $client->getDisplayName(), | ||||
|             '$account' => $account->getDisplayName(), | ||||
|             '$dueDate' => $account->formatDate($invoice->due_date), | ||||
|             '$invoiceDate' => $account->formatDate($invoice->invoice_date), | ||||
|             '$contact' => $invitation->contact->getDisplayName(), | ||||
|             '$firstName' => $invitation->contact->first_name, | ||||
|             '$amount' => $account->formatMoney($data['amount'], $client), | ||||
|             '$invoice' => $invoice->invoice_number, | ||||
|             '$quote' => $invoice->invoice_number, | ||||
|             '$link' => $invitation->getLink(), | ||||
|             '$password' => $passwordHTML, | ||||
|             '$viewLink' => $invitation->getLink().'$password', | ||||
|             '$viewButton' => Form::emailViewButton($invitation->getLink(), $invoice->getEntityType()).'$password', | ||||
|             '$paymentLink' => $invitation->getLink('payment').'$password', | ||||
|             '$paymentButton' => Form::emailPaymentButton($invitation->getLink('payment')).'$password', | ||||
|             '$customClient1' => $account->custom_client_label1, | ||||
|             '$customClient2' => $account->custom_client_label2, | ||||
|             '$customInvoice1' => $account->custom_invoice_text_label1, | ||||
|             '$customInvoice2' => $account->custom_invoice_text_label2, | ||||
|             '$documents' => $documentsHTML, | ||||
|         ]; | ||||
| 
 | ||||
|         // Add variables for available payment types
 | ||||
|         foreach (Gateway::$paymentTypes as $type) { | ||||
|             $camelType = Gateway::getPaymentTypeName($type); | ||||
|             $type = Utils::toSnakeCase($camelType); | ||||
|             $variables["\${$camelType}Link"] = $invitation->getLink('payment') . "/{$type}"; | ||||
|             $variables["\${$camelType}Button"] = Form::emailPaymentButton($invitation->getLink('payment')  . "/{$type}"); | ||||
|         } | ||||
|          | ||||
|         $includesPasswordPlaceholder = strpos($template, '$password') !== false; | ||||
|                  | ||||
|         $str = str_replace(array_keys($variables), array_values($variables), $template); | ||||
| 
 | ||||
|         if (!$includesPasswordPlaceholder && $passwordHTML) { | ||||
|             $pos = strrpos($str, '$password'); | ||||
|             if ($pos !== false) | ||||
|             { | ||||
|                 $str = substr_replace($str, $passwordHTML, $pos, 9/* length of "$password" */); | ||||
|             } | ||||
|         }         | ||||
|         $str = str_replace('$password', '', $str); | ||||
|         $str = autolink($str, 100); | ||||
|          | ||||
|         return $str; | ||||
|     }     | ||||
| } | ||||
| @ -8,6 +8,7 @@ class CurrenciesSeeder extends Seeder | ||||
|     { | ||||
|         Eloquent::unguard(); | ||||
| 
 | ||||
|         // http://www.localeplanet.com/icu/currency.html
 | ||||
|         $currencies = [ | ||||
|             ['name' => 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], | ||||
|             ['name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], | ||||
| @ -56,6 +57,7 @@ class CurrenciesSeeder extends Seeder | ||||
|             ['name' => 'Japanese Yen', 'code' => 'JPY', 'symbol' => '¥', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'], | ||||
|             ['name' => 'Maldivian Rufiyaa', 'code' => 'MVR', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], | ||||
|             ['name' => 'Costa Rican Colón', 'code' => 'CRC', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], | ||||
|             ['name' => 'Pakistani Rupee', 'code' => 'PKR', 'symbol' => 'Rs ', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'], | ||||
|         ]; | ||||
| 
 | ||||
|         foreach ($currencies as $currency) { | ||||
|  | ||||
| @ -23,5 +23,6 @@ class DatabaseSeeder extends Seeder | ||||
|         $this->call('DateFormatsSeeder'); | ||||
|         $this->call('InvoiceDesignsSeeder'); | ||||
|         $this->call('PaymentTermsSeeder'); | ||||
|         $this->call('LanguageSeeder'); | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										41
									
								
								database/seeds/LanguageSeeder.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								database/seeds/LanguageSeeder.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| <?php | ||||
| 
 | ||||
| use App\Models\Language; | ||||
| 
 | ||||
| class LanguageSeeder extends Seeder | ||||
| { | ||||
|     public function run() | ||||
|     { | ||||
|         Eloquent::unguard(); | ||||
| 
 | ||||
|         $languages = [ | ||||
|             ['name' => 'English', 'locale' => 'en'], | ||||
|             ['name' => 'Italian', 'locale' => 'it'], | ||||
|             ['name' => 'German', 'locale' => 'de'], | ||||
|             ['name' => 'French', 'locale' => 'fr'], | ||||
|             ['name' => 'Brazilian Portuguese', 'locale' => 'pt_BR'], | ||||
|             ['name' => 'Dutch', 'locale' => 'nl'], | ||||
|             ['name' => 'Spanish', 'locale' => 'es'], | ||||
|             ['name' => 'Norwegian', 'locale' => 'nb_NO'], | ||||
|             ['name' => 'Danish', 'locale' => 'da'], | ||||
|             ['name' => 'Japanese', 'locale' => 'ja'], | ||||
|             ['name' => 'Swedish', 'locale' => 'sv'], | ||||
|             ['name' => 'Spanish - Spain', 'locale' => 'es_ES'], | ||||
|             ['name' => 'French - Canada', 'locale' => 'fr_CA'], | ||||
|             ['name' => 'Lithuanian', 'locale' => 'lt'],   | ||||
|             ['name' => 'Polish', 'locale' => 'pl'], | ||||
|         ]; | ||||
| 
 | ||||
|         foreach ($languages as $language) { | ||||
|             $record = Language::whereLocale($language['locale'])->first(); | ||||
|             if ($record) { | ||||
|                 $record->name = $language['name']; | ||||
|                 $record->save(); | ||||
|             } else { | ||||
|                 Language::create($language); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Eloquent::reguard(); | ||||
|     } | ||||
| } | ||||
| @ -19,5 +19,6 @@ class UpdateSeeder extends Seeder | ||||
|         $this->call('DateFormatsSeeder'); | ||||
|         $this->call('InvoiceDesignsSeeder'); | ||||
|         $this->call('PaymentTermsSeeder'); | ||||
|         $this->call('LanguageSeeder'); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,9 +1,13 @@ | ||||
| <?php | ||||
| 
 | ||||
| use App\Models\User; | ||||
| use App\Models\Font; | ||||
| use App\Models\Account; | ||||
| use App\Models\Company; | ||||
| use App\Models\Affiliate; | ||||
| use App\Models\Country; | ||||
| use App\Models\InvoiceDesign; | ||||
| use Faker\Factory; | ||||
| 
 | ||||
| class UserTableSeeder extends Seeder | ||||
| { | ||||
| @ -14,11 +18,25 @@ class UserTableSeeder extends Seeder | ||||
| 
 | ||||
|         Eloquent::unguard(); | ||||
| 
 | ||||
|         $faker = Faker\Factory::create(); | ||||
|         $company = Company::create(); | ||||
|          | ||||
|         $account = Account::create([ | ||||
|             //'name' => 'Test Account',
 | ||||
|             'name' => $faker->name, | ||||
|             'address1' => $faker->streetAddress, | ||||
|             'address2' => $faker->secondaryAddress, | ||||
|             'city' => $faker->city, | ||||
|             'state' => $faker->state, | ||||
|             'postal_code' => $faker->postcode, | ||||
|             'country_id' => Country::all()->random()->id,  | ||||
|             'account_key' => str_random(RANDOM_KEY_LENGTH), | ||||
|             'invoice_terms' => $faker->text($faker->numberBetween(50, 300)), | ||||
|             'work_phone' => $faker->phoneNumber, | ||||
|             'work_email' => $faker->safeEmail, | ||||
|             'invoice_design_id' => min(InvoiceDesign::all()->random()->id, 10), | ||||
|             'header_font_id' => min(Font::all()->random()->id, 17), | ||||
|             'body_font_id' => min(Font::all()->random()->id, 17), | ||||
|             'primary_color' => $faker->hexcolor, | ||||
|             'timezone_id' => 1, | ||||
|             'company_id' => $company->id, | ||||
|         ]); | ||||
| @ -30,6 +48,8 @@ class UserTableSeeder extends Seeder | ||||
|             'password' => Hash::make(TEST_PASSWORD), | ||||
|             'registered' => true, | ||||
|             'confirmed' => true, | ||||
|             'notify_sent' => false, | ||||
|             'notify_paid' => false, | ||||
|         ]); | ||||
| 
 | ||||
|         Affiliate::create([ | ||||
|  | ||||
| @ -31196,7 +31196,7 @@ NINJA.decodeJavascript = function(invoice, javascript) | ||||
|             field = toSnakeCase(field); | ||||
|             var value = getDescendantProp(invoice, field); | ||||
|             if (match.indexOf('?') < 0 || value) { | ||||
|                 if (invoice.partial && field == 'balance_due') { | ||||
|                 if (invoice.partial > 0 && field == 'balance_due') { | ||||
|                     field = 'partial_due'; | ||||
|                 } else if (invoice.is_quote) { | ||||
|                     field = field.replace('invoice', 'quote'); | ||||
| @ -31584,7 +31584,7 @@ NINJA.invoiceDetails = function(invoice) { | ||||
|     ], | ||||
|     [ | ||||
|         {text: (invoice.is_quote ? invoiceLabels.valid_until : invoiceLabels.due_date)},  | ||||
|         {text: invoice.due_date} | ||||
|         {text: invoice.is_recurring ? false : invoice.due_date} | ||||
|     ] | ||||
|     ]; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										4
									
								
								public/css/built.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								public/css/built.css
									
									
									
									
										vendored
									
									
								
							| @ -2539,6 +2539,10 @@ ul.dropdown-menu, | ||||
|     box-shadow: 0 0 10px 2px rgba(0,0,0,.05); | ||||
| } | ||||
| 
 | ||||
| .twitter-typeahead .tt-menu { | ||||
|     overflow-x: hidden; | ||||
| } | ||||
| 
 | ||||
| .panel-default, | ||||
| canvas { | ||||
|     border: 1px solid; | ||||
|  | ||||
							
								
								
									
										4
									
								
								public/css/style.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								public/css/style.css
									
									
									
									
										vendored
									
									
								
							| @ -410,6 +410,10 @@ ul.dropdown-menu, | ||||
|     box-shadow: 0 0 10px 2px rgba(0,0,0,.05); | ||||
| } | ||||
| 
 | ||||
| .twitter-typeahead .tt-menu { | ||||
|     overflow-x: hidden; | ||||
| } | ||||
| 
 | ||||
| .panel-default, | ||||
| canvas { | ||||
|     border: 1px solid; | ||||
|  | ||||
| @ -192,7 +192,7 @@ NINJA.decodeJavascript = function(invoice, javascript) | ||||
|             field = toSnakeCase(field); | ||||
|             var value = getDescendantProp(invoice, field); | ||||
|             if (match.indexOf('?') < 0 || value) { | ||||
|                 if (invoice.partial && field == 'balance_due') { | ||||
|                 if (invoice.partial > 0 && field == 'balance_due') { | ||||
|                     field = 'partial_due'; | ||||
|                 } else if (invoice.is_quote) { | ||||
|                     field = field.replace('invoice', 'quote'); | ||||
| @ -580,7 +580,7 @@ NINJA.invoiceDetails = function(invoice) { | ||||
|     ], | ||||
|     [ | ||||
|         {text: (invoice.is_quote ? invoiceLabels.valid_until : invoiceLabels.due_date)},  | ||||
|         {text: invoice.due_date} | ||||
|         {text: invoice.is_recurring ? false : invoice.due_date} | ||||
|     ] | ||||
|     ]; | ||||
| 
 | ||||
|  | ||||
| @ -1176,6 +1176,8 @@ $LANG = array( | ||||
|     'page_size' => 'Page Size', | ||||
|     'live_preview_disabled' => 'Live preview has been disabled to support selected font', | ||||
|     'invoice_number_padding' => 'Padding', | ||||
|     'preview' => 'Preview', | ||||
|     'list_vendors' => 'List Vendors', | ||||
| 
 | ||||
| ); | ||||
| 
 | ||||
|  | ||||
| @ -94,9 +94,9 @@ | ||||
| 						</div> | ||||
| 					@endif | ||||
| 					@if (Utils::isNinjaProd()) | ||||
| 					{!! Former::actions( Button::success(trans('texts.plan_upgrade'))->large()->withAttributes(['onclick' => 'showChangePlan()'])->appendIcon(Icon::create('plus-sign'))) !!} | ||||
| 					@else | ||||
| 					{!! Former::actions( Button::success(trans('texts.white_label_button'))->large()->withAttributes(['onclick' => 'loadImages("#whiteLabelModal");$("#whiteLabelModal").modal("show");'])->appendIcon(Icon::create('plus-sign'))) !!} | ||||
| 					   {!! Former::actions( Button::success(trans('texts.plan_upgrade'))->large()->withAttributes(['onclick' => 'showChangePlan()'])->appendIcon(Icon::create('plus-sign'))) !!} | ||||
| 					@elseif (!$account->hasFeature(FEATURE_WHITE_LABEL)) | ||||
| 					   {!! Former::actions( Button::success(trans('texts.white_label_button'))->large()->withAttributes(['onclick' => 'loadImages("#whiteLabelModal");$("#whiteLabelModal").modal("show");'])->appendIcon(Icon::create('plus-sign'))) !!} | ||||
| 					@endif | ||||
| 				@endif | ||||
| 			</div> | ||||
|  | ||||
| @ -62,11 +62,14 @@ | ||||
|                 <div id="{{ $field }}_template_preview"></div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <p> <p/> | ||||
|         <div class="row"> | ||||
|             <div class="col-md-12"> | ||||
|                 <p> <p/> | ||||
|             <div class="col-md-10"> | ||||
|                 @include('partials/quill_toolbar', ['name' => $field]) | ||||
|             </div> | ||||
|             <div class="col-md-2" style="padding-top:10px"> | ||||
|                 {!! Button::primary(trans('texts.preview'))->withAttributes(['onclick' => 'serverPreview("'.$field.'")'])->small() !!} | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| @ -25,11 +25,16 @@ | ||||
| 
 | ||||
| 
 | ||||
|     {!! Former::vertical_open()->addClass('warn-on-exit') !!} | ||||
|     {!! Former::populate($account) !!} | ||||
| 
 | ||||
|     @foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_PAYMENT, REMINDER1, REMINDER2, REMINDER3] as $type) | ||||
|         @foreach (['subject', 'template'] as $field) | ||||
|             {!! Former::populateField("email_{$field}_{$type}", $templates[$type][$field]) !!} | ||||
|             {{ Former::populateField("email_{$field}_{$type}", $templates[$type][$field]) }} | ||||
|         @endforeach | ||||
|     @endforeach | ||||
| 
 | ||||
|     @foreach ([REMINDER1, REMINDER2, REMINDER3] as $type) | ||||
|         @foreach (['enable', 'num_days', 'direction', 'field'] as $field) | ||||
|             {{ Former::populateField("{$field}_{$type}", $account->{"{$field}_{$type}"}) }} | ||||
|         @endforeach | ||||
|     @endforeach | ||||
| 
 | ||||
| @ -80,6 +85,26 @@ | ||||
|     </div> | ||||
| 
 | ||||
| 
 | ||||
|     <div class="modal fade" id="templatePreviewModal" tabindex="-1" role="dialog" aria-labelledby="templatePreviewModalLabel" aria-hidden="true"> | ||||
|         <div class="modal-dialog" style="width:800px"> | ||||
|             <div class="modal-content"> | ||||
|                 <div class="modal-header"> | ||||
|                     <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> | ||||
|                     <h4 class="modal-title" id="templatePreviewModalLabel">{{ trans('texts.preview') }}</h4> | ||||
|                 </div> | ||||
| 
 | ||||
|                 <div class="modal-body"> | ||||
|                     <iframe id="server-preview" frameborder="1" width="100%" height="500px"/></iframe> | ||||
|                 </div> | ||||
| 
 | ||||
|                 <div class="modal-footer" style="margin-top: 0px"> | ||||
|                     <button type="button" class="btn btn-primary" data-dismiss="modal">{{ trans('texts.close') }}</button> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
| 
 | ||||
|     <div class="modal fade" id="templateHelpModal" tabindex="-1" role="dialog" aria-labelledby="templateHelpModalLabel" aria-hidden="true"> | ||||
|         <div class="modal-dialog" style="min-width:150px"> | ||||
|             <div class="modal-content"> | ||||
| @ -158,6 +183,22 @@ | ||||
|             }             | ||||
|         } | ||||
| 
 | ||||
|         function serverPreview(field) { | ||||
|             console.log(field); | ||||
|             $('#templatePreviewModal').modal('show'); | ||||
|             var template = $('#email_template_' + field).val(); | ||||
|             var url = '{{ URL::to('settings/email_preview') }}?template=' + template; | ||||
|             $('#server-preview').attr('src', url).load(function() { | ||||
|                 // disable links in the preview 
 | ||||
|                 $('iframe').contents().find('a').each(function(index) { | ||||
|                     $(this).on('click', function(event) { | ||||
|                         event.preventDefault(); | ||||
|                         event.stopPropagation(); | ||||
|                     }); | ||||
|                 }); | ||||
|             });             | ||||
|         } | ||||
| 
 | ||||
|         $(function() { | ||||
|             for (var i=0; i<entityTypes.length; i++) { | ||||
|                 var entityType = entityTypes[i]; | ||||
|  | ||||
| @ -12,30 +12,30 @@ | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td style="border-collapse: collapse;"> | ||||
|             <table cellpadding="10" cellspacing="0" border="0" bgcolor="{{ $account->primary_color ?: '#2E2B2B' }}" width="580" align="center" class="header"  | ||||
|                 style="border-bottom-width: 6px; border-bottom-color: {{ $account->primary_color ?: '#2E2B2B' }}; border-bottom-style: solid;"> | ||||
|             <table cellpadding="10" cellspacing="0" border="0" bgcolor="#F4F5F5" width="600" align="center"  | ||||
|                 class="header" style="border-top-width: 6px; border-top-color: {{ $account->primary_color ?: '#2E2B2B' }}; border-top-style: solid;"> | ||||
|                 <tr> | ||||
|                     <td class="logo" width="205" style="border-collapse: collapse; vertical-align: middle; line-height: 16px;" valign="middle"> | ||||
|                     <td class="logo" width="208" style="border-collapse: collapse; vertical-align: middle;" valign="middle"> | ||||
|                         @include('emails.partials.account_logo') | ||||
|                     </td> | ||||
|                     <td width="183" style="border-collapse: collapse; vertical-align: middle; line-height: 16px;" valign="middle"> | ||||
|                         <p class="left" style="line-height: 22px; margin: 3px 0 0; padding: 0;"> | ||||
|                     <td width="183" style="border-collapse: collapse; vertical-align: middle;" valign="middle"> | ||||
|                         <p class="left" style="line-height: 22px; margin: 0; padding: 2px 0 0;"> | ||||
|                             @if ($invoice->due_date) | ||||
|                                 <span style="font-size: 11px; color: #8f8d8e;"> | ||||
|                                     {{ strtoupper(trans('texts.due_by', ['date' => $account->formatDate($invoice->due_date)])) }} | ||||
|                                 </span><br /> | ||||
|                             @endif | ||||
|                             <span style="font-size: 19px; color: #FFFFFF;"> | ||||
|                             <span style="font-size: 18px;"> | ||||
|                                 {{ trans("texts.{$entityType}") }} {{ $invoice->invoice_number }} | ||||
|                             </span> | ||||
|                         </p> | ||||
|                     </td> | ||||
|                     <td style="border-collapse: collapse; vertical-align: middle; line-height: 16px;" valign="middle"> | ||||
|                         <p style="margin: 0; padding: 0;"> | ||||
|                             <span style="font-size: 12px; color: #8f8d8e;"> | ||||
|                                 {{ strtoupper(trans('texts.' . $invoice->present()->balanceDueLabel)) }}: | ||||
|                     <td style="border-collapse: collapse; vertical-align: middle;" valign="middle"> | ||||
|                         <p class="right" style="line-height: 14px; margin: 0; padding: 0;"> | ||||
|                             <span style="font-size: 15px; color: #231F20;"> | ||||
|                                 {{ trans('texts.' . $invoice->present()->balanceDueLabel) }}: | ||||
|                             </span><br /> | ||||
|                             <span class="total" style="font-size: 27px; color: #FFFFFF; margin-top: 5px;display: block;"> | ||||
|                             <span class="total" style="font-size: 26px; display: block;margin-top: 5px;"> | ||||
|                                 {{ $account->formatMoney($invoice->getRequestedAmount(), $client) }} | ||||
|                             </span> | ||||
|                         </p> | ||||
|  | ||||
| @ -12,30 +12,30 @@ | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td style="border-collapse: collapse;"> | ||||
|             <table cellpadding="10" cellspacing="0" border="0" bgcolor="#F4F5F5" width="580" align="center"  | ||||
|                 class="header" style="border-top-width: 6px; border-top-color: {{ $account->primary_color ?: '#2E2B2B' }}; border-top-style: solid;"> | ||||
|             <table cellpadding="10" cellspacing="0" border="0" bgcolor="{{ $account->primary_color ?: '#2E2B2B' }}" width="600" align="center" class="header"  | ||||
|                 style="border-bottom-width: 6px; border-bottom-color: {{ $account->primary_color ?: '#2E2B2B' }}; border-bottom-style: solid;"> | ||||
|                 <tr> | ||||
|                     <td class="logo" width="208" style="border-collapse: collapse; vertical-align: middle;" valign="middle"> | ||||
|                     <td class="logo" width="205" style="border-collapse: collapse; vertical-align: middle; line-height: 16px;" valign="middle"> | ||||
|                         @include('emails.partials.account_logo') | ||||
|                     </td> | ||||
|                     <td width="183" style="border-collapse: collapse; vertical-align: middle;" valign="middle"> | ||||
|                         <p class="left" style="line-height: 22px; margin: 0; padding: 2px 0 0;"> | ||||
|                     <td width="183" style="border-collapse: collapse; vertical-align: middle; line-height: 16px;" valign="middle"> | ||||
|                         <p class="left" style="line-height: 22px; margin: 3px 0 0; padding: 0;"> | ||||
|                             @if ($invoice->due_date) | ||||
|                                 <span style="font-size: 11px; color: #8f8d8e;"> | ||||
|                                     {{ strtoupper(trans('texts.due_by', ['date' => $account->formatDate($invoice->due_date)])) }} | ||||
|                                 </span><br /> | ||||
|                             @endif | ||||
|                             <span style="font-size: 18px;"> | ||||
|                             <span style="font-size: 19px; color: #FFFFFF;"> | ||||
|                                 {{ trans("texts.{$entityType}") }} {{ $invoice->invoice_number }} | ||||
|                             </span> | ||||
|                         </p> | ||||
|                     </td> | ||||
|                     <td style="border-collapse: collapse; vertical-align: middle;" valign="middle"> | ||||
|                         <p class="right" style="line-height: 14px; margin: 0; padding: 0;"> | ||||
|                             <span style="font-size: 15px; color: #231F20;"> | ||||
|                                 {{ trans('texts.' . $invoice->present()->balanceDueLabel) }}: | ||||
|                     <td style="border-collapse: collapse; vertical-align: middle; line-height: 16px;" valign="middle"> | ||||
|                         <p style="margin: 0; padding: 0;"> | ||||
|                             <span style="font-size: 12px; color: #8f8d8e;"> | ||||
|                                 {{ strtoupper(trans('texts.' . $invoice->present()->balanceDueLabel)) }}: | ||||
|                             </span><br /> | ||||
|                             <span class="total" style="font-size: 26px; display: block;margin-top: 5px;"> | ||||
|                             <span class="total" style="font-size: 27px; color: #FFFFFF; margin-top: 5px;display: block;"> | ||||
|                                 {{ $account->formatMoney($invoice->getRequestedAmount(), $client) }} | ||||
|                             </span> | ||||
|                         </p> | ||||
| @ -3,7 +3,7 @@ | ||||
|         <a href="{{ $account->website }}" style="color: #19BB40; text-decoration: underline;"> | ||||
|     @endif | ||||
| 
 | ||||
|     <img src="{{ $message->embed($account->getLogoURL()) }}" style="max-height:50px; max-width:140px; margin-left: 33px;" /> | ||||
|     <img src="{{ isset($message) ? $message->embed($account->getLogoURL()) : $account->getLogoURL() }}" style="max-height:50px; max-width:140px; margin-left: 33px;" /> | ||||
| 
 | ||||
|     @if ($account->website) | ||||
|         </a> | ||||
|  | ||||
| @ -93,14 +93,14 @@ | ||||
|     <div class="container main-container"> | ||||
| 
 | ||||
|         <div class="row"> | ||||
|             <div class="col-md-3 logo"> | ||||
|             <div class="col-md-6 logo"> | ||||
|                 @if ($account->hasLogo()) | ||||
|                     {!! HTML::image($account->getLogoURL()) !!} | ||||
|                 @else | ||||
|                     <h2>{{ $account->name}}</h2> | ||||
|                 @endif | ||||
|             </div> | ||||
|             <div class="col-md-3 col-md-offset-3 address-details"> | ||||
|             <div class="col-md-3 address-details"> | ||||
|                 @if ($account->address1) | ||||
|                     {{ $account->address1 }}<br/> | ||||
|                 @endif | ||||
|  | ||||
| @ -73,7 +73,12 @@ | ||||
| 				<div class="form-group"> | ||||
| 					<label for="client" class="control-label col-lg-4 col-sm-4">{{ trans('texts.client') }}</label> | ||||
| 					<div class="col-lg-8 col-sm-8"> | ||||
|                         <h4><div data-bind="text: getClientDisplayName(ko.toJS(client()))"></div></h4> | ||||
|                         <h4> | ||||
|                             <span data-bind="text: getClientDisplayName(ko.toJS(client()))"></span> | ||||
|                             @if ($invoice->client->is_deleted) | ||||
|                                   <div class="label label-danger">{{ trans('texts.deleted') }}</div> | ||||
|                             @endif | ||||
|                         </h4> | ||||
|                          | ||||
|                         @can('view', $invoice->client) | ||||
|                             @can('edit', $invoice->client) | ||||
| @ -109,6 +114,7 @@ | ||||
| 							<input type="checkbox" value="1" data-bind="checked: send_invoice, attr: {id: $index() + '_check', name: 'client[contacts][' + $index() + '][send_invoice]'}"> | ||||
| 							<span data-bind="html: email.display"></span> | ||||
|                         </label> | ||||
|                         @if ( ! $invoice->is_deleted && ! $invoice->client->is_deleted) | ||||
|                         <span data-bind="visible: !$root.invoice().is_recurring()"> | ||||
|                             <span data-bind="html: $data.view_as_recipient"></span>   | ||||
|                             @if (Utils::isConfirmed()) | ||||
| @ -119,6 +125,7 @@ | ||||
|                                     style: {color: $data.info_color}"></span>
 | ||||
|                             @endif | ||||
|                         </span> | ||||
|                         @endif | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
|  | ||||
| @ -66,6 +66,7 @@ | ||||
|         } | ||||
| 
 | ||||
|         var currency = currencyMap[currencyId]; | ||||
|         var precision = currency.precision; | ||||
|         var thousand = currency.thousand_separator; | ||||
|         var decimal = currency.decimal_separator; | ||||
|         var code = currency.code; | ||||
| @ -82,7 +83,7 @@ | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         value = accounting.formatMoney(value, '', 2, thousand, decimal); | ||||
|         value = accounting.formatMoney(value, '', precision, thousand, decimal); | ||||
|         var symbol = currency.symbol; | ||||
| 
 | ||||
|         if (hideSymbol) { | ||||
|  | ||||
| @ -96,7 +96,7 @@ class OnlinePaymentCest | ||||
|         $I->click('table.invoice-table tbody tr:nth-child(1) .tt-selectable'); | ||||
|         $I->checkOption('#auto_bill'); | ||||
|         $I->executeJS('preparePdfData(\'email\')'); | ||||
|         $I->wait(2); | ||||
|         $I->wait(3); | ||||
|         $I->see("$0.00"); | ||||
| 
 | ||||
|    } | ||||
|  | ||||
| @ -84,6 +84,7 @@ class TaxRatesCest | ||||
|         // check total is right after saving
 | ||||
|         $I->see("\${$total}"); | ||||
|         $I->amOnPage('/invoices'); | ||||
|         $I->wait(2); | ||||
|          | ||||
|         // check total is right in list view
 | ||||
|         $I->see("\${$total}"); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user