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

View File

@ -63,8 +63,30 @@ class SendReminders extends Command
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();
$this->info(count($accounts) . ' accounts found');
$this->info(count($accounts) . ' accounts found with reminders');
/** @var \App\Models\Account $account */
foreach ($accounts as $account) {
@ -78,7 +100,7 @@ class SendReminders extends Command
/** @var Invoice $invoice */
foreach ($invoices as $invoice) {
if ($reminder = $account->getInvoiceReminder($invoice)) {
$this->info('Send to ' . $invoice->id);
$this->info('Send email: ' . $invoice->id);
$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\InitLookup',
'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_PENDING_GATEWAY_FEE', 3);
define('INVOICE_ITEM_TYPE_PAID_GATEWAY_FEE', 4);
define('INVOICE_ITEM_TYPE_LATE_FEE', 5);
define('PERSON_CONTACT', 'contact');
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_DOCS_URL', env('NINJA_DOCS_URL', 'http://docs.invoiceninja.com/en/latest'));
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_TWITTER', env('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja'));
@ -569,6 +570,9 @@ if (! defined('APP_NAME')) {
];
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
function uctrans($text)
{

View File

@ -423,7 +423,6 @@ class AccountController extends BaseController
'timezones' => Cache::get('timezones'),
'dateFormats' => Cache::get('dateFormats'),
'datetimeFormats' => Cache::get('datetimeFormats'),
'currencies' => Cache::get('currencies'),
'title' => trans('texts.localization'),
'weekdays' => Utils::getTranslatedWeekdayNames(),
'months' => Utils::getMonthOptions(),
@ -823,6 +822,10 @@ class AccountController extends BaseController
$account->{"num_days_{$type}"} = Input::get("num_days_{$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}");
$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();

View File

@ -191,7 +191,6 @@ class ClientController extends BaseController
'data' => Input::old('data'),
'account' => Auth::user()->account,
'sizes' => Cache::get('sizes'),
'currencies' => Cache::get('currencies'),
'customLabel1' => Auth::user()->account->custom_client_label1,
'customLabel2' => Auth::user()->account->custom_client_label2,
];
@ -225,25 +224,51 @@ class ClientController extends BaseController
return $this->returnBulk(ENTITY_CLIENT, $action, $ids);
}
public function statement()
public function statement($clientPublicId, $statusId = false, $startDate = false, $endDate = false)
{
$account = Auth::user()->account;
$statusId = intval($statusId);
$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->client = $client;
$invoice->date_format = $account->date_format ? $account->date_format->format_moment : 'MMM D, YYYY';
$invoice->invoice_items = Invoice::scope()
$invoices = Invoice::scope()
->with(['client'])
->whereClientId($client->id)
->invoices()
->whereClientId($client->id)
->whereIsPublic(true)
->where('balance', '>', 0)
->get();
->orderBy('invoice_date', 'asc');
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 = [
'showBreadcrumbs' => false,
'client' => $client,
'invoice' => $invoice,
'account' => $account,
'startDate' => $startDate,
'endDate' => $endDate,
];
return view('clients.statement', $data);

View File

@ -130,7 +130,7 @@ class ClientPortalController extends BaseController
$showApprove = $invoice->quote_invoice_id ? false : true;
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) {
$showApprove = false;
@ -369,7 +369,7 @@ class ClientPortalController extends BaseController
'client' => $contact->client,
'title' => trans('texts.invoices'),
'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);
@ -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;
})
->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) {
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,
'title' => trans('texts.quotes'),
'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);
@ -584,6 +584,10 @@ class ClientPortalController extends BaseController
private function returnError($error = false)
{
if (request()->phantomjs) {
abort(404);
}
return response()->view('error', [
'error' => $error ?: trans('texts.invoice_not_found'),
'hideHeader' => true,
@ -745,7 +749,9 @@ class ClientPortalController extends BaseController
$document = Document::scope($publicId, $invitation->account_id)->firstOrFail();
$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;
} elseif ($document->invoice && $document->invoice->client_id == $invitation->invoice->client_id) {
$authorized = true;

View File

@ -94,11 +94,20 @@ class ExpenseController extends BaseController
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();
$actions = [];
if (! $clone) {
$actions[] = ['url' => 'javascript:submitAction("clone")', 'label' => trans("texts.clone_expense")];
}
if ($expense->invoice) {
$actions[] = ['url' => URL::to("invoices/{$expense->invoice->public_id}/edit"), 'label' => trans('texts.view_invoice')];
} else {
@ -124,12 +133,28 @@ class ExpenseController extends BaseController
$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 = [
'vendor' => null,
'expense' => $expense,
'entity' => $expense,
'method' => 'PUT',
'url' => 'expenses/'.$expense->public_id,
'method' => $method,
'url' => $url,
'title' => 'Edit Expense',
'actions' => $actions,
'vendors' => Vendor::scope()->with('vendor_contacts')->orderBy('name')->get(),
@ -165,8 +190,12 @@ class ExpenseController extends BaseController
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");
}
}
public function store(CreateExpenseRequest $request)
{
@ -260,14 +289,6 @@ class ExpenseController extends BaseController
return [
'data' => Input::old('data'),
'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(),
'taxRates' => TaxRate::scope()->whereIsInclusive(false)->orderBy('name')->get(),
'isRecurring' => false,

View File

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

View File

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

View File

@ -423,7 +423,12 @@ class InvoiceApiController extends BaseAPIController
public function download(InvoiceRequest $request)
{
$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'),
'products' => Product::scope()->orderBy('product_key')->get(),
'taxRateOptions' => $taxRateOptions,
'currencies' => Cache::get('currencies'),
'sizes' => Cache::get('sizes'),
'invoiceDesigns' => InvoiceDesign::getDesigns(),
'invoiceFonts' => Cache::get('fonts'),
@ -480,6 +479,8 @@ class InvoiceController extends BaseController
$key = 'emailed_' . $entityType;
} elseif ($action == 'markPaid') {
$key = 'created_payment';
} elseif ($action == 'download') {
$key = 'downloaded_invoice';
} else {
$key = "{$action}d_{$entityType}";
}

View File

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

View File

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

View File

@ -100,18 +100,15 @@ class QuoteController extends BaseController
'account' => $account,
'products' => Product::scope()->orderBy('product_key')->get(),
'taxRateOptions' => $account->present()->taxRateOptions,
'countries' => Cache::get('countries'),
'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(),
'taxRates' => TaxRate::scope()->orderBy('name')->get(),
'currencies' => Cache::get('currencies'),
'sizes' => Cache::get('sizes'),
'paymentTerms' => Cache::get('paymentTerms'),
'languages' => Cache::get('languages'),
'industries' => Cache::get('industries'),
'invoiceDesigns' => InvoiceDesign::getDesigns(),
'invoiceFonts' => Cache::get('fonts'),
'invoiceLabels' => Auth::user()->account->getInvoiceLabels(),
'isRecurring' => false,
'expenses' => [],
];
}
@ -133,7 +130,13 @@ class QuoteController extends BaseController
$count = $this->invoiceService->bulk($ids, $action);
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);
Session::flash('message', $message);
}

View File

@ -115,14 +115,6 @@ class RecurringExpenseController extends BaseController
return [
'data' => Input::old('data'),
'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(),
'taxRates' => TaxRate::scope()->whereIsInclusive(false)->orderBy('name')->get(),
'isRecurring' => true,

View File

@ -8,6 +8,7 @@ use Input;
use Str;
use Utils;
use View;
use Excel;
/**
* Class ReportController.
@ -53,6 +54,7 @@ class ReportController extends BaseController
}
$action = Input::get('action');
$format = Input::get('format');
if (Input::get('report_type')) {
$reportType = Input::get('report_type');
@ -104,7 +106,7 @@ class ReportController extends BaseController
$params['report'] = $report;
$params = array_merge($params, $report->results());
if ($isExport) {
self::export($reportType, $params['displayData'], $params['columns'], $params['reportTotals']);
return self::export($format, $reportType, $params);
}
} else {
$params['columns'] = [];
@ -117,49 +119,80 @@ class ReportController extends BaseController
}
/**
* @param $format
* @param $reportType
* @param $data
* @param $columns
* @param $totals
* @param $params
* @todo: Add summary to export
*/
private function export($reportType, $data, $columns, $totals)
private function export($format, $reportType, $params)
{
if (! Auth::user()->hasPermission('view_all')) {
exit;
}
$output = fopen('php://output', 'w') or Utils::fatalError();
$date = date('Y-m-d');
$format = strtolower($format);
$data = $params['displayData'];
$columns = $params['columns'];
$totals = $params['reportTotals'];
$report = $params['report'];
$columns = array_map(function($key, $val) {
return is_array($val) ? $key : $val;
}, array_keys($columns), $columns);
$filename = "{$params['startDate']}-{$params['endDate']}_invoiceninja-".strtolower(Utils::normalizeChars(trans("texts.$reportType")))."-report";
header('Content-Type:application/csv');
header("Content-Disposition:attachment;filename={$date}-invoiceninja-{$reportType}-report.csv");
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;
$formats = ['csv', 'pdf', 'xlsx'];
if(!in_array($format, $formats)) {
throw new \Exception("Invalid format request to export report");
}
foreach ($totals as $currencyId => $fields) {
$csv = Utils::getFromCache($currencyId, 'currencies')->name . ',';
foreach ($fields as $key => $value) {
$csv .= '"' . Utils::formatMoney($value, $currencyId).'",';
}
fwrite($output, $csv."\n");
}
*/
//Get labeled header
$columns_labeled = $report->tableHeaderArray();
fclose($output);
exit;
/*$summary = [];
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) : [];
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)
{
if (Auth::user()->hasFeature(FEATURE_USERS)) {
if (! Auth::user()->hasFeature(FEATURE_USERS)) {
return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
}
$rules = [
'first_name' => 'required',
'last_name' => 'required',
@ -227,7 +230,6 @@ class UserController extends BaseController
}
Session::flash('message', $message);
}
return Redirect::to('users/' . $user->public_id . '/edit');
}

View File

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

View File

@ -68,7 +68,7 @@ class Authenticate
}
$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
$authenticated = true;
}

View File

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

View File

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

View File

@ -2,6 +2,7 @@
namespace App\Http\ViewComposers;
use Str;
use Cache;
use Illuminate\View\View;
@ -44,5 +45,11 @@ class TranslationComposer
})->sortBy(function ($lang) {
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/activities/{client_id?}', 'ActivityController@getDatatable');
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::get('api/tasks/{client_id?}', 'TaskController@getDatatable');
@ -224,6 +224,7 @@ Route::group(['middleware' => ['lookup:user', 'auth:user']], function () {
// Expense
Route::resource('expenses', 'ExpenseController');
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/{id}', 'ExpenseController@getDatatableVendor');
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->save();
session([RECENTLY_VIEWED => false]);
if (env('MULTI_DB_ENABLED')) {
$current = config('database.default');
config(['database.default' => DB_NINJA_LOOKUP]);

View File

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

View File

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

View File

@ -916,7 +916,7 @@ class Utils
$str = '';
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) {
$str .= 'ENTITY_DELETED ';
@ -1052,20 +1052,15 @@ class Utils
}
}
public static function formatWebsite($website)
public static function formatWebsite($link)
{
if (! $website) {
if (! $link) {
return '';
}
$link = $website;
$title = $website;
$prefix = 'http://';
if (strlen($link) > 7 && substr($link, 0, 7) === $prefix) {
$title = substr($title, 7);
} else {
$link = $prefix.$link;
$title = $link;
if (substr($link, 0, 4) != 'http') {
$link = 'http://' . $link;
}
return link_to($link, $title, ['target' => '_blank']);
@ -1246,4 +1241,64 @@ class Utils
fclose($handle);
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']));
}
// check custom gateway id is correct
if (! Utils::isNinja()) {
// check custom gateway id is correct
$gateway = Gateway::find(GATEWAY_CUSTOM);
if (! $gateway || $gateway->name !== 'Custom') {
Session::flash('error', trans('texts.error_incorrect_gateway_ids'));
}
/*
if (! env('APP_KEY')) {
Session::flash('error', trans('texts.error_app_key_not_set'));
} elseif (strstr(env('APP_KEY'), 'SomeRandomString')) {
// make sure APP_KEY and APP_CIPHER are in the .env file
$appKey = env('APP_KEY');
$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'));
}
*/
}
}
}

View File

@ -332,6 +332,14 @@ class Account extends Eloquent
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
*/

View File

@ -27,6 +27,12 @@ class AccountEmailSettings extends Eloquent
'email_template_reminder1',
'email_template_reminder2',
'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 = [
'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,
'quote' => $invoice ? link_to($invoice->getRoute(), $invoice->getDisplayName()) : null,
'contact' => $contactId ? $client->getDisplayName() : $user->getDisplayName(),
'payment' => $payment ? $payment->transaction_reference : null,
'contact' => $contactId ? e($client->getDisplayName()) : e($user->getDisplayName()),
'payment' => $payment ? e($payment->transaction_reference) : null,
'payment_amount' => $payment ? $account->formatMoney($payment->amount, $payment) : null,
'adjustment' => $this->adjustment ? $account->formatMoney($this->adjustment, $this) : null,
'credit' => $credit ? $account->formatMoney($credit->amount, $client) : null,

View File

@ -2,6 +2,7 @@
namespace App\Models;
use Crypt;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
@ -33,6 +34,22 @@ class BankAccount extends EntityModel
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
*/

View File

@ -54,54 +54,7 @@ class Client extends EntityModel
'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
@ -109,22 +62,28 @@ class Client extends EntityModel
public static function getImportColumns()
{
return [
self::$fieldName,
self::$fieldPhone,
self::$fieldAddress1,
self::$fieldAddress2,
self::$fieldCity,
self::$fieldState,
self::$fieldPostalCode,
self::$fieldCountry,
self::$fieldNotes,
self::$fieldWebsite,
self::$fieldVatNumber,
self::$fieldIdNumber,
Contact::$fieldFirstName,
Contact::$fieldLastName,
Contact::$fieldPhone,
Contact::$fieldEmail,
'name',
'work_phone',
'address1',
'address2',
'city',
'state',
'postal_code',
'public_notes',
'private_notes',
'country',
'website',
'currency',
'vat_number',
'id_number',
'custom1',
'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()
{
return [
'first' => 'first_name',
'last' => 'last_name',
'email' => 'email',
'mobile|phone' => 'phone',
'first' => 'contact_first_name',
'last' => 'contact_last_name',
'email' => 'contact_email',
'work|office' => 'work_phone',
'mobile|phone' => 'contact_phone',
'name|organization' => 'name',
'apt|street2|address2' => 'address2',
'street|address|address1' => 'address1',
@ -145,8 +105,10 @@ class Client extends EntityModel
'state|province' => 'state',
'zip|postal|code' => 'postal_code',
'country' => 'country',
'note' => 'notes',
'public' => 'public_notes',
'private|note' => 'private_notes',
'site|website' => 'website',
'currency' => 'currency',
'vat' => 'vat_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);
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();
} else {
$contact = Contact::createNew();

View File

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

View File

@ -115,6 +115,8 @@ class Invoice extends EntityModel implements BalanceAffecting
'terms',
'product',
'quantity',
'tax1',
'tax2',
];
}
@ -135,6 +137,7 @@ class Invoice extends EntityModel implements BalanceAffecting
'notes' => 'notes',
'product|item' => 'product',
'quantity|qty' => 'quantity',
'tax' => 'tax1',
];
}
@ -305,6 +308,23 @@ class Invoice extends EntityModel implements BalanceAffecting
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
*/
@ -1319,7 +1339,7 @@ class Invoice extends EntityModel implements BalanceAffecting
/**
* @return int
*/
public function countDocuments()
public function countDocuments($expenses = false)
{
$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;
}
@ -1337,7 +1365,11 @@ class Invoice extends EntityModel implements BalanceAffecting
*/
public function hasDocuments()
{
if (count($this->documents)) {
if ($this->documents->count()) {
return true;
}
if ($this->account->defaultDocuments->count()) {
return true;
}

View File

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

View File

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

View File

@ -4,6 +4,7 @@ namespace App\Models\Traits;
use App\Constants\Domain;
use Utils;
use HTMLUtils;
/**
* Class SendsEmails.
@ -36,7 +37,8 @@ trait SendsEmails
$value = $this->account_email_settings->$field;
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);
// <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
*/
public function getReminderDate($reminder)
public function getReminderDate($reminder, $filterEnabled = true)
{
if (! $this->{"enable_reminder{$reminder}"}) {
if ($filterEnabled && ! $this->{"enable_reminder{$reminder}"}) {
return false;
}
@ -142,10 +146,10 @@ trait SendsEmails
*
* @return bool|string
*/
public function getInvoiceReminder($invoice)
public function getInvoiceReminder($invoice, $filterEnabled = true)
{
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';
if ($invoice->$field == $date) {
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',
function ($model) {
return $model->public_notes;
return e($model->public_notes);
},
],
[
'private_notes',
function ($model) {
return $model->private_notes;
return e($model->private_notes);
},
],
];

View File

@ -84,7 +84,7 @@ class ExpenseDatatable extends EntityDatatable
[
'public_notes',
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]);
},
],
[
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'),
function ($model) {

View File

@ -181,14 +181,18 @@ class InvoiceDatatable extends EntityDatatable
public function bulkActions()
{
$actions = parent::bulkActions();
$actions = [];
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[] = [
'label' => mtrans($this->entityType, 'email_' . $this->entityType),
'url' => 'javascript:submitForm_'.$this->entityType.'("emailInvoice")',
];
$actions[] = \DropdownButton::DIVIDER;
$actions[] = [
'label' => mtrans($this->entityType, 'mark_sent'),
'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;
}
}

View File

@ -46,7 +46,7 @@ class PaymentDatatable extends EntityDatatable
[
'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>';
},
],
[

View File

@ -24,7 +24,7 @@ class ProductDatatable extends EntityDatatable
[
'notes',
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',
function ($model) {
return $model->private_notes;
return e($model->private_notes);
},
],
[

View File

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

View File

@ -14,7 +14,7 @@ class UserDatatable extends EntityDatatable
[
'first_name',
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
*/
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;
}
/**
* @param $name
*
* @return null
*/
public function getProductNotes($name)
{
$name = strtolower(trim($name));
$product = $this->maps['product'][$productKey];
return isset($this->maps['product_notes'][$name]) ? $this->maps['product_notes'][$name] : null;
}
/**
* @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;
return $product->$field ?: $default;
}
/**
@ -156,6 +138,30 @@ class BaseTransformer extends TransformerAbstract
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
*

View File

@ -26,22 +26,29 @@ class ClientTransformer extends BaseTransformer
'name' => $this->getString($data, 'name'),
'work_phone' => $this->getString($data, 'work_phone'),
'address1' => $this->getString($data, 'address1'),
'address2' => $this->getString($data, 'address2'),
'city' => $this->getString($data, 'city'),
'state' => $this->getString($data, 'state'),
'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'),
'vat_number' => $this->getString($data, 'vat_number'),
'id_number' => $this->getString($data, 'id_number'),
'custom_value1' => $this->getString($data, 'custom1'),
'custom_value2' => $this->getString($data, 'custom2'),
'contacts' => [
[
'first_name' => $this->getString($data, 'first_name'),
'last_name' => $this->getString($data, 'last_name'),
'email' => $this->getString($data, 'email'),
'phone' => $this->getString($data, 'phone'),
'first_name' => $this->getString($data, 'contact_first_name'),
'last_name' => $this->getString($data, 'contact_last_name'),
'email' => $this->getString($data, 'contact_email'),
'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,
'currency_code' => $this->getString($data, 'currency'),
];
});
}

View File

@ -38,9 +38,13 @@ class InvoiceTransformer extends BaseTransformer
'invoice_items' => [
[
'product_key' => $this->getString($data, 'product'),
'notes' => $this->getString($data, 'notes') ?: $this->getProductNotes($this->getString($data, 'product')),
'cost' => $this->getFloat($data, 'amount') ?: $this->getProductCost($this->getString($data, 'product')),
'notes' => $this->getString($data, 'notes') ?: $this->getProduct($data, 'product', 'notes', ''),
'cost' => $this->getFloat($data, 'amount') ?: $this->getProduct($data, 'product', 'cost', 0),
'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 [
'public_id' => $this->getProduct($data, 'product_key', 'public_id'),
'product_key' => $this->getString($data, 'product_key'),
'notes' => $this->getString($data, 'notes'),
'cost' => $this->getFloat($data, 'cost'),

View File

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

View File

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

View File

@ -119,6 +119,18 @@ class StripePaymentDriver extends BasePaymentDriver
$data = $this->paymentDetails();
$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'])) {
$plaidResult = $this->getPlaidToken($data['plaidPublicToken'], $data['plaidAccountId']);
unset($data['plaidPublicToken']);
@ -126,11 +138,6 @@ class StripePaymentDriver extends BasePaymentDriver
$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()
->createCard($data)
->send();
@ -146,7 +153,11 @@ class StripePaymentDriver extends BasePaymentDriver
public function creatingCustomer($customer)
{
if (isset($this->tokenResponse['customer'])) {
$customer->token = $this->tokenResponse['customer'];
} else {
$customer->token = $this->tokenResponse['id'];
}
return $customer;
}

View File

@ -22,6 +22,28 @@ class AccountPresenter extends Presenter
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
*/
@ -144,7 +166,7 @@ class AccountPresenter extends Presenter
if ($rate->is_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;

View File

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

View File

@ -285,7 +285,11 @@ class InvoicePresenter extends EntityPresenter
$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()

View File

@ -52,9 +52,8 @@ class AbstractReport
$this->totals[$currencyId][$dimension][$field] += $value;
}
public function tableHeader()
{
$str = '';
public function tableHeaderArray() {
$columns_labeled = [];
foreach ($this->columns as $key => $val) {
if (is_array($val)) {
@ -75,9 +74,21 @@ class AbstractReport
$class = count($class) ? implode(' ', $class) : 'group-false';
$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;
}

View File

@ -662,6 +662,18 @@ class AccountRepository
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)
{
$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);
})
->addColumn('public_notes', function ($model) {
return $model->public_notes;
return e($model->public_notes);
})
->make();

View File

@ -290,6 +290,9 @@ class InvoiceRepository extends BaseRepository
'invoices.invoice_date',
'invoices.balance as balance',
'invoices.due_date',
'invoices.invoice_status_id',
'invoices.due_date',
'invoices.quote_invoice_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"),
'invoices.public_id',
@ -324,6 +327,34 @@ class InvoiceRepository extends BaseRepository
return $table->addColumn('due_date', function ($model) {
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();
}
@ -655,7 +686,7 @@ class InvoiceRepository extends BaseRepository
if ($account->update_products
&& ! $invoice->has_tasks
&& ! $invoice->has_expenses
&& $productKey != trans('texts.surcharge')
&& ! in_array($productKey, Utils::trans(['surcharge', 'discount', 'fee']))
) {
$product = Product::findProductByKey($productKey);
if (! $product) {
@ -1096,19 +1127,24 @@ class InvoiceRepository extends BaseRepository
*
* @return mixed
*/
public function findNeedingReminding(Account $account)
public function findNeedingReminding(Account $account, $filterEnabled = true)
{
$dates = [];
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';
$dates[] = "$field = '$date'";
}
}
if (! count($dates)) {
return [];
}
$sql = implode(' OR ', $dates);
$invoices = Invoice::invoiceType(INVOICE_TYPE_STANDARD)
->with('invoice_items')
->whereAccountId($account->id)
->where('balance', '>', 0)
->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)
{
$account = $invoice->account;

View File

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

View File

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

View File

@ -78,7 +78,7 @@ class DatatableService
$dropdown_contents = '';
$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) {
if (count($action)) {
// if show function isn't set default to true
@ -119,11 +119,15 @@ class DatatableService
$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) {
$dropdown_contents .= "<li><a href=\"javascript:submitForm_{$datatable->entityType}('archive', {$model->public_id})\">"
. 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})\">"
. 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\ProductRepository;
use App\Ninja\Repositories\VendorRepository;
use App\Ninja\Repositories\TaxRateRepository;
use App\Ninja\Serializers\ArraySerializer;
use Auth;
use Cache;
@ -126,7 +127,8 @@ class ImportService
ProductRepository $productRepo,
ExpenseRepository $expenseRepo,
VendorRepository $vendorRepo,
ExpenseCategoryRepository $expenseCategoryRepo
ExpenseCategoryRepository $expenseCategoryRepo,
TaxRateRepository $taxRateRepository
) {
$this->fractal = $manager;
$this->fractal->setSerializer(new ArraySerializer());
@ -139,6 +141,7 @@ class ImportService
$this->expenseRepo = $expenseRepo;
$this->vendorRepo = $vendorRepo;
$this->expenseCategoryRepo = $expenseCategoryRepo;
$this->taxRateRepository = $taxRateRepository;
}
/**
@ -849,6 +852,8 @@ class ImportService
'invoice_ids' => [],
'vendors' => [],
'expense_categories' => [],
'tax_rates' => [],
'tax_names' => [],
];
$clients = $this->clientRepo->all();
@ -886,6 +891,13 @@ class ImportService
foreach ($expenseCaegories as $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)
{
if ($key = strtolower(trim($product->product_key))) {
$this->maps['product'][$key] = $product->id;
$this->maps['product_notes'][$key] = $product->notes;
$this->maps['product_cost'][$key] = $product->cost;
$this->maps['product'][$key] = $product;
}
}

View File

@ -9,6 +9,7 @@ use App\Models\Invoice;
use App\Ninja\Datatables\InvoiceDatatable;
use App\Ninja\Repositories\ClientRepository;
use App\Ninja\Repositories\InvoiceRepository;
use App\Jobs\DownloadInvoices;
use Auth;
use Utils;
@ -54,6 +55,23 @@ class InvoiceService extends BaseService
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 Invoice|null $invoice

View File

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

View File

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

View File

@ -66,6 +66,7 @@
"meebio/omnipay-creditcall": "dev-master",
"meebio/omnipay-secure-trading": "dev-master",
"mfauveau/omnipay-pacnet": "~2.0",
"mpdf/mpdf": "^6.1",
"nwidart/laravel-modules": "^1.14",
"omnipay/2checkout": "dev-master#e9c079c2dde0d7ba461903b3b7bd5caf6dee1248",
"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",
"This file is @generated automatically"
],
"hash": "e8611674b74a220909d4c70784f2e227",
"content-hash": "8d418324fd6e8b5af5c7b2058e31d898",
"hash": "f57537fe1dab41aac024b12e4a284570",
"content-hash": "9d0ce024f2c50440bf896ecc2a37350f",
"packages": [
{
"name": "agmscode/omnipay-agms",
@ -68,12 +68,12 @@
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/alfaproject/omnipay-skrill.git",
"url": "https://github.com/xcaliber-tech/omnipay-skrill.git",
"reference": "41a7a03c5b90d496720e288bebc157d898837ccd"
},
"dist": {
"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",
"shasum": ""
},
@ -4723,6 +4723,57 @@
],
"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",
"version": "v1.2.0",
@ -7537,6 +7588,55 @@
],
"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",
"version": "dev-master",
@ -8044,7 +8144,7 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v2.8.24",
"version": "v2.8.26",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
@ -8202,16 +8302,16 @@
},
{
"name": "symfony/http-foundation",
"version": "v2.8.24",
"version": "v2.8.26",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "2b592ca5fe2ad7ee8a92d409d2b830277ad58231"
"reference": "9ff3a0b3756ace2e3da7dded37e920ee776faa4e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/2b592ca5fe2ad7ee8a92d409d2b830277ad58231",
"reference": "2b592ca5fe2ad7ee8a92d409d2b830277ad58231",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/9ff3a0b3756ace2e3da7dded37e920ee776faa4e",
"reference": "9ff3a0b3756ace2e3da7dded37e920ee776faa4e",
"shasum": ""
},
"require": {
@ -8253,7 +8353,7 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
"time": "2017-06-20 23:27:56"
"time": "2017-07-17 14:02:19"
},
{
"name": "symfony/http-kernel",

View File

@ -1,5 +1,23 @@
<?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(
'cache' => array(
@ -171,7 +189,7 @@ return array(
| 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
*/
'driver' => 'DomPDF',
'driver' => 'mPDF',
/*
|--------------------------------------------------------------------------
@ -306,7 +324,7 @@ return 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)),
'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.
#
# The short X.Y version.
version = u'3.5'
version = u'3.6'
# 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
# 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.
- 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'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
""""""""""""

View File

@ -86,8 +86,7 @@ elixir(function(mix) {
mix.scripts([
'pdf_viewer.js',
'compatibility.js',
//bowerDir + '/pdfmake/build/pdfmake.js',
'pdfmake.js',
bowerDir + '/pdfmake/build/pdfmake.js',
'vfs.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 {
color: #5cb85c;
}
.tooltip-inner {
white-space: normal;
}

View File

@ -191,12 +191,20 @@
left:0;
right:0;
text-align:left;
background-color:#000;
width:100%;
min-width:250px;
}
.sidebar-nav-dark li div.nav-footer {
background-color: #000;
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 {
color:#ccc !important;
}

View File

@ -854,9 +854,9 @@ $LANG = array(
'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.',
'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_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.',
'token_expired' => 'Validation token was expired. Please try again.',
'invoice_link' => 'Invoice Link',
@ -1043,7 +1043,7 @@ $LANG = array(
'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.',
'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
'enable_portal_password' => 'Password Protect Invoices',
@ -1190,8 +1190,8 @@ $LANG = array(
'status_refunded' => 'Refunded',
'status_voided' => 'Cancelled',
'refunded_payment' => 'Refunded Payment',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)',
'activity_40' => ':user refunded :adjustment of 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',
'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Unknown',
@ -1330,7 +1330,7 @@ $LANG = array(
'import_products' => 'Import Products',
'products_will_create' => 'products will be created',
'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.',
'JSON_file' => 'JSON File',
@ -2217,7 +2217,7 @@ $LANG = array(
'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label',
'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',
'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable',
@ -2302,8 +2302,104 @@ $LANG = array(
'app_version' => 'App Version',
'ofx_version' => 'OFX Version',
'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: the APP_KEY value is set to the default 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>',
'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',
'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.',
'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_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.',
'token_expired' => 'Validační token expiroval. Prosím vyzkoušejte znovu.',
'invoice_link' => 'Odkaz na fakturu',
@ -1045,7 +1045,7 @@ $LANG = array(
'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.',
'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
'enable_portal_password' => 'Password Protect Invoices',
@ -1192,8 +1192,8 @@ $LANG = array(
'status_refunded' => 'Refunded',
'status_voided' => 'Cancelled',
'refunded_payment' => 'Refunded Payment',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)',
'activity_40' => ':user refunded :adjustment of 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',
'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Unknown',
@ -1332,7 +1332,7 @@ $LANG = array(
'import_products' => 'Import Products',
'products_will_create' => 'products will be created',
'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.',
'JSON_file' => 'JSON File',
@ -2219,7 +2219,7 @@ $LANG = array(
'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label',
'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',
'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable',
@ -2304,8 +2304,104 @@ $LANG = array(
'app_version' => 'App Version',
'ofx_version' => 'OFX Version',
'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: the APP_KEY value is set to the default 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>',
'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',
'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.',
'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_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.',
'token_expired' => 'Validation token was expired. Please try again.',
'invoice_link' => 'Invoice Link',
@ -1043,7 +1043,7 @@ $LANG = array(
'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.',
'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
'enable_portal_password' => 'Password Protect Invoices',
@ -1190,8 +1190,8 @@ $LANG = array(
'status_refunded' => 'Refunded',
'status_voided' => 'Cancelled',
'refunded_payment' => 'Refunded Payment',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)',
'activity_40' => ':user refunded :adjustment of 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',
'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Unknown',
@ -1330,7 +1330,7 @@ $LANG = array(
'import_products' => 'Import Products',
'products_will_create' => 'products will be created',
'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.',
'JSON_file' => 'JSON File',
@ -2217,7 +2217,7 @@ $LANG = array(
'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label',
'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',
'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable',
@ -2302,8 +2302,104 @@ $LANG = array(
'app_version' => 'App Version',
'ofx_version' => 'OFX Version',
'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: the APP_KEY value is set to the default 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>',
'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(
'organization' => 'Unternehmenn',
'organization' => 'Unternehmen',
'name' => 'Name',
'website' => 'Webseite',
'work_phone' => 'Telefon',
@ -854,9 +854,9 @@ $LANG = array(
'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.',
'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_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.',
'token_expired' => 'Validierungstoken ist abgelaufen. Bitte probieren Sie es erneut.',
'invoice_link' => 'Link zur Rechnung',
@ -1043,7 +1043,7 @@ $LANG = array(
'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.',
'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
'enable_portal_password' => 'Rechnungen mit Passwort schützen',
@ -1190,8 +1190,8 @@ $LANG = array(
'status_refunded' => 'Erstattet',
'status_voided' => 'Abgebrochen',
'refunded_payment' => 'Zahlung erstattet',
'activity_39' => ':user brach eine Zahlung über :payment_amount ab (:payment)',
'activity_40' => ':user rückerstattete :adjustment einer :payment_amount Zahlung (:payment)',
'activity_39' => ':user cancelled a :payment_amount payment :payment',
'activity_40' => ':user refunded :adjustment of a :payment_amount payment :payment',
'card_expiration' => 'Ablaufdatum:&nbsp:expires',
'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',
'products_will_create' => 'Produkte werden erstellt werden',
'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.',
'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',
'surcharge_label' => 'Aufschlagsfeldbezeichnung',
'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',
'credit_total' => 'Credit Total',
'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',
'import_failed' => 'Import fehlgeschlagen',
'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.',
'next_credit_number' => 'The next credit number is :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',
'ofx_version' => 'OFX Version',
'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: the APP_KEY value is set to the default 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>',
'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' => 'Διαγραφή λογότυπου',
'logo_help' => 'Υποστηρίζονται: JPEG, GIF και PNG',
'payment_gateway' => 'Πύλη Πληρωμών (Gateway)',
'gateway_id' => 'Πύλη (Gateway)',
'gateway_id' => 'Πύλη Πληρωμής (Gateway)',
'email_notifications' => 'Ειδοποιήσεις Email',
'email_sent' => 'Αποστολή email όταν το τιμολόγιο <b>σταλεί</b>',
'email_viewed' => 'Αποστολή email όταν το τιμολόγιο <b>προβληθεί</b>',
@ -854,9 +854,9 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'website_help' => 'Εμφανίστε το τιμολόγιο σε ένα iFrame στη δική σας ιστοσελίδα',
'invoice_number_help' => 'Ορίστε ένα πρόθεμα ή χρησιμοποιήστε ένα προσαρμοσμένο μοτίβο για να καθορίζετε δυναμικά τον αριθμό τιμολογίου.',
'quote_number_help' => 'Ορίστε ένα πρόθεμα ή χρησιμοποιήστε ένα προσαρμοσμένο μοτίβο για να καθορίζετε δυναμικά τον αριθμό προσφοράς.',
'custom_client_fields_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα πελάτη και εμφανίστε την ετικέτα και την τιμή στο αρχείο PDF.',
'custom_client_fields_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα πελάτη και επιλέξτε δυνητικά την εμφάνισή της ετικέτας και της τιμής στο αρχείο PDF.',
'custom_account_fields_helps' => 'Προσθέστε μία ετικέτα και μία τιμή στο σημείο που αφορά τις λεπτομέρειες της εταιρίας στο αρχείο PDF.',
'custom_invoice_fields_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα τιμολόγιο και εμφανίστε την ετικέτα και την τιμή στο αρχείο PDF.',
'custom_invoice_fields_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα τιμολόγιο και επιλέξτε δυνητικά την εμφάνισή της ετικέτας και της τιμής στο αρχείο PDF.',
'custom_invoice_charges_helps' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα τιμολόγιο και συμπεριλάβετε την χρέωση στα υποσύνολα του τιμολογίου.',
'token_expired' => 'Το διακριτικό πιστοποίησης έχει λήξει. Παρακαλώ δοκιμάστε ξανά.',
'invoice_link' => 'Σύνδεσμος Τιμολογίου',
@ -1043,7 +1043,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'invoice_item_fields' => 'Πεδία Προϊόντων Τιμολογίου',
'custom_invoice_item_fields_help' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε ένα προϊόν τιμολογίου και εμφανίστε την ετικέτα και την τιμή στο αρχείο PDF.',
'recurring_invoice_number' => 'Επαναλαμβανόμενος Αριθμός',
'recurring_invoice_number_prefix_help' => 'Ορίστε ένα πρόθεμα που να περιλαμβάνεται στον αριθμό τιμολογίου των επαναλαμβανόμενων τιμολογίων. Η εξ\'ορισμού τιμή είναι \'R\'.',
'recurring_invoice_number_prefix_help' => 'Ορίστε ένα πρόθεμα που να περιλαμβάνεται στον αριθμό τιμολογίου των επαναλαμβανόμενων τιμολογίων.',
// Client Passwords
'enable_portal_password' => 'Προστασία Τιμολογίων με Κωδικό',
@ -1180,7 +1180,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
// Payment updates
'refund_payment' => 'Επιστροφή Πληρωμής',
'refund_max' => 'Μέγιστο:',
'refund' => 'Επιστροφή',
'refund' => 'Επιστροφή χρημάτων',
'are_you_sure_refund' => 'Επιστροφή επιλεγμένων πληρωμών:',
'status_pending' => 'Σε εξέλιξη',
'status_completed' => 'Ολοκληρώθηκε',
@ -1189,9 +1189,9 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'status_partially_refunded_amount' => ':amount χρήματα επεστραφησαν',
'status_refunded' => 'Επιστροφή χρημάτων',
'status_voided' => 'Ακυρωμένη',
'refunded_payment' => 'Επεστραμένη Πληρωμής',
'activity_39' => 'Ο χρήστης :user ακύρωσε μία πληρωμή (:payment) ποσού :payment_amount',
'activity_40' => 'Ο χρήστης :user επέστρεψε :adjustment ποσό :payment_amount μιας πληρωμής (:payment)',
'refunded_payment' => 'Επεστραμένη Πληρωμή',
'activity_39' => ':user ακύρωσε :payment_amount πληρωμής :payment',
'activity_40' => ':user επέστρεψε :adjustment μιας :payment_amount πληρωμής :payment',
'card_expiration' => 'Λήξη:&nbsp:expires',
'card_creditcardother' => 'Άγνωστο',
@ -1330,7 +1330,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'import_products' => 'Εισαγωγή Προϊόντων',
'products_will_create' => 'προϊόντα θα δημιουργηθούν',
'product_key' => 'Προϊόν',
'created_products' => 'Επιτυχής δημιουργία :count προϊόντων',
'created_products' => 'Επιτυχής δημιουργία/ενημέρωση :count προϊόν(των)',
'export_help' => 'Χρησιμοποιήστε JSON εάν σχεδιάζετε να εισάγετε δεδομένα στο Invoice Ninja.<br/>Το αρχείο περιλαμβάνει πελάτες, προϊόντα, τιμολόγια, προσφορές και πληρωμές.',
'JSON_file' => 'Αρχείο JSON',
@ -1996,7 +1996,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'edit_credit' => 'Επεξεργασία Πίστωσης',
'live_preview_help' => 'Εμφάνιση μιας ζωντανής προεπισκόπησης του PDF του τιμολογίου.<br/>Απενεργοποιήστε αυτή την επιλογή για βελτίωση της ταχύτητας επεξεργασίας τιμολογίων.',
'force_pdfjs_help' => 'Αντικαταστήστε τον ενσωματωμένο παρουσιαστή PDF στο :chrome_link και :firefox_link.<br/>Ενεργοποιήστε αυτή την επιλογή εάν ο browser σας κατεβάζει αυτόματα το PDF.',
'force_pdfjs' => 'Παρεμπόδιση Μεταφόρτωσης',
'force_pdfjs' => 'Παρεμπόδιση Κατεβάσματος',
'redirect_url' => 'URL Ανακατεύθυνσης',
'redirect_url_help' => 'Εναλλακτικά ορίστε ένα URL για ανακατεύθυνση μετά την πραγματοποίηση μιας πληρωμής.',
'save_draft' => 'Αποθήκευση Πρόχειρου',
@ -2155,10 +2155,10 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'location_second_surcharge' => 'Ενεργοποιημένο - Δεύτερη επιβάρυνση',
'location_line_item' => 'Ενεργοποιημένο - Προϊόν γραμμής',
'online_payment_surcharge' => 'Επιβάρυνση Πληρωμών Online',
'gateway_fees' => 'Προμήθειες Πύλης',
'gateway_fees' => 'Προμήθειες Πύλης Πληρωμής',
'fees_disabled' => 'Οι προμήθειες είναι απενεργοποιημένες',
'gateway_fees_help' => 'Προσθέστε αυτόματα μία επιβάρυνση/έκπτωση online πληρωμής.',
'gateway' => 'Πύλη (Gateway)',
'gateway' => 'Πύλη πληρωμής (Gateway)',
'gateway_fee_change_warning' => 'Εάν υπάρχουν απλήρωτα τιμολόγια με προμήθειες πρέπει να ενημερωθούν χειροκίνητα.',
'fees_surcharge_help' => 'Προσαρμογή επιβάρυνσης :link.',
'label_and_taxes' => 'ετικέτες και φόρους',
@ -2177,7 +2177,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'auto_bill_failed' => 'Αυτόματη τιμολόγηση για το τιμολόγιο :invoice_number failed',
'online_payment_discount' => 'Έκπτωση Online Πληρωμής',
'created_new_company' => 'Επιτυχής δημιουργία νέας εταιρίας',
'fees_disabled_for_gateway' => 'Οι προμήθειες είναι απενεργοποιημένες γι\' αυτή την πύλη.',
'fees_disabled_for_gateway' => 'Οι προμήθειες είναι απενεργοποιημένες γι\' αυτή την πύλη πληρωμής.',
'logout_and_delete' => 'Έξοδος/Διαγραφή λογαριασμού',
'tax_rate_type_help' => 'Οι περιλαμβανόμενοι φόροι προσαρμόζουν το κόστος του αντικειμένου γραμμής όταν επιλεγούν.',
'invoice_footer_help' => 'Χρησιμοποιήστε το $pageNumber και το $pageCount για να εμφανίσετε τις πληροφορίες σελίδας.',
@ -2188,7 +2188,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'credit_number' => 'Αριθμός Πίστωσης',
'create_credit_note' => 'Δημιουργία Πιστωτικού Σημειώματος',
'menu' => 'Μενού',
'error_incorrect_gateway_ids' => 'Σφάλμα: Ο πίνακας των πυλών (gateways) έχει λάθος αριθμούς.',
'error_incorrect_gateway_ids' => 'Σφάλμα: Ο πίνακας των πυλών πληρωμής (gateways) έχει λάθος αριθμούς.',
'purge_data' => 'Εκκαθάριση Δεδομένων',
'delete_data' => 'Διαγραφή Δεδομένων',
'purge_data_help' => 'Οριστική διαγραφή όλων των δεδομένων στο λογαριασμό, κρατώντας μόνο το λογαριασμό και τις ρυθμίσεις.',
@ -2217,7 +2217,7 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'notes_auto_billed' => 'Αυτόματη χρέωση',
'surcharge_label' => 'Ετικέτα Επιβάρυνσης',
'contact_fields' => 'Πεδία Επαφής',
'custom_contact_fields_help' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε μία επαφή και εμφανίστε την ετικέτα και την τιμή του στο αρχείο PDF.',
'custom_contact_fields_help' => 'Προσθέστε ένα πεδίο όταν δημιουργείτε μία επαφή και επιλέξτε δυνητικά την εμφάνισή της ετικέτας και της τιμής στο αρχείο PDF.',
'datatable_info' => 'Εμφάνιση :start έως :end από :total εγγραφές',
'credit_total' => 'Συνολική Πίστωση',
'mark_billable' => 'Σήμανση ως χρεώσιμο',
@ -2301,9 +2301,105 @@ email που είναι συνδεδεμένη με το λογαριασμό σ
'product_notes' => 'Σημειώσεις Προϊόντος',
'app_version' => 'Έκδοση Εφαρμογής',
'ofx_version' => 'Έκδοση OFX',
'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: the APP_KEY value is set to the default in the .env file.'
'gateway_help_23' => ':link για να λάβετε τα κλειδιά του Stripe API.',
'error_app_key_set_to_default' => 'Σφάλμα: Το APP_KEY έχει οριστεί στην προκαθορισμένη τιμή, για να το ενημερώσετε κάντε αντίγραφο ασφαλείας από τη βάση δεδομένων και εκτελέστε το <code>php artisan ninja:update-key</code>',
'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',
'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.',
'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_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.',
'token_expired' => 'Validation token was expired. Please try again.',
'invoice_link' => 'Invoice Link',
@ -1043,7 +1043,7 @@ $LANG = array(
'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.',
'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
'enable_portal_password' => 'Password Protect Invoices',
@ -1190,8 +1190,8 @@ $LANG = array(
'status_refunded' => 'Refunded',
'status_voided' => 'Cancelled',
'refunded_payment' => 'Refunded Payment',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)',
'activity_40' => ':user refunded :adjustment of 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',
'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Unknown',
@ -1330,7 +1330,7 @@ $LANG = array(
'import_products' => 'Import Products',
'products_will_create' => 'products will be created',
'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.',
'JSON_file' => 'JSON File',
@ -2217,7 +2217,7 @@ $LANG = array(
'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label',
'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',
'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable',
@ -2302,8 +2302,104 @@ $LANG = array(
'app_version' => 'App Version',
'ofx_version' => 'OFX Version',
'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: the APP_KEY value is set to the default 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>',
'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',
'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.',
'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_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.',
'token_expired' => 'Token de validación ha caducado. Por favor, vuelva a intentarlo.',
'invoice_link' => 'Enlace a Factura',
@ -1036,7 +1036,7 @@ $LANG = array(
'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.',
'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
'enable_portal_password' => 'Proteger Facturas con Contraseña',
@ -1183,8 +1183,8 @@ $LANG = array(
'status_refunded' => 'Refunded',
'status_voided' => 'Cancelled',
'refunded_payment' => 'Refunded Payment',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)',
'activity_40' => ':user refunded :adjustment of 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',
'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Unknown',
@ -1323,7 +1323,7 @@ $LANG = array(
'import_products' => 'Import Products',
'products_will_create' => 'productos serán creados',
'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.',
'JSON_file' => 'JSON File',
@ -2210,7 +2210,7 @@ $LANG = array(
'notes_auto_billed' => 'Auto-billed',
'surcharge_label' => 'Surcharge Label',
'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',
'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable',
@ -2295,8 +2295,104 @@ $LANG = array(
'app_version' => 'App Version',
'ofx_version' => 'OFX Version',
'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: the APP_KEY value is set to the default 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>',
'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',
'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.',
'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_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.',
'token_expired' => 'Token de validación ha caducado. Por favor, vuelva a intentarlo.',
'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',
'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_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
'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_voided' => 'Cancelado',
'refunded_payment' => 'Pago Reembolsado',
'activity_39' => ':user cancelled a :payment_amount payment (:payment)',
'activity_40' => ':user refunded :adjustment of 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',
'card_expiration' => 'Exp:&nbsp:expires',
'card_creditcardother' => 'Desconocido',
@ -1326,7 +1326,7 @@ Atención! tu password puede estar transmitida como texto plano, considera habil
'import_products' => 'Import Products',
'products_will_create' => 'products will be created',
'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.',
'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',
'surcharge_label' => 'Surcharge Label',
'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',
'credit_total' => 'Credit Total',
'mark_billable' => 'Mark billable',
@ -2298,8 +2298,104 @@ Atención! tu password puede estar transmitida como texto plano, considera habil
'app_version' => 'App Version',
'ofx_version' => 'OFX Version',
'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: the APP_KEY value is set to the default 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>',
'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