Added support for country specific Euro formatting

This commit is contained in:
Hillel Coren 2015-12-07 15:34:55 +02:00
parent 254dd4ff53
commit 1a474f362f
46 changed files with 460 additions and 1731 deletions

View File

@ -62,7 +62,7 @@ class DashboardController extends BaseController
->get(); ->get();
$activities = Activity::where('activities.account_id', '=', Auth::user()->account_id) $activities = Activity::where('activities.account_id', '=', Auth::user()->account_id)
->with('client.contacts', 'user', 'invoice', 'payment', 'credit') ->with('client.contacts', 'user', 'invoice', 'payment', 'credit', 'account')
->where('activity_type_id', '>', 0) ->where('activity_type_id', '>', 0)
->orderBy('created_at', 'desc') ->orderBy('created_at', 'desc')
->take(50) ->take(50)

View File

@ -365,7 +365,6 @@ class InvoiceController extends BaseController
'data' => Input::old('data'), 'data' => Input::old('data'),
'account' => Auth::user()->account->load('country'), 'account' => Auth::user()->account->load('country'),
'products' => Product::scope()->with('default_tax_rate')->orderBy('id')->get(), 'products' => Product::scope()->with('default_tax_rate')->orderBy('id')->get(),
'countries' => Cache::get('countries'),
'taxRates' => TaxRate::scope()->orderBy('name')->get(), 'taxRates' => TaxRate::scope()->orderBy('name')->get(),
'currencies' => Cache::get('currencies'), 'currencies' => Cache::get('currencies'),
'languages' => Cache::get('languages'), 'languages' => Cache::get('languages'),

View File

@ -65,7 +65,7 @@ class PublicClientController extends BaseController
return trans("texts.activity_{$model->activity_type_id}", $data); return trans("texts.activity_{$model->activity_type_id}", $data);
}) })
->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id); }) ->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); })
->addColumn('adjustment', function ($model) { return $model->adjustment != 0 ? Utils::wrapAdjustment($model->adjustment, $model->currency_id) : ''; }) ->addColumn('adjustment', function ($model) { return $model->adjustment != 0 ? Utils::wrapAdjustment($model->adjustment, $model->currency_id) : ''; })
->make(); ->make();
} }
@ -129,7 +129,7 @@ class PublicClientController extends BaseController
->addColumn('invoice_number', function ($model) { return $model->invitation_key ? link_to('/view/'.$model->invitation_key, $model->invoice_number) : $model->invoice_number; }) ->addColumn('invoice_number', function ($model) { return $model->invitation_key ? link_to('/view/'.$model->invitation_key, $model->invoice_number) : $model->invoice_number; })
->addColumn('transaction_reference', function ($model) { return $model->transaction_reference ? $model->transaction_reference : '<i>Manual entry</i>'; }) ->addColumn('transaction_reference', function ($model) { return $model->transaction_reference ? $model->transaction_reference : '<i>Manual entry</i>'; })
->addColumn('payment_type', function ($model) { return $model->payment_type ? $model->payment_type : ($model->account_gateway_id ? '<i>Online payment</i>' : ''); }) ->addColumn('payment_type', function ($model) { return $model->payment_type ? $model->payment_type : ($model->account_gateway_id ? '<i>Online payment</i>' : ''); })
->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id); }) ->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id); })
->addColumn('payment_date', function ($model) { return Utils::dateToString($model->payment_date); }) ->addColumn('payment_date', function ($model) { return Utils::dateToString($model->payment_date); })
->make(); ->make();
} }

View File

@ -223,6 +223,7 @@ class ReportController extends BaseController
} }
$query = DB::table('invoices') $query = DB::table('invoices')
->join('accounts', 'accounts.id', '=', 'invoices.account_id')
->join('clients', 'clients.id', '=', 'invoices.client_id') ->join('clients', 'clients.id', '=', 'invoices.client_id')
->join('contacts', 'contacts.client_id', '=', 'clients.id') ->join('contacts', 'contacts.client_id', '=', 'clients.id')
->where('invoices.account_id', '=', Auth::user()->account_id) ->where('invoices.account_id', '=', Auth::user()->account_id)
@ -235,7 +236,16 @@ class ReportController extends BaseController
->where('invoices.is_recurring', '=', false) ->where('invoices.is_recurring', '=', false)
->where('contacts.is_primary', '=', true); ->where('contacts.is_primary', '=', true);
$select = ['clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'clients.name as client_name', 'clients.public_id as client_public_id', 'invoices.public_id as invoice_public_id']; $select = [
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
'accounts.country_id',
'contacts.first_name',
'contacts.last_name',
'contacts.email',
'clients.name as client_name',
'clients.public_id as client_public_id',
'invoices.public_id as invoice_public_id'
];
if ($reportType == ENTITY_CLIENT) { if ($reportType == ENTITY_CLIENT) {
$query->groupBy('clients.id'); $query->groupBy('clients.id');
@ -283,19 +293,19 @@ class ReportController extends BaseController
Utils::fromSqlDate($record->invoice_date, true) Utils::fromSqlDate($record->invoice_date, true)
); );
} }
array_push($displayRow, Utils::formatMoney($record->amount, $record->currency_id)); array_push($displayRow, Utils::formatMoney($record->amount, $record->currency_id, $record->country_id));
} }
if ($reportType != ENTITY_PAYMENT) { if ($reportType != ENTITY_PAYMENT) {
array_push($displayRow, Utils::formatMoney($record->paid, $record->currency_id)); array_push($displayRow, Utils::formatMoney($record->paid, $record->currency_id, $record->country_id));
} }
if ($reportType == ENTITY_PAYMENT) { if ($reportType == ENTITY_PAYMENT) {
array_push($displayRow, array_push($displayRow,
Utils::fromSqlDate($record->payment_date, true), Utils::fromSqlDate($record->payment_date, true),
Utils::formatMoney($record->paid, $record->currency_id), Utils::formatMoney($record->paid, $record->currency_id, $record->country_id),
$record->gateway ?: $record->payment_type $record->gateway ?: $record->payment_type
); );
} else { } else {
array_push($displayRow, Utils::formatMoney($record->balance, $record->currency_id)); array_push($displayRow, Utils::formatMoney($record->balance, $record->currency_id, $record->country_id));
} }
// export data // export data
@ -311,17 +321,17 @@ class ReportController extends BaseController
$exportRow[trans('texts.invoice_number')] = $record->invoice_number; $exportRow[trans('texts.invoice_number')] = $record->invoice_number;
$exportRow[trans('texts.invoice_date')] = Utils::fromSqlDate($record->invoice_date, true); $exportRow[trans('texts.invoice_date')] = Utils::fromSqlDate($record->invoice_date, true);
} }
$exportRow[trans('texts.amount')] = Utils::formatMoney($record->amount, $record->currency_id); $exportRow[trans('texts.amount')] = Utils::formatMoney($record->amount, $record->currency_id, $record->country_id);
} }
if ($reportType != ENTITY_PAYMENT) { if ($reportType != ENTITY_PAYMENT) {
$exportRow[trans('texts.paid')] = Utils::formatMoney($record->paid, $record->currency_id); $exportRow[trans('texts.paid')] = Utils::formatMoney($record->paid, $record->currency_id, $record->country_id);
} }
if ($reportType == ENTITY_PAYMENT) { if ($reportType == ENTITY_PAYMENT) {
$exportRow[trans('texts.payment_date')] = Utils::fromSqlDate($record->payment_date, true); $exportRow[trans('texts.payment_date')] = Utils::fromSqlDate($record->payment_date, true);
$exportRow[trans('texts.payment_amount')] = Utils::formatMoney($record->paid, $record->currency_id); $exportRow[trans('texts.payment_amount')] = Utils::formatMoney($record->paid, $record->currency_id, $record->country_id);
$exportRow[trans('texts.method')] = $record->gateway ?: $record->payment_type; $exportRow[trans('texts.method')] = $record->gateway ?: $record->payment_type;
} else { } else {
$exportRow[trans('texts.balance')] = Utils::formatMoney($record->balance, $record->currency_id); $exportRow[trans('texts.balance')] = Utils::formatMoney($record->balance, $record->currency_id, $record->country_id);
} }
$displayData[] = $displayRow; $displayData[] = $displayRow;

View File

@ -391,8 +391,12 @@ if (!defined('CONTACT_EMAIL')) {
define('SESSION_LAST_REQUEST_PAGE', 'SESSION_LAST_REQUEST_PAGE'); define('SESSION_LAST_REQUEST_PAGE', 'SESSION_LAST_REQUEST_PAGE');
define('SESSION_LAST_REQUEST_TIME', 'SESSION_LAST_REQUEST_TIME'); define('SESSION_LAST_REQUEST_TIME', 'SESSION_LAST_REQUEST_TIME');
define('CURRENCY_DOLLAR', 1);
define('CURRENCY_EURO', 3);
define('DEFAULT_TIMEZONE', 'US/Eastern'); define('DEFAULT_TIMEZONE', 'US/Eastern');
define('DEFAULT_CURRENCY', 1); // US Dollar define('DEFAULT_COUNTRY', 840); // United Stated
define('DEFAULT_CURRENCY', CURRENCY_DOLLAR);
define('DEFAULT_LANGUAGE', 1); // English define('DEFAULT_LANGUAGE', 1); // English
define('DEFAULT_DATE_FORMAT', 'M j, Y'); define('DEFAULT_DATE_FORMAT', 'M j, Y');
define('DEFAULT_DATE_PICKER_FORMAT', 'M d, yyyy'); define('DEFAULT_DATE_PICKER_FORMAT', 'M d, yyyy');
@ -579,4 +583,4 @@ if (Auth::check() && Auth::user()->id === 1)
{ {
Auth::loginUsingId(1); Auth::loginUsingId(1);
} }
*/ */

View File

@ -239,31 +239,54 @@ class Utils
return intval($value); return intval($value);
} }
public static function formatMoney($value, $currencyId = false, $showSymbol = true) public static function getFromCache($id, $type) {
$data = Cache::get($type)->filter(function($item) use ($id) {
return $item->id == $id;
});
return $data->first();
}
public static function formatMoney($value, $currencyId = false, $countryId = false, $hideSymbol = false)
{ {
if (!$currencyId) {
$currencyId = Session::get(SESSION_CURRENCY, DEFAULT_CURRENCY);
}
foreach (Cache::get('currencies') as $currency) {
if ($currency->id == $currencyId) {
break;
}
}
if (!$currency) {
$currency = Currency::find(1);
}
if (!$value) { if (!$value) {
$value = 0; $value = 0;
} }
$str = ''; if (!$currencyId) {
if ($showSymbol) { $currencyId = Session::get(SESSION_CURRENCY, DEFAULT_CURRENCY);
$str .= $currency->symbol; }
if (!$countryId && Auth::check()) {
$countryId = Auth::user()->account->country_id;
}
$currency = self::getFromCache($currencyId, 'currencies');
$thousand = $currency->thousand_separator;
$decimal = $currency->decimal_separator;
$swapSymbol = false;
if ($countryId && $currencyId == CURRENCY_EURO) {
$country = self::getFromCache($countryId, 'countries');
$swapSymbol = $country->swap_currency_symbol;
if ($country->thousand_separator) {
$thousand = $country->thousand_separator;
}
if ($country->decimal_separator) {
$decimal = $country->decimal_separator;
}
}
$value = number_format($value, $currency->precision, $decimal, $thousand);
$symbol = $currency->symbol;
if ($hideSymbol) {
return $value;
} elseif ($swapSymbol) {
return "{$value} " . trim($symbol);
} else {
return "{$symbol}{$value}";
} }
return $str . number_format($value, $currency->precision, $currency->decimal_separator, $currency->thousand_separator);
} }
public static function pluralize($string, $count) public static function pluralize($string, $count)
@ -814,10 +837,10 @@ class Utils
return link_to($link, $title, array('target' => '_blank')); return link_to($link, $title, array('target' => '_blank'));
} }
public static function wrapAdjustment($adjustment, $currencyId) public static function wrapAdjustment($adjustment, $currencyId, $countryId)
{ {
$class = $adjustment <= 0 ? 'success' : 'default'; $class = $adjustment <= 0 ? 'success' : 'default';
$adjustment = Utils::formatMoney($adjustment, $currencyId); $adjustment = Utils::formatMoney($adjustment, $currencyId, $countryId);
return "<h4><div class=\"label label-{$class}\">$adjustment</div></h4>"; return "<h4><div class=\"label label-{$class}\">$adjustment</div></h4>";
} }

View File

@ -205,18 +205,25 @@ class Account extends Eloquent
return $this->date_format ? $this->date_format->format : DEFAULT_DATE_FORMAT; return $this->date_format ? $this->date_format->format : DEFAULT_DATE_FORMAT;
} }
public function formatMoney($amount, $client = null) public function formatMoney($amount, $client = null, $hideSymbol = false)
{ {
$currency = ($client && $client->currency) ? $client->currency : $this->currency; if ($client && $client->currency_id) {
$currencyId = $client->currency_id;
if ( ! $currency) { } elseif ($this->currency_id) {
$currencies = Cache::get('currencies')->filter(function($item) { $currencyId = $this->currency_id;
return $item->id == DEFAULT_CURRENCY; } else {
}); $currencyId = DEFAULT_CURRENCY;
$currency = $currencies->first();
} }
return $currency->symbol . number_format($amount, $currency->precision, $currency->decimal_separator, $currency->thousand_separator); if ($client && $client->country_id) {
$countryId = $client->country_id;
} elseif ($this->country_id) {
$countryId = $this->country_id;
} else {
$countryId = false;
}
return Utils::formatMoney($amount, $currencyId, $countryId, $hideSymbol);
} }
public function formatDate($date) public function formatDate($date)

View File

@ -51,8 +51,18 @@ class Activity extends Eloquent
return $this->belongsTo('App\Models\Payment')->withTrashed(); return $this->belongsTo('App\Models\Payment')->withTrashed();
} }
public static function calcMessage($activityTypeId, $client, $user, $invoice, $contactId, $payment, $credit, $isSystem) public function getMessage()
{ {
$activityTypeId = $this->activity_type_id;
$account = $this->account;
$client = $this->client;
$user = $this->user;
$invoice = $this->invoice;
$contactId = $this->contact_id;
$payment = $this->payment;
$credit = $this->credit;
$isSystem = $this->is_system;
$data = [ $data = [
'client' => link_to($client->getRoute(), $client->getDisplayName()), 'client' => link_to($client->getRoute(), $client->getDisplayName()),
'user' => $isSystem ? '<i>' . trans('texts.system') . '</i>' : $user->getDisplayName(), 'user' => $isSystem ? '<i>' . trans('texts.system') . '</i>' : $user->getDisplayName(),
@ -60,23 +70,9 @@ class Activity extends Eloquent
'quote' => $invoice ? link_to($invoice->getRoute(), $invoice->getDisplayName()) : null, 'quote' => $invoice ? link_to($invoice->getRoute(), $invoice->getDisplayName()) : null,
'contact' => $contactId ? $client->getDisplayName() : $user->getDisplayName(), 'contact' => $contactId ? $client->getDisplayName() : $user->getDisplayName(),
'payment' => $payment ? $payment->transaction_reference : null, 'payment' => $payment ? $payment->transaction_reference : null,
'credit' => $credit ? Utils::formatMoney($credit->amount, $client->currency_id) : null, 'credit' => $credit ? $account->formatMoney($credit->amount, $client) : null,
]; ];
return trans("texts.activity_{$activityTypeId}", $data); return trans("texts.activity_{$activityTypeId}", $data);
} }
public function getMessage()
{
return static::calcMessage(
$this->activity_type_id,
$this->client,
$this->user,
$this->invoice,
$this->contact_id,
$this->payment,
$this->credit,
$this->is_system
);
}
} }

View File

@ -6,7 +6,19 @@ class Country extends Eloquent
{ {
public $timestamps = false; public $timestamps = false;
protected $visible = ['id', 'name', 'swap_postal_code']; protected $visible = [
'id',
'name',
'swap_postal_code',
'swap_currency_symbol',
'thousand_separator',
'decimal_separator'
];
protected $casts = [
'swap_postal_code' => 'boolean',
'swap_currency_symbol' => 'boolean',
];
public function getName() public function getName()
{ {

View File

@ -57,10 +57,12 @@ class Payment extends EntityModel
return "/payments/{$this->public_id}/edit"; return "/payments/{$this->public_id}/edit";
} }
/*
public function getAmount() public function getAmount()
{ {
return Utils::formatMoney($this->amount, $this->client->getCurrencyId()); return Utils::formatMoney($this->amount, $this->client->getCurrencyId());
} }
*/
public function getName() public function getName()
{ {

View File

@ -206,7 +206,7 @@ class ContactMailer extends Mailer
$data = [ $data = [
'account' => trans('texts.email_from'), 'account' => trans('texts.email_from'),
'client' => $name, 'client' => $name,
'amount' => Utils::formatMoney($amount, 1), 'amount' => Utils::formatMoney($amount, DEFAULT_CURRENCY, DEFAULT_COUNTRY),
'license' => $license 'license' => $license
]; ];
@ -226,7 +226,7 @@ class ContactMailer extends Mailer
'$account' => $account->getDisplayName(), '$account' => $account->getDisplayName(),
'$contact' => $invitation->contact->getDisplayName(), '$contact' => $invitation->contact->getDisplayName(),
'$firstName' => $invitation->contact->first_name, '$firstName' => $invitation->contact->first_name,
'$amount' => Utils::formatMoney($data['amount'], $client->getCurrencyId()), '$amount' => $account->formatMoney($data['amount'], $client),
'$invoice' => $invoice->invoice_number, '$invoice' => $invoice->invoice_number,
'$quote' => $invoice->invoice_number, '$quote' => $invoice->invoice_number,
'$link' => $invitation->getLink(), '$link' => $invitation->getLink(),

View File

@ -42,22 +42,27 @@ class UserMailer extends Mailer
$entityType = $notificationType == 'approved' ? ENTITY_QUOTE : ENTITY_INVOICE; $entityType = $notificationType == 'approved' ? ENTITY_QUOTE : ENTITY_INVOICE;
$view = "{$entityType}_{$notificationType}"; $view = "{$entityType}_{$notificationType}";
$account = $user->account;
$client = $invoice->client;
$data = [ $data = [
'entityType' => $entityType, 'entityType' => $entityType,
'clientName' => $invoice->client->getDisplayName(), 'clientName' => $client->getDisplayName(),
'accountName' => $invoice->account->getDisplayName(), 'accountName' => $account->getDisplayName(),
'userName' => $user->getDisplayName(), 'userName' => $user->getDisplayName(),
'invoiceAmount' => Utils::formatMoney($invoice->getRequestedAmount(), $invoice->client->getCurrencyId()), 'invoiceAmount' => $account->formatMoney($invoice->getRequestedAmount(), $client),
'invoiceNumber' => $invoice->invoice_number, 'invoiceNumber' => $invoice->invoice_number,
'invoiceLink' => SITE_URL."/{$entityType}s/{$invoice->public_id}", 'invoiceLink' => SITE_URL."/{$entityType}s/{$invoice->public_id}",
]; ];
if ($payment) { if ($payment) {
$data['paymentAmount'] = Utils::formatMoney($payment->amount, $invoice->client->getCurrencyId()); $data['paymentAmount'] = $account->formatMoney($payment->amount, $client);
} }
$subject = trans("texts.notification_{$entityType}_{$notificationType}_subject", ['invoice' => $invoice->invoice_number, 'client' => $invoice->client->getDisplayName()]); $subject = trans("texts.notification_{$entityType}_{$notificationType}_subject", [
'invoice' => $invoice->invoice_number,
'client' => $client->getDisplayName()
]);
$this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data); $this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
} }

View File

@ -5,22 +5,6 @@ use Laracasts\Presenter\Presenter;
class ClientPresenter extends Presenter { class ClientPresenter extends Presenter {
public function balance()
{
$amount = $this->entity->balance;
$currencyId = $this->entity->currency_id;
return Utils::formatMoney($amount, $currencyId);
}
public function paid_to_date()
{
$amount = $this->entity->paid_to_date;
$currencyId = $this->entity->currency_id;
return Utils::formatMoney($amount, $currencyId);
}
public function country() public function country()
{ {
return $this->entity->country ? $this->entity->country->name : ''; return $this->entity->country ? $this->entity->country->name : '';

View File

@ -14,22 +14,4 @@ class CreditPresenter extends Presenter {
{ {
return Utils::fromSqlDate($this->entity->credit_date); return Utils::fromSqlDate($this->entity->credit_date);
} }
public function amount()
{
$amount = $this->entity->amount;
$currencyId = $this->entity->client->currency_id;
return Utils::formatMoney($amount, $currencyId);
}
public function balance()
{
$amount = $this->entity->balance;
$currencyId = $this->entity->client->currency_id;
return Utils::formatMoney($amount, $currencyId);
}
} }

View File

@ -26,14 +26,6 @@ class InvoicePresenter extends Presenter {
} }
} }
public function balance_due()
{
$amount = $this->entity->getRequestedAmount();
$currencyId = $this->entity->client->currency_id;
return Utils::formatMoney($amount, $currencyId);
}
public function status() public function status()
{ {
$status = $this->entity->invoice_status ? $this->entity->invoice_status->name : 'draft'; $status = $this->entity->invoice_status ? $this->entity->invoice_status->name : 'draft';
@ -41,32 +33,6 @@ class InvoicePresenter extends Presenter {
return trans("texts.status_{$status}"); return trans("texts.status_{$status}");
} }
public function balance()
{
$amount = $this->entity->balance;
$currencyId = $this->entity->client->currency_id;
return Utils::formatMoney($amount, $currencyId);
}
public function amount()
{
$amount = $this->entity->amount;
$currencyId = $this->entity->client->currency_id;
return Utils::formatMoney($amount, $currencyId);
}
public function discount()
{
if ($this->entity->is_amount_discount) {
$currencyId = $this->entity->client->currency_id;
return Utils::formatMoney($this->entity->discount, $currencyId);
} else {
return $this->entity->discount . '%';
}
}
public function invoice_date() public function invoice_date()
{ {
return Utils::fromSqlDate($this->entity->invoice_date); return Utils::fromSqlDate($this->entity->invoice_date);

View File

@ -15,14 +15,6 @@ class PaymentPresenter extends Presenter {
return Utils::fromSqlDate($this->entity->payment_date); return Utils::fromSqlDate($this->entity->payment_date);
} }
public function amount()
{
$amount = $this->entity->amount;
$currencyId = $this->entity->client->currency_id;
return Utils::formatMoney($amount, $currencyId);
}
public function method() public function method()
{ {
if ($this->entity->account_gateway) { if ($this->entity->account_gateway) {

View File

@ -64,6 +64,7 @@ class ActivityRepository
public function findByClientId($clientId) public function findByClientId($clientId)
{ {
return DB::table('activities') return DB::table('activities')
->join('accounts', 'accounts.id', '=', 'activities.account_id')
->join('users', 'users.id', '=', 'activities.user_id') ->join('users', 'users.id', '=', 'activities.user_id')
->join('clients', 'clients.id', '=', 'activities.client_id') ->join('clients', 'clients.id', '=', 'activities.client_id')
->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id') ->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id')
@ -74,12 +75,13 @@ class ActivityRepository
->where('contacts.is_primary', '=', 1) ->where('contacts.is_primary', '=', 1)
->whereNull('contacts.deleted_at') ->whereNull('contacts.deleted_at')
->select( ->select(
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
'activities.id', 'activities.id',
'activities.created_at', 'activities.created_at',
'activities.contact_id', 'activities.contact_id',
'activities.activity_type_id', 'activities.activity_type_id',
'activities.is_system', 'activities.is_system',
'clients.currency_id',
'activities.balance', 'activities.balance',
'activities.adjustment', 'activities.adjustment',
'users.first_name as user_first_name', 'users.first_name as user_first_name',
@ -88,7 +90,6 @@ class ActivityRepository
'invoices.invoice_number as invoice', 'invoices.invoice_number as invoice',
'invoices.public_id as invoice_public_id', 'invoices.public_id as invoice_public_id',
'invoices.is_recurring', 'invoices.is_recurring',
'clients.currency_id',
'clients.name as client_name', 'clients.name as client_name',
'clients.public_id as client_public_id', 'clients.public_id as client_public_id',
'contacts.id as contact', 'contacts.id as contact',

View File

@ -1,5 +1,6 @@
<?php namespace App\Ninja\Repositories; <?php namespace App\Ninja\Repositories;
use DB;
use App\Ninja\Repositories\BaseRepository; use App\Ninja\Repositories\BaseRepository;
use App\Models\Client; use App\Models\Client;
use App\Models\Contact; use App\Models\Contact;
@ -23,12 +24,27 @@ class ClientRepository extends BaseRepository
public function find($filter = null) public function find($filter = null)
{ {
$query = \DB::table('clients') $query = DB::table('clients')
->join('accounts', 'accounts.id', '=', 'clients.account_id')
->join('contacts', 'contacts.client_id', '=', 'clients.id') ->join('contacts', 'contacts.client_id', '=', 'clients.id')
->where('clients.account_id', '=', \Auth::user()->account_id) ->where('clients.account_id', '=', \Auth::user()->account_id)
->where('contacts.is_primary', '=', true) ->where('contacts.is_primary', '=', true)
->where('contacts.deleted_at', '=', null) ->where('contacts.deleted_at', '=', null)
->select('clients.public_id', 'clients.name', 'contacts.first_name', 'contacts.last_name', 'clients.balance', 'clients.last_login', 'clients.created_at', 'clients.work_phone', 'contacts.email', 'clients.currency_id', 'clients.deleted_at', 'clients.is_deleted'); ->select(
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
'clients.public_id',
'clients.name',
'contacts.first_name',
'contacts.last_name',
'clients.balance',
'clients.last_login',
'clients.created_at',
'clients.work_phone',
'contacts.email',
'clients.deleted_at',
'clients.is_deleted'
);
if (!\Session::get('show_trash:client')) { if (!\Session::get('show_trash:client')) {
$query->where('clients.deleted_at', '=', null); $query->where('clients.deleted_at', '=', null);

View File

@ -1,5 +1,6 @@
<?php namespace App\Ninja\Repositories; <?php namespace App\Ninja\Repositories;
use DB;
use Utils; use Utils;
use App\Models\Credit; use App\Models\Credit;
use App\Models\Client; use App\Models\Client;
@ -14,14 +15,30 @@ class CreditRepository extends BaseRepository
public function find($clientPublicId = null, $filter = null) public function find($clientPublicId = null, $filter = null)
{ {
$query = \DB::table('credits') $query = DB::table('credits')
->join('accounts', 'accounts.id', '=', 'credits.account_id')
->join('clients', 'clients.id', '=', 'credits.client_id') ->join('clients', 'clients.id', '=', 'credits.client_id')
->join('contacts', 'contacts.client_id', '=', 'clients.id') ->join('contacts', 'contacts.client_id', '=', 'clients.id')
->where('clients.account_id', '=', \Auth::user()->account_id) ->where('clients.account_id', '=', \Auth::user()->account_id)
->where('clients.deleted_at', '=', null) ->where('clients.deleted_at', '=', null)
->where('contacts.deleted_at', '=', null) ->where('contacts.deleted_at', '=', null)
->where('contacts.is_primary', '=', true) ->where('contacts.is_primary', '=', true)
->select('credits.public_id', 'clients.name as client_name', 'clients.public_id as client_public_id', 'credits.amount', 'credits.balance', 'credits.credit_date', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'credits.private_notes', 'credits.deleted_at', 'credits.is_deleted'); ->select(
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
'credits.public_id',
'clients.name as client_name',
'clients.public_id as client_public_id',
'credits.amount',
'credits.balance',
'credits.credit_date',
'contacts.first_name',
'contacts.last_name',
'contacts.email',
'credits.private_notes',
'credits.deleted_at',
'credits.is_deleted'
);
if ($clientPublicId) { if ($clientPublicId) {
$query->where('clients.public_id', '=', $clientPublicId); $query->where('clients.public_id', '=', $clientPublicId);

View File

@ -1,6 +1,6 @@
<?php namespace App\Ninja\Repositories; <?php namespace app\Ninja\Repositories;
use Carbon; use DB;
use Utils; use Utils;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\InvoiceItem; use App\Models\InvoiceItem;
@ -34,7 +34,8 @@ class InvoiceRepository extends BaseRepository
public function getInvoices($accountId, $clientPublicId = false, $entityType = ENTITY_INVOICE, $filter = false) public function getInvoices($accountId, $clientPublicId = false, $entityType = ENTITY_INVOICE, $filter = false)
{ {
$query = \DB::table('invoices') $query = DB::table('invoices')
->join('accounts', 'accounts.id', '=', 'invoices.account_id')
->join('clients', 'clients.id', '=', 'invoices.client_id') ->join('clients', 'clients.id', '=', 'invoices.client_id')
->join('invoice_statuses', 'invoice_statuses.id', '=', 'invoices.invoice_status_id') ->join('invoice_statuses', 'invoice_statuses.id', '=', 'invoices.invoice_status_id')
->join('contacts', 'contacts.client_id', '=', 'clients.id') ->join('contacts', 'contacts.client_id', '=', 'clients.id')
@ -43,7 +44,28 @@ class InvoiceRepository extends BaseRepository
->where('contacts.deleted_at', '=', null) ->where('contacts.deleted_at', '=', null)
->where('invoices.is_recurring', '=', false) ->where('invoices.is_recurring', '=', false)
->where('contacts.is_primary', '=', true) ->where('contacts.is_primary', '=', true)
->select('clients.public_id as client_public_id', 'invoice_number', 'invoice_status_id', 'clients.name as client_name', 'invoices.public_id', 'amount', 'invoices.balance', 'invoice_date', 'due_date', 'invoice_statuses.name as invoice_status_name', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'quote_id', 'quote_invoice_id', 'invoices.deleted_at', 'invoices.is_deleted', 'invoices.partial'); ->select(
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
'clients.public_id as client_public_id',
'invoice_number',
'invoice_status_id',
'clients.name as client_name',
'invoices.public_id',
'invoices.amount',
'invoices.balance',
'invoices.invoice_date',
'invoices.due_date',
'invoice_statuses.name as invoice_status_name',
'contacts.first_name',
'contacts.last_name',
'contacts.email',
'invoices.quote_id',
'invoices.quote_invoice_id',
'invoices.deleted_at',
'invoices.is_deleted',
'invoices.partial'
);
if (!\Session::get('show_trash:'.$entityType)) { if (!\Session::get('show_trash:'.$entityType)) {
$query->where('invoices.deleted_at', '=', null); $query->where('invoices.deleted_at', '=', null);
@ -69,7 +91,8 @@ class InvoiceRepository extends BaseRepository
public function getRecurringInvoices($accountId, $clientPublicId = false, $filter = false) public function getRecurringInvoices($accountId, $clientPublicId = false, $filter = false)
{ {
$query = \DB::table('invoices') $query = DB::table('invoices')
->join('accounts', 'accounts.id', '=', 'invoices.account_id')
->join('clients', 'clients.id', '=', 'invoices.client_id') ->join('clients', 'clients.id', '=', 'invoices.client_id')
->join('frequencies', 'frequencies.id', '=', 'invoices.frequency_id') ->join('frequencies', 'frequencies.id', '=', 'invoices.frequency_id')
->join('contacts', 'contacts.client_id', '=', 'clients.id') ->join('contacts', 'contacts.client_id', '=', 'clients.id')
@ -79,7 +102,22 @@ class InvoiceRepository extends BaseRepository
->where('invoices.is_recurring', '=', true) ->where('invoices.is_recurring', '=', true)
->where('contacts.is_primary', '=', true) ->where('contacts.is_primary', '=', true)
->where('clients.deleted_at', '=', null) ->where('clients.deleted_at', '=', null)
->select('clients.public_id as client_public_id', 'clients.name as client_name', 'invoices.public_id', 'amount', 'frequencies.name as frequency', 'start_date', 'end_date', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'invoices.deleted_at', 'invoices.is_deleted'); ->select(
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
'clients.public_id as client_public_id',
'clients.name as client_name',
'invoices.public_id',
'invoices.amount',
'frequencies.name as frequency',
'invoices.start_date',
'invoices.end_date',
'contacts.first_name',
'contacts.last_name',
'contacts.email',
'invoices.deleted_at',
'invoices.is_deleted'
);
if ($clientPublicId) { if ($clientPublicId) {
$query->where('clients.public_id', '=', $clientPublicId); $query->where('clients.public_id', '=', $clientPublicId);
@ -101,7 +139,8 @@ class InvoiceRepository extends BaseRepository
public function getClientDatatable($contactId, $entityType, $search) public function getClientDatatable($contactId, $entityType, $search)
{ {
$query = \DB::table('invitations') $query = DB::table('invitations')
->join('accounts', 'accounts.id', '=', 'invitations.account_id')
->join('invoices', 'invoices.id', '=', 'invitations.invoice_id') ->join('invoices', 'invoices.id', '=', 'invitations.invoice_id')
->join('clients', 'clients.id', '=', 'invoices.client_id') ->join('clients', 'clients.id', '=', 'invoices.client_id')
->where('invitations.contact_id', '=', $contactId) ->where('invitations.contact_id', '=', $contactId)
@ -110,18 +149,36 @@ class InvoiceRepository extends BaseRepository
->where('invoices.is_deleted', '=', false) ->where('invoices.is_deleted', '=', false)
->where('clients.deleted_at', '=', null) ->where('clients.deleted_at', '=', null)
->where('invoices.is_recurring', '=', false) ->where('invoices.is_recurring', '=', false)
->select('invitation_key', 'invoice_number', 'invoice_date', 'invoices.balance as balance', 'due_date', 'clients.public_id as client_public_id', 'clients.name as client_name', 'invoices.public_id', 'amount', 'start_date', 'end_date', 'clients.currency_id', 'invoices.partial'); ->select(
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
'invitations.invitation_key',
'invoices.invoice_number',
'invoices.invoice_date',
'invoices.balance as balance',
'invoices.due_date',
'clients.public_id as client_public_id',
'clients.name as client_name',
'invoices.public_id',
'invoices.amount',
'invoices.start_date',
'invoices.end_date',
'invoices.partial'
);
$table = \Datatable::query($query) $table = \Datatable::query($query)
->addColumn('invoice_number', function ($model) use ($entityType) { return link_to('/view/'.$model->invitation_key, $model->invoice_number); }) ->addColumn('invoice_number', function ($model) use ($entityType) { return link_to('/view/'.$model->invitation_key, $model->invoice_number); })
->addColumn('invoice_date', function ($model) { return Utils::fromSqlDate($model->invoice_date); }) ->addColumn('invoice_date', function ($model) { return Utils::fromSqlDate($model->invoice_date); })
->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id); }); ->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id); });
if ($entityType == ENTITY_INVOICE) { if ($entityType == ENTITY_INVOICE) {
$table->addColumn('balance', function ($model) { $table->addColumn('balance', function ($model) {
return $model->partial > 0 ? return $model->partial > 0 ?
trans('texts.partial_remaining', ['partial' => Utils::formatMoney($model->partial, $model->currency_id), 'balance' => Utils::formatMoney($model->balance, $model->currency_id)]) : trans('texts.partial_remaining', [
Utils::formatMoney($model->balance, $model->currency_id); 'partial' => Utils::formatMoney($model->partial, $model->currency_id, $model->country_id),
'balance' => Utils::formatMoney($model->balance, $model->currency_id, $model->country_id)
]) :
Utils::formatMoney($model->balance, $model->currency_id, $model->country_id);
}); });
} }
@ -133,7 +190,7 @@ class InvoiceRepository extends BaseRepository
{ {
$account = \Auth::user()->account; $account = \Auth::user()->account;
$publicId = isset($data['public_id']) ? $data['public_id'] : false; $publicId = isset($data['public_id']) ? $data['public_id'] : false;
$isNew = !$publicId || $publicId == '-1'; $isNew = !$publicId || $publicId == '-1';
if ($isNew) { if ($isNew) {
@ -259,7 +316,7 @@ class InvoiceRepository extends BaseRepository
$total *= (100 - $invoice->discount) / 100; $total *= (100 - $invoice->discount) / 100;
} }
} }
if (isset($data['custom_value1'])) { if (isset($data['custom_value1'])) {
$invoice->custom_value1 = round($data['custom_value1'], 2); $invoice->custom_value1 = round($data['custom_value1'], 2);
if ($isNew) { if ($isNew) {
@ -272,7 +329,7 @@ class InvoiceRepository extends BaseRepository
$invoice->custom_taxes2 = $account->custom_invoice_taxes2 ?: false; $invoice->custom_taxes2 = $account->custom_invoice_taxes2 ?: false;
} }
} }
if (isset($data['custom_text_value1'])) { if (isset($data['custom_text_value1'])) {
$invoice->custom_text_value1 = trim($data['custom_text_value1']); $invoice->custom_text_value1 = trim($data['custom_text_value1']);
} }
@ -324,7 +381,7 @@ class InvoiceRepository extends BaseRepository
$task->invoice_id = $invoice->id; $task->invoice_id = $invoice->id;
$task->client_id = $invoice->client_id; $task->client_id = $invoice->client_id;
$task->save(); $task->save();
} else if (isset($item['product_key']) && $item['product_key'] && !$invoice->has_tasks) { } elseif (isset($item['product_key']) && $item['product_key'] && !$invoice->has_tasks) {
$product = Product::findProductByKey(trim($item['product_key'])); $product = Product::findProductByKey(trim($item['product_key']));
if (\Auth::user()->account->update_products) { if (\Auth::user()->account->update_products) {
@ -373,7 +430,7 @@ class InvoiceRepository extends BaseRepository
if ($account->quote_number_prefix && strpos($invoiceNumber, $account->quote_number_prefix) === 0) { if ($account->quote_number_prefix && strpos($invoiceNumber, $account->quote_number_prefix) === 0) {
$invoiceNumber = substr($invoiceNumber, strlen($account->quote_number_prefix)); $invoiceNumber = substr($invoiceNumber, strlen($account->quote_number_prefix));
} }
$invoiceNumber = $account->invoice_number_prefix . $invoiceNumber; $invoiceNumber = $account->invoice_number_prefix.$invoiceNumber;
if (Invoice::scope()->withTrashed()->whereInvoiceNumber($invoiceNumber)->first()) { if (Invoice::scope()->withTrashed()->whereInvoiceNumber($invoiceNumber)->first()) {
$invoiceNumber = false; $invoiceNumber = false;
} }
@ -405,7 +462,7 @@ class InvoiceRepository extends BaseRepository
'custom_taxes2', 'custom_taxes2',
'partial', 'partial',
'custom_text_value1', 'custom_text_value1',
'custom_text_value2'] as $field) { 'custom_text_value2', ] as $field) {
$clone->$field = $invoice->$field; $clone->$field = $invoice->$field;
} }
@ -508,7 +565,7 @@ class InvoiceRepository extends BaseRepository
$invoice = Invoice::createNew($recurInvoice); $invoice = Invoice::createNew($recurInvoice);
$invoice->client_id = $recurInvoice->client_id; $invoice->client_id = $recurInvoice->client_id;
$invoice->recurring_invoice_id = $recurInvoice->id; $invoice->recurring_invoice_id = $recurInvoice->id;
$invoice->invoice_number = 'R' . $recurInvoice->account->getNextInvoiceNumber($recurInvoice); $invoice->invoice_number = 'R'.$recurInvoice->account->getNextInvoiceNumber($recurInvoice);
$invoice->amount = $recurInvoice->amount; $invoice->amount = $recurInvoice->amount;
$invoice->balance = $recurInvoice->amount; $invoice->balance = $recurInvoice->amount;
$invoice->invoice_date = date_create()->format('Y-m-d'); $invoice->invoice_date = date_create()->format('Y-m-d');
@ -572,19 +629,19 @@ class InvoiceRepository extends BaseRepository
public function findNeedingReminding($account) public function findNeedingReminding($account)
{ {
$dates = []; $dates = [];
for ($i=1; $i<=3; $i++) { for ($i = 1; $i <= 3; $i++) {
$field = "enable_reminder{$i}"; $field = "enable_reminder{$i}";
if (!$account->$field) { if (!$account->$field) {
continue; continue;
} }
$field = "num_days_reminder{$i}"; $field = "num_days_reminder{$i}";
$dates[] = "due_date = '" . date('Y-m-d', strtotime("- {$account->$field} days")) . "'"; $dates[] = "due_date = '".date('Y-m-d', strtotime("- {$account->$field} days"))."'";
} }
$sql = implode(' OR ', $dates); $sql = implode(' OR ', $dates);
$invoices = Invoice::whereAccountId($account->id) $invoices = Invoice::whereAccountId($account->id)
->where('balance', '>', 0) ->where('balance', '>', 0)
->whereRaw('(' . $sql . ')') ->whereRaw('('.$sql.')')
->get(); ->get();
return $invoices; return $invoices;

View File

@ -1,5 +1,6 @@
<?php namespace App\Ninja\Repositories; <?php namespace App\Ninja\Repositories;
use DB;
use Utils; use Utils;
use App\Models\Payment; use App\Models\Payment;
use App\Models\Credit; use App\Models\Credit;
@ -16,7 +17,8 @@ class PaymentRepository extends BaseRepository
public function find($clientPublicId = null, $filter = null) public function find($clientPublicId = null, $filter = null)
{ {
$query = \DB::table('payments') $query = DB::table('payments')
->join('accounts', 'accounts.id', '=', 'payments.account_id')
->join('clients', 'clients.id', '=', 'payments.client_id') ->join('clients', 'clients.id', '=', 'payments.client_id')
->join('invoices', 'invoices.id', '=', 'payments.invoice_id') ->join('invoices', 'invoices.id', '=', 'payments.invoice_id')
->join('contacts', 'contacts.client_id', '=', 'clients.id') ->join('contacts', 'contacts.client_id', '=', 'clients.id')
@ -29,6 +31,8 @@ class PaymentRepository extends BaseRepository
->where('contacts.deleted_at', '=', null) ->where('contacts.deleted_at', '=', null)
->where('invoices.is_deleted', '=', false) ->where('invoices.is_deleted', '=', false)
->select('payments.public_id', ->select('payments.public_id',
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
'payments.transaction_reference', 'payments.transaction_reference',
'clients.name as client_name', 'clients.name as client_name',
'clients.public_id as client_public_id', 'clients.public_id as client_public_id',
@ -36,7 +40,6 @@ class PaymentRepository extends BaseRepository
'payments.payment_date', 'payments.payment_date',
'invoices.public_id as invoice_public_id', 'invoices.public_id as invoice_public_id',
'invoices.invoice_number', 'invoices.invoice_number',
'clients.currency_id',
'contacts.first_name', 'contacts.first_name',
'contacts.last_name', 'contacts.last_name',
'contacts.email', 'contacts.email',
@ -67,7 +70,8 @@ class PaymentRepository extends BaseRepository
public function findForContact($contactId = null, $filter = null) public function findForContact($contactId = null, $filter = null)
{ {
$query = \DB::table('payments') $query = DB::table('payments')
->join('accounts', 'accounts.id', '=', 'payments.account_id')
->join('clients', 'clients.id', '=', 'payments.client_id') ->join('clients', 'clients.id', '=', 'payments.client_id')
->join('invoices', 'invoices.id', '=', 'payments.invoice_id') ->join('invoices', 'invoices.id', '=', 'payments.invoice_id')
->join('contacts', 'contacts.client_id', '=', 'clients.id') ->join('contacts', 'contacts.client_id', '=', 'clients.id')
@ -81,7 +85,24 @@ class PaymentRepository extends BaseRepository
->where('invitations.deleted_at', '=', null) ->where('invitations.deleted_at', '=', null)
->where('invoices.deleted_at', '=', null) ->where('invoices.deleted_at', '=', null)
->where('invitations.contact_id', '=', $contactId) ->where('invitations.contact_id', '=', $contactId)
->select('invitations.invitation_key', 'payments.public_id', 'payments.transaction_reference', 'clients.name as client_name', 'clients.public_id as client_public_id', 'payments.amount', 'payments.payment_date', 'invoices.public_id as invoice_public_id', 'invoices.invoice_number', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'payment_types.name as payment_type', 'payments.account_gateway_id'); ->select(
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
'invitations.invitation_key',
'payments.public_id',
'payments.transaction_reference',
'clients.name as client_name',
'clients.public_id as client_public_id',
'payments.amount',
'payments.payment_date',
'invoices.public_id as invoice_public_id',
'invoices.invoice_number',
'contacts.first_name',
'contacts.last_name',
'contacts.email',
'payment_types.name as payment_type',
'payments.account_gateway_id'
);
if ($filter) { if ($filter) {
$query->where(function ($query) use ($filter) { $query->where(function ($query) use ($filter) {

View File

@ -44,7 +44,7 @@ class ActivityService extends BaseService
'quote' => $model->invoice ? link_to('/quotes/' . $model->invoice_public_id, $model->invoice) : null, 'quote' => $model->invoice ? link_to('/quotes/' . $model->invoice_public_id, $model->invoice) : null,
'contact' => $model->contact_id ? link_to('/clients/' . $model->client_public_id, Utils::getClientDisplayName($model)) : Utils::getPersonDisplayName($model->user_first_name, $model->user_last_name, $model->user_email), 'contact' => $model->contact_id ? link_to('/clients/' . $model->client_public_id, Utils::getClientDisplayName($model)) : Utils::getPersonDisplayName($model->user_first_name, $model->user_last_name, $model->user_email),
'payment' => $model->payment ?: '', 'payment' => $model->payment ?: '',
'credit' => Utils::formatMoney($model->credit, $model->currency_id) 'credit' => Utils::formatMoney($model->credit, $model->currency_id, $model->country_id)
]; ];
return trans("texts.activity_{$model->activity_type_id}", $data); return trans("texts.activity_{$model->activity_type_id}", $data);
@ -53,13 +53,13 @@ class ActivityService extends BaseService
[ [
'balance', 'balance',
function ($model) { function ($model) {
return Utils::formatMoney($model->balance, $model->currency_id); return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id);
} }
], ],
[ [
'adjustment', 'adjustment',
function ($model) { function ($model) {
return $model->adjustment != 0 ? Utils::wrapAdjustment($model->adjustment, $model->currency_id) : ''; return $model->adjustment != 0 ? Utils::wrapAdjustment($model->adjustment, $model->currency_id, $model->country_id) : '';
} }
] ]
]; ];

View File

@ -76,7 +76,7 @@ class ClientService extends BaseService
[ [
'balance', 'balance',
function ($model) { function ($model) {
return Utils::formatMoney($model->balance, $model->currency_id); return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id);
} }
] ]
]; ];

View File

@ -47,13 +47,13 @@ class CreditService extends BaseService
[ [
'amount', 'amount',
function ($model) { function ($model) {
return Utils::formatMoney($model->amount, $model->currency_id) . '<span '.Utils::getEntityRowClass($model).'/>'; return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id) . '<span '.Utils::getEntityRowClass($model).'/>';
} }
], ],
[ [
'balance', 'balance',
function ($model) { function ($model) {
return Utils::formatMoney($model->balance, $model->currency_id); return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id);
} }
], ],
[ [

View File

@ -116,7 +116,7 @@ class InvoiceService extends BaseService
[ [
'amount', 'amount',
function ($model) { function ($model) {
return Utils::formatMoney($model->amount, $model->currency_id); return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id);
} }
], ],
[ [
@ -124,10 +124,10 @@ class InvoiceService extends BaseService
function ($model) { function ($model) {
return $model->partial > 0 ? return $model->partial > 0 ?
trans('texts.partial_remaining', [ trans('texts.partial_remaining', [
'partial' => Utils::formatMoney($model->partial, $model->currency_id), 'partial' => Utils::formatMoney($model->partial, $model->currency_id, $model->country_id),
'balance' => Utils::formatMoney($model->balance, $model->currency_id)] 'balance' => Utils::formatMoney($model->balance, $model->currency_id, $model->country_id)]
) : ) :
Utils::formatMoney($model->balance, $model->currency_id); Utils::formatMoney($model->balance, $model->currency_id, $model->country_id);
}, },
$entityType == ENTITY_INVOICE $entityType == ENTITY_INVOICE
], ],

View File

@ -287,7 +287,7 @@ class PaymentService extends BaseService
[ [
'amount', 'amount',
function ($model) { function ($model) {
return Utils::formatMoney($model->amount, $model->currency_id); return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id);
} }
], ],
[ [

View File

@ -53,7 +53,7 @@ class RecurringInvoiceService extends BaseService
[ [
'amount', 'amount',
function ($model) { function ($model) {
return Utils::formatMoney($model->amount, $model->currency_id); return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id);
} }
] ]
]; ];

View File

@ -267,8 +267,9 @@ class PaymentLibrariesSeeder extends Seeder
'AR' => [ 'AR' => [
'swap_postal_code' => true, 'swap_postal_code' => true,
], ],
'AT' => [ 'AT' => [ // Austria
'swap_postal_code' => true, 'swap_postal_code' => true,
'swap_currency_symbol' => true,
], ],
'BE' => [ 'BE' => [
'swap_postal_code' => true, 'swap_postal_code' => true,

15
public/css/built.css vendored
View File

@ -3381,19 +3381,4 @@ ul.user-accounts a:hover div.remove {
div.panel-body div.panel-body { div.panel-body div.panel-body {
padding-bottom: 0px; padding-bottom: 0px;
}
.email-button {
border: 0 none;
border-radius: 36px;
padding: 12px 45px;
margin: 0 10px;
cursor: pointer;
display: inline-block;
font-size: 14px;
color: #fff;
text-transform: none;
} }

View File

@ -29911,15 +29911,7 @@ function generatePDF(invoice, javascript, force, cb) {
return; return;
} }
invoiceOld = invoice; invoiceOld = invoice;
pdfmakeMarker = "{"; doc = GetPdfMake(invoice, javascript, cb);
if(javascript.slice(0, pdfmakeMarker.length) === pdfmakeMarker) {
doc = GetPdfMake(invoice, javascript, cb);
} else {
doc = GetPdf(invoice, javascript);
doc.getDataUrl = function(cb) {
cb( this.output("datauristring"));
};
}
if (cb) { if (cb) {
doc.getDataUrl(cb); doc.getDataUrl(cb);
@ -29933,135 +29925,6 @@ function copyObject(orig) {
return JSON.parse(JSON.stringify(orig)); return JSON.parse(JSON.stringify(orig));
} }
function GetPdf(invoice, javascript){
var layout = {
accountTop: 40,
marginLeft: 50,
marginRight: 550,
headerTop: 150,
headerLeft: 360,
headerRight: 550,
rowHeight: 15,
tableRowHeight: 10,
footerLeft: 420,
tablePadding: 12,
tableTop: 250,
descriptionLeft: 150,
unitCostRight: 410,
qtyRight: 480,
taxRight: 480,
lineTotalRight: 550
};
/*
if (invoice.has_taxes)
{
layout.descriptionLeft -= 20;
layout.unitCostRight -= 40;
layout.qtyRight -= 40;
}
*/
/*
@param orientation One of "portrait" or "landscape" (or shortcuts "p" (Default), "l")
@param unit Measurement unit to be used when coordinates are specified. One of "pt" (points), "mm" (Default), "cm", "in"
@param format One of 'a3', 'a4' (Default),'a5' ,'letter' ,'legal'
@returns {jsPDF}
*/
var doc = new jsPDF('portrait', 'pt', 'a4');
//doc.getStringUnitWidth = function(param) { console.log('getStringUnitWidth: %s', param); return 0};
//Set PDF properities
doc.setProperties({
title: 'Invoice ' + invoice.invoice_number,
subject: '',
author: 'InvoiceNinja.com',
keywords: 'pdf, invoice',
creator: 'InvoiceNinja.com'
});
//set default style for report
doc.setFont('Helvetica','');
// For partial payments show "Amount Due" rather than "Balance Due"
if (!invoiceLabels.balance_due_orig) {
invoiceLabels.balance_due_orig = invoiceLabels.balance_due;
}
invoiceLabels.balance_due = NINJA.parseFloat(invoice.partial) ? invoiceLabels.amount_due : invoiceLabels.balance_due_orig;
eval(javascript);
// add footer
if (invoice.invoice_footer) {
doc.setFontType('normal');
doc.setFontSize('8');
SetPdfColor(invoice.invoice_design_id == 2 || invoice.invoice_design_id == 3 ? 'White' : 'Black',doc);
var top = doc.internal.pageSize.height - layout.marginLeft;
if (!invoice.is_pro) top -= 25;
var footer = doc.splitTextToSize(processVariables(invoice.invoice_footer), 500);
var numLines = footer.length - 1;
doc.text(layout.marginLeft, top - (numLines * 8), footer);
}
return doc;
}
function SetPdfColor(color, doc, role)
{
if (role === 'primary' && NINJA.primaryColor) {
return setDocHexColor(doc, NINJA.primaryColor);
} else if (role === 'secondary' && NINJA.secondaryColor) {
return setDocHexColor(doc, NINJA.secondaryColor);
}
if (color=='LightBlue') {
return doc.setTextColor(41,156, 194);
}
if (color=='Black') {
return doc.setTextColor(46,43,43);//select color black
}
if (color=='GrayLogo') {
return doc.setTextColor(207,241, 241);//select color Custom Report GRAY
}
if (color=='GrayBackground') {
return doc.setTextColor(251,251, 251);//select color Custom Report GRAY
}
if (color=='GrayText') {
return doc.setTextColor(161,160,160);//select color Custom Report GRAY Colour
}
if (color=='White') {
return doc.setTextColor(255,255,255);//select color Custom Report GRAY Colour
}
if (color=='SomeGreen') {
return doc.setTextColor(54,164,152);//select color Custom Report GRAY Colour
}
if (color=='LightGrayReport2-gray') {
return doc.setTextColor(240,240,240);//select color Custom Report GRAY Colour
}
if (color=='LightGrayReport2-white') {
return doc.setTextColor(251,251,251);//select color Custom Report GRAY Colour
}
if (color=='orange') {
return doc.setTextColor(234,121,45);//select color Custom Report GRAY Colour
}
if (color=='Green') {
return doc.setTextColor(55,109,69);
}
}
/* Handle converting variables in the invoices (ie, MONTH+1) */ /* Handle converting variables in the invoices (ie, MONTH+1) */
function processVariables(str) { function processVariables(str) {
if (!str) return ''; if (!str) return '';
@ -30494,8 +30357,8 @@ function populateInvoiceComboboxes(clientId, invoiceId) {
var client = clientMap[invoice.client.public_id]; var client = clientMap[invoice.client.public_id];
if (!client) continue; // client is deleted/archived if (!client) continue; // client is deleted/archived
$invoiceCombobox.append(new Option(invoice.invoice_number + ' - ' + invoice.invoice_status.name + ' - ' + $invoiceCombobox.append(new Option(invoice.invoice_number + ' - ' + invoice.invoice_status.name + ' - ' +
getClientDisplayName(client) + ' - ' + formatMoney(invoice.amount, client.currency_id) + ' | ' + getClientDisplayName(client) + ' - ' + formatMoneyInvoice(invoice.amount, invoice) + ' | ' +
formatMoney(invoice.balance, client.currency_id), invoice.public_id)); formatMoneyInvoice(invoice.balance, invoice), invoice.public_id));
} }
$('select#invoice').combobox('refresh'); $('select#invoice').combobox('refresh');
}); });
@ -30506,6 +30369,7 @@ function populateInvoiceComboboxes(clientId, invoiceId) {
if (invoiceId) { if (invoiceId) {
var invoice = invoiceMap[invoiceId]; var invoice = invoiceMap[invoiceId];
var client = clientMap[invoice.client.public_id]; var client = clientMap[invoice.client.public_id];
invoice.client = client;
setComboboxValue($('.client-select'), client.public_id, getClientDisplayName(client)); setComboboxValue($('.client-select'), client.public_id, getClientDisplayName(client));
if (!parseFloat($('#amount').val())) { if (!parseFloat($('#amount').val())) {
$('#amount').val(parseFloat(invoice.balance).toFixed(2)); $('#amount').val(parseFloat(invoice.balance).toFixed(2));
@ -30518,9 +30382,10 @@ function populateInvoiceComboboxes(clientId, invoiceId) {
if (invoiceId) { if (invoiceId) {
var invoice = invoiceMap[invoiceId]; var invoice = invoiceMap[invoiceId];
var client = clientMap[invoice.client.public_id]; var client = clientMap[invoice.client.public_id];
invoice.client = client;
setComboboxValue($('.invoice-select'), invoice.public_id, (invoice.invoice_number + ' - ' + setComboboxValue($('.invoice-select'), invoice.public_id, (invoice.invoice_number + ' - ' +
invoice.invoice_status.name + ' - ' + getClientDisplayName(client) + ' - ' + invoice.invoice_status.name + ' - ' + getClientDisplayName(client) + ' - ' +
formatMoney(invoice.amount, client.currency_id) + ' | ' + formatMoney(invoice.balance, client.currency_id))); formatMoneyInvoice(invoice.amount, invoice) + ' | ' + formatMoneyInvoice(invoice.balance, invoice)));
$invoiceSelect.trigger('change'); $invoiceSelect.trigger('change');
} else if (clientId) { } else if (clientId) {
var client = clientMap[clientId]; var client = clientMap[clientId];
@ -30542,174 +30407,6 @@ CONSTS.INVOICE_STATUS_PAID = 5;
$.fn.datepicker.defaults.autoclose = true; $.fn.datepicker.defaults.autoclose = true;
$.fn.datepicker.defaults.todayHighlight = true; $.fn.datepicker.defaults.todayHighlight = true;
function displayAccount(doc, invoice, x, y, layout) {
var account = invoice.account;
if (!account) {
return;
}
var data1 = [
account.name,
account.id_number,
account.vat_number,
account.work_email,
account.work_phone
];
var data2 = [
concatStrings(account.address1, account.address2),
concatStrings(account.city, account.state, account.postal_code),
account.country ? account.country.name : false,
invoice.account.custom_value1 ? invoice.account['custom_label1'] + ' ' + invoice.account.custom_value1 : false,
invoice.account.custom_value2 ? invoice.account['custom_label2'] + ' ' + invoice.account.custom_value2 : false,
];
if (layout.singleColumn) {
displayGrid(doc, invoice, data1.concat(data2), x, y, layout, {hasHeader:true});
} else {
displayGrid(doc, invoice, data1, x, y, layout, {hasHeader:true});
var nameWidth = account.name ? (doc.getStringUnitWidth(account.name) * doc.internal.getFontSize() * 1.1) : 0;
var emailWidth = account.work_email ? (doc.getStringUnitWidth(account.work_email) * doc.internal.getFontSize() * 1.1) : 0;
width = Math.max(emailWidth, nameWidth, 120);
x += width;
displayGrid(doc, invoice, data2, x, y, layout);
}
}
function displayClient(doc, invoice, x, y, layout) {
var client = invoice.client;
if (!client) {
return;
}
var data = [
getClientDisplayName(client),
client.id_number,
client.vat_number,
concatStrings(client.address1, client.address2),
concatStrings(client.city, client.state, client.postal_code),
client.country ? client.country.name : false,
invoice.contact && getClientDisplayName(client) != invoice.contact.email ? invoice.contact.email : false,
invoice.client.custom_value1 ? invoice.account['custom_client_label1'] + ' ' + invoice.client.custom_value1 : false,
invoice.client.custom_value2 ? invoice.account['custom_client_label2'] + ' ' + invoice.client.custom_value2 : false,
];
return displayGrid(doc, invoice, data, x, y, layout, {hasheader:true});
}
function displayInvoice(doc, invoice, x, y, layout, rightAlignX) {
if (!invoice) {
return;
}
var data = getInvoiceDetails(invoice);
var options = {
hasheader: true,
rightAlignX: rightAlignX,
};
return displayGrid(doc, invoice, data, x, y, layout, options);
}
function getInvoiceDetails(invoice) {
var fields = [
{'invoice_number': invoice.invoice_number},
{'po_number': invoice.po_number},
{'invoice_date': invoice.invoice_date},
{'due_date': invoice.due_date},
];
if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) {
fields.push({'total': formatMoney(invoice.amount, invoice.client.currency_id)});
}
if (NINJA.parseFloat(invoice.partial)) {
fields.push({'balance': formatMoney(invoice.total_amount, invoice.client.currency_id)});
}
fields.push({'balance_due': formatMoney(invoice.balance_amount, invoice.client.currency_id)})
return fields;
}
function getInvoiceDetailsHeight(invoice, layout) {
var data = getInvoiceDetails(invoice);
var count = 0;
for (var key in data) {
if (!data.hasOwnProperty(key)) {
continue;
}
var obj = data[key];
for (var subKey in obj) {
if (!obj.hasOwnProperty(subKey)) {
continue;
}
if (obj[subKey]) {
count++;
}
}
}
return count * layout.rowHeight;
}
function displaySubtotals(doc, layout, invoice, y, rightAlignTitleX)
{
if (!invoice) {
return;
}
var data = [
{'subtotal': formatMoney(invoice.subtotal_amount, invoice.client.currency_id)},
{'discount': invoice.discount_amount != 0 ? formatMoney(invoice.discount_amount, invoice.client.currency_id) : false}
];
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 == '1') {
data.push({'custom_invoice_label1': formatMoney(invoice.custom_value1, invoice.client.currency_id) })
}
if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 == '1') {
data.push({'custom_invoice_label2': formatMoney(invoice.custom_value2, invoice.client.currency_id) })
}
data.push({'tax': (invoice.tax && invoice.tax.name) || invoice.tax_name ? formatMoney(invoice.tax_amount, invoice.client.currency_id) : false});
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') {
data.push({'custom_invoice_label1': formatMoney(invoice.custom_value1, invoice.client.currency_id) })
}
if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 != '1') {
data.push({'custom_invoice_label2': formatMoney(invoice.custom_value2, invoice.client.currency_id) })
}
var paid = invoice.amount - invoice.balance;
if (paid) {
data.push({'total': formatMoney(invoice.amount, invoice.client.currency_id)});
}
if (invoice.account.hide_paid_to_date != '1' || paid) {
data.push({'paid_to_date': formatMoney(paid, invoice.client.currency_id)});
}
if (NINJA.parseFloat(invoice.partial) && invoice.total_amount != invoice.subtotal_amount) {
data.push({'balance': formatMoney(invoice.total_amount, invoice.client.currency_id)});
}
var options = {
hasheader: true,
rightAlignX: 550,
rightAlignTitleX: rightAlignTitleX
};
return displayGrid(doc, invoice, data, 300, y, layout, options) + 10;
}
function formatAddress(city, state, zip, swap) { function formatAddress(city, state, zip, swap) {
var str = ''; var str = '';
if (swap) { if (swap) {
@ -30745,106 +30442,6 @@ function concatStrings() {
return data.length ? concatStr : ""; return data.length ? concatStr : "";
} }
function displayGrid(doc, invoice, data, x, y, layout, options) {
var numLines = 0;
var origY = y;
for (var i=0; i<data.length; i++) {
doc.setFontType('normal');
if (invoice.invoice_design_id == 1 && i > 0 && origY === layout.accountTop) {
SetPdfColor('GrayText',doc);
}
var row = data[i];
if (!row) {
continue;
}
if (options && (options.hasheader && i === 0 && !options.rightAlignTitleX)) {
doc.setFontType('bold');
}
if (typeof row === 'object') {
for (var key in row) {
if (row.hasOwnProperty(key)) {
var value = row[key] ? row[key] + '' : false;
}
}
if (!value) {
continue;
}
var marginLeft;
if (options.rightAlignX) {
marginLeft = options.rightAlignX - (doc.getStringUnitWidth(value) * doc.internal.getFontSize());
} else {
marginLeft = x + 80;
}
doc.text(marginLeft, y, value);
doc.setFontType('normal');
if (invoice.is_quote) {
if (key == 'invoice_number') {
key = 'quote_number';
} else if (key == 'invoice_date') {
key = 'quote_date';
} else if (key == 'balance_due') {
key = 'total';
}
}
if (key.substring(0, 6) === 'custom') {
key = invoice.account[key];
} else if (key === 'tax' && invoice.tax_name) {
key = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%';
} else if (key === 'discount' && NINJA.parseFloat(invoice.discount) && !parseInt(invoice.is_amount_discount)) {
key = invoiceLabels[key] + ' ' + parseFloat(invoice.discount) + '%';
} else {
key = invoiceLabels[key];
}
if (options.rightAlignTitleX) {
marginLeft = options.rightAlignTitleX - (doc.getStringUnitWidth(key) * doc.internal.getFontSize());
} else {
marginLeft = x;
}
doc.text(marginLeft, y, key);
} else {
doc.text(x, y, row);
}
numLines++;
y += layout.rowHeight;
}
return numLines * layout.rowHeight;
}
function displayNotesAndTerms(doc, layout, invoice, y)
{
doc.setFontType("normal");
var origY = y;
if (invoice.public_notes) {
var notes = doc.splitTextToSize(processVariables(invoice.public_notes), 260);
doc.text(layout.marginLeft, y, notes);
y += 16 + (notes.length * doc.internal.getFontSize());
}
if (invoice.terms) {
var terms = doc.splitTextToSize(processVariables(invoice.terms), 260);
doc.setFontType("bold");
doc.text(layout.marginLeft, y, invoiceLabels.terms);
y += 16;
doc.setFontType("normal");
doc.text(layout.marginLeft, y, terms);
y += 16 + (terms.length * doc.internal.getFontSize());
}
return y - origY;
}
function calculateAmounts(invoice) { function calculateAmounts(invoice) {
var total = 0; var total = 0;
var hasTaxes = false; var hasTaxes = false;
@ -30968,311 +30565,6 @@ function getInvoiceTaxRate(invoice) {
return tax; return tax;
} }
function displayInvoiceHeader(doc, invoice, layout) {
if (invoice.invoice_design_id == 6 || invoice.invoice_design_id == 8 || invoice.invoice_design_id == 10) {
invoiceLabels.item = invoiceLabels.item.toUpperCase();
invoiceLabels.description = invoiceLabels.description.toUpperCase();
invoiceLabels.unit_cost = invoiceLabels.unit_cost.toUpperCase();
invoiceLabels.quantity = invoiceLabels.quantity.toUpperCase();
invoiceLabels.line_total = invoiceLabels.total.toUpperCase();
invoiceLabels.tax = invoiceLabels.tax.toUpperCase();
}
var costX = layout.unitCostRight - (doc.getStringUnitWidth(invoiceLabels.unit_cost) * doc.internal.getFontSize());
var qtyX = layout.qtyRight - (doc.getStringUnitWidth(invoiceLabels.quantity) * doc.internal.getFontSize());
var taxX = layout.taxRight - (doc.getStringUnitWidth(invoiceLabels.tax) * doc.internal.getFontSize());
var totalX = layout.lineTotalRight - (doc.getStringUnitWidth(invoiceLabels.line_total) * doc.internal.getFontSize());
doc.text(layout.marginLeft, layout.tableTop, invoiceLabels.item);
doc.text(layout.descriptionLeft, layout.tableTop, invoiceLabels.description);
doc.text(costX, layout.tableTop, invoiceLabels.unit_cost);
if (invoice.account.hide_quantity != '1') {
doc.text(qtyX, layout.tableTop, invoiceLabels.quantity);
}
doc.text(totalX, layout.tableTop, invoiceLabels.line_total);
/*
if (invoice.has_taxes)
{
doc.text(taxX, layout.tableTop, invoiceLabels.tax);
}
*/
}
function displayInvoiceItems(doc, invoice, layout) {
doc.setFontType("normal");
var line = 1;
var total = 0;
var shownItem = false;
var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1;
var tableTop = layout.tableTop;
var hideQuantity = invoice.account.hide_quantity == '1';
doc.setFontSize(8);
for (var i=0; i<invoice.invoice_items.length; i++) {
var item = invoice.invoice_items[i];
var cost = formatMoney(item.cost, currencyId, true);
var qty = NINJA.parseFloat(item.qty) ? roundToTwo(NINJA.parseFloat(item.qty)) + '' : '';
var notes = item.notes;
var productKey = item.product_key;
var tax = 0;
if (item.tax && parseFloat(item.tax.rate)) {
tax = parseFloat(item.tax.rate);
} else if (item.tax_rate && parseFloat(item.tax_rate)) {
tax = parseFloat(item.tax_rate);
}
// show at most one blank line
if (shownItem && (!cost || cost == '0.00') && !notes && !productKey) {
continue;
}
shownItem = true;
var numLines = Math.max(doc.splitTextToSize(item.notes, 200).length, doc.splitTextToSize(item.product_key, 60).length) + 2;
//console.log('num lines %s', numLines);
var y = tableTop + (line * layout.tableRowHeight) + (2 * layout.tablePadding);
var top = y - layout.tablePadding;
var newTop = top + (numLines * layout.tableRowHeight);
if (newTop > 770) {
line = 0;
tableTop = layout.accountTop + layout.tablePadding;
y = tableTop + (2 * layout.tablePadding);
top = y - layout.tablePadding;
newTop = top + (numLines * layout.tableRowHeight);
doc.addPage();
}
var left = layout.marginLeft - layout.tablePadding;
var width = layout.marginRight + layout.tablePadding;
// process date variables
if (invoice.is_recurring) {
notes = processVariables(notes);
productKey = processVariables(productKey);
}
var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty));
if (tax) {
lineTotal += lineTotal * tax / 100;
}
if (lineTotal) {
total += lineTotal;
}
lineTotal = formatMoney(lineTotal, currencyId);
var costX = layout.unitCostRight - (doc.getStringUnitWidth(cost) * doc.internal.getFontSize());
var qtyX = layout.qtyRight - (doc.getStringUnitWidth(qty) * doc.internal.getFontSize());
var taxX = layout.taxRight - (doc.getStringUnitWidth(tax+'%') * doc.internal.getFontSize());
var totalX = layout.lineTotalRight - (doc.getStringUnitWidth(lineTotal) * doc.internal.getFontSize());
//if (i==0) y -= 4;
line += numLines;
if (invoice.invoice_design_id == 1) {
if (i%2 == 0) {
doc.setDrawColor(255,255,255);
doc.setFillColor(246,246,246);
doc.rect(left, top, width-left, newTop-top, 'FD');
doc.setLineWidth(0.3);
doc.setDrawColor(200,200,200);
doc.line(left, top, width, top);
doc.line(left, newTop, width, newTop);
}
} else if (invoice.invoice_design_id == 2) {
if (i%2 == 0) {
left = 0;
width = 1000;
doc.setDrawColor(255,255,255);
doc.setFillColor(235,235,235);
doc.rect(left, top, width-left, newTop-top, 'FD');
}
} else if (invoice.invoice_design_id == 5) {
if (i%2 == 0) {
doc.setDrawColor(255,255,255);
doc.setFillColor(247,247,247);
doc.rect(left, top, width-left+17, newTop-top, 'FD');
} else {
doc.setDrawColor(255,255,255);
doc.setFillColor(232,232,232);
doc.rect(left, top, width-left+17, newTop-top, 'FD');
}
} else if (invoice.invoice_design_id == 6) {
if (i%2 == 0) {
doc.setDrawColor(232,232,232);
doc.setFillColor(232,232,232);
doc.rect(left, top, width-left, newTop-top, 'FD');
} else {
doc.setDrawColor(255,255,255);
doc.setFillColor(255,255,255);
doc.rect(left, top, width-left, newTop-top, 'FD');
}
} else if (invoice.invoice_design_id == 7) {
doc.setLineWidth(1);
doc.setDrawColor(45,35,32);
for(var k = 1; k<=width-20; k++) {
doc.line(left+4+k,newTop,left+4+1+k,newTop);
k = k+3;
}
} else if (invoice.invoice_design_id == 8) {
} else if (invoice.invoice_design_id == 9) {
doc.setLineWidth(1);
doc.setDrawColor(0,157,145);
for(var j = 1; j<=width-40; j++) {
doc.line(left+j,newTop,left+2+j,newTop);
j = j+5;
}
} else if (invoice.invoice_design_id == 10) {
doc.setLineWidth(0.3);
doc.setDrawColor(63,60,60);
doc.line(left, newTop, width, newTop);
} else {
doc.setLineWidth(0.3);
doc.setDrawColor(150,150,150);
doc.line(left, newTop, width, newTop);
}
y += 4;
if (invoice.invoice_design_id == 1) {
SetPdfColor('LightBlue', doc, 'primary');
} else if (invoice.invoice_design_id == 2) {
SetPdfColor('SomeGreen', doc, 'primary');
} else if (invoice.invoice_design_id == 3) {
doc.setFontType('bold');
} else if (invoice.invoice_design_id == 4) {
SetPdfColor('Black', doc);
} else if (invoice.invoice_design_id == 5) {
SetPdfColor('Black', doc);
} else if (invoice.invoice_design_id == 6) {
SetPdfColor('Black', doc);
}
var splitTitle = doc.splitTextToSize(productKey, 60);
if(invoice.invoice_design_id == 6) {
doc.setFontType('bold');
}
if(invoice.invoice_design_id == 9) {
doc.setTextColor(187,51,40);
}
if(invoice.invoice_design_id == 10) {
doc.setTextColor(205,81,56);
}
doc.text(layout.marginLeft, y+2, splitTitle);
if (invoice.invoice_design_id == 5) {
doc.setDrawColor(255, 255, 255);
doc.setLineWidth(1);
doc.line(layout.descriptionLeft-8, y-16,layout.descriptionLeft-8, y+55);
doc.line(costX-30, y-16,costX-30, y+55);
doc.line(qtyX-45, y-16,qtyX-45, y+55);
/*
if (invoice.has_taxes) {
doc.line(taxX-15, y-16,taxX-15, y+55);
}
*/
doc.line(totalX-27, y-16,totalX-27, y+55);
}
/*
if (invoice.invoice_design_id == 8) {
doc.setDrawColor(30, 30, 30);
doc.setLineWidth(0.5);
doc.line(layout.marginLeft-10, y-60,layout.marginLeft-10, y+20);
doc.line(layout.descriptionLeft-8, y-60,layout.descriptionLeft-8, y+20);
doc.line(costX-30, y-60,costX-30, y+20);
console.log('CostX: %s', costX);
doc.line(qtyX-45, y-60,qtyX-45, y+20);
if (invoice.has_taxes) {
doc.line(taxX-10, y-60,taxX-10, y+20);
}
doc.line(totalX-27, y-60,totalX-27, y+120);
doc.line(totalX+35, y-60,totalX+35, y+120);
}
*/
SetPdfColor('Black', doc);
doc.setFontType('normal');
var splitDescription = doc.splitTextToSize(notes, 190);
doc.text(layout.descriptionLeft, y+2, splitDescription);
doc.text(costX, y+2, cost);
if (!hideQuantity) {
doc.text(qtyX, y+2, qty);
}
if(invoice.invoice_design_id == 9) {
doc.setTextColor(187,51,40);
doc.setFontType('bold');
}
if(invoice.invoice_design_id == 10) {
doc.setTextColor(205,81,56);
}
doc.text(totalX, y+2, lineTotal);
doc.setFontType('normal');
SetPdfColor('Black', doc);
if (tax) {
doc.text(taxX, y+2, tax+'%');
}
}
y = tableTop + (line * layout.tableRowHeight) + (3 * layout.tablePadding);
if (invoice.invoice_design_id == 8) {
doc.setDrawColor(30, 30, 30);
doc.setLineWidth(0.5);
var topX = tableTop - 14;
doc.line(layout.marginLeft-10, topX,layout.marginLeft-10, y);
doc.line(layout.descriptionLeft-8, topX,layout.descriptionLeft-8, y);
doc.line(layout.unitCostRight-55, topX,layout.unitCostRight-55, y);
doc.line(layout.qtyRight-50, topX,layout.qtyRight-50, y);
/*
if (invoice.has_taxes) {
doc.line(layout.taxRight-28, topX,layout.taxRight-28, y);
}
*/
doc.line(totalX-25, topX,totalX-25, y+90);
doc.line(totalX+45, topX,totalX+45, y+90);
}
var cutoff = 700;
if (invoice.terms) {
cutoff -= 50;
}
if (invoice.public_notes) {
cutoff -= 50;
}
if (y > cutoff) {
doc.addPage();
return layout.marginLeft;
}
return y;
}
// http://stackoverflow.com/questions/11941876/correctly-suppressing-warnings-in-datatables // http://stackoverflow.com/questions/11941876/correctly-suppressing-warnings-in-datatables
window.alert = (function() { window.alert = (function() {
var nativeAlert = window.alert; var nativeAlert = window.alert;
@ -31719,7 +31011,7 @@ NINJA.decodeJavascript = function(invoice, javascript)
'subtotalsHeight': (NINJA.subtotals(invoice).length * 16) + 16, 'subtotalsHeight': (NINJA.subtotals(invoice).length * 16) + 16,
'subtotalsWithoutBalance': NINJA.subtotals(invoice, true), 'subtotalsWithoutBalance': NINJA.subtotals(invoice, true),
'subtotalsBalance': NINJA.subtotalsBalance(invoice), 'subtotalsBalance': NINJA.subtotalsBalance(invoice),
'balanceDue': formatMoney(invoice.balance_amount, invoice.client.currency_id), 'balanceDue': formatMoneyInvoice(invoice.balance_amount, invoice),
'invoiceFooter': NINJA.invoiceFooter(invoice), 'invoiceFooter': NINJA.invoiceFooter(invoice),
'invoiceNumber': invoice.invoice_number || ' ', 'invoiceNumber': invoice.invoice_number || ' ',
'entityType': invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice, 'entityType': invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice,
@ -31849,7 +31141,6 @@ NINJA.taxWidth = function(invoice)
NINJA.invoiceLines = function(invoice) { NINJA.invoiceLines = function(invoice) {
var total = 0; var total = 0;
var shownItem = false; var shownItem = false;
var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1;
var hideQuantity = invoice.account.hide_quantity == '1'; var hideQuantity = invoice.account.hide_quantity == '1';
var showItemTaxes = invoice.account.show_item_taxes == '1'; var showItemTaxes = invoice.account.show_item_taxes == '1';
@ -31872,7 +31163,7 @@ NINJA.invoiceLines = function(invoice) {
var row = []; var row = [];
var item = invoice.invoice_items[i]; var item = invoice.invoice_items[i];
var cost = formatMoney(item.cost, currencyId, true); var cost = formatMoneyInvoice(item.cost, invoice, true);
var qty = NINJA.parseFloat(item.qty) ? roundToTwo(NINJA.parseFloat(item.qty)) + '' : ''; var qty = NINJA.parseFloat(item.qty) ? roundToTwo(NINJA.parseFloat(item.qty)) + '' : '';
var notes = item.notes; var notes = item.notes;
var productKey = item.product_key; var productKey = item.product_key;
@ -31903,7 +31194,7 @@ NINJA.invoiceLines = function(invoice) {
if (showItemTaxes && tax) { if (showItemTaxes && tax) {
lineTotal += lineTotal * tax / 100; lineTotal += lineTotal * tax / 100;
} }
lineTotal = formatMoney(lineTotal, currencyId); lineTotal = formatMoneyInvoice(lineTotal, invoice);
rowStyle = (i % 2 == 0) ? 'odd' : 'even'; rowStyle = (i % 2 == 0) ? 'odd' : 'even';
@ -31932,49 +31223,49 @@ NINJA.subtotals = function(invoice, hideBalance)
var account = invoice.account; var account = invoice.account;
var data = []; var data = [];
data.push([{text: invoiceLabels.subtotal}, {text: formatMoney(invoice.subtotal_amount, invoice.client.currency_id)}]); data.push([{text: invoiceLabels.subtotal}, {text: formatMoneyInvoice(invoice.subtotal_amount, invoice)}]);
if (invoice.discount_amount != 0) { if (invoice.discount_amount != 0) {
data.push([{text: invoiceLabels.discount}, {text: formatMoney(invoice.discount_amount, invoice.client.currency_id)}]); data.push([{text: invoiceLabels.discount}, {text: formatMoneyInvoice(invoice.discount_amount, invoice)}]);
} }
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 == '1') { if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 == '1') {
data.push([{text: account.custom_invoice_label1}, {text: formatMoney(invoice.custom_value1, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label1}, {text: formatMoneyInvoice(invoice.custom_value1, invoice)}]);
} }
if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 == '1') { if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 == '1') {
data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label2}, {text: formatMoneyInvoice(invoice.custom_value2, invoice)}]);
} }
for (var key in invoice.item_taxes) { for (var key in invoice.item_taxes) {
if (invoice.item_taxes.hasOwnProperty(key)) { if (invoice.item_taxes.hasOwnProperty(key)) {
var taxRate = invoice.item_taxes[key]; var taxRate = invoice.item_taxes[key];
var taxStr = taxRate.name + ' ' + (taxRate.rate*1).toString() + '%'; var taxStr = taxRate.name + ' ' + (taxRate.rate*1).toString() + '%';
data.push([{text: taxStr}, {text: formatMoney(taxRate.amount, invoice.client.currency_id)}]); data.push([{text: taxStr}, {text: formatMoneyInvoice(taxRate.amount, invoice)}]);
} }
} }
if (invoice.tax && invoice.tax.name || invoice.tax_name) { if (invoice.tax && invoice.tax.name || invoice.tax_name) {
var taxStr = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%'; var taxStr = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%';
data.push([{text: taxStr}, {text: formatMoney(invoice.tax_amount, invoice.client.currency_id)}]); data.push([{text: taxStr}, {text: formatMoneyInvoice(invoice.tax_amount, invoice)}]);
} }
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') { if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') {
data.push([{text: account.custom_invoice_label1}, {text: formatMoney(invoice.custom_value1, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label1}, {text: formatMoneyInvoice(invoice.custom_value1, invoice)}]);
} }
if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 != '1') { if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 != '1') {
data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label2}, {text: formatMoneyInvoice(invoice.custom_value2, invoice)}]);
} }
var paid = invoice.amount - invoice.balance; var paid = invoice.amount - invoice.balance;
if (invoice.account.hide_paid_to_date != '1' || paid) { if (invoice.account.hide_paid_to_date != '1' || paid) {
data.push([{text:invoiceLabels.paid_to_date}, {text:formatMoney(paid, invoice.client.currency_id)}]); data.push([{text:invoiceLabels.paid_to_date}, {text:formatMoneyInvoice(paid, invoice)}]);
} }
if (!hideBalance) { if (!hideBalance) {
var isPartial = NINJA.parseFloat(invoice.partial); var isPartial = NINJA.parseFloat(invoice.partial);
data.push([ data.push([
{text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']},
{text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} {text: formatMoneyInvoice(invoice.balance_amount, invoice), style:['balanceDue']}
]); ]);
} }
@ -31985,7 +31276,7 @@ NINJA.subtotalsBalance = function(invoice) {
var isPartial = NINJA.parseFloat(invoice.partial); var isPartial = NINJA.parseFloat(invoice.partial);
return [[ return [[
{text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']},
{text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} {text: formatMoneyInvoice(invoice.balance_amount, invoice), style:['balanceDue']}
]]; ]];
} }
@ -32005,7 +31296,7 @@ NINJA.accountAddress = function(invoice) {
var account = invoice.account; var account = invoice.account;
var cityStatePostal = ''; var cityStatePostal = '';
if (account.city || account.state || account.postal_code) { if (account.city || account.state || account.postal_code) {
var swap = account.country && account.country.swap_postal_code == '1'; var swap = account.country && account.country.swap_postal_code;
cityStatePostal = formatAddress(account.city, account.state, account.postal_code, swap); cityStatePostal = formatAddress(account.city, account.state, account.postal_code, swap);
} }
var data = [ var data = [
@ -32062,18 +31353,18 @@ NINJA.invoiceDetails = function(invoice) {
if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) { if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) {
data.push([ data.push([
{text: invoiceLabels.total}, {text: invoiceLabels.total},
{text: formatMoney(invoice.amount, invoice.client.currency_id)} {text: formatMoneyInvoice(invoice.amount, invoice)}
]); ]);
} else if (isPartial) { } else if (isPartial) {
data.push([ data.push([
{text: invoiceLabels.total}, {text: invoiceLabels.total},
{text: formatMoney(invoice.total_amount, invoice.client.currency_id)} {text: formatMoneyInvoice(invoice.total_amount, invoice)}
]); ]);
} }
data.push([ data.push([
{text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']},
{text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style: ['invoiceDetailBalanceDue']} {text: formatMoneyInvoice(invoice.balance_amount, invoice), style: ['invoiceDetailBalanceDue']}
]) ])
return NINJA.prepareDataPairs(data, 'invoiceDetails'); return NINJA.prepareDataPairs(data, 'invoiceDetails');
@ -32092,7 +31383,7 @@ NINJA.clientDetails = function(invoice) {
var cityStatePostal = ''; var cityStatePostal = '';
if (client.city || client.state || client.postal_code) { if (client.city || client.state || client.postal_code) {
var swap = client.country && client.country.swap_postal_code == '1'; var swap = client.country && client.country.swap_postal_code;
cityStatePostal = formatAddress(client.city, client.state, client.postal_code, swap); cityStatePostal = formatAddress(client.city, client.state, client.postal_code, swap);
} }

View File

@ -132,7 +132,7 @@ NINJA.decodeJavascript = function(invoice, javascript)
'subtotalsHeight': (NINJA.subtotals(invoice).length * 16) + 16, 'subtotalsHeight': (NINJA.subtotals(invoice).length * 16) + 16,
'subtotalsWithoutBalance': NINJA.subtotals(invoice, true), 'subtotalsWithoutBalance': NINJA.subtotals(invoice, true),
'subtotalsBalance': NINJA.subtotalsBalance(invoice), 'subtotalsBalance': NINJA.subtotalsBalance(invoice),
'balanceDue': formatMoney(invoice.balance_amount, invoice.client.currency_id), 'balanceDue': formatMoneyInvoice(invoice.balance_amount, invoice),
'invoiceFooter': NINJA.invoiceFooter(invoice), 'invoiceFooter': NINJA.invoiceFooter(invoice),
'invoiceNumber': invoice.invoice_number || ' ', 'invoiceNumber': invoice.invoice_number || ' ',
'entityType': invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice, 'entityType': invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice,
@ -262,7 +262,6 @@ NINJA.taxWidth = function(invoice)
NINJA.invoiceLines = function(invoice) { NINJA.invoiceLines = function(invoice) {
var total = 0; var total = 0;
var shownItem = false; var shownItem = false;
var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1;
var hideQuantity = invoice.account.hide_quantity == '1'; var hideQuantity = invoice.account.hide_quantity == '1';
var showItemTaxes = invoice.account.show_item_taxes == '1'; var showItemTaxes = invoice.account.show_item_taxes == '1';
@ -285,7 +284,7 @@ NINJA.invoiceLines = function(invoice) {
var row = []; var row = [];
var item = invoice.invoice_items[i]; var item = invoice.invoice_items[i];
var cost = formatMoney(item.cost, currencyId, true); var cost = formatMoneyInvoice(item.cost, invoice, true);
var qty = NINJA.parseFloat(item.qty) ? roundToTwo(NINJA.parseFloat(item.qty)) + '' : ''; var qty = NINJA.parseFloat(item.qty) ? roundToTwo(NINJA.parseFloat(item.qty)) + '' : '';
var notes = item.notes; var notes = item.notes;
var productKey = item.product_key; var productKey = item.product_key;
@ -316,7 +315,7 @@ NINJA.invoiceLines = function(invoice) {
if (showItemTaxes && tax) { if (showItemTaxes && tax) {
lineTotal += lineTotal * tax / 100; lineTotal += lineTotal * tax / 100;
} }
lineTotal = formatMoney(lineTotal, currencyId); lineTotal = formatMoneyInvoice(lineTotal, invoice);
rowStyle = (i % 2 == 0) ? 'odd' : 'even'; rowStyle = (i % 2 == 0) ? 'odd' : 'even';
@ -345,49 +344,49 @@ NINJA.subtotals = function(invoice, hideBalance)
var account = invoice.account; var account = invoice.account;
var data = []; var data = [];
data.push([{text: invoiceLabels.subtotal}, {text: formatMoney(invoice.subtotal_amount, invoice.client.currency_id)}]); data.push([{text: invoiceLabels.subtotal}, {text: formatMoneyInvoice(invoice.subtotal_amount, invoice)}]);
if (invoice.discount_amount != 0) { if (invoice.discount_amount != 0) {
data.push([{text: invoiceLabels.discount}, {text: formatMoney(invoice.discount_amount, invoice.client.currency_id)}]); data.push([{text: invoiceLabels.discount}, {text: formatMoneyInvoice(invoice.discount_amount, invoice)}]);
} }
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 == '1') { if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 == '1') {
data.push([{text: account.custom_invoice_label1}, {text: formatMoney(invoice.custom_value1, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label1}, {text: formatMoneyInvoice(invoice.custom_value1, invoice)}]);
} }
if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 == '1') { if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 == '1') {
data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label2}, {text: formatMoneyInvoice(invoice.custom_value2, invoice)}]);
} }
for (var key in invoice.item_taxes) { for (var key in invoice.item_taxes) {
if (invoice.item_taxes.hasOwnProperty(key)) { if (invoice.item_taxes.hasOwnProperty(key)) {
var taxRate = invoice.item_taxes[key]; var taxRate = invoice.item_taxes[key];
var taxStr = taxRate.name + ' ' + (taxRate.rate*1).toString() + '%'; var taxStr = taxRate.name + ' ' + (taxRate.rate*1).toString() + '%';
data.push([{text: taxStr}, {text: formatMoney(taxRate.amount, invoice.client.currency_id)}]); data.push([{text: taxStr}, {text: formatMoneyInvoice(taxRate.amount, invoice)}]);
} }
} }
if (invoice.tax && invoice.tax.name || invoice.tax_name) { if (invoice.tax && invoice.tax.name || invoice.tax_name) {
var taxStr = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%'; var taxStr = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%';
data.push([{text: taxStr}, {text: formatMoney(invoice.tax_amount, invoice.client.currency_id)}]); data.push([{text: taxStr}, {text: formatMoneyInvoice(invoice.tax_amount, invoice)}]);
} }
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') { if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') {
data.push([{text: account.custom_invoice_label1}, {text: formatMoney(invoice.custom_value1, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label1}, {text: formatMoneyInvoice(invoice.custom_value1, invoice)}]);
} }
if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 != '1') { if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 != '1') {
data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label2}, {text: formatMoneyInvoice(invoice.custom_value2, invoice)}]);
} }
var paid = invoice.amount - invoice.balance; var paid = invoice.amount - invoice.balance;
if (invoice.account.hide_paid_to_date != '1' || paid) { if (invoice.account.hide_paid_to_date != '1' || paid) {
data.push([{text:invoiceLabels.paid_to_date}, {text:formatMoney(paid, invoice.client.currency_id)}]); data.push([{text:invoiceLabels.paid_to_date}, {text:formatMoneyInvoice(paid, invoice)}]);
} }
if (!hideBalance) { if (!hideBalance) {
var isPartial = NINJA.parseFloat(invoice.partial); var isPartial = NINJA.parseFloat(invoice.partial);
data.push([ data.push([
{text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']},
{text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} {text: formatMoneyInvoice(invoice.balance_amount, invoice), style:['balanceDue']}
]); ]);
} }
@ -398,7 +397,7 @@ NINJA.subtotalsBalance = function(invoice) {
var isPartial = NINJA.parseFloat(invoice.partial); var isPartial = NINJA.parseFloat(invoice.partial);
return [[ return [[
{text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']},
{text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} {text: formatMoneyInvoice(invoice.balance_amount, invoice), style:['balanceDue']}
]]; ]];
} }
@ -418,7 +417,7 @@ NINJA.accountAddress = function(invoice) {
var account = invoice.account; var account = invoice.account;
var cityStatePostal = ''; var cityStatePostal = '';
if (account.city || account.state || account.postal_code) { if (account.city || account.state || account.postal_code) {
var swap = account.country && account.country.swap_postal_code == '1'; var swap = account.country && account.country.swap_postal_code;
cityStatePostal = formatAddress(account.city, account.state, account.postal_code, swap); cityStatePostal = formatAddress(account.city, account.state, account.postal_code, swap);
} }
var data = [ var data = [
@ -475,18 +474,18 @@ NINJA.invoiceDetails = function(invoice) {
if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) { if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) {
data.push([ data.push([
{text: invoiceLabels.total}, {text: invoiceLabels.total},
{text: formatMoney(invoice.amount, invoice.client.currency_id)} {text: formatMoneyInvoice(invoice.amount, invoice)}
]); ]);
} else if (isPartial) { } else if (isPartial) {
data.push([ data.push([
{text: invoiceLabels.total}, {text: invoiceLabels.total},
{text: formatMoney(invoice.total_amount, invoice.client.currency_id)} {text: formatMoneyInvoice(invoice.total_amount, invoice)}
]); ]);
} }
data.push([ data.push([
{text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']},
{text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style: ['invoiceDetailBalanceDue']} {text: formatMoneyInvoice(invoice.balance_amount, invoice), style: ['invoiceDetailBalanceDue']}
]) ])
return NINJA.prepareDataPairs(data, 'invoiceDetails'); return NINJA.prepareDataPairs(data, 'invoiceDetails');
@ -505,7 +504,7 @@ NINJA.clientDetails = function(invoice) {
var cityStatePostal = ''; var cityStatePostal = '';
if (client.city || client.state || client.postal_code) { if (client.city || client.state || client.postal_code) {
var swap = client.country && client.country.swap_postal_code == '1'; var swap = client.country && client.country.swap_postal_code;
cityStatePostal = formatAddress(client.city, client.state, client.postal_code, swap); cityStatePostal = formatAddress(client.city, client.state, client.postal_code, swap);
} }

View File

@ -33,15 +33,7 @@ function generatePDF(invoice, javascript, force, cb) {
return; return;
} }
invoiceOld = invoice; invoiceOld = invoice;
pdfmakeMarker = "{"; doc = GetPdfMake(invoice, javascript, cb);
if(javascript.slice(0, pdfmakeMarker.length) === pdfmakeMarker) {
doc = GetPdfMake(invoice, javascript, cb);
} else {
doc = GetPdf(invoice, javascript);
doc.getDataUrl = function(cb) {
cb( this.output("datauristring"));
};
}
if (cb) { if (cb) {
doc.getDataUrl(cb); doc.getDataUrl(cb);
@ -55,135 +47,6 @@ function copyObject(orig) {
return JSON.parse(JSON.stringify(orig)); return JSON.parse(JSON.stringify(orig));
} }
function GetPdf(invoice, javascript){
var layout = {
accountTop: 40,
marginLeft: 50,
marginRight: 550,
headerTop: 150,
headerLeft: 360,
headerRight: 550,
rowHeight: 15,
tableRowHeight: 10,
footerLeft: 420,
tablePadding: 12,
tableTop: 250,
descriptionLeft: 150,
unitCostRight: 410,
qtyRight: 480,
taxRight: 480,
lineTotalRight: 550
};
/*
if (invoice.has_taxes)
{
layout.descriptionLeft -= 20;
layout.unitCostRight -= 40;
layout.qtyRight -= 40;
}
*/
/*
@param orientation One of "portrait" or "landscape" (or shortcuts "p" (Default), "l")
@param unit Measurement unit to be used when coordinates are specified. One of "pt" (points), "mm" (Default), "cm", "in"
@param format One of 'a3', 'a4' (Default),'a5' ,'letter' ,'legal'
@returns {jsPDF}
*/
var doc = new jsPDF('portrait', 'pt', 'a4');
//doc.getStringUnitWidth = function(param) { console.log('getStringUnitWidth: %s', param); return 0};
//Set PDF properities
doc.setProperties({
title: 'Invoice ' + invoice.invoice_number,
subject: '',
author: 'InvoiceNinja.com',
keywords: 'pdf, invoice',
creator: 'InvoiceNinja.com'
});
//set default style for report
doc.setFont('Helvetica','');
// For partial payments show "Amount Due" rather than "Balance Due"
if (!invoiceLabels.balance_due_orig) {
invoiceLabels.balance_due_orig = invoiceLabels.balance_due;
}
invoiceLabels.balance_due = NINJA.parseFloat(invoice.partial) ? invoiceLabels.amount_due : invoiceLabels.balance_due_orig;
eval(javascript);
// add footer
if (invoice.invoice_footer) {
doc.setFontType('normal');
doc.setFontSize('8');
SetPdfColor(invoice.invoice_design_id == 2 || invoice.invoice_design_id == 3 ? 'White' : 'Black',doc);
var top = doc.internal.pageSize.height - layout.marginLeft;
if (!invoice.is_pro) top -= 25;
var footer = doc.splitTextToSize(processVariables(invoice.invoice_footer), 500);
var numLines = footer.length - 1;
doc.text(layout.marginLeft, top - (numLines * 8), footer);
}
return doc;
}
function SetPdfColor(color, doc, role)
{
if (role === 'primary' && NINJA.primaryColor) {
return setDocHexColor(doc, NINJA.primaryColor);
} else if (role === 'secondary' && NINJA.secondaryColor) {
return setDocHexColor(doc, NINJA.secondaryColor);
}
if (color=='LightBlue') {
return doc.setTextColor(41,156, 194);
}
if (color=='Black') {
return doc.setTextColor(46,43,43);//select color black
}
if (color=='GrayLogo') {
return doc.setTextColor(207,241, 241);//select color Custom Report GRAY
}
if (color=='GrayBackground') {
return doc.setTextColor(251,251, 251);//select color Custom Report GRAY
}
if (color=='GrayText') {
return doc.setTextColor(161,160,160);//select color Custom Report GRAY Colour
}
if (color=='White') {
return doc.setTextColor(255,255,255);//select color Custom Report GRAY Colour
}
if (color=='SomeGreen') {
return doc.setTextColor(54,164,152);//select color Custom Report GRAY Colour
}
if (color=='LightGrayReport2-gray') {
return doc.setTextColor(240,240,240);//select color Custom Report GRAY Colour
}
if (color=='LightGrayReport2-white') {
return doc.setTextColor(251,251,251);//select color Custom Report GRAY Colour
}
if (color=='orange') {
return doc.setTextColor(234,121,45);//select color Custom Report GRAY Colour
}
if (color=='Green') {
return doc.setTextColor(55,109,69);
}
}
/* Handle converting variables in the invoices (ie, MONTH+1) */ /* Handle converting variables in the invoices (ie, MONTH+1) */
function processVariables(str) { function processVariables(str) {
if (!str) return ''; if (!str) return '';
@ -616,8 +479,8 @@ function populateInvoiceComboboxes(clientId, invoiceId) {
var client = clientMap[invoice.client.public_id]; var client = clientMap[invoice.client.public_id];
if (!client) continue; // client is deleted/archived if (!client) continue; // client is deleted/archived
$invoiceCombobox.append(new Option(invoice.invoice_number + ' - ' + invoice.invoice_status.name + ' - ' + $invoiceCombobox.append(new Option(invoice.invoice_number + ' - ' + invoice.invoice_status.name + ' - ' +
getClientDisplayName(client) + ' - ' + formatMoney(invoice.amount, client.currency_id) + ' | ' + getClientDisplayName(client) + ' - ' + formatMoneyInvoice(invoice.amount, invoice) + ' | ' +
formatMoney(invoice.balance, client.currency_id), invoice.public_id)); formatMoneyInvoice(invoice.balance, invoice), invoice.public_id));
} }
$('select#invoice').combobox('refresh'); $('select#invoice').combobox('refresh');
}); });
@ -628,6 +491,7 @@ function populateInvoiceComboboxes(clientId, invoiceId) {
if (invoiceId) { if (invoiceId) {
var invoice = invoiceMap[invoiceId]; var invoice = invoiceMap[invoiceId];
var client = clientMap[invoice.client.public_id]; var client = clientMap[invoice.client.public_id];
invoice.client = client;
setComboboxValue($('.client-select'), client.public_id, getClientDisplayName(client)); setComboboxValue($('.client-select'), client.public_id, getClientDisplayName(client));
if (!parseFloat($('#amount').val())) { if (!parseFloat($('#amount').val())) {
$('#amount').val(parseFloat(invoice.balance).toFixed(2)); $('#amount').val(parseFloat(invoice.balance).toFixed(2));
@ -640,9 +504,10 @@ function populateInvoiceComboboxes(clientId, invoiceId) {
if (invoiceId) { if (invoiceId) {
var invoice = invoiceMap[invoiceId]; var invoice = invoiceMap[invoiceId];
var client = clientMap[invoice.client.public_id]; var client = clientMap[invoice.client.public_id];
invoice.client = client;
setComboboxValue($('.invoice-select'), invoice.public_id, (invoice.invoice_number + ' - ' + setComboboxValue($('.invoice-select'), invoice.public_id, (invoice.invoice_number + ' - ' +
invoice.invoice_status.name + ' - ' + getClientDisplayName(client) + ' - ' + invoice.invoice_status.name + ' - ' + getClientDisplayName(client) + ' - ' +
formatMoney(invoice.amount, client.currency_id) + ' | ' + formatMoney(invoice.balance, client.currency_id))); formatMoneyInvoice(invoice.amount, invoice) + ' | ' + formatMoneyInvoice(invoice.balance, invoice)));
$invoiceSelect.trigger('change'); $invoiceSelect.trigger('change');
} else if (clientId) { } else if (clientId) {
var client = clientMap[clientId]; var client = clientMap[clientId];
@ -664,174 +529,6 @@ CONSTS.INVOICE_STATUS_PAID = 5;
$.fn.datepicker.defaults.autoclose = true; $.fn.datepicker.defaults.autoclose = true;
$.fn.datepicker.defaults.todayHighlight = true; $.fn.datepicker.defaults.todayHighlight = true;
function displayAccount(doc, invoice, x, y, layout) {
var account = invoice.account;
if (!account) {
return;
}
var data1 = [
account.name,
account.id_number,
account.vat_number,
account.work_email,
account.work_phone
];
var data2 = [
concatStrings(account.address1, account.address2),
concatStrings(account.city, account.state, account.postal_code),
account.country ? account.country.name : false,
invoice.account.custom_value1 ? invoice.account['custom_label1'] + ' ' + invoice.account.custom_value1 : false,
invoice.account.custom_value2 ? invoice.account['custom_label2'] + ' ' + invoice.account.custom_value2 : false,
];
if (layout.singleColumn) {
displayGrid(doc, invoice, data1.concat(data2), x, y, layout, {hasHeader:true});
} else {
displayGrid(doc, invoice, data1, x, y, layout, {hasHeader:true});
var nameWidth = account.name ? (doc.getStringUnitWidth(account.name) * doc.internal.getFontSize() * 1.1) : 0;
var emailWidth = account.work_email ? (doc.getStringUnitWidth(account.work_email) * doc.internal.getFontSize() * 1.1) : 0;
width = Math.max(emailWidth, nameWidth, 120);
x += width;
displayGrid(doc, invoice, data2, x, y, layout);
}
}
function displayClient(doc, invoice, x, y, layout) {
var client = invoice.client;
if (!client) {
return;
}
var data = [
getClientDisplayName(client),
client.id_number,
client.vat_number,
concatStrings(client.address1, client.address2),
concatStrings(client.city, client.state, client.postal_code),
client.country ? client.country.name : false,
invoice.contact && getClientDisplayName(client) != invoice.contact.email ? invoice.contact.email : false,
invoice.client.custom_value1 ? invoice.account['custom_client_label1'] + ' ' + invoice.client.custom_value1 : false,
invoice.client.custom_value2 ? invoice.account['custom_client_label2'] + ' ' + invoice.client.custom_value2 : false,
];
return displayGrid(doc, invoice, data, x, y, layout, {hasheader:true});
}
function displayInvoice(doc, invoice, x, y, layout, rightAlignX) {
if (!invoice) {
return;
}
var data = getInvoiceDetails(invoice);
var options = {
hasheader: true,
rightAlignX: rightAlignX,
};
return displayGrid(doc, invoice, data, x, y, layout, options);
}
function getInvoiceDetails(invoice) {
var fields = [
{'invoice_number': invoice.invoice_number},
{'po_number': invoice.po_number},
{'invoice_date': invoice.invoice_date},
{'due_date': invoice.due_date},
];
if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) {
fields.push({'total': formatMoney(invoice.amount, invoice.client.currency_id)});
}
if (NINJA.parseFloat(invoice.partial)) {
fields.push({'balance': formatMoney(invoice.total_amount, invoice.client.currency_id)});
}
fields.push({'balance_due': formatMoney(invoice.balance_amount, invoice.client.currency_id)})
return fields;
}
function getInvoiceDetailsHeight(invoice, layout) {
var data = getInvoiceDetails(invoice);
var count = 0;
for (var key in data) {
if (!data.hasOwnProperty(key)) {
continue;
}
var obj = data[key];
for (var subKey in obj) {
if (!obj.hasOwnProperty(subKey)) {
continue;
}
if (obj[subKey]) {
count++;
}
}
}
return count * layout.rowHeight;
}
function displaySubtotals(doc, layout, invoice, y, rightAlignTitleX)
{
if (!invoice) {
return;
}
var data = [
{'subtotal': formatMoney(invoice.subtotal_amount, invoice.client.currency_id)},
{'discount': invoice.discount_amount != 0 ? formatMoney(invoice.discount_amount, invoice.client.currency_id) : false}
];
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 == '1') {
data.push({'custom_invoice_label1': formatMoney(invoice.custom_value1, invoice.client.currency_id) })
}
if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 == '1') {
data.push({'custom_invoice_label2': formatMoney(invoice.custom_value2, invoice.client.currency_id) })
}
data.push({'tax': (invoice.tax && invoice.tax.name) || invoice.tax_name ? formatMoney(invoice.tax_amount, invoice.client.currency_id) : false});
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') {
data.push({'custom_invoice_label1': formatMoney(invoice.custom_value1, invoice.client.currency_id) })
}
if (NINJA.parseFloat(invoice.custom_value2) && invoice.custom_taxes2 != '1') {
data.push({'custom_invoice_label2': formatMoney(invoice.custom_value2, invoice.client.currency_id) })
}
var paid = invoice.amount - invoice.balance;
if (paid) {
data.push({'total': formatMoney(invoice.amount, invoice.client.currency_id)});
}
if (invoice.account.hide_paid_to_date != '1' || paid) {
data.push({'paid_to_date': formatMoney(paid, invoice.client.currency_id)});
}
if (NINJA.parseFloat(invoice.partial) && invoice.total_amount != invoice.subtotal_amount) {
data.push({'balance': formatMoney(invoice.total_amount, invoice.client.currency_id)});
}
var options = {
hasheader: true,
rightAlignX: 550,
rightAlignTitleX: rightAlignTitleX
};
return displayGrid(doc, invoice, data, 300, y, layout, options) + 10;
}
function formatAddress(city, state, zip, swap) { function formatAddress(city, state, zip, swap) {
var str = ''; var str = '';
if (swap) { if (swap) {
@ -867,106 +564,6 @@ function concatStrings() {
return data.length ? concatStr : ""; return data.length ? concatStr : "";
} }
function displayGrid(doc, invoice, data, x, y, layout, options) {
var numLines = 0;
var origY = y;
for (var i=0; i<data.length; i++) {
doc.setFontType('normal');
if (invoice.invoice_design_id == 1 && i > 0 && origY === layout.accountTop) {
SetPdfColor('GrayText',doc);
}
var row = data[i];
if (!row) {
continue;
}
if (options && (options.hasheader && i === 0 && !options.rightAlignTitleX)) {
doc.setFontType('bold');
}
if (typeof row === 'object') {
for (var key in row) {
if (row.hasOwnProperty(key)) {
var value = row[key] ? row[key] + '' : false;
}
}
if (!value) {
continue;
}
var marginLeft;
if (options.rightAlignX) {
marginLeft = options.rightAlignX - (doc.getStringUnitWidth(value) * doc.internal.getFontSize());
} else {
marginLeft = x + 80;
}
doc.text(marginLeft, y, value);
doc.setFontType('normal');
if (invoice.is_quote) {
if (key == 'invoice_number') {
key = 'quote_number';
} else if (key == 'invoice_date') {
key = 'quote_date';
} else if (key == 'balance_due') {
key = 'total';
}
}
if (key.substring(0, 6) === 'custom') {
key = invoice.account[key];
} else if (key === 'tax' && invoice.tax_name) {
key = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%';
} else if (key === 'discount' && NINJA.parseFloat(invoice.discount) && !parseInt(invoice.is_amount_discount)) {
key = invoiceLabels[key] + ' ' + parseFloat(invoice.discount) + '%';
} else {
key = invoiceLabels[key];
}
if (options.rightAlignTitleX) {
marginLeft = options.rightAlignTitleX - (doc.getStringUnitWidth(key) * doc.internal.getFontSize());
} else {
marginLeft = x;
}
doc.text(marginLeft, y, key);
} else {
doc.text(x, y, row);
}
numLines++;
y += layout.rowHeight;
}
return numLines * layout.rowHeight;
}
function displayNotesAndTerms(doc, layout, invoice, y)
{
doc.setFontType("normal");
var origY = y;
if (invoice.public_notes) {
var notes = doc.splitTextToSize(processVariables(invoice.public_notes), 260);
doc.text(layout.marginLeft, y, notes);
y += 16 + (notes.length * doc.internal.getFontSize());
}
if (invoice.terms) {
var terms = doc.splitTextToSize(processVariables(invoice.terms), 260);
doc.setFontType("bold");
doc.text(layout.marginLeft, y, invoiceLabels.terms);
y += 16;
doc.setFontType("normal");
doc.text(layout.marginLeft, y, terms);
y += 16 + (terms.length * doc.internal.getFontSize());
}
return y - origY;
}
function calculateAmounts(invoice) { function calculateAmounts(invoice) {
var total = 0; var total = 0;
var hasTaxes = false; var hasTaxes = false;
@ -1090,311 +687,6 @@ function getInvoiceTaxRate(invoice) {
return tax; return tax;
} }
function displayInvoiceHeader(doc, invoice, layout) {
if (invoice.invoice_design_id == 6 || invoice.invoice_design_id == 8 || invoice.invoice_design_id == 10) {
invoiceLabels.item = invoiceLabels.item.toUpperCase();
invoiceLabels.description = invoiceLabels.description.toUpperCase();
invoiceLabels.unit_cost = invoiceLabels.unit_cost.toUpperCase();
invoiceLabels.quantity = invoiceLabels.quantity.toUpperCase();
invoiceLabels.line_total = invoiceLabels.total.toUpperCase();
invoiceLabels.tax = invoiceLabels.tax.toUpperCase();
}
var costX = layout.unitCostRight - (doc.getStringUnitWidth(invoiceLabels.unit_cost) * doc.internal.getFontSize());
var qtyX = layout.qtyRight - (doc.getStringUnitWidth(invoiceLabels.quantity) * doc.internal.getFontSize());
var taxX = layout.taxRight - (doc.getStringUnitWidth(invoiceLabels.tax) * doc.internal.getFontSize());
var totalX = layout.lineTotalRight - (doc.getStringUnitWidth(invoiceLabels.line_total) * doc.internal.getFontSize());
doc.text(layout.marginLeft, layout.tableTop, invoiceLabels.item);
doc.text(layout.descriptionLeft, layout.tableTop, invoiceLabels.description);
doc.text(costX, layout.tableTop, invoiceLabels.unit_cost);
if (invoice.account.hide_quantity != '1') {
doc.text(qtyX, layout.tableTop, invoiceLabels.quantity);
}
doc.text(totalX, layout.tableTop, invoiceLabels.line_total);
/*
if (invoice.has_taxes)
{
doc.text(taxX, layout.tableTop, invoiceLabels.tax);
}
*/
}
function displayInvoiceItems(doc, invoice, layout) {
doc.setFontType("normal");
var line = 1;
var total = 0;
var shownItem = false;
var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1;
var tableTop = layout.tableTop;
var hideQuantity = invoice.account.hide_quantity == '1';
doc.setFontSize(8);
for (var i=0; i<invoice.invoice_items.length; i++) {
var item = invoice.invoice_items[i];
var cost = formatMoney(item.cost, currencyId, true);
var qty = NINJA.parseFloat(item.qty) ? roundToTwo(NINJA.parseFloat(item.qty)) + '' : '';
var notes = item.notes;
var productKey = item.product_key;
var tax = 0;
if (item.tax && parseFloat(item.tax.rate)) {
tax = parseFloat(item.tax.rate);
} else if (item.tax_rate && parseFloat(item.tax_rate)) {
tax = parseFloat(item.tax_rate);
}
// show at most one blank line
if (shownItem && (!cost || cost == '0.00') && !notes && !productKey) {
continue;
}
shownItem = true;
var numLines = Math.max(doc.splitTextToSize(item.notes, 200).length, doc.splitTextToSize(item.product_key, 60).length) + 2;
//console.log('num lines %s', numLines);
var y = tableTop + (line * layout.tableRowHeight) + (2 * layout.tablePadding);
var top = y - layout.tablePadding;
var newTop = top + (numLines * layout.tableRowHeight);
if (newTop > 770) {
line = 0;
tableTop = layout.accountTop + layout.tablePadding;
y = tableTop + (2 * layout.tablePadding);
top = y - layout.tablePadding;
newTop = top + (numLines * layout.tableRowHeight);
doc.addPage();
}
var left = layout.marginLeft - layout.tablePadding;
var width = layout.marginRight + layout.tablePadding;
// process date variables
if (invoice.is_recurring) {
notes = processVariables(notes);
productKey = processVariables(productKey);
}
var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty));
if (tax) {
lineTotal += lineTotal * tax / 100;
}
if (lineTotal) {
total += lineTotal;
}
lineTotal = formatMoney(lineTotal, currencyId);
var costX = layout.unitCostRight - (doc.getStringUnitWidth(cost) * doc.internal.getFontSize());
var qtyX = layout.qtyRight - (doc.getStringUnitWidth(qty) * doc.internal.getFontSize());
var taxX = layout.taxRight - (doc.getStringUnitWidth(tax+'%') * doc.internal.getFontSize());
var totalX = layout.lineTotalRight - (doc.getStringUnitWidth(lineTotal) * doc.internal.getFontSize());
//if (i==0) y -= 4;
line += numLines;
if (invoice.invoice_design_id == 1) {
if (i%2 == 0) {
doc.setDrawColor(255,255,255);
doc.setFillColor(246,246,246);
doc.rect(left, top, width-left, newTop-top, 'FD');
doc.setLineWidth(0.3);
doc.setDrawColor(200,200,200);
doc.line(left, top, width, top);
doc.line(left, newTop, width, newTop);
}
} else if (invoice.invoice_design_id == 2) {
if (i%2 == 0) {
left = 0;
width = 1000;
doc.setDrawColor(255,255,255);
doc.setFillColor(235,235,235);
doc.rect(left, top, width-left, newTop-top, 'FD');
}
} else if (invoice.invoice_design_id == 5) {
if (i%2 == 0) {
doc.setDrawColor(255,255,255);
doc.setFillColor(247,247,247);
doc.rect(left, top, width-left+17, newTop-top, 'FD');
} else {
doc.setDrawColor(255,255,255);
doc.setFillColor(232,232,232);
doc.rect(left, top, width-left+17, newTop-top, 'FD');
}
} else if (invoice.invoice_design_id == 6) {
if (i%2 == 0) {
doc.setDrawColor(232,232,232);
doc.setFillColor(232,232,232);
doc.rect(left, top, width-left, newTop-top, 'FD');
} else {
doc.setDrawColor(255,255,255);
doc.setFillColor(255,255,255);
doc.rect(left, top, width-left, newTop-top, 'FD');
}
} else if (invoice.invoice_design_id == 7) {
doc.setLineWidth(1);
doc.setDrawColor(45,35,32);
for(var k = 1; k<=width-20; k++) {
doc.line(left+4+k,newTop,left+4+1+k,newTop);
k = k+3;
}
} else if (invoice.invoice_design_id == 8) {
} else if (invoice.invoice_design_id == 9) {
doc.setLineWidth(1);
doc.setDrawColor(0,157,145);
for(var j = 1; j<=width-40; j++) {
doc.line(left+j,newTop,left+2+j,newTop);
j = j+5;
}
} else if (invoice.invoice_design_id == 10) {
doc.setLineWidth(0.3);
doc.setDrawColor(63,60,60);
doc.line(left, newTop, width, newTop);
} else {
doc.setLineWidth(0.3);
doc.setDrawColor(150,150,150);
doc.line(left, newTop, width, newTop);
}
y += 4;
if (invoice.invoice_design_id == 1) {
SetPdfColor('LightBlue', doc, 'primary');
} else if (invoice.invoice_design_id == 2) {
SetPdfColor('SomeGreen', doc, 'primary');
} else if (invoice.invoice_design_id == 3) {
doc.setFontType('bold');
} else if (invoice.invoice_design_id == 4) {
SetPdfColor('Black', doc);
} else if (invoice.invoice_design_id == 5) {
SetPdfColor('Black', doc);
} else if (invoice.invoice_design_id == 6) {
SetPdfColor('Black', doc);
}
var splitTitle = doc.splitTextToSize(productKey, 60);
if(invoice.invoice_design_id == 6) {
doc.setFontType('bold');
}
if(invoice.invoice_design_id == 9) {
doc.setTextColor(187,51,40);
}
if(invoice.invoice_design_id == 10) {
doc.setTextColor(205,81,56);
}
doc.text(layout.marginLeft, y+2, splitTitle);
if (invoice.invoice_design_id == 5) {
doc.setDrawColor(255, 255, 255);
doc.setLineWidth(1);
doc.line(layout.descriptionLeft-8, y-16,layout.descriptionLeft-8, y+55);
doc.line(costX-30, y-16,costX-30, y+55);
doc.line(qtyX-45, y-16,qtyX-45, y+55);
/*
if (invoice.has_taxes) {
doc.line(taxX-15, y-16,taxX-15, y+55);
}
*/
doc.line(totalX-27, y-16,totalX-27, y+55);
}
/*
if (invoice.invoice_design_id == 8) {
doc.setDrawColor(30, 30, 30);
doc.setLineWidth(0.5);
doc.line(layout.marginLeft-10, y-60,layout.marginLeft-10, y+20);
doc.line(layout.descriptionLeft-8, y-60,layout.descriptionLeft-8, y+20);
doc.line(costX-30, y-60,costX-30, y+20);
console.log('CostX: %s', costX);
doc.line(qtyX-45, y-60,qtyX-45, y+20);
if (invoice.has_taxes) {
doc.line(taxX-10, y-60,taxX-10, y+20);
}
doc.line(totalX-27, y-60,totalX-27, y+120);
doc.line(totalX+35, y-60,totalX+35, y+120);
}
*/
SetPdfColor('Black', doc);
doc.setFontType('normal');
var splitDescription = doc.splitTextToSize(notes, 190);
doc.text(layout.descriptionLeft, y+2, splitDescription);
doc.text(costX, y+2, cost);
if (!hideQuantity) {
doc.text(qtyX, y+2, qty);
}
if(invoice.invoice_design_id == 9) {
doc.setTextColor(187,51,40);
doc.setFontType('bold');
}
if(invoice.invoice_design_id == 10) {
doc.setTextColor(205,81,56);
}
doc.text(totalX, y+2, lineTotal);
doc.setFontType('normal');
SetPdfColor('Black', doc);
if (tax) {
doc.text(taxX, y+2, tax+'%');
}
}
y = tableTop + (line * layout.tableRowHeight) + (3 * layout.tablePadding);
if (invoice.invoice_design_id == 8) {
doc.setDrawColor(30, 30, 30);
doc.setLineWidth(0.5);
var topX = tableTop - 14;
doc.line(layout.marginLeft-10, topX,layout.marginLeft-10, y);
doc.line(layout.descriptionLeft-8, topX,layout.descriptionLeft-8, y);
doc.line(layout.unitCostRight-55, topX,layout.unitCostRight-55, y);
doc.line(layout.qtyRight-50, topX,layout.qtyRight-50, y);
/*
if (invoice.has_taxes) {
doc.line(layout.taxRight-28, topX,layout.taxRight-28, y);
}
*/
doc.line(totalX-25, topX,totalX-25, y+90);
doc.line(totalX+45, topX,totalX+45, y+90);
}
var cutoff = 700;
if (invoice.terms) {
cutoff -= 50;
}
if (invoice.public_notes) {
cutoff -= 50;
}
if (y > cutoff) {
doc.addPage();
return layout.marginLeft;
}
return y;
}
// http://stackoverflow.com/questions/11941876/correctly-suppressing-warnings-in-datatables // http://stackoverflow.com/questions/11941876/correctly-suppressing-warnings-in-datatables
window.alert = (function() { window.alert = (function() {
var nativeAlert = window.alert; var nativeAlert = window.alert;

View File

@ -328,7 +328,7 @@
} }
}); });
var tab = localStorage.getItem('client_tab'); var tab = localStorage.getItem('client_tab');
if (tab) { if (tab && tab != 'activity') {
$('.nav-tabs a[href="#' + tab.replace('#', '') + '"]').tab('show'); $('.nav-tabs a[href="#' + tab.replace('#', '') + '"]').tab('show');
} else { } else {
window['load_activity'](); window['load_activity']();

View File

@ -19,7 +19,7 @@
}, },
"totalPaymentDue": { "totalPaymentDue": {
"@type": "PriceSpecification", "@type": "PriceSpecification",
"price": "{{ $invoice->present()->balance_due }}" "price": "{{ $account->formatMoney($invoice->getRequestedAmount(), $client) }}"
}, },
"action": { "action": {
"@type": "ViewAction", "@type": "ViewAction",

View File

@ -25,8 +25,8 @@
@if ($multiUser) @if ($multiUser)
<td>{{ $client->user->getDisplayName() }}</td> <td>{{ $client->user->getDisplayName() }}</td>
@endif @endif
<td>{{ $client->present()->balance }}</td> <td>{{ $account->formatMoney($client->balance, $client) }}</td>
<td>{{ $client->present()->paid_to_date }}</td> <td>{{ $account->formatMoney($client->paid_to_date, $client) }}</td>
<td>{{ $client->address1 }}</td> <td>{{ $client->address1 }}</td>
<td>{{ $client->address2 }}</td> <td>{{ $client->address2 }}</td>
<td>{{ $client->city }}</td> <td>{{ $client->city }}</td>

View File

@ -15,8 +15,8 @@
@if ($multiUser) @if ($multiUser)
<td>{{ $credit->user->getDisplayName() }}</td> <td>{{ $credit->user->getDisplayName() }}</td>
@endif @endif
<td>{{ $credit->present()->amount }}</td> <td>{{ $account->formatMoney($credit->amount, $credit->client) }}</td>
<td>{{ $credit->present()->balance }}</td> <td>{{ $account->formatMoney($credit->balance, $credit->client) }}</td>
<td>{{ $credit->present()->credit_date }}</td> <td>{{ $credit->present()->credit_date }}</td>
</tr> </tr>
@endif @endif

View File

@ -32,8 +32,8 @@
<td>{{ $invoice->present()->user }}</td> <td>{{ $invoice->present()->user }}</td>
@endif @endif
<td>{{ $invoice->invoice_number }}</td> <td>{{ $invoice->invoice_number }}</td>
<td>{{ $invoice->present()->balance }}</td> <td>{{ $account->formatMoney($invoice->balance, $invoice->client) }}</td>
<td>{{ $invoice->present()->amount }}</td> <td>{{ $account->formatMoney($invoice->amount, $invoice->client) }}</td>
<td>{{ $invoice->po_number }}</td> <td>{{ $invoice->po_number }}</td>
<td>{{ $invoice->present()->status }}</td> <td>{{ $invoice->present()->status }}</td>
<td>{{ $invoice->present()->invoice_date }}</td> <td>{{ $invoice->present()->invoice_date }}</td>

View File

@ -18,7 +18,7 @@
<td>{{ $payment->user->getDisplayName() }}</td> <td>{{ $payment->user->getDisplayName() }}</td>
@endif @endif
<td>{{ $payment->invoice->invoice_number }}</td> <td>{{ $payment->invoice->invoice_number }}</td>
<td>{{ $payment->present()->amount }}</td> <td>{{ $account->formatMoney($payment->amount, $payment->client) }}</td>
<td>{{ $payment->present()->payment_date }}</td> <td>{{ $payment->present()->payment_date }}</td>
<td>{{ $payment->present()->method }}</td> <td>{{ $payment->present()->method }}</td>
<td>{{ $payment->transaction_reference }}</td> <td>{{ $payment->transaction_reference }}</td>

View File

@ -41,11 +41,8 @@
} }
@endif @endif
</style> </style>
@include('script')
<script type="text/javascript"> <script type="text/javascript">
function setTheme(id) function setTheme(id)

View File

@ -3,6 +3,7 @@
@section('head') @section('head')
@parent @parent
@include('money_script')
<script src="{{ asset('js/pdf.built.js') }}" type="text/javascript"></script> <script src="{{ asset('js/pdf.built.js') }}" type="text/javascript"></script>
<style type="text/css"> <style type="text/css">
@ -488,7 +489,7 @@
{!! Former::select('client[country_id]') {!! Former::select('client[country_id]')
->label(trans('texts.country_id')) ->label(trans('texts.country_id'))
->addOption('','')->addGroupClass('country_select') ->addOption('','')->addGroupClass('country_select')
->fromQuery($countries, 'name', 'id')->data_bind("dropdown: country_id") !!} ->fromQuery(Cache::get('countries'), 'name', 'id')->data_bind("dropdown: country_id") !!}
</span> </span>
</div> </div>
@ -607,7 +608,6 @@
var products = {!! $products !!}; var products = {!! $products !!};
var clients = {!! $clients !!}; var clients = {!! $clients !!};
var countries = {!! $countries !!};
var account = {!! Auth::user()->account !!}; var account = {!! Auth::user()->account !!};
var clientMap = {}; var clientMap = {};

View File

@ -340,6 +340,10 @@ function InvoiceModel(data) {
refreshPDF(true); refreshPDF(true);
} }
self.formatMoney = function(amount) {
var client = $.parseJSON(ko.toJSON(self.client()));
return formatMoneyAccount(amount, self.account, client);
}
self.totals = ko.observable(); self.totals = ko.observable();
@ -354,7 +358,7 @@ function InvoiceModel(data) {
self.totals.subtotal = ko.computed(function() { self.totals.subtotal = ko.computed(function() {
var total = self.totals.rawSubtotal(); var total = self.totals.rawSubtotal();
return formatMoney(total, self.client().currency_id()); return self.formatMoney(total);
}); });
self.totals.rawDiscounted = ko.computed(function() { self.totals.rawDiscounted = ko.computed(function() {
@ -366,7 +370,7 @@ function InvoiceModel(data) {
}); });
self.totals.discounted = ko.computed(function() { self.totals.discounted = ko.computed(function() {
return formatMoney(self.totals.rawDiscounted(), self.client().currency_id()); return self.formatMoney(self.totals.rawDiscounted());
}); });
self.totals.taxAmount = ko.computed(function() { self.totals.taxAmount = ko.computed(function() {
@ -388,10 +392,10 @@ function InvoiceModel(data) {
var taxRate = parseFloat(self.tax_rate()); var taxRate = parseFloat(self.tax_rate());
if (taxRate > 0) { if (taxRate > 0) {
var tax = roundToTwo(total * (taxRate/100)); var tax = roundToTwo(total * (taxRate/100));
return formatMoney(tax, self.client().currency_id()); return self.formatMoney(tax);
} else { } else {
return formatMoney(0, self.client().currency_id()); return self.formatMoney(0);
} }
}); });
@ -448,7 +452,7 @@ function InvoiceModel(data) {
var parts = []; var parts = [];
for (var key in taxes) { for (var key in taxes) {
if (taxes.hasOwnProperty(key)) { if (taxes.hasOwnProperty(key)) {
parts.push(formatMoney(taxes[key].amount, self.client().currency_id())); parts.push(self.formatMoney(taxes[key].amount));
} }
} }
return parts.join('<br/>'); return parts.join('<br/>');
@ -460,7 +464,7 @@ function InvoiceModel(data) {
self.totals.paidToDate = ko.computed(function() { self.totals.paidToDate = ko.computed(function() {
var total = self.totals.rawPaidToDate(); var total = self.totals.rawPaidToDate();
return formatMoney(total, self.client().currency_id()); return self.formatMoney(total);
}); });
self.totals.rawTotal = ko.computed(function() { self.totals.rawTotal = ko.computed(function() {
@ -508,7 +512,7 @@ function InvoiceModel(data) {
}); });
self.totals.total = ko.computed(function() { self.totals.total = ko.computed(function() {
return formatMoney(self.partial() ? self.partial() : self.totals.rawTotal(), self.client().currency_id()); return self.formatMoney(self.partial() ? self.partial() : self.totals.rawTotal());
}); });
self.onDragged = function(item) { self.onDragged = function(item) {
@ -781,11 +785,14 @@ function ItemModel(data) {
this.totals.total = ko.computed(function() { this.totals.total = ko.computed(function() {
var total = self.totals.rawTotal(); var total = self.totals.rawTotal();
return total ? model.invoice().formatMoney(total) : '';
/*
if (window.hasOwnProperty('model') && model.invoice && model.invoice() && model.invoice().client()) { if (window.hasOwnProperty('model') && model.invoice && model.invoice() && model.invoice().client()) {
return total ? formatMoney(total, model.invoice().client().currency_id()) : ''; return total ? model.invoice().formatMoney(total) : '';
} else { } else {
return total ? formatMoney(total, 1) : ''; return total ? model.invoice().formatMoney(total, 1) : '';
} }
*/
}); });
this.hideActions = function() { this.hideActions = function() {

View File

@ -3,7 +3,7 @@
@section('head') @section('head')
@parent @parent
@include('script') @include('money_script')
<script src="{{ asset('js/pdf.built.js') }}" type="text/javascript"></script> <script src="{{ asset('js/pdf.built.js') }}" type="text/javascript"></script>

View File

@ -0,0 +1,94 @@
<script type="text/javascript">
var currencies = {!! \Cache::get('currencies') !!};
var currencyMap = {};
for (var i=0; i<currencies.length; i++) {
var currency = currencies[i];
currencyMap[currency.id] = currency;
}
var countries = {!! \Cache::get('countries') !!};
var countryMap = {};
for (var i=0; i<countries.length; i++) {
var country = countries[i];
countryMap[country.id] = country;
}
var NINJA = NINJA || {};
@if (Auth::check())
NINJA.primaryColor = "{{ Auth::user()->account->primary_color }}";
NINJA.secondaryColor = "{{ Auth::user()->account->secondary_color }}";
NINJA.fontSize = {{ Auth::user()->account->font_size ?: DEFAULT_FONT_SIZE }};
@else
NINJA.fontSize = {{ DEFAULT_FONT_SIZE }};
@endif
NINJA.parseFloat = function(str) {
if (!str) return '';
str = (str+'').replace(/[^0-9\.\-]/g, '');
return window.parseFloat(str);
}
function formatMoneyInvoice(value, invoice, hideSymbol) {
var account = invoice.account;
var client = invoice.client;
return formatMoneyAccount(value, account, client, hideSymbol);
}
function formatMoneyAccount(value, account, client, hideSymbol) {
var currencyId = false;
var countryId = false;
if (client && client.currency_id) {
currencyId = client.currency_id;
} else if (account && account.currency_id) {
currencyId = account.currency_id;
}
if (client && client.country_id) {
countryId = client.country_id;
} else if (account && account.country_id) {
countryId = account.country_id;
}
return formatMoney(value, currencyId, countryId, hideSymbol)
}
function formatMoney(value, currencyId, countryId, hideSymbol) {
value = NINJA.parseFloat(value);
if (!currencyId) {
currencyId = {{ Session::get(SESSION_CURRENCY, DEFAULT_CURRENCY) }};
}
var currency = currencyMap[currencyId];
var thousand = currency.thousand_separator;
var decimal = currency.decimal_separator;
var swapSymbol = false;
if (countryId && currencyId == {{ CURRENCY_EURO }}) {
var country = countryMap[countryId];
swapSymbol = country.swap_currency_symbol;
if (country.thousand_separator) {
thousand = country.thousand_separator;
}
if (country.decimal_separator) {
decimal = country.decimal_separator;
}
}
value = accounting.formatMoney(value, '', 2, thousand, decimal);
var symbol = currency.symbol;
if (hideSymbol) {
return value;
} else if (swapSymbol) {
return value + ' ' + symbol.trim();
} else {
return symbol + value;
}
}
</script>

View File

@ -101,7 +101,7 @@
<header> <header>
@if ($client) @if ($client)
<h2>{{ $client->getDisplayName() }}</h2> <h2>{{ $client->getDisplayName() }}</h2>
<h3>{{ trans('texts.invoice') . ' ' . $invoiceNumber }}<span>|&nbsp; {{ trans('texts.amount_due') }}: <em>{{ Utils::formatMoney($amount, $currencyId, false) }} {{ $currencyCode }}</em></span></h3> <h3>{{ trans('texts.invoice') . ' ' . $invoiceNumber }}<span>|&nbsp; {{ trans('texts.amount_due') }}: <em>{{ $account->formatMoney($amount, $client, true) }} {{ $currencyCode }}</em></span></h3>
@elseif ($paymentTitle) @elseif ($paymentTitle)
<h2>{{ $paymentTitle }}<br/><small>{{ $paymentSubtitle }}</small></h2> <h2>{{ $paymentTitle }}<br/><small>{{ $paymentSubtitle }}</small></h2>
@endif @endif
@ -280,7 +280,7 @@
<div class="row"> <div class="row">
<div class="col-md-4 col-md-offset-4"> <div class="col-md-4 col-md-offset-4">
{!! Button::success(strtoupper(trans('texts.pay_now') . ' - ' . Utils::formatMoney($amount, $currencyId, false) . ' ' . $currencyCode ))->submit()->block()->large() !!} {!! Button::success(strtoupper(trans('texts.pay_now') . ' - ' . $account->formatMoney($amount, $client, true) . ' ' . $currencyCode ))->submit()->block()->large() !!}
</div> </div>
</div> </div>

View File

@ -3,6 +3,7 @@
@section('head') @section('head')
@parent @parent
@include('money_script')
<script src="{!! asset('js/d3.min.js') !!}" type="text/javascript"></script> <script src="{!! asset('js/d3.min.js') !!}" type="text/javascript"></script>
<style type="text/css"> <style type="text/css">

View File

@ -1,32 +0,0 @@
<script type="text/javascript">
var currencies = {!! \Cache::get('currencies') !!};
var currencyMap = {};
for (var i=0; i<currencies.length; i++) {
var currency = currencies[i];
currencyMap[currency.id] = currency;
}
var NINJA = NINJA || {};
@if (Auth::check())
NINJA.primaryColor = "{{ Auth::user()->account->primary_color }}";
NINJA.secondaryColor = "{{ Auth::user()->account->secondary_color }}";
NINJA.fontSize = {{ Auth::user()->account->font_size ?: DEFAULT_FONT_SIZE }};
@else
NINJA.fontSize = {{ DEFAULT_FONT_SIZE }};
@endif
NINJA.parseFloat = function(str) {
if (!str) return '';
str = (str+'').replace(/[^0-9\.\-]/g, '');
return window.parseFloat(str);
}
function formatMoney(value, currency_id, hide_symbol) {
value = NINJA.parseFloat(value);
if (!currency_id) currency_id = {{ Session::get(SESSION_CURRENCY, DEFAULT_CURRENCY) }};
var currency = currencyMap[currency_id];
return accounting.formatMoney(value, hide_symbol ? '' : currency.symbol, currency.precision, currency.thousand_separator, currency.decimal_separator);
}
</script>