Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses

This commit is contained in:
paulwer 2024-03-17 09:14:07 +01:00
commit 21d569bd2b
188 changed files with 21059 additions and 8257 deletions

View File

@ -1 +1 @@
5.8.30
5.8.37

View File

@ -884,14 +884,14 @@ class CheckData extends Command
public function checkClientSettings()
{
if ($this->option('fix') == 'true') {
Client::query()->whereNull('country_id')->cursor()->each(function ($client) {
Client::query()->whereNull('country_id')->orWhere('country_id', 0)->cursor()->each(function ($client) {
$client->country_id = $client->company->settings->country_id;
$client->saveQuietly();
$this->logMessage("Fixing country for # {$client->id}");
});
Client::query()->whereNull("settings->currency_id")->cursor()->each(function ($client) {
Client::query()->whereNull("settings->currency_id")->orWhereJsonContains('settings', ['currency_id' => ''])->cursor()->each(function ($client) {
$settings = $client->settings;
$settings->currency_id = (string)$client->company->settings->currency_id;
$client->settings = $settings;
@ -933,7 +933,6 @@ class CheckData extends Command
});
Invoice::withTrashed()
->where("partial", 0)
->whereNotNull("partial_due_date")
@ -947,7 +946,42 @@ class CheckData extends Command
});
Company::whereDoesntHave('company_users', function ($query){
$query->where('is_owner', 1);
})
->cursor()
->when(Ninja::isHosted())
->each(function ($c){
$this->logMessage("Orphan Account # {$c->account_id}");
});
CompanyUser::whereDoesntHave('tokens')
->cursor()
->when(Ninja::isHosted())
->each(function ($cu){
$this->logMessage("Missing tokens for Company User # {$cu->id}");
});
CompanyUser::whereDoesntHave('user')
->cursor()
->when(Ninja::isHosted())
->each(function ($cu) {
$this->logMessage("Missing user for Company User # {$cu->id}");
});
$cus = CompanyUser::withTrashed()
->whereHas("user", function ($query) {
$query->whereColumn("users.account_id", "!=", "company_user.account_id");
})->pluck('id')->implode(",");
$this->logMessage("Cross Linked CompanyUser ids # {$cus}");
}

View File

@ -264,7 +264,7 @@ class BaseRule implements RuleInterface
return USStates::getState(strlen($this->client->postal_code) > 1 ? $this->client->postal_code : $this->client->shipping_postal_code);
} catch (\Exception $e) {
return $this->client->company->country()->iso_3166_2 == 'US' ? $this->client->company->tax_data->seller_subregion : 'CA';
return 'CA';
}
}

View File

@ -55,14 +55,12 @@ class Handler extends ExceptionHandler
protected $selfHostDontReport = [
FilePermissionsFailure::class,
PDOException::class,
MaxAttemptsExceededException::class,
CommandNotFoundException::class,
ValidationException::class,
ModelNotFoundException::class,
NotFoundHttpException::class,
UnableToCreateDirectory::class,
ConnectException::class,
RuntimeException::class,
InvalidArgumentException::class,
CredentialsException::class,
@ -140,7 +138,7 @@ class Handler extends ExceptionHandler
'email' => 'anonymous@example.com',
'name' => 'Anonymous User',
]);
} elseif (auth()->guard('user') && auth()->guard('user')->user() && auth()->user()->company() && auth()->user()->company()->account->report_errors) {
} elseif (auth()->guard('user') && auth()->guard('user')->user() && auth()->user()->companyIsSet() && auth()->user()->company()->account->report_errors) {
$scope->setUser([
'id' => auth()->user()->account->key,
'email' => 'anonymous@example.com',

View File

@ -827,7 +827,14 @@ class BaseExport
}
public function applyFilters(Builder $query): Builder
/**
* Apply Product Filters
*
* @param Builder $query
*
* @return Builder
*/
public function applyProductFilters(Builder $query): Builder
{
if(isset($this->input['product_key'])) {
@ -845,7 +852,15 @@ class BaseExport
return $query;
}
protected function addClientFilter($query, $clients): Builder
/**
* Add Client Filter
*
* @param Builder $query
* @param mixed $clients
*
* @return Builder
*/
protected function addClientFilter(Builder $query, $clients): Builder
{
if(is_string($clients)) {
$clients = explode(',', $clients);
@ -863,7 +878,15 @@ class BaseExport
return $query;
}
protected function addVendorFilter($query, $vendors): Builder
/**
* Add Vendor Filter
*
* @param Builder $query
* @param string $vendors
*
* @return Builder
*/
protected function addVendorFilter(Builder$query, string $vendors): Builder
{
if(is_string($vendors)) {
@ -879,7 +902,15 @@ class BaseExport
return $query;
}
protected function addProjectFilter($query, $projects): Builder
/**
* AddProjectFilter
*
* @param Builder $query
* @param string $projects
*
* @return Builder
*/
protected function addProjectFilter(Builder $query, string $projects): Builder
{
if(is_string($projects)) {
@ -895,7 +926,15 @@ class BaseExport
return $query;
}
protected function addCategoryFilter($query, $expense_categories): Builder
/**
* Add Category Filter
*
* @param Builder $query
* @param string $expense_categories
*
* @return Builder
*/
protected function addCategoryFilter(Builder $query, string $expense_categories): Builder
{
if(is_string($expense_categories)) {
@ -912,12 +951,229 @@ class BaseExport
return $query;
}
protected function addInvoiceStatusFilter($query, $status): Builder
/**
* Add Payment Status Filters
*
* @param Builder $query
* @param string $status
*
* @return Builder
*/
protected function addPaymentStatusFilters(Builder $query, string $status): Builder
{
$status_parameters = explode(',', $status);
if(in_array('all', $status_parameters)) {
if(in_array('all', $status_parameters) || count($status_parameters) == 0) {
return $query;
}
$query->where(function ($query) use ($status_parameters) {
$payment_filters = [];
if (in_array('pending', $status_parameters)) {
$payment_filters[] = Payment::STATUS_PENDING;
}
if (in_array('cancelled', $status_parameters)) {
$payment_filters[] = Payment::STATUS_CANCELLED;
}
if (in_array('failed', $status_parameters)) {
$payment_filters[] = Payment::STATUS_FAILED;
}
if (in_array('completed', $status_parameters)) {
$payment_filters[] = Payment::STATUS_COMPLETED;
}
if (in_array('partially_refunded', $status_parameters)) {
$payment_filters[] = Payment::STATUS_PARTIALLY_REFUNDED;
}
if (in_array('refunded', $status_parameters)) {
$payment_filters[] = Payment::STATUS_REFUNDED;
}
if (count($payment_filters) > 0) {
$query->whereIn('status_id', $payment_filters);
}
if(in_array('partially_unapplied', $status_parameters)) {
$query->whereColumn('amount', '>', 'applied')->where('refunded', 0);
}
});
return $query;
}
/**
* Add RecurringInvoice Status Filter
*
* @param Builder $query
* @param string $status
*
* @return Builder
*/
protected function addRecurringInvoiceStatusFilter(Builder $query, string $status): Builder
{
$status_parameters = explode(',', $status);
if (in_array('all', $status_parameters) || count($status_parameters) == 0){
return $query;
}
$recurring_filters = [];
if (in_array('active', $status_parameters)) {
$recurring_filters[] = RecurringInvoice::STATUS_ACTIVE;
}
if (in_array('paused', $status_parameters)) {
$recurring_filters[] = RecurringInvoice::STATUS_PAUSED;
}
if (in_array('completed', $status_parameters)) {
$recurring_filters[] = RecurringInvoice::STATUS_COMPLETED;
}
if (count($recurring_filters) >= 1) {
return $query->whereIn('status_id', $recurring_filters);
}
return $query;
}
/**
* Add QuoteStatus Filter
*
* @param Builder $query
* @param string $status
*
* @return Builder
*/
protected function addQuoteStatusFilter(Builder $query, string $status): Builder
{
$status_parameters = explode(',', $status);
if (in_array('all', $status_parameters)) {
return $query;
}
$query->where(function ($query) use ($status_parameters) {
if (in_array('sent', $status_parameters)) {
$query->orWhere(function ($q) {
$q->where('status_id', Quote::STATUS_SENT)
->whereNull('due_date')
->orWhere('due_date', '>=', now()->toDateString());
});
}
$quote_filters = [];
if (in_array('draft', $status_parameters)) {
$quote_filters[] = Quote::STATUS_DRAFT;
}
if (in_array('approved', $status_parameters)) {
$quote_filters[] = Quote::STATUS_APPROVED;
}
if (count($quote_filters) > 0) {
$query->orWhereIn('status_id', $quote_filters);
}
if (in_array('expired', $status_parameters)) {
$query->orWhere(function ($q) {
$q->where('status_id', Quote::STATUS_SENT)
->whereNotNull('due_date')
->where('due_date', '<=', now()->toDateString());
});
}
if (in_array('upcoming', $status_parameters)) {
$query->orWhere(function ($q) {
$q->where('status_id', Quote::STATUS_SENT)
->where('due_date', '>=', now()->toDateString())
->orderBy('due_date', 'DESC');
});
}
if(in_array('converted', $status_parameters)) {
$query->orWhere(function ($q) {
$q->whereNotNull('invoice_id');
});
}
});
return $query;
}
/**
* Add PurchaseOrder Status Filter
*
* @param Builder $query
* @param string $status
*
* @return Builder
*/
protected function addPurchaseOrderStatusFilter(Builder $query, string $status): Builder
{
$status_parameters = explode(',', $status);
if (in_array('all', $status_parameters) || count($status_parameters) == 0) {
return $query;
}
$query->where(function ($query) use ($status_parameters) {
$po_status = [];
if (in_array('draft', $status_parameters)) {
$po_status[] = PurchaseOrder::STATUS_DRAFT;
}
if (in_array('sent', $status_parameters)) {
$query->orWhere(function ($q) {
$q->where('status_id', PurchaseOrder::STATUS_SENT)
->whereNull('due_date')
->orWhere('due_date', '>=', now()->toDateString());
});
}
if (in_array('accepted', $status_parameters)) {
$po_status[] = PurchaseOrder::STATUS_ACCEPTED;
}
if (in_array('cancelled', $status_parameters)) {
$po_status[] = PurchaseOrder::STATUS_CANCELLED;
}
if (count($po_status) >= 1) {
$query->whereIn('status_id', $po_status);
}
});
return $query;
}
/**
* Add Invoice Status Filter
*
* @param Builder $query
* @param string $status
* @return Builder
*/
protected function addInvoiceStatusFilter(Builder $query, string $status): Builder
{
$status_parameters = explode(',', $status);
if(in_array('all', $status_parameters) || count($status_parameters) == 0) {
return $query;
}
@ -942,6 +1198,10 @@ class BaseExport
$invoice_filters[] = Invoice::STATUS_PARTIAL;
}
if (in_array('cancelled', $status_parameters)) {
$invoice_filters[] = Invoice::STATUS_CANCELLED;
}
if (count($invoice_filters) > 0) {
$nested->whereIn('status_id', $invoice_filters);
}
@ -966,14 +1226,18 @@ class BaseExport
return $query;
}
protected function addDateRange($query)
/**
* Add Date Range
*
* @param Builder $query
* @return Builder
*/
protected function addDateRange(Builder $query): Builder
{
$query = $this->applyFilters($query);
$query = $this->applyProductFilters($query);
$date_range = $this->input['date_range'];
nlog($date_range);
if (array_key_exists('date_key', $this->input) && strlen($this->input['date_key']) > 1) {
$this->date_key = $this->input['date_key'];
}

View File

@ -127,7 +127,7 @@ class ClientExport extends BaseExport
$query = Client::query()->with('contacts')
->withTrashed()
->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);

View File

@ -103,10 +103,14 @@ class CreditExport extends BaseExport
->withTrashed()
->with('client')
->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);
if($this->input['status'] ?? false) {
$query = $this->addCreditStatusFilter($query, $this->input['status']);
}
if($this->input['document_email_attachment'] ?? false) {
$this->queueDocuments($query);
}
@ -162,6 +166,40 @@ class CreditExport extends BaseExport
return $this->decorateAdvancedFields($credit, $entity);
}
public function addCreditStatusFilter($query, $status): Builder
{
$status_parameters = explode(',', $status);
if (in_array('all', $status_parameters)) {
return $query;
}
$credit_filters = [];
if (in_array('draft', $status_parameters)) {
$credit_filters[] = Credit::STATUS_DRAFT;
}
if (in_array('sent', $status_parameters)) {
$credit_filters[] = Credit::STATUS_SENT;
}
if (in_array('partial', $status_parameters)) {
$credit_filters[] = Credit::STATUS_PARTIAL;
}
if (in_array('applied', $status_parameters)) {
$credit_filters[] = Credit::STATUS_APPLIED;
}
if (count($credit_filters) >= 1) {
$query->whereIn('status_id', $credit_filters);
}
return $query;
}
private function decorateAdvancedFields(Credit $credit, array $entity): array
{
// if (in_array('country_id', $this->input['report_keys'])) {

View File

@ -83,10 +83,14 @@ class ExpenseExport extends BaseExport
->with('client')
->withTrashed()
->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);
if($this->input['status'] ?? false) {
$query = $this->addExpenseStatusFilter($query, $this->input['status']);
}
if(isset($this->input['clients'])) {
$query = $this->addClientFilter($query, $this->input['clients']);
}
@ -152,6 +156,55 @@ class ExpenseExport extends BaseExport
return $this->decorateAdvancedFields($expense, $entity);
}
protected function addExpenseStatusFilter($query, $status): Builder
{
$status_parameters = explode(',', $status);
if (in_array('all', $status_parameters)) {
return $query;
}
$query->where(function ($query) use ($status_parameters) {
if (in_array('logged', $status_parameters)) {
$query->orWhere(function ($query) {
$query->where('amount', '>', 0)
->whereNull('invoice_id')
->whereNull('payment_date')
->where('should_be_invoiced', false);
});
}
if (in_array('pending', $status_parameters)) {
$query->orWhere(function ($query) {
$query->where('should_be_invoiced', true)
->whereNull('invoice_id');
});
}
if (in_array('invoiced', $status_parameters)) {
$query->orWhere(function ($query) {
$query->whereNotNull('invoice_id');
});
}
if (in_array('paid', $status_parameters)) {
$query->orWhere(function ($query) {
$query->whereNotNull('payment_date');
});
}
if (in_array('unpaid', $status_parameters)) {
$query->orWhere(function ($query) {
$query->whereNull('payment_date');
});
}
});
return $query;
}
private function decorateAdvancedFields(Expense $expense, array $entity): array
{
// if (in_array('expense.currency_id', $this->input['report_keys'])) {

View File

@ -58,7 +58,7 @@ class InvoiceExport extends BaseExport
->withTrashed()
->with('client')
->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);
@ -151,9 +151,9 @@ class InvoiceExport extends BaseExport
// $entity['invoice.status'] = $invoice->stringStatus($invoice->status_id);
// }
// if (in_array('invoice.recurring_id', $this->input['report_keys'])) {
// $entity['invoice.recurring_id'] = $invoice->recurring_invoice->number ?? '';
// }
if (in_array('invoice.recurring_id', $this->input['report_keys'])) {
$entity['invoice.recurring_id'] = $invoice->recurring_invoice->number ?? '';
}
if (in_array('invoice.auto_bill_enabled', $this->input['report_keys'])) {
$entity['invoice.auto_bill_enabled'] = $invoice->auto_bill_enabled ? ctrans('texts.yes') : ctrans('texts.no');

View File

@ -71,11 +71,15 @@ class InvoiceItemExport extends BaseExport
->withTrashed()
->with('client')
->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);
$query = $this->applyFilters($query);
if($this->input['status'] ?? false) {
$query = $this->addInvoiceStatusFilter($query, $this->input['status']);
}
$query = $this->applyProductFilters($query);
if($this->input['document_email_attachment'] ?? false) {
$this->queueDocuments($query);
@ -232,9 +236,9 @@ class InvoiceItemExport extends BaseExport
// $entity['invoice.status'] = $invoice->stringStatus($invoice->status_id);
// }
// if (in_array('invoice.recurring_id', $this->input['report_keys'])) {
// $entity['invoice.recurring_id'] = $invoice->recurring_invoice->number ?? '';
// }
if (in_array('invoice.recurring_id', $this->input['report_keys'])) {
$entity['invoice.recurring_id'] = $invoice->recurring_invoice->number ?? '';
}
if (in_array('invoice.assigned_user_id', $this->input['report_keys'])) {
$entity['invoice.assigned_user_id'] = $invoice->assigned_user ? $invoice->assigned_user->present()->name() : '';

View File

@ -61,6 +61,8 @@ class PaymentExport extends BaseExport
$query = $this->addDateRange($query);
$query = $this->addPaymentStatusFilters($query, $this->input['status'] ?? '');
if($this->input['document_email_attachment'] ?? false) {
$this->queueDocuments($query);
}

View File

@ -31,51 +31,6 @@ class PurchaseOrderExport extends BaseExport
private Decorator $decorator;
public array $entity_keys = [
'amount' => 'purchase_order.amount',
'balance' => 'purchase_order.balance',
'vendor' => 'purchase_order.vendor_id',
// 'custom_surcharge1' => 'purchase_order.custom_surcharge1',
// 'custom_surcharge2' => 'purchase_order.custom_surcharge2',
// 'custom_surcharge3' => 'purchase_order.custom_surcharge3',
// 'custom_surcharge4' => 'purchase_order.custom_surcharge4',
'custom_value1' => 'purchase_order.custom_value1',
'custom_value2' => 'purchase_order.custom_value2',
'custom_value3' => 'purchase_order.custom_value3',
'custom_value4' => 'purchase_order.custom_value4',
'date' => 'purchase_order.date',
'discount' => 'purchase_order.discount',
'due_date' => 'purchase_order.due_date',
'exchange_rate' => 'purchase_order.exchange_rate',
'footer' => 'purchase_order.footer',
'number' => 'purchase_order.number',
'paid_to_date' => 'purchase_order.paid_to_date',
'partial' => 'purchase_order.partial',
'partial_due_date' => 'purchase_order.partial_due_date',
'po_number' => 'purchase_order.po_number',
'private_notes' => 'purchase_order.private_notes',
'public_notes' => 'purchase_order.public_notes',
'status' => 'purchase_order.status',
'tax_name1' => 'purchase_order.tax_name1',
'tax_name2' => 'purchase_order.tax_name2',
'tax_name3' => 'purchase_order.tax_name3',
'tax_rate1' => 'purchase_order.tax_rate1',
'tax_rate2' => 'purchase_order.tax_rate2',
'tax_rate3' => 'purchase_order.tax_rate3',
'terms' => 'purchase_order.terms',
'total_taxes' => 'purchase_order.total_taxes',
'currency_id' => 'purchase_order.currency_id',
];
private array $decorate_keys = [
'country',
'currency_id',
'status',
'vendor',
'project',
];
public function __construct(Company $company, array $input)
{
$this->company = $company;
@ -104,10 +59,12 @@ class PurchaseOrderExport extends BaseExport
->withTrashed()
->with('vendor')
->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);
$query = $this->addPurchaseOrderStatusFilter($query, $this->input['status'] ?? '');
if($this->input['document_email_attachment'] ?? false) {
$this->queueDocuments($query);
}
@ -167,7 +124,7 @@ class PurchaseOrderExport extends BaseExport
if (is_array($parts) && $parts[0] == 'purchase_order' && array_key_exists($parts[1], $transformed_purchase_order)) {
$entity[$key] = $transformed_purchase_order[$parts[1]];
} else {
// nlog($key);
nlog($key);
$entity[$key] = $this->decorator->transform($key, $purchase_order);
// $entity[$key] = '';
@ -182,16 +139,13 @@ class PurchaseOrderExport extends BaseExport
private function decorateAdvancedFields(PurchaseOrder $purchase_order, array $entity): array
{
if (in_array('country_id', $this->input['report_keys'])) {
$entity['country'] = $purchase_order->vendor->country ? ctrans("texts.country_{$purchase_order->vendor->country->name}") : '';
if (in_array('purchase_order.currency_id', $this->input['report_keys'])) {
$entity['purchase_order.currency_id'] = $purchase_order->vendor->currency() ? $purchase_order->vendor->currency()->code : $purchase_order->company->currency()->code;
}
if (in_array('currency_id', $this->input['report_keys'])) {
$entity['currency_id'] = $purchase_order->vendor->currency() ? $purchase_order->vendor->currency()->code : $purchase_order->company->currency()->code;
}
if (in_array('vendor_id', $this->input['report_keys'])) {
$entity['vendor'] = $purchase_order->vendor->present()->name();
if (in_array('purchase_order.vendor_id', $this->input['report_keys'])) {
$entity['purchase_order.vendor_id'] = $purchase_order->vendor->present()->name();
}
if (in_array('purchase_order.status', $this->input['report_keys'])) {

View File

@ -63,10 +63,12 @@ class PurchaseOrderItemExport extends BaseExport
$query = PurchaseOrder::query()
->withTrashed()
->with('vendor')->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);
$query = $this->addPurchaseOrderStatusFilter($query, $this->input['status'] ?? '');
if($this->input['document_email_attachment'] ?? false) {
$this->queueDocuments($query);
}
@ -190,23 +192,35 @@ class PurchaseOrderItemExport extends BaseExport
private function decorateAdvancedFields(PurchaseOrder $purchase_order, array $entity): array
{
if (in_array('currency_id', $this->input['report_keys'])) {
$entity['currency'] = $purchase_order->vendor->currency() ? $purchase_order->vendor->currency()->code : $purchase_order->company->currency()->code;
// if (in_array('currency_id', $this->input['report_keys'])) {
// $entity['currency'] = $purchase_order->vendor->currency() ? $purchase_order->vendor->currency()->code : $purchase_order->company->currency()->code;
// }
// if(array_key_exists('type', $entity)) {
// $entity['type'] = $purchase_order->typeIdString($entity['type']);
// }
// if(array_key_exists('tax_category', $entity)) {
// $entity['tax_category'] = $purchase_order->taxTypeString($entity['tax_category']);
// }
// if($this->force_keys) {
// $entity['vendor'] = $purchase_order->vendor->present()->name();
// $entity['vendor_id_number'] = $purchase_order->vendor->id_number;
// $entity['vendor_number'] = $purchase_order->vendor->number;
// $entity['status'] = $purchase_order->stringStatus($purchase_order->status_id);
// }
if (in_array('purchase_order.currency_id', $this->input['report_keys'])) {
$entity['purchase_order.currency_id'] = $purchase_order->vendor->currency() ? $purchase_order->vendor->currency()->code : $purchase_order->company->currency()->code;
}
if(array_key_exists('type', $entity)) {
$entity['type'] = $purchase_order->typeIdString($entity['type']);
if (in_array('purchase_order.vendor_id', $this->input['report_keys'])) {
$entity['purchase_order.vendor_id'] = $purchase_order->vendor->present()->name();
}
if(array_key_exists('tax_category', $entity)) {
$entity['tax_category'] = $purchase_order->taxTypeString($entity['tax_category']);
}
if($this->force_keys) {
$entity['vendor'] = $purchase_order->vendor->present()->name();
$entity['vendor_id_number'] = $purchase_order->vendor->id_number;
$entity['vendor_number'] = $purchase_order->vendor->number;
$entity['status'] = $purchase_order->stringStatus($purchase_order->status_id);
if (in_array('purchase_order.status', $this->input['report_keys'])) {
$entity['purchase_order.status'] = $purchase_order->stringStatus($purchase_order->status_id);
}
if (in_array('purchase_order.user_id', $this->input['report_keys'])) {

View File

@ -65,10 +65,12 @@ class QuoteExport extends BaseExport
->withTrashed()
->with('client')
->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);
$query = $this->addQuoteStatusFilter($query, $this->input['status'] ?? '');
if($this->input['document_email_attachment'] ?? false) {
$this->queueDocuments($query);
}

View File

@ -66,10 +66,12 @@ class QuoteItemExport extends BaseExport
$query = Quote::query()
->withTrashed()
->with('client')->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);
$query = $this->addQuoteStatusFilter($query, $this->input['status'] ?? '');
if($this->input['document_email_attachment'] ?? false) {
$this->queueDocuments($query);
}

View File

@ -57,10 +57,12 @@ class RecurringInvoiceExport extends BaseExport
->withTrashed()
->with('client')
->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);
$query = $this->addRecurringInvoiceStatusFilter($query, $this->input['status'] ?? '');
return $query;
}

View File

@ -68,7 +68,7 @@ class TaskExport extends BaseExport
$query = Task::query()
->withTrashed()
->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);
@ -203,6 +203,34 @@ class TaskExport extends BaseExport
}
/**
* Add Task Status Filter
*
* @param Builder $query
* @param string $status
* @return Builder
*/
protected function addTaskStatusFilter(Builder $query, string $status): Builder
{
$status_parameters = explode(',', $status);
if (in_array('all', $status_parameters) || count($status_parameters) == 0) {
return $query;
}
if (in_array('invoiced', $status_parameters)) {
$query->whereNotNull('invoice_id');
}
if (in_array('uninvoiced', $status_parameters)) {
$query->whereNull('invoice_id');
}
return $query;
}
private function decorateAdvancedFields(Task $task, array $entity): array
{
if (in_array('task.status_id', $this->input['report_keys'])) {

View File

@ -62,7 +62,7 @@ class VendorExport extends BaseExport
$query = Vendor::query()->with('contacts')
->withTrashed()
->where('company_id', $this->company->id)
->where('is_deleted', 0);
->where('is_deleted', $this->input['include_deleted'] ?? false);
$query = $this->addDateRange($query);

View File

@ -79,7 +79,6 @@ class InvoiceDecorator extends Decorator implements DecoratorInterface
return $invoice->partial_due_date ?? '';
}
public function assigned_user_id(Invoice $invoice)
{
return $invoice->assigned_user ? $invoice->assigned_user->present()->name() : '';

View File

@ -29,11 +29,13 @@ class DocumentFilters extends QueryFilters
*/
public function filter(string $filter = ''): Builder
{
if (strlen($filter) == 0) {
return $this->builder;
}
return $this->builder;
return $this->builder->where('name', 'like', '%'.$filter.'%');
}
/**
@ -47,6 +49,43 @@ class DocumentFilters extends QueryFilters
*/
public function client_id(string $client_id = ''): Builder
{
return $this->builder->where(function ($query) use ($client_id) {
$query->whereHasMorph('documentable', [
\App\Models\Invoice::class,
\App\Models\Quote::class,
\App\Models\Credit::class,
\App\Models\Expense::class,
\App\Models\Payment::class,
\App\Models\Task::class,
\App\Models\RecurringExpense::class,
\App\Models\RecurringInvoice::class,
\App\Models\Project::class,
], function ($q2) use ($client_id) {
$q2->where('client_id', $this->decodePrimaryKey($client_id));
})->orWhereHasMorph('documentable', [\App\Models\Client::class], function ($q3) use ($client_id) {
$q3->where('id', $this->decodePrimaryKey($client_id));
});
});
}
public function type(string $types = '')
{
$types = explode(',', $types);
foreach ($types as $type)
{
match($type) {
'private' => $this->builder->where('is_public', 0),
'public' => $this->builder->where('is_public', 1),
'pdf' => $this->builder->where('type', 'pdf'),
'image' => $this->builder->whereIn('type', ['png','jpeg','jpg','gif','svg']),
'other' => $this->builder->whereNotIn('type', ['pdf','png','jpeg','jpg','gif','svg']),
default => $this->builder,
};
}
return $this->builder;
}

View File

@ -62,6 +62,10 @@ class InvoiceFilters extends QueryFilters
$invoice_filters[] = Invoice::STATUS_PAID;
}
if (in_array('cancelled', $status_parameters)) {
$invoice_filters[] = Invoice::STATUS_CANCELLED;
}
if (in_array('unpaid', $status_parameters)) {
$invoice_filters[] = Invoice::STATUS_SENT;
$invoice_filters[] = Invoice::STATUS_PARTIAL;
@ -324,6 +328,7 @@ class InvoiceFilters extends QueryFilters
}
if($sort_col[0] == 'number') {
// return $this->builder->orderByRaw('CAST(number AS UNSIGNED), number ' . $dir);
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}

View File

@ -97,11 +97,11 @@ class Nordigen
return $it->transform($out);
} catch (\Exception $e) {
if (strpos($e->getMessage(), "Invalid Account ID") !== false) {
return false;
}
throw $e;
nlog("Nordigen getAccount() failed => {$account_id} => " . $e->getMessage());
return false;
}
}

View File

@ -277,7 +277,7 @@ class InvoiceItemSum
$item_tax += $item_tax_rate1_total;
if (strlen($this->item->tax_name1) > 2) {
if (strlen($this->item->tax_name1) > 1) {
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total);
}
@ -285,7 +285,7 @@ class InvoiceItemSum
$item_tax += $item_tax_rate2_total;
if (strlen($this->item->tax_name2) > 2) {
if (strlen($this->item->tax_name2) > 1) {
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total);
}
@ -293,7 +293,7 @@ class InvoiceItemSum
$item_tax += $item_tax_rate3_total;
if (strlen($this->item->tax_name3) > 2) {
if (strlen($this->item->tax_name3) > 1) {
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
}

View File

@ -231,7 +231,7 @@ class InvoiceItemSumInclusive
/** @var float $item_tax */
$item_tax += $this->formatValue($item_tax_rate1_total, $this->currency->precision);
if (strlen($this->item->tax_name1) > 2) {
if (strlen($this->item->tax_name1) > 1) {
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total);
}
@ -239,7 +239,7 @@ class InvoiceItemSumInclusive
$item_tax += $this->formatValue($item_tax_rate2_total, $this->currency->precision);
if (strlen($this->item->tax_name2) > 2) {
if (strlen($this->item->tax_name2) > 1) {
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total);
}
@ -247,7 +247,7 @@ class InvoiceItemSumInclusive
$item_tax += $this->formatValue($item_tax_rate3_total, $this->currency->precision);
if (strlen($this->item->tax_name3) > 2) {
if (strlen($this->item->tax_name3) > 1) {
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
}

View File

@ -122,7 +122,7 @@ class InvoiceSum
private function calculateInvoiceTaxes(): self
{
if (is_string($this->invoice->tax_name1) && strlen($this->invoice->tax_name1) > 2) {
if (is_string($this->invoice->tax_name1) && strlen($this->invoice->tax_name1) >= 2) {
$tax = $this->taxer($this->total, $this->invoice->tax_rate1);
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name1, $this->invoice->tax_rate1);
@ -130,7 +130,7 @@ class InvoiceSum
$this->total_tax_map[] = ['name' => $this->invoice->tax_name1.' '.floatval($this->invoice->tax_rate1).'%', 'total' => $tax];
}
if (is_string($this->invoice->tax_name2) && strlen($this->invoice->tax_name2) > 2) {
if (is_string($this->invoice->tax_name2) && strlen($this->invoice->tax_name2) >= 2) {
$tax = $this->taxer($this->total, $this->invoice->tax_rate2);
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name2, $this->invoice->tax_rate2);
@ -138,7 +138,7 @@ class InvoiceSum
$this->total_tax_map[] = ['name' => $this->invoice->tax_name2.' '.floatval($this->invoice->tax_rate2).'%', 'total' => $tax];
}
if (is_string($this->invoice->tax_name3) && strlen($this->invoice->tax_name3) > 2) {
if (is_string($this->invoice->tax_name3) && strlen($this->invoice->tax_name3) >= 2) {
$tax = $this->taxer($this->total, $this->invoice->tax_rate3);
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name3, $this->invoice->tax_rate3);

View File

@ -340,8 +340,7 @@ class InvoiceSumInclusive
$this->total_taxes += $total_line_tax;
}
nlog($this->tax_map);
nlog($this->total_taxes);
return $this;
}

View File

@ -159,7 +159,7 @@ class SwissQrGenerator
// Optionally, add some human-readable information about what the bill is for.
$qrBill->setAdditionalInformation(
QrBill\DataGroup\Element\AdditionalInformation::create(
$this->invoice->public_notes ? substr($this->invoice->public_notes, 0, 139) : ctrans('texts.invoice_number_placeholder', ['invoice' => $this->invoice->number])
$this->invoice->public_notes ? substr(strip_tags($this->invoice->public_notes), 0, 139) : ctrans('texts.invoice_number_placeholder', ['invoice' => $this->invoice->number])
)
);

View File

@ -49,6 +49,9 @@ use App\Http\Requests\Client\ClientDocumentsRequest;
use App\Http\Requests\Client\ReactivateClientEmailRequest;
use App\Models\Expense;
use App\Models\Payment;
use App\Models\Project;
use App\Models\RecurringExpense;
use App\Models\RecurringInvoice;
use App\Models\Task;
use App\Transformers\DocumentTransformer;
@ -421,7 +424,7 @@ class ClientController extends BaseController
$documents = Document::query()
->company()
->whereHasMorph('documentable', [Invoice::class, Quote::class, Credit::class, Expense::class, Payment::class, Task::class], function ($query) use ($client) {
->whereHasMorph('documentable', [Invoice::class, Quote::class, Credit::class, Expense::class, Payment::class, Task::class, RecurringInvoice::class, RecurringExpense::class, Project::class], function ($query) use ($client) {
$query->where('client_id', $client->id);
})
->orWhereHasMorph('documentable', [Client::class], function ($query) use ($client) {

View File

@ -45,7 +45,7 @@ class EmailPreferencesController extends Controller
if ($invitation->contact->is_locked && !Cache::has("unsubscribe_notitfication_suppression:{$invitation_key}")) {
$nmo = new NinjaMailerObject();
$nmo->mailable = new NinjaMailer((new ClientUnsubscribedObject($invitation->contact, $invitation->contact->company, $invitation->contact->company->owner()->company_users()->first()->portalType() ?? true))->build());
$nmo->mailable = new NinjaMailer((new ClientUnsubscribedObject($invitation->contact, $invitation->contact->company, true))->build());
$nmo->company = $invitation->contact->company;
$nmo->to_user = $invitation->contact->company->owner();
$nmo->settings = $invitation->contact->company->settings;

View File

@ -271,6 +271,7 @@ class InvitationController extends Controller
->with('contact.client')
->firstOrFail();
if ($invitation->contact->trashed()) {
$invitation->contact->restore();
}
@ -294,7 +295,10 @@ class InvitationController extends Controller
'payable_invoices' => [
['invoice_id' => $invitation->invoice->hashed_id, 'amount' => $amount],
],
'signature' => false
'signature' => false,
'contact_first_name' => $invitation->contact->first_name ?? '',
'contact_last_name' => $invitation->contact->last_name ?? '',
'contact_email' => $invitation->contact->email ?? ''
];
$request->replace($data);

View File

@ -25,6 +25,10 @@ class SubscriptionPurchaseController extends Controller
{
App::setLocale($subscription->company->locale());
if ($subscription->trashed()) {
return $this->render('generic.not_available', ['account' => $subscription->company->account, 'company' => $subscription->company]);
}
/* Make sure the contact is logged into the correct company for this subscription */
if (auth()->guard('contact')->user() && auth()->guard('contact')->user()->company_id != $subscription->company_id) {
auth()->guard('contact')->logout();

View File

@ -158,7 +158,6 @@ class LicenseController extends BaseController
/* Catch claim license requests */
if (config('ninja.environment') == 'selfhost') {
// $response = Http::get( "http://ninja.test:8000/claim_license", [
$response = Http::get("https://invoicing.co/claim_license", [
'license_key' => $license_key,
'product_id' => 3,

View File

@ -21,7 +21,7 @@ class ProtectedDownloadController extends BaseController
public function index(Request $request, string $hash)
{
/** @var string $hashed_path */
$hashed_path = Cache::pull($hash);
$hashed_path = Cache::get($hash);
if (!$hashed_path) {
throw new SystemError('File no longer available', 404);

View File

@ -30,16 +30,24 @@ class SmtpController extends BaseController
$user = auth()->user();
$company = $user->company();
$smtp_host = $request->input('smtp_host', $company->smtp_host);
$smtp_port = $request->input('smtp_port', $company->smtp_port);
$smtp_username = $request->input('smtp_username', $company->smtp_username);
$smtp_password = $request->input('smtp_password', $company->smtp_password);
$smtp_encryption = $request->input('smtp_encryption', $company->smtp_encryption ?? 'tls');
$smtp_local_domain = $request->input('smtp_local_domain', strlen($company->smtp_local_domain) > 2 ? $company->smtp_local_domain : null);
$smtp_verify_peer = $request->input('verify_peer', $company->smtp_verify_peer ?? true);
config([
'mail.mailers.smtp' => [
'transport' => 'smtp',
'host' => $request->input('smtp_host', $company->smtp_host),
'port' => $request->input('smtp_port', $company->smtp_port),
'username' => $request->input('smtp_username', $company->smtp_username),
'password' => $request->input('smtp_password', $company->smtp_password),
'encryption' => $request->input('smtp_encryption', $company->smtp_encryption ?? 'tls'),
'local_domain' => $request->input('smtp_local_domain', strlen($company->smtp_local_domain) > 2 ? $company->smtp_local_domain : null),
'verify_peer' => $request->input('verify_peer', $company->smtp_verify_peer ?? true),
'host' => $smtp_host,
'port' => $smtp_port,
'username' => $smtp_username,
'password' => $smtp_password,
'encryption' => $smtp_encryption,
'local_domain' => $smtp_local_domain,
'verify_peer' => $smtp_verify_peer,
'timeout' => 5,
],
]);
@ -47,7 +55,7 @@ class SmtpController extends BaseController
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
try {
Mail::to($user->email, $user->present()->name())->send(new TestMailServer('Email Server Works!', strlen($company->settings->custom_sending_email) > 1 ? $company->settings->custom_sending_email : $user->email));
Mail::mailer('smtp')->to($user->email, $user->present()->name())->send(new TestMailServer('Email Server Works!', strlen($company->settings->custom_sending_email) > 1 ? $company->settings->custom_sending_email : $user->email));
} catch (\Exception $e) {
app('mail.manager')->forgetMailers();
return response()->json(['message' => $e->getMessage()], 400);

View File

@ -65,6 +65,8 @@ class StripeConnectController extends BaseController
return view('auth.connect.access_denied');
}
$response = false;
try {
/** @class \stdClass $response
* @property string $scope
@ -88,6 +90,11 @@ class StripeConnectController extends BaseController
nlog($response);
} catch (\Exception $e) {
}
if(!$response) {
return view('auth.connect.access_denied');
}
@ -144,11 +151,14 @@ class StripeConnectController extends BaseController
if(isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react']) {
$redirect_uri = config('ninja.react_url').'/#/settings/online_payments';
} else {
$redirect_uri = config('ninja.app_url').'/stripe/completed';
$redirect_uri = config('ninja.app_url');
}
\Illuminate\Support\Facades\Cache::pull($request->token);
//response here
return view('auth.connect.completed', ['url' => $redirect_uri]);
// return redirect($redirect_uri);
}
}

View File

@ -135,7 +135,7 @@ class Kernel extends HttpKernel
'can' => Authorize::class,
'cors' => Cors::class,
'guest' => RedirectIfAuthenticated::class,
'signed' => ValidateSignature::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'verified' => EnsureEmailIsVerified::class,
'query_logging' => QueryLogging::class,
'token_auth' => TokenAuth::class,

View File

@ -59,20 +59,6 @@ class StoreClientRequest extends Request
$rules['file'] = $this->file_validation;
}
if (isset($this->number)) {
$rules['number'] = Rule::unique('clients')->where('company_id', $user->company()->id);
}
$rules['country_id'] = 'integer|nullable';
if (isset($this->currency_code)) {
$rules['currency_code'] = 'sometimes|exists:currencies,code';
}
if (isset($this->country_code)) {
$rules['country_code'] = new CountryCodeExistsRule();
}
/* Ensure we have a client name, and that all emails are unique*/
//$rules['name'] = 'required|min:1';
$rules['settings'] = new ValidClientGroupSettingsRule();
@ -97,6 +83,9 @@ class StoreClientRequest extends Request
$rules['number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)];
$rules['id_number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)];
$rules['classification'] = 'bail|sometimes|nullable|in:individual,business,company,partnership,trust,charity,government,other';
$rules['shipping_country_id'] = 'integer|nullable|exists:countries,id';
$rules['number'] = ['sometimes', 'nullable', 'bail', Rule::unique('clients')->where('company_id', $user->company()->id)];
$rules['country_id'] = 'integer|nullable|exists:countries,id';
return $rules;
}
@ -139,12 +128,16 @@ class StoreClientRequest extends Request
if (! array_key_exists('currency_id', $input['settings']) && isset($input['group_settings_id'])) {
$group_settings = GroupSetting::find($input['group_settings_id']);
if ($group_settings && property_exists($group_settings->settings, 'currency_id') && isset($group_settings->settings->currency_id)) {
if ($group_settings && property_exists($group_settings->settings, 'currency_id') && is_numeric($group_settings->settings->currency_id)) {
$input['settings']['currency_id'] = (string) $group_settings->settings->currency_id;
} else {
$input['settings']['currency_id'] = (string) $user->company()->settings->currency_id;
}
} elseif (! array_key_exists('currency_id', $input['settings'])) {
}
elseif (! array_key_exists('currency_id', $input['settings'])) {
$input['settings']['currency_id'] = (string) $user->company()->settings->currency_id;
}
elseif (empty($input['settings']['currency_id']) ?? true) {
$input['settings']['currency_id'] = (string) $user->company()->settings->currency_id;
}
@ -160,10 +153,13 @@ class StoreClientRequest extends Request
}
}
// allow setting country_id by iso code
if (isset($input['country_code'])) {
$input['country_id'] = $this->getCountryCode($input['country_code']);
}
// allow setting country_id by iso code
if (isset($input['shipping_country_code'])) {
$input['shipping_country_id'] = $this->getCountryCode($input['shipping_country_code']);
}
@ -173,10 +169,14 @@ class StoreClientRequest extends Request
unset($input['number']);
}
// prevent xss injection
if (array_key_exists('name', $input)) {
$input['name'] = strip_tags($input['name']);
}
//If you want to validate, the prop must be set.
$input['id'] = null;
$this->replace($input);
}

View File

@ -60,17 +60,11 @@ class UpdateClientRequest extends Request
$rules['company_logo'] = 'mimes:jpeg,jpg,png,gif|max:10000';
$rules['industry_id'] = 'integer|nullable';
$rules['size_id'] = 'integer|nullable';
$rules['country_id'] = 'integer|nullable';
$rules['shipping_country_id'] = 'integer|nullable';
$rules['country_id'] = 'integer|nullable|exists:countries,id';
$rules['shipping_country_id'] = 'integer|nullable|exists:countries,id';
$rules['classification'] = 'bail|sometimes|nullable|in:individual,business,company,partnership,trust,charity,government,other';
if ($this->id_number) {
$rules['id_number'] = Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id);
}
if ($this->number) {
$rules['number'] = Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id);
}
$rules['id_number'] = ['sometimes', 'bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id)];
$rules['number'] = ['sometimes', 'bail', Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id)];
$rules['settings'] = new ValidClientGroupSettingsRule();
$rules['contacts'] = 'array';
@ -112,6 +106,9 @@ class UpdateClientRequest extends Request
if (array_key_exists('settings', $input) && ! array_key_exists('currency_id', $input['settings'])) {
$input['settings']['currency_id'] = (string) $user->company()->settings->currency_id;
}
elseif (empty($input['settings']['currency_id']) ?? true) {
$input['settings']['currency_id'] = (string) $user->company()->settings->currency_id;
}
if (isset($input['language_code'])) {
$input['settings']['language_id'] = $this->getLanguageId($input['language_code']);
@ -127,9 +124,35 @@ class UpdateClientRequest extends Request
$input['name'] = strip_tags($input['name']);
}
// allow setting country_id by iso code
if (isset($input['country_code'])) {
$input['country_id'] = $this->getCountryCode($input['country_code']);
}
// allow setting country_id by iso code
if (isset($input['shipping_country_code'])) {
$input['shipping_country_id'] = $this->getCountryCode($input['shipping_country_code']);
}
$this->replace($input);
}
private function getCountryCode($country_code)
{
$countries = Cache::get('countries');
$country = $countries->filter(function ($item) use ($country_code) {
return $item->iso_3166_2 == $country_code || $item->iso_3166_3 == $country_code;
})->first();
if ($country) {
return (string) $country->id;
}
return '';
}
private function getLanguageId($language_code)
{
$languages = Cache::get('languages');

View File

@ -77,6 +77,7 @@ class StoreInvoiceRequest extends Request
$rules['exchange_rate'] = 'bail|sometimes|numeric';
$rules['partial'] = 'bail|sometimes|nullable|numeric|gte:0';
$rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date'];
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
return $rules;
@ -112,6 +113,12 @@ class StoreInvoiceRequest extends Request
$input['exchange_rate'] = 1;
}
//handles edge case where we need for force set the due date of the invoice.
if((isset($input['partial_due_date']) && strlen($input['partial_due_date']) > 1) && (!array_key_exists('due_date', $input) || (empty($input['due_date']) && empty($this->invoice->due_date)))) {
$client = \App\Models\Client::withTrashed()->find($input['client_id']);
$input['due_date'] = \Illuminate\Support\Carbon::parse($input['date'])->addDays($client->getSetting('payment_terms'))->format('Y-m-d');
}
$this->replace($input);
}
}

View File

@ -78,6 +78,7 @@ class UpdateInvoiceRequest extends Request
$rules['exchange_rate'] = 'bail|sometimes|numeric';
$rules['partial'] = 'bail|sometimes|nullable|numeric';
$rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date'];
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
return $rules;
@ -107,6 +108,12 @@ class UpdateInvoiceRequest extends Request
$input['exchange_rate'] = 1;
}
//handles edge case where we need for force set the due date of the invoice.
if((isset($input['partial_due_date']) && strlen($input['partial_due_date']) > 1) && (!array_key_exists('due_date', $input) || (empty($input['due_date']) && empty($this->invoice->due_date)))) {
$client = \App\Models\Client::withTrashed()->find($input['client_id']);
$input['due_date'] = \Illuminate\Support\Carbon::parse($input['date'])->addDays($client->getSetting('payment_terms'))->format('Y-m-d');
}
$this->replace($input);
}

View File

@ -44,6 +44,7 @@ class StoreProjectRequest extends Request
$rules['name'] = 'required';
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
$rules['budgeted_hours'] = 'sometimes|numeric';
if (isset($this->number)) {
$rules['number'] = Rule::unique('projects')->where('company_id', $user->company()->id);
@ -74,6 +75,9 @@ class StoreProjectRequest extends Request
$input['color'] = '';
}
if(array_key_exists('budgeted_hours', $input) && empty($input['budgeted_hours']))
$input['budgeted_hours'] = 0;
$this->replace($input);
}

View File

@ -45,6 +45,8 @@ class UpdateProjectRequest extends Request
$rules['number'] = Rule::unique('projects')->where('company_id', $user->company()->id)->ignore($this->project->id);
}
$rules['budgeted_hours'] = 'sometimes|numeric';
if ($this->file('documents') && is_array($this->file('documents'))) {
$rules['documents.*'] = $this->file_validation;
} elseif ($this->file('documents')) {
@ -74,6 +76,10 @@ class UpdateProjectRequest extends Request
$input['color'] = '';
}
if(array_key_exists('budgeted_hours', $input) && empty($input['budgeted_hours'])) {
$input['budgeted_hours'] = 0;
}
$this->replace($input);
}
}

View File

@ -37,7 +37,8 @@ class GenericReportRequest extends Request
'start_date' => 'bail|required_if:date_range,custom|nullable|date',
'report_keys' => 'present|array',
'send_email' => 'required|bool',
'document_email_attachment' => 'sometimes|bool'
'document_email_attachment' => 'sometimes|bool',
'include_deleted' => 'required|bool',
// 'status' => 'sometimes|string|nullable|in:all,draft,sent,viewed,paid,unpaid,overdue',
];
}
@ -63,6 +64,8 @@ class GenericReportRequest extends Request
$input['end_date'] = null;
}
$input['include_deleted'] = array_key_exists('include_deleted', $input) ? filter_var($input['include_deleted'], FILTER_VALIDATE_BOOLEAN) : false;
$input['user_id'] = auth()->user()->id;
$this->replace($input);

View File

@ -36,18 +36,46 @@ class CheckSmtpRequest extends Request
public function rules()
{
return [
'smtp_host' => 'sometimes|nullable|string|min:3',
'smtp_port' => 'sometimes|nullable|integer',
'smtp_username' => 'sometimes|nullable|string|min:3',
'smtp_password' => 'sometimes|nullable|string|min:3',
];
}
public function prepareForValidation()
{
/** @var \App\Models\User $user */
$user = auth()->user();
$company = $user->company();
$input = $this->input();
if(isset($input['smtp_username']) && $input['smtp_username'] == '********')
unset($input['smtp_username']);
if(isset($input['smtp_username']) && $input['smtp_username'] == '********'){
// unset($input['smtp_username']);
$input['smtp_username'] = $company->smtp_username;
}
if(isset($input['smtp_password'])&& $input['smtp_password'] == '********'){
// unset($input['smtp_password']);
$input['smtp_password'] = $company->smtp_password;
}
if(isset($input['smtp_host']) && strlen($input['smtp_host']) >=3){
}
else {
$input['smtp_host'] = $company->smtp_host;
}
if(isset($input['smtp_port']) && strlen($input['smtp_port']) >= 3) {
} else {
$input['smtp_port'] = $company->smtp_port;
}
if(isset($input['smtp_password'])&& $input['smtp_password'] == '********')
unset($input['smtp_password']);
$this->replace($input);
}

View File

@ -13,11 +13,30 @@ namespace App\Http\Requests\TaskScheduler;
use App\Http\Requests\Request;
use App\Http\ValidationRules\Scheduler\ValidClientIds;
use App\Utils\Traits\MakesHash;
class StoreSchedulerRequest extends Request
{
use MakesHash;
public array $client_statuses = [
'all',
'draft',
'paid',
'unpaid',
'overdue',
'pending',
'invoiced',
'logged',
'partial',
'applied',
'active',
'paused',
'completed',
'approved',
'expired',
'upcoming',
'converted',
'uninvoiced',
];
/**
* Determine if the user is authorized to make this request.
*
@ -47,7 +66,7 @@ class StoreSchedulerRequest extends Request
'parameters.end_date' => ['bail', 'sometimes', 'date:Y-m-d', 'required_if:parameters.date_rate,custom', 'after_or_equal:parameters.start_date'],
'parameters.entity' => ['bail', 'sometimes', 'string', 'in:invoice,credit,quote,purchase_order'],
'parameters.entity_id' => ['bail', 'sometimes', 'string'],
'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report','in:vendor,purchase_order_item,purchase_order,ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,activity,client,contact,client_contact,credit,document,expense,invoice,invoice_item,quote,quote_item,recurring_invoice,payment,product,task'],
'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report','in:vendor,purchase_order_item,purchase_order,ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,activity,activities,client,clients,client_contact,client_contacts,credit,credits,document,documents,expense,expenses,invoice,invoices,invoice_item,invoice_items,quote,quotes,quote_item,quote_items,recurring_invoice,recurring_invoices,payment,payments,product,products,task,tasks'],
'parameters.date_key' => ['bail','sometimes', 'string'],
'parameters.status' => ['bail','sometimes', 'nullable', 'string'],
];
@ -73,10 +92,18 @@ class StoreSchedulerRequest extends Request
if(isset($input['parameters']['status'])) {
$task_statuses = [];
if(isset($input['parameters']['report_name']) && $input['parameters']['report_name'] == 'task') {
$task_statuses = array_diff(explode(",", $input['parameters']['status']), $this->client_statuses);
}
$input['parameters']['status'] = collect(explode(",", $input['parameters']['status']))
->filter(function ($status) {
return in_array($status, ['all','draft','paid','unpaid','overdue']);
})->implode(",") ?? '';
return in_array($status, $this->client_statuses);
})->merge($task_statuses)
->implode(",") ?? '';
}
$this->replace($input);

View File

@ -16,6 +16,27 @@ use App\Http\ValidationRules\Scheduler\ValidClientIds;
class UpdateSchedulerRequest extends Request
{
public array $client_statuses = [
'all',
'draft',
'paid',
'unpaid',
'overdue',
'pending',
'invoiced',
'logged',
'partial',
'applied',
'active',
'paused',
'completed',
'approved',
'expired',
'upcoming',
'converted',
'uninvoiced',
];
/**
* Determine if the user is authorized to make this request.
*
@ -45,9 +66,9 @@ class UpdateSchedulerRequest extends Request
'parameters.end_date' => ['bail', 'sometimes', 'date:Y-m-d', 'required_if:parameters.date_rate,custom', 'after_or_equal:parameters.start_date'],
'parameters.entity' => ['bail', 'sometimes', 'string', 'in:invoice,credit,quote,purchase_order'],
'parameters.entity_id' => ['bail', 'sometimes', 'string'],
'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report','in:vendor,purchase_order_item,purchase_order,ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,activity,client,contact,client_contact,credit,document,expense,invoice,invoice_item,quote,quote_item,recurring_invoice,payment,product,task'],
'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report','in:vendor,purchase_order_item,purchase_order,ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,activity,activities,client,clients,client_contact,client_contacts,credit,credits,document,documents,expense,expenses,invoice,invoices,invoice_item,invoice_items,quote,quotes,quote_item,quote_items,recurring_invoice,recurring_invoices,payment,payments,product,products,task,tasks'],
'parameters.date_key' => ['bail','sometimes', 'string'],
'parameters.status' => ['bail','sometimes', 'string'],
'parameters.status' => ['bail','sometimes', 'nullable', 'string'],
];
return $rules;
@ -71,10 +92,18 @@ class UpdateSchedulerRequest extends Request
if(isset($input['parameters']['status'])) {
$task_statuses = [];
if(isset($input['parameters']['report_name']) && $input['parameters']['report_name'] == 'task') {
$task_statuses = array_diff(explode(",", $input['parameters']['status']), $this->client_statuses);
}
$input['parameters']['status'] = collect(explode(",", $input['parameters']['status']))
->filter(function ($status) {
return in_array($status, ['all','draft','paid','unpaid','overdue']);
})->implode(",") ?? '';
return in_array($status, $this->client_statuses);
})->merge($task_statuses)
->implode(",") ?? '';
}
$this->replace($input);

View File

@ -95,6 +95,8 @@ class StoreUserRequest extends Request
$input['last_name'] = strip_tags($input['last_name']);
}
$input['id'] = null;
$this->replace($input);
}

View File

@ -23,7 +23,10 @@ class StoreWebhookRequest extends Request
*/
public function authorize(): bool
{
return auth()->user()->isAdmin() && auth()->user()->account->hasFeature(Account::FEATURE_API);
/** @var \App\Models\User $user */
$user = auth()->user();
return $user->isAdmin() && $user->account->hasFeature(Account::FEATURE_API);
}
public function rules()
@ -31,7 +34,6 @@ class StoreWebhookRequest extends Request
return [
'target_url' => 'bail|required|url',
'event_id' => 'bail|required',
// 'headers' => 'bail|sometimes|json',
'rest_method' => 'required|in:post,put'
];
}
@ -43,8 +45,6 @@ class StoreWebhookRequest extends Request
if (!isset($input['rest_method'])) {
$input['rest_method'] = 'post';
}
// if(isset($input['headers']) && count($input['headers']) == 0)
// $input['headers'] = null;
$this->replace($input);
}

View File

@ -98,19 +98,19 @@ class InvoiceTransformer extends BaseTransformer
$invoice_data,
'invoice.partial_due_date'
),
'custom_surcharge1' => $this->getString(
'custom_surcharge1' => $this->getFloat(
$invoice_data,
'invoice.custom_surcharge1'
),
'custom_surcharge2' => $this->getString(
'custom_surcharge2' => $this->getFloat(
$invoice_data,
'invoice.custom_surcharge2'
),
'custom_surcharge3' => $this->getString(
'custom_surcharge3' => $this->getFloat(
$invoice_data,
'invoice.custom_surcharge3'
),
'custom_surcharge4' => $this->getString(
'custom_surcharge4' => $this->getFloat(
$invoice_data,
'invoice.custom_surcharge4'
),

View File

@ -114,23 +114,26 @@ class ProcessBankTransactionsNordigen implements ShouldQueue
private function updateAccount()
{
if (!$this->nordigen->isAccountActive($this->bank_integration->nordigen_account_id)) {
$is_account_active = $this->nordigen->isAccountActive($this->bank_integration->nordigen_account_id);
$account = $this->nordigen->getAccount($this->bank_integration->nordigen_account_id);
if (!$is_account_active || !$account) {
$this->bank_integration->disabled_upstream = true;
$this->bank_integration->save();
$this->stop_loop = false;
nlog("Nordigen: account inactive: " . $this->bank_integration->nordigen_account_id);
// @turbo124 @todo send email for expired account
$this->nordigen->disabledAccountEmail($this->bank_integration);
return;
}
$this->nordigen_account = $this->nordigen->getAccount($this->bank_integration->nordigen_account_id);
$this->nordigen_account = $account;
$this->bank_integration->disabled_upstream = false;
$this->bank_integration->bank_account_status = $this->nordigen_account['account_status'];
$this->bank_integration->balance = $this->nordigen_account['current_balance'];
$this->bank_integration->bank_account_status = $account['account_status'];
$this->bank_integration->balance = $account['current_balance'];
$this->bank_integration->save();
}

View File

@ -311,7 +311,10 @@ class CompanyImport implements ShouldQueue
}
}
if(file_exists($tmp_file))
unlink($tmp_file);
if(Storage::exists($this->file_location))
unlink(Storage::path($this->file_location));
}

View File

@ -145,7 +145,8 @@ class NinjaMailerJob implements ShouldQueue
->send($mailable);
/* Count the amount of emails sent across all the users accounts */
Cache::increment("email_quota".$this->company->account->key);
$this->incrementEmailCounter();
LightLogs::create(new EmailSuccess($this->nmo->company->company_key, $this->nmo->mailable->subject))
->send();
@ -221,6 +222,12 @@ class NinjaMailerJob implements ShouldQueue
$this->cleanUpMailers();
}
private function incrementEmailCounter(): void
{
if(in_array($this->mailer, ['default','mailgun']))
Cache::increment("email_quota".$this->company->account->key);
}
/**
* Entity notification when an email fails to send
*
@ -279,13 +286,21 @@ class NinjaMailerJob implements ShouldQueue
$this->mailer = 'postmark';
$this->client_postmark_secret = config('services.postmark-outlook.token');
if (property_exists($this->nmo->settings, 'email_from_name') && strlen($this->nmo->settings->email_from_name) > 1) {
$email_from_name = $this->nmo->settings->email_from_name;
} else {
$email_from_name = $this->company->present()->name();
}
$this->nmo
->mailable
->from('maildelivery@invoice.services', 'Invoice Ninja');
->from(config('services.postmark-outlook.from.address'), $email_from_name);
return $this;
}
} catch(\Exception $e) {
nlog("problem switching outlook driver - hosted");
nlog($e->getMessage());
}
}
@ -316,7 +331,10 @@ class NinjaMailerJob implements ShouldQueue
$this->mailer = 'mailgun';
$this->setMailgunMailer();
return $this;
case 'smtp':
$this->mailer = 'smtp';
$this->configureSmtpMailer();
return $this;
default:
break;
}
@ -328,6 +346,48 @@ class NinjaMailerJob implements ShouldQueue
return $this;
}
private function configureSmtpMailer(): void
{
$company = $this->company;
$smtp_host = $company->smtp_host;
$smtp_port = $company->smtp_port;
$smtp_username = $company->smtp_username;
$smtp_password = $company->smtp_password;
$smtp_encryption = $company->smtp_encryption ?? 'tls';
$smtp_local_domain = strlen($company->smtp_local_domain) > 2 ? $company->smtp_local_domain : null;
$smtp_verify_peer = $company->smtp_verify_peer ?? true;
config([
'mail.mailers.smtp' => [
'transport' => 'smtp',
'host' => $smtp_host,
'port' => $smtp_port,
'username' => $smtp_username,
'password' => $smtp_password,
'encryption' => $smtp_encryption,
'local_domain' => $smtp_local_domain,
'verify_peer' => $smtp_verify_peer,
'timeout' => 30,
],
]);
if (property_exists($this->nmo->settings, 'email_from_name') && strlen($this->nmo->settings->email_from_name) > 1) {
$email_from_name = $this->nmo->settings->email_from_name;
} else {
$email_from_name = $this->company->present()->name();
}
$user = $this->resolveSendingUser();
$sending_email = (isset($this->nmo->settings->custom_sending_email) && stripos($this->nmo->settings->custom_sending_email, "@")) ? $this->nmo->settings->custom_sending_email : $user->email;
$this->nmo
->mailable
->from($sending_email, $email_from_name);
}
/**
* Allows configuration of multiple mailers
* per company for use by self hosted users

View File

@ -60,6 +60,7 @@ class TaskScheduler implements ShouldQueue
nlog("Doing job {$scheduler->name}");
try {
//@var \App\Models\Schedule $scheduler
$scheduler->service()->runTask();
} catch(\Exception $e) {
nlog($e->getMessage());

View File

@ -26,7 +26,6 @@ use App\Utils\Traits\MakesReminders;
use Illuminate\Support\Facades\Auth;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Spatie\OpenTelemetry\Jobs\TraceAware;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

View File

@ -123,7 +123,7 @@ class WebhookSingle implements ShouldQueue
]);
(new SystemLogger(
array_merge((array) $response, $data),
['message' => $response->getHeaders(), 'body' => $data],
SystemLog::CATEGORY_WEBHOOK,
SystemLog::EVENT_WEBHOOK_SUCCESS,
SystemLog::TYPE_WEBHOOK_RESPONSE,
@ -136,7 +136,7 @@ class WebhookSingle implements ShouldQueue
nlog($e->getMessage());
(new SystemLogger(
['message' => "Error connecting to ". $subscription->target_url],
['message' => "Error connecting to ". $subscription->target_url, 'body' => $data],
SystemLog::CATEGORY_WEBHOOK,
SystemLog::EVENT_WEBHOOK_FAILURE,
SystemLog::TYPE_WEBHOOK_RESPONSE,
@ -152,7 +152,7 @@ class WebhookSingle implements ShouldQueue
$message = "There was a problem when connecting to {$subscription->target_url} => status code ". $e->getResponse()->getStatusCode(). " This webhook call will be suspended until further action is taken.";
(new SystemLogger(
['message' => $message],
['message' => $message, 'body' => $data],
SystemLog::CATEGORY_WEBHOOK,
SystemLog::EVENT_WEBHOOK_FAILURE,
SystemLog::TYPE_WEBHOOK_RESPONSE,
@ -170,7 +170,7 @@ class WebhookSingle implements ShouldQueue
nlog($message);
(new SystemLogger(
['message' => $message],
['message' => $message, 'body' => $data],
SystemLog::CATEGORY_WEBHOOK,
SystemLog::EVENT_WEBHOOK_FAILURE,
SystemLog::TYPE_WEBHOOK_RESPONSE,
@ -192,7 +192,7 @@ class WebhookSingle implements ShouldQueue
$message = "There was a problem when connecting to {$subscription->target_url} => status code ". $e->getResponse()->getStatusCode(). " no retry attempted.";
(new SystemLogger(
['message' => $message],
['message' => $message, 'body' => $data],
SystemLog::CATEGORY_WEBHOOK,
SystemLog::EVENT_WEBHOOK_FAILURE,
SystemLog::TYPE_WEBHOOK_RESPONSE,
@ -208,7 +208,7 @@ class WebhookSingle implements ShouldQueue
$error = json_decode($e->getResponse()->getBody()->getContents());
(new SystemLogger(
['message' => $error],
['message' => $error, 'body' => $data],
SystemLog::CATEGORY_WEBHOOK,
SystemLog::EVENT_WEBHOOK_FAILURE,
SystemLog::TYPE_WEBHOOK_RESPONSE,
@ -220,7 +220,7 @@ class WebhookSingle implements ShouldQueue
$error = json_decode($e->getResponse()->getBody()->getContents());
(new SystemLogger(
['message' => $error],
['message' => $error, 'body' => $data],
SystemLog::CATEGORY_WEBHOOK,
SystemLog::EVENT_WEBHOOK_FAILURE,
SystemLog::TYPE_WEBHOOK_RESPONSE,
@ -232,7 +232,7 @@ class WebhookSingle implements ShouldQueue
nlog($e->getCode());
(new SystemLogger(
$e->getMessage(),
['message' => $e->getMessage(), 'body' => $data],
SystemLog::CATEGORY_WEBHOOK,
SystemLog::EVENT_WEBHOOK_FAILURE,
SystemLog::TYPE_WEBHOOK_RESPONSE,

View File

@ -149,6 +149,7 @@ class PdfSlot extends Component
return render('components.livewire.pdf-slot', [
'invitation' => $this->invitation,
'entity' => $this->entity,
'settings' => $this->settings,
'data' => $this->invitation->company->settings,
'entity_type' => $this->entity_type,
'products' => $this->getProducts(),

View File

@ -12,15 +12,17 @@
namespace App\Livewire;
use App\Models\Client;
use App\Models\Invoice;
use Livewire\Component;
use App\Libraries\MultiDB;
use Illuminate\Support\Str;
use App\Models\ClientContact;
use App\Models\CompanyGateway;
use App\Models\Invoice;
use App\Utils\Traits\MakesHash;
use Livewire\Attributes\Computed;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Livewire\Component;
class RequiredClientInfo extends Component
{
@ -31,10 +33,7 @@ class RequiredClientInfo extends Component
*/
public $show_terms = false;
/**
* @var array
*/
public $invoice;
public $invoice_terms;
/**
* @var bool
@ -49,18 +48,40 @@ class RequiredClientInfo extends Component
/**
* @var ClientContact
*/
public $contact;
public $contact_id;
/**
* @var \App\Models\Client
*/
public $client;
public $client_id;
/**
* @var array
*/
public $countries;
public $client_name;
public $contact_first_name;
public $contact_last_name;
public $contact_email;
public $client_phone;
public $client_address_line_1;
public $client_city;
public $client_state;
public $client_country_id;
public $client_postal_code;
public $client_shipping_address_line_1;
public $client_shipping_city;
public $client_shipping_state;
public $client_shipping_postal_code;
public $client_shipping_country_id;
public $client_custom_value1;
public $client_custom_value2;
public $client_custom_value3;
public $client_custom_value4;
/**
* Mappings for updating the database. Left side is mapping from gateway,
* right side is column in database.
@ -113,50 +134,96 @@ class RequiredClientInfo extends Component
];
protected $rules = [
'client.address1' => '',
'client.address2' => '',
'client.city' => '',
'client.state' => '',
'client.postal_code' => '',
'client.country_id' => '',
'client.shipping_address1' => '',
'client.shipping_address2' => '',
'client.shipping_city' => '',
'client.shipping_state' => '',
'client.shipping_postal_code' => '',
'client.shipping_country_id' => '',
'contact.first_name' => '',
'contact.last_name' => '',
'contact.email' => '',
'client.name' => '',
'client.website' => '',
'client.phone' => '',
'client.custom_value1' => '',
'client.custom_value2' => '',
'client.custom_value3' => '',
'client.custom_value4' => '',
// 'client.address1' => '',
// 'client.address2' => '',
// 'client.city' => '',
// 'client.state' => '',
// 'client.postal_code' => '',
// 'client.country_id' => '',
// 'client.shipping_address1' => '',
// 'client.shipping_address2' => '',
// 'client.shipping_city' => '',
// 'client.shipping_state' => '',
// 'client.shipping_postal_code' => '',
// 'client.shipping_country_id' => '',
// 'contact.first_name' => '',
// 'contact.last_name' => '',
// 'contact.email' => '',
// 'client.name' => '',
// 'client.website' => '',
// 'client.phone' => '',
// 'client.custom_value1' => '',
// 'client.custom_value2' => '',
// 'client.custom_value3' => '',
// 'client.custom_value4' => '',
'client_name' => '',
'client_website' => '',
'client_phone' => '',
'client_address_line_1' => '',
'client_address_line_2' => '',
'client_city' => '',
'client_state' => '',
'client_postal_code' => '',
'client_country_id' => '',
'client_shipping_address_line_1' => '',
'client_shipping_address_line_2' => '',
'client_shipping_city' => '',
'client_shipping_state' => '',
'client_shipping_postal_code' => '',
'client_shipping_country_id' => '',
'client_custom_value1' => '',
'client_custom_value2' => '',
'client_custom_value3' => '',
'client_custom_value4' => '',
'contact_first_name' => '',
'contact_last_name' => '',
'contact_email' => '',
];
public $show_form = false;
public $company;
public $company_id;
public $company_gateway_id;
public $db;
public function mount()
{
MultiDB::setDb($this->company->db);
MultiDB::setDb($this->db);
$contact = ClientContact::withTrashed()->find($this->contact_id);
$company = $contact->company;
$this->client = $this->contact->client;
$this->client_name = $contact->client->name;
$this->contact_first_name = $contact->first_name;
$this->contact_last_name = $contact->last_name;
$this->contact_email = $contact->email;
$this->client_phone = $contact->client->phone;
$this->client_address_line_1 = $contact->client->address1;
$this->client_city = $contact->client->city ;
$this->client_state = $contact->client->state;
$this->client_country_id = $contact->client->country_id;
$this->client_postal_code = $contact->client->postal_code;
$this->client_shipping_address_line_1 = $contact->client->shipping_address1;
$this->client_shipping_city = $contact->client->shipping_city;
$this->client_shipping_state = $contact->client->shipping_state;
$this->client_shipping_postal_code = $contact->client->shipping_postal_code;
$this->client_shipping_country_id = $contact->client->shipping_country_id;
$this->client_custom_value1 = $contact->client->custom_value1;
$this->client_custom_value2 = $contact->client->custom_value2;
$this->client_custom_value3 = $contact->client->custom_value3;
$this->client_custom_value4 = $contact->client->custom_value4;
if ($this->company->settings->show_accept_invoice_terms && request()->query('hash')) {
// $this->client = $this->contact->client;
if ($company->settings->show_accept_invoice_terms && request()->query('hash')) {
$this->show_terms = true;
$this->terms_accepted = false;
$this->show_form = true;
$hash = Cache::get(request()->input('hash'));
$this->invoice = Invoice::find($this->decodePrimaryKey($hash['invoice_id']));
$this->invoice_terms = Invoice::find($this->decodePrimaryKey($hash['invoice_id']))->terms;
}
count($this->fields) > 0 || $this->show_terms
@ -164,6 +231,24 @@ class RequiredClientInfo extends Component
: $this->show_form = false;
}
#[Computed]
public function contact()
{
MultiDB::setDb($this->db);
return ClientContact::withTrashed()->find($this->contact_id);
}
#[Computed]
public function client()
{
MultiDB::setDb($this->db);
return ClientContact::withTrashed()->find($this->contact_id)->client;
}
public function toggleTermsAccepted()
{
$this->terms_accepted = !$this->terms_accepted;
@ -171,6 +256,10 @@ class RequiredClientInfo extends Component
public function handleSubmit(array $data): bool
{
MultiDB::setDb($this->db);
$contact = ClientContact::withTrashed()->find($this->contact_id);
$rules = [];
collect($this->fields)->map(function ($field) use (&$rules) {
@ -192,7 +281,7 @@ class RequiredClientInfo extends Component
if ($this->updateClientDetails($data)) {
$this->dispatch(
'passed-required-fields-check',
client_postal_code: $this->contact->client->postal_code
client_postal_code: $contact->client->postal_code
);
//if stripe is enabled, we want to update the customer at this point.
@ -209,6 +298,11 @@ class RequiredClientInfo extends Component
$client = [];
$contact = [];
MultiDB::setDb($this->db);
$_contact = ClientContact::withTrashed()->find($this->contact_id);
foreach ($data as $field => $value) {
if (Str::startsWith($field, 'client_')) {
$client[$this->mappings[$field]] = $value;
@ -219,20 +313,43 @@ class RequiredClientInfo extends Component
}
}
$contact_update = $this->contact
$_contact->first_name = $this->contact_first_name;
$_contact->last_name = $this->contact_last_name;
$_contact->client->name = $this->client_name;
$_contact->email = $this->contact_email;
$_contact->client->phone = $this->client_phone;
$_contact->client->address1 = $this->client_address_line_1;
$_contact->client->city = $this->client_city;
$_contact->client->state = $this->client_state;
$_contact->client->country_id = $this->client_country_id;
$_contact->client->postal_code = $this->client_postal_code;
$_contact->client->shipping_address1 = $this->client_shipping_address_line_1;
$_contact->client->shipping_city = $this->client_shipping_city;
$_contact->client->shipping_state = $this->client_shipping_state;
$_contact->client->shipping_postal_code = $this->client_shipping_postal_code;
$_contact->client->shipping_country_id = $this->client_shipping_country_id;
$_contact->client->custom_value1 = $this->client_custom_value1;
$_contact->client->custom_value2 = $this->client_custom_value2;
$_contact->client->custom_value3 = $this->client_custom_value3;
$_contact->client->custom_value4 = $this->client_custom_value4;
$_contact->push();
$contact_update = $_contact
->fill($contact)
->push();
$client_update = $this->contact->client
$client_update = $_contact->client
->fill($client)
->push();
if ($contact_update && $client_update) {
if ($_contact) {
/** @var \App\Models\CompanyGateway $cg */
$cg = CompanyGateway::find($this->company_gateway_id);
if ($cg && $cg->update_details) {
$payment_gateway = $cg->driver($this->client)->init();
$payment_gateway = $cg->driver($_contact->client)->init();
if (method_exists($payment_gateway, "updateCustomer")) {
$payment_gateway->updateCustomer();
@ -247,11 +364,15 @@ class RequiredClientInfo extends Component
public function checkFields()
{
MultiDB::setDb($this->db);
$_contact = ClientContact::withTrashed()->find($this->contact_id);
foreach ($this->fields as $index => $field) {
$_field = $this->mappings[$field['name']];
if (Str::startsWith($field['name'], 'client_')) {
if (empty($this->contact->client->{$_field}) || is_null($this->contact->client->{$_field}) || in_array($_field, $this->client_address_array)) {
if (empty($_contact->client->{$_field}) || is_null($_contact->client->{$_field}) || in_array($_field, $this->client_address_array)) {
$this->show_form = true;
} else {
$this->fields[$index]['filled'] = true;
@ -259,7 +380,7 @@ class RequiredClientInfo extends Component
}
if (Str::startsWith($field['name'], 'contact_')) {
if (empty($this->contact->{$_field}) || is_null($this->contact->{$_field}) || str_contains($this->contact->{$_field}, '@example.com')) {
if (empty($_contact->{$_field}) || is_null($_contact->{$_field}) || str_contains($_contact->{$_field}, '@example.com')) {
$this->show_form = true;
} else {
$this->fields[$index]['filled'] = true;
@ -289,14 +410,18 @@ class RequiredClientInfo extends Component
public function handleCopyBilling(): void
{
MultiDB::setDb($this->db);
$_contact = ClientContact::withTrashed()->find($this->contact_id);
$this->dispatch(
'update-shipping-data',
client_shipping_address_line_1: $this->contact->client->address1,
client_shipping_address_line_2: $this->contact->client->address2,
client_shipping_city: $this->contact->client->city,
client_shipping_state: $this->contact->client->state,
client_shipping_postal_code: $this->contact->client->postal_code,
client_shipping_country_id: $this->contact->client->country_id,
client_shipping_address_line_1: $_contact->client->address1,
client_shipping_address_line_2: $_contact->client->address2,
client_shipping_city: $_contact->client->city,
client_shipping_state: $_contact->client->state,
client_shipping_postal_code: $_contact->client->postal_code,
client_shipping_country_id: $_contact->client->country_id,
);
}

View File

@ -52,7 +52,7 @@ class ClientStatement extends Mailable
public function content()
{
return new Content(
view: $this->data['company']->account->isPremium() ? 'email.template.client_premium' : 'email.template.client',
view: 'email.template.client',
text: 'email.template.text',
with: [
'text_body' => $this->data['body'],

View File

@ -75,7 +75,8 @@ class TemplateEmail extends Mailable
$template_name = 'email.template.'.$this->build_email->getTemplate();
if ($this->build_email->getTemplate() == 'light' || $this->build_email->getTemplate() == 'dark') {
$template_name = $this->company->account->isPremium() ? 'email.template.client_premium' : 'email.template.client';
// $template_name = $this->company->account->isPremium() ? 'email.template.client_premium' : 'email.template.client';
$template_name = 'email.template.client';
}
if ($this->build_email->getTemplate() == 'custom') {

View File

@ -72,7 +72,8 @@ class VendorTemplateEmail extends Mailable
$template_name = 'email.template.'.$this->build_email->getTemplate();
if ($this->build_email->getTemplate() == 'light' || $this->build_email->getTemplate() == 'dark') {
$template_name = $this->company->account->isPremium() ? 'email.template.client_premium' : 'email.template.client';
// $template_name = $this->company->account->isPremium() ? 'email.template.client_premium' : 'email.template.client';
$template_name = 'email.template.client';
}
if ($this->build_email->getTemplate() == 'custom') {

View File

@ -208,6 +208,29 @@ class Document extends BaseModel
return ctrans('texts.document');
}
public function link()
{
$entity_id = $this->encodePrimaryKey($this->documentable_id);
$link = '';
match($this->documentable_type) {
'App\Models\Vendor' => $link = "/vendors/{$entity_id}",
'App\Models\Project' => $link = "/projects/{$entity_id}",
'invoices' => $link = "/invoices/{$entity_id}/edit",
'App\Models\Quote' => $link = "/quotes/{$entity_id}/edit",
'App\Models\Credit' => $link = "/credits/{$entity_id}/edit",
'App\Models\Expense' => $link = "/expenses/{$entity_id}/edit",
'App\Models\Payment' => $link = "/payments/{$entity_id}/edit",
'App\Models\Task' => $link = "/tasks/{$entity_id}/edit",
'App\Models\Client' => $link = "/clients/{$entity_id}",
'App\Models\RecurringExpense' => $link = "/recurring_expenses/{$entity_id}/edit",
'App\Models\RecurringInvoice' => $link = "/recurring_invoices/{$entity_id}/edit",
default => $link = '',
};
return $link;
}
public function compress(): mixed
{

View File

@ -137,22 +137,22 @@ class Gateway extends StaticModel
case 56:
return [
GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true, 'webhooks' => ['payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'customer.source.updated','payment_intent.processing', 'payment_intent.payment_failed']],
GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'customer.source.updated','payment_intent.processing', 'payment_intent.payment_failed', 'charge.failed']],
GatewayType::DIRECT_DEBIT => ['refund' => false, 'token_billing' => false, 'webhooks' => ['payment_intent.processing','payment_intent.succeeded','payment_intent.partially_funded', 'payment_intent.payment_failed']],
GatewayType::ALIPAY => ['refund' => false, 'token_billing' => false],
GatewayType::APPLE_PAY => ['refund' => false, 'token_billing' => false],
GatewayType::BACS => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.processing', 'payment_intent.succeeded', 'mandate.updated', 'payment_intent.payment_failed']],
GatewayType::SOFORT => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::KLARNA => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::SEPA => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::PRZELEWY24 => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::GIROPAY => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::EPS => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::BANCONTACT => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::BECS => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::IDEAL => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::ACSS => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::FPX => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']],
GatewayType::BACS => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.processing', 'payment_intent.succeeded', 'mandate.updated', 'payment_intent.payment_failed']],
GatewayType::SOFORT => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::KLARNA => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::SEPA => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::PRZELEWY24 => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::GIROPAY => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::EPS => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::BANCONTACT => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::BECS => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::IDEAL => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::ACSS => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', 'payment_intent.succeeded', 'payment_intent.payment_failed']],
GatewayType::FPX => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'charge.failed', ]],
];
case 39:
return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true, 'webhooks' => [' ']]]; //Checkout

View File

@ -355,10 +355,12 @@ class RecurringInvoice extends BaseModel
public function calculateStatus(bool $new_model = false) //15-02-2024 - $new_model needed
{
if($this->remaining_cycles == 0) {
if($this->remaining_cycles == 0)
return self::STATUS_COMPLETED;
} elseif ($new_model && $this->status_id == self::STATUS_ACTIVE && Carbon::parse($this->next_send_date)->isFuture())
elseif ($new_model && $this->status_id == self::STATUS_ACTIVE && Carbon::parse($this->next_send_date)->isFuture())
return self::STATUS_PENDING;
elseif($this->remaining_cycles != 0 && ($this->status_id == self::STATUS_COMPLETED))
return self::STATUS_ACTIVE;
return $this->status_id;

View File

@ -180,6 +180,7 @@ class Webhook extends BaseModel
self::EVENT_DELETE_PURCHASE_ORDER,
self::EVENT_RESTORE_PURCHASE_ORDER,
self::EVENT_ARCHIVE_PURCHASE_ORDER,
self::EVENT_CREATE_PRODUCT,
self::EVENT_UPDATE_PRODUCT,
self::EVENT_DELETE_PRODUCT,
self::EVENT_RESTORE_PRODUCT,

View File

@ -271,7 +271,7 @@ class CreditCard implements MethodInterface
$errors = $api_response->getErrors();
}
if (property_exists($customers, 'customers')) {
if ($customers && property_exists($customers, 'customers')) {
return $customers->customers[0]->id;
}

View File

@ -89,6 +89,10 @@ class PaymentIntentWebhook implements ShouldQueue
}
$company_gateway = CompanyGateway::query()->find($this->company_gateway_id);
if(!$company_gateway)
return;
$stripe_driver = $company_gateway->driver()->init();
$charge_id = false;

View File

@ -44,7 +44,6 @@ class InstantPayment
public function run()
{
nlog($this->request->all());
$cc = auth()->guard('contact')->user();

View File

@ -244,6 +244,12 @@ class Email implements ShouldQueue
return $this;
}
private function incrementEmailCounter(): void
{
if(in_array($this->mailer, ['default','mailgun']))
Cache::increment("email_quota".$this->company->account->key);
}
/**
* Attempts to send the email
*
@ -270,7 +276,7 @@ class Email implements ShouldQueue
$mailer->send($this->mailable);
Cache::increment("email_quota".$this->company->account->key);
$this->incrementEmailCounter();
LightLogs::create(new EmailSuccess($this->company->company_key, $this->mailable->subject))
->send();
@ -503,15 +509,22 @@ class Email implements ShouldQueue
$server = $dns[0]["target"];
if(stripos($server, "outlook.com") !== false) {
if (property_exists($this->email_object->settings, 'email_from_name') && strlen($this->email_object->settings->email_from_name) > 1) {
$email_from_name = $this->email_object->settings->email_from_name;
} else {
$email_from_name = $this->company->present()->name();
}
$this->mailer = 'postmark';
$this->client_postmark_secret = config('services.postmark-outlook.token');
$this->mailable
->from('maildelivery@invoice.services', 'Invoice Ninja');
->from(config('services.postmark-outlook.from.address'), $email_from_name);
return $this;
}
} catch(\Exception $e) {
nlog("problem switching outlook driver - hosted");
nlog($e->getMessage());
}
}
@ -542,7 +555,10 @@ class Email implements ShouldQueue
$this->mailer = 'mailgun';
$this->setMailgunMailer();
return $this;
case 'smtp':
$this->mailer = 'smtp';
$this->configureSmtpMailer();
return $this;
default:
$this->mailer = config('mail.default');
return $this;
@ -555,6 +571,43 @@ class Email implements ShouldQueue
return $this;
}
private function configureSmtpMailer(): void
{
$company = $this->company;
$smtp_host = $company->smtp_host;
$smtp_port = $company->smtp_port;
$smtp_username = $company->smtp_username;
$smtp_password = $company->smtp_password;
$smtp_encryption = $company->smtp_encryption ?? 'tls';
$smtp_local_domain = strlen($company->smtp_local_domain) > 2 ? $company->smtp_local_domain : null;
$smtp_verify_peer = $company->smtp_verify_peer ?? true;
config([
'mail.mailers.smtp' => [
'transport' => 'smtp',
'host' => $smtp_host,
'port' => $smtp_port,
'username' => $smtp_username,
'password' => $smtp_password,
'encryption' => $smtp_encryption,
'local_domain' => $smtp_local_domain,
'verify_peer' => $smtp_verify_peer,
'timeout' => 30,
],
]);
$user = $this->resolveSendingUser();
$sending_email = (isset($this->email_object->settings->custom_sending_email) && stripos($this->email_object->settings->custom_sending_email, "@")) ? $this->email_object->settings->custom_sending_email : $user->email;
$sending_user = (isset($this->email_object->settings->email_from_name) && strlen($this->email_object->settings->email_from_name) > 2) ? $this->email_object->settings->email_from_name : $user->name();
$this->mailable
->from($sending_email, $sending_user);
}
/**
* Allows configuration of multiple mailers
* per company for use by self hosted users

View File

@ -107,10 +107,10 @@ class EmailDefaults
match ($this->email->email_object->settings->email_style) {
'plain' => $this->template = 'email.template.plain',
'light' => $this->template = $this->email->email_object->company->account->isPremium() ? 'email.template.client_premium' : 'email.template.client',
'dark' => $this->template = $this->email->email_object->company->account->isPremium() ? 'email.template.client_premium' :'email.template.client',
'light' => $this->template = 'email.template.client',
'dark' => $this->template = 'email.template.client',
'custom' => $this->template = 'email.template.custom',
default => $this->template = $this->email->email_object->company->account->isPremium() ? 'email.template.client_premium' :'email.template.client',
default => $this->template = 'email.template.client',
};
$this->email->email_object->html_template = $this->template;
@ -123,7 +123,7 @@ class EmailDefaults
*/
private function setFrom(): self
{
if (Ninja::isHosted() && $this->email->email_object->settings->email_sending_method == 'default') {
if (Ninja::isHosted() && in_array($this->email->email_object->settings->email_sending_method,['default', 'mailgun'])) {
if ($this->email->company->account->isPaid() && property_exists($this->email->email_object->settings, 'email_from_name') && strlen($this->email->email_object->settings->email_from_name) > 1) {
$email_from_name = $this->email->email_object->settings->email_from_name;
} else {

View File

@ -11,34 +11,35 @@
namespace App\Services\Scheduler;
use App\Export\CSV\ClientExport;
use App\Export\CSV\ContactExport;
use App\Export\CSV\CreditExport;
use App\Export\CSV\DocumentExport;
use App\Export\CSV\ExpenseExport;
use App\Export\CSV\InvoiceExport;
use App\Export\CSV\InvoiceItemExport;
use App\Export\CSV\PaymentExport;
use App\Export\CSV\ProductExport;
use App\Export\CSV\ProductSalesExport;
use App\Export\CSV\QuoteExport;
use App\Export\CSV\QuoteItemExport;
use App\Export\CSV\RecurringInvoiceExport;
use App\Export\CSV\TaskExport;
use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
use App\Mail\DownloadReport;
use App\Models\Client;
use App\Models\Scheduler;
use App\Mail\DownloadReport;
use App\Export\CSV\TaskExport;
use App\Export\CSV\QuoteExport;
use App\Utils\Traits\MakesHash;
use App\Export\CSV\ClientExport;
use App\Export\CSV\CreditExport;
use App\Utils\Traits\MakesDates;
use App\Export\CSV\ContactExport;
use App\Export\CSV\ExpenseExport;
use App\Export\CSV\InvoiceExport;
use App\Export\CSV\PaymentExport;
use App\Export\CSV\ProductExport;
use App\Jobs\Mail\NinjaMailerJob;
use App\Export\CSV\ActivityExport;
use App\Export\CSV\DocumentExport;
use App\Export\CSV\QuoteItemExport;
use App\Services\Report\ProfitLoss;
use App\Jobs\Mail\NinjaMailerObject;
use App\Export\CSV\InvoiceItemExport;
use App\Export\CSV\ProductSalesExport;
use App\Services\Report\ARDetailReport;
use App\Services\Report\ARSummaryReport;
use App\Services\Report\ClientBalanceReport;
use App\Services\Report\ClientSalesReport;
use App\Services\Report\ProfitLoss;
use App\Services\Report\TaxSummaryReport;
use App\Services\Report\UserSalesReport;
use App\Utils\Traits\MakesDates;
use App\Utils\Traits\MakesHash;
use App\Services\Report\TaxSummaryReport;
use App\Export\CSV\RecurringInvoiceExport;
use App\Services\Report\ClientSalesReport;
use App\Services\Report\ClientBalanceReport;
class EmailReport
{
@ -77,19 +78,33 @@ class EmailReport
'client_sales' => $export = (new ClientSalesReport($this->scheduler->company, $data)),
'user_sales' => $export = (new UserSalesReport($this->scheduler->company, $data)),
'profitloss' => $export = (new ProfitLoss($this->scheduler->company, $data)),
'activity' => $export = (new ActivityExport($this->scheduler->company, $data)),
'activities' => $export = (new ActivityExport($this->scheduler->company, $data)),
'client' => $export = (new ClientExport($this->scheduler->company, $data)),
'clients' => $export = (new ClientExport($this->scheduler->company, $data)),
'client_contact' => $export = (new ContactExport($this->scheduler->company, $data)),
'client_contacts' => $export = (new ContactExport($this->scheduler->company, $data)),
'credit' => $export = (new CreditExport($this->scheduler->company, $data)),
'credits' => $export = (new CreditExport($this->scheduler->company, $data)),
'document' => $export = (new DocumentExport($this->scheduler->company, $data)),
'documents' => $export = (new DocumentExport($this->scheduler->company, $data)),
'expense' => $export = (new ExpenseExport($this->scheduler->company, $data)),
'expenses' => $export = (new ExpenseExport($this->scheduler->company, $data)),
'invoice' => $export = (new InvoiceExport($this->scheduler->company, $data)),
'invoices' => $export = (new InvoiceExport($this->scheduler->company, $data)),
'invoice_item' => $export = (new InvoiceItemExport($this->scheduler->company, $data)),
'invoice_items' => $export = (new InvoiceItemExport($this->scheduler->company, $data)),
'quote' => $export = (new QuoteExport($this->scheduler->company, $data)),
'quotes' => $export = (new QuoteExport($this->scheduler->company, $data)),
'quote_item' => $export = (new QuoteItemExport($this->scheduler->company, $data)),
'quote_items' => $export = (new QuoteItemExport($this->scheduler->company, $data)),
'recurring_invoice' => $export = (new RecurringInvoiceExport($this->scheduler->company, $data)),
'recurring_invoices' => $export = (new RecurringInvoiceExport($this->scheduler->company, $data)),
'payment' => $export = (new PaymentExport($this->scheduler->company, $data)),
'payments' => $export = (new PaymentExport($this->scheduler->company, $data)),
'product' => $export = (new ProductExport($this->scheduler->company, $data)),
'task' => $export = (new TaskExport($this->scheduler->company, $data)),
'products' => $export = (new ProductExport($this->scheduler->company, $data)),
'tasks' => $export = (new TaskExport($this->scheduler->company, $data)),
default => $export = false,
};

View File

@ -717,7 +717,7 @@ class TemplateService
return collect($payment->refund_meta)
->map(function ($refund) use ($payment) {
$date = \Carbon\Carbon::parse($refund['date'])->addSeconds($payment->client->timezone_offset());
$date = \Carbon\Carbon::parse($refund['date'] ?? $payment->date)->addSeconds($payment->client->timezone_offset());
$date = $this->translateDate($date, $payment->client->date_format(), $payment->client->locale());
$entity = ctrans('texts.invoice');
@ -1032,6 +1032,8 @@ class TemplateService
'payment_balance' => $purchase_order->client->payment_balance,
'credit_balance' => $purchase_order->client->credit_balance,
'vat_number' => $purchase_order->client->vat_number ?? '',
'address' => $purchase_order->client->present()->address(),
'shipping_address' => $purchase_order->client->present()->shipping_address(),
] : [],
'status_id' => (string)($purchase_order->status_id ?: 1),
'status' => PurchaseOrder::stringStatus($purchase_order->status_id ?? 1),

View File

@ -132,6 +132,8 @@ class CreditTransformer extends EntityTransformer
'paid_to_date' => (float) $credit->paid_to_date,
'subscription_id' => $this->encodePrimaryKey($credit->subscription_id),
'invoice_id' => $credit->invoice_id ? $this->encodePrimaryKey($credit->invoice_id) : '',
'tax_info' => $credit->tax_data ?: new \stdClass(),
];
}
}

View File

@ -52,6 +52,7 @@ class DocumentTransformer extends EntityTransformer
'created_at' => (int) $document->created_at,
'is_deleted' => (bool) false,
'is_public' => (bool) $document->is_public,
'link' => (string) $document->link(),
];
}
}

View File

@ -49,6 +49,12 @@ class ProjectTransformer extends EntityTransformer
public function includeClient(Project $project): \League\Fractal\Resource\Item
{
if (!$project->client) {
nlog("Project {$project->hashed_id} does not have a client attached - this project is in a bad state");
return null;
}
$transformer = new ClientTransformer($this->serializer);
return $this->includeItem($project->client, $transformer, Client::class);

View File

@ -149,6 +149,7 @@ class PurchaseOrderTransformer extends EntityTransformer
'subscription_id' => $this->encodePrimaryKey($purchase_order->subscription_id),
'expense_id' => $this->encodePrimaryKey($purchase_order->expense_id),
'currency_id' => $purchase_order->currency_id ? (string) $purchase_order->currency_id : '',
'tax_info' => $purchase_order->tax_data ?: new \stdClass(),
];
}
}

View File

@ -148,7 +148,7 @@ class QuoteTransformer extends EntityTransformer
'paid_to_date' => (float) $quote->paid_to_date,
'project_id' => $this->encodePrimaryKey($quote->project_id),
'subscription_id' => $this->encodePrimaryKey($quote->subscription_id),
'tax_info' => $quote->tax_data ?: new \stdClass(),
];
}
}

View File

@ -397,6 +397,7 @@ class HtmlEngine
$data['$credit.date'] = ['value' => $this->translateDate($this->entity->date, $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.credit_date')];
$data['$balance'] = ['value' => Number::formatMoney($this->getBalance(), $this->client) ?: ' ', 'label' => ctrans('texts.balance')];
$data['$credit.balance'] = ['value' => Number::formatMoney($this->entity_calc->getBalance(), $this->client) ?: ' ', 'label' => ctrans('texts.credit_balance')];
$data['$client.credit_balance'] = &$data['$credit.balance'];
$data['$invoice.balance'] = &$data['$balance'];
$data['$taxes'] = ['value' => Number::formatMoney($this->entity_calc->getItemTotalTaxes(), $this->client) ?: ' ', 'label' => ctrans('texts.taxes')];
@ -621,6 +622,33 @@ class HtmlEngine
$data['$task.task3'] = ['value' => '', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'task3')];
$data['$task.task4'] = ['value' => '', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'task4')];
if($this->entity->vendor) {
$data['$vendor_name'] = ['value' => $this->entity->vendor->present()->name() ?: '&nbsp;', 'label' => ctrans('texts.vendor_name')];
$data['$vendor.name'] = &$data['$vendor_name'];
$data['$vendor'] = &$data['$vendor_name'];
$data['$vendor.address1'] = ['value' => $this->entity->vendor->address1 ?: '&nbsp;', 'label' => ctrans('texts.address1')];
$data['$vendor.address2'] = ['value' => $this->entity->vendor->address2 ?: '&nbsp;', 'label' => ctrans('texts.address2')];
$data['$vendor.id_number'] = ['value' => $this->entity->vendor->id_number ?: '&nbsp;', 'label' => ctrans('texts.id_number')];
$data['$vendor.number'] = ['value' => $this->entity->vendor->number ?: '&nbsp;', 'label' => ctrans('texts.number')];
$data['$vendor.vat_number'] = ['value' => $this->entity->vendor->vat_number ?: '&nbsp;', 'label' => ctrans('texts.vat_number')];
$data['$vendor.website'] = ['value' => $this->entity->vendor->present()->website() ?: '&nbsp;', 'label' => ctrans('texts.website')];
$data['$vendor.phone'] = ['value' => $this->entity->vendor->present()->phone() ?: '&nbsp;', 'label' => ctrans('texts.phone')];
$data['$vendor.country'] = ['value' => isset($this->entity->vendor->country->name) ? ctrans('texts.country_' . $this->entity->vendor->country->name) : '', 'label' => ctrans('texts.country')];
$data['$vendor.country_2'] = ['value' => isset($this->entity->vendor->country) ? $this->entity->vendor->country->iso_3166_2 : '', 'label' => ctrans('texts.country')];
$data['$vendor_address'] = ['value' => $this->entity->vendor->present()->address() ?: '&nbsp;', 'label' => ctrans('texts.address')];
$data['$vendor.address'] = &$data['$vendor_address'];
$data['$vendor.postal_code'] = ['value' => $this->entity->vendor->postal_code ?: '&nbsp;', 'label' => ctrans('texts.postal_code')];
$data['$vendor.public_notes'] = ['value' => $this->entity->vendor->public_notes ?: '&nbsp;', 'label' => ctrans('texts.notes')];
$data['$vendor.city'] = ['value' => $this->entity->vendor->city ?: '&nbsp;', 'label' => ctrans('texts.city')];
$data['$vendor.state'] = ['value' => $this->entity->vendor->state ?: '&nbsp;', 'label' => ctrans('texts.state')];
$data['$vendor.city_state_postal'] = ['value' => $this->entity->vendor->present()->cityStateZip($this->entity->vendor->city, $this->entity->vendor->state, $this->entity->vendor->postal_code, false) ?: '&nbsp;', 'label' => ctrans('texts.city_state_postal')];
$data['$vendor.postal_city_state'] = ['value' => $this->entity->vendor->present()->cityStateZip($this->entity->vendor->city, $this->entity->vendor->state, $this->entity->vendor->postal_code, true) ?: '&nbsp;', 'label' => ctrans('texts.postal_city_state')];
$data['$vendor.postal_city'] = ['value' => $this->entity->vendor->present()->cityStateZip($this->entity->vendor->city, null, $this->entity->vendor->postal_code, true) ?: '&nbsp;', 'label' => ctrans('texts.postal_city')];
}
if ($this->settings->signature_on_pdf) {
$data['$contact.signature'] = ['value' => $this->invitation->signature_base64, 'label' => ctrans('texts.signature')];
$data['$contact.signature_date'] = ['value' => $this->translateDate($this->invitation->signature_date, $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.date')];

View File

@ -86,15 +86,9 @@ class Number
return rtrim(rtrim(number_format($value, $precision, $decimal, $thousand), '0'), $decimal);
}
/**
* Formats a given value based on the clients currency
* BACK to a float.
*
* @param string $value The formatted number to be converted back to float
* @return float The formatted value
*/
public static function parseFloat($value)
{
if(!$value)
return 0;
@ -104,44 +98,100 @@ class Number
$decimal = strpos($value, '.');
$comma = strpos($value, ',');
if(!$comma) //no comma must be a decimal number already
if($comma === false) //no comma must be a decimal number already
return (float) $value;
if($decimal < $comma){ //decimal before a comma = euro
$value = str_replace(['.',','], ['','.'], $value);
// $value = str_replace(',', '.', $value);
return (float) $value;
}
//comma first = traditional thousan separator
//comma first = traditional thousand separator
$value = str_replace(',', '', $value);
return (float)$value;
// if(!$value)
// return 0;
// $multiplier = false;
// if(substr($value, 0,1) == '-')
// $multiplier = -1;
// $s = str_replace(',', '.', $value);
// $s = preg_replace("/[^0-9\.]/", '', $s);
// if ($s < 1) {
// return (float) $s;
// }
// $s = str_replace('.', '', substr($s, 0, -3)).substr($s, -3);
// if($multiplier)
// $s = floatval($s)*-1;
// return (float) $s;
}
/**
* Formats a given value based on the clients currency
* BACK to a float.
*
* @param string $value The formatted number to be converted back to float
* @return float The formatted value
*/
public static function parseFloatXX($value)
{
if(!$value)
return 0;
$multiplier = false;
if(substr($value, 0,1) == '-')
$multiplier = -1;
$s = str_replace(',', '.', $value);
$s = preg_replace("/[^0-9\.]/", '', $s);
if ($s < 1) {
return (float) $s;
}
$s = str_replace('.', '', substr($s, 0, -3)).substr($s, -3);
if($multiplier)
$s = floatval($s)*-1;
return (float) $s;
}
//next iteration of float parsing
public static function parseFloat2($value)
{
if(!$value) {
return 0;
}
//remove everything except for numbers, decimals, commas and hyphens
$value = preg_replace('/[^0-9.,-]+/', '', $value);
$decimal = strpos($value, '.');
$comma = strpos($value, ',');
//check the 3rd last character
if(!in_array(substr($value, -3, 1), [".", ","])) {
if($comma && (substr($value, -3, 1) != ".")) {
$value .= ".00";
} elseif($decimal && (substr($value, -3, 1) != ",")) {
$value .= ",00";
}
}
$decimal = strpos($value, '.');
$comma = strpos($value, ',');
if($comma === false) { //no comma must be a decimal number already
return (float) $value;
}
if($decimal < $comma) { //decimal before a comma = euro
$value = str_replace(['.',','], ['','.'], $value);
return (float) $value;
}
//comma first = traditional thousand separator
$value = str_replace(',', '', $value);
return (float)$value;
}
public static function parseStringFloat($value)
{

View File

@ -84,6 +84,7 @@ class SystemHealth
'trailing_slash' => (bool) self::checkUrlState(),
'file_permissions' => (string) self::checkFileSystem(),
'exchange_rate_api_not_configured' => (bool)self::checkCurrencySanity(),
'api_version' => (string) config('ninja.app_version'),
];
}

833
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -17,8 +17,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => env('APP_VERSION', '5.8.30'),
'app_tag' => env('APP_TAG', '5.8.30'),
'app_version' => env('APP_VERSION', '5.8.37'),
'app_tag' => env('APP_TAG', '5.8.37'),
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false),

View File

@ -35,7 +35,10 @@ return [
],
'postmark-outlook' => [
'token' => env('POSTMARK_OUTLOOK_SECRET','')
'token' => env('POSTMARK_OUTLOOK_SECRET',''),
'from' => [
'address' => env('POSTMARK_OUTLOOK_FROM_ADDRESS', '')
],
],
'microsoft' => [

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('quotes', function (Blueprint $table) {
$table->mediumText('tax_data')->nullable(); //json object
});
Schema::table('credits', function (Blueprint $table) {
$table->mediumText('tax_data')->nullable(); //json object
});
Schema::table('purchase_orders', function (Blueprint $table) {
$table->mediumText('tax_data')->nullable(); //json object
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
}
};

View File

@ -0,0 +1,45 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('invoices', function (Blueprint $table) {
$table->decimal('discount', 20, 6)->default(0)->change();
});
Schema::table('credits', function (Blueprint $table) {
$table->decimal('discount', 20, 6)->default(0)->change();
});
Schema::table('quotes', function (Blueprint $table) {
$table->decimal('discount', 20, 6)->default(0)->change();
});
Schema::table('purchase_orders', function (Blueprint $table) {
$table->decimal('discount', 20, 6)->default(0)->change();
});
Schema::table('recurring_invoices', function (Blueprint $table) {
$table->decimal('discount', 20, 6)->default(0)->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};

View File

@ -453,7 +453,7 @@ $lang = array(
'edit_token' => 'تحرير الرمز',
'delete_token' => 'حذف الرمز المميز',
'token' => 'رمز',
'add_gateway' => 'إضافة بوابة',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'حذف البوابة',
'edit_gateway' => 'تحرير البوابة',
'updated_gateway' => 'تم تحديث البوابة بنجاح',
@ -499,8 +499,8 @@ $lang = array(
'auto_wrap' => 'التفاف خط السيارات',
'duplicate_post' => 'تحذير: الصفحة السابقة قدمت مرتين. تم تجاهل التقديم الثاني.',
'view_documentation' => 'عرض التوثيق',
'app_title' => 'Free Online Invoicing',
'app_description' => 'Invoice Ninja is a free, open-code solution for invoicing and billing customers. With Invoice Ninja, you can easily build and send beautiful invoices from any device that has access to the web. Your clients can print your invoices, download them as pdf files, and even pay you online from within the system.',
'app_title' => 'فواتير مجانية عبر الإنترنت',
'app_description' => 'يعد Invoice Ninja حلاً مجانيًا مفتوح الرمز لإعداد الفواتير وإعداد الفواتير للعملاء. باستخدام Invoice Ninja، يمكنك بسهولة إنشاء وإرسال فواتير جميلة من أي جهاز لديه إمكانية الوصول إلى الويب. يمكن لعملائك طباعة فواتيرك، وتنزيلها كملفات pdf، وحتى الدفع لك عبر الإنترنت من داخل النظام.',
'rows' => 'صفوف',
'www' => 'www',
'logo' => 'شعار',
@ -686,9 +686,9 @@ $lang = array(
'disable' => 'إبطال',
'invoice_quote_number' => 'أرقام الفاتورة والاقتباس',
'invoice_charges' => 'رسوم الفاتورة الإضافية',
'notification_invoice_bounced' => 'We were unable to deliver Invoice :invoice to :contact. <br><br> :error',
'notification_invoice_bounced' => 'لم نتمكن من تسليم الفاتورة :invoice إلى :contact .<br><br> :error',
'notification_invoice_bounced_subject' => 'تعذر تسليم الفاتورة :invoice',
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact. <br><br> :error',
'notification_quote_bounced' => 'لم نتمكن من تسليم عرض الأسعار :invoice إلى :contact .<br><br> :error',
'notification_quote_bounced_subject' => 'غير قادر على تسليم اقتباس :invoice',
'custom_invoice_link' => 'رابط الفاتورة المخصصة',
'total_invoiced' => 'إجمالي الفاتورة',
@ -2991,7 +2991,7 @@ $lang = array(
'hosted_login' => 'مستضاف تسجيل الدخول',
'selfhost_login' => 'تسجيل الدخول إلى Selfhost',
'google_login' => 'جوجل تسجيل الدخول',
'thanks_for_patience' => 'Thank for your patience while we work to implement these features.<br><br>We hope to have them completed in the next few months.<br><br>Until then we\'ll continue to support the',
'thanks_for_patience' => 'نشكرك على سعة صدرك بينما نعمل على تنفيذ هذه الميزات.<br><br> ونأمل أن يتم الانتهاء منها في الأشهر القليلة المقبلة.<br><br> وحتى ذلك الحين سنواصل دعمنا',
'legacy_mobile_app' => 'تطبيق جوال قديم',
'today' => 'اليوم',
'current' => 'حاضِر',
@ -3849,7 +3849,7 @@ $lang = array(
'cancellation_pending' => 'الإلغاء معلق ، سنكون على اتصال!',
'list_of_payments' => 'قائمة المدفوعات',
'payment_details' => 'تفاصيل الدفع',
'list_of_payment_invoices' => 'Associate invoices',
'list_of_payment_invoices' => 'الفواتير المرتبطة',
'list_of_payment_methods' => 'قائمة طرق الدفع',
'payment_method_details' => 'تفاصيل طريقة الدفع',
'permanently_remove_payment_method' => 'قم بإزالة طريقة الدفع هذه بشكل دائم.',
@ -4906,7 +4906,7 @@ $lang = array(
'no_assigned_tasks' => 'لا توجد مهام قابلة للفوترة لهذا المشروع',
'authorization_failure' => 'أذونات غير كافية لتنفيذ هذا الإجراء',
'authorization_sms_failure' => 'يرجى التحقق من حسابك لإرسال رسائل البريد الإلكتروني.',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'white_label_body' => 'شكرًا لك على شراء ترخيص العلامة البيضاء.<br><br> مفتاح الترخيص الخاص بك هو:<br><br> :license_key<br><br> يمكنك إدارة الترخيص الخاص بك هنا: https://invoiceninja.invoicing.co/client/login',
'payment_type_Klarna' => 'كلارنا',
'payment_type_Interac E Transfer' => 'Interac E Transfer',
'xinvoice_payable' => 'مستحق الدفع paydate: صافي أيام الدفع payeddue: تاريخ الدفع',
@ -5071,7 +5071,7 @@ $lang = array(
'region' => 'منطقة',
'county' => 'مقاطعة',
'tax_details' => 'التفاصيل الضريبية',
'activity_10_online' => ':contact made payment :payment for invoice :invoice for :client',
'activity_10_online' => ':contact تم الدفع :payment للفاتورة :invoice لـ :client',
'activity_10_manual' => ':user الدفعة المدخلة :payment للفاتورة :invoice لـ :client',
'default_payment_type' => 'نوع الدفع الافتراضي',
'number_precision' => 'دقة العدد',
@ -5101,7 +5101,7 @@ $lang = array(
'set_private' => 'تعيين خاص',
'individual' => 'فردي',
'business' => 'عمل',
'partnership' => 'Partnership',
'partnership' => 'شراكة',
'trust' => 'يثق',
'charity' => 'صدقة',
'government' => 'حكومة',
@ -5182,42 +5182,59 @@ $lang = array(
'nordigen_handler_error_heading_requisition_invalid_status' => 'غير جاهز',
'nordigen_handler_error_contents_requisition_invalid_status' => 'لقد اتصلت بهذا الموقع مبكرًا جدًا. الرجاء إنهاء الترخيص وتحديث هذه الصفحة. اتصل بالدعم للحصول على المساعدة، إذا استمرت هذه المشكلة.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'لم يتم تحديد أي حسابات',
'nordigen_handler_error_contents_requisition_no_accounts' => 'لم تقم الخدمة بإرجاع أي حسابات صالحة. فكر في إعادة تشغيل التدفق.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'إعادة تشغيل التدفق.',
'nordigen_handler_return' => 'العودة إلى التطبيق.',
'lang_Lao' => 'Lao',
'currency_lao_kip' => 'Lao kip',
'yodlee_regions' => 'Regions: USA, UK, Australia & India',
'nordigen_regions' => 'Regions: Europe & UK',
'select_provider' => 'Select Provider',
'nordigen_requisition_subject' => 'Requisition expired, please reauthenticate.',
'nordigen_requisition_body' => 'Access to bank account feeds has expired as set in End User Agreement. <br><br>Please log into Invoice Ninja and re-authenticate with your banks to continue receiving transactions.',
'participant' => 'Participant',
'participant_name' => 'Participant name',
'client_unsubscribed' => 'Client unsubscribed from emails.',
'client_unsubscribed_help' => 'Client :client has unsubscribed from your e-mails. The client needs to consent to receive future emails from you.',
'resubscribe' => 'Resubscribe',
'subscribe' => 'Subscribe',
'subscribe_help' => 'You are currently subscribed and will continue to receive email communications.',
'unsubscribe_help' => 'You are currently not subscribed, and therefore, will not receive emails at this time.',
'notification_purchase_order_bounced' => 'We were unable to deliver Purchase Order :invoice to :contact. <br><br> :error',
'notification_purchase_order_bounced_subject' => 'Unable to deliver Purchase Order :invoice',
'show_pdfhtml_on_mobile' => 'Display HTML version of entity when viewing on mobile',
'show_pdfhtml_on_mobile_help' => 'For improved visualization, displays a HTML version of the invoice/quote when viewing on mobile.',
'please_select_an_invoice_or_credit' => 'Please select an invoice or credit',
'mobile_version' => 'Mobile Version',
'venmo' => 'Venmo',
'my_bank' => 'MyBank',
'pay_later' => 'Pay Later',
'local_domain' => 'Local Domain',
'verify_peer' => 'Verify Peer',
'nordigen_help' => 'Note: connecting an account requires a GoCardless/Nordigen API key',
'ar_detailed' => 'Accounts Receivable Detailed',
'ar_summary' => 'Accounts Receivable Summary',
'client_sales' => 'Client Sales',
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'lang_Lao' => 'لاو',
'currency_lao_kip' => 'لاو كيب',
'yodlee_regions' => 'المناطق: الولايات المتحدة الأمريكية والمملكة المتحدة وأستراليا والهند',
'nordigen_regions' => 'المناطق: أوروبا والمملكة المتحدة',
'select_provider' => 'حدد الموفر',
'nordigen_requisition_subject' => 'انتهت صلاحية الطلب، يرجى إعادة المصادقة.',
'nordigen_requisition_body' => 'انتهت صلاحية الوصول إلى خلاصات حساب البنك كما هو محدد في اتفاقية المستخدم النهائي.<br><br> يرجى تسجيل الدخول إلى Invoice Ninja وإعادة المصادقة مع البنوك التي تتعامل معها لمواصلة تلقي المعاملات.',
'participant' => 'مشارك',
'participant_name' => 'اسم المشارك',
'client_unsubscribed' => 'تم إلغاء اشتراك العميل من رسائل البريد الإلكتروني.',
'client_unsubscribed_help' => 'لقد قام العميل :client بإلغاء اشتراكه في رسائل البريد الإلكتروني الخاصة بك. يحتاج العميل إلى الموافقة على تلقي رسائل البريد الإلكتروني المستقبلية منك.',
'resubscribe' => 'إعادة الاشتراك',
'subscribe' => 'يشترك',
'subscribe_help' => 'أنت مشترك حاليًا وستستمر في تلقي اتصالات البريد الإلكتروني.',
'unsubscribe_help' => 'أنت غير مشترك حاليًا، وبالتالي لن تتلقى رسائل بريد إلكتروني في الوقت الحالي.',
'notification_purchase_order_bounced' => 'لم نتمكن من تسليم طلب الشراء :invoice إلى :contact .<br><br> :error',
'notification_purchase_order_bounced_subject' => 'غير قادر على تسليم أمر الشراء :invoice',
'show_pdfhtml_on_mobile' => 'عرض إصدار HTML للكيان عند العرض على الهاتف المحمول',
'show_pdfhtml_on_mobile_help' => 'لتحسين التصور، يتم عرض نسخة HTML من الفاتورة/عرض الأسعار عند عرضها على الهاتف المحمول.',
'please_select_an_invoice_or_credit' => 'الرجاء تحديد فاتورة أو رصيد',
'mobile_version' => 'اصدار المحمول',
'venmo' => 'فينمو',
'my_bank' => 'بنكي',
'pay_later' => 'ادفع لاحقا',
'local_domain' => 'المجال المحلي',
'verify_peer' => 'التحقق من النظير',
'nordigen_help' => 'ملاحظة: يتطلب ربط حساب مفتاح GoCardless/Nordigen API',
'ar_detailed' => 'حسابات القبض مفصلة',
'ar_summary' => 'ملخص حسابات القبض',
'client_sales' => 'مبيعات العملاء',
'user_sales' => 'مبيعات المستخدم',
'iframe_url' => 'عنوان URL لإطار iFrame',
'user_unsubscribed' => 'تم إلغاء اشتراك المستخدم من رسائل البريد الإلكتروني :link',
'use_available_payments' => 'استخدم المدفوعات المتاحة',
'test_email_sent' => 'تم إرسال البريد الإلكتروني بنجاح',
'gateway_type' => 'نوع البوابة',
'save_template_body' => 'هل ترغب في حفظ تعيين الاستيراد هذا كقالب لاستخدامه في المستقبل؟',
'save_as_template' => 'حفظ تعيين القالب',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'يضبط <b>تاريخ استحقاق الفاتورة</b> الافتراضي',
'payment_type_help' => 'يعيّن <b>نوع الدفع اليدوي</b> الافتراضي.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);
return $lang;

View File

@ -461,7 +461,7 @@ $lang = array(
'edit_token' => 'Редакция на токън',
'delete_token' => 'Изтриване на токън',
'token' => 'Токън',
'add_gateway' => 'Добавяне на Gateway',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Изтриване на Gateway',
'edit_gateway' => 'Редакция на Gateway',
'updated_gateway' => 'Успешно актуализиран Gateway',
@ -3869,7 +3869,7 @@ $lang = array(
'cancellation_pending' => 'Cancellation pending, we\'ll be in touch!',
'list_of_payments' => 'List of payments',
'payment_details' => 'Details of the payment',
'list_of_payment_invoices' => 'List of invoices affected by the payment',
'list_of_payment_invoices' => 'Associate invoices',
'list_of_payment_methods' => 'List of payment methods',
'payment_method_details' => 'Details of payment method',
'permanently_remove_payment_method' => 'Permanently remove this payment method.',
@ -4926,7 +4926,7 @@ $lang = array(
'no_assigned_tasks' => 'No billable tasks for this project',
'authorization_failure' => 'Insufficient permissions to perform this action',
'authorization_sms_failure' => 'Please verify your account to send emails.',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Interac E Transfer',
'xinvoice_payable' => 'Payable within :payeddue days net until :paydate',
@ -5121,7 +5121,7 @@ $lang = array(
'set_private' => 'Set private',
'individual' => 'Individual',
'business' => 'Business',
'partnership' => 'partnership',
'partnership' => 'Partnership',
'trust' => 'Trust',
'charity' => 'Charity',
'government' => 'Government',
@ -5202,7 +5202,7 @@ $lang = array(
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
'lang_Lao' => 'Lao',
@ -5222,6 +5222,38 @@ $lang = array(
'unsubscribe_help' => 'You are currently not subscribed, and therefore, will not receive emails at this time.',
'notification_purchase_order_bounced' => 'We were unable to deliver Purchase Order :invoice to :contact. <br><br> :error',
'notification_purchase_order_bounced_subject' => 'Unable to deliver Purchase Order :invoice',
'show_pdfhtml_on_mobile' => 'Display HTML version of entity when viewing on mobile',
'show_pdfhtml_on_mobile_help' => 'For improved visualization, displays a HTML version of the invoice/quote when viewing on mobile.',
'please_select_an_invoice_or_credit' => 'Please select an invoice or credit',
'mobile_version' => 'Mobile Version',
'venmo' => 'Venmo',
'my_bank' => 'MyBank',
'pay_later' => 'Pay Later',
'local_domain' => 'Local Domain',
'verify_peer' => 'Verify Peer',
'nordigen_help' => 'Note: connecting an account requires a GoCardless/Nordigen API key',
'ar_detailed' => 'Accounts Receivable Detailed',
'ar_summary' => 'Accounts Receivable Summary',
'client_sales' => 'Client Sales',
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'use_available_payments' => 'Use Available Payments',
'test_email_sent' => 'Successfully sent email',
'gateway_type' => 'Gateway Type',
'save_template_body' => 'Would you like to save this import mapping as a template for future use?',
'save_as_template' => 'Save Template Mapping',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Задава <b>падеж на фактурата</b> по подразбиране',
'payment_type_help' => 'Задава <b>тип за ръчно плащане</b> по подразбиране.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Edit Token',
'delete_token' => 'Delete Token',
'token' => 'Token',
'add_gateway' => 'Add Gateway',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Delete Gateway',
'edit_gateway' => 'Edit Gateway',
'updated_gateway' => 'Successfully updated gateway',
@ -5201,7 +5201,7 @@ $lang = array(
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
'lang_Lao' => 'Lao',
@ -5237,6 +5237,23 @@ $lang = array(
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'use_available_payments' => 'Use Available Payments',
'test_email_sent' => 'Successfully sent email',
'gateway_type' => 'Gateway Type',
'save_template_body' => 'Would you like to save this import mapping as a template for future use?',
'save_as_template' => 'Save Template Mapping',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Sets the default <b>invoice due date</b>',
'payment_type_help' => 'Sets the default <b>manual payment type</b>.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);
return $lang;

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Editovat token',
'delete_token' => 'Smazat Token',
'token' => 'Token',
'add_gateway' => 'Přidat platební bránu',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Smazat platební bránu',
'edit_gateway' => 'Editovat bránu',
'updated_gateway' => 'Brána úspěšně změněna',
@ -5202,7 +5202,7 @@ $lang = array(
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
'lang_Lao' => 'Lao',
@ -5238,6 +5238,23 @@ $lang = array(
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'use_available_payments' => 'Use Available Payments',
'test_email_sent' => 'Successfully sent email',
'gateway_type' => 'Gateway Type',
'save_template_body' => 'Would you like to save this import mapping as a template for future use?',
'save_as_template' => 'Save Template Mapping',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Nastaví jako výchozí <b>datum splatnosti faktury</b>',
'payment_type_help' => 'Sets the default <b>manual payment type</b>.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);
return $lang;

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Redigér token',
'delete_token' => 'Slet token',
'token' => 'Token',
'add_gateway' => 'Tilføj gateway',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Slet gateway',
'edit_gateway' => 'Redigér gateway',
'updated_gateway' => 'Gateway blev opdateret',
@ -5200,7 +5200,7 @@ $lang = array(
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
'lang_Lao' => 'Lao',
@ -5236,6 +5236,23 @@ $lang = array(
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'use_available_payments' => 'Use Available Payments',
'test_email_sent' => 'Successfully sent email',
'gateway_type' => 'Gateway Type',
'save_template_body' => 'Would you like to save this import mapping as a template for future use?',
'save_as_template' => 'Save Template Mapping',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Sætter standard <b>faktura forfalds dato</b>',
'payment_type_help' => 'Indstiller den <b>manuelle Betaling</b> som standard.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);
return $lang;

View File

@ -461,7 +461,7 @@ $lang = array(
'edit_token' => 'Token bearbeiten',
'delete_token' => 'Token löschen',
'token' => 'Token',
'add_gateway' => 'Zahlungsanbieter hinzufügen',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Zahlungsanbieter löschen',
'edit_gateway' => 'Zahlungsanbieter bearbeiten',
'updated_gateway' => 'Zahlungsanbieter aktualisiert',
@ -507,8 +507,8 @@ $lang = array(
'auto_wrap' => 'Automatischer Zeilenumbruch',
'duplicate_post' => 'Achtung: Die vorherige Seite wurde zweimal übermittelt. Die zweite Übermittlung wurde ignoriert.',
'view_documentation' => 'Dokumentation anzeigen',
'app_title' => 'Free Online Invoicing',
'app_description' => 'Invoice Ninja is a free, open-code solution for invoicing and billing customers. With Invoice Ninja, you can easily build and send beautiful invoices from any device that has access to the web. Your clients can print your invoices, download them as pdf files, and even pay you online from within the system.',
'app_title' => 'Kostenlose Online-Rechnung',
'app_description' => 'Invoice Ninja ist eine kostenlose Open-Code-Lösung für die Rechnungsstellung und Abrechnung mit Kunden. Mit Invoice Ninja können Sie ganz einfach schöne Rechnungen erstellen und versenden, von jedem Gerät aus, das Zugriff auf das Internet hat. Ihre Kunden können Ihre Rechnungen ausdrucken, als PDF-Dateien herunterladen und sogar online über das System bezahlen.',
'rows' => 'Zeilen',
'www' => 'www',
'logo' => 'Logo',
@ -1902,7 +1902,7 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese
'require_quote_signature_help' => 'Erfordern Sie die Unterschrift des Kunden bei Angeboten.',
'i_agree' => 'Ich stimme den Bedingungen zu',
'sign_here' => 'Bitte unterschreiben Sie hier:',
'sign_here_ux_tip' => 'Use the mouse or your touchpad to trace your signature.',
'sign_here_ux_tip' => 'Verwenden Sie die Maus oder Ihr Touchpad, um Ihre Signatur nachzuzeichnen.',
'authorization' => 'Genehmigung',
'signed' => 'unterzeichnet',
@ -3011,7 +3011,7 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese
'hosted_login' => 'Hosted Login',
'selfhost_login' => 'Selfhost Login',
'google_login' => 'Google Login',
'thanks_for_patience' => 'Thank for your patience while we work to implement these features.<br><br>We hope to have them completed in the next few months.<br><br>Until then we\'ll continue to support the',
'thanks_for_patience' => 'Vielen Dank für Ihre Geduld, während wir an der Implementierung dieser Funktionen arbeiten.<br><br> Wir hoffen, sie in den nächsten Monaten fertigstellen zu können.<br><br> Bis dahin unterstützen wir weiterhin die',
'legacy_mobile_app' => 'legacy Mobile App',
'today' => 'Heute',
'current' => 'Aktuell',
@ -3329,7 +3329,7 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese
'credit_number_counter' => 'Gutschriftnummernzähler',
'reset_counter_date' => 'Zählerdatum zurücksetzen',
'counter_padding' => 'Zähler-Innenabstand',
'shared_invoice_quote_counter' => 'Share Invoice/Quote Counter',
'shared_invoice_quote_counter' => 'Share Invoice/ Angebot / Kostenvoranschlag Counter',
'default_tax_name_1' => 'Standard-Steuername 1',
'default_tax_rate_1' => 'Standard-Steuersatz 1',
'default_tax_name_2' => 'Standard-Steuername 2',
@ -3870,7 +3870,7 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting',
'cancellation_pending' => 'Kündigung in Bearbeitung! Wir melden uns bei Ihnen...',
'list_of_payments' => 'Liste der Zahlungen',
'payment_details' => 'Details zu der Zahlung',
'list_of_payment_invoices' => 'Associate invoices',
'list_of_payment_invoices' => 'Rechnungen zuordnen',
'list_of_payment_methods' => 'Liste der Zahlungsmethoden',
'payment_method_details' => 'Details zu der Zahlungsmethode',
'permanently_remove_payment_method' => 'Zahlungsmethode endgültig entfernen.',
@ -4219,7 +4219,7 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting',
'direct_debit' => 'Lastschriftverfahren',
'clone_to_expense' => 'Klonen zu Ausgabe',
'checkout' => 'Kasse',
'acss' => 'ACSS Debit',
'acss' => 'ACSS-Lastschrift',
'invalid_amount' => 'Ungültiger Betrag. Nur Zahlen/Dezimalwerte.',
'client_payment_failure_body' => 'Zahlung für Rechnung :invoice for amount :amount fehlgeschlagen.',
'browser_pay' => 'Google Pay, Apple Pay, Microsoft Pay',
@ -4927,7 +4927,7 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting',
'no_assigned_tasks' => 'Keine abzurechenden Aufgaben für diese Rechnung',
'authorization_failure' => 'Unzureichende Berechtigungen um diese Aktion auszuführen',
'authorization_sms_failure' => 'Bitte bestätigen Sie Ihr Konto um E-Mails zu versenden',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'white_label_body' => 'Vielen Dank, dass Sie eine White-Label-Lizenz erworben haben.<br><br> Ihr Lizenzschlüssel lautet:<br><br> :license_key<br><br> Sie können Ihre Lizenz hier verwalten: https://invoiceninja.invoicing.co/ Kunde /login',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Interac E-Übertragung',
'xinvoice_payable' => 'Zahlbar innerhalb von :payeddue Tagen netto bis :paydate',
@ -5092,7 +5092,7 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting',
'region' => 'Region',
'county' => 'Landkreis',
'tax_details' => 'Steuerdetails',
'activity_10_online' => ':contact made payment :payment for invoice :invoice for :client',
'activity_10_online' => ':contact hat die Zahlung :payment für die Rechnung :invoice für :client geleistet',
'activity_10_manual' => ':user hat die Zahlung :payment für die Rechnung :invoice des Kunden :client eingegeben',
'default_payment_type' => 'Standard Zahlungsart',
'number_precision' => 'Genauigkeit der Nummern',
@ -5150,7 +5150,7 @@ Leistungsempfängers',
'payment_receipt' => 'Zahlungsbeleg #:number',
'load_template_description' => 'Das Template wird auf Folgendes angewendet:',
'run_template' => 'Template anwenden',
'statement_design' => 'Statement Design',
'statement_design' => 'Statement-Design',
'delivery_note_design' => 'Lieferschein Design',
'payment_receipt_design' => 'Zahlungsbeleg Design',
'payment_refund_design' => 'Gutschrift Design',
@ -5159,88 +5159,105 @@ Leistungsempfängers',
'view_extension' => 'Erweiterung ansehen',
'reactivate_email' => 'E-Mail reaktivieren',
'email_reactivated' => 'Email erfolgreich reaktiviert',
'template_help' => 'Enable using the design as a template',
'template_help' => 'Aktivieren Sie die Verwendung des Designs als Vorlage',
'quarter' => 'Quartal',
'item_description' => 'Item Description',
'task_item' => 'Task Item',
'record_state' => 'Record State',
'save_files_to_this_folder' => 'Save files to this folder',
'downloads_folder' => 'Downloads Folder',
'total_invoiced_quotes' => 'Invoiced Quotes',
'total_invoice_paid_quotes' => 'Invoice Paid Quotes',
'downloads_folder_does_not_exist' => 'The downloads folder does not exist :value',
'user_logged_in_notification' => 'User Logged in Notification',
'user_logged_in_notification_help' => 'Send an email when logging in from a new location',
'payment_email_all_contacts' => 'Payment Email To All Contacts',
'payment_email_all_contacts_help' => 'Sends the payment email to all contacts when enabled',
'item_description' => 'Artikelbeschreibung',
'task_item' => 'Aufgabe',
'record_state' => 'Aufnahmestatus',
'save_files_to_this_folder' => 'Speichern Sie Dateien in diesem Ordner',
'downloads_folder' => 'Downloads-Ordner',
'total_invoiced_quotes' => 'Angebote auf Rechnung',
'total_invoice_paid_quotes' => 'Auf Rechnung bezahlte Angebote',
'downloads_folder_does_not_exist' => 'Der Download-Ordner existiert nicht :value',
'user_logged_in_notification' => 'Benachrichtigung über angemeldeten Benutzer',
'user_logged_in_notification_help' => 'Senden Sie eine E-Mail, wenn Sie sich von einem neuen Standort aus anmelden',
'payment_email_all_contacts' => 'Zahlungs-E-Mail an alle Kontakte',
'payment_email_all_contacts_help' => 'Sendet die Zahlungs-E-Mail an alle Kontakte, wenn diese Option aktiviert ist',
'add_line' => 'Zeile hinzufügen',
'activity_139' => 'Expense :expense notification sent to :contact',
'vendor_notification_subject' => 'Confirmation of payment :amount sent to :vendor',
'vendor_notification_body' => 'Payment processed for :amount dated :payment_date. <br>[Transaction Reference: :transaction_reference]',
'receipt' => 'Receipt',
'charges' => 'Charges',
'activity_139' => 'Ausgabe :expense Benachrichtigung an :contact gesendet',
'vendor_notification_subject' => 'Zahlungsbestätigung :amount gesendet an :vendor',
'vendor_notification_body' => 'Zahlung für :amount vom :payment _date verarbeitet.<br> [Transaktionsreferenz: :transaction_reference ]',
'receipt' => 'Quittung',
'charges' => 'Gebühren',
'email_report' => 'E-Mail-Bericht',
'payment_type_Pay Later' => 'Später bezahlen',
'payment_type_credit' => 'Payment Type Credit',
'payment_type_debit' => 'Payment Type Debit',
'payment_type_credit' => 'Zahlungsart Gutschrift',
'payment_type_debit' => 'Zahlungsart Lastschrift',
'send_emails_to' => 'Sende E-Mails an',
'primary_contact' => 'Primärkontakt',
'all_contacts' => 'Alle Kontakte',
'insert_below' => 'Darunter einfügen',
'nordigen_handler_subtitle' => 'Bank account authentication. Selecting your institution to complete the request with your account credentials.',
'nordigen_handler_subtitle' => 'Authentifizierung des Bankkontos. Wählen Sie Ihre Institution aus, um die Anfrage mit Ihren Kontoanmeldeinformationen abzuschließen.',
'nordigen_handler_error_heading_unknown' => 'Ein Fehler ist aufgetreten',
'nordigen_handler_error_contents_unknown' => 'Ein unbekannter Fehler ist aufgetreten. Grund:',
'nordigen_handler_error_heading_token_invalid' => 'Ungültiges Token',
'nordigen_handler_error_contents_token_invalid' => 'The provided token was invalid. Contact support for help, if this issue persists.',
'nordigen_handler_error_contents_token_invalid' => 'Das bereitgestellte Token war ungültig. Wenn das Problem weiterhin besteht, wenden Sie sich an den Support.',
'nordigen_handler_error_heading_account_config_invalid' => 'Fehlende Zugangsdaten',
'nordigen_handler_error_contents_account_config_invalid' => 'Invalid or missing credentials for Gocardless Bank Account Data. Contact support for help, if this issue persists.',
'nordigen_handler_error_contents_account_config_invalid' => 'Ungültige oder fehlende Zugangsdaten für Gocardless Bankverbindung . Wenn das Problem weiterhin besteht, wenden Sie sich an den Support.',
'nordigen_handler_error_heading_not_available' => 'Nicht verfügbar',
'nordigen_handler_error_contents_not_available' => 'Funktion ist nur im Enterprise-Tarif verfügbar.',
'nordigen_handler_error_heading_institution_invalid' => 'Invalid Institution',
'nordigen_handler_error_contents_institution_invalid' => 'The provided institution-id is invalid or no longer valid.',
'nordigen_handler_error_heading_institution_invalid' => 'Ungültige Institution',
'nordigen_handler_error_contents_institution_invalid' => 'Die angegebene Institutions-ID ist ungültig oder nicht mehr gültig.',
'nordigen_handler_error_heading_ref_invalid' => 'Ungültige Referenz',
'nordigen_handler_error_contents_ref_invalid' => 'GoCardless did not provide a valid reference. Please run flow again and contact support, if this issue persists.',
'nordigen_handler_error_heading_not_found' => 'Invalid Requisition',
'nordigen_handler_error_contents_not_found' => 'GoCardless did not provide a valid reference. Please run flow again and contact support, if this issue persists.',
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
'lang_Lao' => 'Lao',
'currency_lao_kip' => 'Lao kip',
'yodlee_regions' => 'Regions: USA, UK, Australia & India',
'nordigen_regions' => 'Regions: Europe & UK',
'select_provider' => 'Select Provider',
'nordigen_requisition_subject' => 'Requisition expired, please reauthenticate.',
'nordigen_requisition_body' => 'Access to bank account feeds has expired as set in End User Agreement. <br><br>Please log into Invoice Ninja and re-authenticate with your banks to continue receiving transactions.',
'participant' => 'Participant',
'participant_name' => 'Participant name',
'client_unsubscribed' => 'Client unsubscribed from emails.',
'client_unsubscribed_help' => 'Client :client has unsubscribed from your e-mails. The client needs to consent to receive future emails from you.',
'resubscribe' => 'Resubscribe',
'subscribe' => 'Subscribe',
'subscribe_help' => 'You are currently subscribed and will continue to receive email communications.',
'unsubscribe_help' => 'You are currently not subscribed, and therefore, will not receive emails at this time.',
'notification_purchase_order_bounced' => 'We were unable to deliver Purchase Order :invoice to :contact. <br><br> :error',
'notification_purchase_order_bounced_subject' => 'Unable to deliver Purchase Order :invoice',
'show_pdfhtml_on_mobile' => 'Display HTML version of entity when viewing on mobile',
'show_pdfhtml_on_mobile_help' => 'For improved visualization, displays a HTML version of the invoice/quote when viewing on mobile.',
'please_select_an_invoice_or_credit' => 'Please select an invoice or credit',
'nordigen_handler_error_contents_ref_invalid' => 'GoCardless hat keine gültige Referenz angegeben. Bitte führen Sie Flow erneut aus und wenden Sie sich an den Support, wenn das Problem weiterhin besteht.',
'nordigen_handler_error_heading_not_found' => 'Ungültige Anforderung',
'nordigen_handler_error_contents_not_found' => 'GoCardless hat keine gültige Referenz angegeben. Bitte führen Sie Flow erneut aus und wenden Sie sich an den Support, wenn das Problem weiterhin besteht.',
'nordigen_handler_error_heading_requisition_invalid_status' => 'Nicht bereit',
'nordigen_handler_error_contents_requisition_invalid_status' => 'Sie haben diese Seite zu früh aufgerufen. Bitte schließen Sie die Autorisierung ab und aktualisieren Sie diese Seite. Wenn das Problem weiterhin besteht, wenden Sie sich an den Support.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'Keine Konten ausgewählt',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Fluss neu starten.',
'nordigen_handler_return' => 'Zurück zur Bewerbung.',
'lang_Lao' => 'Laotisch',
'currency_lao_kip' => 'Laotischer Kip',
'yodlee_regions' => 'Regionen: USA, Großbritannien, Australien und Indien',
'nordigen_regions' => 'Regionen: Europa und Großbritannien',
'select_provider' => 'Wählen Sie Anbieter aus',
'nordigen_requisition_subject' => 'Die Anforderung ist abgelaufen. Bitte authentifizieren Sie sich erneut.',
'nordigen_requisition_body' => 'Der Zugriff auf Bankkonto-Feeds ist gemäß der Endbenutzervereinbarung abgelaufen.<br><br> Bitte melden Sie sich bei Invoice Ninja an und authentifizieren Sie sich erneut bei Ihren Banken, um weiterhin Transaktionen zu erhalten.',
'participant' => 'Teilnehmer',
'participant_name' => 'Teilnehmername',
'client_unsubscribed' => 'Kunde hat sich von E-Mails abgemeldet.',
'client_unsubscribed_help' => 'Kunde :client hat sich von Ihren E-Mails abgemeldet. Der Kunde muss zustimmen, künftige E-Mails von Ihnen zu erhalten.',
'resubscribe' => 'Abonnieren Sie erneut',
'subscribe' => 'Abonnieren',
'subscribe_help' => 'Sie sind derzeit angemeldet und erhalten weiterhin E-Mail-Mitteilungen.',
'unsubscribe_help' => 'Sie sind derzeit nicht abonniert und erhalten daher derzeit keine E-Mails.',
'notification_purchase_order_bounced' => 'Wir konnten die Bestellung :invoice nicht an :contact liefern.<br><br> :error',
'notification_purchase_order_bounced_subject' => 'Bestellung :invoice kann nicht geliefert werden',
'show_pdfhtml_on_mobile' => 'Zeigt die HTML-Version der Entität an, wenn sie auf Mobilgeräten angezeigt wird',
'show_pdfhtml_on_mobile_help' => 'Zur besseren Visualisierung wird bei der Anzeige auf Mobilgeräten eine HTML-Version der Rechnung/ Angebot / Kostenvoranschlag angezeigt.',
'please_select_an_invoice_or_credit' => 'Bitte wählen Sie eine Rechnung oder Gutschrift aus',
'mobile_version' => 'Mobile Version',
'venmo' => 'Venmo',
'my_bank' => 'MyBank',
'my_bank' => 'Meine Bank',
'pay_later' => 'Später Zahlen',
'local_domain' => 'Local Domain',
'verify_peer' => 'Verify Peer',
'nordigen_help' => 'Note: connecting an account requires a GoCardless/Nordigen API key',
'ar_detailed' => 'Accounts Receivable Detailed',
'ar_summary' => 'Accounts Receivable Summary',
'client_sales' => 'Client Sales',
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'local_domain' => 'Lokale Domäne',
'verify_peer' => 'Peer überprüfen',
'nordigen_help' => 'Hinweis: Für die Verbindung eines Kontos ist ein GoCardless/Nordigen-API-Schlüssel erforderlich',
'ar_detailed' => 'Detaillierte Debitorenbuchhaltung',
'ar_summary' => 'Zusammenfassung der Debitorenbuchhaltung',
'client_sales' => 'Kunde',
'user_sales' => 'Benutzerverkäufe',
'iframe_url' => 'iFrame-URL',
'user_unsubscribed' => 'Der Benutzer hat die E-Mails :link abgemeldet',
'use_available_payments' => 'Verwenden Sie verfügbare Zahlungen',
'test_email_sent' => 'E-Mail erfolgreich gesendet',
'gateway_type' => 'Gateway-Typ',
'save_template_body' => 'Möchten Sie diese Importzuordnung als Vorlage für die zukünftige Verwendung speichern?',
'save_as_template' => 'Vorlagenzuordnung speichern',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Setzt das <b>Standardfälligkeitsdatum</b>',
'payment_type_help' => 'Setze die Standard <b>manuelle Zahlungsmethode</b>.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);
return $lang;

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Επεξεργασία Διακριτικού',
'delete_token' => 'Διαγραφή Διακριτικού',
'token' => 'Διακριτικό',
'add_gateway' => 'Προσθήκη Πύλης Πληρωμών (Gateway)',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Διαγραφή Πύλης Πληρωμών (Gateway)',
'edit_gateway' => 'Επεξεργασία Πύλης Πληρωμών (Gateway)',
'updated_gateway' => 'Επιτυχής ενημέρωση πύλης πληρωμών (Gateway)',
@ -3868,7 +3868,7 @@ $lang = array(
'cancellation_pending' => 'Η ακύρωση εκκρεμεί, θα επικοινωνήσουμε μαζί σας!',
'list_of_payments' => 'Λίστα Πληρωμών',
'payment_details' => 'Details of the payment',
'list_of_payment_invoices' => 'List of invoices affected by the payment',
'list_of_payment_invoices' => 'Associate invoices',
'list_of_payment_methods' => 'List of payment methods',
'payment_method_details' => 'Details of payment method',
'permanently_remove_payment_method' => 'Οριστική αφαίρεσηε αυτής της μεθόδου πληρωμής',
@ -4925,7 +4925,7 @@ $lang = array(
'no_assigned_tasks' => 'Δεν υπάρχουν χρεώσιμες εργασίες για αυτό το έργο',
'authorization_failure' => 'Insufficient permissions to perform this action',
'authorization_sms_failure' => 'Please verify your account to send emails.',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Interac E Transfer',
'xinvoice_payable' => 'Payable within :payeddue days net until :paydate',
@ -5120,7 +5120,7 @@ $lang = array(
'set_private' => 'Set private',
'individual' => 'Individual',
'business' => 'Business',
'partnership' => 'partnership',
'partnership' => 'Partnership',
'trust' => 'Trust',
'charity' => 'Charity',
'government' => 'Government',
@ -5201,7 +5201,7 @@ $lang = array(
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
'lang_Lao' => 'Lao',
@ -5221,6 +5221,38 @@ $lang = array(
'unsubscribe_help' => 'You are currently not subscribed, and therefore, will not receive emails at this time.',
'notification_purchase_order_bounced' => 'We were unable to deliver Purchase Order :invoice to :contact. <br><br> :error',
'notification_purchase_order_bounced_subject' => 'Unable to deliver Purchase Order :invoice',
'show_pdfhtml_on_mobile' => 'Display HTML version of entity when viewing on mobile',
'show_pdfhtml_on_mobile_help' => 'For improved visualization, displays a HTML version of the invoice/quote when viewing on mobile.',
'please_select_an_invoice_or_credit' => 'Please select an invoice or credit',
'mobile_version' => 'Mobile Version',
'venmo' => 'Venmo',
'my_bank' => 'MyBank',
'pay_later' => 'Pay Later',
'local_domain' => 'Local Domain',
'verify_peer' => 'Verify Peer',
'nordigen_help' => 'Note: connecting an account requires a GoCardless/Nordigen API key',
'ar_detailed' => 'Accounts Receivable Detailed',
'ar_summary' => 'Accounts Receivable Summary',
'client_sales' => 'Client Sales',
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'use_available_payments' => 'Use Available Payments',
'test_email_sent' => 'Successfully sent email',
'gateway_type' => 'Gateway Type',
'save_template_body' => 'Would you like to save this import mapping as a template for future use?',
'save_as_template' => 'Save Template Mapping',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Ορίζει την προεπιλεγμένη <b>ημερομηνία ολοκλήρωσης<b> των τιμολογίων',
'payment_type_help' => 'Ορίζει τον προεπιλεγμένο <b>τρόπο χειροκίνητης πληρωμής</b>.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Edit Token',
'delete_token' => 'Delete Token',
'token' => 'Token',
'add_gateway' => 'Add Gateway',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Delete Gateway',
'edit_gateway' => 'Edit Gateway',
'updated_gateway' => 'Successfully updated gateway',
@ -5203,7 +5203,7 @@ $lang = array(
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
'lang_Lao' => 'Lao',
@ -5242,6 +5242,22 @@ $lang = array(
'use_available_payments' => 'Use Available Payments',
'test_email_sent' => 'Successfully sent email',
'gateway_type' => 'Gateway Type',
'save_template_body' => 'Would you like to save this import mapping as a template for future use?',
'save_as_template' => 'Save Template Mapping',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'The number of days after the invoice date that payment is due',
'payment_type_help' => 'The default payment type to be used for payments',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
'select_email_provider' => 'Set your email as the sending user',
'purchase_order_items' => 'Purchase Order Items',
'csv_rows_length' => 'No data found in this CSV file',
);
return $lang;

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Editar Token',
'delete_token' => 'Eliminar Token',
'token' => 'Token',
'add_gateway' => 'Agregar Gateway',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Eliminar Gateway',
'edit_gateway' => 'Editar Gateway',
'updated_gateway' => 'Gateway actualizado con éxito',
@ -506,8 +506,8 @@ $lang = array(
'auto_wrap' => 'Ajuste Automático de Línea',
'duplicate_post' => 'Advertencia: la página anterior fue enviada dos veces. El segundo envío ha sido ignorado.',
'view_documentation' => 'Ver Documentación',
'app_title' => 'Free Online Invoicing',
'app_description' => 'Invoice Ninja is a free, open-code solution for invoicing and billing customers. With Invoice Ninja, you can easily build and send beautiful invoices from any device that has access to the web. Your clients can print your invoices, download them as pdf files, and even pay you online from within the system.',
'app_title' => 'Facturación en línea gratuita',
'app_description' => 'Invoice Ninja es una solución gratuita de código abierto para facturar y facturar a los clientes. Con Invoice Ninja, puedes crear y enviar fácilmente hermosas facturas desde cualquier dispositivo que tenga acceso a la web. Sus clientes pueden imprimir sus facturas, descargarlas como archivos pdf e incluso pagarle en línea desde el sistema.',
'rows' => 'filas',
'www' => 'www',
'logo' => 'Logo',
@ -693,9 +693,9 @@ $lang = array(
'disable' => 'Deshabilitado',
'invoice_quote_number' => 'Números de Cotización y Factura',
'invoice_charges' => 'Cargos de Factura',
'notification_invoice_bounced' => 'We were unable to deliver Invoice :invoice to :contact. <br><br> :error',
'notification_invoice_bounced' => 'No pudimos entregar la factura :invoice a :contact .<br><br> :error',
'notification_invoice_bounced_subject' => 'No fue posible entregar la Factura :invoice',
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact. <br><br> :error',
'notification_quote_bounced' => 'No pudimos entregar la cotización :invoice a :contact .<br><br> :error',
'notification_quote_bounced_subject' => 'No nos fue posible entregar la Cotización :invoice',
'custom_invoice_link' => 'Link Personalizado de Factura',
'total_invoiced' => 'Total Facturado',
@ -3009,7 +3009,7 @@ $lang = array(
'hosted_login' => 'Inicio de sesión alojado',
'selfhost_login' => 'Iniciar sesión',
'google_login' => 'Inicio de sesión de Google',
'thanks_for_patience' => 'Thank for your patience while we work to implement these features.<br><br>We hope to have them completed in the next few months.<br><br>Until then we\'ll continue to support the',
'thanks_for_patience' => 'Gracias por su paciencia mientras trabajamos para implementar estas funciones.<br><br> Esperamos tenerlos terminados en los próximos meses.<br><br> Hasta entonces seguiremos apoyando a la',
'legacy_mobile_app' => 'aplicación móvil heredada',
'today' => 'Hoy',
'current' => 'Actual',
@ -3867,7 +3867,7 @@ $lang = array(
'cancellation_pending' => 'Cancelación pendiente, ¡nos pondremos en contacto!',
'list_of_payments' => 'Lista de pagos',
'payment_details' => 'Detalles del pago',
'list_of_payment_invoices' => 'Associate invoices',
'list_of_payment_invoices' => 'Facturas asociadas',
'list_of_payment_methods' => 'Lista de métodos de pago',
'payment_method_details' => 'Detalles del método de pago',
'permanently_remove_payment_method' => 'Eliminar permanentemente este método de pago.',
@ -4924,7 +4924,7 @@ $lang = array(
'no_assigned_tasks' => 'No hay tareas facturables para este proyecto',
'authorization_failure' => 'Permisos insuficientes para realizar esta acción',
'authorization_sms_failure' => 'Por favor verifique su cuenta para enviar correos electrónicos.',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'white_label_body' => 'Gracias por adquirir una licencia de marca blanca.<br><br> Su clave de licencia es:<br><br> :license_key<br><br> Puedes gestionar tu licencia aquí: https://invoiceninja.invoicing.co/client/login',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Transferencia Interac E',
'xinvoice_payable' => 'Payable within :payeddue days net until :paydate',
@ -5119,7 +5119,7 @@ $lang = array(
'set_private' => 'Establecer privado',
'individual' => 'Individual',
'business' => 'Negocio',
'partnership' => 'Partnership',
'partnership' => 'Camaradería',
'trust' => 'Confianza',
'charity' => 'Caridad',
'government' => 'Gobierno',
@ -5200,7 +5200,7 @@ $lang = array(
'nordigen_handler_error_heading_requisition_invalid_status' => 'No está listo',
'nordigen_handler_error_contents_requisition_invalid_status' => 'Llamaste a este sitio demasiado pronto. Finalice la autorización y actualice esta página. Póngase en contacto con el soporte para obtener ayuda si este problema persiste.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No hay cuentas seleccionadas',
'nordigen_handler_error_contents_requisition_no_accounts' => 'El servicio no ha devuelto ninguna cuenta válida. Considere reiniciar el flujo.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Reiniciar el flujo.',
'nordigen_handler_return' => 'Volver a la aplicación.',
'lang_Lao' => 'laosiano',
@ -5210,32 +5210,49 @@ $lang = array(
'select_provider' => 'Seleccionar Proveedor',
'nordigen_requisition_subject' => 'La solicitud expiró, vuelva a autenticarse.',
'nordigen_requisition_body' => 'El acceso a los feeds de cuentas bancarias ha caducado según lo establecido en el Acuerdo de usuario final.<br><br> Inicie sesión en Invoice Ninja y vuelva a autenticarse con sus bancos para continuar recibiendo transacciones.',
'participant' => 'Participant',
'participant_name' => 'Participant name',
'client_unsubscribed' => 'Client unsubscribed from emails.',
'client_unsubscribed_help' => 'Client :client has unsubscribed from your e-mails. The client needs to consent to receive future emails from you.',
'resubscribe' => 'Resubscribe',
'subscribe' => 'Subscribe',
'subscribe_help' => 'You are currently subscribed and will continue to receive email communications.',
'unsubscribe_help' => 'You are currently not subscribed, and therefore, will not receive emails at this time.',
'notification_purchase_order_bounced' => 'We were unable to deliver Purchase Order :invoice to :contact. <br><br> :error',
'notification_purchase_order_bounced_subject' => 'Unable to deliver Purchase Order :invoice',
'show_pdfhtml_on_mobile' => 'Display HTML version of entity when viewing on mobile',
'show_pdfhtml_on_mobile_help' => 'For improved visualization, displays a HTML version of the invoice/quote when viewing on mobile.',
'please_select_an_invoice_or_credit' => 'Please select an invoice or credit',
'mobile_version' => 'Mobile Version',
'participant' => 'Partícipe',
'participant_name' => 'Nombre del participante',
'client_unsubscribed' => 'El cliente se dio de baja de los correos electrónicos.',
'client_unsubscribed_help' => 'El cliente :client se ha dado de baja de sus correos electrónicos. El cliente debe dar su consentimiento para recibir futuros correos electrónicos suyos.',
'resubscribe' => 'Volver a suscribirse',
'subscribe' => 'Suscribir',
'subscribe_help' => 'Actualmente está suscrito y seguirá recibiendo comunicaciones por correo electrónico.',
'unsubscribe_help' => 'Actualmente no estás suscrito y, por lo tanto, no recibirás correos electrónicos en este momento.',
'notification_purchase_order_bounced' => 'No pudimos entregar la orden de compra :invoice a :contact .<br><br> :error',
'notification_purchase_order_bounced_subject' => 'No se puede entregar la orden de compra :invoice',
'show_pdfhtml_on_mobile' => 'Mostrar la versión HTML de la entidad cuando se visualiza en un dispositivo móvil',
'show_pdfhtml_on_mobile_help' => 'Para una visualización mejorada, muestra una versión HTML de la factura/cotización cuando se visualiza en el dispositivo móvil.',
'please_select_an_invoice_or_credit' => 'Por favor seleccione una factura o crédito',
'mobile_version' => 'Version móvil',
'venmo' => 'Venmo',
'my_bank' => 'MyBank',
'pay_later' => 'Pay Later',
'local_domain' => 'Local Domain',
'verify_peer' => 'Verify Peer',
'nordigen_help' => 'Note: connecting an account requires a GoCardless/Nordigen API key',
'ar_detailed' => 'Accounts Receivable Detailed',
'ar_summary' => 'Accounts Receivable Summary',
'client_sales' => 'Client Sales',
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'my_bank' => 'Mi banco',
'pay_later' => 'Paga después',
'local_domain' => 'Dominio local',
'verify_peer' => 'Verificar par',
'nordigen_help' => 'Nota: conectar una cuenta requiere una clave API de GoCardless/Nordigen',
'ar_detailed' => 'Cuentas por cobrar detalladas',
'ar_summary' => 'Resumen de cuentas por cobrar',
'client_sales' => 'Ventas al cliente',
'user_sales' => 'Ventas de usuarios',
'iframe_url' => 'URL del marco flotante',
'user_unsubscribed' => 'Usuario dado de baja de los correos electrónicos :link',
'use_available_payments' => 'Usar pagos disponibles',
'test_email_sent' => 'Correo electrónico enviado correctamente',
'gateway_type' => 'Tipo de puerta de enlace',
'save_template_body' => '¿Le gustaría guardar este mapeo de importación como plantilla para uso futuro?',
'save_as_template' => 'Guardar asignación de plantilla',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Establecer <b>fecha de vencimiento de la factura</b> por defecto',
'payment_type_help' => 'Establecer el <b>tipo de pago manual</b> por defecto.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);
return $lang;

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Editar Token',
'delete_token' => 'Eliminar Token',
'token' => 'Token',
'add_gateway' => 'Agregar Pasarela',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Eliminar Pasarela',
'edit_gateway' => 'Editar Pasarela',
'updated_gateway' => 'Pasarela actualizada correctamente',
@ -4921,7 +4921,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
'no_assigned_tasks' => 'No hay tareas facturables para este proyecto',
'authorization_failure' => 'Permisos insuficientes para realizar esta acción',
'authorization_sms_failure' => 'Por favor verifique su cuenta para enviar correos electrónicos.',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'white_label_body' => 'Gracias por adquirir una licencia de marca blanca. <br><br> Su clave de licencia es: <br><br> :license_key <br><br> Puedes gestionar tu licencia aquí: https://invoiceninja.invoicing.co/client/login',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Interac E Transfer',
'xinvoice_payable' => 'Pagadero dentro de :payeddue días de pago vencido neto hasta :paydate',
@ -5198,7 +5198,7 @@ De lo contrario, este campo deberá dejarse en blanco.',
'nordigen_handler_error_heading_requisition_invalid_status' => 'No listo',
'nordigen_handler_error_contents_requisition_invalid_status' => 'Llamaste a este sitio demasiado pronto. Finalice la autorización y actualice esta página. Póngase en contacto con el soporte para obtener ayuda si este problema persiste.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No hay cuentas seleccionadas',
'nordigen_handler_error_contents_requisition_no_accounts' => 'El servicio no ha devuelto ninguna cuenta válida. Considere reiniciar el flujo.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Reiniciar el flujo.',
'nordigen_handler_return' => 'Volver a la aplicación.',
'lang_Lao' => 'Lao',
@ -5234,6 +5234,23 @@ De lo contrario, este campo deberá dejarse en blanco.',
'user_sales' => 'Ventas de usuarios',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'Usuario dado de baja de los correos electrónicos :link',
'use_available_payments' => 'Usar pagos disponibles',
'test_email_sent' => 'Correo electrónico enviado correctamente',
'gateway_type' => 'Tipo de puerta de enlace',
'save_template_body' => '¿Le gustaría guardar este mapeo de importación como plantilla para uso futuro?',
'save_as_template' => 'Guardar asignación de plantilla',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Establezca la <b>fecha límite de pago de factura</b> por defecto',
'payment_type_help' => 'Establece el <b>tipo de pago manual</b> predeterminado.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);
return $lang;

View File

@ -461,7 +461,7 @@ $lang = array(
'edit_token' => 'Redigeeri Tokenit',
'delete_token' => 'Kustuta Token',
'token' => 'Token',
'add_gateway' => 'Lisa Lüüs',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Kustuta Lüüs',
'edit_gateway' => 'Muuda Lüüsi',
'updated_gateway' => 'Makselahendus uuendatud',
@ -3868,7 +3868,7 @@ $lang = array(
'cancellation_pending' => 'Cancellation pending, we\'ll be in touch!',
'list_of_payments' => 'List of payments',
'payment_details' => 'Details of the payment',
'list_of_payment_invoices' => 'List of invoices affected by the payment',
'list_of_payment_invoices' => 'Associate invoices',
'list_of_payment_methods' => 'List of payment methods',
'payment_method_details' => 'Details of payment method',
'permanently_remove_payment_method' => 'Permanently remove this payment method.',
@ -4925,7 +4925,7 @@ $lang = array(
'no_assigned_tasks' => 'No billable tasks for this project',
'authorization_failure' => 'Insufficient permissions to perform this action',
'authorization_sms_failure' => 'Please verify your account to send emails.',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Interac E Transfer',
'xinvoice_payable' => 'Payable within :payeddue days net until :paydate',
@ -5120,7 +5120,7 @@ $lang = array(
'set_private' => 'Set private',
'individual' => 'Individual',
'business' => 'Business',
'partnership' => 'partnership',
'partnership' => 'Partnership',
'trust' => 'Trust',
'charity' => 'Charity',
'government' => 'Government',
@ -5201,7 +5201,7 @@ $lang = array(
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
'lang_Lao' => 'Lao',
@ -5221,6 +5221,38 @@ $lang = array(
'unsubscribe_help' => 'You are currently not subscribed, and therefore, will not receive emails at this time.',
'notification_purchase_order_bounced' => 'We were unable to deliver Purchase Order :invoice to :contact. <br><br> :error',
'notification_purchase_order_bounced_subject' => 'Unable to deliver Purchase Order :invoice',
'show_pdfhtml_on_mobile' => 'Display HTML version of entity when viewing on mobile',
'show_pdfhtml_on_mobile_help' => 'For improved visualization, displays a HTML version of the invoice/quote when viewing on mobile.',
'please_select_an_invoice_or_credit' => 'Please select an invoice or credit',
'mobile_version' => 'Mobile Version',
'venmo' => 'Venmo',
'my_bank' => 'MyBank',
'pay_later' => 'Pay Later',
'local_domain' => 'Local Domain',
'verify_peer' => 'Verify Peer',
'nordigen_help' => 'Note: connecting an account requires a GoCardless/Nordigen API key',
'ar_detailed' => 'Accounts Receivable Detailed',
'ar_summary' => 'Accounts Receivable Summary',
'client_sales' => 'Client Sales',
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'use_available_payments' => 'Use Available Payments',
'test_email_sent' => 'Successfully sent email',
'gateway_type' => 'Gateway Type',
'save_template_body' => 'Would you like to save this import mapping as a template for future use?',
'save_as_template' => 'Save Template Mapping',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Määrab vaikimisi <b>arve tähtaeg</b>',
'payment_type_help' => 'Määrab vaikimisi <b>käsitsimakse tüüp</b>.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Edit Token',
'delete_token' => 'Delete Token',
'token' => 'Token',
'add_gateway' => 'Add Gateway',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Delete Gateway',
'edit_gateway' => 'Edit Gateway',
'updated_gateway' => 'Successfully updated gateway',
@ -3868,7 +3868,7 @@ $lang = array(
'cancellation_pending' => 'Cancellation pending, we\'ll be in touch!',
'list_of_payments' => 'List of payments',
'payment_details' => 'Details of the payment',
'list_of_payment_invoices' => 'List of invoices affected by the payment',
'list_of_payment_invoices' => 'Associate invoices',
'list_of_payment_methods' => 'List of payment methods',
'payment_method_details' => 'Details of payment method',
'permanently_remove_payment_method' => 'Permanently remove this payment method.',
@ -4925,7 +4925,7 @@ $lang = array(
'no_assigned_tasks' => 'No billable tasks for this project',
'authorization_failure' => 'Insufficient permissions to perform this action',
'authorization_sms_failure' => 'Please verify your account to send emails.',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Interac E Transfer',
'xinvoice_payable' => 'Payable within :payeddue days net until :paydate',
@ -5120,7 +5120,7 @@ $lang = array(
'set_private' => 'Set private',
'individual' => 'Individual',
'business' => 'Business',
'partnership' => 'partnership',
'partnership' => 'Partnership',
'trust' => 'Trust',
'charity' => 'Charity',
'government' => 'Government',
@ -5201,7 +5201,7 @@ $lang = array(
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
'lang_Lao' => 'Lao',
@ -5221,6 +5221,38 @@ $lang = array(
'unsubscribe_help' => 'You are currently not subscribed, and therefore, will not receive emails at this time.',
'notification_purchase_order_bounced' => 'We were unable to deliver Purchase Order :invoice to :contact. <br><br> :error',
'notification_purchase_order_bounced_subject' => 'Unable to deliver Purchase Order :invoice',
'show_pdfhtml_on_mobile' => 'Display HTML version of entity when viewing on mobile',
'show_pdfhtml_on_mobile_help' => 'For improved visualization, displays a HTML version of the invoice/quote when viewing on mobile.',
'please_select_an_invoice_or_credit' => 'Please select an invoice or credit',
'mobile_version' => 'Mobile Version',
'venmo' => 'Venmo',
'my_bank' => 'MyBank',
'pay_later' => 'Pay Later',
'local_domain' => 'Local Domain',
'verify_peer' => 'Verify Peer',
'nordigen_help' => 'Note: connecting an account requires a GoCardless/Nordigen API key',
'ar_detailed' => 'Accounts Receivable Detailed',
'ar_summary' => 'Accounts Receivable Summary',
'client_sales' => 'Client Sales',
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'use_available_payments' => 'Use Available Payments',
'test_email_sent' => 'Successfully sent email',
'gateway_type' => 'Gateway Type',
'save_template_body' => 'Would you like to save this import mapping as a template for future use?',
'save_as_template' => 'Save Template Mapping',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Sets the default <b>invoice due date</b>',
'payment_type_help' => 'Sets the default <b>manual payment type</b>.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Muokkaa tokenia',
'delete_token' => 'Poista token',
'token' => 'Token',
'add_gateway' => 'Lisää maksunvälittäjä',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Poista maksunvälittäjä',
'edit_gateway' => 'Muokkaa maksunvälittäjää',
'updated_gateway' => 'Maksunvälittäjä päivitetty onnistuneesti',
@ -3868,7 +3868,7 @@ Kun saat summat, palaa tälle maksutapasivulle ja klikkaa "Saata loppuun todenta
'cancellation_pending' => 'Cancellation pending, we\'ll be in touch!',
'list_of_payments' => 'List of payments',
'payment_details' => 'Details of the payment',
'list_of_payment_invoices' => 'List of invoices affected by the payment',
'list_of_payment_invoices' => 'Associate invoices',
'list_of_payment_methods' => 'Lista maksutavoista',
'payment_method_details' => 'Details of payment method',
'permanently_remove_payment_method' => 'Permanently remove this payment method.',
@ -4925,7 +4925,7 @@ Kun saat summat, palaa tälle maksutapasivulle ja klikkaa "Saata loppuun todenta
'no_assigned_tasks' => 'No billable tasks for this project',
'authorization_failure' => 'Insufficient permissions to perform this action',
'authorization_sms_failure' => 'Please verify your account to send emails.',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Interac E Transfer',
'xinvoice_payable' => 'Payable within :payeddue days net until :paydate',
@ -5120,7 +5120,7 @@ Kun saat summat, palaa tälle maksutapasivulle ja klikkaa "Saata loppuun todenta
'set_private' => 'Set private',
'individual' => 'Individual',
'business' => 'Business',
'partnership' => 'partnership',
'partnership' => 'Partnership',
'trust' => 'Trust',
'charity' => 'Charity',
'government' => 'Government',
@ -5201,7 +5201,7 @@ Kun saat summat, palaa tälle maksutapasivulle ja klikkaa "Saata loppuun todenta
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
'lang_Lao' => 'Lao',
@ -5221,6 +5221,38 @@ Kun saat summat, palaa tälle maksutapasivulle ja klikkaa "Saata loppuun todenta
'unsubscribe_help' => 'You are currently not subscribed, and therefore, will not receive emails at this time.',
'notification_purchase_order_bounced' => 'We were unable to deliver Purchase Order :invoice to :contact. <br><br> :error',
'notification_purchase_order_bounced_subject' => 'Unable to deliver Purchase Order :invoice',
'show_pdfhtml_on_mobile' => 'Display HTML version of entity when viewing on mobile',
'show_pdfhtml_on_mobile_help' => 'For improved visualization, displays a HTML version of the invoice/quote when viewing on mobile.',
'please_select_an_invoice_or_credit' => 'Please select an invoice or credit',
'mobile_version' => 'Mobile Version',
'venmo' => 'Venmo',
'my_bank' => 'MyBank',
'pay_later' => 'Pay Later',
'local_domain' => 'Local Domain',
'verify_peer' => 'Verify Peer',
'nordigen_help' => 'Note: connecting an account requires a GoCardless/Nordigen API key',
'ar_detailed' => 'Accounts Receivable Detailed',
'ar_summary' => 'Accounts Receivable Summary',
'client_sales' => 'Client Sales',
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'use_available_payments' => 'Use Available Payments',
'test_email_sent' => 'Successfully sent email',
'gateway_type' => 'Gateway Type',
'save_template_body' => 'Would you like to save this import mapping as a template for future use?',
'save_as_template' => 'Save Template Mapping',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Asettaa <b>eräpäivään</b> vakioasetuksen',
'payment_type_help' => 'Asettaa oletuksena <b>manuaalisen maksutavan</b>.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Éditer ce jeton',
'delete_token' => 'Supprimer ce jeton',
'token' => 'Jeton',
'add_gateway' => 'Ajouter une passerelle',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Supprimer la passerelle',
'edit_gateway' => 'Éditer la passerelle',
'updated_gateway' => 'Passerelle mise à jour avec succès',
@ -506,8 +506,8 @@ $lang = array(
'auto_wrap' => 'Retour à la ligne automatique',
'duplicate_post' => 'Attention: la page précédente a été soumise deux fois. La deuxième soumission a été ignorée.',
'view_documentation' => 'Voir documentation',
'app_title' => 'Free Online Invoicing',
'app_description' => 'Invoice Ninja is a free, open-code solution for invoicing and billing customers. With Invoice Ninja, you can easily build and send beautiful invoices from any device that has access to the web. Your clients can print your invoices, download them as pdf files, and even pay you online from within the system.',
'app_title' => 'Facturation en ligne gratuite',
'app_description' => 'Invoice Ninja est une solution gratuite et à code ouvert pour la facturation et la facturation des clients. Avec Invoice Ninja, vous pouvez facilement créer et envoyer de belles factures depuis n&#39;importe quel appareil ayant accès au Web. Vos clients peuvent imprimer vos factures, les télécharger sous forme de fichiers PDF et même vous payer en ligne depuis le système.',
'rows' => 'lignes',
'www' => 'www',
'logo' => 'Logo',
@ -693,9 +693,9 @@ $lang = array(
'disable' => 'Désactiver',
'invoice_quote_number' => 'Numéro des devis & factures',
'invoice_charges' => 'Majoration de facture',
'notification_invoice_bounced' => 'We were unable to deliver Invoice :invoice to :contact. <br><br> :error',
'notification_invoice_bounced' => 'Nous n&#39;avons pas pu transmettre la facture :invoice à :contact .<br><br> :error',
'notification_invoice_bounced_subject' => 'Impossible d\'envoyer la facture :invoice',
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact. <br><br> :error',
'notification_quote_bounced' => 'Nous n&#39;avons pas pu transmettre le devis :invoice à :contact .<br><br> :error',
'notification_quote_bounced_subject' => 'Impossible d\'envoyer le devis :invoice',
'custom_invoice_link' => 'Personnaliser le lien de la facture',
'total_invoiced' => 'Total facturé',
@ -3010,7 +3010,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'hosted_login' => 'Authentification Hosted',
'selfhost_login' => 'Authentification Selfhost',
'google_login' => 'Authentification Google',
'thanks_for_patience' => 'Thank for your patience while we work to implement these features.<br><br>We hope to have them completed in the next few months.<br><br>Until then we\'ll continue to support the',
'thanks_for_patience' => 'Merci de votre patience pendant que nous travaillons à la mise en œuvre de ces fonctionnalités.<br><br> Nous espérons les terminer dans les prochains mois.<br><br> D&#39;ici là, nous continuerons à soutenir le',
'legacy_mobile_app' => 'Ancienne App mobile',
'today' => 'Aujourd\'hui',
'current' => 'Actuel',
@ -3868,7 +3868,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'cancellation_pending' => 'Annulation en cours, nous vous contacterons !',
'list_of_payments' => 'Liste des paiements',
'payment_details' => 'Détails du paiement',
'list_of_payment_invoices' => 'Associate invoices',
'list_of_payment_invoices' => 'Factures associées',
'list_of_payment_methods' => 'Liste des moyens de paiement',
'payment_method_details' => 'Détails du mode de paiement',
'permanently_remove_payment_method' => 'Supprimer définitivement ce mode de paiement.',
@ -4925,7 +4925,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'no_assigned_tasks' => 'Aucune tâche facturable pour ce projet',
'authorization_failure' => 'Autorisations insuffisantes pour effectuer cette action',
'authorization_sms_failure' => 'Veuillez vérifier votre compte pour envoyer des e-mails.',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'white_label_body' => 'Merci d&#39;avoir acheté une licence en marque blanche.<br><br> Votre clé de licence est :<br><br> :license_key<br><br> Vous pouvez gérer votre licence ici : https://invoiceninja.invoicing.co/client/login',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Virement Interac E',
'xinvoice_payable' => 'Payable sous :payeddue days net jusqu\'au :paydate',
@ -5090,7 +5090,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'region' => 'Région',
'county' => 'Comté',
'tax_details' => 'Détails fiscaux',
'activity_10_online' => ':contact made payment :payment for invoice :invoice for :client',
'activity_10_online' => ':contact a effectué le paiement :payment pour la facture :invoice pour :client',
'activity_10_manual' => ':user a saisi le paiement :payment pour la facture :invoice pour :client',
'default_payment_type' => 'Type de paiement par défaut',
'number_precision' => 'Précision du nombre',
@ -5120,7 +5120,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'set_private' => 'Définir comme privé',
'individual' => 'Individuel',
'business' => 'Entreprise',
'partnership' => 'Partnership',
'partnership' => 'Partenariat',
'trust' => 'Confiance',
'charity' => 'Charité',
'government' => 'Gouvernement',
@ -5201,42 +5201,59 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'nordigen_handler_error_heading_requisition_invalid_status' => 'Pas prêt',
'nordigen_handler_error_contents_requisition_invalid_status' => 'Vous avez appelé ce site trop tôt. Veuillez terminer l&#39;autorisation et actualiser cette page. Contactez le support pour obtenir de l&#39;aide si ce problème persiste.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'Aucun compte sélectionné',
'nordigen_handler_error_contents_requisition_no_accounts' => 'Le service n&#39;a renvoyé aucun compte valide. Pensez à redémarrer le flux.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Redémarrez le flux.',
'nordigen_handler_return' => 'Retour à la candidature.',
'lang_Lao' => 'Lao',
'currency_lao_kip' => 'Lao kip',
'yodlee_regions' => 'Regions: USA, UK, Australia & India',
'nordigen_regions' => 'Regions: Europe & UK',
'select_provider' => 'Select Provider',
'nordigen_requisition_subject' => 'Requisition expired, please reauthenticate.',
'nordigen_requisition_body' => 'Access to bank account feeds has expired as set in End User Agreement. <br><br>Please log into Invoice Ninja and re-authenticate with your banks to continue receiving transactions.',
'lang_Lao' => 'Laotien',
'currency_lao_kip' => 'Kip laotien',
'yodlee_regions' => 'Régions : États-Unis, Royaume-Uni, Australie et Inde',
'nordigen_regions' => 'Régions : Europe et Royaume-Uni',
'select_provider' => 'Sélectionnez le fournisseur',
'nordigen_requisition_subject' => 'La demande a expiré, veuillez vous authentifier à nouveau.',
'nordigen_requisition_body' => 'L&#39;accès aux flux des comptes bancaires a expiré comme indiqué dans le Contrat de l&#39;utilisateur final.<br><br> Veuillez vous connecter à Invoice Ninja et vous authentifier à nouveau auprès de vos banques pour continuer à recevoir des transactions.',
'participant' => 'Participant',
'participant_name' => 'Participant name',
'client_unsubscribed' => 'Client unsubscribed from emails.',
'client_unsubscribed_help' => 'Client :client has unsubscribed from your e-mails. The client needs to consent to receive future emails from you.',
'resubscribe' => 'Resubscribe',
'subscribe' => 'Subscribe',
'subscribe_help' => 'You are currently subscribed and will continue to receive email communications.',
'unsubscribe_help' => 'You are currently not subscribed, and therefore, will not receive emails at this time.',
'notification_purchase_order_bounced' => 'We were unable to deliver Purchase Order :invoice to :contact. <br><br> :error',
'notification_purchase_order_bounced_subject' => 'Unable to deliver Purchase Order :invoice',
'show_pdfhtml_on_mobile' => 'Display HTML version of entity when viewing on mobile',
'show_pdfhtml_on_mobile_help' => 'For improved visualization, displays a HTML version of the invoice/quote when viewing on mobile.',
'please_select_an_invoice_or_credit' => 'Please select an invoice or credit',
'mobile_version' => 'Mobile Version',
'participant_name' => 'Nom du participant',
'client_unsubscribed' => 'Client désabonné des e-mails.',
'client_unsubscribed_help' => 'Le client :client s&#39;est désabonné de vos e-mails. Le client doit consentir à recevoir de futurs e-mails de votre part.',
'resubscribe' => 'Réabonnez-vous',
'subscribe' => 'S&#39;abonner',
'subscribe_help' => 'Vous êtes actuellement abonné et continuerez à recevoir des communications par courrier électronique.',
'unsubscribe_help' => 'Vous n&#39;êtes actuellement pas abonné et ne recevrez donc pas d&#39;e-mails pour le moment.',
'notification_purchase_order_bounced' => 'Nous n&#39;avons pas pu livrer le bon de commande :invoice à :contact .<br><br> :error',
'notification_purchase_order_bounced_subject' => 'Impossible de livrer le bon de commande :invoice',
'show_pdfhtml_on_mobile' => 'Afficher la version HTML de l&#39;entité lors de la visualisation sur mobile',
'show_pdfhtml_on_mobile_help' => 'Pour une visualisation améliorée, affiche une version HTML de la facture/devis lors de la visualisation sur mobile.',
'please_select_an_invoice_or_credit' => 'Veuillez sélectionner une facture ou un crédit',
'mobile_version' => 'Version mobile',
'venmo' => 'Venmo',
'my_bank' => 'MyBank',
'pay_later' => 'Pay Later',
'local_domain' => 'Local Domain',
'verify_peer' => 'Verify Peer',
'nordigen_help' => 'Note: connecting an account requires a GoCardless/Nordigen API key',
'ar_detailed' => 'Accounts Receivable Detailed',
'ar_summary' => 'Accounts Receivable Summary',
'client_sales' => 'Client Sales',
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'my_bank' => 'Ma banque',
'pay_later' => 'Payer plus tard',
'local_domain' => 'Domaine local',
'verify_peer' => 'Vérifier le pair',
'nordigen_help' => 'Remarque : la connexion d&#39;un compte nécessite une clé API GoCardless/Nordigen',
'ar_detailed' => 'Comptes clients détaillés',
'ar_summary' => 'Sommaire des comptes clients',
'client_sales' => 'Ventes clients',
'user_sales' => 'Ventes aux utilisateurs',
'iframe_url' => 'URL iFrame',
'user_unsubscribed' => 'Utilisateur désabonné des e-mails :link',
'use_available_payments' => 'Utiliser les paiements disponibles',
'test_email_sent' => 'E-mail envoyé avec succès',
'gateway_type' => 'Type de passerelle',
'save_template_body' => 'Souhaitez-vous enregistrer ce mappage dimportation en tant que modèle pour une utilisation future ?',
'save_as_template' => 'Enregistrer le mappage de modèle',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Définit <b>la date d\'échéance de la facture</b> par défaut ',
'payment_type_help' => 'Définit le <b>type de paiement manuel </b> par défaut.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);
return $lang;

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Éditer le jeton',
'delete_token' => 'Supprimer le jeton',
'token' => 'Jeton',
'add_gateway' => 'Ajouter une passerelle',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Supprimer la passerelle',
'edit_gateway' => 'Éditer la passerelle',
'updated_gateway' => 'La passerelle a été mise à jour',
@ -5198,7 +5198,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'nordigen_handler_error_heading_requisition_invalid_status' => 'Pas prêt',
'nordigen_handler_error_contents_requisition_invalid_status' => 'Vous avez contacté ce site trop tôt. Veuillez terminer l\'autorisation et rafraîchir cette page. Contactez le support pour obtenir de l\'aide si ce problème persiste.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'Aucun compte sélectionné',
'nordigen_handler_error_contents_requisition_no_accounts' => 'Le service n\'a retourné aucun compte valide. Veuillez redémarrer le processus.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'Le service na retourné aucun compte valide. Veuillez redémarrer le processus.',
'nordigen_handler_restart' => 'Redémarrer le processus',
'nordigen_handler_return' => 'Retour à l\'application',
'lang_Lao' => 'Lao',
@ -5234,6 +5234,23 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'user_sales' => 'Ventes de l\'utilisateur',
'iframe_url' => 'URL de l\'iFrame',
'user_unsubscribed' => 'Utilisateur désabonné des courriels :link',
'use_available_payments' => 'Utilisez les paiements disponibles',
'test_email_sent' => 'Le courriel a été envoyé',
'gateway_type' => 'Type de passerelle',
'save_template_body' => 'Souhaitez-vous enregistrer cette correspondance d\'importation en tant que modèle pour une utilisation future ?',
'save_as_template' => 'Enregistrer la correspondance de modèle',
'auto_bill_standard_invoices_help' => 'Facturer automatiquement les factures régulières à la date d\'échéance',
'auto_bill_on_help' => 'Facturation automatique à la date d\'envoi OU à la date d\'échéance (factures récurrentes)',
'use_available_credits_help' => 'Appliquer tout solde de crédit aux paiements avant de facturer une méthode de paiement',
'use_unapplied_payments' => 'Utiliser les paiements non appliqués',
'use_unapplied_payments_help' => 'Appliquer tout solde de paiement avant de facturer une méthode de paiement',
'payment_terms_help' => 'Définit la <b>date d\'échéance de la facture</b> par défaut',
'payment_type_help' => 'Définit le <b>type de paiement manuel<b/> par défaut.',
'quote_valid_until_help' => 'Le nombre de jours pour lesquels la soumission est valide',
'expense_payment_type_help' => 'Le type de paiement de dépenses par défaut à utiliser',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);
return $lang;

View File

@ -460,7 +460,7 @@ $lang = array(
'edit_token' => 'Éditer le jeton',
'delete_token' => 'Supprimer le jeton',
'token' => 'Jeton',
'add_gateway' => 'Ajouter une passerelle',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Supprimer la passerelle',
'edit_gateway' => 'Éditer la passerelle',
'updated_gateway' => 'La passerelle a été mise à jour avec succès',
@ -506,8 +506,8 @@ $lang = array(
'auto_wrap' => 'Retour à la ligne automatique',
'duplicate_post' => 'Avertissement: la page précédente a été envoyée deux fois. Le deuxième envoi a été ignoré.',
'view_documentation' => 'Voir la documentation',
'app_title' => 'Free Online Invoicing',
'app_description' => 'Invoice Ninja is a free, open-code solution for invoicing and billing customers. With Invoice Ninja, you can easily build and send beautiful invoices from any device that has access to the web. Your clients can print your invoices, download them as pdf files, and even pay you online from within the system.',
'app_title' => 'Facturation en ligne gratuite',
'app_description' => 'Invoice Ninja est une solution gratuite et à code ouvert pour la facturation et la facturation des clients. Avec Invoice Ninja, vous pouvez facilement créer et envoyer de belles factures depuis n&#39;importe quel appareil ayant accès au Web. Vos clients peuvent imprimer vos factures, les télécharger sous forme de fichiers PDF et même vous payer en ligne depuis le système.',
'rows' => 'lignes',
'www' => 'www',
'logo' => 'Logo',
@ -693,9 +693,9 @@ $lang = array(
'disable' => 'Désactiver',
'invoice_quote_number' => 'Numéro des offres & factures',
'invoice_charges' => 'Suppléments de facture',
'notification_invoice_bounced' => 'We were unable to deliver Invoice :invoice to :contact. <br><br> :error',
'notification_invoice_bounced' => 'Nous n&#39;avons pas pu transmettre la facture :invoice à :contact .<br><br> :error',
'notification_invoice_bounced_subject' => 'Impossible d\'envoyer la facture :invoice',
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact. <br><br> :error',
'notification_quote_bounced' => 'Nous n&#39;avons pas pu transmettre le devis :invoice à :contact .<br><br> :error',
'notification_quote_bounced_subject' => 'Impossible d\'envoyer l\'offre :invoice',
'custom_invoice_link' => 'Lien de facture personnalisé',
'total_invoiced' => 'Total facturé',
@ -3007,7 +3007,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'hosted_login' => 'Connexion hébergée',
'selfhost_login' => 'Connexion autohébergée',
'google_login' => 'Connexion Google',
'thanks_for_patience' => 'Thank for your patience while we work to implement these features.<br><br>We hope to have them completed in the next few months.<br><br>Until then we\'ll continue to support the',
'thanks_for_patience' => 'Merci de votre patience pendant que nous travaillons à la mise en œuvre de ces fonctionnalités.<br><br> Nous espérons les terminer dans les prochains mois.<br><br> D&#39;ici là, nous continuerons à soutenir le',
'legacy_mobile_app' => 'Ancienne App mobile',
'today' => 'Aujourd\'hui',
'current' => 'En cours',
@ -3865,7 +3865,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'cancellation_pending' => 'Annulation en attente. Nous vous tiendrons au courant.',
'list_of_payments' => 'Liste des paiements',
'payment_details' => 'Détails du paiement',
'list_of_payment_invoices' => 'Associate invoices',
'list_of_payment_invoices' => 'Factures associées',
'list_of_payment_methods' => 'Liste des modes de paiement',
'payment_method_details' => 'Détails du mode de paiement',
'permanently_remove_payment_method' => 'Supprimer de façon définitive ce mode de paiement',
@ -4922,7 +4922,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'no_assigned_tasks' => 'Aucune intervetion facturable pour ce projet',
'authorization_failure' => 'Insufficient permissions to perform this action',
'authorization_sms_failure' => 'Please verify your account to send emails.',
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key <br><br> You can manage your license here: https://invoiceninja.invoicing.co/client/login',
'white_label_body' => 'Merci d&#39;avoir acheté une licence en marque blanche.<br><br> Votre clé de licence est :<br><br> :license_key<br><br> Vous pouvez gérer votre licence ici : https://invoiceninja.invoicing.co/client/login',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Interac E Transfer',
'xinvoice_payable' => 'Payable sous :payeddue jours net jusqu&#39;à :paydate',
@ -5117,7 +5117,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'set_private' => 'Définir comme privé',
'individual' => 'Individuel',
'business' => 'Entreprise',
'partnership' => 'Partnership',
'partnership' => 'Partenariat',
'trust' => 'Confiance',
'charity' => 'Charité',
'government' => 'Gouvernement',
@ -5198,42 +5198,59 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'nordigen_handler_error_heading_requisition_invalid_status' => 'Pas prêt',
'nordigen_handler_error_contents_requisition_invalid_status' => 'Vous avez appelé ce site trop tôt. Veuillez terminer l&#39;autorisation et actualiser cette page. Contactez le support pour obtenir de l&#39;aide si ce problème persiste.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'Aucun compte sélectionné',
'nordigen_handler_error_contents_requisition_no_accounts' => 'Le service n&#39;a renvoyé aucun compte valide. Pensez à redémarrer le flux.',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Consider restarting the flow.',
'nordigen_handler_restart' => 'Redémarrez le flux.',
'nordigen_handler_return' => 'Retour à la candidature.',
'lang_Lao' => 'Lao',
'currency_lao_kip' => 'Lao kip',
'yodlee_regions' => 'Regions: USA, UK, Australia & India',
'nordigen_regions' => 'Regions: Europe & UK',
'select_provider' => 'Select Provider',
'nordigen_requisition_subject' => 'Requisition expired, please reauthenticate.',
'nordigen_requisition_body' => 'Access to bank account feeds has expired as set in End User Agreement. <br><br>Please log into Invoice Ninja and re-authenticate with your banks to continue receiving transactions.',
'lang_Lao' => 'Laotien',
'currency_lao_kip' => 'Kip laotien',
'yodlee_regions' => 'Régions : États-Unis, Royaume-Uni, Australie et Inde',
'nordigen_regions' => 'Régions : Europe et Royaume-Uni',
'select_provider' => 'Sélectionnez le fournisseur',
'nordigen_requisition_subject' => 'La demande a expiré, veuillez vous authentifier à nouveau.',
'nordigen_requisition_body' => 'L&#39;accès aux flux des comptes bancaires a expiré comme indiqué dans le Contrat de l&#39;utilisateur final.<br><br> Veuillez vous connecter à Invoice Ninja et vous authentifier à nouveau auprès de vos banques pour continuer à recevoir des transactions.',
'participant' => 'Participant',
'participant_name' => 'Participant name',
'client_unsubscribed' => 'Client unsubscribed from emails.',
'client_unsubscribed_help' => 'Client :client has unsubscribed from your e-mails. The client needs to consent to receive future emails from you.',
'resubscribe' => 'Resubscribe',
'subscribe' => 'Subscribe',
'subscribe_help' => 'You are currently subscribed and will continue to receive email communications.',
'unsubscribe_help' => 'You are currently not subscribed, and therefore, will not receive emails at this time.',
'notification_purchase_order_bounced' => 'We were unable to deliver Purchase Order :invoice to :contact. <br><br> :error',
'notification_purchase_order_bounced_subject' => 'Unable to deliver Purchase Order :invoice',
'show_pdfhtml_on_mobile' => 'Display HTML version of entity when viewing on mobile',
'show_pdfhtml_on_mobile_help' => 'For improved visualization, displays a HTML version of the invoice/quote when viewing on mobile.',
'please_select_an_invoice_or_credit' => 'Please select an invoice or credit',
'mobile_version' => 'Mobile Version',
'participant_name' => 'Nom du participant',
'client_unsubscribed' => 'Client désabonné des e-mails.',
'client_unsubscribed_help' => 'Le client :client s&#39;est désabonné de vos e-mails. Le client doit consentir à recevoir de futurs e-mails de votre part.',
'resubscribe' => 'Réabonnez-vous',
'subscribe' => 'S&#39;abonner',
'subscribe_help' => 'Vous êtes actuellement abonné et continuerez à recevoir des communications par courrier électronique.',
'unsubscribe_help' => 'Vous n&#39;êtes actuellement pas abonné et ne recevrez donc pas d&#39;e-mails pour le moment.',
'notification_purchase_order_bounced' => 'Nous n&#39;avons pas pu livrer le bon de commande :invoice à :contact .<br><br> :error',
'notification_purchase_order_bounced_subject' => 'Impossible de livrer le bon de commande :invoice',
'show_pdfhtml_on_mobile' => 'Afficher la version HTML de l&#39;entité lors de la visualisation sur mobile',
'show_pdfhtml_on_mobile_help' => 'Pour une visualisation améliorée, affiche une version HTML de la facture/devis lors de la visualisation sur mobile.',
'please_select_an_invoice_or_credit' => 'Veuillez sélectionner une facture ou un crédit',
'mobile_version' => 'Version mobile',
'venmo' => 'Venmo',
'my_bank' => 'MyBank',
'pay_later' => 'Pay Later',
'local_domain' => 'Local Domain',
'verify_peer' => 'Verify Peer',
'nordigen_help' => 'Note: connecting an account requires a GoCardless/Nordigen API key',
'ar_detailed' => 'Accounts Receivable Detailed',
'ar_summary' => 'Accounts Receivable Summary',
'client_sales' => 'Client Sales',
'user_sales' => 'User Sales',
'iframe_url' => 'iFrame URL',
'user_unsubscribed' => 'User unsubscribed from emails :link',
'my_bank' => 'Ma banque',
'pay_later' => 'Payer plus tard',
'local_domain' => 'Domaine local',
'verify_peer' => 'Vérifier le pair',
'nordigen_help' => 'Remarque : la connexion d&#39;un compte nécessite une clé API GoCardless/Nordigen',
'ar_detailed' => 'Comptes clients détaillés',
'ar_summary' => 'Sommaire des comptes clients',
'client_sales' => 'Ventes clients',
'user_sales' => 'Ventes aux utilisateurs',
'iframe_url' => 'URL iFrame',
'user_unsubscribed' => 'Utilisateur désabonné des e-mails :link',
'use_available_payments' => 'Utiliser les paiements disponibles',
'test_email_sent' => 'E-mail envoyé avec succès',
'gateway_type' => 'Type de passerelle',
'save_template_body' => 'Souhaitez-vous enregistrer ce mappage dimportation en tant que modèle pour une utilisation future ?',
'save_as_template' => 'Enregistrer le mappage de modèle',
'auto_bill_standard_invoices_help' => 'Auto bill standard invoices on the due date',
'auto_bill_on_help' => 'Auto bill on send date OR due date (recurring invoices)',
'use_available_credits_help' => 'Apply any credit balances to payments prior to charging a payment method',
'use_unapplied_payments' => 'Use unapplied payments',
'use_unapplied_payments_help' => 'Apply any payment balances prior to charging a payment method',
'payment_terms_help' => 'Définit la <b>date d\'échéance de la facture</b> par défaut',
'payment_type_help' => 'Définit le <b>type de paiement manuel<b/> par défaut.',
'quote_valid_until_help' => 'The number of days that the quote is valid for',
'expense_payment_type_help' => 'The default expense payment type to be used',
'paylater' => 'Pay in 4',
'payment_provider' => 'Payment Provider',
);
return $lang;

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