Merge branch 'release-3.6.0'

This commit is contained in:
Hillel Coren 2017-08-07 18:08:52 +03:00
commit 10f54fae44
141 changed files with 6532 additions and 2949 deletions

View File

@ -64,7 +64,7 @@ class CheckData extends Command
public function fire() public function fire()
{ {
$this->logMessage(date('Y-m-d') . ' Running CheckData...'); $this->logMessage(date('Y-m-d h:i:s') . ' Running CheckData...');
if ($database = $this->option('database')) { if ($database = $this->option('database')) {
config(['database.default' => $database]); config(['database.default' => $database]);
@ -84,9 +84,9 @@ class CheckData extends Command
if (! $this->option('client_id')) { if (! $this->option('client_id')) {
$this->checkOAuth(); $this->checkOAuth();
$this->checkInvitations(); $this->checkInvitations();
$this->checkFailedJobs();
$this->checkAccountData(); $this->checkAccountData();
$this->checkLookupData(); $this->checkLookupData();
$this->checkFailedJobs();
} }
$this->logMessage('Done: ' . strtoupper($this->isValid ? RESULT_SUCCESS : RESULT_FAILURE)); $this->logMessage('Done: ' . strtoupper($this->isValid ? RESULT_SUCCESS : RESULT_FAILURE));
@ -143,6 +143,11 @@ class CheckData extends Command
return; return;
} }
if ($this->option('fix') == 'true') {
return;
}
$isValid = true;
$date = new Carbon(); $date = new Carbon();
$date = $date->subDays(1)->format('Y-m-d'); $date = $date->subDays(1)->format('Y-m-d');
@ -159,12 +164,12 @@ class CheckData extends Command
//$this->logMessage('Result: ' . $result); //$this->logMessage('Result: ' . $result);
if ($result && $result != $invoice->balance) { if ($result && $result != $invoice->balance) {
$this->logMessage("Amounts do not match {$link} - PHP: {$invoice->balance}, JS: {$result}"); $this->logMessage("PHP/JS amounts do not match {$link} - PHP: {$invoice->balance}, JS: {$result}");
$this->isValid = false; $this->isValid = $isValid = false;
} }
} }
if ($this->isValid) { if ($isValid) {
$this->logMessage('0 invoices with mismatched PHP/JS balances'); $this->logMessage('0 invoices with mismatched PHP/JS balances');
} }
} }
@ -371,6 +376,13 @@ class CheckData extends Command
private function checkFailedJobs() private function checkFailedJobs()
{ {
if (Utils::isTravis()) {
return;
}
$current = config('database.default');
config(['database.default' => env('QUEUE_DATABASE')]);
$count = DB::table('failed_jobs')->count(); $count = DB::table('failed_jobs')->count();
if ($count > 0) { if ($count > 0) {
@ -378,6 +390,8 @@ class CheckData extends Command
} }
$this->logMessage($count . ' failed jobs'); $this->logMessage($count . ' failed jobs');
config(['database.default' => $current]);
} }
private function checkBlankInvoiceHistory() private function checkBlankInvoiceHistory()

View File

@ -63,8 +63,30 @@ class SendReminders extends Command
config(['database.default' => $database]); config(['database.default' => $database]);
} }
$accounts = $this->accountRepo->findWithFees();
$this->info(count($accounts) . ' accounts found with fees');
foreach ($accounts as $account) {
if (! $account->hasFeature(FEATURE_EMAIL_TEMPLATES_REMINDERS)) {
continue;
}
$invoices = $this->invoiceRepo->findNeedingReminding($account, false);
$this->info($account->name . ': ' . count($invoices) . ' invoices found');
foreach ($invoices as $invoice) {
if ($reminder = $account->getInvoiceReminder($invoice, false)) {
$this->info('Charge fee: ' . $invoice->id);
$number = preg_replace('/[^0-9]/', '', $reminder);
$amount = $account->account_email_settings->{"late_fee{$number}_amount"};
$percent = $account->account_email_settings->{"late_fee{$number}_percent"};
$this->invoiceRepo->setLateFee($invoice, $amount, $percent);
}
}
}
$accounts = $this->accountRepo->findWithReminders(); $accounts = $this->accountRepo->findWithReminders();
$this->info(count($accounts) . ' accounts found'); $this->info(count($accounts) . ' accounts found with reminders');
/** @var \App\Models\Account $account */ /** @var \App\Models\Account $account */
foreach ($accounts as $account) { foreach ($accounts as $account) {
@ -78,7 +100,7 @@ class SendReminders extends Command
/** @var Invoice $invoice */ /** @var Invoice $invoice */
foreach ($invoices as $invoice) { foreach ($invoices as $invoice) {
if ($reminder = $account->getInvoiceReminder($invoice)) { if ($reminder = $account->getInvoiceReminder($invoice)) {
$this->info('Send to ' . $invoice->id); $this->info('Send email: ' . $invoice->id);
$this->mailer->sendInvoice($invoice, $reminder); $this->mailer->sendInvoice($invoice, $reminder);
} }
} }

View File

@ -0,0 +1,80 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use App\Models\AccountGateway;
use App\Models\BankAccount;
use Artisan;
use Crypt;
use Illuminate\Encryption\Encrypter;
/**
* Class PruneData.
*/
class UpdateKey extends Command
{
/**
* @var string
*/
protected $name = 'ninja:update-key';
/**
* @var string
*/
protected $description = 'Update application key';
public function fire()
{
$this->info(date('Y-m-d h:i:s') . ' Running UpdateKey...');
// load the current values
$gatewayConfigs = [];
$bankUsernames = [];
foreach (AccountGateway::all() as $gateway) {
$gatewayConfigs[$gateway->id] = $gateway->getConfig();
}
foreach (BankAccount::all() as $bank) {
$bankUsernames[$bank->id] = $bank->getUsername();
}
// set the new key and create a new encrypter
Artisan::call('key:generate');
$key = base64_decode(str_replace('base64:', '', config('app.key')));
$crypt = new Encrypter($key, config('app.cipher'));
// update values using the new key/encrypter
foreach (AccountGateway::all() as $gateway) {
$config = $gatewayConfigs[$gateway->id];
$gateway->config = $crypt->encrypt(json_encode($config));
$gateway->save();
}
foreach (BankAccount::all() as $bank) {
$username = $bankUsernames[$bank->id];
$bank->username = $crypt->encrypt($username);
$bank->save();
}
$this->info(date('Y-m-d h:i:s') . ' Successfully updated the application key');
}
/**
* @return array
*/
protected function getArguments()
{
return [];
}
/**
* @return array
*/
protected function getOptions()
{
return [];
}
}

View File

@ -29,6 +29,7 @@ class Kernel extends ConsoleKernel
'App\Console\Commands\MakeClass', 'App\Console\Commands\MakeClass',
'App\Console\Commands\InitLookup', 'App\Console\Commands\InitLookup',
'App\Console\Commands\CalculatePayouts', 'App\Console\Commands\CalculatePayouts',
'App\Console\Commands\UpdateKey',
]; ];
/** /**

View File

@ -46,6 +46,7 @@ if (! defined('APP_NAME')) {
define('INVOICE_ITEM_TYPE_TASK', 2); define('INVOICE_ITEM_TYPE_TASK', 2);
define('INVOICE_ITEM_TYPE_PENDING_GATEWAY_FEE', 3); define('INVOICE_ITEM_TYPE_PENDING_GATEWAY_FEE', 3);
define('INVOICE_ITEM_TYPE_PAID_GATEWAY_FEE', 4); define('INVOICE_ITEM_TYPE_PAID_GATEWAY_FEE', 4);
define('INVOICE_ITEM_TYPE_LATE_FEE', 5);
define('PERSON_CONTACT', 'contact'); define('PERSON_CONTACT', 'contact');
define('PERSON_USER', 'user'); define('PERSON_USER', 'user');
@ -307,7 +308,7 @@ if (! defined('APP_NAME')) {
define('NINJA_APP_URL', env('NINJA_APP_URL', 'https://app.invoiceninja.com')); define('NINJA_APP_URL', env('NINJA_APP_URL', 'https://app.invoiceninja.com'));
define('NINJA_DOCS_URL', env('NINJA_DOCS_URL', 'http://docs.invoiceninja.com/en/latest')); define('NINJA_DOCS_URL', env('NINJA_DOCS_URL', 'http://docs.invoiceninja.com/en/latest'));
define('NINJA_DATE', '2000-01-01'); define('NINJA_DATE', '2000-01-01');
define('NINJA_VERSION', '3.5.1' . env('NINJA_VERSION_SUFFIX')); define('NINJA_VERSION', '3.6.0' . env('NINJA_VERSION_SUFFIX'));
define('SOCIAL_LINK_FACEBOOK', env('SOCIAL_LINK_FACEBOOK', 'https://www.facebook.com/invoiceninja')); define('SOCIAL_LINK_FACEBOOK', env('SOCIAL_LINK_FACEBOOK', 'https://www.facebook.com/invoiceninja'));
define('SOCIAL_LINK_TWITTER', env('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja')); define('SOCIAL_LINK_TWITTER', env('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja'));
@ -569,6 +570,9 @@ if (! defined('APP_NAME')) {
]; ];
define('CACHED_TABLES', serialize($cachedTables)); define('CACHED_TABLES', serialize($cachedTables));
// Fix for mPDF: https://github.com/kartik-v/yii2-mpdf/issues/9
define('_MPDF_TTFONTDATAPATH', storage_path('framework/cache/'));
// TODO remove these translation functions // TODO remove these translation functions
function uctrans($text) function uctrans($text)
{ {

View File

@ -423,7 +423,6 @@ class AccountController extends BaseController
'timezones' => Cache::get('timezones'), 'timezones' => Cache::get('timezones'),
'dateFormats' => Cache::get('dateFormats'), 'dateFormats' => Cache::get('dateFormats'),
'datetimeFormats' => Cache::get('datetimeFormats'), 'datetimeFormats' => Cache::get('datetimeFormats'),
'currencies' => Cache::get('currencies'),
'title' => trans('texts.localization'), 'title' => trans('texts.localization'),
'weekdays' => Utils::getTranslatedWeekdayNames(), 'weekdays' => Utils::getTranslatedWeekdayNames(),
'months' => Utils::getMonthOptions(), 'months' => Utils::getMonthOptions(),
@ -823,6 +822,10 @@ class AccountController extends BaseController
$account->{"num_days_{$type}"} = Input::get("num_days_{$type}"); $account->{"num_days_{$type}"} = Input::get("num_days_{$type}");
$account->{"field_{$type}"} = Input::get("field_{$type}"); $account->{"field_{$type}"} = Input::get("field_{$type}");
$account->{"direction_{$type}"} = Input::get("field_{$type}") == REMINDER_FIELD_INVOICE_DATE ? REMINDER_DIRECTION_AFTER : Input::get("direction_{$type}"); $account->{"direction_{$type}"} = Input::get("field_{$type}") == REMINDER_FIELD_INVOICE_DATE ? REMINDER_DIRECTION_AFTER : Input::get("direction_{$type}");
$number = preg_replace('/[^0-9]/', '', $type);
$account->account_email_settings->{"late_fee{$number}_amount"} = Input::get("late_fee{$number}_amount");
$account->account_email_settings->{"late_fee{$number}_percent"} = Input::get("late_fee{$number}_percent");
} }
$account->save(); $account->save();

View File

@ -191,7 +191,6 @@ class ClientController extends BaseController
'data' => Input::old('data'), 'data' => Input::old('data'),
'account' => Auth::user()->account, 'account' => Auth::user()->account,
'sizes' => Cache::get('sizes'), 'sizes' => Cache::get('sizes'),
'currencies' => Cache::get('currencies'),
'customLabel1' => Auth::user()->account->custom_client_label1, 'customLabel1' => Auth::user()->account->custom_client_label1,
'customLabel2' => Auth::user()->account->custom_client_label2, 'customLabel2' => Auth::user()->account->custom_client_label2,
]; ];
@ -225,25 +224,51 @@ class ClientController extends BaseController
return $this->returnBulk(ENTITY_CLIENT, $action, $ids); return $this->returnBulk(ENTITY_CLIENT, $action, $ids);
} }
public function statement() public function statement($clientPublicId, $statusId = false, $startDate = false, $endDate = false)
{ {
$account = Auth::user()->account; $account = Auth::user()->account;
$statusId = intval($statusId);
$client = Client::scope(request()->client_id)->with('contacts')->firstOrFail(); $client = Client::scope(request()->client_id)->with('contacts')->firstOrFail();
if (! $startDate) {
$startDate = Utils::today(false)->modify('-6 month')->format('Y-m-d');
$endDate = Utils::today(false)->format('Y-m-d');
}
$invoice = $account->createInvoice(ENTITY_INVOICE); $invoice = $account->createInvoice(ENTITY_INVOICE);
$invoice->client = $client; $invoice->client = $client;
$invoice->date_format = $account->date_format ? $account->date_format->format_moment : 'MMM D, YYYY'; $invoice->date_format = $account->date_format ? $account->date_format->format_moment : 'MMM D, YYYY';
$invoice->invoice_items = Invoice::scope()
$invoices = Invoice::scope()
->with(['client']) ->with(['client'])
->whereClientId($client->id)
->invoices() ->invoices()
->whereClientId($client->id)
->whereIsPublic(true) ->whereIsPublic(true)
->where('balance', '>', 0) ->orderBy('invoice_date', 'asc');
->get();
if ($statusId == INVOICE_STATUS_PAID) {
$invoices->where('invoice_status_id', '=', INVOICE_STATUS_PAID);
} elseif ($statusId == INVOICE_STATUS_UNPAID) {
$invoices->where('invoice_status_id', '!=', INVOICE_STATUS_PAID);
}
if ($statusId == INVOICE_STATUS_PAID || ! $statusId) {
$invoices->where('invoice_date', '>=', $startDate)
->where('invoice_date', '<=', $endDate);
}
$invoice->invoice_items = $invoices->get();
if (request()->json) {
return json_encode($invoice);
}
$data = [ $data = [
'showBreadcrumbs' => false, 'showBreadcrumbs' => false,
'client' => $client, 'client' => $client,
'invoice' => $invoice, 'account' => $account,
'startDate' => $startDate,
'endDate' => $endDate,
]; ];
return view('clients.statement', $data); return view('clients.statement', $data);

View File

@ -130,7 +130,7 @@ class ClientPortalController extends BaseController
$showApprove = $invoice->quote_invoice_id ? false : true; $showApprove = $invoice->quote_invoice_id ? false : true;
if ($invoice->due_date) { if ($invoice->due_date) {
$showApprove = time() < strtotime($invoice->due_date); $showApprove = time() < strtotime($invoice->getOriginal('due_date'));
} }
if ($invoice->invoice_status_id >= INVOICE_STATUS_APPROVED) { if ($invoice->invoice_status_id >= INVOICE_STATUS_APPROVED) {
$showApprove = false; $showApprove = false;
@ -369,7 +369,7 @@ class ClientPortalController extends BaseController
'client' => $contact->client, 'client' => $contact->client,
'title' => trans('texts.invoices'), 'title' => trans('texts.invoices'),
'entityType' => ENTITY_INVOICE, 'entityType' => ENTITY_INVOICE,
'columns' => Utils::trans(['invoice_number', 'invoice_date', 'invoice_total', 'balance_due', 'due_date']), 'columns' => Utils::trans(['invoice_number', 'invoice_date', 'invoice_total', 'balance_due', 'due_date', 'status']),
]; ];
return response()->view('public_list', $data); return response()->view('public_list', $data);
@ -431,7 +431,7 @@ class ClientPortalController extends BaseController
return $model->invitation_key ? link_to('/view/'.$model->invitation_key, $model->invoice_number)->toHtml() : $model->invoice_number; return $model->invitation_key ? link_to('/view/'.$model->invitation_key, $model->invoice_number)->toHtml() : $model->invoice_number;
}) })
->addColumn('transaction_reference', function ($model) { ->addColumn('transaction_reference', function ($model) {
return $model->transaction_reference ? $model->transaction_reference : '<i>'.trans('texts.manual_entry').'</i>'; return $model->transaction_reference ? e($model->transaction_reference) : '<i>'.trans('texts.manual_entry').'</i>';
}) })
->addColumn('payment_type', function ($model) { ->addColumn('payment_type', function ($model) {
return ($model->payment_type && ! $model->last4) ? $model->payment_type : ($model->account_gateway_id ? '<i>Online payment</i>' : ''); return ($model->payment_type && ! $model->last4) ? $model->payment_type : ($model->account_gateway_id ? '<i>Online payment</i>' : '');
@ -497,7 +497,7 @@ class ClientPortalController extends BaseController
'account' => $account, 'account' => $account,
'title' => trans('texts.quotes'), 'title' => trans('texts.quotes'),
'entityType' => ENTITY_QUOTE, 'entityType' => ENTITY_QUOTE,
'columns' => Utils::trans(['quote_number', 'quote_date', 'quote_total', 'due_date']), 'columns' => Utils::trans(['quote_number', 'quote_date', 'quote_total', 'due_date', 'status']),
]; ];
return response()->view('public_list', $data); return response()->view('public_list', $data);
@ -584,6 +584,10 @@ class ClientPortalController extends BaseController
private function returnError($error = false) private function returnError($error = false)
{ {
if (request()->phantomjs) {
abort(404);
}
return response()->view('error', [ return response()->view('error', [
'error' => $error ?: trans('texts.invoice_not_found'), 'error' => $error ?: trans('texts.invoice_not_found'),
'hideHeader' => true, 'hideHeader' => true,
@ -745,7 +749,9 @@ class ClientPortalController extends BaseController
$document = Document::scope($publicId, $invitation->account_id)->firstOrFail(); $document = Document::scope($publicId, $invitation->account_id)->firstOrFail();
$authorized = false; $authorized = false;
if ($document->expense && $document->expense->invoice_documents && $document->expense->client_id == $invitation->invoice->client_id) { if ($document->is_default) {
$authorized = true;
} elseif ($document->expense && $document->expense->invoice_documents && $document->expense->client_id == $invitation->invoice->client_id) {
$authorized = true; $authorized = true;
} elseif ($document->invoice && $document->invoice->client_id == $invitation->invoice->client_id) { } elseif ($document->invoice && $document->invoice->client_id == $invitation->invoice->client_id) {
$authorized = true; $authorized = true;

View File

@ -94,11 +94,20 @@ class ExpenseController extends BaseController
return View::make('expenses.edit', $data); return View::make('expenses.edit', $data);
} }
public function edit(ExpenseRequest $request) public function clone(ExpenseRequest $request, $publicId)
{
return self::edit($request, $publicId, true);
}
public function edit(ExpenseRequest $request, $publicId = false, $clone = false)
{ {
$expense = $request->entity(); $expense = $request->entity();
$actions = []; $actions = [];
if (! $clone) {
$actions[] = ['url' => 'javascript:submitAction("clone")', 'label' => trans("texts.clone_expense")];
}
if ($expense->invoice) { if ($expense->invoice) {
$actions[] = ['url' => URL::to("invoices/{$expense->invoice->public_id}/edit"), 'label' => trans('texts.view_invoice')]; $actions[] = ['url' => URL::to("invoices/{$expense->invoice->public_id}/edit"), 'label' => trans('texts.view_invoice')];
} else { } else {
@ -124,12 +133,28 @@ class ExpenseController extends BaseController
$actions[] = ['url' => 'javascript:submitAction("restore")', 'label' => trans('texts.restore_expense')]; $actions[] = ['url' => 'javascript:submitAction("restore")', 'label' => trans('texts.restore_expense')];
} }
if ($clone) {
$expense->id = null;
$expense->public_id = null;
$expense->expense_date = date_create()->format('Y-m-d');
$expense->deleted_at = null;
$expense->invoice_id = null;
$expense->payment_date = null;
$expense->payment_type_id = null;
$expense->transaction_reference = null;
$method = 'POST';
$url = 'expenses';
} else {
$method = 'PUT';
$url = 'expenses/' . $expense->public_id;
}
$data = [ $data = [
'vendor' => null, 'vendor' => null,
'expense' => $expense, 'expense' => $expense,
'entity' => $expense, 'entity' => $expense,
'method' => 'PUT', 'method' => $method,
'url' => 'expenses/'.$expense->public_id, 'url' => $url,
'title' => 'Edit Expense', 'title' => 'Edit Expense',
'actions' => $actions, 'actions' => $actions,
'vendors' => Vendor::scope()->with('vendor_contacts')->orderBy('name')->get(), 'vendors' => Vendor::scope()->with('vendor_contacts')->orderBy('name')->get(),
@ -165,8 +190,12 @@ class ExpenseController extends BaseController
return self::bulk(); return self::bulk();
} }
if ($action == 'clone') {
return redirect()->to(sprintf('expenses/%s/clone', $expense->public_id));
} else {
return redirect()->to("expenses/{$expense->public_id}/edit"); return redirect()->to("expenses/{$expense->public_id}/edit");
} }
}
public function store(CreateExpenseRequest $request) public function store(CreateExpenseRequest $request)
{ {
@ -260,14 +289,6 @@ class ExpenseController extends BaseController
return [ return [
'data' => Input::old('data'), 'data' => Input::old('data'),
'account' => Auth::user()->account, 'account' => Auth::user()->account,
'sizes' => Cache::get('sizes'),
'paymentTerms' => Cache::get('paymentTerms'),
'industries' => Cache::get('industries'),
'currencies' => Cache::get('currencies'),
'languages' => Cache::get('languages'),
'countries' => Cache::get('countries'),
'customLabel1' => Auth::user()->account->custom_vendor_label1,
'customLabel2' => Auth::user()->account->custom_vendor_label2,
'categories' => ExpenseCategory::whereAccountId(Auth::user()->account_id)->withArchived()->orderBy('name')->get(), 'categories' => ExpenseCategory::whereAccountId(Auth::user()->account_id)->withArchived()->orderBy('name')->get(),
'taxRates' => TaxRate::scope()->whereIsInclusive(false)->orderBy('name')->get(), 'taxRates' => TaxRate::scope()->whereIsInclusive(false)->orderBy('name')->get(),
'isRecurring' => false, 'isRecurring' => false,

View File

@ -170,7 +170,7 @@ class ExportController extends BaseController
if ($request->input('include') === 'all' || $request->input('clients')) { if ($request->input('include') === 'all' || $request->input('clients')) {
$data['clients'] = Client::scope() $data['clients'] = Client::scope()
->with('user', 'contacts', 'country') ->with('user', 'contacts', 'country', 'currency')
->withArchived() ->withArchived()
->get(); ->get();
} }

View File

@ -132,9 +132,11 @@ class HomeController extends BaseController
public function contactUs() public function contactUs()
{ {
Mail::raw(request()->contact_us_message, function ($message) { Mail::raw(request()->contact_us_message, function ($message) {
$subject = 'Customer Message'; $subject = 'Customer Message: ';
if (! Utils::isNinja()) { if (Utils::isNinja()) {
$subject .= ': v' . NINJA_VERSION; $subject .= config('database.default');
} else {
$subject .= 'v' . NINJA_VERSION;
} }
$message->to(env('CONTACT_EMAIL', 'contact@invoiceninja.com')) $message->to(env('CONTACT_EMAIL', 'contact@invoiceninja.com'))
->from(CONTACT_EMAIL, Auth::user()->present()->fullName) ->from(CONTACT_EMAIL, Auth::user()->present()->fullName)

View File

@ -423,7 +423,12 @@ class InvoiceApiController extends BaseAPIController
public function download(InvoiceRequest $request) public function download(InvoiceRequest $request)
{ {
$invoice = $request->entity(); $invoice = $request->entity();
$pdfString = $invoice->getPDFString();
return $this->fileReponse($invoice->getFileName(), $invoice->getPDFString()); if ($pdfString) {
return $this->fileReponse($invoice->getFileName(), $pdfString);
} else {
abort(404);
}
} }
} }

View File

@ -305,7 +305,6 @@ class InvoiceController extends BaseController
'account' => Auth::user()->account->load('country'), 'account' => Auth::user()->account->load('country'),
'products' => Product::scope()->orderBy('product_key')->get(), 'products' => Product::scope()->orderBy('product_key')->get(),
'taxRateOptions' => $taxRateOptions, 'taxRateOptions' => $taxRateOptions,
'currencies' => Cache::get('currencies'),
'sizes' => Cache::get('sizes'), 'sizes' => Cache::get('sizes'),
'invoiceDesigns' => InvoiceDesign::getDesigns(), 'invoiceDesigns' => InvoiceDesign::getDesigns(),
'invoiceFonts' => Cache::get('fonts'), 'invoiceFonts' => Cache::get('fonts'),
@ -480,6 +479,8 @@ class InvoiceController extends BaseController
$key = 'emailed_' . $entityType; $key = 'emailed_' . $entityType;
} elseif ($action == 'markPaid') { } elseif ($action == 'markPaid') {
$key = 'created_payment'; $key = 'created_payment';
} elseif ($action == 'download') {
$key = 'downloaded_invoice';
} else { } else {
$key = "{$action}d_{$entityType}"; $key = "{$action}d_{$entityType}";
} }

View File

@ -339,6 +339,9 @@ class OnlinePaymentController extends BaseController
if (request()->currency_code) { if (request()->currency_code) {
$data['currency_code'] = request()->currency_code; $data['currency_code'] = request()->currency_code;
} }
if (request()->country_code) {
$data['country_code'] = request()->country_code;
}
$client = $clientRepo->save($data, $client); $client = $clientRepo->save($data, $client);
} }

View File

@ -236,7 +236,6 @@ class PaymentController extends BaseController
public function bulk() public function bulk()
{ {
$action = Input::get('action'); $action = Input::get('action');
$amount = Input::get('refund_amount');
$ids = Input::get('public_id') ? Input::get('public_id') : Input::get('ids'); $ids = Input::get('public_id') ? Input::get('public_id') : Input::get('ids');
if ($action === 'email') { if ($action === 'email') {
@ -244,7 +243,10 @@ class PaymentController extends BaseController
$this->contactMailer->sendPaymentConfirmation($payment); $this->contactMailer->sendPaymentConfirmation($payment);
Session::flash('message', trans('texts.emailed_payment')); Session::flash('message', trans('texts.emailed_payment'));
} else { } else {
$count = $this->paymentService->bulk($ids, $action, ['refund_amount' => $amount]); $count = $this->paymentService->bulk($ids, $action, [
'refund_amount' => Input::get('refund_amount'),
'refund_email' => Input::get('refund_email'),
]);
if ($count > 0) { if ($count > 0) {
$message = Utils::pluralize($action == 'refund' ? 'refunded_payment' : $action.'d_payment', $count); $message = Utils::pluralize($action == 'refund' ? 'refunded_payment' : $action.'d_payment', $count);
Session::flash('message', $message); Session::flash('message', $message);

View File

@ -100,18 +100,15 @@ class QuoteController extends BaseController
'account' => $account, 'account' => $account,
'products' => Product::scope()->orderBy('product_key')->get(), 'products' => Product::scope()->orderBy('product_key')->get(),
'taxRateOptions' => $account->present()->taxRateOptions, 'taxRateOptions' => $account->present()->taxRateOptions,
'countries' => Cache::get('countries'),
'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(), 'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(),
'taxRates' => TaxRate::scope()->orderBy('name')->get(), 'taxRates' => TaxRate::scope()->orderBy('name')->get(),
'currencies' => Cache::get('currencies'),
'sizes' => Cache::get('sizes'), 'sizes' => Cache::get('sizes'),
'paymentTerms' => Cache::get('paymentTerms'), 'paymentTerms' => Cache::get('paymentTerms'),
'languages' => Cache::get('languages'),
'industries' => Cache::get('industries'),
'invoiceDesigns' => InvoiceDesign::getDesigns(), 'invoiceDesigns' => InvoiceDesign::getDesigns(),
'invoiceFonts' => Cache::get('fonts'), 'invoiceFonts' => Cache::get('fonts'),
'invoiceLabels' => Auth::user()->account->getInvoiceLabels(), 'invoiceLabels' => Auth::user()->account->getInvoiceLabels(),
'isRecurring' => false, 'isRecurring' => false,
'expenses' => [],
]; ];
} }
@ -133,7 +130,13 @@ class QuoteController extends BaseController
$count = $this->invoiceService->bulk($ids, $action); $count = $this->invoiceService->bulk($ids, $action);
if ($count > 0) { if ($count > 0) {
$key = $action == 'markSent' ? 'updated_quote' : "{$action}d_quote"; if ($action == 'markSent') {
$key = 'updated_quote';
} elseif ($action == 'download') {
$key = 'downloaded_quote';
} else {
$key = "{$action}d_quote";
}
$message = Utils::pluralize($key, $count); $message = Utils::pluralize($key, $count);
Session::flash('message', $message); Session::flash('message', $message);
} }

View File

@ -115,14 +115,6 @@ class RecurringExpenseController extends BaseController
return [ return [
'data' => Input::old('data'), 'data' => Input::old('data'),
'account' => Auth::user()->account, 'account' => Auth::user()->account,
'sizes' => Cache::get('sizes'),
'paymentTerms' => Cache::get('paymentTerms'),
'industries' => Cache::get('industries'),
'currencies' => Cache::get('currencies'),
'languages' => Cache::get('languages'),
'countries' => Cache::get('countries'),
'customLabel1' => Auth::user()->account->custom_vendor_label1,
'customLabel2' => Auth::user()->account->custom_vendor_label2,
'categories' => ExpenseCategory::whereAccountId(Auth::user()->account_id)->withArchived()->orderBy('name')->get(), 'categories' => ExpenseCategory::whereAccountId(Auth::user()->account_id)->withArchived()->orderBy('name')->get(),
'taxRates' => TaxRate::scope()->whereIsInclusive(false)->orderBy('name')->get(), 'taxRates' => TaxRate::scope()->whereIsInclusive(false)->orderBy('name')->get(),
'isRecurring' => true, 'isRecurring' => true,

View File

@ -8,6 +8,7 @@ use Input;
use Str; use Str;
use Utils; use Utils;
use View; use View;
use Excel;
/** /**
* Class ReportController. * Class ReportController.
@ -53,6 +54,7 @@ class ReportController extends BaseController
} }
$action = Input::get('action'); $action = Input::get('action');
$format = Input::get('format');
if (Input::get('report_type')) { if (Input::get('report_type')) {
$reportType = Input::get('report_type'); $reportType = Input::get('report_type');
@ -104,7 +106,7 @@ class ReportController extends BaseController
$params['report'] = $report; $params['report'] = $report;
$params = array_merge($params, $report->results()); $params = array_merge($params, $report->results());
if ($isExport) { if ($isExport) {
self::export($reportType, $params['displayData'], $params['columns'], $params['reportTotals']); return self::export($format, $reportType, $params);
} }
} else { } else {
$params['columns'] = []; $params['columns'] = [];
@ -117,49 +119,80 @@ class ReportController extends BaseController
} }
/** /**
* @param $format
* @param $reportType * @param $reportType
* @param $data * @param $params
* @param $columns * @todo: Add summary to export
* @param $totals
*/ */
private function export($reportType, $data, $columns, $totals) private function export($format, $reportType, $params)
{ {
if (! Auth::user()->hasPermission('view_all')) { if (! Auth::user()->hasPermission('view_all')) {
exit; exit;
} }
$output = fopen('php://output', 'w') or Utils::fatalError(); $format = strtolower($format);
$date = date('Y-m-d'); $data = $params['displayData'];
$columns = $params['columns'];
$totals = $params['reportTotals'];
$report = $params['report'];
$columns = array_map(function($key, $val) { $filename = "{$params['startDate']}-{$params['endDate']}_invoiceninja-".strtolower(Utils::normalizeChars(trans("texts.$reportType")))."-report";
return is_array($val) ? $key : $val;
}, array_keys($columns), $columns);
header('Content-Type:application/csv'); $formats = ['csv', 'pdf', 'xlsx'];
header("Content-Disposition:attachment;filename={$date}-invoiceninja-{$reportType}-report.csv"); if(!in_array($format, $formats)) {
throw new \Exception("Invalid format request to export report");
Utils::exportData($output, $data, Utils::trans($columns));
/*
fwrite($output, trans('texts.totals'));
foreach ($totals as $currencyId => $fields) {
foreach ($fields as $key => $value) {
fwrite($output, ',' . trans("texts.{$key}"));
}
fwrite($output, "\n");
break;
} }
foreach ($totals as $currencyId => $fields) { //Get labeled header
$csv = Utils::getFromCache($currencyId, 'currencies')->name . ','; $columns_labeled = $report->tableHeaderArray();
foreach ($fields as $key => $value) {
$csv .= '"' . Utils::formatMoney($value, $currencyId).'",';
}
fwrite($output, $csv."\n");
}
*/
fclose($output); /*$summary = [];
exit; if(count(array_values($totals))) {
$summary[] = array_merge([
trans("texts.totals")
], array_map(function ($key) {return trans("texts.{$key}");}, array_keys(array_values(array_values($totals)[0])[0])));
}
foreach ($totals as $currencyId => $each) {
foreach ($each as $dimension => $val) {
$tmp = [];
$tmp[] = Utils::getFromCache($currencyId, 'currencies')->name . (($dimension) ? ' - ' . $dimension : '');
foreach ($val as $id => $field) $tmp[] = Utils::formatMoney($field, $currencyId);
$summary[] = $tmp;
}
}
dd($summary);*/
return Excel::create($filename, function($excel) use($report, $data, $reportType, $format, $columns_labeled) {
$excel->sheet(trans("texts.$reportType"), function($sheet) use($report, $data, $format, $columns_labeled) {
$sheet->setOrientation('landscape');
$sheet->freezeFirstRow();
//Add border on PDF
if($format == 'pdf')
$sheet->setAllBorders('thin');
$sheet->rows(array_merge(
[array_map(function($col) {return $col['label'];}, $columns_labeled)],
$data
));
//Styling header
$sheet->cells('A1:'.Utils::num2alpha(count($columns_labeled)-1).'1', function($cells) {
$cells->setBackground('#777777');
$cells->setFontColor('#FFFFFF');
$cells->setFontSize(13);
$cells->setFontFamily('Calibri');
$cells->setFontWeight('bold');
});
$sheet->setAutoSize(true);
});
})->export($format);
} }
} }

View File

@ -161,7 +161,7 @@ class TaskController extends BaseController
$invoices = $task->client_id ? $this->invoiceRepo->findOpenInvoices($task->client_id) : []; $invoices = $task->client_id ? $this->invoiceRepo->findOpenInvoices($task->client_id) : [];
foreach ($invoices as $invoice) { foreach ($invoices as $invoice) {
$actions[] = ['url' => 'javascript:submitAction("add_to_invoice", '.$invoice->public_id.')', 'label' => trans('texts.add_to_invoice', ['invoice' => $invoice->invoice_number])]; $actions[] = ['url' => 'javascript:submitAction("add_to_invoice", '.$invoice->public_id.')', 'label' => trans('texts.add_to_invoice', ['invoice' => e($invoice->invoice_number)])];
} }
} }

View File

@ -156,7 +156,10 @@ class UserController extends BaseController
*/ */
public function save($userPublicId = false) public function save($userPublicId = false)
{ {
if (Auth::user()->hasFeature(FEATURE_USERS)) { if (! Auth::user()->hasFeature(FEATURE_USERS)) {
return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
}
$rules = [ $rules = [
'first_name' => 'required', 'first_name' => 'required',
'last_name' => 'required', 'last_name' => 'required',
@ -227,7 +230,6 @@ class UserController extends BaseController
} }
Session::flash('message', $message); Session::flash('message', $message);
}
return Redirect::to('users/' . $user->public_id . '/edit'); return Redirect::to('users/' . $user->public_id . '/edit');
} }

View File

@ -151,7 +151,6 @@ class VendorController extends BaseController
return [ return [
'data' => Input::old('data'), 'data' => Input::old('data'),
'account' => Auth::user()->account, 'account' => Auth::user()->account,
'currencies' => Cache::get('currencies'),
]; ];
} }

View File

@ -68,7 +68,7 @@ class Authenticate
} }
$account = $contact->account; $account = $contact->account;
if (Auth::guard('user')->check() && Auth::user('user')->account_id === $account->id) { if (Auth::guard('user')->check() && Auth::user('user')->account_id == $account->id) {
// This is an admin; let them pretend to be a client // This is an admin; let them pretend to be a client
$authenticated = true; $authenticated = true;
} }

View File

@ -33,7 +33,11 @@ class CreatePaymentAPIRequest extends PaymentRequest
$this->invoice = $invoice = Invoice::scope($this->invoice_id) $this->invoice = $invoice = Invoice::scope($this->invoice_id)
->withArchived() ->withArchived()
->invoices() ->invoices()
->firstOrFail(); ->first();
if (! $this->invoice) {
abort(404, 'Invoice was not found');
}
$this->merge([ $this->merge([
'invoice_id' => $invoice->id, 'invoice_id' => $invoice->id,

View File

@ -31,7 +31,7 @@ class RegisterRequest extends Request
public function rules() public function rules()
{ {
$rules = [ $rules = [
'email' => 'required|unique:users', 'email' => 'email|required|unique:users',
'first_name' => 'required', 'first_name' => 'required',
'last_name' => 'required', 'last_name' => 'required',
'password' => 'required', 'password' => 'required',

View File

@ -2,6 +2,7 @@
namespace App\Http\ViewComposers; namespace App\Http\ViewComposers;
use Str;
use Cache; use Cache;
use Illuminate\View\View; use Illuminate\View\View;
@ -44,5 +45,11 @@ class TranslationComposer
})->sortBy(function ($lang) { })->sortBy(function ($lang) {
return $lang->name; return $lang->name;
})); }));
$view->with('currencies', Cache::get('currencies')->each(function ($currency) {
$currency->name = trans('texts.currency_' . Str::slug($currency->name, '_'));
})->sortBy(function ($currency) {
return $currency->name;
}));
} }
} }

View File

@ -144,7 +144,7 @@ Route::group(['middleware' => ['lookup:user', 'auth:user']], function () {
Route::get('api/clients', 'ClientController@getDatatable'); Route::get('api/clients', 'ClientController@getDatatable');
Route::get('api/activities/{client_id?}', 'ActivityController@getDatatable'); Route::get('api/activities/{client_id?}', 'ActivityController@getDatatable');
Route::post('clients/bulk', 'ClientController@bulk'); Route::post('clients/bulk', 'ClientController@bulk');
Route::get('clients/statement/{client_id}', 'ClientController@statement'); Route::get('clients/statement/{client_id}/{status_id?}/{start_date?}/{end_date?}', 'ClientController@statement');
Route::resource('tasks', 'TaskController'); Route::resource('tasks', 'TaskController');
Route::get('api/tasks/{client_id?}', 'TaskController@getDatatable'); Route::get('api/tasks/{client_id?}', 'TaskController@getDatatable');
@ -224,6 +224,7 @@ Route::group(['middleware' => ['lookup:user', 'auth:user']], function () {
// Expense // Expense
Route::resource('expenses', 'ExpenseController'); Route::resource('expenses', 'ExpenseController');
Route::get('expenses/create/{vendor_id?}/{client_id?}/{category_id?}', 'ExpenseController@create'); Route::get('expenses/create/{vendor_id?}/{client_id?}/{category_id?}', 'ExpenseController@create');
Route::get('expenses/{expenses}/clone', 'ExpenseController@clone');
Route::get('api/expenses', 'ExpenseController@getDatatable'); Route::get('api/expenses', 'ExpenseController@getDatatable');
Route::get('api/expenses/{id}', 'ExpenseController@getDatatableVendor'); Route::get('api/expenses/{id}', 'ExpenseController@getDatatableVendor');
Route::post('expenses/bulk', 'ExpenseController@bulk'); Route::post('expenses/bulk', 'ExpenseController@bulk');

View File

@ -0,0 +1,87 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Models\User;
use App\Ninja\Mailers\UserMailer;
use Barracuda\ArchiveStream\Archive;
/**
* Class SendInvoiceEmail.
*/
//class DownloadInvoices extends Job implements ShouldQueue
class DownloadInvoices extends Job
{
//use InteractsWithQueue, SerializesModels;
/**
* @var User
*/
protected $user;
/**
* @var array
*/
protected $invoices;
/**
* Create a new job instance.
*
* @param mixed $files
* @param mixed $settings
*/
public function __construct(User $user, $invoices)
{
$this->user = $user;
$this->invoices = $invoices;
}
/**
* Execute the job.
*
* @param ContactMailer $mailer
*/
public function handle(UserMailer $userMailer)
{
$zip = Archive::instance_by_useragent(date('Y-m-d') . '-Invoice_PDFs');
foreach ($this->invoices as $invoice) {
$zip->add_file($invoice->getFileName(), $invoice->getPDFString());
}
$zip->finish();
exit;
/*
// if queues are disabled download a zip file
if (config('queue.default') === 'sync' || count($this->invoices) <= 10) {
$zip = Archive::instance_by_useragent(date('Y-m-d') . '-Invoice_PDFs');
foreach ($this->invoices as $invoice) {
$zip->add_file($invoice->getFileName(), $invoice->getPDFString());
}
$zip->finish();
exit;
// otherwise sends the PDFs in an email
} else {
$data = [];
foreach ($this->invoices as $invoice) {
$data[] = [
'name' => $invoice->getFileName(),
'data' => $invoice->getPDFString(),
];
}
$subject = trans('texts.invoices_are_attached');
$data = [
'documents' => $data
];
$userMailer->sendMessage($this->user, $subject, false, $data);
}
*/
}
}

View File

@ -61,6 +61,8 @@ class PurgeAccountData extends Job
$account->client_number_counter = $account->client_number_counter > 0 ? 1 : 0; $account->client_number_counter = $account->client_number_counter > 0 ? 1 : 0;
$account->save(); $account->save();
session([RECENTLY_VIEWED => false]);
if (env('MULTI_DB_ENABLED')) { if (env('MULTI_DB_ENABLED')) {
$current = config('database.default'); $current = config('database.default');
config(['database.default' => DB_NINJA_LOOKUP]); config(['database.default' => DB_NINJA_LOOKUP]);

View File

@ -7,13 +7,16 @@ use App\Ninja\Mailers\UserMailer;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use App\Models\Traits\SerialisesDeletedModels;
/** /**
* Class SendInvoiceEmail. * Class SendInvoiceEmail.
*/ */
class SendNotificationEmail extends Job implements ShouldQueue class SendNotificationEmail extends Job implements ShouldQueue
{ {
use InteractsWithQueue, SerializesModels; use InteractsWithQueue, SerializesModels, SerialisesDeletedModels {
SerialisesDeletedModels::getRestoredPropertyValue insteadof SerializesModels;
}
/** /**
* @var User * @var User

View File

@ -39,6 +39,8 @@ class HTMLUtils
public static function sanitizeHTML($html) public static function sanitizeHTML($html)
{ {
$html = html_entity_decode($html);
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config); $purifier = new HTMLPurifier($config);

View File

@ -916,7 +916,7 @@ class Utils
$str = ''; $str = '';
if (property_exists($model, 'is_deleted')) { if (property_exists($model, 'is_deleted')) {
$str = $model->is_deleted || ($model->deleted_at && $model->deleted_at != '0000-00-00') ? 'DISABLED ' : ''; $str = $model->is_deleted ? 'DISABLED ' : '';
if ($model->is_deleted) { if ($model->is_deleted) {
$str .= 'ENTITY_DELETED '; $str .= 'ENTITY_DELETED ';
@ -1052,20 +1052,15 @@ class Utils
} }
} }
public static function formatWebsite($website) public static function formatWebsite($link)
{ {
if (! $website) { if (! $link) {
return ''; return '';
} }
$link = $website; $title = $link;
$title = $website; if (substr($link, 0, 4) != 'http') {
$prefix = 'http://'; $link = 'http://' . $link;
if (strlen($link) > 7 && substr($link, 0, 7) === $prefix) {
$title = substr($title, 7);
} else {
$link = $prefix.$link;
} }
return link_to($link, $title, ['target' => '_blank']); return link_to($link, $title, ['target' => '_blank']);
@ -1246,4 +1241,64 @@ class Utils
fclose($handle); fclose($handle);
return( ord($contents[28]) != 0 ); return( ord($contents[28]) != 0 );
} }
//Source: https://stackoverflow.com/questions/3302857/algorithm-to-get-the-excel-like-column-name-of-a-number
public static function num2alpha($n)
{
for($r = ""; $n >= 0; $n = intval($n / 26) - 1)
$r = chr($n%26 + 0x41) . $r;
return $r;
}
/**
* Replace language-specific characters by ASCII-equivalents.
* @param string $s
* @return string
* Source: https://stackoverflow.com/questions/3371697/replacing-accented-characters-php/16427125#16427125
*/
public static function normalizeChars($s) {
$replace = array(
'ъ'=>'-', 'Ь'=>'-', 'Ъ'=>'-', 'ь'=>'-',
'Ă'=>'A', 'Ą'=>'A', 'À'=>'A', 'Ã'=>'A', 'Á'=>'A', 'Æ'=>'A', 'Â'=>'A', 'Å'=>'A', 'Ä'=>'Ae',
'Þ'=>'B',
'Ć'=>'C', 'ץ'=>'C', 'Ç'=>'C',
'È'=>'E', 'Ę'=>'E', 'É'=>'E', 'Ë'=>'E', 'Ê'=>'E',
'Ğ'=>'G',
'İ'=>'I', 'Ï'=>'I', 'Î'=>'I', 'Í'=>'I', 'Ì'=>'I',
'Ł'=>'L',
'Ñ'=>'N', 'Ń'=>'N',
'Ø'=>'O', 'Ó'=>'O', 'Ò'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'Oe',
'Ş'=>'S', 'Ś'=>'S', 'Ș'=>'S', 'Š'=>'S',
'Ț'=>'T',
'Ù'=>'U', 'Û'=>'U', 'Ú'=>'U', 'Ü'=>'Ue',
'Ý'=>'Y',
'Ź'=>'Z', 'Ž'=>'Z', 'Ż'=>'Z',
'â'=>'a', 'ǎ'=>'a', 'ą'=>'a', 'á'=>'a', 'ă'=>'a', 'ã'=>'a', 'Ǎ'=>'a', 'а'=>'a', 'А'=>'a', 'å'=>'a', 'à'=>'a', 'א'=>'a', 'Ǻ'=>'a', 'Ā'=>'a', 'ǻ'=>'a', 'ā'=>'a', 'ä'=>'ae', 'æ'=>'ae', 'Ǽ'=>'ae', 'ǽ'=>'ae',
'б'=>'b', 'ב'=>'b', 'Б'=>'b', 'þ'=>'b',
'ĉ'=>'c', 'Ĉ'=>'c', 'Ċ'=>'c', 'ć'=>'c', 'ç'=>'c', 'ц'=>'c', 'צ'=>'c', 'ċ'=>'c', 'Ц'=>'c', 'Č'=>'c', 'č'=>'c', 'Ч'=>'ch', 'ч'=>'ch',
'ד'=>'d', 'ď'=>'d', 'Đ'=>'d', 'Ď'=>'d', 'đ'=>'d', 'д'=>'d', 'Д'=>'D', 'ð'=>'d',
'є'=>'e', 'ע'=>'e', 'е'=>'e', 'Е'=>'e', 'Ə'=>'e', 'ę'=>'e', 'ĕ'=>'e', 'ē'=>'e', 'Ē'=>'e', 'Ė'=>'e', 'ė'=>'e', 'ě'=>'e', 'Ě'=>'e', 'Є'=>'e', 'Ĕ'=>'e', 'ê'=>'e', 'ə'=>'e', 'è'=>'e', 'ë'=>'e', 'é'=>'e',
'ф'=>'f', 'ƒ'=>'f', 'Ф'=>'f',
'ġ'=>'g', 'Ģ'=>'g', 'Ġ'=>'g', 'Ĝ'=>'g', 'Г'=>'g', 'г'=>'g', 'ĝ'=>'g', 'ğ'=>'g', 'ג'=>'g', 'Ґ'=>'g', 'ґ'=>'g', 'ģ'=>'g',
'ח'=>'h', 'ħ'=>'h', 'Х'=>'h', 'Ħ'=>'h', 'Ĥ'=>'h', 'ĥ'=>'h', 'х'=>'h', 'ה'=>'h',
'î'=>'i', 'ï'=>'i', 'í'=>'i', 'ì'=>'i', 'į'=>'i', 'ĭ'=>'i', 'ı'=>'i', 'Ĭ'=>'i', 'И'=>'i', 'ĩ'=>'i', 'ǐ'=>'i', 'Ĩ'=>'i', 'Ǐ'=>'i', 'и'=>'i', 'Į'=>'i', 'י'=>'i', 'Ї'=>'i', 'Ī'=>'i', 'І'=>'i', 'ї'=>'i', 'і'=>'i', 'ī'=>'i', 'ij'=>'ij', 'IJ'=>'ij',
'й'=>'j', 'Й'=>'j', 'Ĵ'=>'j', 'ĵ'=>'j', 'я'=>'ja', 'Я'=>'ja', 'Э'=>'je', 'э'=>'je', 'ё'=>'jo', 'Ё'=>'jo', 'ю'=>'ju', 'Ю'=>'ju',
'ĸ'=>'k', 'כ'=>'k', 'Ķ'=>'k', 'К'=>'k', 'к'=>'k', 'ķ'=>'k', 'ך'=>'k',
'Ŀ'=>'l', 'ŀ'=>'l', 'Л'=>'l', 'ł'=>'l', 'ļ'=>'l', 'ĺ'=>'l', 'Ĺ'=>'l', 'Ļ'=>'l', 'л'=>'l', 'Ľ'=>'l', 'ľ'=>'l', 'ל'=>'l',
'מ'=>'m', 'М'=>'m', 'ם'=>'m', 'м'=>'m',
'ñ'=>'n', 'н'=>'n', 'Ņ'=>'n', 'ן'=>'n', 'ŋ'=>'n', 'נ'=>'n', 'Н'=>'n', 'ń'=>'n', 'Ŋ'=>'n', 'ņ'=>'n', 'ʼn'=>'n', 'Ň'=>'n', 'ň'=>'n',
'о'=>'o', 'О'=>'o', 'ő'=>'o', 'õ'=>'o', 'ô'=>'o', 'Ő'=>'o', 'ŏ'=>'o', 'Ŏ'=>'o', 'Ō'=>'o', 'ō'=>'o', 'ø'=>'o', 'ǿ'=>'o', 'ǒ'=>'o', 'ò'=>'o', 'Ǿ'=>'o', 'Ǒ'=>'o', 'ơ'=>'o', 'ó'=>'o', 'Ơ'=>'o', 'œ'=>'oe', 'Œ'=>'oe', 'ö'=>'oe',
'פ'=>'p', 'ף'=>'p', 'п'=>'p', 'П'=>'p',
'ק'=>'q',
'ŕ'=>'r', 'ř'=>'r', 'Ř'=>'r', 'ŗ'=>'r', 'Ŗ'=>'r', 'ר'=>'r', 'Ŕ'=>'r', 'Р'=>'r', 'р'=>'r',
'ș'=>'s', 'с'=>'s', 'Ŝ'=>'s', 'š'=>'s', 'ś'=>'s', 'ס'=>'s', 'ş'=>'s', 'С'=>'s', 'ŝ'=>'s', 'Щ'=>'sch', 'щ'=>'sch', 'ш'=>'sh', 'Ш'=>'sh', 'ß'=>'ss',
'т'=>'t', 'ט'=>'t', 'ŧ'=>'t', 'ת'=>'t', 'ť'=>'t', 'ţ'=>'t', 'Ţ'=>'t', 'Т'=>'t', 'ț'=>'t', 'Ŧ'=>'t', 'Ť'=>'t', '™'=>'tm',
'ū'=>'u', 'у'=>'u', 'Ũ'=>'u', 'ũ'=>'u', 'Ư'=>'u', 'ư'=>'u', 'Ū'=>'u', 'Ǔ'=>'u', 'ų'=>'u', 'Ų'=>'u', 'ŭ'=>'u', 'Ŭ'=>'u', 'Ů'=>'u', 'ů'=>'u', 'ű'=>'u', 'Ű'=>'u', 'Ǖ'=>'u', 'ǔ'=>'u', 'Ǜ'=>'u', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'У'=>'u', 'ǚ'=>'u', 'ǜ'=>'u', 'Ǚ'=>'u', 'Ǘ'=>'u', 'ǖ'=>'u', 'ǘ'=>'u', 'ü'=>'ue',
'в'=>'v', 'ו'=>'v', 'В'=>'v',
'ש'=>'w', 'ŵ'=>'w', 'Ŵ'=>'w',
'ы'=>'y', 'ŷ'=>'y', 'ý'=>'y', 'ÿ'=>'y', 'Ÿ'=>'y', 'Ŷ'=>'y',
'Ы'=>'y', 'ž'=>'z', 'З'=>'z', 'з'=>'z', 'ź'=>'z', 'ז'=>'z', 'ż'=>'z', 'ſ'=>'z', 'Ж'=>'zh', 'ж'=>'zh'
);
return strtr($s, $replace);
}
} }

View File

@ -71,19 +71,31 @@ class HandleUserLoggedIn
Session::flash('warning', trans('texts.logo_too_large', ['size' => $account->getLogoSize() . 'KB'])); Session::flash('warning', trans('texts.logo_too_large', ['size' => $account->getLogoSize() . 'KB']));
} }
// check custom gateway id is correct
if (! Utils::isNinja()) { if (! Utils::isNinja()) {
// check custom gateway id is correct
$gateway = Gateway::find(GATEWAY_CUSTOM); $gateway = Gateway::find(GATEWAY_CUSTOM);
if (! $gateway || $gateway->name !== 'Custom') { if (! $gateway || $gateway->name !== 'Custom') {
Session::flash('error', trans('texts.error_incorrect_gateway_ids')); Session::flash('error', trans('texts.error_incorrect_gateway_ids'));
} }
/*
if (! env('APP_KEY')) { // make sure APP_KEY and APP_CIPHER are in the .env file
Session::flash('error', trans('texts.error_app_key_not_set')); $appKey = env('APP_KEY');
} elseif (strstr(env('APP_KEY'), 'SomeRandomString')) { $appCipher = env('APP_CIPHER');
if (! $appKey || ! $appCipher) {
$fp = fopen(base_path().'/.env', 'a');
if (! $appKey) {
fwrite($fp, "\nAPP_KEY=" . config('app.key'));
}
if (! $appCipher) {
fwrite($fp, "\nAPP_CIPHER=" . config('app.cipher'));
}
fclose($fp);
}
// warn if using the default app key
if (in_array(config('app.key'), ['SomeRandomString', 'SomeRandomStringSomeRandomString', 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'])) {
Session::flash('error', trans('texts.error_app_key_set_to_default')); Session::flash('error', trans('texts.error_app_key_set_to_default'));
} }
*/
} }
} }
} }

View File

@ -332,6 +332,14 @@ class Account extends Eloquent
return $this->hasMany('App\Models\Product'); return $this->hasMany('App\Models\Product');
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function defaultDocuments()
{
return $this->hasMany('App\Models\Document')->whereIsDefault(true);
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/ */

View File

@ -27,6 +27,12 @@ class AccountEmailSettings extends Eloquent
'email_template_reminder1', 'email_template_reminder1',
'email_template_reminder2', 'email_template_reminder2',
'email_template_reminder3', 'email_template_reminder3',
'late_fee1_amount',
'late_fee1_percent',
'late_fee2_amount',
'late_fee2_percent',
'late_fee3_amount',
'late_fee3_percent',
]; ];
} }

View File

@ -123,11 +123,11 @@ class Activity extends Eloquent
$data = [ $data = [
'client' => $client ? link_to($client->getRoute(), $client->getDisplayName()) : null, 'client' => $client ? link_to($client->getRoute(), $client->getDisplayName()) : null,
'user' => $isSystem ? '<i>' . trans('texts.system') . '</i>' : $user->getDisplayName(), 'user' => $isSystem ? '<i>' . trans('texts.system') . '</i>' : e($user->getDisplayName()),
'invoice' => $invoice ? link_to($invoice->getRoute(), $invoice->getDisplayName()) : null, 'invoice' => $invoice ? link_to($invoice->getRoute(), $invoice->getDisplayName()) : null,
'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 ? e($client->getDisplayName()) : e($user->getDisplayName()),
'payment' => $payment ? $payment->transaction_reference : null, 'payment' => $payment ? e($payment->transaction_reference) : null,
'payment_amount' => $payment ? $account->formatMoney($payment->amount, $payment) : null, 'payment_amount' => $payment ? $account->formatMoney($payment->amount, $payment) : null,
'adjustment' => $this->adjustment ? $account->formatMoney($this->adjustment, $this) : null, 'adjustment' => $this->adjustment ? $account->formatMoney($this->adjustment, $this) : null,
'credit' => $credit ? $account->formatMoney($credit->amount, $client) : null, 'credit' => $credit ? $account->formatMoney($credit->amount, $client) : null,

View File

@ -2,6 +2,7 @@
namespace App\Models; namespace App\Models;
use Crypt;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
@ -33,6 +34,22 @@ class BankAccount extends EntityModel
return ENTITY_BANK_ACCOUNT; return ENTITY_BANK_ACCOUNT;
} }
/**
* @return mixed
*/
public function getUsername()
{
return Crypt::decrypt($this->username);
}
/**
* @param $config
*/
public function setUsername($value)
{
$this->username = Crypt::encrypt($value);
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/ */

View File

@ -54,54 +54,7 @@ class Client extends EntityModel
'public_notes', 'public_notes',
]; ];
/**
* @var string
*/
public static $fieldName = 'name';
/**
* @var string
*/
public static $fieldPhone = 'work_phone';
/**
* @var string
*/
public static $fieldAddress1 = 'address1';
/**
* @var string
*/
public static $fieldAddress2 = 'address2';
/**
* @var string
*/
public static $fieldCity = 'city';
/**
* @var string
*/
public static $fieldState = 'state';
/**
* @var string
*/
public static $fieldPostalCode = 'postal_code';
/**
* @var string
*/
public static $fieldNotes = 'notes';
/**
* @var string
*/
public static $fieldCountry = 'country';
/**
* @var string
*/
public static $fieldWebsite = 'website';
/**
* @var string
*/
public static $fieldVatNumber = 'vat_number';
/**
* @var string
*/
public static $fieldIdNumber = 'id_number';
/** /**
* @return array * @return array
@ -109,22 +62,28 @@ class Client extends EntityModel
public static function getImportColumns() public static function getImportColumns()
{ {
return [ return [
self::$fieldName, 'name',
self::$fieldPhone, 'work_phone',
self::$fieldAddress1, 'address1',
self::$fieldAddress2, 'address2',
self::$fieldCity, 'city',
self::$fieldState, 'state',
self::$fieldPostalCode, 'postal_code',
self::$fieldCountry, 'public_notes',
self::$fieldNotes, 'private_notes',
self::$fieldWebsite, 'country',
self::$fieldVatNumber, 'website',
self::$fieldIdNumber, 'currency',
Contact::$fieldFirstName, 'vat_number',
Contact::$fieldLastName, 'id_number',
Contact::$fieldPhone, 'custom1',
Contact::$fieldEmail, 'custom2',
'contact_first_name',
'contact_last_name',
'contact_phone',
'contact_email',
'contact_custom1',
'contact_custom2',
]; ];
} }
@ -134,10 +93,11 @@ class Client extends EntityModel
public static function getImportMap() public static function getImportMap()
{ {
return [ return [
'first' => 'first_name', 'first' => 'contact_first_name',
'last' => 'last_name', 'last' => 'contact_last_name',
'email' => 'email', 'email' => 'contact_email',
'mobile|phone' => 'phone', 'work|office' => 'work_phone',
'mobile|phone' => 'contact_phone',
'name|organization' => 'name', 'name|organization' => 'name',
'apt|street2|address2' => 'address2', 'apt|street2|address2' => 'address2',
'street|address|address1' => 'address1', 'street|address|address1' => 'address1',
@ -145,8 +105,10 @@ class Client extends EntityModel
'state|province' => 'state', 'state|province' => 'state',
'zip|postal|code' => 'postal_code', 'zip|postal|code' => 'postal_code',
'country' => 'country', 'country' => 'country',
'note' => 'notes', 'public' => 'public_notes',
'private|note' => 'private_notes',
'site|website' => 'website', 'site|website' => 'website',
'currency' => 'currency',
'vat' => 'vat_number', 'vat' => 'vat_number',
'number' => 'id_number', 'number' => 'id_number',
]; ];
@ -282,7 +244,9 @@ class Client extends EntityModel
{ {
$publicId = isset($data['public_id']) ? $data['public_id'] : (isset($data['id']) ? $data['id'] : false); $publicId = isset($data['public_id']) ? $data['public_id'] : (isset($data['id']) ? $data['id'] : false);
if ($publicId && $publicId != '-1') { // check if this client wasRecentlyCreated to ensure a new contact is
// always created even if the request includes a contact id
if (! $this->wasRecentlyCreated && $publicId && $publicId != '-1') {
$contact = Contact::scope($publicId)->firstOrFail(); $contact = Contact::scope($publicId)->firstOrFail();
} else { } else {
$contact = Contact::createNew(); $contact = Contact::createNew();

View File

@ -24,6 +24,7 @@ class Document extends EntityModel
protected $fillable = [ protected $fillable = [
'invoice_id', 'invoice_id',
'expense_id', 'expense_id',
'is_default',
]; ];
/** /**

View File

@ -115,6 +115,8 @@ class Invoice extends EntityModel implements BalanceAffecting
'terms', 'terms',
'product', 'product',
'quantity', 'quantity',
'tax1',
'tax2',
]; ];
} }
@ -135,6 +137,7 @@ class Invoice extends EntityModel implements BalanceAffecting
'notes' => 'notes', 'notes' => 'notes',
'product|item' => 'product', 'product|item' => 'product',
'quantity|qty' => 'quantity', 'quantity|qty' => 'quantity',
'tax' => 'tax1',
]; ];
} }
@ -305,6 +308,23 @@ class Invoice extends EntityModel implements BalanceAffecting
return $this->hasMany('App\Models\Document')->orderBy('id'); return $this->hasMany('App\Models\Document')->orderBy('id');
} }
/**
* @return mixed
*/
public function allDocuments()
{
$documents = $this->documents;
$documents = $documents->merge($this->account->defaultDocuments);
foreach ($this->expenses as $expense) {
if ($expense->invoice_documents) {
$documents = $documents->merge($expense->documents);
}
}
return $documents;
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/ */
@ -1319,7 +1339,7 @@ class Invoice extends EntityModel implements BalanceAffecting
/** /**
* @return int * @return int
*/ */
public function countDocuments() public function countDocuments($expenses = false)
{ {
$count = count($this->documents); $count = count($this->documents);
@ -1329,6 +1349,14 @@ class Invoice extends EntityModel implements BalanceAffecting
} }
} }
if ($expenses) {
foreach ($expenses as $expense) {
if ($expense->invoice_documents) {
$count += count($expense->documents);
}
}
}
return $count; return $count;
} }
@ -1337,7 +1365,11 @@ class Invoice extends EntityModel implements BalanceAffecting
*/ */
public function hasDocuments() public function hasDocuments()
{ {
if (count($this->documents)) { if ($this->documents->count()) {
return true;
}
if ($this->account->defaultDocuments->count()) {
return true; return true;
} }

View File

@ -34,7 +34,7 @@ class LookupModel extends Eloquent
if ($lookupAccount) { if ($lookupAccount) {
$data['lookup_account_id'] = $lookupAccount->id; $data['lookup_account_id'] = $lookupAccount->id;
} else { } else {
abort('Lookup account not found for ' . $accountKey); abort(500, 'Lookup account not found for ' . $accountKey);
} }
static::create($data); static::create($data);
@ -96,7 +96,7 @@ class LookupModel extends Eloquent
->first(); ->first();
} }
if (! $isFound) { if (! $isFound) {
abort("Looked up {$className} not found: {$field} => {$value}"); abort(500, "Looked up {$className} not found: {$field} => {$value}");
} }
Cache::put($key, $server, 120); Cache::put($key, $server, 120);

View File

@ -290,7 +290,7 @@ trait PresentsInvoice
'contact.custom_value1' => 'custom_contact_label1', 'contact.custom_value1' => 'custom_contact_label1',
'contact.custom_value2' => 'custom_contact_label2', 'contact.custom_value2' => 'custom_contact_label2',
] as $field => $property) { ] as $field => $property) {
$data[$field] = $this->$property ?: trans('texts.custom_field'); $data[$field] = e($this->$property) ?: trans('texts.custom_field');
} }
return $data; return $data;

View File

@ -4,6 +4,7 @@ namespace App\Models\Traits;
use App\Constants\Domain; use App\Constants\Domain;
use Utils; use Utils;
use HTMLUtils;
/** /**
* Class SendsEmails. * Class SendsEmails.
@ -36,7 +37,8 @@ trait SendsEmails
$value = $this->account_email_settings->$field; $value = $this->account_email_settings->$field;
if ($value) { if ($value) {
return preg_replace("/\r\n|\r|\n/", ' ', $value); $value = preg_replace("/\r\n|\r|\n/", ' ', $value);
return HTMLUtils::sanitizeHTML($value);
} }
} }
@ -94,7 +96,9 @@ trait SendsEmails
$template = preg_replace("/\r\n|\r|\n/", ' ', $template); $template = preg_replace("/\r\n|\r|\n/", ' ', $template);
// <br/> is causing page breaks with the email designs // <br/> is causing page breaks with the email designs
return str_replace('/>', ' />', $template); $template = str_replace('/>', ' />', $template);
return HTMLUtils::sanitizeHTML($template);
} }
/** /**
@ -125,9 +129,9 @@ trait SendsEmails
* *
* @return bool * @return bool
*/ */
public function getReminderDate($reminder) public function getReminderDate($reminder, $filterEnabled = true)
{ {
if (! $this->{"enable_reminder{$reminder}"}) { if ($filterEnabled && ! $this->{"enable_reminder{$reminder}"}) {
return false; return false;
} }
@ -142,10 +146,10 @@ trait SendsEmails
* *
* @return bool|string * @return bool|string
*/ */
public function getInvoiceReminder($invoice) public function getInvoiceReminder($invoice, $filterEnabled = true)
{ {
for ($i = 1; $i <= 3; $i++) { for ($i = 1; $i <= 3; $i++) {
if ($date = $this->getReminderDate($i)) { if ($date = $this->getReminderDate($i, $filterEnabled)) {
$field = $this->{"field_reminder{$i}"} == REMINDER_FIELD_DUE_DATE ? 'due_date' : 'invoice_date'; $field = $this->{"field_reminder{$i}"} == REMINDER_FIELD_DUE_DATE ? 'due_date' : 'invoice_date';
if ($invoice->$field == $date) { if ($invoice->$field == $date) {
return "reminder{$i}"; return "reminder{$i}";

View File

@ -0,0 +1,36 @@
<?php
namespace App\Models\Traits;
use Illuminate\Contracts\Database\ModelIdentifier;
/**
* Class SerialisesDeletedModels
* @see https://github.com/laravel/framework/issues/9347#issuecomment-165647596
*/
trait SerialisesDeletedModels
{
/**
* @param $value
* @return mixed
*/
protected function getRestoredPropertyValue($value)
{
if (!$value instanceof ModelIdentifier) {
return $value;
}
if (is_array($value->id)) {
return $this->restoreCollection($value);
}
$instance = new $value->class;
$query = $instance->newQuery()->useWritePdo();
if (property_exists($instance, 'forceDeleting')) {
return $query->withTrashed()->find($value->id);
}
return $query->findOrFail($value->id);
}
}

View File

@ -50,13 +50,13 @@ class CreditDatatable extends EntityDatatable
[ [
'public_notes', 'public_notes',
function ($model) { function ($model) {
return $model->public_notes; return e($model->public_notes);
}, },
], ],
[ [
'private_notes', 'private_notes',
function ($model) { function ($model) {
return $model->private_notes; return e($model->private_notes);
}, },
], ],
]; ];

View File

@ -84,7 +84,7 @@ class ExpenseDatatable extends EntityDatatable
[ [
'public_notes', 'public_notes',
function ($model) { function ($model) {
return $model->public_notes != null ? substr($model->public_notes, 0, 100) : ''; return $model->public_notes != null ? e(substr($model->public_notes, 0, 100)) : '';
}, },
], ],
[ [
@ -108,6 +108,15 @@ class ExpenseDatatable extends EntityDatatable
return Auth::user()->can('editByOwner', [ENTITY_EXPENSE, $model->user_id]); return Auth::user()->can('editByOwner', [ENTITY_EXPENSE, $model->user_id]);
}, },
], ],
[
trans("texts.clone_expense"),
function ($model) {
return URL::to("expenses/{$model->public_id}/clone");
},
function ($model) {
return Auth::user()->can('create', ENTITY_EXPENSE);
},
],
[ [
trans('texts.view_invoice'), trans('texts.view_invoice'),
function ($model) { function ($model) {

View File

@ -181,14 +181,18 @@ class InvoiceDatatable extends EntityDatatable
public function bulkActions() public function bulkActions()
{ {
$actions = parent::bulkActions(); $actions = [];
if ($this->entityType == ENTITY_INVOICE || $this->entityType == ENTITY_QUOTE) { if ($this->entityType == ENTITY_INVOICE || $this->entityType == ENTITY_QUOTE) {
$actions[] = \DropdownButton::DIVIDER; $actions[] = [
'label' => mtrans($this->entityType, 'download_' . $this->entityType),
'url' => 'javascript:submitForm_'.$this->entityType.'("download")',
];
$actions[] = [ $actions[] = [
'label' => mtrans($this->entityType, 'email_' . $this->entityType), 'label' => mtrans($this->entityType, 'email_' . $this->entityType),
'url' => 'javascript:submitForm_'.$this->entityType.'("emailInvoice")', 'url' => 'javascript:submitForm_'.$this->entityType.'("emailInvoice")',
]; ];
$actions[] = \DropdownButton::DIVIDER;
$actions[] = [ $actions[] = [
'label' => mtrans($this->entityType, 'mark_sent'), 'label' => mtrans($this->entityType, 'mark_sent'),
'url' => 'javascript:submitForm_'.$this->entityType.'("markSent")', 'url' => 'javascript:submitForm_'.$this->entityType.'("markSent")',
@ -202,6 +206,9 @@ class InvoiceDatatable extends EntityDatatable
]; ];
} }
$actions[] = \DropdownButton::DIVIDER;
$actions = array_merge($actions, parent::bulkActions());
return $actions; return $actions;
} }
} }

View File

@ -46,7 +46,7 @@ class PaymentDatatable extends EntityDatatable
[ [
'transaction_reference', 'transaction_reference',
function ($model) { function ($model) {
return $model->transaction_reference ? $model->transaction_reference : '<i>'.trans('texts.manual_entry').'</i>'; return $model->transaction_reference ? e($model->transaction_reference) : '<i>'.trans('texts.manual_entry').'</i>';
}, },
], ],
[ [

View File

@ -24,7 +24,7 @@ class ProductDatatable extends EntityDatatable
[ [
'notes', 'notes',
function ($model) { function ($model) {
return nl2br(Str::limit($model->notes, 100)); return e(nl2br(Str::limit($model->notes, 100)));
}, },
], ],
[ [

View File

@ -64,7 +64,7 @@ class RecurringInvoiceDatatable extends EntityDatatable
[ [
'private_notes', 'private_notes',
function ($model) { function ($model) {
return $model->private_notes; return e($model->private_notes);
}, },
], ],
[ [

View File

@ -55,7 +55,7 @@ class TaskDatatable extends EntityDatatable
[ [
'description', 'description',
function ($model) { function ($model) {
return $model->description; return e($model->description);
}, },
], ],
[ [

View File

@ -14,7 +14,7 @@ class UserDatatable extends EntityDatatable
[ [
'first_name', 'first_name',
function ($model) { function ($model) {
return $model->public_id ? link_to('users/'.$model->public_id.'/edit', $model->first_name.' '.$model->last_name)->toHtml() : ($model->first_name.' '.$model->last_name); return $model->public_id ? link_to('users/'.$model->public_id.'/edit', $model->first_name.' '.$model->last_name)->toHtml() : e($model->first_name.' '.$model->last_name);
}, },
], ],
[ [

View File

@ -101,35 +101,17 @@ class BaseTransformer extends TransformerAbstract
* *
* @return null * @return null
*/ */
public function getProductId($name) public function getProduct($data, $key, $field, $default = false)
{ {
$name = strtolower(trim($name)); $productKey = trim(strtolower($data->$key));
return isset($this->maps[ENTITY_PRODUCT][$name]) ? $this->maps[ENTITY_PRODUCT][$name] : null; if (! isset($this->maps['product'][$productKey])) {
return $default;
} }
/** $product = $this->maps['product'][$productKey];
* @param $name
*
* @return null
*/
public function getProductNotes($name)
{
$name = strtolower(trim($name));
return isset($this->maps['product_notes'][$name]) ? $this->maps['product_notes'][$name] : null; return $product->$field ?: $default;
}
/**
* @param $name
*
* @return null
*/
public function getProductCost($name)
{
$name = strtolower(trim($name));
return isset($this->maps['product_cost'][$name]) ? $this->maps['product_cost'][$name] : null;
} }
/** /**
@ -156,6 +138,30 @@ class BaseTransformer extends TransformerAbstract
return isset($this->maps['countries2'][$name]) ? $this->maps['countries2'][$name] : null; return isset($this->maps['countries2'][$name]) ? $this->maps['countries2'][$name] : null;
} }
/**
* @param $name
*
* @return null
*/
public function getTaxRate($name)
{
$name = strtolower(trim($name));
return isset($this->maps['tax_rates'][$name]) ? $this->maps['tax_rates'][$name] : 0;
}
/**
* @param $name
*
* @return null
*/
public function getTaxName($name)
{
$name = strtolower(trim($name));
return isset($this->maps['tax_names'][$name]) ? $this->maps['tax_names'][$name] : '';
}
/** /**
* @param $name * @param $name
* *

View File

@ -26,22 +26,29 @@ class ClientTransformer extends BaseTransformer
'name' => $this->getString($data, 'name'), 'name' => $this->getString($data, 'name'),
'work_phone' => $this->getString($data, 'work_phone'), 'work_phone' => $this->getString($data, 'work_phone'),
'address1' => $this->getString($data, 'address1'), 'address1' => $this->getString($data, 'address1'),
'address2' => $this->getString($data, 'address2'),
'city' => $this->getString($data, 'city'), 'city' => $this->getString($data, 'city'),
'state' => $this->getString($data, 'state'), 'state' => $this->getString($data, 'state'),
'postal_code' => $this->getString($data, 'postal_code'), 'postal_code' => $this->getString($data, 'postal_code'),
'private_notes' => $this->getString($data, 'notes'), 'public_notes' => $this->getString($data, 'public_notes'),
'private_notes' => $this->getString($data, 'private_notes'),
'website' => $this->getString($data, 'website'), 'website' => $this->getString($data, 'website'),
'vat_number' => $this->getString($data, 'vat_number'), 'vat_number' => $this->getString($data, 'vat_number'),
'id_number' => $this->getString($data, 'id_number'), 'id_number' => $this->getString($data, 'id_number'),
'custom_value1' => $this->getString($data, 'custom1'),
'custom_value2' => $this->getString($data, 'custom2'),
'contacts' => [ 'contacts' => [
[ [
'first_name' => $this->getString($data, 'first_name'), 'first_name' => $this->getString($data, 'contact_first_name'),
'last_name' => $this->getString($data, 'last_name'), 'last_name' => $this->getString($data, 'contact_last_name'),
'email' => $this->getString($data, 'email'), 'email' => $this->getString($data, 'contact_email'),
'phone' => $this->getString($data, 'phone'), 'phone' => $this->getString($data, 'contact_phone'),
'custom_value1' => $this->getString($data, 'contact_custom1'),
'custom_value2' => $this->getString($data, 'contact_custom2'),
], ],
], ],
'country_id' => isset($data->country) ? $this->getCountryId($data->country) : null, 'country_id' => isset($data->country) ? $this->getCountryId($data->country) : null,
'currency_code' => $this->getString($data, 'currency'),
]; ];
}); });
} }

View File

@ -38,9 +38,13 @@ class InvoiceTransformer extends BaseTransformer
'invoice_items' => [ 'invoice_items' => [
[ [
'product_key' => $this->getString($data, 'product'), 'product_key' => $this->getString($data, 'product'),
'notes' => $this->getString($data, 'notes') ?: $this->getProductNotes($this->getString($data, 'product')), 'notes' => $this->getString($data, 'notes') ?: $this->getProduct($data, 'product', 'notes', ''),
'cost' => $this->getFloat($data, 'amount') ?: $this->getProductCost($this->getString($data, 'product')), 'cost' => $this->getFloat($data, 'amount') ?: $this->getProduct($data, 'product', 'cost', 0),
'qty' => $this->getFloat($data, 'quantity') ?: 1, 'qty' => $this->getFloat($data, 'quantity') ?: 1,
'tax_name1' => $this->getTaxName($this->getString($data, 'tax1')),
'tax_rate1' => $this->getTaxRate($this->getString($data, 'tax1')),
'tax_name2' => $this->getTaxName($this->getString($data, 'tax2')),
'tax_rate2' => $this->getTaxRate($this->getString($data, 'tax2')),
], ],
], ],
]; ];

View File

@ -23,6 +23,7 @@ class ProductTransformer extends BaseTransformer
return new Item($data, function ($data) { return new Item($data, function ($data) {
return [ return [
'public_id' => $this->getProduct($data, 'product_key', 'public_id'),
'product_key' => $this->getString($data, 'product_key'), 'product_key' => $this->getString($data, 'product_key'),
'notes' => $this->getString($data, 'notes'), 'notes' => $this->getString($data, 'notes'),
'cost' => $this->getFloat($data, 'cost'), 'cost' => $this->getFloat($data, 'cost'),

View File

@ -68,14 +68,7 @@ class ContactMailer extends Mailer
$documentStrings = []; $documentStrings = [];
if ($account->document_email_attachment && $invoice->hasDocuments()) { if ($account->document_email_attachment && $invoice->hasDocuments()) {
$documents = $invoice->documents; $documents = $invoice->allDocuments();
foreach ($invoice->expenses as $expense) {
if ($expense->invoice_documents) {
$documents = $documents->merge($expense->documents);
}
}
$documents = $documents->sortBy('size'); $documents = $documents->sortBy('size');
$size = 0; $size = 0;
@ -238,17 +231,25 @@ class ContactMailer extends Mailer
/** /**
* @param Payment $payment * @param Payment $payment
*/ */
public function sendPaymentConfirmation(Payment $payment) public function sendPaymentConfirmation(Payment $payment, $refunded = 0)
{ {
$account = $payment->account; $account = $payment->account;
$client = $payment->client; $client = $payment->client;
$account->loadLocalizationSettings($client); $account->loadLocalizationSettings($client);
$invoice = $payment->invoice; $invoice = $payment->invoice;
$accountName = $account->getDisplayName(); $accountName = $account->getDisplayName();
$emailTemplate = $account->getEmailTemplate(ENTITY_PAYMENT);
if ($refunded > 0) {
$emailSubject = trans('texts.refund_subject');
$emailTemplate = trans('texts.refund_body', [
'amount' => $account->formatMoney($refunded, $client),
'invoice_number' => $invoice->invoice_number,
]);
} else {
$emailSubject = $invoice->account->getEmailSubject(ENTITY_PAYMENT); $emailSubject = $invoice->account->getEmailSubject(ENTITY_PAYMENT);
$emailTemplate = $account->getEmailTemplate(ENTITY_PAYMENT);
}
if ($payment->invitation) { if ($payment->invitation) {
$user = $payment->invitation->user; $user = $payment->invitation->user;
@ -277,9 +278,10 @@ class ContactMailer extends Mailer
'entityType' => ENTITY_INVOICE, 'entityType' => ENTITY_INVOICE,
'bccEmail' => $account->getBccEmail(), 'bccEmail' => $account->getBccEmail(),
'fromEmail' => $account->getFromEmail(), 'fromEmail' => $account->getFromEmail(),
'isRefund' => $refunded > 0,
]; ];
if ($account->attachPDF()) { if (! $refunded && $account->attachPDF()) {
$data['pdfString'] = $invoice->getPDFString(); $data['pdfString'] = $invoice->getPDFString();
$data['pdfFileName'] = $invoice->getFileName(); $data['pdfFileName'] = $invoice->getFileName();
} }

View File

@ -119,14 +119,17 @@ class UserMailer extends Mailer
/** /**
* @param Invitation $invitation * @param Invitation $invitation
*/ */
public function sendMessage($user, $subject, $message, $invoice = false) public function sendMessage($user, $subject, $message, $data = false)
{ {
if (! $user->email) { if (! $user->email) {
return; return;
} }
$invoice = $data && isset($data['invoice']) ? $data['invoice'] : false;
$view = 'user_message'; $view = 'user_message';
$data = [
$data = $data ?: [];
$data += [
'userName' => $user->getDisplayName(), 'userName' => $user->getDisplayName(),
'primaryMessage' => $subject, 'primaryMessage' => $subject,
'secondaryMessage' => $message, 'secondaryMessage' => $message,

View File

@ -119,6 +119,18 @@ class StripePaymentDriver extends BasePaymentDriver
$data = $this->paymentDetails(); $data = $this->paymentDetails();
$data['description'] = $client->getDisplayName(); $data['description'] = $client->getDisplayName();
// if a customer already exists link the token to it
if ($customer = $this->customer()) {
$data['customerReference'] = $customer->token;
// otherwise create a new customer
} else {
$response = $this->gateway()->createCustomer([
'description' => $client->getDisplayName(),
'email' => $this->contact()->email,
])->send();
$data['customerReference'] = $response->getCustomerReference();
}
if (! empty($data['plaidPublicToken'])) { if (! empty($data['plaidPublicToken'])) {
$plaidResult = $this->getPlaidToken($data['plaidPublicToken'], $data['plaidAccountId']); $plaidResult = $this->getPlaidToken($data['plaidPublicToken'], $data['plaidAccountId']);
unset($data['plaidPublicToken']); unset($data['plaidPublicToken']);
@ -126,11 +138,6 @@ class StripePaymentDriver extends BasePaymentDriver
$data['token'] = $plaidResult['stripe_bank_account_token']; $data['token'] = $plaidResult['stripe_bank_account_token'];
} }
// if a customer already exists link the token to it
if ($customer = $this->customer()) {
$data['customerReference'] = $customer->token;
}
$tokenResponse = $this->gateway() $tokenResponse = $this->gateway()
->createCard($data) ->createCard($data)
->send(); ->send();
@ -146,7 +153,11 @@ class StripePaymentDriver extends BasePaymentDriver
public function creatingCustomer($customer) public function creatingCustomer($customer)
{ {
if (isset($this->tokenResponse['customer'])) {
$customer->token = $this->tokenResponse['customer'];
} else {
$customer->token = $this->tokenResponse['id']; $customer->token = $this->tokenResponse['id'];
}
return $customer; return $customer;
} }

View File

@ -22,6 +22,28 @@ class AccountPresenter extends Presenter
return $this->entity->name ?: trans('texts.untitled_account'); return $this->entity->name ?: trans('texts.untitled_account');
} }
/**
* @return string
*/
public function address()
{
$account = $this->entity;
$str = $account->address1 ?: '';
if ($account->address2 && $str) {
$str .= ', ';
}
$str .= $account->address2;
if ($account->getCityState() && $str) {
$str .= ' - ';
}
return $str . $account->getCityState();
}
/** /**
* @return string * @return string
*/ */
@ -144,7 +166,7 @@ class AccountPresenter extends Presenter
if ($rate->is_inclusive) { if ($rate->is_inclusive) {
$name .= ' - ' . trans('texts.inclusive'); $name .= ' - ' . trans('texts.inclusive');
} }
$options[($rate->is_inclusive ? '1 ' : '0 ') . $rate->rate . ' ' . $rate->name] = $name; $options[($rate->is_inclusive ? '1 ' : '0 ') . $rate->rate . ' ' . $rate->name] = e($name);
} }
return $options; return $options;

View File

@ -33,7 +33,9 @@ class EntityPresenter extends Presenter
{ {
$class = $text = ''; $class = $text = '';
if ($this->entity->is_deleted) { if (! $this->entity->id) {
return '';
} elseif ($this->entity->is_deleted) {
$class = 'danger'; $class = 'danger';
$label = trans('texts.deleted'); $label = trans('texts.deleted');
} elseif ($this->entity->trashed()) { } elseif ($this->entity->trashed()) {

View File

@ -285,7 +285,11 @@ class InvoicePresenter extends EntityPresenter
$label = trans('texts.fee'); $label = trans('texts.fee');
} }
return ' - ' . $fee . ' ' . $label; $label = ' - ' . $fee . ' ' . $label;
$label .= '&nbsp;&nbsp; <i class="fa fa-info-circle" data-toggle="tooltip" data-placement="bottom" title="' . trans('texts.fee_help') . '"></i>';
return $label;
} }
public function multiAccountLink() public function multiAccountLink()

View File

@ -52,9 +52,8 @@ class AbstractReport
$this->totals[$currencyId][$dimension][$field] += $value; $this->totals[$currencyId][$dimension][$field] += $value;
} }
public function tableHeader() public function tableHeaderArray() {
{ $columns_labeled = [];
$str = '';
foreach ($this->columns as $key => $val) { foreach ($this->columns as $key => $val) {
if (is_array($val)) { if (is_array($val)) {
@ -75,9 +74,21 @@ class AbstractReport
$class = count($class) ? implode(' ', $class) : 'group-false'; $class = count($class) ? implode(' ', $class) : 'group-false';
$label = trans("texts.{$field}"); $label = trans("texts.{$field}");
$str .= "<th class=\"{$class}\">{$label}</th>";
$columns_labeled[] = ['label' => $label, 'class' => $class, 'key' => $field];
} }
return $columns_labeled;
}
public function tableHeader()
{
$columns_labeled = $this->tableHeaderArray();
$str = '';
foreach ($columns_labeled as $field => $attr)
$str .= "<th class=\"{$attr['class']}\">{$attr['label']}</th>";
return $str; return $str;
} }

View File

@ -662,6 +662,18 @@ class AccountRepository
return Account::whereRaw('enable_reminder1 = 1 OR enable_reminder2 = 1 OR enable_reminder3 = 1')->get(); return Account::whereRaw('enable_reminder1 = 1 OR enable_reminder2 = 1 OR enable_reminder3 = 1')->get();
} }
public function findWithFees()
{
return Account::whereHas('account_email_settings', function($query) {
$query->where('late_fee1_amount', '>', 0)
->orWhere('late_fee1_percent', '>', 0)
->orWhere('late_fee2_amount', '>', 0)
->orWhere('late_fee2_percent', '>', 0)
->orWhere('late_fee3_amount', '>', 0)
->orWhere('late_fee3_percent', '>', 0);
})->get();
}
public function createTokens($user, $name) public function createTokens($user, $name)
{ {
$name = trim($name) ?: 'TOKEN'; $name = trim($name) ?: 'TOKEN';

View File

@ -89,7 +89,7 @@ class CreditRepository extends BaseRepository
return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id);
}) })
->addColumn('public_notes', function ($model) { ->addColumn('public_notes', function ($model) {
return $model->public_notes; return e($model->public_notes);
}) })
->make(); ->make();

View File

@ -290,6 +290,9 @@ class InvoiceRepository extends BaseRepository
'invoices.invoice_date', 'invoices.invoice_date',
'invoices.balance as balance', 'invoices.balance as balance',
'invoices.due_date', 'invoices.due_date',
'invoices.invoice_status_id',
'invoices.due_date',
'invoices.quote_invoice_id',
'clients.public_id as client_public_id', 'clients.public_id as client_public_id',
DB::raw("COALESCE(NULLIF(clients.name,''), NULLIF(CONCAT(contacts.first_name, ' ', contacts.last_name),''), NULLIF(contacts.email,'')) client_name"), DB::raw("COALESCE(NULLIF(clients.name,''), NULLIF(CONCAT(contacts.first_name, ' ', contacts.last_name),''), NULLIF(contacts.email,'')) client_name"),
'invoices.public_id', 'invoices.public_id',
@ -324,6 +327,34 @@ class InvoiceRepository extends BaseRepository
return $table->addColumn('due_date', function ($model) { return $table->addColumn('due_date', function ($model) {
return Utils::fromSqlDate($model->due_date); return Utils::fromSqlDate($model->due_date);
}) })
->addColumn('status', function ($model) use ($entityType) {
if ($model->invoice_status_id == INVOICE_STATUS_PAID) {
$label = trans('texts.status_paid');
$class = 'success';
} elseif ($model->invoice_status_id == INVOICE_STATUS_PARTIAL) {
$label = trans('texts.status_partial');
$class = 'info';
} elseif (Invoice::calcIsOverdue($model->balance, $model->due_date)) {
$class = 'danger';
if ($entityType == ENTITY_INVOICE) {
$label = trans('texts.overdue');
} else {
$label = trans('texts.expired');
}
} elseif ($entityType == ENTITY_QUOTE && ($model->invoice_status_id >= INVOICE_STATUS_APPROVED || $model->quote_invoice_id)) {
$label = trans('texts.status_approved');
$class = 'success';
} else {
$class = 'default';
if ($entityType == ENTITY_INVOICE) {
$label = trans('texts.unpaid');
} else {
$label = trans('texts.pending');
}
}
return "<h4><div class=\"label label-{$class}\">$label</div></h4>";
})
->make(); ->make();
} }
@ -655,7 +686,7 @@ class InvoiceRepository extends BaseRepository
if ($account->update_products if ($account->update_products
&& ! $invoice->has_tasks && ! $invoice->has_tasks
&& ! $invoice->has_expenses && ! $invoice->has_expenses
&& $productKey != trans('texts.surcharge') && ! in_array($productKey, Utils::trans(['surcharge', 'discount', 'fee']))
) { ) {
$product = Product::findProductByKey($productKey); $product = Product::findProductByKey($productKey);
if (! $product) { if (! $product) {
@ -1096,19 +1127,24 @@ class InvoiceRepository extends BaseRepository
* *
* @return mixed * @return mixed
*/ */
public function findNeedingReminding(Account $account) public function findNeedingReminding(Account $account, $filterEnabled = true)
{ {
$dates = []; $dates = [];
for ($i = 1; $i <= 3; $i++) { for ($i = 1; $i <= 3; $i++) {
if ($date = $account->getReminderDate($i)) { if ($date = $account->getReminderDate($i, $filterEnabled)) {
$field = $account->{"field_reminder{$i}"} == REMINDER_FIELD_DUE_DATE ? 'due_date' : 'invoice_date'; $field = $account->{"field_reminder{$i}"} == REMINDER_FIELD_DUE_DATE ? 'due_date' : 'invoice_date';
$dates[] = "$field = '$date'"; $dates[] = "$field = '$date'";
} }
} }
if (! count($dates)) {
return [];
}
$sql = implode(' OR ', $dates); $sql = implode(' OR ', $dates);
$invoices = Invoice::invoiceType(INVOICE_TYPE_STANDARD) $invoices = Invoice::invoiceType(INVOICE_TYPE_STANDARD)
->with('invoice_items')
->whereAccountId($account->id) ->whereAccountId($account->id)
->where('balance', '>', 0) ->where('balance', '>', 0)
->where('is_recurring', '=', false) ->where('is_recurring', '=', false)
@ -1137,6 +1173,32 @@ class InvoiceRepository extends BaseRepository
} }
} }
public function setLateFee($invoice, $amount, $percent)
{
if ($amount <= 0 && $percent <= 0) {
return false;
}
$account = $invoice->account;
$data = $invoice->toArray();
$fee = $amount;
if ($invoice->amount > 0) {
$fee += round($invoice->amount * $percent / 100, 2);
}
$item = [];
$item['product_key'] = trans('texts.fee');
$item['notes'] = trans('texts.late_fee_added', ['date' => $account->formatDate('now')]);
$item['qty'] = 1;
$item['cost'] = $fee;
$item['invoice_item_type_id'] = INVOICE_ITEM_TYPE_LATE_FEE;
$data['invoice_items'][] = $item;
$this->save($data, $invoice);
}
public function setGatewayFee($invoice, $gatewayTypeId) public function setGatewayFee($invoice, $gatewayTypeId)
{ {
$account = $invoice->account; $account = $invoice->account;

View File

@ -17,6 +17,7 @@ class ProductRepository extends BaseRepository
{ {
return Product::scope() return Product::scope()
->withTrashed() ->withTrashed()
->where('is_deleted', '=', false)
->get(); ->get();
} }
@ -54,7 +55,7 @@ class ProductRepository extends BaseRepository
if ($product) { if ($product) {
// do nothing // do nothing
} elseif ($publicId) { } elseif ($publicId) {
$product = Product::scope($publicId)->firstOrFail(); $product = Product::scope($publicId)->withArchived()->firstOrFail();
\Log::warning('Entity not set in product repo save'); \Log::warning('Entity not set in product repo save');
} else { } else {
$product = Product::createNew(); $product = Product::createNew();

View File

@ -13,6 +13,11 @@ class TaxRateRepository extends BaseRepository
return 'App\Models\TaxRate'; return 'App\Models\TaxRate';
} }
public function all()
{
return TaxRate::scope()->get();
}
public function find($accountId) public function find($accountId)
{ {
return DB::table('tax_rates') return DB::table('tax_rates')

View File

@ -78,7 +78,7 @@ class DatatableService
$dropdown_contents = ''; $dropdown_contents = '';
$lastIsDivider = false; $lastIsDivider = false;
if (! $model->deleted_at || $model->deleted_at == '0000-00-00') { if (! property_exists($model, 'is_deleted') || ! $model->is_deleted) {
foreach ($datatable->actions() as $action) { foreach ($datatable->actions() as $action) {
if (count($action)) { if (count($action)) {
// if show function isn't set default to true // if show function isn't set default to true
@ -119,11 +119,15 @@ class DatatableService
$dropdown_contents .= '<li class="divider"></li>'; $dropdown_contents .= '<li class="divider"></li>';
} }
if (! $model->deleted_at || $model->deleted_at == '0000-00-00') {
if (($datatable->entityType != ENTITY_USER || $model->public_id) && $can_edit) { if (($datatable->entityType != ENTITY_USER || $model->public_id) && $can_edit) {
$dropdown_contents .= "<li><a href=\"javascript:submitForm_{$datatable->entityType}('archive', {$model->public_id})\">" $dropdown_contents .= "<li><a href=\"javascript:submitForm_{$datatable->entityType}('archive', {$model->public_id})\">"
. mtrans($datatable->entityType, "archive_{$datatable->entityType}") . '</a></li>'; . mtrans($datatable->entityType, "archive_{$datatable->entityType}") . '</a></li>';
} }
} elseif ($can_edit) { }
}
if ($model->deleted_at && $model->deleted_at != '0000-00-00' && $can_edit) {
$dropdown_contents .= "<li><a href=\"javascript:submitForm_{$datatable->entityType}('restore', {$model->public_id})\">" $dropdown_contents .= "<li><a href=\"javascript:submitForm_{$datatable->entityType}('restore', {$model->public_id})\">"
. mtrans($datatable->entityType, "restore_{$datatable->entityType}") . '</a></li>'; . mtrans($datatable->entityType, "restore_{$datatable->entityType}") . '</a></li>';
} }

View File

@ -19,6 +19,7 @@ use App\Ninja\Repositories\InvoiceRepository;
use App\Ninja\Repositories\PaymentRepository; use App\Ninja\Repositories\PaymentRepository;
use App\Ninja\Repositories\ProductRepository; use App\Ninja\Repositories\ProductRepository;
use App\Ninja\Repositories\VendorRepository; use App\Ninja\Repositories\VendorRepository;
use App\Ninja\Repositories\TaxRateRepository;
use App\Ninja\Serializers\ArraySerializer; use App\Ninja\Serializers\ArraySerializer;
use Auth; use Auth;
use Cache; use Cache;
@ -126,7 +127,8 @@ class ImportService
ProductRepository $productRepo, ProductRepository $productRepo,
ExpenseRepository $expenseRepo, ExpenseRepository $expenseRepo,
VendorRepository $vendorRepo, VendorRepository $vendorRepo,
ExpenseCategoryRepository $expenseCategoryRepo ExpenseCategoryRepository $expenseCategoryRepo,
TaxRateRepository $taxRateRepository
) { ) {
$this->fractal = $manager; $this->fractal = $manager;
$this->fractal->setSerializer(new ArraySerializer()); $this->fractal->setSerializer(new ArraySerializer());
@ -139,6 +141,7 @@ class ImportService
$this->expenseRepo = $expenseRepo; $this->expenseRepo = $expenseRepo;
$this->vendorRepo = $vendorRepo; $this->vendorRepo = $vendorRepo;
$this->expenseCategoryRepo = $expenseCategoryRepo; $this->expenseCategoryRepo = $expenseCategoryRepo;
$this->taxRateRepository = $taxRateRepository;
} }
/** /**
@ -849,6 +852,8 @@ class ImportService
'invoice_ids' => [], 'invoice_ids' => [],
'vendors' => [], 'vendors' => [],
'expense_categories' => [], 'expense_categories' => [],
'tax_rates' => [],
'tax_names' => [],
]; ];
$clients = $this->clientRepo->all(); $clients = $this->clientRepo->all();
@ -886,6 +891,13 @@ class ImportService
foreach ($expenseCaegories as $category) { foreach ($expenseCaegories as $category) {
$this->addExpenseCategoryToMaps($category); $this->addExpenseCategoryToMaps($category);
} }
$taxRates = $this->taxRateRepository->all();
foreach ($taxRates as $taxRate) {
$name = trim(strtolower($taxRate->name));
$this->maps['tax_rates'][$name] = $taxRate->rate;
$this->maps['tax_names'][$name] = $taxRate->name;
}
} }
/** /**
@ -921,9 +933,7 @@ class ImportService
private function addProductToMaps(Product $product) private function addProductToMaps(Product $product)
{ {
if ($key = strtolower(trim($product->product_key))) { if ($key = strtolower(trim($product->product_key))) {
$this->maps['product'][$key] = $product->id; $this->maps['product'][$key] = $product;
$this->maps['product_notes'][$key] = $product->notes;
$this->maps['product_cost'][$key] = $product->cost;
} }
} }

View File

@ -9,6 +9,7 @@ use App\Models\Invoice;
use App\Ninja\Datatables\InvoiceDatatable; use App\Ninja\Datatables\InvoiceDatatable;
use App\Ninja\Repositories\ClientRepository; use App\Ninja\Repositories\ClientRepository;
use App\Ninja\Repositories\InvoiceRepository; use App\Ninja\Repositories\InvoiceRepository;
use App\Jobs\DownloadInvoices;
use Auth; use Auth;
use Utils; use Utils;
@ -54,6 +55,23 @@ class InvoiceService extends BaseService
return $this->invoiceRepo; return $this->invoiceRepo;
} }
/**
* @param $ids
* @param $action
*
* @return int
*/
public function bulk($ids, $action)
{
if ($action == 'download') {
$invoices = $this->getRepo()->findByPublicIdsWithTrashed($ids);
dispatch(new DownloadInvoices(Auth::user(), $invoices));
return count($invoices);
} else {
return parent::bulk($ids, $action);
}
}
/** /**
* @param array $data * @param array $data
* @param Invoice|null $invoice * @param Invoice|null $invoice

View File

@ -140,7 +140,9 @@ class PaymentService extends BaseService
$subject = trans('texts.auto_bill_failed', ['invoice_number' => $invoice->invoice_number]); $subject = trans('texts.auto_bill_failed', ['invoice_number' => $invoice->invoice_number]);
$message = sprintf('%s: %s', ucwords($paymentDriver->providerName()), $exception->getMessage()); $message = sprintf('%s: %s', ucwords($paymentDriver->providerName()), $exception->getMessage());
$mailer = app('App\Ninja\Mailers\UserMailer'); $mailer = app('App\Ninja\Mailers\UserMailer');
$mailer->sendMessage($invoice->user, $subject, $message, $invoice); $mailer->sendMessage($invoice->user, $subject, $message, [
'invoice' => $invoice
]);
} }
return false; return false;
@ -178,17 +180,28 @@ class PaymentService extends BaseService
foreach ($payments as $payment) { foreach ($payments as $payment) {
if (Auth::user()->can('edit', $payment)) { if (Auth::user()->can('edit', $payment)) {
$amount = ! empty($params['refund_amount']) ? floatval($params['refund_amount']) : null; $amount = ! empty($params['refund_amount']) ? floatval($params['refund_amount']) : null;
$sendEmail = ! empty($params['refund_email']) ? boolval($params['refund_email']) : false;
$paymentDriver = false; $paymentDriver = false;
$refunded = false;
if ($accountGateway = $payment->account_gateway) { if ($accountGateway = $payment->account_gateway) {
$paymentDriver = $accountGateway->paymentDriver(); $paymentDriver = $accountGateway->paymentDriver();
} }
if ($paymentDriver && $paymentDriver->canRefundPayments) { if ($paymentDriver && $paymentDriver->canRefundPayments) {
if ($paymentDriver->refundPayment($payment, $amount)) { if ($paymentDriver->refundPayment($payment, $amount)) {
$successful++; $successful++;
$refunded = true;
} }
} else { } else {
$payment->recordRefund($amount); $payment->recordRefund($amount);
$successful++; $successful++;
$refunded = true;
}
if ($refunded && $sendEmail) {
$mailer = app('App\Ninja\Mailers\ContactMailer');
$mailer->sendPaymentConfirmation($payment, $amount);
} }
} }
} }

View File

@ -34,16 +34,9 @@ class TemplateService
if ($account->hasFeature(FEATURE_DOCUMENTS) && $invoice->hasDocuments()) { if ($account->hasFeature(FEATURE_DOCUMENTS) && $invoice->hasDocuments()) {
$documentsHTML .= trans('texts.email_documents_header').'<ul>'; $documentsHTML .= trans('texts.email_documents_header').'<ul>';
foreach ($invoice->documents as $document) { foreach ($invoice->allDocuments() as $document) {
$documentsHTML .= '<li><a href="'.HTML::entities($document->getClientUrl($invitation)).'">'.HTML::entities($document->name).'</a></li>'; $documentsHTML .= '<li><a href="'.HTML::entities($document->getClientUrl($invitation)).'">'.HTML::entities($document->name).'</a></li>';
} }
foreach ($invoice->expenses as $expense) {
if ($expense->invoice_documents) {
foreach ($expense->documents as $document) {
$documentsHTML .= '<li><a href="'.HTML::entities($document->getClientUrl($invitation)).'">'.HTML::entities($document->name).'</a></li>';
}
}
}
$documentsHTML .= '</ul>'; $documentsHTML .= '</ul>';
} }

View File

@ -16,10 +16,10 @@
"bootstrap-datepicker": "1.4.0", "bootstrap-datepicker": "1.4.0",
"typeahead.js": "0.11.1", "typeahead.js": "0.11.1",
"accounting": "0.3.2", "accounting": "0.3.2",
"spectrum": "1.3.4", "spectrum": "1.8.0",
"d3": "3.4.11", "d3": "3.4.11",
"handsontable": "*", "handsontable": "*",
"pdfmake": "0.1.24", "pdfmake": "0.1.31",
"moment": "*", "moment": "*",
"jsoneditor": "*", "jsoneditor": "*",
"moment-timezone": "~0.4.0", "moment-timezone": "~0.4.0",

View File

@ -66,6 +66,7 @@
"meebio/omnipay-creditcall": "dev-master", "meebio/omnipay-creditcall": "dev-master",
"meebio/omnipay-secure-trading": "dev-master", "meebio/omnipay-secure-trading": "dev-master",
"mfauveau/omnipay-pacnet": "~2.0", "mfauveau/omnipay-pacnet": "~2.0",
"mpdf/mpdf": "^6.1",
"nwidart/laravel-modules": "^1.14", "nwidart/laravel-modules": "^1.14",
"omnipay/2checkout": "dev-master#e9c079c2dde0d7ba461903b3b7bd5caf6dee1248", "omnipay/2checkout": "dev-master#e9c079c2dde0d7ba461903b3b7bd5caf6dee1248",
"omnipay/bitpay": "dev-master", "omnipay/bitpay": "dev-master",

120
composer.lock generated
View File

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "e8611674b74a220909d4c70784f2e227", "hash": "f57537fe1dab41aac024b12e4a284570",
"content-hash": "8d418324fd6e8b5af5c7b2058e31d898", "content-hash": "9d0ce024f2c50440bf896ecc2a37350f",
"packages": [ "packages": [
{ {
"name": "agmscode/omnipay-agms", "name": "agmscode/omnipay-agms",
@ -68,12 +68,12 @@
"version": "dev-master", "version": "dev-master",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/alfaproject/omnipay-skrill.git", "url": "https://github.com/xcaliber-tech/omnipay-skrill.git",
"reference": "41a7a03c5b90d496720e288bebc157d898837ccd" "reference": "41a7a03c5b90d496720e288bebc157d898837ccd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/alfaproject/omnipay-skrill/zipball/41a7a03c5b90d496720e288bebc157d898837ccd", "url": "https://api.github.com/repos/xcaliber-tech/omnipay-skrill/zipball/41a7a03c5b90d496720e288bebc157d898837ccd",
"reference": "41a7a03c5b90d496720e288bebc157d898837ccd", "reference": "41a7a03c5b90d496720e288bebc157d898837ccd",
"shasum": "" "shasum": ""
}, },
@ -4723,6 +4723,57 @@
], ],
"time": "2017-06-19 01:22:40" "time": "2017-06-19 01:22:40"
}, },
{
"name": "mpdf/mpdf",
"version": "v6.1.3",
"source": {
"type": "git",
"url": "https://github.com/mpdf/mpdf.git",
"reference": "7f138bf7508eac895ac2c13d2509b056ac7e7e97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mpdf/mpdf/zipball/7f138bf7508eac895ac2c13d2509b056ac7e7e97",
"reference": "7f138bf7508eac895ac2c13d2509b056ac7e7e97",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": ">=5.4.0",
"setasign/fpdi": "1.6.*"
},
"require-dev": {
"phpunit/phpunit": "^4.7"
},
"suggest": {
"ext-zlib": "Needed for compression of embedded resources, such as fonts"
},
"type": "library",
"autoload": {
"classmap": [
"mpdf.php",
"classes"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0"
],
"authors": [
{
"name": "Ian Back",
"role": "Developer"
}
],
"description": "A PHP class to generate PDF files from HTML with Unicode/UTF-8 and CJK support",
"homepage": "http://mpdf.github.io",
"keywords": [
"pdf",
"php",
"utf-8"
],
"time": "2016-12-12 10:42:18"
},
{ {
"name": "mtdowling/cron-expression", "name": "mtdowling/cron-expression",
"version": "v1.2.0", "version": "v1.2.0",
@ -7537,6 +7588,55 @@
], ],
"time": "2017-06-14 03:57:53" "time": "2017-06-14 03:57:53"
}, },
{
"name": "setasign/fpdi",
"version": "1.6.2",
"source": {
"type": "git",
"url": "https://github.com/Setasign/FPDI.git",
"reference": "a6ad58897a6d97cc2d2cd2adaeda343b25a368ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Setasign/FPDI/zipball/a6ad58897a6d97cc2d2cd2adaeda343b25a368ea",
"reference": "a6ad58897a6d97cc2d2cd2adaeda343b25a368ea",
"shasum": ""
},
"suggest": {
"setasign/fpdf": "FPDI will extend this class but as it is also possible to use \"tecnickcom/tcpdf\" as an alternative there's no fixed dependency configured.",
"setasign/fpdi-fpdf": "Use this package to automatically evaluate dependencies to FPDF.",
"setasign/fpdi-tcpdf": "Use this package to automatically evaluate dependencies to TCPDF."
},
"type": "library",
"autoload": {
"classmap": [
"filters/",
"fpdi.php",
"fpdf_tpl.php",
"fpdi_pdf_parser.php",
"pdf_context.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jan Slabon",
"email": "jan.slabon@setasign.com",
"homepage": "https://www.setasign.com"
}
],
"description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.",
"homepage": "https://www.setasign.com/fpdi",
"keywords": [
"fpdf",
"fpdi",
"pdf"
],
"time": "2017-05-11 14:25:49"
},
{ {
"name": "simshaun/recurr", "name": "simshaun/recurr",
"version": "dev-master", "version": "dev-master",
@ -8044,7 +8144,7 @@
}, },
{ {
"name": "symfony/event-dispatcher", "name": "symfony/event-dispatcher",
"version": "v2.8.24", "version": "v2.8.26",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/event-dispatcher.git", "url": "https://github.com/symfony/event-dispatcher.git",
@ -8202,16 +8302,16 @@
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v2.8.24", "version": "v2.8.26",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "2b592ca5fe2ad7ee8a92d409d2b830277ad58231" "reference": "9ff3a0b3756ace2e3da7dded37e920ee776faa4e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/2b592ca5fe2ad7ee8a92d409d2b830277ad58231", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9ff3a0b3756ace2e3da7dded37e920ee776faa4e",
"reference": "2b592ca5fe2ad7ee8a92d409d2b830277ad58231", "reference": "9ff3a0b3756ace2e3da7dded37e920ee776faa4e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8253,7 +8353,7 @@
], ],
"description": "Symfony HttpFoundation Component", "description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2017-06-20 23:27:56" "time": "2017-07-17 14:02:19"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",

View File

@ -1,5 +1,23 @@
<?php <?php
//https://github.com/PHPOffice/PHPExcel/issues/556#issuecomment-216722159
switch (PHP_OS) {
case 'WINNT':
PHPExcel_Shared_Font::setTrueTypeFontPath('C:/Windows/Fonts/');
PHPExcel_Shared_Font::setAutoSizeMethod(PHPExcel_Shared_Font::AUTOSIZE_METHOD_EXACT);
break;
case 'Darwin':
PHPExcel_Shared_Font::setTrueTypeFontPath('/Library/Fonts/');
PHPExcel_Shared_Font::setAutoSizeMethod(PHPExcel_Shared_Font::AUTOSIZE_METHOD_EXACT);
break;
case 'Linux':
PHPExcel_Shared_Font::setTrueTypeFontPath('/usr/share/fonts/truetype/');
PHPExcel_Shared_Font::setAutoSizeMethod(PHPExcel_Shared_Font::AUTOSIZE_METHOD_EXACT);
break;
}
return array( return array(
'cache' => array( 'cache' => array(
@ -171,7 +189,7 @@ return array(
| having the appropriate fonts installed. | having the appropriate fonts installed.
| |
*/ */
'autosize-method' => PHPExcel_Shared_Font::AUTOSIZE_METHOD_APPROX, 'autosize-method' => constant('\PHPExcel_Shared_Font::AUTOSIZE_METHOD_' . env('EXCEL_AUTOSIZE_MODE', 'APPROX')),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -291,7 +309,7 @@ return array(
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Supported: DomPDF, tcPDF, mPDF | Supported: DomPDF, tcPDF, mPDF
*/ */
'driver' => 'DomPDF', 'driver' => 'mPDF',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -306,7 +324,7 @@ return array(
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
*/ */
'DomPDF' => array( 'DomPDF' => array(
'path' => base_path('vendor/dompdf/dompdf/') 'path' => base_path('vendor/dompdf/dompdf/'),
), ),
/* /*

View File

@ -31,7 +31,7 @@ return [
'lifetime' => env('SESSION_LIFETIME', (60 * 8)), 'lifetime' => env('SESSION_LIFETIME', (60 * 8)),
'expire_on_close' => false, 'expire_on_close' => true,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddLateFees extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('account_email_settings', function ($table) {
$table->decimal('late_fee1_amount', 13, 2)->nullable();
$table->decimal('late_fee1_percent', 13, 3)->nullable();
$table->decimal('late_fee2_amount', 13, 2)->nullable();
$table->decimal('late_fee2_percent', 13, 3)->nullable();
$table->decimal('late_fee3_amount', 13, 2)->nullable();
$table->decimal('late_fee3_percent', 13, 3)->nullable();
});
Schema::table('documents', function ($table) {
$table->boolean('is_default')->default(false)->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('account_email_settings', function ($table) {
$table->dropColumn('late_fee1_amount');
$table->dropColumn('late_fee1_percent');
$table->dropColumn('late_fee2_amount');
$table->dropColumn('late_fee2_percent');
$table->dropColumn('late_fee3_amount');
$table->dropColumn('late_fee3_percent');
});
Schema::table('documents', function ($table) {
$table->dropColumn('is_default');
});
}
}

File diff suppressed because one or more lines are too long

View File

@ -57,9 +57,9 @@ author = u'Invoice Ninja'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = u'3.5' version = u'3.6'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = u'3.5.1' release = u'3.6.0'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@ -67,6 +67,8 @@ Troubleshooting
- We suggest using PhantomJS version >= 2.1.1, users have reported seeing 'Error: 0' with older versions. - We suggest using PhantomJS version >= 2.1.1, users have reported seeing 'Error: 0' with older versions.
- You can use `this script <https://raw.githubusercontent.com/invoiceninja/invoiceninja/develop/resources/test.pjs>`_ to test from the command line, change ``__YOUR_LINK_HERE__`` to a 'View as recipient' link. - You can use `this script <https://raw.githubusercontent.com/invoiceninja/invoiceninja/develop/resources/test.pjs>`_ to test from the command line, change ``__YOUR_LINK_HERE__`` to a 'View as recipient' link.
- If you require contacts to enter a password to see their invoice you'll need to set a random value for ``PHANTOMJS_SECRET``. - If you require contacts to enter a password to see their invoice you'll need to set a random value for ``PHANTOMJS_SECRET``.
- If you're using a proxy and/or self-signed certificate `this comment <https://github.com/invoiceninja/dockerfiles/issues/39#issuecomment-282489039>`_ may help.
- If you're using a custom design try using a standard one, if the PDF is outside the printable area it can fail.
Custom Fonts Custom Fonts
"""""""""""" """"""""""""

View File

@ -86,8 +86,7 @@ elixir(function(mix) {
mix.scripts([ mix.scripts([
'pdf_viewer.js', 'pdf_viewer.js',
'compatibility.js', 'compatibility.js',
//bowerDir + '/pdfmake/build/pdfmake.js', bowerDir + '/pdfmake/build/pdfmake.js',
'pdfmake.js',
'vfs.js' 'vfs.js'
], 'public/pdf.built.js'); ], 'public/pdf.built.js');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -287,3 +287,7 @@ fieldset[disabled] .btn-success.active {
.btn-success .badge { .btn-success .badge {
color: #5cb85c; color: #5cb85c;
} }
.tooltip-inner {
white-space: normal;
}

View File

@ -191,12 +191,20 @@
left:0; left:0;
right:0; right:0;
text-align:left; text-align:left;
background-color:#000;
width:100%; width:100%;
min-width:250px; min-width:250px;
}
.sidebar-nav-dark li div.nav-footer {
background-color: #000;
border-top-style: solid; border-top-style: solid;
} }
.sidebar-nav-light li div.nav-footer {
background-color: #777;
border-top-style: inset;;
}
.sidebar-nav li div.nav-footer i { .sidebar-nav li div.nav-footer i {
color:#ccc !important; color:#ccc !important;
} }

View File

@ -854,9 +854,9 @@ $LANG = array(
'website_help' => 'Display the invoice in an iFrame on your own website', 'website_help' => 'Display the invoice in an iFrame on your own website',
'invoice_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the invoice number.', 'invoice_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the invoice number.',
'quote_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the quote number.', 'quote_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the quote number.',
'custom_client_fields_helps' => 'Add a field when creating a client and display the label and value on the PDF.', 'custom_client_fields_helps' => 'Add a field when creating a client and optionally display the label and value on the PDF.',
'custom_account_fields_helps' => 'Add a label and value to the company details section of the PDF.', 'custom_account_fields_helps' => 'Add a label and value to the company details section of the PDF.',
'custom_invoice_fields_helps' => 'Add a field when creating an invoice and display the label and value on the PDF.', 'custom_invoice_fields_helps' => 'Add a field when creating an invoice and optionally display the label and value on the PDF.',
'custom_invoice_charges_helps' => 'Add a field when creating an invoice and include the charge in the invoice subtotals.', 'custom_invoice_charges_helps' => 'Add a field when creating an invoice and include the charge in the invoice subtotals.',
'token_expired' => 'Validation token was expired. Please try again.', 'token_expired' => 'Validation token was expired. Please try again.',
'invoice_link' => 'Invoice Link', 'invoice_link' => 'Invoice Link',
@ -1043,7 +1043,7 @@ $LANG = array(
'invoice_item_fields' => 'Invoice Item Fields', 'invoice_item_fields' => 'Invoice Item Fields',
'custom_invoice_item_fields_help' => 'Add a field when creating an invoice item and display the label and value on the PDF.', 'custom_invoice_item_fields_help' => 'Add a field when creating an invoice item and display the label and value on the PDF.',
'recurring_invoice_number' => 'Recurring Number', 'recurring_invoice_number' => 'Recurring Number',
'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices. The default value is \'R\'.', 'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices.',
// Client Passwords // Client Passwords
'enable_portal_password' => 'Password Protect Invoices', 'enable_portal_password' => 'Password Protect Invoices',
@ -1190,8 +1190,8 @@ $LANG = array(
'status_refunded' => 'Refunded', 'status_refunded' => 'Refunded',
'status_voided' => 'Cancelled', 'status_voided' => 'Cancelled',
'refunded_payment' => 'Refunded Payment', 'refunded_payment' => 'Refunded Payment',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)', 'activity_39' => ':user cancelled a :payment_amount payment :payment',
'activity_40' => ':user refunded :adjustment of a :payment_amount payment (:payment)', 'activity_40' => ':user refunded :adjustment of a :payment_amount payment :payment',
'card_expiration' => 'Exp:&nbsp:expires', 'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Unknown', 'card_creditcardother' => 'Unknown',
@ -1330,7 +1330,7 @@ $LANG = array(
'import_products' => 'Import Products', 'import_products' => 'Import Products',
'products_will_create' => 'products will be created', 'products_will_create' => 'products will be created',
'product_key' => 'Product', 'product_key' => 'Product',
'created_products' => 'Successfully created :count product(s)', 'created_products' => 'Successfully created/updated :count product(s)',
'export_help' => 'Use JSON if you plan to import the data into Invoice Ninja.<br/>The file includes clients, products, invoices, quotes and payments.', 'export_help' => 'Use JSON if you plan to import the data into Invoice Ninja.<br/>The file includes clients, products, invoices, quotes and payments.',
'JSON_file' => 'JSON File', 'JSON_file' => 'JSON File',
@ -2217,7 +2217,7 @@ $LANG = array(
'notes_auto_billed' => 'Auto-billed', 'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label', 'surcharge_label' => 'Surcharge Label',
'contact_fields' => 'Contact Fields', 'contact_fields' => 'Contact Fields',
'custom_contact_fields_help' => 'Add a field when creating a contact and display the label and value on the PDF.', 'custom_contact_fields_help' => 'Add a field when creating a contact and optionally display the label and value on the PDF.',
'datatable_info' => 'Showing :start to :end of :total entries', 'datatable_info' => 'Showing :start to :end of :total entries',
'credit_total' => 'Credit Total', 'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable', 'mark_billable' => 'Mark billable',
@ -2302,8 +2302,104 @@ $LANG = array(
'app_version' => 'App Version', 'app_version' => 'App Version',
'ofx_version' => 'OFX Version', 'ofx_version' => 'OFX Version',
'gateway_help_23' => ':link to get your Stripe API keys.', 'gateway_help_23' => ':link to get your Stripe API keys.',
'error_app_key_not_set' => 'Error: the APP_KEY value is not set in the .env file.', 'error_app_key_set_to_default' => 'Error: APP_KEY is set to a default value, to update it backup your database and then run <code>php artisan ninja:update-key</code>',
'error_app_key_set_to_default' => 'Error: the APP_KEY value is set to the default in the .env file.' 'charge_late_fee' => 'Charge Late Fee',
'late_fee_amount' => 'Late Fee Amount',
'late_fee_percent' => 'Late Fee Percent',
'late_fee_added' => 'Late fee added on :date',
'download_invoice' => 'Download Invoice',
'download_quote' => 'Download Quote',
'invoices_are_attached' => 'Your invoice PDFs are attached.',
'downloaded_invoice' => 'An email will be sent with the invoice PDF',
'downloaded_quote' => 'An email will be sent with the quote PDF',
'downloaded_invoices' => 'An email will be sent with the invoice PDFs',
'downloaded_quotes' => 'An email will be sent with the quote PDFs',
'clone_expense' => 'Clone Expense',
'default_documents' => 'Default Documents',
'send_email_to_client' => 'Send email to the client',
'refund_subject' => 'Refund Processed',
'refund_body' => 'You have been processed a refund of :amount for invoice :invoice_number.',
'currency_us_dollar' => 'US Dollar',
'currency_british_pound' => 'British Pound',
'currency_euro' => 'Euro',
'currency_south_african_rand' => 'South African Rand',
'currency_danish_krone' => 'Danish Krone',
'currency_israeli_shekel' => 'Israeli Shekel',
'currency_swedish_krona' => 'Swedish Krona',
'currency_kenyan_shilling' => 'Kenyan Shilling',
'currency_canadian_dollar' => 'Canadian Dollar',
'currency_philippine_peso' => 'Philippine Peso',
'currency_indian_rupee' => 'Indian Rupee',
'currency_australian_dollar' => 'Australian Dollar',
'currency_singapore_dollar' => 'Singapore Dollar',
'currency_norske_kroner' => 'Norske Kroner',
'currency_new_zealand_dollar' => 'New Zealand Dollar',
'currency_vietnamese_dong' => 'Vietnamese Dong',
'currency_swiss_franc' => 'Swiss Franc',
'currency_guatemalan_quetzal' => 'Guatemalan Quetzal',
'currency_malaysian_ringgit' => 'Malaysian Ringgit',
'currency_brazilian_real' => 'Brazilian Real',
'currency_thai_baht' => 'Thai Baht',
'currency_nigerian_naira' => 'Nigerian Naira',
'currency_argentine_peso' => 'Argentine Peso',
'currency_bangladeshi_taka' => 'Bangladeshi Taka',
'currency_united_arab_emirates_dirham' => 'United Arab Emirates Dirham',
'currency_hong_kong_dollar' => 'Hong Kong Dollar',
'currency_indonesian_rupiah' => 'Indonesian Rupiah',
'currency_mexican_peso' => 'Mexican Peso',
'currency_egyptian_pound' => 'Egyptian Pound',
'currency_colombian_peso' => 'Colombian Peso',
'currency_west_african_franc' => 'West African Franc',
'currency_chinese_renminbi' => 'Chinese Renminbi',
'currency_rwandan_franc' => 'Rwandan Franc',
'currency_tanzanian_shilling' => 'Tanzanian Shilling',
'currency_netherlands_antillean_guilder' => 'Netherlands Antillean Guilder',
'currency_trinidad_and_tobago_dollar' => 'Trinidad and Tobago Dollar',
'currency_east_caribbean_dollar' => 'East Caribbean Dollar',
'currency_ghanaian_cedi' => 'Ghanaian Cedi',
'currency_bulgarian_lev' => 'Bulgarian Lev',
'currency_aruban_florin' => 'Aruban Florin',
'currency_turkish_lira' => 'Turkish Lira',
'currency_romanian_new_leu' => 'Romanian New Leu',
'currency_croatian_kuna' => 'Croatian Kuna',
'currency_saudi_riyal' => 'Saudi Riyal',
'currency_japanese_yen' => 'Japanese Yen',
'currency_maldivian_rufiyaa' => 'Maldivian Rufiyaa',
'currency_costa_rican_colón' => 'Costa Rican Colón',
'currency_pakistani_rupee' => 'Pakistani Rupee',
'currency_polish_zloty' => 'Polish Zloty',
'currency_sri_lankan_rupee' => 'Sri Lankan Rupee',
'currency_czech_koruna' => 'Czech Koruna',
'currency_uruguayan_peso' => 'Uruguayan Peso',
'currency_namibian_dollar' => 'Namibian Dollar',
'currency_tunisian_dinar' => 'Tunisian Dinar',
'currency_russian_ruble' => 'Russian Ruble',
'currency_mozambican_metical' => 'Mozambican Metical',
'currency_omani_rial' => 'Omani Rial',
'currency_ukrainian_hryvnia' => 'Ukrainian Hryvnia',
'currency_macanese_pataca' => 'Macanese Pataca',
'currency_taiwan_new_dollar' => 'Taiwan New Dollar',
'currency_dominican_peso' => 'Dominican Peso',
'currency_chilean_peso' => 'Chilean Peso',
'currency_icelandic_króna' => 'Icelandic Króna',
'currency_papua_new_guinean_kina' => 'Papua New Guinean Kina',
'currency_jordanian_dinar' => 'Jordanian Dinar',
'currency_myanmar_kyat' => 'Myanmar Kyat',
'currency_peruvian_sol' => 'Peruvian Sol',
'use_english_version' => 'Make sure to use the English version of the files.<br/>We use the column headers to match the fields.',
'tax1' => 'First Tax',
'tax2' => 'Second Tax',
'fee_help' => 'Gateway fees are the costs charged for access to the financial networks that handle the processing of online payments.',
'format_export' => 'Exporting format',
'custom1' => 'First Custom',
'custom2' => 'Second Custom',
'contact_first_name' => 'Contact First Name',
'contact_last_name' => 'Contact Last Name',
'contact_custom1' => 'Contact First Custom',
'contact_custom2' => 'Contact Second Custom',
'currency' => 'Currency',
); );

View File

@ -855,9 +855,9 @@ $LANG = array(
'website_help' => 'Display the invoice in an iFrame on your own website', 'website_help' => 'Display the invoice in an iFrame on your own website',
'invoice_number_help' => 'Určete prefix nebo použijte upravitelný vzorec pro nastavení číslování faktur.', 'invoice_number_help' => 'Určete prefix nebo použijte upravitelný vzorec pro nastavení číslování faktur.',
'quote_number_help' => 'Určete prefix nebo použijte upravitelný vzorec pro nastavení číslování nabídek.', 'quote_number_help' => 'Určete prefix nebo použijte upravitelný vzorec pro nastavení číslování nabídek.',
'custom_client_fields_helps' => 'Když vytváříte klienta - přidejte nové pole a jeho popis a hodnotu pro zobrazení v PDF.', 'custom_client_fields_helps' => 'Add a field when creating a client and optionally display the label and value on the PDF.',
'custom_account_fields_helps' => 'Přidejte si pole a hodnotu k detailům společnosti na PDF.', 'custom_account_fields_helps' => 'Přidejte si pole a hodnotu k detailům společnosti na PDF.',
'custom_invoice_fields_helps' => 'Přidejte si nové pole když vytváříte fakturu a zobrazte si jeho popis a hodnotu v PDF.', 'custom_invoice_fields_helps' => 'Add a field when creating an invoice and optionally display the label and value on the PDF.',
'custom_invoice_charges_helps' => 'Přidejte si pole během vytváření faktury a zahrňte ho mezi poplatky do faktury.', 'custom_invoice_charges_helps' => 'Přidejte si pole během vytváření faktury a zahrňte ho mezi poplatky do faktury.',
'token_expired' => 'Validační token expiroval. Prosím vyzkoušejte znovu.', 'token_expired' => 'Validační token expiroval. Prosím vyzkoušejte znovu.',
'invoice_link' => 'Odkaz na fakturu', 'invoice_link' => 'Odkaz na fakturu',
@ -1045,7 +1045,7 @@ $LANG = array(
'invoice_item_fields' => 'Pole položky faktury', 'invoice_item_fields' => 'Pole položky faktury',
'custom_invoice_item_fields_help' => 'Během vytváření faktury si přidejte pole a zobrazte si jeho popis a hodnotu v PDF.', 'custom_invoice_item_fields_help' => 'Během vytváření faktury si přidejte pole a zobrazte si jeho popis a hodnotu v PDF.',
'recurring_invoice_number' => 'Recurring Number', 'recurring_invoice_number' => 'Recurring Number',
'recurring_invoice_number_prefix_help' => 'Určete prefix, který se přidá k číslu pravidelných faktur. Výchozí hodnota je \'R\'.', 'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices.',
// Client Passwords // Client Passwords
'enable_portal_password' => 'Password Protect Invoices', 'enable_portal_password' => 'Password Protect Invoices',
@ -1192,8 +1192,8 @@ $LANG = array(
'status_refunded' => 'Refunded', 'status_refunded' => 'Refunded',
'status_voided' => 'Cancelled', 'status_voided' => 'Cancelled',
'refunded_payment' => 'Refunded Payment', 'refunded_payment' => 'Refunded Payment',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)', 'activity_39' => ':user cancelled a :payment_amount payment :payment',
'activity_40' => ':user refunded :adjustment of a :payment_amount payment (:payment)', 'activity_40' => ':user refunded :adjustment of a :payment_amount payment :payment',
'card_expiration' => 'Exp:&nbsp:expires', 'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Unknown', 'card_creditcardother' => 'Unknown',
@ -1332,7 +1332,7 @@ $LANG = array(
'import_products' => 'Import Products', 'import_products' => 'Import Products',
'products_will_create' => 'products will be created', 'products_will_create' => 'products will be created',
'product_key' => 'Product', 'product_key' => 'Product',
'created_products' => 'Successfully created :count product(s)', 'created_products' => 'Successfully created/updated :count product(s)',
'export_help' => 'Use JSON if you plan to import the data into Invoice Ninja.<br/>The file includes clients, products, invoices, quotes and payments.', 'export_help' => 'Use JSON if you plan to import the data into Invoice Ninja.<br/>The file includes clients, products, invoices, quotes and payments.',
'JSON_file' => 'JSON File', 'JSON_file' => 'JSON File',
@ -2219,7 +2219,7 @@ $LANG = array(
'notes_auto_billed' => 'Auto-billed', 'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label', 'surcharge_label' => 'Surcharge Label',
'contact_fields' => 'Contact Fields', 'contact_fields' => 'Contact Fields',
'custom_contact_fields_help' => 'Add a field when creating a contact and display the label and value on the PDF.', 'custom_contact_fields_help' => 'Add a field when creating a contact and optionally display the label and value on the PDF.',
'datatable_info' => 'Zobrazeno :start do :end z :total položek', 'datatable_info' => 'Zobrazeno :start do :end z :total položek',
'credit_total' => 'Credit Total', 'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable', 'mark_billable' => 'Mark billable',
@ -2304,8 +2304,104 @@ $LANG = array(
'app_version' => 'App Version', 'app_version' => 'App Version',
'ofx_version' => 'OFX Version', 'ofx_version' => 'OFX Version',
'gateway_help_23' => ':link to get your Stripe API keys.', 'gateway_help_23' => ':link to get your Stripe API keys.',
'error_app_key_not_set' => 'Error: the APP_KEY value is not set in the .env file.', 'error_app_key_set_to_default' => 'Error: APP_KEY is set to a default value, to update it backup your database and then run <code>php artisan ninja:update-key</code>',
'error_app_key_set_to_default' => 'Error: the APP_KEY value is set to the default in the .env file.' 'charge_late_fee' => 'Charge Late Fee',
'late_fee_amount' => 'Late Fee Amount',
'late_fee_percent' => 'Late Fee Percent',
'late_fee_added' => 'Late fee added on :date',
'download_invoice' => 'Download Invoice',
'download_quote' => 'Download Quote',
'invoices_are_attached' => 'Your invoice PDFs are attached.',
'downloaded_invoice' => 'An email will be sent with the invoice PDF',
'downloaded_quote' => 'An email will be sent with the quote PDF',
'downloaded_invoices' => 'An email will be sent with the invoice PDFs',
'downloaded_quotes' => 'An email will be sent with the quote PDFs',
'clone_expense' => 'Clone Expense',
'default_documents' => 'Default Documents',
'send_email_to_client' => 'Send email to the client',
'refund_subject' => 'Refund Processed',
'refund_body' => 'You have been processed a refund of :amount for invoice :invoice_number.',
'currency_us_dollar' => 'US Dollar',
'currency_british_pound' => 'British Pound',
'currency_euro' => 'Euro',
'currency_south_african_rand' => 'South African Rand',
'currency_danish_krone' => 'Danish Krone',
'currency_israeli_shekel' => 'Israeli Shekel',
'currency_swedish_krona' => 'Swedish Krona',
'currency_kenyan_shilling' => 'Kenyan Shilling',
'currency_canadian_dollar' => 'Canadian Dollar',
'currency_philippine_peso' => 'Philippine Peso',
'currency_indian_rupee' => 'Indian Rupee',
'currency_australian_dollar' => 'Australian Dollar',
'currency_singapore_dollar' => 'Singapore Dollar',
'currency_norske_kroner' => 'Norske Kroner',
'currency_new_zealand_dollar' => 'New Zealand Dollar',
'currency_vietnamese_dong' => 'Vietnamese Dong',
'currency_swiss_franc' => 'Swiss Franc',
'currency_guatemalan_quetzal' => 'Guatemalan Quetzal',
'currency_malaysian_ringgit' => 'Malaysian Ringgit',
'currency_brazilian_real' => 'Brazilian Real',
'currency_thai_baht' => 'Thai Baht',
'currency_nigerian_naira' => 'Nigerian Naira',
'currency_argentine_peso' => 'Argentine Peso',
'currency_bangladeshi_taka' => 'Bangladeshi Taka',
'currency_united_arab_emirates_dirham' => 'United Arab Emirates Dirham',
'currency_hong_kong_dollar' => 'Hong Kong Dollar',
'currency_indonesian_rupiah' => 'Indonesian Rupiah',
'currency_mexican_peso' => 'Mexican Peso',
'currency_egyptian_pound' => 'Egyptian Pound',
'currency_colombian_peso' => 'Colombian Peso',
'currency_west_african_franc' => 'West African Franc',
'currency_chinese_renminbi' => 'Chinese Renminbi',
'currency_rwandan_franc' => 'Rwandan Franc',
'currency_tanzanian_shilling' => 'Tanzanian Shilling',
'currency_netherlands_antillean_guilder' => 'Netherlands Antillean Guilder',
'currency_trinidad_and_tobago_dollar' => 'Trinidad and Tobago Dollar',
'currency_east_caribbean_dollar' => 'East Caribbean Dollar',
'currency_ghanaian_cedi' => 'Ghanaian Cedi',
'currency_bulgarian_lev' => 'Bulgarian Lev',
'currency_aruban_florin' => 'Aruban Florin',
'currency_turkish_lira' => 'Turkish Lira',
'currency_romanian_new_leu' => 'Romanian New Leu',
'currency_croatian_kuna' => 'Croatian Kuna',
'currency_saudi_riyal' => 'Saudi Riyal',
'currency_japanese_yen' => 'Japanese Yen',
'currency_maldivian_rufiyaa' => 'Maldivian Rufiyaa',
'currency_costa_rican_colón' => 'Costa Rican Colón',
'currency_pakistani_rupee' => 'Pakistani Rupee',
'currency_polish_zloty' => 'Polish Zloty',
'currency_sri_lankan_rupee' => 'Sri Lankan Rupee',
'currency_czech_koruna' => 'Czech Koruna',
'currency_uruguayan_peso' => 'Uruguayan Peso',
'currency_namibian_dollar' => 'Namibian Dollar',
'currency_tunisian_dinar' => 'Tunisian Dinar',
'currency_russian_ruble' => 'Russian Ruble',
'currency_mozambican_metical' => 'Mozambican Metical',
'currency_omani_rial' => 'Omani Rial',
'currency_ukrainian_hryvnia' => 'Ukrainian Hryvnia',
'currency_macanese_pataca' => 'Macanese Pataca',
'currency_taiwan_new_dollar' => 'Taiwan New Dollar',
'currency_dominican_peso' => 'Dominican Peso',
'currency_chilean_peso' => 'Chilean Peso',
'currency_icelandic_króna' => 'Icelandic Króna',
'currency_papua_new_guinean_kina' => 'Papua New Guinean Kina',
'currency_jordanian_dinar' => 'Jordanian Dinar',
'currency_myanmar_kyat' => 'Myanmar Kyat',
'currency_peruvian_sol' => 'Peruvian Sol',
'use_english_version' => 'Make sure to use the English version of the files.<br/>We use the column headers to match the fields.',
'tax1' => 'First Tax',
'tax2' => 'Second Tax',
'fee_help' => 'Gateway fees are the costs charged for access to the financial networks that handle the processing of online payments.',
'format_export' => 'Exporting format',
'custom1' => 'First Custom',
'custom2' => 'Second Custom',
'contact_first_name' => 'Contact First Name',
'contact_last_name' => 'Contact Last Name',
'contact_custom1' => 'Contact First Custom',
'contact_custom2' => 'Contact Second Custom',
'currency' => 'Currency',
); );

View File

@ -854,9 +854,9 @@ $LANG = array(
'website_help' => 'Display the invoice in an iFrame on your own website', 'website_help' => 'Display the invoice in an iFrame on your own website',
'invoice_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the invoice number.', 'invoice_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the invoice number.',
'quote_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the quote number.', 'quote_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the quote number.',
'custom_client_fields_helps' => 'Add a text input to the client create/edit page and display the label and value on the PDF.', 'custom_client_fields_helps' => 'Add a field when creating a client and optionally display the label and value on the PDF.',
'custom_account_fields_helps' => 'Add a label and value to the company details section of the PDF.', 'custom_account_fields_helps' => 'Add a label and value to the company details section of the PDF.',
'custom_invoice_fields_helps' => 'Add a text input to the invoice create/edit page and display the label and value on the PDF.', 'custom_invoice_fields_helps' => 'Add a field when creating an invoice and optionally display the label and value on the PDF.',
'custom_invoice_charges_helps' => 'Add a text input to the invoice create/edit page and include the charge in the invoice subtotals.', 'custom_invoice_charges_helps' => 'Add a text input to the invoice create/edit page and include the charge in the invoice subtotals.',
'token_expired' => 'Validation token was expired. Please try again.', 'token_expired' => 'Validation token was expired. Please try again.',
'invoice_link' => 'Invoice Link', 'invoice_link' => 'Invoice Link',
@ -1043,7 +1043,7 @@ $LANG = array(
'invoice_item_fields' => 'Invoice Item Fields', 'invoice_item_fields' => 'Invoice Item Fields',
'custom_invoice_item_fields_help' => 'Add a field when creating an invoice item and display the label and value on the PDF.', 'custom_invoice_item_fields_help' => 'Add a field when creating an invoice item and display the label and value on the PDF.',
'recurring_invoice_number' => 'Recurring Number', 'recurring_invoice_number' => 'Recurring Number',
'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices. The default value is \'R\'.', 'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices.',
// Client Passwords // Client Passwords
'enable_portal_password' => 'Password Protect Invoices', 'enable_portal_password' => 'Password Protect Invoices',
@ -1190,8 +1190,8 @@ $LANG = array(
'status_refunded' => 'Refunded', 'status_refunded' => 'Refunded',
'status_voided' => 'Cancelled', 'status_voided' => 'Cancelled',
'refunded_payment' => 'Refunded Payment', 'refunded_payment' => 'Refunded Payment',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)', 'activity_39' => ':user cancelled a :payment_amount payment :payment',
'activity_40' => ':user refunded :adjustment of a :payment_amount payment (:payment)', 'activity_40' => ':user refunded :adjustment of a :payment_amount payment :payment',
'card_expiration' => 'Exp:&nbsp:expires', 'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Unknown', 'card_creditcardother' => 'Unknown',
@ -1330,7 +1330,7 @@ $LANG = array(
'import_products' => 'Import Products', 'import_products' => 'Import Products',
'products_will_create' => 'products will be created', 'products_will_create' => 'products will be created',
'product_key' => 'Product', 'product_key' => 'Product',
'created_products' => 'Successfully created :count product(s)', 'created_products' => 'Successfully created/updated :count product(s)',
'export_help' => 'Use JSON if you plan to import the data into Invoice Ninja.<br/>The file includes clients, products, invoices, quotes and payments.', 'export_help' => 'Use JSON if you plan to import the data into Invoice Ninja.<br/>The file includes clients, products, invoices, quotes and payments.',
'JSON_file' => 'JSON File', 'JSON_file' => 'JSON File',
@ -2217,7 +2217,7 @@ $LANG = array(
'notes_auto_billed' => 'Auto-billed', 'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label', 'surcharge_label' => 'Surcharge Label',
'contact_fields' => 'Contact Fields', 'contact_fields' => 'Contact Fields',
'custom_contact_fields_help' => 'Add a field when creating a contact and display the label and value on the PDF.', 'custom_contact_fields_help' => 'Add a field when creating a contact and optionally display the label and value on the PDF.',
'datatable_info' => 'Showing :start to :end of :total entries', 'datatable_info' => 'Showing :start to :end of :total entries',
'credit_total' => 'Credit Total', 'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable', 'mark_billable' => 'Mark billable',
@ -2302,8 +2302,104 @@ $LANG = array(
'app_version' => 'App Version', 'app_version' => 'App Version',
'ofx_version' => 'OFX Version', 'ofx_version' => 'OFX Version',
'gateway_help_23' => ':link to get your Stripe API keys.', 'gateway_help_23' => ':link to get your Stripe API keys.',
'error_app_key_not_set' => 'Error: the APP_KEY value is not set in the .env file.', 'error_app_key_set_to_default' => 'Error: APP_KEY is set to a default value, to update it backup your database and then run <code>php artisan ninja:update-key</code>',
'error_app_key_set_to_default' => 'Error: the APP_KEY value is set to the default in the .env file.' 'charge_late_fee' => 'Charge Late Fee',
'late_fee_amount' => 'Late Fee Amount',
'late_fee_percent' => 'Late Fee Percent',
'late_fee_added' => 'Late fee added on :date',
'download_invoice' => 'Download Invoice',
'download_quote' => 'Download Quote',
'invoices_are_attached' => 'Your invoice PDFs are attached.',
'downloaded_invoice' => 'An email will be sent with the invoice PDF',
'downloaded_quote' => 'An email will be sent with the quote PDF',
'downloaded_invoices' => 'An email will be sent with the invoice PDFs',
'downloaded_quotes' => 'An email will be sent with the quote PDFs',
'clone_expense' => 'Clone Expense',
'default_documents' => 'Default Documents',
'send_email_to_client' => 'Send email to the client',
'refund_subject' => 'Refund Processed',
'refund_body' => 'You have been processed a refund of :amount for invoice :invoice_number.',
'currency_us_dollar' => 'US Dollar',
'currency_british_pound' => 'British Pound',
'currency_euro' => 'Euro',
'currency_south_african_rand' => 'South African Rand',
'currency_danish_krone' => 'Danish Krone',
'currency_israeli_shekel' => 'Israeli Shekel',
'currency_swedish_krona' => 'Swedish Krona',
'currency_kenyan_shilling' => 'Kenyan Shilling',
'currency_canadian_dollar' => 'Canadian Dollar',
'currency_philippine_peso' => 'Philippine Peso',
'currency_indian_rupee' => 'Indian Rupee',
'currency_australian_dollar' => 'Australian Dollar',
'currency_singapore_dollar' => 'Singapore Dollar',
'currency_norske_kroner' => 'Norske Kroner',
'currency_new_zealand_dollar' => 'New Zealand Dollar',
'currency_vietnamese_dong' => 'Vietnamese Dong',
'currency_swiss_franc' => 'Swiss Franc',
'currency_guatemalan_quetzal' => 'Guatemalan Quetzal',
'currency_malaysian_ringgit' => 'Malaysian Ringgit',
'currency_brazilian_real' => 'Brazilian Real',
'currency_thai_baht' => 'Thai Baht',
'currency_nigerian_naira' => 'Nigerian Naira',
'currency_argentine_peso' => 'Argentine Peso',
'currency_bangladeshi_taka' => 'Bangladeshi Taka',
'currency_united_arab_emirates_dirham' => 'United Arab Emirates Dirham',
'currency_hong_kong_dollar' => 'Hong Kong Dollar',
'currency_indonesian_rupiah' => 'Indonesian Rupiah',
'currency_mexican_peso' => 'Mexican Peso',
'currency_egyptian_pound' => 'Egyptian Pound',
'currency_colombian_peso' => 'Colombian Peso',
'currency_west_african_franc' => 'West African Franc',
'currency_chinese_renminbi' => 'Chinese Renminbi',
'currency_rwandan_franc' => 'Rwandan Franc',
'currency_tanzanian_shilling' => 'Tanzanian Shilling',
'currency_netherlands_antillean_guilder' => 'Netherlands Antillean Guilder',
'currency_trinidad_and_tobago_dollar' => 'Trinidad and Tobago Dollar',
'currency_east_caribbean_dollar' => 'East Caribbean Dollar',
'currency_ghanaian_cedi' => 'Ghanaian Cedi',
'currency_bulgarian_lev' => 'Bulgarian Lev',
'currency_aruban_florin' => 'Aruban Florin',
'currency_turkish_lira' => 'Turkish Lira',
'currency_romanian_new_leu' => 'Romanian New Leu',
'currency_croatian_kuna' => 'Croatian Kuna',
'currency_saudi_riyal' => 'Saudi Riyal',
'currency_japanese_yen' => 'Japanese Yen',
'currency_maldivian_rufiyaa' => 'Maldivian Rufiyaa',
'currency_costa_rican_colón' => 'Costa Rican Colón',
'currency_pakistani_rupee' => 'Pakistani Rupee',
'currency_polish_zloty' => 'Polish Zloty',
'currency_sri_lankan_rupee' => 'Sri Lankan Rupee',
'currency_czech_koruna' => 'Czech Koruna',
'currency_uruguayan_peso' => 'Uruguayan Peso',
'currency_namibian_dollar' => 'Namibian Dollar',
'currency_tunisian_dinar' => 'Tunisian Dinar',
'currency_russian_ruble' => 'Russian Ruble',
'currency_mozambican_metical' => 'Mozambican Metical',
'currency_omani_rial' => 'Omani Rial',
'currency_ukrainian_hryvnia' => 'Ukrainian Hryvnia',
'currency_macanese_pataca' => 'Macanese Pataca',
'currency_taiwan_new_dollar' => 'Taiwan New Dollar',
'currency_dominican_peso' => 'Dominican Peso',
'currency_chilean_peso' => 'Chilean Peso',
'currency_icelandic_króna' => 'Icelandic Króna',
'currency_papua_new_guinean_kina' => 'Papua New Guinean Kina',
'currency_jordanian_dinar' => 'Jordanian Dinar',
'currency_myanmar_kyat' => 'Myanmar Kyat',
'currency_peruvian_sol' => 'Peruvian Sol',
'use_english_version' => 'Make sure to use the English version of the files.<br/>We use the column headers to match the fields.',
'tax1' => 'First Tax',
'tax2' => 'Second Tax',
'fee_help' => 'Gateway fees are the costs charged for access to the financial networks that handle the processing of online payments.',
'format_export' => 'Exporting format',
'custom1' => 'First Custom',
'custom2' => 'Second Custom',
'contact_first_name' => 'Contact First Name',
'contact_last_name' => 'Contact Last Name',
'contact_custom1' => 'Contact First Custom',
'contact_custom2' => 'Contact Second Custom',
'currency' => 'Currency',
); );

View File

@ -2,7 +2,7 @@
$LANG = array( $LANG = array(
'organization' => 'Unternehmenn', 'organization' => 'Unternehmen',
'name' => 'Name', 'name' => 'Name',
'website' => 'Webseite', 'website' => 'Webseite',
'work_phone' => 'Telefon', 'work_phone' => 'Telefon',
@ -854,9 +854,9 @@ $LANG = array(
'website_help' => 'Zeige die Rechnung als iFrame auf deiner eigenen Webseite an', 'website_help' => 'Zeige die Rechnung als iFrame auf deiner eigenen Webseite an',
'invoice_number_help' => 'Geben Sie einen Präfix oder ein benutzerdefiniertes Schema an, um die Rechnungsnummer dynamisch zu erzeugen.', 'invoice_number_help' => 'Geben Sie einen Präfix oder ein benutzerdefiniertes Schema an, um die Rechnungsnummer dynamisch zu erzeugen.',
'quote_number_help' => 'Geben Sie einen Präfix oder ein benutzerdefiniertes Schema an, um die Angebotsnummer dynamisch zu erzeugen.', 'quote_number_help' => 'Geben Sie einen Präfix oder ein benutzerdefiniertes Schema an, um die Angebotsnummer dynamisch zu erzeugen.',
'custom_client_fields_helps' => 'Füge ein Feld hinzu, wenn ein neuer Kunde erstellt wird und zeige die Bezeichnung und den Wert auf der Rechnung.', 'custom_client_fields_helps' => 'Add a field when creating a client and optionally display the label and value on the PDF.',
'custom_account_fields_helps' => 'Füge ein Feld, mit Bezeichnung und zugehörigem Wert, zum Firmen-Detailabschnitt in der Rechnung hinzu.', 'custom_account_fields_helps' => 'Füge ein Feld, mit Bezeichnung und zugehörigem Wert, zum Firmen-Detailabschnitt in der Rechnung hinzu.',
'custom_invoice_fields_helps' => 'Füge ein Feld hinzu, wenn eine neue Rechnung erstellt wird und zeige die Bezeichnung und den Wert auf der Rechnung an.', 'custom_invoice_fields_helps' => 'Add a field when creating an invoice and optionally display the label and value on the PDF.',
'custom_invoice_charges_helps' => 'Füge ein Feld hinzu, wenn eine neue Rechnung erstellt wird und erfasse die Kosten in den Zwischensummen der Rechnung.', 'custom_invoice_charges_helps' => 'Füge ein Feld hinzu, wenn eine neue Rechnung erstellt wird und erfasse die Kosten in den Zwischensummen der Rechnung.',
'token_expired' => 'Validierungstoken ist abgelaufen. Bitte probieren Sie es erneut.', 'token_expired' => 'Validierungstoken ist abgelaufen. Bitte probieren Sie es erneut.',
'invoice_link' => 'Link zur Rechnung', 'invoice_link' => 'Link zur Rechnung',
@ -1043,7 +1043,7 @@ $LANG = array(
'invoice_item_fields' => 'Rechnungspositionsfeld', 'invoice_item_fields' => 'Rechnungspositionsfeld',
'custom_invoice_item_fields_help' => 'Add a field when creating an invoice item and display the label and value on the PDF.', 'custom_invoice_item_fields_help' => 'Add a field when creating an invoice item and display the label and value on the PDF.',
'recurring_invoice_number' => 'Wiederkehrende Nummer', 'recurring_invoice_number' => 'Wiederkehrende Nummer',
'recurring_invoice_number_prefix_help' => 'Geben Sie einen Präfix für wiederkehrende Rechnungen an. Standard ist \'R\'.', 'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices.',
// Client Passwords // Client Passwords
'enable_portal_password' => 'Rechnungen mit Passwort schützen', 'enable_portal_password' => 'Rechnungen mit Passwort schützen',
@ -1190,8 +1190,8 @@ $LANG = array(
'status_refunded' => 'Erstattet', 'status_refunded' => 'Erstattet',
'status_voided' => 'Abgebrochen', 'status_voided' => 'Abgebrochen',
'refunded_payment' => 'Zahlung erstattet', 'refunded_payment' => 'Zahlung erstattet',
'activity_39' => ':user brach eine Zahlung über :payment_amount ab (:payment)', 'activity_39' => ':user cancelled a :payment_amount payment :payment',
'activity_40' => ':user rückerstattete :adjustment einer :payment_amount Zahlung (:payment)', 'activity_40' => ':user refunded :adjustment of a :payment_amount payment :payment',
'card_expiration' => 'Ablaufdatum:&nbsp:expires', 'card_expiration' => 'Ablaufdatum:&nbsp:expires',
'card_creditcardother' => 'Unbekannt', 'card_creditcardother' => 'Unbekannt',
@ -1330,7 +1330,7 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese
'import_products' => 'Produkte importieren', 'import_products' => 'Produkte importieren',
'products_will_create' => 'Produkte werden erstellt werden', 'products_will_create' => 'Produkte werden erstellt werden',
'product_key' => 'Produkt', 'product_key' => 'Produkt',
'created_products' => 'Erfolgreich :count Produkt(e) erstellt', 'created_products' => 'Successfully created/updated :count product(s)',
'export_help' => 'Nutzen Sie JSON wenn Sie die Daten in Invoice Ninja importieren wollen.<br/>Die Datei beinhaltet Kunden, Produkte, Rechnungen, Angebote und Zahlungen.', 'export_help' => 'Nutzen Sie JSON wenn Sie die Daten in Invoice Ninja importieren wollen.<br/>Die Datei beinhaltet Kunden, Produkte, Rechnungen, Angebote und Zahlungen.',
'JSON_file' => 'JSON Datei', 'JSON_file' => 'JSON Datei',
@ -2217,7 +2217,7 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese
'notes_auto_billed' => 'Auto-billed', 'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Aufschlagsfeldbezeichnung', 'surcharge_label' => 'Aufschlagsfeldbezeichnung',
'contact_fields' => 'Kontaktfelder', 'contact_fields' => 'Kontaktfelder',
'custom_contact_fields_help' => 'Füge ein Feld hinzu, wenn ein neuer Kontakt erstellt wird und zeige die Bezeichnung und den Wert auf der Rechnung.', 'custom_contact_fields_help' => 'Add a field when creating a contact and optionally display the label and value on the PDF.',
'datatable_info' => 'Zeige Eintrag :start bis :end von :total', 'datatable_info' => 'Zeige Eintrag :start bis :end von :total',
'credit_total' => 'Credit Total', 'credit_total' => 'Credit Total',
'mark_billable' => 'zur Verrechnung kennzeichnen', 'mark_billable' => 'zur Verrechnung kennzeichnen',
@ -2293,7 +2293,7 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese
'taxes_and_fees' => 'Steuern und Gebühren', 'taxes_and_fees' => 'Steuern und Gebühren',
'import_failed' => 'Import fehlgeschlagen', 'import_failed' => 'Import fehlgeschlagen',
'recurring_prefix' => 'Wiederkehrender Präfix', 'recurring_prefix' => 'Wiederkehrender Präfix',
'options' => 'Options', 'options' => 'Optionen',
'credit_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the credit number for negative invoices.', 'credit_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the credit number for negative invoices.',
'next_credit_number' => 'The next credit number is :number.', 'next_credit_number' => 'The next credit number is :number.',
'padding_help' => 'The number of zero\'s to pad the number.', 'padding_help' => 'The number of zero\'s to pad the number.',
@ -2302,8 +2302,104 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese
'app_version' => 'App Version', 'app_version' => 'App Version',
'ofx_version' => 'OFX Version', 'ofx_version' => 'OFX Version',
'gateway_help_23' => ':link to get your Stripe API keys.', 'gateway_help_23' => ':link to get your Stripe API keys.',
'error_app_key_not_set' => 'Error: the APP_KEY value is not set in the .env file.', 'error_app_key_set_to_default' => 'Error: APP_KEY is set to a default value, to update it backup your database and then run <code>php artisan ninja:update-key</code>',
'error_app_key_set_to_default' => 'Error: the APP_KEY value is set to the default in the .env file.' 'charge_late_fee' => 'Charge Late Fee',
'late_fee_amount' => 'Late Fee Amount',
'late_fee_percent' => 'Late Fee Percent',
'late_fee_added' => 'Late fee added on :date',
'download_invoice' => 'Rechnung herunterladen',
'download_quote' => 'Angebot herunterladen',
'invoices_are_attached' => 'Your invoice PDFs are attached.',
'downloaded_invoice' => 'An email will be sent with the invoice PDF',
'downloaded_quote' => 'An email will be sent with the quote PDF',
'downloaded_invoices' => 'An email will be sent with the invoice PDFs',
'downloaded_quotes' => 'An email will be sent with the quote PDFs',
'clone_expense' => 'Clone Expense',
'default_documents' => 'Default Documents',
'send_email_to_client' => 'Send email to the client',
'refund_subject' => 'Refund Processed',
'refund_body' => 'You have been processed a refund of :amount for invoice :invoice_number.',
'currency_us_dollar' => 'US Dollar',
'currency_british_pound' => 'British Pound',
'currency_euro' => 'Euro',
'currency_south_african_rand' => 'South African Rand',
'currency_danish_krone' => 'Danish Krone',
'currency_israeli_shekel' => 'Israeli Shekel',
'currency_swedish_krona' => 'Swedish Krona',
'currency_kenyan_shilling' => 'Kenyan Shilling',
'currency_canadian_dollar' => 'Canadian Dollar',
'currency_philippine_peso' => 'Philippine Peso',
'currency_indian_rupee' => 'Indian Rupee',
'currency_australian_dollar' => 'Australian Dollar',
'currency_singapore_dollar' => 'Singapore Dollar',
'currency_norske_kroner' => 'Norske Kroner',
'currency_new_zealand_dollar' => 'New Zealand Dollar',
'currency_vietnamese_dong' => 'Vietnamese Dong',
'currency_swiss_franc' => 'Swiss Franc',
'currency_guatemalan_quetzal' => 'Guatemalan Quetzal',
'currency_malaysian_ringgit' => 'Malaysian Ringgit',
'currency_brazilian_real' => 'Brazilian Real',
'currency_thai_baht' => 'Thai Baht',
'currency_nigerian_naira' => 'Nigerian Naira',
'currency_argentine_peso' => 'Argentine Peso',
'currency_bangladeshi_taka' => 'Bangladeshi Taka',
'currency_united_arab_emirates_dirham' => 'United Arab Emirates Dirham',
'currency_hong_kong_dollar' => 'Hong Kong Dollar',
'currency_indonesian_rupiah' => 'Indonesian Rupiah',
'currency_mexican_peso' => 'Mexican Peso',
'currency_egyptian_pound' => 'Egyptian Pound',
'currency_colombian_peso' => 'Colombian Peso',
'currency_west_african_franc' => 'West African Franc',
'currency_chinese_renminbi' => 'Chinese Renminbi',
'currency_rwandan_franc' => 'Rwandan Franc',
'currency_tanzanian_shilling' => 'Tanzanian Shilling',
'currency_netherlands_antillean_guilder' => 'Netherlands Antillean Guilder',
'currency_trinidad_and_tobago_dollar' => 'Trinidad and Tobago Dollar',
'currency_east_caribbean_dollar' => 'East Caribbean Dollar',
'currency_ghanaian_cedi' => 'Ghanaian Cedi',
'currency_bulgarian_lev' => 'Bulgarian Lev',
'currency_aruban_florin' => 'Aruban Florin',
'currency_turkish_lira' => 'Turkish Lira',
'currency_romanian_new_leu' => 'Romanian New Leu',
'currency_croatian_kuna' => 'Croatian Kuna',
'currency_saudi_riyal' => 'Saudi Riyal',
'currency_japanese_yen' => 'Japanese Yen',
'currency_maldivian_rufiyaa' => 'Maldivian Rufiyaa',
'currency_costa_rican_colón' => 'Costa Rican Colón',
'currency_pakistani_rupee' => 'Pakistani Rupee',
'currency_polish_zloty' => 'Polish Zloty',
'currency_sri_lankan_rupee' => 'Sri Lankan Rupee',
'currency_czech_koruna' => 'Czech Koruna',
'currency_uruguayan_peso' => 'Uruguayan Peso',
'currency_namibian_dollar' => 'Namibian Dollar',
'currency_tunisian_dinar' => 'Tunisian Dinar',
'currency_russian_ruble' => 'Russian Ruble',
'currency_mozambican_metical' => 'Mozambican Metical',
'currency_omani_rial' => 'Omani Rial',
'currency_ukrainian_hryvnia' => 'Ukrainian Hryvnia',
'currency_macanese_pataca' => 'Macanese Pataca',
'currency_taiwan_new_dollar' => 'Taiwan New Dollar',
'currency_dominican_peso' => 'Dominican Peso',
'currency_chilean_peso' => 'Chilean Peso',
'currency_icelandic_króna' => 'Icelandic Króna',
'currency_papua_new_guinean_kina' => 'Papua New Guinean Kina',
'currency_jordanian_dinar' => 'Jordanian Dinar',
'currency_myanmar_kyat' => 'Myanmar Kyat',
'currency_peruvian_sol' => 'Peruvian Sol',
'use_english_version' => 'Make sure to use the English version of the files.<br/>We use the column headers to match the fields.',
'tax1' => 'First Tax',
'tax2' => 'Second Tax',
'fee_help' => 'Gateway fees are the costs charged for access to the financial networks that handle the processing of online payments.',
'format_export' => 'Exporting format',
'custom1' => 'First Custom',
'custom2' => 'Second Custom',
'contact_first_name' => 'Contact First Name',
'contact_last_name' => 'Contact Last Name',
'contact_custom1' => 'Contact First Custom',
'contact_custom2' => 'Contact Second Custom',
'currency' => 'Currency',
); );

View File

@ -169,7 +169,7 @@ $LANG = array(
'remove_logo' => 'Διαγραφή λογότυπου', 'remove_logo' => 'Διαγραφή λογότυπου',
'logo_help' => 'Υποστηρίζονται: JPEG, GIF και PNG', 'logo_help' => 'Υποστηρίζονται: JPEG, GIF και PNG',
'payment_gateway' => 'Πύλη Πληρωμών (Gateway)', 'payment_gateway' => 'Πύλη Πληρωμών (Gateway)',
'gateway_id' => 'Πύλη (Gateway)', 'gateway_id' => 'Πύλη Πληρωμής (Gateway)',
'email_notifications' => 'Ειδοποιήσεις Email', 'email_notifications' => 'Ειδοποιήσεις Email',
'email_sent' => 'Αποστολή email όταν το τιμολόγιο <b>σταλεί</b>', 'email_sent' => 'Αποστολή email όταν το τιμολόγιο <b>σταλεί</b>',
'email_viewed' => 'Αποστολή email όταν το τιμολόγιο <b>προβληθεί</b>', 'email_viewed' => 'Αποστολή email όταν το τιμολόγιο <b>προβληθεί</b>',
@ -854,9 +854,9 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'website_help' => 'Εμφανίστε το τιμολόγιο σε ένα iFrame στη δική σας ιστοσελίδα', 'website_help' => 'Εμφανίστε το τιμολόγιο σε ένα iFrame στη δική σας ιστοσελίδα',
'invoice_number_help' => 'Ορίστε ένα πρόθεμα ή χρησιμοποιήστε ένα προσαρμοσμένο μοτίβο για να καθορίζετε δυναμικά τον αριθμό τιμολογίου.', 'invoice_number_help' => 'Ορίστε ένα πρόθεμα ή χρησιμοποιήστε ένα προσαρμοσμένο μοτίβο για να καθορίζετε δυναμικά τον αριθμό τιμολογίου.',
'quote_number_help' => 'Ορίστε ένα πρόθεμα ή χρησιμοποιήστε ένα προσαρμοσμένο μοτίβο για να καθορίζετε δυναμικά τον αριθμό προσφοράς.', 'quote_number_help' => 'Ορίστε ένα πρόθεμα ή χρησιμοποιήστε ένα προσαρμοσμένο μοτίβο για να καθορίζετε δυναμικά τον αριθμό προσφοράς.',
'custom_client_fields_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα πελάτη και εμφανίστε την ετικέτα και την τιμή στο αρχείο PDF.', 'custom_client_fields_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα πελάτη και επιλέξτε δυνητικά την εμφάνισή της ετικέτας και της τιμής στο αρχείο PDF.',
'custom_account_fields_helps' => 'Προσθέστε μία ετικέτα και μία τιμή στο σημείο που αφορά τις λεπτομέρειες της εταιρίας στο αρχείο PDF.', 'custom_account_fields_helps' => 'Προσθέστε μία ετικέτα και μία τιμή στο σημείο που αφορά τις λεπτομέρειες της εταιρίας στο αρχείο PDF.',
'custom_invoice_fields_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα τιμολόγιο και εμφανίστε την ετικέτα και την τιμή στο αρχείο PDF.', 'custom_invoice_fields_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα τιμολόγιο και επιλέξτε δυνητικά την εμφάνισή της ετικέτας και της τιμής στο αρχείο PDF.',
'custom_invoice_charges_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα τιμολόγιο και συμπεριλάβετε την χρέωση στα υποσύνολα του τιμολογίου.', 'custom_invoice_charges_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα τιμολόγιο και συμπεριλάβετε την χρέωση στα υποσύνολα του τιμολογίου.',
'token_expired' => 'Το διακριτικό πιστοποίησης έχει λήξει. Παρακαλώ δοκιμάστε ξανά.', 'token_expired' => 'Το διακριτικό πιστοποίησης έχει λήξει. Παρακαλώ δοκιμάστε ξανά.',
'invoice_link' => 'Σύνδεσμος Τιμολογίου', 'invoice_link' => 'Σύνδεσμος Τιμολογίου',
@ -1043,7 +1043,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'invoice_item_fields' => 'Πεδία Προϊόντων Τιμολογίου', 'invoice_item_fields' => 'Πεδία Προϊόντων Τιμολογίου',
'custom_invoice_item_fields_help' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα προϊόν τιμολογίου και εμφανίστε την ετικέτα και την τιμή στο αρχείο PDF.', 'custom_invoice_item_fields_help' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα προϊόν τιμολογίου και εμφανίστε την ετικέτα και την τιμή στο αρχείο PDF.',
'recurring_invoice_number' => 'Επαναλαμβανόμενος Αριθμός', 'recurring_invoice_number' => 'Επαναλαμβανόμενος Αριθμός',
'recurring_invoice_number_prefix_help' => 'Ορίστε ένα πρόθεμα που να περιλαμβάνεται στον αριθμό τιμολογίου των επαναλαμβανόμενων τιμολογίων. Η εξ\'ορισμού τιμή είναι \'R\'.', 'recurring_invoice_number_prefix_help' => 'Ορίστε ένα πρόθεμα που να περιλαμβάνεται στον αριθμό τιμολογίου των επαναλαμβανόμενων τιμολογίων.',
// Client Passwords // Client Passwords
'enable_portal_password' => 'Προστασία Τιμολογίων με Κωδικό', 'enable_portal_password' => 'Προστασία Τιμολογίων με Κωδικό',
@ -1180,7 +1180,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
// Payment updates // Payment updates
'refund_payment' => 'Επιστροφή Πληρωμής', 'refund_payment' => 'Επιστροφή Πληρωμής',
'refund_max' => 'Μέγιστο:', 'refund_max' => 'Μέγιστο:',
'refund' => 'Επιστροφή', 'refund' => 'Επιστροφή χρημάτων',
'are_you_sure_refund' => 'Επιστροφή επιλεγμένων πληρωμών:', 'are_you_sure_refund' => 'Επιστροφή επιλεγμένων πληρωμών:',
'status_pending' => 'Σε εξέλιξη', 'status_pending' => 'Σε εξέλιξη',
'status_completed' => 'Ολοκληρώθηκε', 'status_completed' => 'Ολοκληρώθηκε',
@ -1189,9 +1189,9 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'status_partially_refunded_amount' => ':amount χρήματα επεστραφησαν', 'status_partially_refunded_amount' => ':amount χρήματα επεστραφησαν',
'status_refunded' => 'Επιστροφή χρημάτων', 'status_refunded' => 'Επιστροφή χρημάτων',
'status_voided' => 'Ακυρωμένη', 'status_voided' => 'Ακυρωμένη',
'refunded_payment' => 'Επεστραμένη Πληρωμής', 'refunded_payment' => 'Επεστραμένη Πληρωμή',
'activity_39' => 'Ο χρήστης :user ακύρωσε μία πληρωμή (:payment) ποσού :payment_amount', 'activity_39' => ':user ακύρωσε :payment_amount πληρωμής :payment',
'activity_40' => 'Ο χρήστης :user επέστρεψε :adjustment ποσό :payment_amount μιας πληρωμής (:payment)', 'activity_40' => ':user επέστρεψε :adjustment μιας :payment_amount πληρωμής :payment',
'card_expiration' => 'Λήξη:&nbsp:expires', 'card_expiration' => 'Λήξη:&nbsp:expires',
'card_creditcardother' => 'Άγνωστο', 'card_creditcardother' => 'Άγνωστο',
@ -1330,7 +1330,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'import_products' => 'Εισαγωγή Προϊόντων', 'import_products' => 'Εισαγωγή Προϊόντων',
'products_will_create' => 'προϊόντα θα δημιουργηθούν', 'products_will_create' => 'προϊόντα θα δημιουργηθούν',
'product_key' => 'Προϊόν', 'product_key' => 'Προϊόν',
'created_products' => 'Επιτυχής δημιουργία :count προϊόντων', 'created_products' => 'Επιτυχής δημιουργία/ενημέρωση :count προϊόν(των)',
'export_help' => 'Χρησιμοποιήστε JSON εάν σχεδιάζετε να εισάγετε δεδομένα στο Invoice Ninja.<br/>Το αρχείο περιλαμβάνει πελάτες, προϊόντα, τιμολόγια, προσφορές και πληρωμές.', 'export_help' => 'Χρησιμοποιήστε JSON εάν σχεδιάζετε να εισάγετε δεδομένα στο Invoice Ninja.<br/>Το αρχείο περιλαμβάνει πελάτες, προϊόντα, τιμολόγια, προσφορές και πληρωμές.',
'JSON_file' => 'Αρχείο JSON', 'JSON_file' => 'Αρχείο JSON',
@ -1996,7 +1996,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'edit_credit' => 'Επεξεργασία Πίστωσης', 'edit_credit' => 'Επεξεργασία Πίστωσης',
'live_preview_help' => 'Εμφάνιση μιας ζωντανής προεπισκόπησης του PDF του τιμολογίου.<br/>Απενεργοποιήστε αυτή την επιλογή για βελτίωση της ταχύτητας επεξεργασίας τιμολογίων.', 'live_preview_help' => 'Εμφάνιση μιας ζωντανής προεπισκόπησης του PDF του τιμολογίου.<br/>Απενεργοποιήστε αυτή την επιλογή για βελτίωση της ταχύτητας επεξεργασίας τιμολογίων.',
'force_pdfjs_help' => 'Αντικαταστήστε τον ενσωματωμένο παρουσιαστή PDF στο :chrome_link και :firefox_link.<br/>Ενεργοποιήστε αυτή την επιλογή εάν ο browser σας κατεβάζει αυτόματα το PDF.', 'force_pdfjs_help' => 'Αντικαταστήστε τον ενσωματωμένο παρουσιαστή PDF στο :chrome_link και :firefox_link.<br/>Ενεργοποιήστε αυτή την επιλογή εάν ο browser σας κατεβάζει αυτόματα το PDF.',
'force_pdfjs' => 'Παρεμπόδιση Μεταφόρτωσης', 'force_pdfjs' => 'Παρεμπόδιση Κατεβάσματος',
'redirect_url' => 'URL Ανακατεύθυνσης', 'redirect_url' => 'URL Ανακατεύθυνσης',
'redirect_url_help' => 'Εναλλακτικά ορίστε ένα URL για ανακατεύθυνση μετά την πραγματοποίηση μιας πληρωμής.', 'redirect_url_help' => 'Εναλλακτικά ορίστε ένα URL για ανακατεύθυνση μετά την πραγματοποίηση μιας πληρωμής.',
'save_draft' => 'Αποθήκευση Πρόχειρου', 'save_draft' => 'Αποθήκευση Πρόχειρου',
@ -2155,10 +2155,10 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'location_second_surcharge' => 'Ενεργοποιημένο - Δεύτερη επιβάρυνση', 'location_second_surcharge' => 'Ενεργοποιημένο - Δεύτερη επιβάρυνση',
'location_line_item' => 'Ενεργοποιημένο - Προϊόν γραμμής', 'location_line_item' => 'Ενεργοποιημένο - Προϊόν γραμμής',
'online_payment_surcharge' => 'Επιβάρυνση Πληρωμών Online', 'online_payment_surcharge' => 'Επιβάρυνση Πληρωμών Online',
'gateway_fees' => 'Προμήθειες Πύλης', 'gateway_fees' => 'Προμήθειες Πύλης Πληρωμής',
'fees_disabled' => 'Οι προμήθειες είναι απενεργοποιημένες', 'fees_disabled' => 'Οι προμήθειες είναι απενεργοποιημένες',
'gateway_fees_help' => 'Προσθέστε αυτόματα μία επιβάρυνση/έκπτωση online πληρωμής.', 'gateway_fees_help' => 'Προσθέστε αυτόματα μία επιβάρυνση/έκπτωση online πληρωμής.',
'gateway' => 'Πύλη (Gateway)', 'gateway' => 'Πύλη πληρωμής (Gateway)',
'gateway_fee_change_warning' => 'Εάν υπάρχουν απλήρωτα τιμολόγια με προμήθειες πρέπει να ενημερωθούν χειροκίνητα.', 'gateway_fee_change_warning' => 'Εάν υπάρχουν απλήρωτα τιμολόγια με προμήθειες πρέπει να ενημερωθούν χειροκίνητα.',
'fees_surcharge_help' => 'Προσαρμογή επιβάρυνσης :link.', 'fees_surcharge_help' => 'Προσαρμογή επιβάρυνσης :link.',
'label_and_taxes' => 'ετικέτες και φόρους', 'label_and_taxes' => 'ετικέτες και φόρους',
@ -2177,7 +2177,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'auto_bill_failed' => 'Αυτόματη τιμολόγηση για το τιμολόγιο :invoice_number failed', 'auto_bill_failed' => 'Αυτόματη τιμολόγηση για το τιμολόγιο :invoice_number failed',
'online_payment_discount' => 'Έκπτωση Online Πληρωμής', 'online_payment_discount' => 'Έκπτωση Online Πληρωμής',
'created_new_company' => 'Επιτυχής δημιουργία νέας εταιρίας', 'created_new_company' => 'Επιτυχής δημιουργία νέας εταιρίας',
'fees_disabled_for_gateway' => 'Οι προμήθειες είναι απενεργοποιημένες γι\' αυτή την πύλη.', 'fees_disabled_for_gateway' => 'Οι προμήθειες είναι απενεργοποιημένες γι\' αυτή την πύλη πληρωμής.',
'logout_and_delete' => 'Έξοδος/Διαγραφή λογαριασμού', 'logout_and_delete' => 'Έξοδος/Διαγραφή λογαριασμού',
'tax_rate_type_help' => 'Οι περιλαμβανόμενοι φόροι προσαρμόζουν το κόστος του αντικειμένου γραμμής όταν επιλεγούν.', 'tax_rate_type_help' => 'Οι περιλαμβανόμενοι φόροι προσαρμόζουν το κόστος του αντικειμένου γραμμής όταν επιλεγούν.',
'invoice_footer_help' => 'Χρησιμοποιήστε το $pageNumber και το $pageCount για να εμφανίσετε τις πληροφορίες σελίδας.', 'invoice_footer_help' => 'Χρησιμοποιήστε το $pageNumber και το $pageCount για να εμφανίσετε τις πληροφορίες σελίδας.',
@ -2188,7 +2188,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'credit_number' => 'Αριθμός Πίστωσης', 'credit_number' => 'Αριθμός Πίστωσης',
'create_credit_note' => 'Δημιουργία Πιστωτικού Σημειώματος', 'create_credit_note' => 'Δημιουργία Πιστωτικού Σημειώματος',
'menu' => 'Μενού', 'menu' => 'Μενού',
'error_incorrect_gateway_ids' => 'Σφάλμα: Ο πίνακας των πυλών (gateways) έχει λάθος αριθμούς.', 'error_incorrect_gateway_ids' => 'Σφάλμα: Ο πίνακας των πυλών πληρωμής (gateways) έχει λάθος αριθμούς.',
'purge_data' => 'Εκκαθάριση Δεδομένων', 'purge_data' => 'Εκκαθάριση Δεδομένων',
'delete_data' => 'Διαγραφή Δεδομένων', 'delete_data' => 'Διαγραφή Δεδομένων',
'purge_data_help' => 'Οριστική διαγραφή όλων των δεδομένων στο λογαριασμό, κρατώντας μόνο το λογαριασμό και τις ρυθμίσεις.', 'purge_data_help' => 'Οριστική διαγραφή όλων των δεδομένων στο λογαριασμό, κρατώντας μόνο το λογαριασμό και τις ρυθμίσεις.',
@ -2217,7 +2217,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'notes_auto_billed' => 'Αυτόματη χρέωση', 'notes_auto_billed' => 'Αυτόματη χρέωση',
'surcharge_label' => 'Ετικέτα Επιβάρυνσης', 'surcharge_label' => 'Ετικέτα Επιβάρυνσης',
'contact_fields' => 'Πεδία Επαφής', 'contact_fields' => 'Πεδία Επαφής',
'custom_contact_fields_help' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε μία επαφή και εμφανίστε την ετικέτα και την τιμή του στο αρχείο PDF.', 'custom_contact_fields_help' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε μία επαφή και επιλέξτε δυνητικά την εμφάνισή της ετικέτας και της τιμής στο αρχείο PDF.',
'datatable_info' => 'Εμφάνιση :start έως :end από :total εγγραφές', 'datatable_info' => 'Εμφάνιση :start έως :end από :total εγγραφές',
'credit_total' => 'Συνολική Πίστωση', 'credit_total' => 'Συνολική Πίστωση',
'mark_billable' => 'Σήμανση ως χρεώσιμο', 'mark_billable' => 'Σήμανση ως χρεώσιμο',
@ -2301,9 +2301,105 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'product_notes' => 'Σημειώσεις Προϊόντος', 'product_notes' => 'Σημειώσεις Προϊόντος',
'app_version' => 'Έκδοση Εφαρμογής', 'app_version' => 'Έκδοση Εφαρμογής',
'ofx_version' => 'Έκδοση OFX', 'ofx_version' => 'Έκδοση OFX',
'gateway_help_23' => ':link to get your Stripe API keys.', 'gateway_help_23' => ':link για να λάβετε τα κλειδιά του Stripe API.',
'error_app_key_not_set' => 'Error: the APP_KEY value is not set in the .env file.', 'error_app_key_set_to_default' => 'Σφάλμα: Το APP_KEY έχει οριστεί στην προκαθορισμένη τιμή, για να το ενημερώσετε κάντε αντίγραφο ασφαλείας από τη βάση δεδομένων και εκτελέστε το <code>php artisan ninja:update-key</code>',
'error_app_key_set_to_default' => 'Error: the APP_KEY value is set to the default in the .env file.' 'charge_late_fee' => 'Χρέωση Καθυστερημένης Εξόφλισης',
'late_fee_amount' => 'Ποσό Χρέωσης Καθυστερημένης Εξόφλισης',
'late_fee_percent' => 'Ποσοστό Χρέωσης Καθυστερημένης Εξόφλισης',
'late_fee_added' => 'Χρέωση καθυστερημένης εξόφλισης προστέθηκε την :date',
'download_invoice' => 'Κατέβασμα Τιμολογίου',
'download_quote' => 'Κατέβασμα Προσφοράς',
'invoices_are_attached' => 'Τα αρχεία PDF έχουν επισυναφθεί.',
'downloaded_invoice' => 'Θα αποσταλεί email με το τιμολόγιο σε αρχείο PDF',
'downloaded_quote' => 'Θα αποσταλεί email με την προσφορά σε αρχείο PDF',
'downloaded_invoices' => 'Θα αποσταλεί email με τα τιμολόγια σε αρχεία PDF',
'downloaded_quotes' => 'Θα αποσταλεί email με τις προσφορές σε αρχεία PDF',
'clone_expense' => 'Κλωνοποίηση Δαπάνης',
'default_documents' => 'Προεπιλεγμένα Κείμενα',
'send_email_to_client' => 'Αποστολή email στον πελάτη',
'refund_subject' => 'Επιστροφή Χρημάτων Επεξεργάσθηκε',
'refund_body' => 'Έχετε επιστροφή χρημάτων ποσού :amount για το τιμολόγιο :invoice_number.',
'currency_us_dollar' => 'Δολάριο Ηνωμένων Πολιτειών',
'currency_british_pound' => 'Βρετανική Λίρα',
'currency_euro' => 'Ευρώ',
'currency_south_african_rand' => 'Ραντ Νότιας Αφρικής',
'currency_danish_krone' => 'Δανική Κορώνα',
'currency_israeli_shekel' => 'Σέκελ Ισραήλ',
'currency_swedish_krona' => 'Κορώνα Σουηδίας',
'currency_kenyan_shilling' => 'Σελίνι Κένυας',
'currency_canadian_dollar' => 'Δολάριο Καναδά',
'currency_philippine_peso' => 'Πέσο Φιλιπίνων',
'currency_indian_rupee' => 'Ρουπία Ινδίας',
'currency_australian_dollar' => 'Δολάριο Αυστραλίας',
'currency_singapore_dollar' => 'Δολάριο Σιγκαπούρης',
'currency_norske_kroner' => 'Κορώνα Νορβηγίας',
'currency_new_zealand_dollar' => 'Δολάριο Νέας Ζηλανδίας',
'currency_vietnamese_dong' => 'Ντονγκ Βιετνάμ',
'currency_swiss_franc' => 'Φράγκο Σουηδίας',
'currency_guatemalan_quetzal' => 'Κουετσάλ Γουατεμάλας',
'currency_malaysian_ringgit' => 'Ρινγκίτ Μαλαισίας',
'currency_brazilian_real' => 'Ρεάλ Βραζιλίας',
'currency_thai_baht' => 'Μπατ Ταϊλάνδης',
'currency_nigerian_naira' => 'Νάιρα Νιγηρίας',
'currency_argentine_peso' => 'Πέσο Αργεντινής',
'currency_bangladeshi_taka' => 'Τάκα Μπαγκλαντές',
'currency_united_arab_emirates_dirham' => 'Ντιρχάμ Ηνωμένων Αραβικών Εμιράτων',
'currency_hong_kong_dollar' => 'Δολάριο Χονγκ Κονγκ',
'currency_indonesian_rupiah' => 'Ρουπία Ινδονησίας',
'currency_mexican_peso' => 'Πέσο Μεξικού',
'currency_egyptian_pound' => 'Λίρα Αιγύπτου',
'currency_colombian_peso' => 'Πέσο Κολομβίας',
'currency_west_african_franc' => 'Φράγκο Δυτικής Αφρικής',
'currency_chinese_renminbi' => 'Ρενμίνμπι Κίνας',
'currency_rwandan_franc' => 'Φράγκο Ρουάντα',
'currency_tanzanian_shilling' => 'Σελίνι Τανζανίας',
'currency_netherlands_antillean_guilder' => 'Γκίλντα Ολλανδικών Αντιλλών',
'currency_trinidad_and_tobago_dollar' => 'Δολάριο Τρινιντάντ και Ταμπάκο',
'currency_east_caribbean_dollar' => 'Δολάριο Ανατολικής Καραϊβικής',
'currency_ghanaian_cedi' => 'Σέντι Γκάνας',
'currency_bulgarian_lev' => 'Λέβαβ Βουλγαρίας',
'currency_aruban_florin' => 'Φιορίνι Αρούμπα',
'currency_turkish_lira' => 'Λίρα Τουρκίας',
'currency_romanian_new_leu' => 'Νέο Λέβα Ρουμανίας',
'currency_croatian_kuna' => 'Κούνα Κροατίας',
'currency_saudi_riyal' => 'Ριάλ Σαουδικής Αραβίας',
'currency_japanese_yen' => 'Γιεν Ιαπωνίας',
'currency_maldivian_rufiyaa' => 'Ρουφίγια Μαλδίβων',
'currency_costa_rican_colón' => 'Κολόνι Κόστα Ρίκα',
'currency_pakistani_rupee' => 'Ρουπία Πακιστάν',
'currency_polish_zloty' => 'Ζλότυ Πολωνίας',
'currency_sri_lankan_rupee' => 'Ρουπία Σρι Λάνκα',
'currency_czech_koruna' => 'Κορώνα Τσεχίας',
'currency_uruguayan_peso' => 'Πέσο Ουρουγουάης',
'currency_namibian_dollar' => 'Δολάριο Ναμίμπια',
'currency_tunisian_dinar' => 'Δηνάριο Τυνησίας',
'currency_russian_ruble' => 'Ρούβλι Ρωσίας',
'currency_mozambican_metical' => 'Μετικάλ Μοζαμβίκης',
'currency_omani_rial' => 'Ριάλ Ομάν',
'currency_ukrainian_hryvnia' => 'Γρίβνα Ουκρανίας',
'currency_macanese_pataca' => 'Πατάκα Μακάο',
'currency_taiwan_new_dollar' => 'Νέο Δολάριο Ταϊβάν',
'currency_dominican_peso' => 'Πέσο Αγίου Δομίνικου',
'currency_chilean_peso' => 'Πέσο χιλής',
'currency_icelandic_króna' => 'Κορώνα Ισλανδίας',
'currency_papua_new_guinean_kina' => 'Κίνα Παπούα και Νέα Γουινέα',
'currency_jordanian_dinar' => 'Δηνάριο Ιορδανίας',
'currency_myanmar_kyat' => 'Κιάτ Νιανμάρ',
'currency_peruvian_sol' => 'Σολ Περού',
'use_english_version' => 'Σιγουρευτείτε ότι χρησιμοποιείτε την Αγγλική έκδοση των αρχείων.<br/>Χρησιμοποιούμε τις κεφαλίδες των στηλών για να ταιριάξουμε τα πεδία.',
'tax1' => 'Πρώτο; Φόρος',
'tax2' => 'Δεύτερος Φόρος',
'fee_help' => 'Προμήθειες της πύλης πληρωμής (Gateway) είναι τα κόστη για την πρόσβαση στα δίκτυα που αναλαμβάνουν την επεξεργασία των online πληρωμών',
'format_export' => 'Μορφή εξαγωγής',
'custom1' => 'Πρώτη Προσαρμογή',
'custom2' => 'Δεύτερη Προσαρμογή',
'contact_first_name' => 'Όνομα Επαφής',
'contact_last_name' => 'Επώνυμο Επαφής',
'contact_custom1' => 'Πρώτη Προσαρμογή Επαφής',
'contact_custom2' => 'Δεύτερη Προσαρμογή Επαφής',
'currency' => 'Νόμισμα',
); );

View File

@ -854,9 +854,9 @@ $LANG = array(
'website_help' => 'Display the invoice in an iFrame on your own website', 'website_help' => 'Display the invoice in an iFrame on your own website',
'invoice_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the invoice number.', 'invoice_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the invoice number.',
'quote_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the quote number.', 'quote_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the quote number.',
'custom_client_fields_helps' => 'Add a field when creating a client and display the label and value on the PDF.', 'custom_client_fields_helps' => 'Add a field when creating a client and optionally display the label and value on the PDF.',
'custom_account_fields_helps' => 'Add a label and value to the company details section of the PDF.', 'custom_account_fields_helps' => 'Add a label and value to the company details section of the PDF.',
'custom_invoice_fields_helps' => 'Add a field when creating an invoice and display the label and value on the PDF.', 'custom_invoice_fields_helps' => 'Add a field when creating an invoice and optionally display the label and value on the PDF.',
'custom_invoice_charges_helps' => 'Add a field when creating an invoice and include the charge in the invoice subtotals.', 'custom_invoice_charges_helps' => 'Add a field when creating an invoice and include the charge in the invoice subtotals.',
'token_expired' => 'Validation token was expired. Please try again.', 'token_expired' => 'Validation token was expired. Please try again.',
'invoice_link' => 'Invoice Link', 'invoice_link' => 'Invoice Link',
@ -1043,7 +1043,7 @@ $LANG = array(
'invoice_item_fields' => 'Invoice Item Fields', 'invoice_item_fields' => 'Invoice Item Fields',
'custom_invoice_item_fields_help' => 'Add a field when creating an invoice item and display the label and value on the PDF.', 'custom_invoice_item_fields_help' => 'Add a field when creating an invoice item and display the label and value on the PDF.',
'recurring_invoice_number' => 'Recurring Number', 'recurring_invoice_number' => 'Recurring Number',
'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices. The default value is \'R\'.', 'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices.',
// Client Passwords // Client Passwords
'enable_portal_password' => 'Password Protect Invoices', 'enable_portal_password' => 'Password Protect Invoices',
@ -1190,8 +1190,8 @@ $LANG = array(
'status_refunded' => 'Refunded', 'status_refunded' => 'Refunded',
'status_voided' => 'Cancelled', 'status_voided' => 'Cancelled',
'refunded_payment' => 'Refunded Payment', 'refunded_payment' => 'Refunded Payment',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)', 'activity_39' => ':user cancelled a :payment_amount payment :payment',
'activity_40' => ':user refunded :adjustment of a :payment_amount payment (:payment)', 'activity_40' => ':user refunded :adjustment of a :payment_amount payment :payment',
'card_expiration' => 'Exp:&nbsp:expires', 'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Unknown', 'card_creditcardother' => 'Unknown',
@ -1330,7 +1330,7 @@ $LANG = array(
'import_products' => 'Import Products', 'import_products' => 'Import Products',
'products_will_create' => 'products will be created', 'products_will_create' => 'products will be created',
'product_key' => 'Product', 'product_key' => 'Product',
'created_products' => 'Successfully created :count product(s)', 'created_products' => 'Successfully created/updated :count product(s)',
'export_help' => 'Use JSON if you plan to import the data into Invoice Ninja.<br/>The file includes clients, products, invoices, quotes and payments.', 'export_help' => 'Use JSON if you plan to import the data into Invoice Ninja.<br/>The file includes clients, products, invoices, quotes and payments.',
'JSON_file' => 'JSON File', 'JSON_file' => 'JSON File',
@ -2217,7 +2217,7 @@ $LANG = array(
'notes_auto_billed' => 'Auto-billed', 'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label', 'surcharge_label' => 'Surcharge Label',
'contact_fields' => 'Contact Fields', 'contact_fields' => 'Contact Fields',
'custom_contact_fields_help' => 'Add a field when creating a contact and display the label and value on the PDF.', 'custom_contact_fields_help' => 'Add a field when creating a contact and optionally display the label and value on the PDF.',
'datatable_info' => 'Showing :start to :end of :total entries', 'datatable_info' => 'Showing :start to :end of :total entries',
'credit_total' => 'Credit Total', 'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable', 'mark_billable' => 'Mark billable',
@ -2302,8 +2302,104 @@ $LANG = array(
'app_version' => 'App Version', 'app_version' => 'App Version',
'ofx_version' => 'OFX Version', 'ofx_version' => 'OFX Version',
'gateway_help_23' => ':link to get your Stripe API keys.', 'gateway_help_23' => ':link to get your Stripe API keys.',
'error_app_key_not_set' => 'Error: the APP_KEY value is not set in the .env file.', 'error_app_key_set_to_default' => 'Error: APP_KEY is set to a default value, to update it backup your database and then run <code>php artisan ninja:update-key</code>',
'error_app_key_set_to_default' => 'Error: the APP_KEY value is set to the default in the .env file.' 'charge_late_fee' => 'Charge Late Fee',
'late_fee_amount' => 'Late Fee Amount',
'late_fee_percent' => 'Late Fee Percent',
'late_fee_added' => 'Late fee added on :date',
'download_invoice' => 'Download Invoice',
'download_quote' => 'Download Quote',
'invoices_are_attached' => 'Your invoice PDFs are attached.',
'downloaded_invoice' => 'An email will be sent with the invoice PDF',
'downloaded_quote' => 'An email will be sent with the quote PDF',
'downloaded_invoices' => 'An email will be sent with the invoice PDFs',
'downloaded_quotes' => 'An email will be sent with the quote PDFs',
'clone_expense' => 'Clone Expense',
'default_documents' => 'Default Documents',
'send_email_to_client' => 'Send email to the client',
'refund_subject' => 'Refund Processed',
'refund_body' => 'You have been processed a refund of :amount for invoice :invoice_number.',
'currency_us_dollar' => 'US Dollar',
'currency_british_pound' => 'British Pound',
'currency_euro' => 'Euro',
'currency_south_african_rand' => 'South African Rand',
'currency_danish_krone' => 'Danish Krone',
'currency_israeli_shekel' => 'Israeli Shekel',
'currency_swedish_krona' => 'Swedish Krona',
'currency_kenyan_shilling' => 'Kenyan Shilling',
'currency_canadian_dollar' => 'Canadian Dollar',
'currency_philippine_peso' => 'Philippine Peso',
'currency_indian_rupee' => 'Indian Rupee',
'currency_australian_dollar' => 'Australian Dollar',
'currency_singapore_dollar' => 'Singapore Dollar',
'currency_norske_kroner' => 'Norske Kroner',
'currency_new_zealand_dollar' => 'New Zealand Dollar',
'currency_vietnamese_dong' => 'Vietnamese Dong',
'currency_swiss_franc' => 'Swiss Franc',
'currency_guatemalan_quetzal' => 'Guatemalan Quetzal',
'currency_malaysian_ringgit' => 'Malaysian Ringgit',
'currency_brazilian_real' => 'Brazilian Real',
'currency_thai_baht' => 'Thai Baht',
'currency_nigerian_naira' => 'Nigerian Naira',
'currency_argentine_peso' => 'Argentine Peso',
'currency_bangladeshi_taka' => 'Bangladeshi Taka',
'currency_united_arab_emirates_dirham' => 'United Arab Emirates Dirham',
'currency_hong_kong_dollar' => 'Hong Kong Dollar',
'currency_indonesian_rupiah' => 'Indonesian Rupiah',
'currency_mexican_peso' => 'Mexican Peso',
'currency_egyptian_pound' => 'Egyptian Pound',
'currency_colombian_peso' => 'Colombian Peso',
'currency_west_african_franc' => 'West African Franc',
'currency_chinese_renminbi' => 'Chinese Renminbi',
'currency_rwandan_franc' => 'Rwandan Franc',
'currency_tanzanian_shilling' => 'Tanzanian Shilling',
'currency_netherlands_antillean_guilder' => 'Netherlands Antillean Guilder',
'currency_trinidad_and_tobago_dollar' => 'Trinidad and Tobago Dollar',
'currency_east_caribbean_dollar' => 'East Caribbean Dollar',
'currency_ghanaian_cedi' => 'Ghanaian Cedi',
'currency_bulgarian_lev' => 'Bulgarian Lev',
'currency_aruban_florin' => 'Aruban Florin',
'currency_turkish_lira' => 'Turkish Lira',
'currency_romanian_new_leu' => 'Romanian New Leu',
'currency_croatian_kuna' => 'Croatian Kuna',
'currency_saudi_riyal' => 'Saudi Riyal',
'currency_japanese_yen' => 'Japanese Yen',
'currency_maldivian_rufiyaa' => 'Maldivian Rufiyaa',
'currency_costa_rican_colón' => 'Costa Rican Colón',
'currency_pakistani_rupee' => 'Pakistani Rupee',
'currency_polish_zloty' => 'Polish Zloty',
'currency_sri_lankan_rupee' => 'Sri Lankan Rupee',
'currency_czech_koruna' => 'Czech Koruna',
'currency_uruguayan_peso' => 'Uruguayan Peso',
'currency_namibian_dollar' => 'Namibian Dollar',
'currency_tunisian_dinar' => 'Tunisian Dinar',
'currency_russian_ruble' => 'Russian Ruble',
'currency_mozambican_metical' => 'Mozambican Metical',
'currency_omani_rial' => 'Omani Rial',
'currency_ukrainian_hryvnia' => 'Ukrainian Hryvnia',
'currency_macanese_pataca' => 'Macanese Pataca',
'currency_taiwan_new_dollar' => 'Taiwan New Dollar',
'currency_dominican_peso' => 'Dominican Peso',
'currency_chilean_peso' => 'Chilean Peso',
'currency_icelandic_króna' => 'Icelandic Króna',
'currency_papua_new_guinean_kina' => 'Papua New Guinean Kina',
'currency_jordanian_dinar' => 'Jordanian Dinar',
'currency_myanmar_kyat' => 'Myanmar Kyat',
'currency_peruvian_sol' => 'Peruvian Sol',
'use_english_version' => 'Make sure to use the English version of the files.<br/>We use the column headers to match the fields.',
'tax1' => 'First Tax',
'tax2' => 'Second Tax',
'fee_help' => 'Gateway fees are the costs charged for access to the financial networks that handle the processing of online payments.',
'format_export' => 'Exporting format',
'custom1' => 'First Custom',
'custom2' => 'Second Custom',
'contact_first_name' => 'Contact First Name',
'contact_last_name' => 'Contact Last Name',
'contact_custom1' => 'Contact First Custom',
'contact_custom2' => 'Contact Second Custom',
'currency' => 'Currency',
); );

View File

@ -848,9 +848,9 @@ $LANG = array(
'website_help' => 'Display the invoice in an iFrame on your own website', 'website_help' => 'Display the invoice in an iFrame on your own website',
'invoice_number_help' => 'Especifique un prefijo o utilice un patrón a medida para establecer dinámicamente el número de factura.', 'invoice_number_help' => 'Especifique un prefijo o utilice un patrón a medida para establecer dinámicamente el número de factura.',
'quote_number_help' => 'Especifique un prefijo o utilice un patrón a medida para establecer dinámicamente el número de presupuesto.', 'quote_number_help' => 'Especifique un prefijo o utilice un patrón a medida para establecer dinámicamente el número de presupuesto.',
'custom_client_fields_helps' => 'Agregar una entrada de texto a la pagina de crear/editar cliente y mostrar la etiqueta y el valor en el PDF.', 'custom_client_fields_helps' => 'Add a field when creating a client and optionally display the label and value on the PDF.',
'custom_account_fields_helps' => 'Añadir una etiqueta y valor a la sección de detalles de la empresa del PDF.', 'custom_account_fields_helps' => 'Añadir una etiqueta y valor a la sección de detalles de la empresa del PDF.',
'custom_invoice_fields_helps' => 'Agregar una entrada de texto a la pagina de crear/editar factura y mostrar la etiqueta y el valor en el PDF.', 'custom_invoice_fields_helps' => 'Add a field when creating an invoice and optionally display the label and value on the PDF.',
'custom_invoice_charges_helps' => 'gregar una entrada de texto a la pagina de crear/editar factura y mostrar la carga en los subtotales de la factura.', 'custom_invoice_charges_helps' => 'gregar una entrada de texto a la pagina de crear/editar factura y mostrar la carga en los subtotales de la factura.',
'token_expired' => 'Token de validación ha caducado. Por favor, vuelva a intentarlo.', 'token_expired' => 'Token de validación ha caducado. Por favor, vuelva a intentarlo.',
'invoice_link' => 'Enlace a Factura', 'invoice_link' => 'Enlace a Factura',
@ -1036,7 +1036,7 @@ $LANG = array(
'invoice_item_fields' => 'Campos de Ítem de Factura', 'invoice_item_fields' => 'Campos de Ítem de Factura',
'custom_invoice_item_fields_help' => 'Agregar un campo al crear un ítem de factura y mostrar la etiqueta y valor en el PDF.', 'custom_invoice_item_fields_help' => 'Agregar un campo al crear un ítem de factura y mostrar la etiqueta y valor en el PDF.',
'recurring_invoice_number' => 'Recurring Number', 'recurring_invoice_number' => 'Recurring Number',
'recurring_invoice_number_prefix_help' => 'Especificar un prefijo para las facturas recurrentes. Por defecto es \'R\'.', 'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices.',
// Client Passwords // Client Passwords
'enable_portal_password' => 'Proteger Facturas con Contraseña', 'enable_portal_password' => 'Proteger Facturas con Contraseña',
@ -1183,8 +1183,8 @@ $LANG = array(
'status_refunded' => 'Refunded', 'status_refunded' => 'Refunded',
'status_voided' => 'Cancelled', 'status_voided' => 'Cancelled',
'refunded_payment' => 'Refunded Payment', 'refunded_payment' => 'Refunded Payment',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)', 'activity_39' => ':user cancelled a :payment_amount payment :payment',
'activity_40' => ':user refunded :adjustment of a :payment_amount payment (:payment)', 'activity_40' => ':user refunded :adjustment of a :payment_amount payment :payment',
'card_expiration' => 'Exp:&nbsp:expires', 'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Unknown', 'card_creditcardother' => 'Unknown',
@ -1323,7 +1323,7 @@ $LANG = array(
'import_products' => 'Import Products', 'import_products' => 'Import Products',
'products_will_create' => 'productos serán creados', 'products_will_create' => 'productos serán creados',
'product_key' => 'Product', 'product_key' => 'Product',
'created_products' => 'Successfully created :count product(s)', 'created_products' => 'Successfully created/updated :count product(s)',
'export_help' => 'Use JSON si planea importar la información en Invoice Ninja.<br/>El archivo incluye clientes, productos, facturas, cotizaciones y pagos.', 'export_help' => 'Use JSON si planea importar la información en Invoice Ninja.<br/>El archivo incluye clientes, productos, facturas, cotizaciones y pagos.',
'JSON_file' => 'JSON File', 'JSON_file' => 'JSON File',
@ -2210,7 +2210,7 @@ $LANG = array(
'notes_auto_billed' => 'Auto-billed', 'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label', 'surcharge_label' => 'Surcharge Label',
'contact_fields' => 'Contact Fields', 'contact_fields' => 'Contact Fields',
'custom_contact_fields_help' => 'Add a field when creating a contact and display the label and value on the PDF.', 'custom_contact_fields_help' => 'Add a field when creating a contact and optionally display the label and value on the PDF.',
'datatable_info' => 'Showing :start to :end of :total entries', 'datatable_info' => 'Showing :start to :end of :total entries',
'credit_total' => 'Credit Total', 'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable', 'mark_billable' => 'Mark billable',
@ -2295,8 +2295,104 @@ $LANG = array(
'app_version' => 'App Version', 'app_version' => 'App Version',
'ofx_version' => 'OFX Version', 'ofx_version' => 'OFX Version',
'gateway_help_23' => ':link to get your Stripe API keys.', 'gateway_help_23' => ':link to get your Stripe API keys.',
'error_app_key_not_set' => 'Error: the APP_KEY value is not set in the .env file.', 'error_app_key_set_to_default' => 'Error: APP_KEY is set to a default value, to update it backup your database and then run <code>php artisan ninja:update-key</code>',
'error_app_key_set_to_default' => 'Error: the APP_KEY value is set to the default in the .env file.' 'charge_late_fee' => 'Charge Late Fee',
'late_fee_amount' => 'Late Fee Amount',
'late_fee_percent' => 'Late Fee Percent',
'late_fee_added' => 'Late fee added on :date',
'download_invoice' => 'Download Invoice',
'download_quote' => 'Download Quote',
'invoices_are_attached' => 'Your invoice PDFs are attached.',
'downloaded_invoice' => 'An email will be sent with the invoice PDF',
'downloaded_quote' => 'An email will be sent with the quote PDF',
'downloaded_invoices' => 'An email will be sent with the invoice PDFs',
'downloaded_quotes' => 'An email will be sent with the quote PDFs',
'clone_expense' => 'Clone Expense',
'default_documents' => 'Default Documents',
'send_email_to_client' => 'Send email to the client',
'refund_subject' => 'Refund Processed',
'refund_body' => 'You have been processed a refund of :amount for invoice :invoice_number.',
'currency_us_dollar' => 'US Dollar',
'currency_british_pound' => 'British Pound',
'currency_euro' => 'Euro',
'currency_south_african_rand' => 'South African Rand',
'currency_danish_krone' => 'Danish Krone',
'currency_israeli_shekel' => 'Israeli Shekel',
'currency_swedish_krona' => 'Swedish Krona',
'currency_kenyan_shilling' => 'Kenyan Shilling',
'currency_canadian_dollar' => 'Canadian Dollar',
'currency_philippine_peso' => 'Philippine Peso',
'currency_indian_rupee' => 'Indian Rupee',
'currency_australian_dollar' => 'Australian Dollar',
'currency_singapore_dollar' => 'Singapore Dollar',
'currency_norske_kroner' => 'Norske Kroner',
'currency_new_zealand_dollar' => 'New Zealand Dollar',
'currency_vietnamese_dong' => 'Vietnamese Dong',
'currency_swiss_franc' => 'Swiss Franc',
'currency_guatemalan_quetzal' => 'Guatemalan Quetzal',
'currency_malaysian_ringgit' => 'Malaysian Ringgit',
'currency_brazilian_real' => 'Brazilian Real',
'currency_thai_baht' => 'Thai Baht',
'currency_nigerian_naira' => 'Nigerian Naira',
'currency_argentine_peso' => 'Argentine Peso',
'currency_bangladeshi_taka' => 'Bangladeshi Taka',
'currency_united_arab_emirates_dirham' => 'United Arab Emirates Dirham',
'currency_hong_kong_dollar' => 'Hong Kong Dollar',
'currency_indonesian_rupiah' => 'Indonesian Rupiah',
'currency_mexican_peso' => 'Mexican Peso',
'currency_egyptian_pound' => 'Egyptian Pound',
'currency_colombian_peso' => 'Colombian Peso',
'currency_west_african_franc' => 'West African Franc',
'currency_chinese_renminbi' => 'Chinese Renminbi',
'currency_rwandan_franc' => 'Rwandan Franc',
'currency_tanzanian_shilling' => 'Tanzanian Shilling',
'currency_netherlands_antillean_guilder' => 'Netherlands Antillean Guilder',
'currency_trinidad_and_tobago_dollar' => 'Trinidad and Tobago Dollar',
'currency_east_caribbean_dollar' => 'East Caribbean Dollar',
'currency_ghanaian_cedi' => 'Ghanaian Cedi',
'currency_bulgarian_lev' => 'Bulgarian Lev',
'currency_aruban_florin' => 'Aruban Florin',
'currency_turkish_lira' => 'Turkish Lira',
'currency_romanian_new_leu' => 'Romanian New Leu',
'currency_croatian_kuna' => 'Croatian Kuna',
'currency_saudi_riyal' => 'Saudi Riyal',
'currency_japanese_yen' => 'Japanese Yen',
'currency_maldivian_rufiyaa' => 'Maldivian Rufiyaa',
'currency_costa_rican_colón' => 'Costa Rican Colón',
'currency_pakistani_rupee' => 'Pakistani Rupee',
'currency_polish_zloty' => 'Polish Zloty',
'currency_sri_lankan_rupee' => 'Sri Lankan Rupee',
'currency_czech_koruna' => 'Czech Koruna',
'currency_uruguayan_peso' => 'Uruguayan Peso',
'currency_namibian_dollar' => 'Namibian Dollar',
'currency_tunisian_dinar' => 'Tunisian Dinar',
'currency_russian_ruble' => 'Russian Ruble',
'currency_mozambican_metical' => 'Mozambican Metical',
'currency_omani_rial' => 'Omani Rial',
'currency_ukrainian_hryvnia' => 'Ukrainian Hryvnia',
'currency_macanese_pataca' => 'Macanese Pataca',
'currency_taiwan_new_dollar' => 'Taiwan New Dollar',
'currency_dominican_peso' => 'Dominican Peso',
'currency_chilean_peso' => 'Chilean Peso',
'currency_icelandic_króna' => 'Icelandic Króna',
'currency_papua_new_guinean_kina' => 'Papua New Guinean Kina',
'currency_jordanian_dinar' => 'Jordanian Dinar',
'currency_myanmar_kyat' => 'Myanmar Kyat',
'currency_peruvian_sol' => 'Peruvian Sol',
'use_english_version' => 'Make sure to use the English version of the files.<br/>We use the column headers to match the fields.',
'tax1' => 'First Tax',
'tax2' => 'Second Tax',
'fee_help' => 'Gateway fees are the costs charged for access to the financial networks that handle the processing of online payments.',
'format_export' => 'Exporting format',
'custom1' => 'First Custom',
'custom2' => 'Second Custom',
'contact_first_name' => 'Contact First Name',
'contact_last_name' => 'Contact Last Name',
'contact_custom1' => 'Contact First Custom',
'contact_custom2' => 'Contact Second Custom',
'currency' => 'Currency',
); );

View File

@ -849,9 +849,9 @@ Acceder a 10 hermosos diseños de Factura',
'website_help' => 'Display the invoice in an iFrame on your own website', 'website_help' => 'Display the invoice in an iFrame on your own website',
'invoice_number_help' => 'Especifique un prefijo o utilice un patrón a medida para establecer dinámicamente el número de factura.', 'invoice_number_help' => 'Especifique un prefijo o utilice un patrón a medida para establecer dinámicamente el número de factura.',
'quote_number_help' => 'Especifique un prefijo o utilice un patrón a medida para establecer dinámicamente el número de presupuesto.', 'quote_number_help' => 'Especifique un prefijo o utilice un patrón a medida para establecer dinámicamente el número de presupuesto.',
'custom_client_fields_helps' => 'Añadir un campo al crear un cliente y mostrar la etiqueta y su valor en el PDF.', 'custom_client_fields_helps' => 'Add a field when creating a client and optionally display the label and value on the PDF.',
'custom_account_fields_helps' => 'Añadir una etiqueta y su valor a la sección de detalles de la empresa del PDF.', 'custom_account_fields_helps' => 'Añadir una etiqueta y su valor a la sección de detalles de la empresa del PDF.',
'custom_invoice_fields_helps' => 'Añadir un campo al crear una factura y mostrar la etiqueta y su valor en el PDF.', 'custom_invoice_fields_helps' => 'Add a field when creating an invoice and optionally display the label and value on the PDF.',
'custom_invoice_charges_helps' => 'Añadir un campo al crear una factura e incluir el cargo en el subtotal de la factura.', 'custom_invoice_charges_helps' => 'Añadir un campo al crear una factura e incluir el cargo en el subtotal de la factura.',
'token_expired' => 'Token de validación ha caducado. Por favor, vuelva a intentarlo.', 'token_expired' => 'Token de validación ha caducado. Por favor, vuelva a intentarlo.',
'invoice_link' => 'Enlace a Factura', 'invoice_link' => 'Enlace a Factura',
@ -1039,7 +1039,7 @@ Atención! tu password puede estar transmitida como texto plano, considera habil
'invoice_item_fields' => 'Campos de concepto de factura', 'invoice_item_fields' => 'Campos de concepto de factura',
'custom_invoice_item_fields_help' => 'Añadir un campo al crear un concepto de factura y mostrar la etiqueta y su valor en el PDF.', 'custom_invoice_item_fields_help' => 'Añadir un campo al crear un concepto de factura y mostrar la etiqueta y su valor en el PDF.',
'recurring_invoice_number' => 'Recurring Number', 'recurring_invoice_number' => 'Recurring Number',
'recurring_invoice_number_prefix_help' => 'Especifique un prefijo que se antepondrá al número de factura sólo para las facturas recurrentes. El valor predeterminado es \'R\'.', 'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices.',
// Client Passwords // Client Passwords
'enable_portal_password' => 'Password Protect Invoices', 'enable_portal_password' => 'Password Protect Invoices',
@ -1186,8 +1186,8 @@ Atención! tu password puede estar transmitida como texto plano, considera habil
'status_refunded' => 'Reembolsado', 'status_refunded' => 'Reembolsado',
'status_voided' => 'Cancelado', 'status_voided' => 'Cancelado',
'refunded_payment' => 'Pago Reembolsado', 'refunded_payment' => 'Pago Reembolsado',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)', 'activity_39' => ':user cancelled a :payment_amount payment :payment',
'activity_40' => ':user refunded :adjustment of a :payment_amount payment (:payment)', 'activity_40' => ':user refunded :adjustment of a :payment_amount payment :payment',
'card_expiration' => 'Exp:&nbsp:expires', 'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Desconocido', 'card_creditcardother' => 'Desconocido',
@ -1326,7 +1326,7 @@ Atención! tu password puede estar transmitida como texto plano, considera habil
'import_products' => 'Import Products', 'import_products' => 'Import Products',
'products_will_create' => 'products will be created', 'products_will_create' => 'products will be created',
'product_key' => 'Producto', 'product_key' => 'Producto',
'created_products' => 'Successfully created :count product(s)', 'created_products' => 'Successfully created/updated :count product(s)',
'export_help' => 'Use JSON if you plan to import the data into Invoice Ninja.<br/>The file includes clients, products, invoices, quotes and payments.', 'export_help' => 'Use JSON if you plan to import the data into Invoice Ninja.<br/>The file includes clients, products, invoices, quotes and payments.',
'JSON_file' => 'JSON File', 'JSON_file' => 'JSON File',
@ -2213,7 +2213,7 @@ Atención! tu password puede estar transmitida como texto plano, considera habil
'notes_auto_billed' => 'Auto-billed', 'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label', 'surcharge_label' => 'Surcharge Label',
'contact_fields' => 'Contact Fields', 'contact_fields' => 'Contact Fields',
'custom_contact_fields_help' => 'Add a field when creating a contact and display the label and value on the PDF.', 'custom_contact_fields_help' => 'Add a field when creating a contact and optionally display the label and value on the PDF.',
'datatable_info' => 'Showing :start to :end of :total entries', 'datatable_info' => 'Showing :start to :end of :total entries',
'credit_total' => 'Credit Total', 'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable', 'mark_billable' => 'Mark billable',
@ -2298,8 +2298,104 @@ Atención! tu password puede estar transmitida como texto plano, considera habil
'app_version' => 'App Version', 'app_version' => 'App Version',
'ofx_version' => 'OFX Version', 'ofx_version' => 'OFX Version',
'gateway_help_23' => ':link to get your Stripe API keys.', 'gateway_help_23' => ':link to get your Stripe API keys.',
'error_app_key_not_set' => 'Error: the APP_KEY value is not set in the .env file.', 'error_app_key_set_to_default' => 'Error: APP_KEY is set to a default value, to update it backup your database and then run <code>php artisan ninja:update-key</code>',
'error_app_key_set_to_default' => 'Error: the APP_KEY value is set to the default in the .env file.' 'charge_late_fee' => 'Charge Late Fee',
'late_fee_amount' => 'Late Fee Amount',
'late_fee_percent' => 'Late Fee Percent',
'late_fee_added' => 'Late fee added on :date',
'download_invoice' => 'Download Invoice',
'download_quote' => 'Download Quote',
'invoices_are_attached' => 'Your invoice PDFs are attached.',
'downloaded_invoice' => 'An email will be sent with the invoice PDF',
'downloaded_quote' => 'An email will be sent with the quote PDF',
'downloaded_invoices' => 'An email will be sent with the invoice PDFs',
'downloaded_quotes' => 'An email will be sent with the quote PDFs',
'clone_expense' => 'Clone Expense',
'default_documents' => 'Default Documents',
'send_email_to_client' => 'Send email to the client',
'refund_subject' => 'Refund Processed',
'refund_body' => 'You have been processed a refund of :amount for invoice :invoice_number.',
'currency_us_dollar' => 'US Dollar',
'currency_british_pound' => 'British Pound',
'currency_euro' => 'Euro',
'currency_south_african_rand' => 'South African Rand',
'currency_danish_krone' => 'Danish Krone',
'currency_israeli_shekel' => 'Israeli Shekel',
'currency_swedish_krona' => 'Swedish Krona',
'currency_kenyan_shilling' => 'Kenyan Shilling',
'currency_canadian_dollar' => 'Canadian Dollar',
'currency_philippine_peso' => 'Philippine Peso',
'currency_indian_rupee' => 'Indian Rupee',
'currency_australian_dollar' => 'Australian Dollar',
'currency_singapore_dollar' => 'Singapore Dollar',
'currency_norske_kroner' => 'Norske Kroner',
'currency_new_zealand_dollar' => 'New Zealand Dollar',
'currency_vietnamese_dong' => 'Vietnamese Dong',
'currency_swiss_franc' => 'Swiss Franc',
'currency_guatemalan_quetzal' => 'Guatemalan Quetzal',
'currency_malaysian_ringgit' => 'Malaysian Ringgit',
'currency_brazilian_real' => 'Brazilian Real',
'currency_thai_baht' => 'Thai Baht',
'currency_nigerian_naira' => 'Nigerian Naira',
'currency_argentine_peso' => 'Argentine Peso',
'currency_bangladeshi_taka' => 'Bangladeshi Taka',
'currency_united_arab_emirates_dirham' => 'United Arab Emirates Dirham',
'currency_hong_kong_dollar' => 'Hong Kong Dollar',
'currency_indonesian_rupiah' => 'Indonesian Rupiah',
'currency_mexican_peso' => 'Mexican Peso',
'currency_egyptian_pound' => 'Egyptian Pound',
'currency_colombian_peso' => 'Colombian Peso',
'currency_west_african_franc' => 'West African Franc',
'currency_chinese_renminbi' => 'Chinese Renminbi',
'currency_rwandan_franc' => 'Rwandan Franc',
'currency_tanzanian_shilling' => 'Tanzanian Shilling',
'currency_netherlands_antillean_guilder' => 'Netherlands Antillean Guilder',
'currency_trinidad_and_tobago_dollar' => 'Trinidad and Tobago Dollar',
'currency_east_caribbean_dollar' => 'East Caribbean Dollar',
'currency_ghanaian_cedi' => 'Ghanaian Cedi',
'currency_bulgarian_lev' => 'Bulgarian Lev',
'currency_aruban_florin' => 'Aruban Florin',
'currency_turkish_lira' => 'Turkish Lira',
'currency_romanian_new_leu' => 'Romanian New Leu',
'currency_croatian_kuna' => 'Croatian Kuna',
'currency_saudi_riyal' => 'Saudi Riyal',
'currency_japanese_yen' => 'Japanese Yen',
'currency_maldivian_rufiyaa' => 'Maldivian Rufiyaa',
'currency_costa_rican_colón' => 'Costa Rican Colón',
'currency_pakistani_rupee' => 'Pakistani Rupee',
'currency_polish_zloty' => 'Polish Zloty',
'currency_sri_lankan_rupee' => 'Sri Lankan Rupee',
'currency_czech_koruna' => 'Czech Koruna',
'currency_uruguayan_peso' => 'Uruguayan Peso',
'currency_namibian_dollar' => 'Namibian Dollar',
'currency_tunisian_dinar' => 'Tunisian Dinar',
'currency_russian_ruble' => 'Russian Ruble',
'currency_mozambican_metical' => 'Mozambican Metical',
'currency_omani_rial' => 'Omani Rial',
'currency_ukrainian_hryvnia' => 'Ukrainian Hryvnia',
'currency_macanese_pataca' => 'Macanese Pataca',
'currency_taiwan_new_dollar' => 'Taiwan New Dollar',
'currency_dominican_peso' => 'Dominican Peso',
'currency_chilean_peso' => 'Chilean Peso',
'currency_icelandic_króna' => 'Icelandic Króna',
'currency_papua_new_guinean_kina' => 'Papua New Guinean Kina',
'currency_jordanian_dinar' => 'Jordanian Dinar',
'currency_myanmar_kyat' => 'Myanmar Kyat',
'currency_peruvian_sol' => 'Peruvian Sol',
'use_english_version' => 'Make sure to use the English version of the files.<br/>We use the column headers to match the fields.',
'tax1' => 'First Tax',
'tax2' => 'Second Tax',
'fee_help' => 'Gateway fees are the costs charged for access to the financial networks that handle the processing of online payments.',
'format_export' => 'Exporting format',
'custom1' => 'First Custom',
'custom2' => 'Second Custom',
'contact_first_name' => 'Contact First Name',
'contact_last_name' => 'Contact Last Name',
'contact_custom1' => 'Contact First Custom',
'contact_custom2' => 'Contact Second Custom',
'currency' => 'Currency',
); );

Some files were not shown because too many files have changed in this diff Show More