mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-07 18:44:28 -04:00
Merge pull request #30 from M-E-Development-Design/v5-develop
V5 develop
This commit is contained in:
commit
d85f0b98fd
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -8,7 +8,7 @@ assignees: ''
|
||||
---
|
||||
|
||||
<!-- Before posting please check our "Troubleshooting" category in the docs:
|
||||
https://invoiceninja.github.io/docs/self-host-troubleshooting/ -->
|
||||
https://invoiceninja.github.io/en/self-host-troubleshooting/ -->
|
||||
|
||||
## Setup
|
||||
- Version: <!-- i.e. v4.5.25 / v5.0.30 -->
|
||||
|
@ -1 +1 @@
|
||||
5.10.19
|
||||
5.10.24
|
@ -130,9 +130,8 @@ class BaseRule implements RuleInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function shouldCalcTax(): bool
|
||||
{
|
||||
return $this->should_calc_tax;
|
||||
public function shouldCalcTax(): bool {
|
||||
return $this->should_calc_tax && $this->checkIfInvoiceLocked();
|
||||
}
|
||||
/**
|
||||
* Initializes the tax rule for the entity.
|
||||
@ -215,7 +214,7 @@ class BaseRule implements RuleInterface
|
||||
|
||||
$this->invoice->tax_data = $tax_data;
|
||||
|
||||
if(\DB::transactionLevel() == 0) {
|
||||
if(\DB::transactionLevel() == 0 && isset($this->invoice->id)) {
|
||||
|
||||
try {
|
||||
$this->invoice->saveQuietly();
|
||||
@ -400,4 +399,36 @@ class BaseRule implements RuleInterface
|
||||
return ! in_array($iso_3166_2, array_merge($this->eu_country_codes, array_keys($this->region_codes)));
|
||||
}
|
||||
|
||||
private function checkIfInvoiceLocked(): bool
|
||||
{
|
||||
$lock_invoices = $this->client->getSetting('lock_invoices');
|
||||
|
||||
switch ($lock_invoices) {
|
||||
case 'off':
|
||||
return true;
|
||||
case 'when_sent':
|
||||
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
case 'when_paid':
|
||||
if ($this->invoice->status_id == Invoice::STATUS_PAID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
//if now is greater than the end of month the invoice was dated - do not modify
|
||||
case 'end_of_month':
|
||||
if(\Carbon\Carbon::parse($this->invoice->date)->setTimezone($this->invoice->company->timezone()->name)->endOfMonth()->lte(now())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ class Rule extends BaseRule implements RuleInterface
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'MwSt.';
|
||||
|
||||
private string $tax_name;
|
||||
/**
|
||||
* Initializes the rules and builds any required data.
|
||||
*
|
||||
@ -50,6 +52,7 @@ class Rule extends BaseRule implements RuleInterface
|
||||
*/
|
||||
public function init(): self
|
||||
{
|
||||
$this->tax_name = $this->tax_name1;
|
||||
$this->calculateRates();
|
||||
|
||||
return $this;
|
||||
@ -91,6 +94,7 @@ class Rule extends BaseRule implements RuleInterface
|
||||
*/
|
||||
public function reverseTax($item): self
|
||||
{
|
||||
$this->tax_name1 = $this->tax_name;
|
||||
$this->tax_rate1 = 0;
|
||||
|
||||
return $this;
|
||||
@ -103,6 +107,8 @@ class Rule extends BaseRule implements RuleInterface
|
||||
*/
|
||||
public function taxReduced($item): self
|
||||
{
|
||||
|
||||
$this->tax_name1 = $this->tax_name;
|
||||
$this->tax_rate1 = $this->reduced_tax_rate;
|
||||
|
||||
return $this;
|
||||
@ -115,6 +121,8 @@ class Rule extends BaseRule implements RuleInterface
|
||||
*/
|
||||
public function zeroRated($item): self
|
||||
{
|
||||
|
||||
$this->tax_name1 = $this->tax_name;
|
||||
$this->tax_rate1 = 0;
|
||||
|
||||
return $this;
|
||||
@ -142,6 +150,7 @@ class Rule extends BaseRule implements RuleInterface
|
||||
public function taxDigital($item): self
|
||||
{
|
||||
|
||||
$this->tax_name1 = $this->tax_name;
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
|
||||
return $this;
|
||||
@ -155,6 +164,7 @@ class Rule extends BaseRule implements RuleInterface
|
||||
public function taxService($item): self
|
||||
{
|
||||
|
||||
$this->tax_name1 = $this->tax_name;
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
|
||||
return $this;
|
||||
@ -168,6 +178,7 @@ class Rule extends BaseRule implements RuleInterface
|
||||
public function taxShipping($item): self
|
||||
{
|
||||
|
||||
$this->tax_name1 = $this->tax_name;
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
|
||||
return $this;
|
||||
@ -181,6 +192,7 @@ class Rule extends BaseRule implements RuleInterface
|
||||
public function taxPhysical($item): self
|
||||
{
|
||||
|
||||
$this->tax_name1 = $this->tax_name;
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
|
||||
return $this;
|
||||
|
@ -451,6 +451,7 @@ class BaseExport
|
||||
'project' => 'task.project_id',
|
||||
'billable' => 'task.billable',
|
||||
'item_notes' => 'task.item_notes',
|
||||
'time_log' => 'task.time_log',
|
||||
];
|
||||
|
||||
protected array $forced_client_fields = [
|
||||
|
@ -156,7 +156,7 @@ class TaskExport extends BaseExport
|
||||
$entity[$key] = $transformed_entity[$parts[1]];
|
||||
} elseif (array_key_exists($key, $transformed_entity)) {
|
||||
$entity[$key] = $transformed_entity[$key];
|
||||
} elseif (in_array($key, ['task.start_date', 'task.end_date', 'task.duration', 'task.billable', 'task.item_notes'])) {
|
||||
} elseif (in_array($key, ['task.start_date', 'task.end_date', 'task.duration', 'task.billable', 'task.item_notes', 'task.time_log'])) {
|
||||
$entity[$key] = '';
|
||||
} else {
|
||||
$entity[$key] = $this->decorator->transform($key, $task);
|
||||
@ -207,6 +207,9 @@ class TaskExport extends BaseExport
|
||||
$seconds = $task->calcDuration();
|
||||
$entity['task.duration'] = $seconds;
|
||||
$entity['task.duration_words'] = $seconds > 86400 ? CarbonInterval::seconds($seconds)->locale($this->company->locale())->cascade()->forHumans() : now()->startOfDay()->addSeconds($seconds)->format('H:i:s');
|
||||
|
||||
$entity['task.time_log'] = (isset($item[1]) && $item[1] != 0) ? $item[1] - $item[0] : ctrans('texts.is_running');
|
||||
|
||||
}
|
||||
|
||||
if (in_array('task.billable', $this->input['report_keys']) || in_array('billable', $this->input['report_keys'])) {
|
||||
|
@ -98,7 +98,14 @@ class CreditFilters extends QueryFilters
|
||||
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||
->orWhere('email', 'like', '%'.$filter.'%');
|
||||
})
|
||||
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||
->orWhereRaw("
|
||||
JSON_UNQUOTE(JSON_EXTRACT(
|
||||
JSON_ARRAY(
|
||||
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
|
||||
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
|
||||
), '$[*]')
|
||||
) LIKE ?", ['%'.$filter.'%']);
|
||||
// ->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -158,6 +158,18 @@ class ExpenseFilters extends QueryFilters
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
public function categories(string $categories = ''): Builder
|
||||
{
|
||||
$categories_exploded = explode(",", $categories);
|
||||
|
||||
if(empty($categories) || count(array_filter($categories_exploded)) == 0)
|
||||
return $this->builder;
|
||||
|
||||
$categories_keys = $this->transformKeys($categories_exploded);
|
||||
|
||||
return $this->builder->whereIn('category_id', $categories_keys);
|
||||
}
|
||||
|
||||
public function number(string $number = ''): Builder
|
||||
{
|
||||
if (strlen($number) == 0) {
|
||||
|
@ -125,7 +125,14 @@ class InvoiceFilters extends QueryFilters
|
||||
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||
->orWhere('email', 'like', '%'.$filter.'%');
|
||||
})
|
||||
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||
->orWhereRaw("
|
||||
JSON_UNQUOTE(JSON_EXTRACT(
|
||||
JSON_ARRAY(
|
||||
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
|
||||
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
|
||||
), '$[*]')
|
||||
) LIKE ?", ['%'.$filter.'%']);
|
||||
// ->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,14 @@ class PurchaseOrderFilters extends QueryFilters
|
||||
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
||||
->orWhereHas('vendor', function ($q) use ($filter) {
|
||||
$q->where('name', 'like', '%'.$filter.'%');
|
||||
});
|
||||
})
|
||||
->orWhereRaw("
|
||||
JSON_UNQUOTE(JSON_EXTRACT(
|
||||
JSON_ARRAY(
|
||||
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
|
||||
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
|
||||
), '$[*]')
|
||||
) LIKE ?", ['%'.$filter.'%']);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,14 @@ class QuoteFilters extends QueryFilters
|
||||
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||
->orWhere('email', 'like', '%'.$filter.'%');
|
||||
})
|
||||
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||
->orWhereRaw("
|
||||
JSON_UNQUOTE(JSON_EXTRACT(
|
||||
JSON_ARRAY(
|
||||
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
|
||||
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
|
||||
), '$[*]')
|
||||
) LIKE ?", ['%'.$filter.'%']);
|
||||
// ->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,14 @@ class RecurringInvoiceFilters extends QueryFilters
|
||||
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||
->orWhere('email', 'like', '%'.$filter.'%');
|
||||
})
|
||||
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||
->orWhereRaw("
|
||||
JSON_UNQUOTE(JSON_EXTRACT(
|
||||
JSON_ARRAY(
|
||||
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
|
||||
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
|
||||
), '$[*]')
|
||||
) LIKE ?", ['%'.$filter.'%']);
|
||||
//->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,10 @@ class TaskFilters extends QueryFilters
|
||||
$this->builder->whereNull('invoice_id');
|
||||
}
|
||||
|
||||
if (in_array('is_running', $status_parameters)) {
|
||||
$this->builder->where('is_running', true);
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
|
@ -51,9 +51,9 @@ class EmailHistoryController extends BaseController
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
|
||||
$data = SystemLog::where('company_id', $user->company()->id)
|
||||
->where('category_id', SystemLog::CATEGORY_MAIL)
|
||||
->whereJsonContains('log->history->entity', $request->entity)
|
||||
->whereJsonContains('log->history->entity_id', $this->encodePrimaryKey($request->entity_id))
|
||||
->orderBy('id', 'DESC')
|
||||
->cursor()
|
||||
|
@ -40,10 +40,10 @@ class BulkInvoiceRequest extends Request
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
if(\Illuminate\Support\Facades\Cache::has($this->ip()."|".$this->input('action', 0)."|".json_encode($this->input('ids', ''))."|".$user->company()->company_key))
|
||||
if(\Illuminate\Support\Facades\Cache::has($this->ip()."|".$this->input('action', 0)."|".$user->company()->company_key))
|
||||
throw new DuplicatePaymentException('Duplicate request.', 429);
|
||||
|
||||
\Illuminate\Support\Facades\Cache::put(($this->ip()."|".$this->input('action', 0)."|".json_encode($this->input('ids', ''))."|".$user->company()->company_key), true, 1);
|
||||
\Illuminate\Support\Facades\Cache::put(($this->ip()."|".$this->input('action', 0)."|".$user->company()->company_key), true, 1);
|
||||
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ class UpdateTaskRequest extends Request
|
||||
|
||||
}
|
||||
|
||||
if(!isset($input['time_log']) || empty($input['time_log']) || $input['time_log'] == '{}') {
|
||||
if(!isset($input['time_log']) || empty($input['time_log']) || $input['time_log'] == '{}' || $input['time_log'] == '[""]') {
|
||||
$input['time_log'] = json_encode([]);
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,6 @@ class ContactComponent extends Component
|
||||
|
||||
public function render()
|
||||
{
|
||||
\Debugbar::debug($this->attributes->getAttributes() + $this->defaults);
|
||||
return render('gateways.rotessa.components.contact', $this->attributes->getAttributes() + $this->defaults );
|
||||
}
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
|
||||
private function incrementEmailCounter(): void
|
||||
{
|
||||
if(in_array($this->mailer, ['default','mailgun','postmark'])) {
|
||||
if(in_array($this->nmo->settings->email_sending_method, ['default','mailgun','postmark'])) {
|
||||
Cache::increment("email_quota".$this->company->account->key);
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ class AdjustEmailQuota implements ShouldQueue
|
||||
|
||||
/** Use redis pipelines to execute bulk deletes efficiently */
|
||||
$redis = Redis::connection('sentinel-cache');
|
||||
$prefix = config('cache.prefix'). ":email_quota*";
|
||||
$prefix = config('cache.prefix'). "email_quota*";
|
||||
|
||||
$keys = $redis->keys($prefix);
|
||||
|
||||
@ -92,7 +92,7 @@ class AdjustEmailQuota implements ShouldQueue
|
||||
}
|
||||
$keys = null;
|
||||
|
||||
$prefix = config('cache.prefix'). ":throttle_notified*";
|
||||
$prefix = config('cache.prefix'). "throttle_notified*";
|
||||
|
||||
$keys = $redis->keys($prefix);
|
||||
|
||||
|
@ -58,10 +58,6 @@ class EmailPayment implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->company->is_disabled || (!$this->contact?->email ?? false)) {
|
||||
nlog("company disabled - or - contact email not found");
|
||||
return;
|
||||
}
|
||||
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
@ -71,6 +67,11 @@ class EmailPayment implements ShouldQueue
|
||||
$this->contact = $this->payment->client->contacts()->orderBy('is_primary', 'desc')->first();
|
||||
}
|
||||
|
||||
if ($this->company->is_disabled || (!$this->contact?->email ?? false)) {
|
||||
nlog("company disabled - or - contact email not found");
|
||||
return;
|
||||
}
|
||||
|
||||
$this->contact->load('client');
|
||||
|
||||
$email_builder = (new PaymentEmailEngine($this->payment, $this->contact))->build();
|
||||
|
@ -349,7 +349,11 @@ class BillingPortalPurchase extends Component
|
||||
}
|
||||
|
||||
if ((int)$this->price == 0) {
|
||||
|
||||
$this->steps['payment_required'] = false;
|
||||
$this->steps['fetched_payment_methods'] = false;
|
||||
$this->heading_text = ctrans('texts.payment_methods');
|
||||
return $this;
|
||||
} else {
|
||||
// $this->steps['fetched_payment_methods'] = true;
|
||||
}
|
||||
|
@ -262,6 +262,7 @@ class PaymentEmailEngine extends BaseEmailEngine
|
||||
$data['$client.email'] = &$data['$email'];
|
||||
|
||||
$data['$client.balance'] = ['value' => Number::formatMoney($this->client->balance, $this->client), 'label' => ctrans('texts.account_balance')];
|
||||
$data['$client.payment_balance'] = ['value' => Number::formatMoney($this->client->payment_balance, $this->client), 'label' => ctrans('texts.payment_balance_on_file')];
|
||||
$data['$outstanding'] = ['value' => Number::formatMoney($this->client->balance, $this->client), 'label' => ctrans('texts.account_balance')];
|
||||
$data['$client_balance'] = ['value' => Number::formatMoney($this->client->balance, $this->client), 'label' => ctrans('texts.account_balance')];
|
||||
$data['$paid_to_date'] = ['value' => Number::formatMoney($this->client->paid_to_date, $this->client), 'label' => ctrans('texts.paid_to_date')];
|
||||
|
@ -431,7 +431,7 @@ class Invoice extends BaseModel
|
||||
|
||||
public function isPayable(): bool
|
||||
{
|
||||
if($this->is_deleted)
|
||||
if($this->is_deleted || $this->status_id == self::STATUS_PAID)
|
||||
return false;
|
||||
elseif ($this->status_id == self::STATUS_DRAFT && $this->is_deleted == false) {
|
||||
return true;
|
||||
@ -614,17 +614,17 @@ class Invoice extends BaseModel
|
||||
event(new InvoiceWasEmailed($invitation, $invitation->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null), $template));
|
||||
break;
|
||||
case 'reminder1':
|
||||
event(new InvoiceReminderWasEmailed($invitation, $invitation->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null), $template));
|
||||
event(new InvoiceReminderWasEmailed($invitation, $invitation->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null), $reminder_template));
|
||||
break;
|
||||
case 'reminder2':
|
||||
event(new InvoiceReminderWasEmailed($invitation, $invitation->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null), $template));
|
||||
event(new InvoiceReminderWasEmailed($invitation, $invitation->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null), $reminder_template));
|
||||
break;
|
||||
case 'reminder3':
|
||||
event(new InvoiceReminderWasEmailed($invitation, $invitation->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null), $template));
|
||||
event(new InvoiceReminderWasEmailed($invitation, $invitation->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null), $reminder_template));
|
||||
break;
|
||||
case 'reminder_endless':
|
||||
case 'endless_reminder':
|
||||
event(new InvoiceReminderWasEmailed($invitation, $invitation->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null), $template));
|
||||
event(new InvoiceReminderWasEmailed($invitation, $invitation->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null), $reminder_template));
|
||||
break;
|
||||
case 'custom1':
|
||||
case 'custom2':
|
||||
|
@ -232,7 +232,7 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
*
|
||||
* @param ClientGatewayToken $cgt The client gateway token object
|
||||
* @param PaymentHash $payment_hash The Payment hash containing the payment meta data
|
||||
* @return void The payment response
|
||||
* @return ?Payment|bool The payment response
|
||||
*/
|
||||
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
|
||||
{
|
||||
@ -305,7 +305,7 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
public function createPayment($data, $status = Payment::STATUS_COMPLETED): Payment
|
||||
{
|
||||
if (in_array($status, [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING])) {
|
||||
$this->confirmGatewayFee();
|
||||
$this->confirmGatewayFee($data);
|
||||
}
|
||||
|
||||
/*Never create a payment with a duplicate transaction reference*/
|
||||
@ -388,10 +388,9 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
*
|
||||
* @return void Success/Failure
|
||||
*/
|
||||
public function confirmGatewayFee(): void
|
||||
public function confirmGatewayFee($data = []): void
|
||||
{
|
||||
/*Payment invoices*/
|
||||
$payment_invoices = $this->payment_hash->invoices();
|
||||
nlog("confirming gateway fee");
|
||||
|
||||
/*Fee charged at gateway*/
|
||||
$fee_total = $this->payment_hash->fee_total;
|
||||
@ -399,21 +398,16 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
if(!$fee_total || $fee_total == 0)
|
||||
return;
|
||||
|
||||
$invoices = Invoice::query()
|
||||
->whereIn('id', $this->transformKeys(array_column($payment_invoices, 'invoice_id')))
|
||||
->whereJsonContains('line_items', ['type_id' => '3'])
|
||||
->withTrashed();
|
||||
$invoice = $this->payment_hash->fee_invoice;
|
||||
|
||||
if($invoices->count() == 0){
|
||||
$fee_count = collect($invoice->line_items)
|
||||
->whereIn('type_id', ['3','4'])
|
||||
->where('gross_line_total', $fee_total)
|
||||
->count();
|
||||
|
||||
$invoice = Invoice::query()
|
||||
->whereIn('id', $this->transformKeys(array_column($payment_invoices, 'invoice_id')))
|
||||
->orderBy('id','desc')
|
||||
->withTrashed()
|
||||
->first();
|
||||
if($invoice && $fee_count == 0){
|
||||
|
||||
if(!$invoice)
|
||||
return;
|
||||
nlog("apparently no fee, so injecting here!");
|
||||
|
||||
$balance = $invoice->balance;
|
||||
|
||||
@ -432,6 +426,16 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
$invoice_items = (array) $invoice->line_items;
|
||||
$invoice_items[] = $invoice_item;
|
||||
|
||||
if (isset($data['gateway_type_id']) && $fees_and_limits = $this->company_gateway->getFeesAndLimits($data['gateway_type_id'])) {
|
||||
$invoice_item->tax_rate1 = $fees_and_limits->fee_tax_rate1;
|
||||
$invoice_item->tax_name1 = $fees_and_limits->fee_tax_name1;
|
||||
$invoice_item->tax_rate2 = $fees_and_limits->fee_tax_rate2;
|
||||
$invoice_item->tax_name2 = $fees_and_limits->fee_tax_name2;
|
||||
$invoice_item->tax_rate3 = $fees_and_limits->fee_tax_rate3;
|
||||
$invoice_item->tax_name3 = $fees_and_limits->fee_tax_name3;
|
||||
$invoice_item->tax_id = (string)\App\Models\Product::PRODUCT_TYPE_OVERRIDE_TAX;
|
||||
}
|
||||
|
||||
$invoice->line_items = $invoice_items;
|
||||
|
||||
/**Refresh Invoice values*/
|
||||
@ -452,15 +456,10 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
}
|
||||
else {
|
||||
|
||||
$invoices
|
||||
->cursor()
|
||||
->each(function ($i){
|
||||
$i->service()->toggleFeesPaid()->save();
|
||||
});
|
||||
$invoice->service()->toggleFeesPaid()->save();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -472,11 +471,8 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
*/
|
||||
public function unWindGatewayFees(PaymentHash $payment_hash)
|
||||
{
|
||||
$invoices = Invoice::query()->whereIn('id', $this->transformKeys(array_column($payment_hash->invoices(), 'invoice_id')))->withTrashed()->get();
|
||||
|
||||
$invoices->each(function ($invoice) {
|
||||
$invoice->service()->removeUnpaidGatewayFees();
|
||||
});
|
||||
if($payment_hash->fee_invoice)
|
||||
$payment_hash->fee_invoice->service()->removeUnpaidGatewayFees();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,7 +241,6 @@ class BraintreePaymentDriver extends BaseDriver
|
||||
]);
|
||||
|
||||
if ($result->success) {
|
||||
$this->confirmGatewayFee();
|
||||
|
||||
$data = [
|
||||
'payment_type' => PaymentType::parseCardType(strtolower($result->transaction->creditCard['cardType'])),
|
||||
@ -250,6 +249,8 @@ class BraintreePaymentDriver extends BaseDriver
|
||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||
];
|
||||
|
||||
$this->confirmGatewayFee($data);
|
||||
|
||||
$payment = $this->createPayment($data, Payment::STATUS_COMPLETED);
|
||||
|
||||
SystemLogger::dispatch(
|
||||
|
@ -242,7 +242,12 @@ class CreditCard implements MethodInterface
|
||||
}
|
||||
|
||||
if ($response['status'] == 'Pending') {
|
||||
$this->checkout->confirmGatewayFee();
|
||||
|
||||
$data = [
|
||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||
];
|
||||
|
||||
$this->checkout->confirmGatewayFee($data);
|
||||
|
||||
return $this->processPendingPayment($response);
|
||||
}
|
||||
|
@ -406,15 +406,17 @@ class CheckoutComPaymentDriver extends BaseDriver
|
||||
$response = $this->gateway->getPaymentsClient()->requestPayment($paymentRequest);
|
||||
|
||||
if ($response['status'] == 'Authorized') {
|
||||
$this->confirmGatewayFee($request);
|
||||
|
||||
$data = [
|
||||
'payment_method' => $response['source']['id'],
|
||||
'payment_type' => PaymentType::parseCardType(strtolower($response['source']['scheme'])),
|
||||
'amount' => $amount,
|
||||
'transaction_reference' => $response['id'],
|
||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||
];
|
||||
|
||||
$this->confirmGatewayFee($data);
|
||||
|
||||
$payment = $this->createPayment($data, Payment::STATUS_COMPLETED);
|
||||
|
||||
SystemLogger::dispatch(
|
||||
|
@ -17,6 +17,54 @@ use App\Models\Company;
|
||||
|
||||
class ForteCustomerFactory
|
||||
{
|
||||
|
||||
public function convertToForte(Client $client): array
|
||||
{
|
||||
|
||||
return [
|
||||
"first_name" => $client->present()->first_name(),
|
||||
"last_name" => $client->present()->last_name(),
|
||||
"company_name" => $client->present()->name(),
|
||||
"addresses" => [
|
||||
[
|
||||
"label" => "Billing Address",
|
||||
"first_name" => $client->present()->first_name(),
|
||||
"last_name" => $client->present()->last_name(),
|
||||
"company_name" => $client->present()->name(),
|
||||
"phone" => $client->present()->phone(),
|
||||
"email" => $client->present()->email(),
|
||||
"shipping_address_type" => "commercial",
|
||||
"address_type" => "default_shipping",
|
||||
"physical_address" => [
|
||||
"street_line1" => $client->address2,
|
||||
"street_line2" => $client->address1,
|
||||
"locality" => $client->city,
|
||||
"region" => $client->state,
|
||||
"postal_code" => $client->postal_code
|
||||
]
|
||||
],
|
||||
// [
|
||||
// "label" => "Brown Billing",
|
||||
// "first_name" => "Emmett",
|
||||
// "last_name" => "Brown",
|
||||
// "company_name" => "Brown Associates",
|
||||
// "phone" => "444-444-4444",
|
||||
// "email" => "e.brown@forte.net",
|
||||
// "shipping_address_type" => "commercial",
|
||||
// "address_type" => "default_billing",
|
||||
// "physical_address" => [
|
||||
// "street_line1" => "500 Delorean Dr",
|
||||
// "street_line2" => "Suite 200",
|
||||
// "locality" => "Hill Valley",
|
||||
// "region" => "CA",
|
||||
// "postal_code" => "95420"
|
||||
// ]
|
||||
// ]
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
public function convertToNinja(array $customer, Company $company): array
|
||||
{
|
||||
return
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
namespace App\PaymentDrivers\Forte;
|
||||
|
||||
use App\Exceptions\PaymentFailed;
|
||||
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Models\GatewayType;
|
||||
@ -59,22 +60,99 @@ class CreditCard
|
||||
|
||||
public function authorizeResponse($request)
|
||||
{
|
||||
$cst = $this->forte->findOrCreateCustomer();
|
||||
|
||||
$data = [
|
||||
"label" => $request->card_holders_name." " .$request->card_type,
|
||||
"notes" => $request->card_holders_name." " .$request->card_type,
|
||||
"card" => [
|
||||
"one_time_token" => $request->one_time_token,
|
||||
"name_on_card" => $request->card_holders_name
|
||||
],
|
||||
];
|
||||
|
||||
$response = $this->forte->stubRequest()
|
||||
->post("{$this->forte->baseUri()}/organizations/{$this->forte->getOrganisationId()}/locations/{$this->forte->getLocationId()}/customers/{$cst}/paymethods", $data);
|
||||
|
||||
if($response->successful()){
|
||||
|
||||
$token = $response->object();
|
||||
|
||||
$payment_meta = new \stdClass();
|
||||
$payment_meta->exp_month = (string) $request->expire_month;
|
||||
$payment_meta->exp_year = (string) $request->expire_year;
|
||||
$payment_meta->brand = (string) $request->card_type;
|
||||
$payment_meta->brand = (string) $request->card_brand;
|
||||
$payment_meta->last4 = (string) $request->last_4;
|
||||
$payment_meta->type = GatewayType::CREDIT_CARD;
|
||||
|
||||
$data = [
|
||||
'payment_meta' => $payment_meta,
|
||||
'token' => $request->one_time_token,
|
||||
'token' => $token->paymethod_token,
|
||||
'payment_method_id' => $request->payment_method_id,
|
||||
];
|
||||
|
||||
$this->forte->storeGatewayToken($data);
|
||||
$this->forte->storeGatewayToken($data, ['gateway_customer_reference' => $cst]);
|
||||
|
||||
return redirect()->route('client.payment_methods.index')->withSuccess('Payment Method added.');
|
||||
|
||||
}
|
||||
|
||||
$error = $response->object();
|
||||
$message = [
|
||||
'server_message' => $error->response->response_desc,
|
||||
'server_response' => $response->json(),
|
||||
'data' => $data,
|
||||
];
|
||||
|
||||
SystemLogger::dispatch(
|
||||
$message,
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
SystemLog::TYPE_FORTE,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
||||
throw new \App\Exceptions\PaymentFailed("Unable to store payment method: {$error->response->response_desc}", 400);
|
||||
|
||||
}
|
||||
|
||||
private function createPaymentToken($request)
|
||||
{
|
||||
$cst = $this->forte->findOrCreateCustomer();
|
||||
|
||||
$data = [
|
||||
"label" => $this->forte->client->present()->name(),
|
||||
"notes" => $this->forte->client->present()->name(),
|
||||
"card" => [
|
||||
"one_time_token" => $request->payment_token,
|
||||
"name_on_card" => $this->forte->client->present()->first_name(). " ". $this->forte->client->present()->last_name()
|
||||
],
|
||||
];
|
||||
|
||||
$response = $this->forte->stubRequest()
|
||||
->post("{$this->forte->baseUri()}/organizations/{$this->forte->getOrganisationId()}/locations/{$this->forte->getLocationId()}/customers/{$cst}/paymethods", $data);
|
||||
|
||||
if($response->successful()){
|
||||
|
||||
$token = $response->object();
|
||||
|
||||
$payment_meta = new \stdClass();
|
||||
$payment_meta->exp_month = (string) $request->expire_month;
|
||||
$payment_meta->exp_year = (string) $request->expire_year;
|
||||
$payment_meta->brand = (string) $request->card_brand;
|
||||
$payment_meta->last4 = (string) $request->last_4;
|
||||
$payment_meta->type = GatewayType::CREDIT_CARD;
|
||||
|
||||
$data = [
|
||||
'payment_meta' => $payment_meta,
|
||||
'token' => $token->paymethod_token,
|
||||
'payment_method_id' => $request->payment_method_id,
|
||||
];
|
||||
|
||||
$this->forte->storeGatewayToken($data, ['gateway_customer_reference' => $cst]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function paymentView(array $data)
|
||||
@ -88,7 +166,20 @@ class CreditCard
|
||||
|
||||
public function paymentResponse(PaymentResponseRequest $request)
|
||||
{
|
||||
|
||||
$payment_hash = PaymentHash::where('hash', $request->input('payment_hash'))->firstOrFail();
|
||||
|
||||
if(strlen($request->token ?? '') > 3){
|
||||
|
||||
|
||||
$cgt = \App\Models\ClientGatewayToken::find($this->decodePrimaryKey($request->token));
|
||||
|
||||
$payment = $this->forte->tokenBilling($cgt, $payment_hash);
|
||||
|
||||
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
|
||||
|
||||
}
|
||||
|
||||
$amount_with_fee = $payment_hash->data->total->amount_with_fee;
|
||||
$invoice_totals = $payment_hash->data->total->invoice_totals;
|
||||
$fee_total = null;
|
||||
@ -126,8 +217,8 @@ class CreditCard
|
||||
"authorization_amount":'.$amount_with_fee.',
|
||||
"service_fee_amount":'.$fee_total.',
|
||||
"billing_address":{
|
||||
"first_name":"'.$this->forte->client->name.'",
|
||||
"last_name":"'.$this->forte->client->name.'"
|
||||
"first_name":"'.$this->forte->client->present()->first_name().'",
|
||||
"last_name":"'.$this->forte->client->present()->last_name().'"
|
||||
},
|
||||
"card":{
|
||||
"one_time_token":"'.$request->payment_token.'"
|
||||
@ -146,6 +237,7 @@ class CreditCard
|
||||
curl_close($curl);
|
||||
|
||||
$response = json_decode($response);
|
||||
|
||||
} catch (\Throwable $th) {
|
||||
throw $th;
|
||||
}
|
||||
@ -187,7 +279,11 @@ class CreditCard
|
||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||
];
|
||||
$payment = $this->forte->createPayment($data, Payment::STATUS_COMPLETED);
|
||||
// return redirect('client/invoices')->withSuccess('Invoice paid.');
|
||||
|
||||
if($request->store_card) {
|
||||
$this->createPaymentToken($request);
|
||||
}
|
||||
|
||||
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace App\PaymentDrivers;
|
||||
|
||||
use App\Exceptions\PaymentFailed;
|
||||
use App\Models\Payment;
|
||||
use App\Models\SystemLog;
|
||||
use App\Models\GatewayType;
|
||||
@ -224,7 +225,7 @@ class FortePaymentDriver extends BaseDriver
|
||||
return $forte_base_uri;
|
||||
}
|
||||
|
||||
private function getOrganisationId(): string
|
||||
public function getOrganisationId(): string
|
||||
{
|
||||
return $this->company_gateway->getConfigField('organizationId');
|
||||
}
|
||||
@ -247,12 +248,90 @@ class FortePaymentDriver extends BaseDriver
|
||||
|
||||
private function getClient(?string $email)
|
||||
{
|
||||
if(!$email)
|
||||
return false;
|
||||
|
||||
return ClientContact::query()
|
||||
->where('company_id', $this->company_gateway->company_id)
|
||||
->where('email', $email)
|
||||
->first();
|
||||
}
|
||||
|
||||
public function tokenBilling(\App\Models\ClientGatewayToken $cgt, \App\Models\PaymentHash $payment_hash)
|
||||
{
|
||||
|
||||
$amount_with_fee = $payment_hash->data->amount_with_fee;
|
||||
$fee_total = $payment_hash->fee_total;
|
||||
|
||||
$data =
|
||||
[
|
||||
"action" => "sale",
|
||||
"authorization_amount" => $amount_with_fee,
|
||||
"paymethod_token" => $cgt->token,
|
||||
"billing_address" => [
|
||||
"first_name" => $this->client->present()->first_name(),
|
||||
"last_name" => $this->client->present()->last_name()
|
||||
],
|
||||
];
|
||||
|
||||
if($fee_total > 0){
|
||||
$data["service_fee_amount"] = $fee_total;
|
||||
}
|
||||
|
||||
$response = $this->stubRequest()
|
||||
->post("{$this->baseUri()}/organizations/{$this->getOrganisationId()}/locations/{$this->getLocationId()}/transactions", $data);
|
||||
|
||||
$forte_response = $response->object();
|
||||
|
||||
if($response->successful()){
|
||||
|
||||
$data = [
|
||||
'payment_method' => $cgt->gateway_type_id,
|
||||
'payment_type' => $cgt->gateway_type_id == 2 ? \App\Models\PaymentType::ACH : \App\Models\PaymentType::CREDIT_CARD_OTHER,
|
||||
'amount' => $payment_hash->data->amount_with_fee,
|
||||
'transaction_reference' => $forte_response->transaction_id,
|
||||
'gateway_type_id' => $cgt->gateway_type_id,
|
||||
];
|
||||
|
||||
$payment = $this->createPayment($data, Payment::STATUS_COMPLETED);
|
||||
|
||||
$message = [
|
||||
'server_message' => $forte_response->response->response_desc,
|
||||
'server_response' => $response->json(),
|
||||
'data' => $data,
|
||||
];
|
||||
|
||||
SystemLogger::dispatch(
|
||||
$message,
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_SUCCESS,
|
||||
SystemLog::TYPE_FORTE,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
||||
return $payment;
|
||||
}
|
||||
|
||||
$message = [
|
||||
'server_message' => $forte_response->response->response_desc,
|
||||
'server_response' => $response->json(),
|
||||
'data' => $data,
|
||||
];
|
||||
|
||||
SystemLogger::dispatch(
|
||||
$message,
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
SystemLog::TYPE_FORTE,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
||||
throw new PaymentFailed($forte_response->response->response_desc, 500);
|
||||
|
||||
}
|
||||
|
||||
public function getLocation()
|
||||
{
|
||||
|
||||
@ -264,6 +343,8 @@ class FortePaymentDriver extends BaseDriver
|
||||
return $response->json();
|
||||
}
|
||||
|
||||
// return $response->body();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -297,6 +378,43 @@ class FortePaymentDriver extends BaseDriver
|
||||
|
||||
}
|
||||
|
||||
public function findOrCreateCustomer()
|
||||
{
|
||||
|
||||
$client_gateway_token = \App\Models\ClientGatewayToken::query()
|
||||
->where('client_id', $this->client->id)
|
||||
->where('company_gateway_id', $this->company_gateway->id)
|
||||
->whereNotLike('token', 'ott_%')
|
||||
->first();
|
||||
|
||||
if($client_gateway_token){
|
||||
return $client_gateway_token->gateway_customer_reference;
|
||||
}
|
||||
else {
|
||||
|
||||
$factory = new ForteCustomerFactory();
|
||||
$data = $factory->convertToForte($this->client);
|
||||
|
||||
$response = $this->stubRequest()
|
||||
->post("{$this->baseUri()}/organizations/{$this->getOrganisationId()}/locations/{$this->getLocationId()}/customers/", $data);
|
||||
|
||||
|
||||
//create customer
|
||||
if($response->successful()){
|
||||
$customer = $response->object();
|
||||
nlog($customer);
|
||||
return $customer->customer_token;
|
||||
}
|
||||
|
||||
nlog($response->body());
|
||||
|
||||
throw new PaymentFailed("Unable to create customer in Forte", 400);
|
||||
|
||||
//@todo add syslog here
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function importCustomers()
|
||||
{
|
||||
|
||||
|
@ -165,7 +165,6 @@ class GoCardlessPaymentDriver extends BaseDriver
|
||||
]);
|
||||
|
||||
if (in_array($payment->status, ['submitted', 'pending_submission'])) {
|
||||
$this->confirmGatewayFee();
|
||||
|
||||
$data = [
|
||||
'payment_method' => $cgt->hashed_id,
|
||||
@ -175,6 +174,8 @@ class GoCardlessPaymentDriver extends BaseDriver
|
||||
'gateway_type_id' => GatewayType::BANK_TRANSFER,
|
||||
];
|
||||
|
||||
$this->confirmGatewayFee($data);
|
||||
|
||||
$payment = $this->createPayment($data, Payment::STATUS_PENDING);
|
||||
|
||||
SystemLogger::dispatch(
|
||||
|
@ -171,7 +171,7 @@ class MolliePaymentDriver extends BaseDriver
|
||||
];
|
||||
} catch (ApiException $e) {
|
||||
SystemLogger::dispatch(
|
||||
['server_response' => $refund, 'data' => request()->all()],
|
||||
['server_response' => $e->getMessage(), 'data' => request()->all()],
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
SystemLog::TYPE_MOLLIE,
|
||||
@ -223,7 +223,7 @@ class MolliePaymentDriver extends BaseDriver
|
||||
]);
|
||||
|
||||
if ($payment->status === 'paid') {
|
||||
$this->confirmGatewayFee($request);
|
||||
|
||||
|
||||
$data = [
|
||||
'payment_method' => $cgt->token,
|
||||
@ -233,6 +233,8 @@ class MolliePaymentDriver extends BaseDriver
|
||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||
];
|
||||
|
||||
$this->confirmGatewayFee($data);
|
||||
|
||||
$payment = $this->createPayment($data, Payment::STATUS_COMPLETED);
|
||||
|
||||
SystemLogger::dispatch(
|
||||
@ -284,7 +286,7 @@ class MolliePaymentDriver extends BaseDriver
|
||||
public function processWebhookRequest(PaymentWebhookRequest $request)
|
||||
{
|
||||
// Allow app to catch up with webhook request.
|
||||
sleep(2);
|
||||
sleep(4);
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'id' => ['required', 'starts_with:tr'],
|
||||
@ -335,6 +337,8 @@ class MolliePaymentDriver extends BaseDriver
|
||||
'transaction_reference' => $payment->id,
|
||||
];
|
||||
|
||||
$this->confirmGatewayFee($data);
|
||||
|
||||
$record = $this->createPayment(
|
||||
$data,
|
||||
$codes[$payment->status]
|
||||
|
@ -115,10 +115,9 @@ class PayPalBasePaymentDriver extends BaseDriver
|
||||
|
||||
$this->api_endpoint_url = $this->company_gateway->getConfigField('testMode') ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
|
||||
|
||||
if(\App\Utils\Ninja::isHosted()) {
|
||||
if(\App\Utils\Ninja::isHosted() && $this->company_gateway->gateway_key != '80af24a6a691230bbec33e930ab40665') {
|
||||
$secret = config('ninja.paypal.secret');
|
||||
$client_id = config('ninja.paypal.client_id');
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -100,7 +100,16 @@ class PaymentMethod implements MethodInterface
|
||||
|
||||
$customer = array_merge(['address' => $request->only('address_1','address_2','city','postal_code','province_code','country'), 'custom_identifier' => $request->input('custom_identifier') ], $request->all());
|
||||
|
||||
try{
|
||||
$this->rotessa->findOrCreateCustomer($customer);
|
||||
}
|
||||
catch(\Exception $e){
|
||||
|
||||
$message = json_decode($e->getMessage(), true);
|
||||
|
||||
return redirect()->route('client.payment_methods.index')->withErrors(array_values($message['errors']));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('client.payment_methods.index')->withMessage(ctrans('texts.payment_method_added'));
|
||||
|
||||
|
@ -202,7 +202,6 @@ class RotessaPaymentDriver extends BaseDriver
|
||||
|
||||
public function findOrCreateCustomer(array $data)
|
||||
{
|
||||
nlog($data);
|
||||
|
||||
$result = null;
|
||||
try {
|
||||
@ -219,7 +218,6 @@ class RotessaPaymentDriver extends BaseDriver
|
||||
|
||||
if(!isset($data['id'])) {
|
||||
|
||||
nlog("no id, lets goo");
|
||||
$result = $this->gatewayRequest('post', 'customers', $data);
|
||||
|
||||
if($result->failed())
|
||||
@ -252,9 +250,16 @@ class RotessaPaymentDriver extends BaseDriver
|
||||
'code' => 500
|
||||
];
|
||||
|
||||
SystemLogger::dispatch(['server_response' => is_null($result) ? '' : $result->getMessage(), 'data' => $data], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, 880 , $this->client, $this->company_gateway->company);
|
||||
SystemLogger::dispatch(['server_response' => $data, 'data' => []], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, 880 , $this->client, $this->company_gateway->company);
|
||||
|
||||
throw $th;
|
||||
try{
|
||||
$errors = explode("422:", $th->getMessage())[1];
|
||||
}
|
||||
catch(\Exception){
|
||||
$errors = 'Unknown error occured';
|
||||
}
|
||||
|
||||
throw new \Exception($errors, $th->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ class BaseRepository
|
||||
$className = $this->getEventClass($entity, 'Archived');
|
||||
|
||||
if (class_exists($className)) {
|
||||
event(new $className($entity, $entity->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
event(new $className($entity, $entity->company, Ninja::eventVars(auth()->guard('api')->user() ? auth()->guard('api')->user()->id : null)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ class BaseRepository
|
||||
$className = $this->getEventClass($entity, 'Restored');
|
||||
|
||||
if (class_exists($className)) {
|
||||
event(new $className($entity, $fromDeleted, $entity->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
event(new $className($entity, $fromDeleted, $entity->company, Ninja::eventVars(auth()->guard('api')->user() ? auth()->guard('api')->user()->id : null)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ class BaseRepository
|
||||
$className = $this->getEventClass($entity, 'Deleted');
|
||||
|
||||
if (class_exists($className) && !($entity instanceof Company)) {
|
||||
event(new $className($entity, $entity->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
event(new $className($entity, $entity->company, Ninja::eventVars(auth()->guard('api')->user() ? auth()->guard('api')->user()->id : null)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,6 +147,10 @@ class TaskRepository extends BaseRepository
|
||||
|
||||
$task->calculated_start_date = $this->harvestStartDate($time_log, $task);
|
||||
|
||||
if(isset(end($time_log)[1])){
|
||||
$task->is_running = end($time_log)[1] == 0;
|
||||
}
|
||||
|
||||
$task->time_log = json_encode($time_log);
|
||||
|
||||
$task->saveQuietly();
|
||||
@ -259,7 +263,7 @@ class TaskRepository extends BaseRepository
|
||||
|
||||
$log = array_merge($log, [$new]);
|
||||
$task->time_log = json_encode($log);
|
||||
|
||||
$task->is_running = true;
|
||||
$task->saveQuietly();
|
||||
}
|
||||
|
||||
@ -303,6 +307,7 @@ class TaskRepository extends BaseRepository
|
||||
$log = array_merge($log, [$last]);//check at this point, it may be prepending here.
|
||||
|
||||
$task->time_log = json_encode($log);
|
||||
$task->is_running = false;
|
||||
$task->saveQuietly();
|
||||
}
|
||||
|
||||
|
@ -137,24 +137,29 @@ class Storecove {
|
||||
|
||||
}
|
||||
|
||||
public function sendDocument($document)
|
||||
public function sendDocument(string $document, int $routing_id, array $override_payload = [])
|
||||
{
|
||||
|
||||
$payload = [
|
||||
"legalEntityId"=> 290868,
|
||||
"legalEntityId" => $routing_id,
|
||||
"idempotencyGuid"=> \Illuminate\Support\Str::uuid(),
|
||||
"routing" => [
|
||||
"eIdentifiers" => [],
|
||||
"emails" => ["david@invoiceninja.com"]
|
||||
],
|
||||
"document"=> [
|
||||
'documentType' => 'invoice',
|
||||
"rawDocumentData"=> [
|
||||
|
||||
],
|
||||
];
|
||||
|
||||
$payload = array_merge($payload, $override_payload);
|
||||
|
||||
|
||||
$payload['document']['documentType'] = 'invoice';
|
||||
$payload['document']["rawDocumentData"] = [
|
||||
"document" => base64_encode($document),
|
||||
"parse" => true,
|
||||
"parseStrategy"=> "ubl",
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$uri = "document_submissions";
|
||||
|
@ -13,22 +13,25 @@ namespace App\Services\EDocument\Standards;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use App\Helpers\Invoice\Taxer;
|
||||
use App\Services\AbstractService;
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use InvoiceNinja\EInvoice\EInvoice;
|
||||
use App\Utils\Traits\NumberFormatter;
|
||||
use App\Helpers\Invoice\InvoiceSumInclusive;
|
||||
use App\Helpers\Invoice\Taxer;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PaymentMeans;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\ItemType\Item;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyType\Party;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PriceType\Price;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\IdentifierType\ID;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AddressType\Address;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\ContactType\Contact;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\CountryType\Country;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyIdentification;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\Party as PeppolParty;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxTotalType\TaxTotal;
|
||||
use App\Services\EDocument\Standards\Settings\PropertyResolver;
|
||||
use App\Utils\Traits\NumberFormatter;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\PriceAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyNameType\PartyName;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxSchemeType\TaxScheme;
|
||||
@ -42,14 +45,13 @@ use InvoiceNinja\EInvoice\Models\Peppol\TaxScheme as PeppolTaxScheme;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxExclusiveAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxInclusiveAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\LineExtensionAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\OrderReferenceType\OrderReference;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\MonetaryTotalType\LegalMonetaryTotal;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxCategoryType\ClassifiedTaxCategory;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\CustomerPartyType\AccountingCustomerParty;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\SupplierPartyType\AccountingSupplierParty;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\FinancialAccountType\PayeeFinancialAccount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\IdentifierType\ID;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\Party as PeppolParty;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyIdentification;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\IdentifierType\CustomerAssignedAccountID;
|
||||
|
||||
class Peppol extends AbstractService
|
||||
{
|
||||
@ -57,6 +59,12 @@ class Peppol extends AbstractService
|
||||
use NumberFormatter;
|
||||
|
||||
/**
|
||||
* Assumptions:
|
||||
*
|
||||
* Line Item Taxes Only
|
||||
* Exclusive Taxes
|
||||
*
|
||||
*
|
||||
* used as a proxy for
|
||||
* the schemeID of partyidentification
|
||||
* property - for Storecove only:
|
||||
@ -82,7 +90,7 @@ class Peppol extends AbstractService
|
||||
'NO' => 'VAT',
|
||||
'AD' => 'VAT',
|
||||
'AL' => 'VAT',
|
||||
'AT' => 'VAT',
|
||||
'AT' => 'VAT', //Tested - Routing GOV + Business
|
||||
'BA' => 'VAT',
|
||||
'BE' => 'VAT',
|
||||
'BG' => 'VAT',
|
||||
@ -94,12 +102,12 @@ class Peppol extends AbstractService
|
||||
'SA' => 'TIN', //South Africa
|
||||
'CY' => 'VAT',
|
||||
'CZ' => 'VAT',
|
||||
'DE' => 'VAT', //tested - requires Payment Means to be defined.
|
||||
'DE' => 'VAT', //tested - Requires Payment Means to be defined.
|
||||
'DK' => 'ERST',
|
||||
'EE' => 'VAT',
|
||||
'ES' => 'VAT',
|
||||
'ES' => 'VAT', //tested - B2G pending
|
||||
'FI' => 'VAT',
|
||||
'FR' => 'VAT',
|
||||
'FR' => 'VAT', //tested - Need to ensure Siren/Siret routing
|
||||
'GR' => 'VAT',
|
||||
'HR' => 'VAT',
|
||||
'HU' => 'VAT',
|
||||
@ -147,11 +155,96 @@ class Peppol extends AbstractService
|
||||
"896" => "Debit note related to self-billed invoice"
|
||||
];
|
||||
|
||||
// 0 1 2 3
|
||||
// ["Country" => ["B2X","Legal","Tax","Routing"],
|
||||
private array $routing_rules = [
|
||||
"US" => ["B","DUNS, GLN, LEI","US:EIN, US:SSN","DUNS, GLN, LEI"],
|
||||
"CA" => ["B","CA:CBN","","CA:CBN"],
|
||||
"MX" => ["B","MX:RFC","","MX:RFC"],
|
||||
"AU" => ["B+G","AU:ABN","","AU:ABN"],
|
||||
"NZ" => ["B+G","GLN","NZ:GST","GLN"],
|
||||
"CH" => ["B+G","CH:UIDB","CH:VAT","CH:UIDB"],
|
||||
"IS" => ["B+G","IS:KTNR","IS:VAT","IS:KTNR"],
|
||||
"LI" => ["B+G","","LI:VAT","LI:VAT"],
|
||||
"NO" => ["B+G","NO:ORG","NO:VAT","NO:ORG"],
|
||||
"AD" => ["B+G","","AD:VAT","AD:VAT"],
|
||||
"AL" => ["B+G","","AL:VAT","AL:VAT"],
|
||||
"AT" => [
|
||||
["G","AT:GOV","","9915:b"],
|
||||
["B","","AT:VAT","AT:VAT"],
|
||||
],
|
||||
"BA" => ["B+G","","BA:VAT","BA:VAT"],
|
||||
"BE" => ["B+G","BE:EN","BE:VAT","BE:EN"],
|
||||
"BG" => ["B+G","","BG:VAT","BG:VAT"],
|
||||
"CY" => ["B+G","","CY:VAT","CY:VAT"],
|
||||
"CZ" => ["B+G","","CZ:VAT","CZ:VAT"],
|
||||
"DE" => [
|
||||
["G","DE:LWID","","DE:LWID"],
|
||||
["B","","DE:VAT","DE:VAT"],
|
||||
],
|
||||
"DK" => ["B+G","DK:DIGST","DK:ERST","DK:DIGST"],
|
||||
"EE" => ["B+G","EE:CC","EE:VAT","EE:CC"],
|
||||
"ES" => ["B","","ES:VAT","ES:VAT"],
|
||||
"FI" => ["B+G","FI:OVT","FI:VAT","FI:OVT"],
|
||||
"FR" => [
|
||||
["G","FR:SIRET + customerAssignedAccountIdValue","","0009:11000201100044"],
|
||||
["B","FR:SIRENE or FR:SIRET","FR:VAT","FR:SIRENE or FR:SIRET"],
|
||||
],
|
||||
"GR" => ["B+G","","GR:VAT","GR:VAT"],
|
||||
"HR" => ["B+G","","HR:VAT","HR:VAT"],
|
||||
"HU" => ["B+G","","HU:VAT","HU:VAT"],
|
||||
"IE" => ["B+G","","IE:VAT","IE:VAT"],
|
||||
"IT" => [
|
||||
["G (Peppol)","","IT:IVA","IT:CUUO"],
|
||||
["B (SDI)","","IT:CF and/or IT:IVA","IT:CUUO"],
|
||||
["C (SDI)","","IT:CF","Email"],
|
||||
["G (SDI)","","IT:IVA","IT:CUUO"],
|
||||
],
|
||||
"LT" => ["B+G","LT:LEC","LT:VAT","LT:LEC"],
|
||||
"LU" => ["B+G","LU:MAT","LU:VAT","LU:VAT"],
|
||||
"LV" => ["B+G","","LV:VAT","LV:VAT"],
|
||||
"MC" => ["B+G","","MC:VAT","MC:VAT"],
|
||||
"ME" => ["B+G","","ME:VAT","ME:VAT"],
|
||||
"MK" => ["B+G","","MK:VAT","MK:VAT"],
|
||||
"MT" => ["B+G","","MT:VAT","MT:VAT"],
|
||||
"NL" => ["G","NL:OINO","","NL:OINO"],
|
||||
"NL" => ["B","NL:KVK","NL:VAT","NL:KVK or NL:VAT"],
|
||||
"PL" => ["G+B","","PL:VAT","PL:VAT"],
|
||||
"PT" => ["G+B","","PT:VAT","PT:VAT"],
|
||||
"RO" => ["G+B","","RO:VAT","RO:VAT"],
|
||||
"RS" => ["G+B","","RS:VAT","RS:VAT"],
|
||||
"SE" => ["G+B","SE:ORGNR","SE:VAT","SE:ORGNR"],
|
||||
"SI" => ["G+B","","SI:VAT","SI:VAT"],
|
||||
"SK" => ["G+B","","SK:VAT","SK:VAT"],
|
||||
"SM" => ["G+B","","SM:VAT","SM:VAT"],
|
||||
"TR" => ["G+B","","TR:VAT","TR:VAT"],
|
||||
"VA" => ["G+B","","VA:VAT","VA:VAT"],
|
||||
"IN" => ["B","","IN:GSTIN","Email"],
|
||||
"JP" => ["B","JP:SST","JP:IIN","JP:SST"],
|
||||
"MY" => ["B","MY:EIF","MY:TIN","MY:EIF"],
|
||||
"SG" => [
|
||||
["G","SG:UEN","","0195:SGUENT08GA0028A"],
|
||||
["B","SG:UEN","SG:GST (optional)","SG:UEN"],
|
||||
],
|
||||
"GB" => ["B","","GB:VAT","GB:VAT"],
|
||||
"SA" => ["B","","SA:TIN","Email"],
|
||||
"Other" => ["B","DUNS, GLN, LEI","","DUNS, GLN, LEI"],
|
||||
];
|
||||
|
||||
private Company $company;
|
||||
|
||||
private InvoiceSum | InvoiceSumInclusive $calc;
|
||||
|
||||
private \InvoiceNinja\EInvoice\Models\Peppol\Invoice $p_invoice;
|
||||
|
||||
private ?\InvoiceNinja\EInvoice\Models\Peppol\Invoice $_client_settings;
|
||||
|
||||
private ?\InvoiceNinja\EInvoice\Models\Peppol\Invoice $_company_settings;
|
||||
|
||||
private EInvoice $e;
|
||||
|
||||
private array $storecove_meta = [];
|
||||
|
||||
/**
|
||||
* @param Invoice $invoice
|
||||
*/
|
||||
@ -159,18 +252,21 @@ class Peppol extends AbstractService
|
||||
{
|
||||
$this->company = $invoice->company;
|
||||
$this->calc = $this->invoice->calc();
|
||||
$this->setInvoice();
|
||||
$this->e = new EInvoice();
|
||||
$this->setSettings()->setInvoice();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rehydrates an existing e invoice - or - scaffolds a new one
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function setInvoice(): self
|
||||
{
|
||||
|
||||
|
||||
if($this->invoice->e_invoice){
|
||||
|
||||
|
||||
$e = new EInvoice();
|
||||
$this->p_invoice = $e->decode('Peppol', json_encode($this->invoice->e_invoice->Invoice), 'json');
|
||||
$this->p_invoice = $this->e->decode('Peppol', json_encode($this->invoice->e_invoice->Invoice), 'json');
|
||||
|
||||
return $this;
|
||||
|
||||
@ -183,6 +279,21 @@ class Peppol extends AbstractService
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the settings props into usable models we can merge.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function setSettings(): self
|
||||
{
|
||||
$this->_client_settings = isset($this->invoice->client->e_invoice->Invoice) ? $this->e->decode('Peppol', json_encode($this->invoice->client->e_invoice->Invoice), 'json') : null;
|
||||
|
||||
$this->_company_settings = isset($this->invoice->company->e_invoice->Invoice) ? $this->e->decode('Peppol', json_encode($this->invoice->company->e_invoice->Invoice), 'json') : null;
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function getInvoice(): \InvoiceNinja\EInvoice\Models\Peppol\Invoice
|
||||
{
|
||||
//@todo - need to process this and remove null values
|
||||
@ -211,8 +322,7 @@ class Peppol extends AbstractService
|
||||
$json = $e->encode($this->p_invoice, 'json');
|
||||
|
||||
return $json;
|
||||
// $prefixes = str_ireplace(["cac:","cbc:"], "", $json);
|
||||
// return str_ireplace(["InvoiceLine", "PostalAddress", "PartyName"], ["invoiceLines","address", "companyName"], $prefixes);
|
||||
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
@ -224,15 +334,20 @@ class Peppol extends AbstractService
|
||||
{
|
||||
$this->p_invoice->ID = $this->invoice->number;
|
||||
$this->p_invoice->IssueDate = new \DateTime($this->invoice->date);
|
||||
|
||||
if($this->invoice->due_date)
|
||||
$this->p_invoice->DueDate = new \DateTime($this->invoice->due_date);
|
||||
|
||||
$this->p_invoice->InvoiceTypeCode = 380; //
|
||||
$this->p_invoice->AccountingSupplierParty = $this->getAccountingSupplierParty();
|
||||
$this->p_invoice->AccountingCustomerParty = $this->getAccountingCustomerParty();
|
||||
$this->p_invoice->InvoiceLine = $this->getInvoiceLines();
|
||||
|
||||
$this->p_invoice->TaxTotal = $this->getTotalTaxes();
|
||||
// $this->p_invoice->TaxTotal = $this->getTotalTaxes(); it only wants the aggregate here!!
|
||||
$this->p_invoice->LegalMonetaryTotal = $this->getLegalMonetaryTotal();
|
||||
|
||||
$this->countryLevelMutators();
|
||||
$this->senderSpecificLevelMutators()
|
||||
->receiverSpecificLevelMutators();
|
||||
|
||||
return $this;
|
||||
|
||||
@ -340,7 +455,7 @@ class Peppol extends AbstractService
|
||||
|
||||
$tax_total = new TaxTotal();
|
||||
$tax_total->TaxAmount = $tax_amount;
|
||||
$tax_total->TaxSubtotal = $tax_subtotal;
|
||||
$tax_total->TaxSubtotal[] = $tax_subtotal;
|
||||
|
||||
$taxes[] = $tax_total;
|
||||
|
||||
@ -372,7 +487,7 @@ class Peppol extends AbstractService
|
||||
|
||||
$tax_total = new TaxTotal();
|
||||
$tax_total->TaxAmount = $tax_amount;
|
||||
$tax_total->TaxSubtotal = $tax_subtotal;
|
||||
$tax_total->TaxSubtotal[] = $tax_subtotal;
|
||||
|
||||
$taxes[] = $tax_total;
|
||||
|
||||
@ -707,6 +822,37 @@ class Peppol extends AbstractService
|
||||
return $total;
|
||||
}
|
||||
|
||||
///////////////// Helper Methods /////////////////////////
|
||||
|
||||
private function getClientRoutingCode(): string
|
||||
{
|
||||
$receiver_identifiers = $this->routing_rules[$this->invoice->client->country->iso_3166_2];
|
||||
$client_classification = $this->invoice->client->classification == 'government' ? 'G' : 'B';
|
||||
|
||||
if(count($receiver_identifiers) > 1) {
|
||||
|
||||
foreach($receiver_identifiers as $ident)
|
||||
{
|
||||
if(str_contains($ident[0], $client_classification))
|
||||
{
|
||||
return $ident[3];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
elseif(count($receiver_identifiers) == 1)
|
||||
return $receiver_identifiers[3];
|
||||
|
||||
throw new \Exception("e-invoice generation halted:: Could not resolve the Tax Code for this client? {$this->invoice->client->hashed_id}");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* setInvoiceDefaults
|
||||
*
|
||||
* Stubs a default einvoice
|
||||
* @return self
|
||||
*/
|
||||
public function setInvoiceDefaults(): self
|
||||
{
|
||||
$settings = [
|
||||
@ -736,21 +882,38 @@ class Peppol extends AbstractService
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* getSetting
|
||||
*
|
||||
* Attempts to harvest and return a preconfigured prop from company / client / invoice settings
|
||||
*
|
||||
* @param string $property_path
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSetting(string $property_path): mixed
|
||||
{
|
||||
|
||||
if($prop_value = PropertyResolver::resolve($this->invoice->e_invoice, $property_path))
|
||||
if($prop_value = PropertyResolver::resolve($this->p_invoice, $property_path)) {
|
||||
return $prop_value;
|
||||
elseif($prop_value = PropertyResolver::resolve($this->invoice->client->e_invoice, $property_path))
|
||||
}elseif($prop_value = PropertyResolver::resolve($this->_client_settings, $property_path)) {
|
||||
return $prop_value;
|
||||
elseif($prop_value = PropertyResolver::resolve($this->invoice->company->e_invoice, $property_path))
|
||||
}elseif($prop_value = PropertyResolver::resolve($this->_company_settings, $property_path)) {
|
||||
return $prop_value;
|
||||
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public function countryLevelMutators():self
|
||||
/**
|
||||
* senderSpecificLevelMutators
|
||||
*
|
||||
* Runs sender level specific requirements for the e-invoice,
|
||||
*
|
||||
* ie, mutations that are required by the senders country.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function senderSpecificLevelMutators():self
|
||||
{
|
||||
|
||||
if(method_exists($this, $this->invoice->company->country()->iso_3166_2))
|
||||
@ -759,42 +922,240 @@ class Peppol extends AbstractService
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* receiverSpecificLevelMutators
|
||||
*
|
||||
* Runs receiver level specific requirements for the e-invoice
|
||||
*
|
||||
* ie mutations that are required by the receiving country
|
||||
* @return self
|
||||
*/
|
||||
private function receiverSpecificLevelMutators():self
|
||||
{
|
||||
|
||||
if(method_exists($this, "client_{$this->invoice->company->country()->iso_3166_2}"))
|
||||
$this->{"client_{$this->invoice->company->country()->iso_3166_2}"}();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* setPaymentMeans
|
||||
*
|
||||
* Sets the payment means - if it exists
|
||||
* @param bool $required
|
||||
* @return self
|
||||
*/
|
||||
private function setPaymentMeans(bool $required = false): self
|
||||
{
|
||||
|
||||
if($this->p_invoice->PaymentMeans)
|
||||
if(isset($this->p_invoice->PaymentMeans))
|
||||
return $this;
|
||||
elseif(!isset($this->p_invoice->PaymentMeans) && $paymentMeans = $this->getSetting('Invoice.PaymentMeans')){
|
||||
elseif($paymentMeans = $this->getSetting('Invoice.PaymentMeans')){
|
||||
$this->p_invoice->PaymentMeans = is_array($paymentMeans) ? $paymentMeans : [$paymentMeans];
|
||||
return $this;
|
||||
}
|
||||
|
||||
if($required)
|
||||
throw new \Exception('e-invoice generation halted:: Payment Means required');
|
||||
return $this->checkRequired($required, "Payment Means");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* setOrderReference
|
||||
*
|
||||
* sets the order reference - if it exists (Never rely on settings for this)
|
||||
*
|
||||
* @param bool $required
|
||||
* @return self
|
||||
*/
|
||||
private function setOrderReference(bool $required = false): self
|
||||
{
|
||||
$this->p_invoice->BuyerReference = $this->invoice->po_number ?? '';
|
||||
|
||||
if(strlen($this->invoice->po_number ?? '') > 1)
|
||||
{
|
||||
$order_reference = new OrderReference();
|
||||
$id = new ID();
|
||||
$id->value = $this->invoice->po_number;
|
||||
|
||||
$order_reference->ID = $id;
|
||||
|
||||
$this->p_invoice->OrderReference = $order_reference;
|
||||
|
||||
// $this->setStorecoveMeta(["document" => [
|
||||
// "invoice" => [
|
||||
// [
|
||||
// "references" => [
|
||||
// "documentType" => "purchase_order",
|
||||
// "documentId" => $this->invoice->po_number,
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
// ]
|
||||
// ]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this->checkRequired($required, 'Order Reference');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* setCustomerAssignedAccountId
|
||||
*
|
||||
* Sets the client id_number CAN rely on settings
|
||||
*
|
||||
* @param bool $required
|
||||
* @return self
|
||||
*/
|
||||
private function setCustomerAssignedAccountId(bool $required = false): self
|
||||
{
|
||||
//@phpstan-ignore-next-line
|
||||
if(isset($this->p_invoice->AccountingCustomerParty->CustomerAssignedAccountID)){
|
||||
return $this;
|
||||
}
|
||||
elseif($customer_assigned_account_id = $this->getSetting('Invoice.AccountingCustomerParty.CustomerAssignedAccountID')){
|
||||
|
||||
$this->p_invoice->AccountingCustomerParty->CustomerAssignedAccountID = $customer_assigned_account_id;
|
||||
return $this;
|
||||
}
|
||||
elseif(strlen($this->invoice->client->id_number ?? '') > 1){
|
||||
|
||||
$customer_assigned_account_id = new CustomerAssignedAccountID();
|
||||
$customer_assigned_account_id->value = $this->invoice->client->id_number;
|
||||
|
||||
$this->p_invoice->AccountingCustomerParty->CustomerAssignedAccountID = $customer_assigned_account_id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
//@phpstan-ignore-next-line
|
||||
return $this->checkRequired($required, 'Client ID Number');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Required
|
||||
*
|
||||
* Throws if a required field is missing.
|
||||
*
|
||||
* @param bool $required
|
||||
* @param string $section
|
||||
* @return self
|
||||
*/
|
||||
private function checkRequired(bool $required, string $section): self
|
||||
{
|
||||
|
||||
return $required ? throw new \Exception("e-invoice generation halted:: {$section} required") : $this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds the Routing object for StoreCove
|
||||
*
|
||||
* @param string $schemeId
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
private function buildRouting(string $schemeId, string $id): array
|
||||
{
|
||||
|
||||
return
|
||||
[
|
||||
"routing" => [
|
||||
"publicIdentifiers" => [
|
||||
[
|
||||
"scheme" => $schemeId,
|
||||
"id" => $id
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* setStorecoveMeta
|
||||
*
|
||||
* updates the storecove payload for sending documents
|
||||
*
|
||||
* @param array $meta
|
||||
* @return self
|
||||
*/
|
||||
private function setStorecoveMeta(array $meta): self
|
||||
{
|
||||
$this->storecove_meta = array_merge($this->storecove_meta, $meta);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStorecoveMeta(): array
|
||||
{
|
||||
return $this->storecove_meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////// Country level mutators /////////////////////////////////////
|
||||
|
||||
/**
|
||||
* DE
|
||||
*
|
||||
* @Completed
|
||||
* @Tested
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function DE(): self
|
||||
{
|
||||
// accountingsupplierparty.party.contact MUST be set - Name / Telephone / Electronic Mail
|
||||
// this is forced by default.
|
||||
|
||||
$this->setPaymentMeans(true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* CH
|
||||
*
|
||||
* @Completed
|
||||
*
|
||||
* Completed - QR-Bill to be implemented at a later date.
|
||||
* @return self
|
||||
*/
|
||||
private function CH(): self
|
||||
{
|
||||
//if QR-Bill support required - then special flow required.... optional.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* AT
|
||||
*
|
||||
* @Pending
|
||||
*
|
||||
* Need to ensure when sending to government entities that we route appropriately
|
||||
* Also need to ensure customerAssignedAccountIdValue is set so that the sender can be resolved.
|
||||
*
|
||||
* Need a way to define if the client is a government entity.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function AT(): self
|
||||
{
|
||||
//special fields for sending to AT:GOV
|
||||
|
||||
if($this->invoice->client->classification == 'government') {
|
||||
//routing "b" for production "test" for test environment
|
||||
$this->setStorecoveMeta($this->buildRouting('AT:GOV', "b"));
|
||||
|
||||
//for government clients this must be set.
|
||||
$this->setCustomerAssignedAccountId(true);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -805,13 +1166,27 @@ class Peppol extends AbstractService
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* ES
|
||||
*
|
||||
* @Pending
|
||||
* B2G configuration
|
||||
* B2G Testing
|
||||
*
|
||||
* testing. // routing identifier - 293098
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function ES(): self
|
||||
{
|
||||
|
||||
// For B2B, provide an ES:DIRE routing identifier and an ES:VAT tax identifier.
|
||||
// both sender and receiver must be an ES company;
|
||||
// you must have a "credit_transfer" PaymentMean;
|
||||
// the "dueDate" property is mandatory.
|
||||
if(!isset($this->invoice->due_date))
|
||||
$this->p_invoice->DueDate = new \DateTime($this->invoice->date);
|
||||
|
||||
if($this->invoice->client->classification == 'business' && $this->invoice->company->getSetting('classification') == 'business') {
|
||||
//must have a paymentmeans as credit_transfer
|
||||
$this->setPaymentMeans(true);
|
||||
}
|
||||
|
||||
// For B2G, provide three ES:FACE identifiers in the routing object,
|
||||
// as well as the ES:VAT tax identifier in the accountingCustomerParty.publicIdentifiers.
|
||||
@ -849,40 +1224,99 @@ class Peppol extends AbstractService
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* FR
|
||||
* @Pending - clarification on codes needed
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function FR(): self
|
||||
{
|
||||
|
||||
// When sending invoices to the French government (Chorus Pro):
|
||||
|
||||
// All invoices have to be routed to SIRET 0009:11000201100044. There is no test environment for sending to public entities.
|
||||
|
||||
// The SIRET / 0009 identifier of the final recipient is to be included in the invoice.accountingCustomerParty.publicIdentifiers array.
|
||||
|
||||
if($this->invoice->client->classification == 'government'){
|
||||
//route to SIRET 0009:11000201100044
|
||||
$this->setStorecoveMeta($this->buildRouting('FR:SIRET', "0009:11000201100044"));
|
||||
|
||||
// The SIRET / 0009 identifier of the final recipient is to be included in the invoice.accountingCustomerParty.publicIdentifiers array.
|
||||
$this->setCustomerAssignedAccountId(true);
|
||||
|
||||
}
|
||||
|
||||
if(strlen($this->invoice->client->id_number ?? '') == 9) {
|
||||
//SIREN
|
||||
$this->setStorecoveMeta($this->buildRouting('FR:SIREN', "0002:{$this->invoice->client->id_number}"));
|
||||
}
|
||||
else {
|
||||
//SIRET
|
||||
$this->setStorecoveMeta($this->buildRouting('FR:SIRET', "0009:{$this->invoice->client->id_number}"));
|
||||
}
|
||||
|
||||
// Apparently this is not a special field according to support
|
||||
// sounds like it is optional
|
||||
// The service code must be sent in invoice.buyerReference (deprecated) or the invoice.references array (documentType buyer_reference)
|
||||
|
||||
// The commitment number must be sent in the invoice.orderReference (deprecated) or the invoice.references array (documentType purchase_order).
|
||||
if(strlen($this->invoice->po_number ?? '') >1) {
|
||||
$this->setOrderReference(false);
|
||||
}
|
||||
|
||||
// Invoices to companies (SIRET / 0009 or SIRENE / 0002) are routed directly to that identifier.
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function IT(): self
|
||||
{
|
||||
|
||||
// IT Sender, IT Receiver, B2B/B2G
|
||||
// Provide the receiver IT:VAT and the receiver IT:CUUO (codice destinatario)
|
||||
if($this->invoice->client->classification == 'government' && $this->invoice->company->country()->iso_3166_2 == 'IT') {
|
||||
|
||||
$this->setStorecoveMeta($this->buildRouting('IT:VAT', $this->invoice->client->routing_id));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// IT Sender, IT Receiver, B2C
|
||||
// Provide the receiver IT:CF and the receiver IT:CUUO (codice destinatario)
|
||||
if($this->invoice->client->classification == 'individual' && $this->invoice->company->country()->iso_3166_2 == 'IT') {
|
||||
|
||||
$this->setStorecoveMeta($this->buildRouting('IT:CF', $this->invoice->client->routing_id));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// IT Sender, non-IT Receiver
|
||||
// Provide the receiver tax identifier and any routing identifier applicable to the receiving country (see Receiver Identifiers).
|
||||
if($this->invoice->client->country->iso_3166_2 != 'IT' && $this->invoice->company->country()->iso_3166_2 == 'IT') {
|
||||
|
||||
$code = $this->getClientRoutingCode();
|
||||
|
||||
$this->setStorecoveMeta($this->buildRouting($code, $this->invoice->client->vat_number));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function client_IT(): self
|
||||
{
|
||||
|
||||
// non-IT Sender, IT Receiver, B2C
|
||||
// Provide the receiver IT:CF and an optional email. The invoice will be eReported and sent via email. Note that this cannot be a PEC email address.
|
||||
if(in_array($this->invoice->client->classification, ['individual']) && $this->invoice->company->country()->iso_3166_2 != 'IT') {
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
// non-IT Sender, IT Receiver, B2B/B2G
|
||||
// Provide the receiver IT:VAT and the receiver IT:CUUO (codice destinatario)
|
||||
|
||||
// non-IT Sender, IT Receiver, B2C
|
||||
// Provide the receiver IT:CF and an optional email. The invoice will be eReported and sent via email. Note that this cannot be a PEC email address.
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
private function MY(): self
|
||||
|
@ -250,7 +250,7 @@ class Email implements ShouldQueue
|
||||
|
||||
private function incrementEmailCounter(): void
|
||||
{
|
||||
if(in_array($this->mailer, ['default','mailgun','postmark'])) {
|
||||
if(in_array($this->email_object->settings->email_sending_method, ['default','mailgun','postmark'])) {
|
||||
Cache::increment("email_quota".$this->company->account->key);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ use App\Models\Invoice;
|
||||
use App\Services\AbstractService;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use App\Models\Product;
|
||||
|
||||
class AddGatewayFee extends AbstractService
|
||||
{
|
||||
@ -80,6 +81,7 @@ class AddGatewayFee extends AbstractService
|
||||
$invoice_item->tax_name2 = $fees_and_limits->fee_tax_name2;
|
||||
$invoice_item->tax_rate3 = $fees_and_limits->fee_tax_rate3;
|
||||
$invoice_item->tax_name3 = $fees_and_limits->fee_tax_name3;
|
||||
$invoice_item->tax_id = (string)Product::PRODUCT_TYPE_OVERRIDE_TAX;
|
||||
}
|
||||
|
||||
$invoice_items = (array) $this->invoice->line_items;
|
||||
|
@ -1260,6 +1260,7 @@ class SubscriptionService
|
||||
return Subscription::query()
|
||||
->where('company_id', $this->subscription->company_id)
|
||||
->where('group_id', $this->subscription->group_id)
|
||||
->whereNotNull('group_id')
|
||||
->where('id', '!=', $this->subscription->id)
|
||||
->get();
|
||||
}
|
||||
|
@ -507,7 +507,9 @@ class HtmlEngine
|
||||
|
||||
$data['$client.lang_2'] = ['value' => optional($this->client->language())->locale, 'label' => ''];
|
||||
|
||||
|
||||
$data['$client.balance'] = ['value' => Number::formatMoney($this->client->balance, $this->client), 'label' => ctrans('texts.account_balance')];
|
||||
$data['$client.payment_balance'] = ['value' => Number::formatMoney($this->client->payment_balance, $this->client), 'label' => ctrans('texts.payment_balance_on_file')];
|
||||
$data['$client_balance'] = ['value' => Number::formatMoney($this->client->balance, $this->client), 'label' => ctrans('texts.account_balance')];
|
||||
$data['$paid_to_date'] = ['value' => Number::formatMoney($this->entity->paid_to_date, $this->client), 'label' => ctrans('texts.paid_to_date')];
|
||||
|
||||
|
@ -20,12 +20,18 @@ class PDF extends FPDI
|
||||
public function Footer()
|
||||
{
|
||||
$this->SetXY(0, -6);
|
||||
|
||||
$this->SetFont('Arial', 'I', 9);
|
||||
|
||||
$this->SetTextColor(135, 135, 135);
|
||||
|
||||
$trans = ctrans('texts.pdf_page_info', ['current' => $this->PageNo(), 'total' => '{nb}']);
|
||||
// $trans = iconv('UTF-8', 'ISO-8859-7', $trans);
|
||||
|
||||
try {
|
||||
$trans = mb_convert_encoding($trans, 'ISO-8859-1', 'UTF-8');
|
||||
}
|
||||
catch(\Exception $e){}
|
||||
|
||||
$this->Cell(0, 5, $trans, 0, 0, $this->text_alignment);
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
"asm/php-ansible": "dev-main",
|
||||
"authorizenet/authorizenet": "^2.0",
|
||||
"awobaz/compoships": "^2.1",
|
||||
"aws/aws-sdk-php": "^3.319",
|
||||
"bacon/bacon-qr-code": "^2.0",
|
||||
"beganovich/snappdf": "dev-master",
|
||||
"braintree/braintree_php": "^6.0",
|
||||
|
17
composer.lock
generated
17
composer.lock
generated
@ -535,16 +535,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.317.1",
|
||||
"version": "3.319.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "dc1e3031c2721a25beb2e8fbb175b576e3d60ab9"
|
||||
"reference": "a5c408d4cd1945d5fc817f45e46383634b610497"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/dc1e3031c2721a25beb2e8fbb175b576e3d60ab9",
|
||||
"reference": "dc1e3031c2721a25beb2e8fbb175b576e3d60ab9",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a5c408d4cd1945d5fc817f45e46383634b610497",
|
||||
"reference": "a5c408d4cd1945d5fc817f45e46383634b610497",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -597,7 +597,10 @@
|
||||
],
|
||||
"psr-4": {
|
||||
"Aws\\": "src/"
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"src/data/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -624,9 +627,9 @@
|
||||
"support": {
|
||||
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.317.1"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.319.0"
|
||||
},
|
||||
"time": "2024-08-02T18:09:42+00:00"
|
||||
"time": "2024-08-07T18:05:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
|
@ -1,19 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Imdhemy\Purchases\Events\AppStore\DidChangeRenewalStatus;
|
||||
use Imdhemy\Purchases\Events\AppStore\DidFailToRenew;
|
||||
use Imdhemy\Purchases\Events\AppStore\DidRenew;
|
||||
use Imdhemy\Purchases\Events\AppStore\InitialBuy;
|
||||
use Imdhemy\Purchases\Events\AppStore\InteractiveRenewal;
|
||||
use Imdhemy\Purchases\Events\AppStore\Cancel;
|
||||
use Imdhemy\Purchases\Events\AppStore\Refund;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionCanceled;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionExpired;
|
||||
use Imdhemy\Purchases\Events\AppStore\DidRenew;
|
||||
use Imdhemy\Purchases\Events\AppStore\DidRecover;
|
||||
use Imdhemy\Purchases\Events\AppStore\InitialBuy;
|
||||
use Imdhemy\Purchases\Events\AppStore\DidFailToRenew;
|
||||
use Imdhemy\Purchases\Events\AppStore\InteractiveRenewal;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionPaused;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionExpired;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionRenewed;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionRevoked;
|
||||
use Imdhemy\Purchases\Events\AppStore\DidChangeRenewalStatus;
|
||||
use Imdhemy\Purchases\Events\AppStore\Subscribed;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionCanceled;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionPurchased;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionRecovered;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionRenewed;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionRestarted;
|
||||
use Imdhemy\Purchases\Events\GooglePlay\SubscriptionRevoked;
|
||||
|
||||
return [
|
||||
/*
|
||||
@ -108,9 +111,10 @@ return [
|
||||
\App\Listeners\GooglePlay\SubscriptionRecovered::class,
|
||||
],*/
|
||||
|
||||
Subscribed::class => class_exists(\Modules\Admin\Listeners\Subscription\AppleSubscribed::class) ? [\Modules\Admin\Listeners\Subscription\AppleSubscribed::class] : [],
|
||||
DidRenew::class => class_exists(\Modules\Admin\Listeners\Subscription\AppleAutoRenew::class) ? [\Modules\Admin\Listeners\Subscription\AppleAutoRenew::class] : [],
|
||||
SubscriptionRenewed::class => class_exists(\Modules\Admin\Listeners\Subscription\GoogleAutoRenew::class) ? [\Modules\Admin\Listeners\Subscription\GoogleAutoRenew::class] : [],
|
||||
DidChangeRenewalStatus::class => class_exists(\Modules\Admin\Listeners\Subscription\GoogleChangeRenewalStaus::class) ? [\Modules\Admin\Listeners\Subscription\GoogleChangeRenewalStaus::class] : [],
|
||||
// DidChangeRenewalStatus::class => class_exists(\Modules\Admin\Listeners\Subscription\GoogleChangeRenewalStaus::class) ? [\Modules\Admin\Listeners\Subscription\GoogleChangeRenewalStaus::class] : [],
|
||||
DidFailToRenew::class => class_exists(\Modules\Admin\Listeners\Subscription\GoogleFailedToRenew::class) ? [\Modules\Admin\Listeners\Subscription\GoogleFailedToRenew::class] : [],
|
||||
Refund::class => class_exists(\Modules\Admin\Listeners\Subscription\AppleRefund::class) ? [\Modules\Admin\Listeners\Subscription\AppleRefund::class] : [],
|
||||
SubscriptionRecovered::class => class_exists(\Modules\Admin\Listeners\Subscription\GoogleSubscriptionRecovered::class) ? [\Modules\Admin\Listeners\Subscription\GoogleSubscriptionRecovered::class] : [],
|
||||
|
@ -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.10.19'),
|
||||
'app_tag' => env('APP_TAG', '5.10.19'),
|
||||
'app_version' => env('APP_VERSION', '5.10.24'),
|
||||
'app_tag' => env('APP_TAG', '5.10.24'),
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', false),
|
||||
|
@ -5311,6 +5311,9 @@ $lang = array(
|
||||
'customer_type' => 'Customer Type',
|
||||
'process_date' => 'Process Date',
|
||||
'forever_free' => 'Forever Free',
|
||||
'comments_only' => 'Comments Only',
|
||||
'payment_balance_on_file' => 'Payment Balance On File',
|
||||
'ubl_email_attachment_help' => 'For more e-invoice settings please navigate :here',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -199,7 +199,7 @@ $lang = array(
|
||||
'removed_logo' => 'Logo eliminado correctamente',
|
||||
'sent_message' => 'Mensaje enviado correctamente',
|
||||
'invoice_error' => 'Seleccionar cliente y corregir errores.',
|
||||
'limit_clients' => 'You\'ve hit the :count client limit on Free accounts. Congrats on your success!',
|
||||
'limit_clients' => 'Has alcanzado el límite de :count clientes en cuentas gratuitas. ¡Felicitaciones por tu éxito!',
|
||||
'payment_error' => 'Ha habido un error en el proceso de tu Pago. Inténtalo de nuevo más tarde.',
|
||||
'registration_required' => 'Se requiere registro',
|
||||
'confirmation_required' => 'Por favor, confirma tu dirección de correo electrónico, :link para reenviar el email de confirmación.',
|
||||
@ -1095,7 +1095,7 @@ $lang = array(
|
||||
'invoice_embed_documents' => 'Documentos anexados',
|
||||
'invoice_embed_documents_help' => 'Incluye imagenes adjuntas en la factura',
|
||||
'document_email_attachment' => 'Adjuntar documentos',
|
||||
'ubl_email_attachment' => 'Attach UBL/E-Invoice',
|
||||
'ubl_email_attachment' => 'Adjuntar UBL/E-Invoice',
|
||||
'download_documents' => 'Descargar documentos (:size)',
|
||||
'documents_from_expenses' => 'De los Gastos:',
|
||||
'dropzone_default_message' => 'Arrastra ficheros aquí o Haz clic para subir',
|
||||
@ -2691,7 +2691,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
|
||||
'no_assets' => 'Sin imágenes, arrastra aquí para subir',
|
||||
'add_image' => 'Añadir Imagen',
|
||||
'select_image' => 'Seleccionar Imagen',
|
||||
'upgrade_to_upload_images' => 'Upgrade to the Enterprise Plan to upload files & images',
|
||||
'upgrade_to_upload_images' => 'Actualice al plan Enterprise para cargar archivos e imágenes',
|
||||
'delete_image' => 'Borrar Imagen',
|
||||
'delete_image_help' => 'Atención: borrar la imagen la eliminará de todas las propuestas.',
|
||||
'amount_variable_help' => 'Nota: el campo de la factura $amount usará el campo parcial/depósito si se indica, de otra forma se usará el balance de la factura.',
|
||||
@ -2909,13 +2909,13 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
|
||||
'mime_types' => 'Tipos de ficheros',
|
||||
'mime_types_placeholder' => '.pdf , .docx, .jpg',
|
||||
'mime_types_help' => 'Lista separada por comas de los tipos mime de fichero aceptados, déjalo en blanco para todos',
|
||||
'ticket_number_start_help' => 'Ticket number must be greater than the current ticket number',
|
||||
'new_ticket_template_id' => 'New ticket',
|
||||
'new_ticket_autoresponder_help' => 'Selecting a template will send an auto response to a client/contact when a new ticket is created',
|
||||
'update_ticket_template_id' => 'Updated ticket',
|
||||
'update_ticket_autoresponder_help' => 'Selecting a template will send an auto response to a client/contact when a ticket is updated',
|
||||
'close_ticket_template_id' => 'Closed ticket',
|
||||
'close_ticket_autoresponder_help' => 'Selecting a template will send an auto response to a client/contact when a ticket is closed',
|
||||
'ticket_number_start_help' => 'El número de ticket debe ser mayor que el número de ticket actual',
|
||||
'new_ticket_template_id' => 'Nuevo Ticket',
|
||||
'new_ticket_autoresponder_help' => 'Al seleccionar una plantilla se enviará una respuesta automática a un cliente/contacto cuando se cree un nuevo ticket.',
|
||||
'update_ticket_template_id' => 'Ticket actualizado',
|
||||
'update_ticket_autoresponder_help' => 'Al seleccionar una plantilla se enviará una respuesta automática a un cliente/contacto cuando se actualice un ticket.',
|
||||
'close_ticket_template_id' => 'Ticket cerrado',
|
||||
'close_ticket_autoresponder_help' => 'Al seleccionar una plantilla se enviará una respuesta automática a un cliente/contacto cuando se cierre un ticket.',
|
||||
'default_priority' => 'Prioridad por defecto',
|
||||
'alert_new_comment_id' => 'Nuevo comentario',
|
||||
'update_ticket_notification_list' => 'Notificaciones de nuevo comentario adicionales',
|
||||
@ -3041,7 +3041,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
|
||||
'portal_mode' => 'Modo portal',
|
||||
'attach_pdf' => 'Adjuntar PDF',
|
||||
'attach_documents' => 'Adjuntar Documentos',
|
||||
'attach_ubl' => 'Attach UBL/E-Invoice',
|
||||
'attach_ubl' => 'Adjuntar UBL/E-Invoice',
|
||||
'email_style' => 'Estilo de correo electrónico',
|
||||
'processed' => 'Procesado',
|
||||
'fee_amount' => 'Importe de la cuota',
|
||||
@ -3782,7 +3782,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
|
||||
'entity_number_placeholder' => ':entity # :entity_number',
|
||||
'email_link_not_working' => 'Si el botón de arriba no te está funcionando, por favor pulsa en el enlace',
|
||||
'display_log' => 'Mostrar Registro',
|
||||
'send_fail_logs_to_our_server' => 'Report errors to help improve the app',
|
||||
'send_fail_logs_to_our_server' => 'Informar errores para ayudar a mejorar la aplicación',
|
||||
'setup' => 'Instalación',
|
||||
'quick_overview_statistics' => 'Vistazo rápido y estadísticas',
|
||||
'update_your_personal_info' => 'Actualiza tu información personal',
|
||||
@ -4371,7 +4371,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
|
||||
'client_shipping_country' => 'País de envío del cliente',
|
||||
'load_pdf' => 'Cargar PDF',
|
||||
'start_free_trial' => 'Iniciar prueba gratuita',
|
||||
'start_free_trial_message' => 'Start your FREE 14 day trial of the Pro Plan',
|
||||
'start_free_trial_message' => 'Comience su prueba GRATUITA de 14 días del Plan Pro',
|
||||
'due_on_receipt' => 'Adeudado a la recepción',
|
||||
'is_paid' => 'Está pagado',
|
||||
'age_group_paid' => 'Pagado',
|
||||
@ -5082,7 +5082,7 @@ De lo contrario, este campo deberá dejarse en blanco.',
|
||||
'payment_refund_receipt' => 'Recibo de reembolso de pago Nº :number',
|
||||
'payment_receipt' => 'Recibo de pago Nº :number',
|
||||
'load_template_description' => 'La plantilla se aplicará a lo siguiente:',
|
||||
'run_template' => 'Run Template',
|
||||
'run_template' => 'Ejecutar plantilla',
|
||||
'statement_design' => 'Diseño de Estado de Cuenta',
|
||||
'delivery_note_design' => 'Diseño de albarán de entrega',
|
||||
'payment_receipt_design' => 'Diseño de recibo de pago',
|
||||
@ -5121,7 +5121,7 @@ De lo contrario, este campo deberá dejarse en blanco.',
|
||||
'all_contacts' => 'Todos los contactos',
|
||||
'insert_below' => 'Insertar abajo',
|
||||
'nordigen_handler_subtitle' => 'Autenticación de cuenta bancaria. Seleccionar su institución para completar la solicitud con las credenciales de su cuenta.',
|
||||
'nordigen_handler_error_heading_unknown' => 'Ha ocurrido un error',
|
||||
'nordigen_handler_error_heading_unknown' => 'Se ha producido un error',
|
||||
'nordigen_handler_error_contents_unknown' => '¡Se ha producido un error desconocido! Razón:',
|
||||
'nordigen_handler_error_heading_token_invalid' => 'Token no válido',
|
||||
'nordigen_handler_error_contents_token_invalid' => 'El token proporcionado no era válido. Póngase en contacto con el soporte para obtener ayuda si este problema persiste.',
|
||||
@ -5235,69 +5235,79 @@ De lo contrario, este campo deberá dejarse en blanco.',
|
||||
'local_domain_help' => 'Dominio EHLO (opcional)',
|
||||
'port_help' => 'Ej. 25.587.465',
|
||||
'host_help' => 'Ej. smtp.gmail.com',
|
||||
'always_show_required_fields' => 'Allows show required fields form',
|
||||
'always_show_required_fields_help' => 'Displays the required fields form always at checkout',
|
||||
'advanced_cards' => 'Advanced Cards',
|
||||
'activity_140' => 'Statement sent to :client',
|
||||
'invoice_net_amount' => 'Invoice Net Amount',
|
||||
'round_to_minutes' => 'Round To Minutes',
|
||||
'1_second' => '1 Second',
|
||||
'1_minute' => '1 Minute',
|
||||
'5_minutes' => '5 Minutes',
|
||||
'15_minutes' => '15 Minutes',
|
||||
'30_minutes' => '30 Minutes',
|
||||
'1_hour' => '1 Hour',
|
||||
'1_day' => '1 Day',
|
||||
'round_tasks' => 'Task Rounding Direction',
|
||||
'round_tasks_help' => 'Round task times up or down.',
|
||||
'direction' => 'Direction',
|
||||
'round_up' => 'Round Up',
|
||||
'round_down' => 'Round Down',
|
||||
'task_round_to_nearest' => 'Round To Nearest',
|
||||
'task_round_to_nearest_help' => 'The interval to round the task to.',
|
||||
'bulk_updated' => 'Successfully updated data',
|
||||
'bulk_update' => 'Bulk Update',
|
||||
'calculate' => 'Calculate',
|
||||
'sum' => 'Sum',
|
||||
'money' => 'Money',
|
||||
'web_app' => 'Web App',
|
||||
'desktop_app' => 'Desktop App',
|
||||
'disconnected' => 'Disconnected',
|
||||
'reconnect' => 'Reconnect',
|
||||
'e_invoice_settings' => 'E-Invoice Settings',
|
||||
'btcpay_refund_subject' => 'Refund of your invoice via BTCPay',
|
||||
'btcpay_refund_body' => 'A refund intended for you has been issued. To claim it via BTCPay, please click on this link:',
|
||||
'always_show_required_fields' => 'Mostrar siempre los campos obligatorios del formulario',
|
||||
'always_show_required_fields_help' => 'Muestra siempre el formulario de campos obligatorios al finalizar la compra',
|
||||
'advanced_cards' => 'Tarjetas avanzadas',
|
||||
'activity_140' => 'Declaración enviada a :client',
|
||||
'invoice_net_amount' => 'Importe neto de la factura',
|
||||
'round_to_minutes' => 'Redondear a minutos',
|
||||
'1_second' => '1 segundo',
|
||||
'1_minute' => '1 minuto',
|
||||
'5_minutes' => '5 minutos',
|
||||
'15_minutes' => '15 minutos',
|
||||
'30_minutes' => '30 minutos',
|
||||
'1_hour' => '1 hora',
|
||||
'1_day' => '1 día',
|
||||
'round_tasks' => 'Dirección de redondeo de tareas',
|
||||
'round_tasks_help' => 'Redondea los tiempos de las tareas hacia arriba o hacia abajo.',
|
||||
'direction' => 'Dirección',
|
||||
'round_up' => 'Redondeo',
|
||||
'round_down' => 'Redondear a la baja',
|
||||
'task_round_to_nearest' => 'Redondear al más cercano',
|
||||
'task_round_to_nearest_help' => 'El intervalo al que se debe redondear la tarea.',
|
||||
'bulk_updated' => 'Datos actualizados con éxito',
|
||||
'bulk_update' => 'Actualización masiva',
|
||||
'calculate' => 'Calcular',
|
||||
'sum' => 'Suma',
|
||||
'money' => 'Dinero',
|
||||
'web_app' => 'Aplicación Web',
|
||||
'desktop_app' => 'Aplicación de escritorio',
|
||||
'disconnected' => 'Desconectado',
|
||||
'reconnect' => 'Reconectar',
|
||||
'e_invoice_settings' => 'Configuración de factura electrónica',
|
||||
'btcpay_refund_subject' => 'Reembolso de su factura a través de BTCPay',
|
||||
'btcpay_refund_body' => 'Se ha emitido un reembolso destinado a usted. Para reclamarlo a través de BTCPay, haga clic en este enlace:',
|
||||
'currency_mauritanian_ouguiya' => 'Mauritanian Ouguiya',
|
||||
'currency_bhutan_ngultrum' => 'Bhutan Ngultrum',
|
||||
'end_of_month' => 'End Of Month',
|
||||
'merge_e_invoice_to_pdf' => 'Merge E-Invoice and PDF',
|
||||
'task_assigned_subject' => 'New task assignment [Task :task] [ :date ]',
|
||||
'task_assigned_body' => 'You have been assigned task :task <br><br> Description: :description <br><br> Client: :client',
|
||||
'activity_141' => 'User :user entered note: :notes',
|
||||
'quote_reminder_subject' => 'Reminder: Quote :quote from :company',
|
||||
'quote_reminder_message' => 'Reminder for quote :number for :amount',
|
||||
'quote_reminder1' => 'First Quote Reminder',
|
||||
'before_valid_until_date' => 'Before the valid until date',
|
||||
'after_valid_until_date' => 'After the valid until date',
|
||||
'after_quote_date' => 'After the quote date',
|
||||
'remind_quote' => 'Remind Quote',
|
||||
'end_of_month' => 'End Of Month',
|
||||
'tax_currency_mismatch' => 'Tax currency is different from invoice currency',
|
||||
'edocument_import_already_exists' => 'The invoice has already been imported on :date',
|
||||
'before_valid_until' => 'Before the valid until',
|
||||
'after_valid_until' => 'After the valid until',
|
||||
'task_assigned_notification' => 'Task Assigned Notification',
|
||||
'task_assigned_notification_help' => 'Send an email when a task is assigned',
|
||||
'invoices_locked_end_of_month' => 'Invoices are locked at the end of the month',
|
||||
'referral_url' => 'Referral URL',
|
||||
'add_comment' => 'Add Comment',
|
||||
'added_comment' => 'Successfully saved comment',
|
||||
'end_of_month' => 'Fin de mes',
|
||||
'merge_e_invoice_to_pdf' => 'Fusionar factura electrónica y PDF',
|
||||
'task_assigned_subject' => 'Nueva asignación de tarea [Tarea :task] [ :date ]',
|
||||
'task_assigned_body' => 'Se le ha asignado la tarea :task <br><br> Descripción: :description <br><br> Cliente: :client',
|
||||
'activity_141' => 'El usuario: :user ingresó la nota: :notes',
|
||||
'quote_reminder_subject' => 'Recordatorio: Presupuesto :quote de :company',
|
||||
'quote_reminder_message' => 'Recordatorio de presupuesto :number por :amount',
|
||||
'quote_reminder1' => 'Recordatorio del primer presupuesto',
|
||||
'before_valid_until_date' => 'Antes del válido hasta la fecha',
|
||||
'after_valid_until_date' => 'Después de la fecha de validez hasta',
|
||||
'after_quote_date' => 'Después de la fecha del presupuesto',
|
||||
'remind_quote' => 'Recordatorio de presupuesto',
|
||||
'end_of_month' => 'Fin de mes',
|
||||
'tax_currency_mismatch' => 'La moneda del impuesto es diferente a la moneda de la factura',
|
||||
'edocument_import_already_exists' => 'La factura ya fué importada el :date',
|
||||
'before_valid_until' => 'Antes del válido hasta',
|
||||
'after_valid_until' => 'Después del válido hasta',
|
||||
'task_assigned_notification' => 'Notificación de tarea asignada',
|
||||
'task_assigned_notification_help' => 'Enviar un correo electrónico cuando se asigna una tarea',
|
||||
'invoices_locked_end_of_month' => 'Las facturas se bloquean al final del mes.',
|
||||
'referral_url' => 'URL de referencia',
|
||||
'add_comment' => 'Agregar comentario',
|
||||
'added_comment' => 'Comentario guardado correctamente',
|
||||
'tickets' => 'Tickets',
|
||||
'assigned_group' => 'Successfully assigned group',
|
||||
'merge_to_pdf' => 'Merge to PDF',
|
||||
'latest_requires_php_version' => 'Note: the latest version requires PHP :version',
|
||||
'auto_expand_product_table_notes' => 'Automatically expand products table notes',
|
||||
'auto_expand_product_table_notes_help' => 'Automatically expands the notes section within the products table to display more lines.',
|
||||
'assigned_group' => 'Grupo asignado exitosamente',
|
||||
'merge_to_pdf' => 'Fusionar a PDF',
|
||||
'latest_requires_php_version' => 'Nota: la última versión requiere PHP :version',
|
||||
'auto_expand_product_table_notes' => 'Expandir automáticamente las notas de la tabla de productos',
|
||||
'auto_expand_product_table_notes_help' => 'Expande automáticamente la sección de notas dentro de la tabla de productos para mostrar más líneas.',
|
||||
'institution_number' => 'Número de institución',
|
||||
'transit_number' => 'Número de Tránsito',
|
||||
'personal' => 'Personal',
|
||||
'address_information' => 'Datos del Domicilio',
|
||||
'enter_the_information_for_the_bank_account' => 'Introduzca la información de la cuenta bancaria',
|
||||
'account_holder_information' => 'Información del titular de la cuenta',
|
||||
'enter_information_for_the_account_holder' => 'Introducir información del titular de la cuenta',
|
||||
'customer_type' => 'Tipo de cliente',
|
||||
'process_date' => 'Fecha de procesamiento',
|
||||
'forever_free' => 'Forever Free',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -5235,7 +5235,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'local_domain_help' => 'Domaine EHLO (facultatif)',
|
||||
'port_help' => 'ex. 25,587,465',
|
||||
'host_help' => 'ex. smtp.gmail.com',
|
||||
'always_show_required_fields' => 'Permet l\'affichage des champs requis d\'un formulaire',
|
||||
'always_show_required_fields' => 'Toujours afficher les champs requis d\'un formulaire',
|
||||
'always_show_required_fields_help' => 'Affiche toujours les champs requis d\'un formulaire au paiement',
|
||||
'advanced_cards' => 'Cartes avancées',
|
||||
'activity_140' => 'État de compte envoyé à :client',
|
||||
@ -5298,7 +5298,20 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'latest_requires_php_version' => 'Note: La dernière version requiert PHP :version',
|
||||
'auto_expand_product_table_notes' => 'Développer automatiquement les notes du tableau de produits',
|
||||
'auto_expand_product_table_notes_help' => '
|
||||
Développe automatiquement la section des notes dans le tableau de produits pour afficher plus de lignes.'
|
||||
Développe automatiquement la section des notes dans le tableau de produits pour afficher plus de lignes.',
|
||||
'institution_number' => 'Numéro d\'institution',
|
||||
'transit_number' => 'Numéro de transit',
|
||||
'personal' => 'Personnel',
|
||||
'address_information' => 'Information d\'adresse',
|
||||
'enter_the_information_for_the_bank_account' => 'Entrez l\'information du compte de banque',
|
||||
'account_holder_information' => 'Information sur le détenteur du compte',
|
||||
'enter_information_for_the_account_holder' => 'Entrez l\'information du détenteur du compte',
|
||||
'customer_type' => 'Type de client',
|
||||
'process_date' => 'Date de traitement',
|
||||
'forever_free' => 'Gratuit pour toujours',
|
||||
'comments_only' => 'Commentaires seulement',
|
||||
'payment_balance_on_file' => 'Payer le solde inscrit au dossier',
|
||||
'ubl_email_attachment_help' => 'Plus de paramètres pour E-facture, cliquez :here',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -3428,7 +3428,7 @@ adva :date',
|
||||
'reminder2_sent' => 'Emlékeztető 2 elküldve',
|
||||
'reminder3_sent' => 'Emlékeztető 3 elküldve',
|
||||
'reminder_last_sent' => 'Utolsó emlékeztető elküldve',
|
||||
'pdf_page_info' => 'PDF oldal információ',
|
||||
'pdf_page_info' => 'PDF oldal :current / :total',
|
||||
'emailed_credits' => 'E-mailezett jóváírások',
|
||||
'view_in_stripe' => 'Megtekintés a Stripe-ban',
|
||||
'rows_per_page' => 'Sorok száma oldalanként',
|
||||
@ -5108,7 +5108,7 @@ adva :date',
|
||||
'all_contacts' => 'Minden névjegy',
|
||||
'insert_below' => 'Beszúrás alább',
|
||||
'nordigen_handler_subtitle' => 'Bankszámla hitelesítés. Intézményének kiválasztása a kérelem kitöltéséhez a fiók hitelesítő adataival.',
|
||||
'nordigen_handler_error_heading_unknown' => 'Hiba történt',
|
||||
'nordigen_handler_error_heading_unknown' => 'An error has occurred',
|
||||
'nordigen_handler_error_contents_unknown' => 'Ismeretlen hiba lépett fel! Ok:',
|
||||
'nordigen_handler_error_heading_token_invalid' => 'Érvénytelen kód',
|
||||
'nordigen_handler_error_contents_token_invalid' => 'A megadott token érvénytelen. Ha a probléma továbbra is fennáll, forduljon az ügyfélszolgálathoz.',
|
||||
@ -5222,7 +5222,7 @@ adva :date',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
'always_show_required_fields' => 'Allows show required fields form',
|
||||
'always_show_required_fields' => 'Always show required fields form',
|
||||
'always_show_required_fields_help' => 'Displays the required fields form always at checkout',
|
||||
'advanced_cards' => 'Advanced Cards',
|
||||
'activity_140' => 'Statement sent to :client',
|
||||
@ -5285,6 +5285,16 @@ adva :date',
|
||||
'latest_requires_php_version' => 'Note: the latest version requires PHP :version',
|
||||
'auto_expand_product_table_notes' => 'Automatically expand products table notes',
|
||||
'auto_expand_product_table_notes_help' => 'Automatically expands the notes section within the products table to display more lines.',
|
||||
'institution_number' => 'Institution Number',
|
||||
'transit_number' => 'Transit Number',
|
||||
'personal' => 'Personal',
|
||||
'address_information' => 'Address Information',
|
||||
'enter_the_information_for_the_bank_account' => 'Enter the Information for the Bank Account',
|
||||
'account_holder_information' => 'Account Holder Information',
|
||||
'enter_information_for_the_account_holder' => 'Enter Information for the Account Holder',
|
||||
'customer_type' => 'Customer Type',
|
||||
'process_date' => 'Process Date',
|
||||
'forever_free' => 'Forever Free',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4946,7 +4946,7 @@ $lang = array(
|
||||
'tax_exempt' => 'Esente da tasse',
|
||||
'late_fee_added_locked_invoice' => 'Penale per ritardo Fattura :invoice aggiunta su :date',
|
||||
'lang_Khmer' => 'Khmer',
|
||||
'routing_id' => 'ID di instradamento',
|
||||
'routing_id' => 'Codice Destinario',
|
||||
'enable_e_invoice' => 'Abilita E- Fattura',
|
||||
'e_invoice_type' => 'Tipo di Fattura E',
|
||||
'reduced_tax' => 'Tassa ridotta',
|
||||
@ -5115,7 +5115,7 @@ $lang = array(
|
||||
'all_contacts' => 'Tutti i contatti',
|
||||
'insert_below' => 'Inserisci sotto',
|
||||
'nordigen_handler_subtitle' => 'Autenticazione del conto bancario. Seleziona il tuo istituto per completare la richiesta con le credenziali del tuo account.',
|
||||
'nordigen_handler_error_heading_unknown' => 'C'è stato un errore',
|
||||
'nordigen_handler_error_heading_unknown' => 'An error has occurred',
|
||||
'nordigen_handler_error_contents_unknown' => 'Si è verificato un errore sconosciuto! Motivo:',
|
||||
'nordigen_handler_error_heading_token_invalid' => 'gettone non valido',
|
||||
'nordigen_handler_error_contents_token_invalid' => 'Il token fornito non era valido. contatto il supporto per assistenza, se il problema persiste.',
|
||||
@ -5229,7 +5229,7 @@ $lang = array(
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
'always_show_required_fields' => 'Allows show required fields form',
|
||||
'always_show_required_fields' => 'Always show required fields form',
|
||||
'always_show_required_fields_help' => 'Displays the required fields form always at checkout',
|
||||
'advanced_cards' => 'Advanced Cards',
|
||||
'activity_140' => 'Statement sent to :client',
|
||||
@ -5292,6 +5292,19 @@ $lang = array(
|
||||
'latest_requires_php_version' => 'Note: the latest version requires PHP :version',
|
||||
'auto_expand_product_table_notes' => 'Automatically expand products table notes',
|
||||
'auto_expand_product_table_notes_help' => 'Automatically expands the notes section within the products table to display more lines.',
|
||||
'institution_number' => 'Institution Number',
|
||||
'transit_number' => 'Transit Number',
|
||||
'personal' => 'Personal',
|
||||
'address_information' => 'Address Information',
|
||||
'enter_the_information_for_the_bank_account' => 'Enter the Information for the Bank Account',
|
||||
'account_holder_information' => 'Account Holder Information',
|
||||
'enter_information_for_the_account_holder' => 'Enter Information for the Account Holder',
|
||||
'customer_type' => 'Customer Type',
|
||||
'process_date' => 'Process Date',
|
||||
'forever_free' => 'Forever Free',
|
||||
'comments_only' => 'Comments Only',
|
||||
'payment_balance_on_file' => 'Payment Balance On File',
|
||||
'ubl_email_attachment_help' => 'For more e-invoice settings please navigate :here',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -3444,7 +3444,7 @@ $lang = array(
|
||||
'reminder2_sent' => 'ແຈ້ງເຕືອນ 2 ສົ່ງແລ້ວ',
|
||||
'reminder3_sent' => 'ເຕືອນ 3 ສົ່ງແລ້ວ',
|
||||
'reminder_last_sent' => 'ເຕືອນທີ່ສົ່ງຫຼ້າສຸດ',
|
||||
'pdf_page_info' => 'ໜ້າ :ປັດຈຸບັນຂອງ :ທັງໝົດ',
|
||||
'pdf_page_info' => 'ໜ້າ :current :total',
|
||||
'emailed_credits' => 'ເຄຣດິດທີ່ສົ່ງອີເມວສຳເລັດແລ້ວ',
|
||||
'view_in_stripe' => 'ເບິ່ງເປັນເສັ້ນດ່າງ',
|
||||
'rows_per_page' => 'ແຖວຕໍ່ໜ້າ',
|
||||
@ -5124,7 +5124,7 @@ $lang = array(
|
||||
'all_contacts' => 'ຕິດຕໍ່ພົວພັນທັງໝົດ',
|
||||
'insert_below' => 'ໃສ່ທາງລຸ່ມ',
|
||||
'nordigen_handler_subtitle' => 'ການຢືນຢັນບັນຊີທະນາຄານ. ການເລືອກສະຖາບັນຂອງທ່ານເພື່ອເຮັດສໍາເລັດຄໍາຮ້ອງຂໍທີ່ມີຂໍ້ມູນປະຈໍາບັນຊີຂອງທ່ານ.',
|
||||
'nordigen_handler_error_heading_unknown' => 'ເກີດຄວາມຜິດພາດຂຶ້ນ',
|
||||
'nordigen_handler_error_heading_unknown' => 'An error has occurred',
|
||||
'nordigen_handler_error_contents_unknown' => 'ມີຄວາມຜິດພາດທີ່ບໍ່ຮູ້ຈັກເກີດຂຶ້ນ! ເຫດຜົນ:',
|
||||
'nordigen_handler_error_heading_token_invalid' => 'ໂທເຄັນບໍ່ຖືກຕ້ອງ',
|
||||
'nordigen_handler_error_contents_token_invalid' => 'ໂທເຄັນທີ່ໃຫ້ມາບໍ່ຖືກຕ້ອງ. ຕິດຕໍ່ຝ່າຍຊ່ວຍເຫຼືອເພື່ອຂໍຄວາມຊ່ວຍເຫຼືອ, ຖ້າບັນຫານີ້ຍັງຄົງຢູ່.',
|
||||
@ -5238,7 +5238,7 @@ $lang = array(
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
'always_show_required_fields' => 'ອະນຸຍາດໃຫ້ສະແດງແບບຟອມທີ່ຕ້ອງການ',
|
||||
'always_show_required_fields' => 'Always show required fields form',
|
||||
'always_show_required_fields_help' => 'ສະແດງແບບຟອມຊ່ອງຂໍ້ມູນທີ່ຕ້ອງການຢູ່ສະເໝີໃນເວລາຈ່າຍເງິນ',
|
||||
'advanced_cards' => 'ບັດຂັ້ນສູງ',
|
||||
'activity_140' => 'Statement sent to :client',
|
||||
@ -5301,6 +5301,16 @@ $lang = array(
|
||||
'latest_requires_php_version' => 'Note: the latest version requires PHP :version',
|
||||
'auto_expand_product_table_notes' => 'Automatically expand products table notes',
|
||||
'auto_expand_product_table_notes_help' => 'Automatically expands the notes section within the products table to display more lines.',
|
||||
'institution_number' => 'Institution Number',
|
||||
'transit_number' => 'Transit Number',
|
||||
'personal' => 'Personal',
|
||||
'address_information' => 'Address Information',
|
||||
'enter_the_information_for_the_bank_account' => 'Enter the Information for the Bank Account',
|
||||
'account_holder_information' => 'Account Holder Information',
|
||||
'enter_information_for_the_account_holder' => 'Enter Information for the Account Holder',
|
||||
'customer_type' => 'Customer Type',
|
||||
'process_date' => 'Process Date',
|
||||
'forever_free' => 'Forever Free',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -233,7 +233,7 @@ $lang = array(
|
||||
'updated_vendor' => 'De leverancier is gewijzigd',
|
||||
'created_vendor' => 'De leverancier is aangemaakt',
|
||||
'archived_vendor' => 'De leverancier is gearchiveerd',
|
||||
'archived_vendors' => 'Succesvol :count leveranciers gearchiveerd',
|
||||
'archived_vendors' => 'Succesvol gerachiveerd: :count leverancier(s)',
|
||||
'deleted_vendor' => 'De leverancier is verwijderd',
|
||||
'deleted_vendors' => 'Succesvol :count leveranciers verwijderd',
|
||||
'confirmation_subject' => 'Bevestiging account',
|
||||
@ -468,7 +468,7 @@ $lang = array(
|
||||
'deleted_gateway' => 'De betaalprovider is verwijderd',
|
||||
'pay_with_paypal' => 'PayPal',
|
||||
'pay_with_card' => 'Creditcard',
|
||||
'change_password' => 'Verander wachtwoord',
|
||||
'change_password' => 'Wachtwoord wijzigen',
|
||||
'current_password' => 'Huidig wachtwoord',
|
||||
'new_password' => 'Nieuw wachtwoord',
|
||||
'confirm_password' => 'Bevestig wachtwoord',
|
||||
@ -883,13 +883,13 @@ $lang = array(
|
||||
'expense' => 'Uitgave',
|
||||
'expenses' => 'Uitgaven',
|
||||
'new_expense' => 'Nieuwe uitgave',
|
||||
'new_vendor' => 'Nieuwe leverancier',
|
||||
'new_vendor' => 'Nieuwe Leverancier',
|
||||
'payment_terms_net' => 'Betaaltermijn',
|
||||
'vendor' => 'Leverancier',
|
||||
'edit_vendor' => 'Bewerk leverancier',
|
||||
'archive_vendor' => 'Archiveer leverancier',
|
||||
'delete_vendor' => 'Verwijder leverancier',
|
||||
'view_vendor' => 'Bekijk leverancier',
|
||||
'edit_vendor' => 'Bewerk Leverancier',
|
||||
'archive_vendor' => 'Archiveer Leverancier',
|
||||
'delete_vendor' => 'Verwijder Leverancier',
|
||||
'view_vendor' => 'Bekijk Leverancier',
|
||||
'deleted_expense' => 'De uitgave is verwijderd',
|
||||
'archived_expense' => 'De uitgave is gearchiveerd',
|
||||
'deleted_expenses' => 'De uitgaven zijn verwijderd',
|
||||
@ -1046,7 +1046,7 @@ $lang = array(
|
||||
'enable_portal_password' => 'Facturen beveiligen met een wachtwoord',
|
||||
'enable_portal_password_help' => 'Geeft u de mogelijkheid om een wachtwoord in te stellen voor elke contactpersoon. Als er een wachtwoord is ingesteld moet de contactpersoon het wachtwoord invoeren voordat deze facturen kan bekijken.',
|
||||
'send_portal_password' => 'Genereer automatisch',
|
||||
'send_portal_password_help' => 'Als er geen wachtwoord is ingesteld zal deze automatisch worden gegenereerd en verzonden bij de eerste factuur.',
|
||||
'send_portal_password_help' => 'Als er geen wachtwoord is ingesteld zal dit automatisch worden gegenereerd en verzonden bij de eerste factuur.',
|
||||
|
||||
'expired' => 'Verlopen',
|
||||
'invalid_card_number' => 'Het creditcardnummer is niet geldig.',
|
||||
@ -1063,7 +1063,7 @@ $lang = array(
|
||||
'user_view_all' => 'Bekijken van klanten, facturen, enz.',
|
||||
'user_edit_all' => 'Bewerken van alle klanten, facturen, enz.',
|
||||
'partial_due' => 'Voorschot',
|
||||
'restore_vendor' => 'Herstel leverancier',
|
||||
'restore_vendor' => 'Herstel Leverancier',
|
||||
'restored_vendor' => 'De leverancier is hersteld',
|
||||
'restored_expense' => 'De uitgave is hersteld',
|
||||
'permissions' => 'Rechten',
|
||||
@ -1114,9 +1114,9 @@ $lang = array(
|
||||
'document_size' => 'Grootte',
|
||||
|
||||
'enable_client_portal' => 'Dashboard',
|
||||
'enable_client_portal_help' => 'Toon/verberg het klantenportaal.',
|
||||
'enable_client_portal_help' => 'Toon of verberg het klantenportaal.',
|
||||
'enable_client_portal_dashboard' => 'Dashboard',
|
||||
'enable_client_portal_dashboard_help' => 'Toon/verberg de dashboard pagina in het klantenportaal.',
|
||||
'enable_client_portal_dashboard_help' => 'Toon of verberg de dashboardpagina in het klantenportaal.',
|
||||
|
||||
// Plans
|
||||
'account_management' => 'Accountbeheer',
|
||||
@ -1168,7 +1168,7 @@ $lang = array(
|
||||
'live_preview_disabled' => 'Live voorbeeld weergave is uitgeschakeld om het geselecteerde lettertype te ondersteunen.',
|
||||
'invoice_number_padding' => 'Marge',
|
||||
'preview' => 'Voorbeeld',
|
||||
'list_vendors' => 'Toon leveranciers',
|
||||
'list_vendors' => 'Toon Leveranciers',
|
||||
'add_users_not_supported' => 'Upgrade naar het Enterprise-abonnement om extra gebruikers aan uw account toe te voegen.',
|
||||
'enterprise_plan_features' => 'Het Enterprise Plan voegt ondersteuning toe voor meerdere gebruikers en bestandsbijlagen, :link om de volledige lijst met functies te zien.',
|
||||
'return_to_app' => 'Terug naar de app',
|
||||
@ -2487,7 +2487,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'self_host_login' => 'Self-Host login',
|
||||
'set_self_hoat_url' => 'Self-Host URL',
|
||||
'local_storage_required' => 'Fout: lokale opslag is niet beschikbaar.',
|
||||
'your_password_reset_link' => 'Uw wachtwoord reset koppeling',
|
||||
'your_password_reset_link' => 'Uw Wachtwoord Resetlink',
|
||||
'subdomain_taken' => 'Het subdomein is al in gebruik',
|
||||
'client_login' => 'Klantenlogin',
|
||||
'converted_amount' => 'Omgezet bedrag',
|
||||
@ -2544,8 +2544,8 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'subscription_event_10' => 'Klant bijgewerkt',
|
||||
'subscription_event_11' => 'Klant verwijderd',
|
||||
'subscription_event_12' => 'Betaling verwijderd',
|
||||
'subscription_event_13' => 'Verkoper bijgewerkt',
|
||||
'subscription_event_14' => 'Verkoper verwijderd',
|
||||
'subscription_event_13' => 'Leverancier bijgewerkt',
|
||||
'subscription_event_14' => 'Leverancier verwijderd',
|
||||
'subscription_event_15' => 'Uitgave aangemaakt',
|
||||
'subscription_event_16' => 'Uitgave bijgewerkt',
|
||||
'subscription_event_17' => 'Uitgave verwijderen',
|
||||
@ -2565,7 +2565,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'module_credit' => 'Creditfacturen',
|
||||
'module_quote' => 'Offertes & voorstellen',
|
||||
'module_task' => 'Taken & projecten',
|
||||
'module_expense' => 'Uitgaven & leveranciers',
|
||||
'module_expense' => 'Uitgaven & Leveranciers',
|
||||
'module_ticket' => 'Tickets',
|
||||
'reminders' => 'Herinneringen',
|
||||
'send_client_reminders' => 'Verzend e-mailherinneringen',
|
||||
@ -2904,7 +2904,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'from_name_placeholder' => 'Support centrum',
|
||||
'attachments' => 'Bijlagen',
|
||||
'client_upload' => 'Klant uploads',
|
||||
'enable_client_upload_help' => 'Laat klanten documenten/bijlagen uploaden',
|
||||
'enable_client_upload_help' => 'Klanten toestaan om documenten/bijlagen te uploaden',
|
||||
'max_file_size_help' => 'De maximale bestandsgrootte (KB) wordt beperkt door de post_max_size en upload_max_filesize variabelen zoals ingesteld in uw PHP.INI',
|
||||
'max_file_size' => 'Maximale bestandsgrootte',
|
||||
'mime_types' => 'MIME-types',
|
||||
@ -3078,7 +3078,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'filtered_by_group' => 'Filteren op groep',
|
||||
'filtered_by_invoice' => 'Filteren op factuur',
|
||||
'filtered_by_client' => 'Filteren op klant',
|
||||
'filtered_by_vendor' => 'Filteren op leverancier',
|
||||
'filtered_by_vendor' => 'Gefilterd op Leverancier',
|
||||
'group_settings' => 'Groepsinstellingen',
|
||||
'groups' => 'Groep',
|
||||
'new_group' => 'Nieuwe groep',
|
||||
@ -3174,7 +3174,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'applied' => 'Toegepast',
|
||||
'include_recent_errors' => 'Voeg recente fouten uit de logboeken toe',
|
||||
'your_message_has_been_received' => 'We hebben uw bericht ontvangen, en zullen zo spoedig mogelijk reageren. ',
|
||||
'show_product_details' => 'toon product details',
|
||||
'show_product_details' => 'Toon Productdetails',
|
||||
'show_product_details_help' => 'Neem de beschrijving en kosten op in de vervolgkeuzelijst met producten',
|
||||
'pdf_min_requirements' => 'De PDF renderaar vereist :version',
|
||||
'adjust_fee_percent' => 'Pas Vergoedingspercentage Aan',
|
||||
@ -3182,7 +3182,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'about' => 'Over',
|
||||
'credit_email' => 'Krediet E-mail',
|
||||
'domain_url' => 'Domein URL',
|
||||
'password_is_too_easy' => 'Het wachtwoord moet een hoofdletter en een nummer bevatten',
|
||||
'password_is_too_easy' => 'Het wachtwoord moet een hoofdletter en een cijfer bevatten',
|
||||
'client_portal_tasks' => 'Klantenportaal taken',
|
||||
'client_portal_dashboard' => 'Klantenportaal dashboard',
|
||||
'please_enter_a_value' => 'Voer alstublieft een waarde in',
|
||||
@ -3227,7 +3227,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'multi_line_text' => 'Multi-regelige tekst',
|
||||
'dropdown' => 'Dropdown',
|
||||
'field_type' => 'Veld type',
|
||||
'recover_password_email_sent' => 'Een wachtwoord herstel mail is verzonden',
|
||||
'recover_password_email_sent' => 'Een e-mail voor wachtwoordherstel werd verzonden',
|
||||
'removed_user' => 'Gebruiker verwijderd',
|
||||
'freq_three_years' => 'Drie jaar',
|
||||
'military_time_help' => '24-uurs weergave',
|
||||
@ -3297,9 +3297,9 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'custom_surcharge3' => 'Aangepaste toeslag 3',
|
||||
'custom_surcharge4' => 'Aangepaste toeslag 4',
|
||||
'is_deleted' => 'Is verwijderd',
|
||||
'vendor_city' => 'Stad van de klant',
|
||||
'vendor_state' => 'Leverancier provincie',
|
||||
'vendor_country' => 'Land van de verkoper',
|
||||
'vendor_city' => 'Leverancier Stad',
|
||||
'vendor_state' => 'Leverancier Provincie',
|
||||
'vendor_country' => 'Leverancier Land',
|
||||
'credit_footer' => 'Voettekst creditfactuur',
|
||||
'credit_terms' => 'Voorwaarden creditfactuur',
|
||||
'untitled_company' => 'Naamloos bedrijf',
|
||||
@ -3402,7 +3402,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'search_products' => 'Producten zoeken',
|
||||
'search_quotes' => 'Offertes zoeken',
|
||||
'search_credits' => 'Zoek creditfactuur',
|
||||
'search_vendors' => 'Zoek leveranciers',
|
||||
'search_vendors' => 'Zoek Leveranciers',
|
||||
'search_users' => 'Zoek gebruikers',
|
||||
'search_tax_rates' => 'Zoek belastingstarieven',
|
||||
'search_tasks' => 'Zoek taken',
|
||||
@ -3431,7 +3431,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'failure' => 'Fout',
|
||||
'quota_exceeded' => 'Limiet bereikt',
|
||||
'upstream_failure' => 'Upload mislukt',
|
||||
'system_logs' => 'Systeem log',
|
||||
'system_logs' => 'Systeemlogboek',
|
||||
'copy_link' => 'Link kopiëren',
|
||||
'welcome_to_invoice_ninja' => 'Welkom bij Invoice Ninja',
|
||||
'optin' => 'Inschrijven',
|
||||
@ -3519,7 +3519,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'search_product' => 'Zoek 1 product',
|
||||
'search_quote' => 'Zoek 1 offerte',
|
||||
'search_credit' => 'Zoek 1 creditfactuur',
|
||||
'search_vendor' => 'Zoek 1 leverancier',
|
||||
'search_vendor' => 'Zoek 1 Leverancier',
|
||||
'search_user' => 'Zoek 1 gebruiker',
|
||||
'search_tax_rate' => 'Zoek 1 BTW-tarief',
|
||||
'search_task' => 'Zoek 1 taak',
|
||||
@ -3691,10 +3691,10 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'archived_groups' => 'Succesvol gearchiveerd: waarde groepen',
|
||||
'deleted_groups' => 'Succesvol verwijderd: waarde groepen',
|
||||
'restored_groups' => 'Succesvol hersteld: waarde groepen',
|
||||
'archived_documents' => 'Succesvol gearchiveerd: waarde documenten',
|
||||
'deleted_documents' => 'Succesvol verwijderd: waarde documenten',
|
||||
'restored_documents' => 'Succesvol hersteld: waarde documenten',
|
||||
'restored_vendors' => 'Succesvol hersteld: waarde leveranciers',
|
||||
'archived_documents' => 'Succesvol gearchiveerd: :value document(en)',
|
||||
'deleted_documents' => 'Succesvol verwijderd: :value document(en)',
|
||||
'restored_documents' => 'Succesvol hersteld: :value document(en)',
|
||||
'restored_vendors' => 'Succesvol hersteld: :value leveranciers',
|
||||
'restored_expenses' => 'Succesvol hersteld: waarde uitgaven',
|
||||
'restored_tasks' => 'Succesvol hersteld: waarde taken',
|
||||
'restored_projects' => 'Succesvol hersteld: waarde projecten',
|
||||
@ -3729,8 +3729,8 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'save_and_email' => 'Opslaan en e-mail versturen',
|
||||
'converted_balance' => 'Omgezet saldo',
|
||||
'is_sent' => 'Is verzonden',
|
||||
'document_upload' => 'Document uploaden',
|
||||
'document_upload_help' => 'Laat klanten documenten uploaden',
|
||||
'document_upload' => 'Documenten uploaden',
|
||||
'document_upload_help' => 'Klanten toestaan om documenten te uploaden',
|
||||
'expense_total' => 'Totale uitgave',
|
||||
'enter_taxes' => 'Voer belastingen in',
|
||||
'by_rate' => 'Op tarief',
|
||||
@ -3827,7 +3827,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'per_page' => 'Per pagina',
|
||||
'of' => 'Of',
|
||||
'view_credit' => 'Toon creditfactuur',
|
||||
'to_view_entity_password' => 'Om de :entity te zien moet u een wachtwoord invoeren.',
|
||||
'to_view_entity_password' => 'Om de :entity te bekijken moet u een wachtwoord invoeren.',
|
||||
'showing_x_of' => 'Toont de :first tot :last van de :total resultaten',
|
||||
'no_results' => 'Geen resultaten gevonden.',
|
||||
'payment_failed_subject' => 'Betaling mislukt voor klant :klant',
|
||||
@ -3966,7 +3966,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'payment_message_extended' => 'Bedankt voor uw betaling van :amount voor :invoice',
|
||||
'online_payments_minimum_note' => 'Opmerking: online-betalingen worden alleen ondersteund als het bedrag hoger is dan € 1,- of het equivalent in een andere valuta.',
|
||||
'payment_token_not_found' => 'Betalingstoken niet gevonden. Probeer het opnieuw. Als het probleem zich blijft voordoen, probeer het dan met een andere betaalmethode',
|
||||
'vendor_address1' => 'Leverancier straatnaam',
|
||||
'vendor_address1' => 'Leverancier Straatnaam',
|
||||
'vendor_address2' => 'Leverancier appartement/busnr.',
|
||||
'partially_unapplied' => 'Gedeeltelijk niet toegepast',
|
||||
'select_a_gmail_user' => 'Selecteer een gebruiker die is geverifieerd met Gmail',
|
||||
@ -4022,7 +4022,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'disconnected_google' => 'Account succesvol losgekoppeld',
|
||||
'delivered' => 'Afgeleverd',
|
||||
'spam' => 'Spam',
|
||||
'view_docs' => 'Bekijk documenten',
|
||||
'view_docs' => 'Bekijk documentatie',
|
||||
'enter_phone_to_enable_two_factor' => 'Geef een mobiel telefoonnummer op om tweefactorauthenticatie in te schakelen',
|
||||
'send_sms' => 'Verzend SMS',
|
||||
'sms_code' => 'SMS Code',
|
||||
@ -4368,7 +4368,7 @@ E-mail: :email<b><br><b>',
|
||||
'to_view_entity_set_password' => 'Om de :entity te bekijken, moet u een wachtwoord instellen.',
|
||||
'unsubscribe' => 'Afmelden',
|
||||
'unsubscribed' => 'Afgemeld',
|
||||
'unsubscribed_text' => 'U bent verwijderd uit meldingen voor dit document',
|
||||
'unsubscribed_text' => 'U ontvangt geen notificaties meer voor dit document',
|
||||
'client_shipping_state' => 'Staat/provincie leveringsadres klant',
|
||||
'client_shipping_city' => 'Stad leveringsadres klant',
|
||||
'client_shipping_postal_code' => 'Postcode leveringsadres klant',
|
||||
@ -4476,13 +4476,13 @@ E-mail: :email<b><br><b>',
|
||||
'view_purchase_order' => 'Bekijk inkooporder',
|
||||
'purchase_orders_backup_subject' => 'Uw inkooporders zijn gereed om te downloaden',
|
||||
'notification_purchase_order_viewed_subject' => 'Inkooporder :invoice is bekeken door :client',
|
||||
'notification_purchase_order_viewed' => 'De volgende leverancier :client heeft inkooporder :invoice voor :amount bekeken.',
|
||||
'notification_purchase_order_viewed' => 'De leverancier :client heeft inkooporder :invoice van :amount bekeken.',
|
||||
'purchase_order_date' => 'Datum inkooporder',
|
||||
'purchase_orders' => 'Inkooporders',
|
||||
'purchase_order_number_placeholder' => 'Inkooporder #:purchase_order',
|
||||
'accepted' => 'Geaccepteerd',
|
||||
'activity_137' => ':contact geaccepteerde bestelling :purchase_order',
|
||||
'vendor_information' => 'Informatie verkoper',
|
||||
'vendor_information' => 'Leveracier Informatie',
|
||||
'notification_purchase_order_accepted_subject' => 'Inkooporder :purchase_order is geaccepteerd door :vendor',
|
||||
'notification_purchase_order_accepted' => 'De volgende leverancier :vendor heeft inkooporder :purchase_order geaccepteerd voor :amount.',
|
||||
'amount_received' => 'Bedrag ontvangen',
|
||||
@ -4491,9 +4491,9 @@ E-mail: :email<b><br><b>',
|
||||
'add_to_inventory' => 'Toevoegen aan inventaris',
|
||||
'added_purchase_order_to_inventory' => 'Inkooporder met succes aan voorraad toegevoegd',
|
||||
'added_purchase_orders_to_inventory' => 'Inkooporder met succes aan voorraad toegevoegd',
|
||||
'client_document_upload' => 'Uploaden klantdocument',
|
||||
'vendor_document_upload' => 'Verkoopdocument uploaden',
|
||||
'vendor_document_upload_help' => 'Leveranciers in staat stellen documenten te uploaden',
|
||||
'client_document_upload' => 'Klantendocumenten uploaden',
|
||||
'vendor_document_upload' => 'Leverancier Document Upload',
|
||||
'vendor_document_upload_help' => 'Leveranciers toestaan om documenten te uploaden',
|
||||
'are_you_enjoying_the_app' => 'Bevalt de app?',
|
||||
'yes_its_great' => 'Ja, het is geweldig!',
|
||||
'not_so_much' => 'Niet zo veel',
|
||||
@ -4505,12 +4505,12 @@ E-mail: :email<b><br><b>',
|
||||
'last_sent_template' => 'Laatst verzonden sjabloon',
|
||||
'enable_flexible_search' => 'Flexibel zoeken inschakelen',
|
||||
'enable_flexible_search_help' => 'Overeenkomen met niet-aangrenzende tekens, dwz. "ct" komt overeen met "kat"',
|
||||
'vendor_details' => 'Details verkoper',
|
||||
'vendor_details' => 'Leverancier Details',
|
||||
'purchase_order_details' => 'Details inkooporder',
|
||||
'qr_iban' => 'QR IBAN',
|
||||
'besr_id' => 'BESR-ID',
|
||||
'clone_to_purchase_order' => 'Kloon naar PO',
|
||||
'vendor_email_not_set' => 'Verkoper heeft geen e-mailadres ingesteld',
|
||||
'vendor_email_not_set' => 'Leverancier heeft geen e-mailadres ingesteld',
|
||||
'bulk_send_email' => 'Verzend e-mail',
|
||||
'marked_purchase_order_as_sent' => 'Inkooporder succesvol gemarkeerd als verzonden',
|
||||
'marked_purchase_orders_as_sent' => 'Inkooporders zijn gemarkeerd als verzonden',
|
||||
@ -4518,7 +4518,7 @@ E-mail: :email<b><br><b>',
|
||||
'accepted_purchase_orders' => 'Succesvol geaccepteerde inkooporders',
|
||||
'cancelled_purchase_order' => 'Inkooporder succesvol geannuleerd',
|
||||
'cancelled_purchase_orders' => 'Inkooporders succesvol geannuleerd',
|
||||
'please_select_a_vendor' => 'Gelieve een verkoper te selecteren',
|
||||
'please_select_a_vendor' => 'Gelieve een leverancier te selecteren',
|
||||
'purchase_order_total' => 'Totaal inkooporder',
|
||||
'email_purchase_order' => 'E-mail inkooporder',
|
||||
'bulk_email_purchase_order' => 'E-mail inkooporder',
|
||||
@ -4637,7 +4637,7 @@ E-mail: :email<b><br><b>',
|
||||
'category_type' => 'Categorietype',
|
||||
'bank_transaction' => 'Transactie',
|
||||
'bulk_print' => 'Druk PDF af',
|
||||
'vendor_postal_code' => 'Postcode leverancier',
|
||||
'vendor_postal_code' => 'Leverancier Postcode',
|
||||
'preview_location' => 'Voorbeeldlocatie',
|
||||
'bottom' => 'Onderkant',
|
||||
'side' => 'Kant',
|
||||
@ -4754,7 +4754,7 @@ E-mail: :email<b><br><b>',
|
||||
'backup_restore' => 'Back-up | Herstellen',
|
||||
'export_company' => 'Maak bedrijfsback-up',
|
||||
'backup' => 'Back-up',
|
||||
'notification_purchase_order_created_body' => 'De volgende purchase_order :purchase_order is gemaakt voor vendor :vendor for :amount.',
|
||||
'notification_purchase_order_created_body' => 'Inkooporder :purchase_order van :amount is aangemaakt voor leverancier :vendor.',
|
||||
'notification_purchase_order_created_subject' => 'Inkooporder :purchase_order is aangemaakt voor :vendor',
|
||||
'notification_purchase_order_sent_subject' => 'Inkooporder :purchase_order is verzonden naar :vendor',
|
||||
'notification_purchase_order_sent' => 'De volgende leverancier :vendor kreeg een inkooporder per e-mail :purchase_order voor :amount.',
|
||||
@ -5020,7 +5020,7 @@ E-mail: :email<b><br><b>',
|
||||
'currency_swazi_lilangeni' => 'Swazische Lilangeni',
|
||||
'income' => 'Inkomen',
|
||||
'amount_received_help' => 'Vul hier een waarde in als het totaal ontvangen bedrag MEER was dan het factuurbedrag, of bij het vastleggen van een betaling zonder facturen. Anders moet dit veld leeg worden gelaten.',
|
||||
'vendor_phone' => 'Verkoper telefoon',
|
||||
'vendor_phone' => 'Leverancier Telefoonnummer',
|
||||
'mercado_pago' => 'Mercado Pago',
|
||||
'mybank' => 'Mijn bank',
|
||||
'paypal_paylater' => 'Betaal in 4',
|
||||
@ -5065,7 +5065,7 @@ E-mail: :email<b><br><b>',
|
||||
'charity' => 'Goed doel',
|
||||
'government' => 'Overheid',
|
||||
'in_stock_quantity' => 'Voorraadhoeveelheid',
|
||||
'vendor_contact' => 'Contactpersoon leverancier',
|
||||
'vendor_contact' => 'Leverancier Contactpersoon',
|
||||
'expense_status_4' => 'Onbetaald',
|
||||
'expense_status_5' => 'Betaald',
|
||||
'ziptax_help' => 'Let op: deze functie vereist een Zip-Tax API-sleutel om de Amerikaanse omzetbelasting op adres op te zoeken',
|
||||
@ -5111,7 +5111,7 @@ E-mail: :email<b><br><b>',
|
||||
'payment_email_all_contacts_help' => 'Stuurt de betalings-e-mail naar alle contacten indien ingeschakeld',
|
||||
'add_line' => 'Lijn toevoegen',
|
||||
'activity_139' => 'Melding onkosten :expense verzonden naar :contact',
|
||||
'vendor_notification_subject' => 'Bevestiging van betaling :amount verzonden naar :vendor',
|
||||
'vendor_notification_subject' => 'Bevestiging van betaling van :amount verzonden naar :vendor',
|
||||
'vendor_notification_body' => 'Betaling verwerkt voor :amount gedateerd :payment _date.<br> [Transactiereferentie: :transaction_reference ]',
|
||||
'receipt' => 'Ontvangst',
|
||||
'charges' => 'Kosten',
|
||||
@ -5309,7 +5309,11 @@ E-mail: :email<b><br><b>',
|
||||
'account_holder_information' => 'Rekeninghouderinformatie',
|
||||
'enter_information_for_the_account_holder' => 'Voer de gegevens in van de rekeninghouder',
|
||||
'customer_type' => 'Klanttype',
|
||||
'process_date' => 'Verwerkingsdatum'
|
||||
'process_date' => 'Verwerkingsdatum',
|
||||
'forever_free' => 'Voor altijd gratis',
|
||||
'comments_only' => 'Alleen opmerkingen',
|
||||
'payment_balance_on_file' => 'Huidig saldo',
|
||||
'ubl_email_attachment_help' => 'Voor meer e-factuurinstellingen, navigeer naar :here',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -1646,7 +1646,7 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
|
||||
'country_Turkey' => 'Turquia',
|
||||
'country_Turkmenistan' => 'Turcomenistão',
|
||||
'country_Turks and Caicos Islands' => 'Ilhas Turks e Caicos',
|
||||
'country_Tuvalu' => 'Tuvalu',
|
||||
'country_Tuvalu' => ' Tuvalu',
|
||||
'country_Uganda' => 'Uganda',
|
||||
'country_Ukraine' => 'Ucrânia',
|
||||
'country_Macedonia, the former Yugoslav Republic of' => 'Macedônia, antiga República Iugoslava',
|
||||
@ -3441,7 +3441,7 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
|
||||
'reminder2_sent' => 'Lembrete 2 Enviado',
|
||||
'reminder3_sent' => 'Lembrete 3 Enviado',
|
||||
'reminder_last_sent' => 'Último Lembrete Enviado',
|
||||
'pdf_page_info' => 'Página: atual de: total',
|
||||
'pdf_page_info' => 'Página: :current de: :total',
|
||||
'emailed_credits' => 'Créditos enviados por e-mail com sucesso',
|
||||
'view_in_stripe' => 'Ver em Listra',
|
||||
'rows_per_page' => 'Linhas por Página',
|
||||
@ -5121,7 +5121,7 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
|
||||
'all_contacts' => 'Todos os contatos',
|
||||
'insert_below' => 'Inserir abaixo',
|
||||
'nordigen_handler_subtitle' => 'Autenticação de conta bancária. Selecionando sua instituição para concluir a solicitação com as credenciais de sua conta.',
|
||||
'nordigen_handler_error_heading_unknown' => 'Ocorreu um erro',
|
||||
'nordigen_handler_error_heading_unknown' => 'An error has occurred',
|
||||
'nordigen_handler_error_contents_unknown' => 'Um erro desconhecido ocorreu! Razão:',
|
||||
'nordigen_handler_error_heading_token_invalid' => 'Token inválido',
|
||||
'nordigen_handler_error_contents_token_invalid' => 'O token fornecido era inválido. Entre em contato com o suporte para obter ajuda, se o problema persistir.',
|
||||
@ -5235,7 +5235,7 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
'always_show_required_fields' => 'Allows show required fields form',
|
||||
'always_show_required_fields' => 'Always show required fields form',
|
||||
'always_show_required_fields_help' => 'Displays the required fields form always at checkout',
|
||||
'advanced_cards' => 'Advanced Cards',
|
||||
'activity_140' => 'Statement sent to :client',
|
||||
@ -5298,6 +5298,16 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
|
||||
'latest_requires_php_version' => 'Note: the latest version requires PHP :version',
|
||||
'auto_expand_product_table_notes' => 'Automatically expand products table notes',
|
||||
'auto_expand_product_table_notes_help' => 'Automatically expands the notes section within the products table to display more lines.',
|
||||
'institution_number' => 'Institution Number',
|
||||
'transit_number' => 'Transit Number',
|
||||
'personal' => 'Personal',
|
||||
'address_information' => 'Address Information',
|
||||
'enter_the_information_for_the_bank_account' => 'Enter the Information for the Bank Account',
|
||||
'account_holder_information' => 'Account Holder Information',
|
||||
'enter_information_for_the_account_holder' => 'Enter Information for the Account Holder',
|
||||
'customer_type' => 'Customer Type',
|
||||
'process_date' => 'Process Date',
|
||||
'forever_free' => 'Forever Free',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -3443,7 +3443,7 @@ debitar da sua conta de acordo com essas instruções. Está elegível a um reem
|
||||
'reminder2_sent' => 'Lembrete 2 Enviado',
|
||||
'reminder3_sent' => 'Lembrete 3 Enviado',
|
||||
'reminder_last_sent' => 'Último Lembrete Enviado',
|
||||
'pdf_page_info' => 'Página: atual de: total',
|
||||
'pdf_page_info' => 'Página: :current de: :total',
|
||||
'emailed_credits' => 'Créditos enviados por e-mail com sucesso',
|
||||
'view_in_stripe' => 'Ver em Formato Lista',
|
||||
'rows_per_page' => 'Colunas por Página',
|
||||
|
@ -1,9 +0,0 @@
|
||||
var a=Object.defineProperty;var d=(n,e,t)=>e in n?a(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var r=(n,e,t)=>(d(n,typeof e!="symbol"?e+"":e,t),t);/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/class o{constructor(e){r(this,"handleAuthorization",()=>{var e=$("#my-card"),t={api_login_id:this.apiLoginId,card_number:e.CardJs("cardNumber").replace(/[^\d]/g,""),expire_year:e.CardJs("expiryYear").replace(/[^\d]/g,""),expire_month:e.CardJs("expiryMonth").replace(/[^\d]/g,""),cvv:document.getElementById("cvv").value.replace(/[^\d]/g,"")};return document.getElementById("pay-now")&&(document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden")),forte.createToken(t).success(this.successResponseHandler).error(this.failedResponseHandler),!1});r(this,"successResponseHandler",e=>(document.getElementById("payment_token").value=e.onetime_token,document.getElementById("card_brand").value=e.card_type,document.getElementById("server_response").submit(),!1));r(this,"failedResponseHandler",e=>{var t='<div class="alert alert-failure mb-4"><ul><li>'+e.response_description+"</li></ul></div>";return document.getElementById("forte_errors").innerHTML=t,document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden"),!1});r(this,"handle",()=>{let e=document.getElementById("pay-now");return e&&e.addEventListener("click",t=>{this.handleAuthorization()}),this});this.apiLoginId=e,this.cardHolderName=document.getElementById("cardholder_name")}}const s=document.querySelector('meta[name="forte-api-login-id"]').content;new o(s).handle();
|
9
public/build/assets/forte-credit-card-payment-d2571506.js
vendored
Normal file
9
public/build/assets/forte-credit-card-payment-d2571506.js
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
var r=Object.defineProperty;var l=(n,e,t)=>e in n?r(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var d=(n,e,t)=>(l(n,typeof e!="symbol"?e+"":e,t),t);/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/class c{constructor(e){d(this,"handleAuthorization",()=>{var e=$("#my-card"),t={api_login_id:this.apiLoginId,card_number:e.CardJs("cardNumber").replace(/[^\d]/g,""),expire_year:e.CardJs("expiryYear").replace(/[^\d]/g,""),expire_month:e.CardJs("expiryMonth").replace(/[^\d]/g,""),cvv:document.getElementById("cvv").value.replace(/[^\d]/g,"")};return document.getElementById("pay-now")&&(document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden")),forte.createToken(t).success(this.successResponseHandler).error(this.failedResponseHandler),!1});d(this,"successResponseHandler",e=>{document.getElementById("payment_token").value=e.onetime_token,document.getElementById("card_brand").value=e.card_type,document.getElementById("expire_year").value=e.expire_year,document.getElementById("expire_month").value=e.expire_month,document.getElementById("last_4").value=e.last_4;let t=document.querySelector("input[name=token-billing-checkbox]:checked");return t&&(document.getElementById("store_card").value=t.value),document.getElementById("server_response").submit(),!1});d(this,"failedResponseHandler",e=>{var t='<div class="alert alert-failure mb-4"><ul><li>'+e.response_description+"</li></ul></div>";return document.getElementById("forte_errors").innerHTML=t,document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden"),!1});d(this,"handle",()=>{Array.from(document.getElementsByClassName("toggle-payment-with-token")).forEach(o=>o.addEventListener("click",a=>{document.getElementById("save-card--container").style.display="none",document.getElementById("forte--credit-card-container").style.display="none",document.getElementById("token").value=a.target.dataset.token}));let e=document.getElementById("toggle-payment-with-credit-card");e&&e.addEventListener("click",()=>{document.getElementById("save-card--container").style.display="grid",document.getElementById("forte--credit-card-container").style.display="flex",document.getElementById("token").value=null});let t=document.getElementById("pay-now");return t&&t.addEventListener("click",o=>{let a=document.getElementById("token");a.value?this.handlePayNowAction(a.value):this.handleAuthorization()}),this});this.apiLoginId=e,this.cardHolderName=document.getElementById("cardholder_name")}handlePayNowAction(e){document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),document.getElementById("token").value=e,document.getElementById("server_response").submit()}}const i=document.querySelector('meta[name="forte-api-login-id"]').content;new c(i).handle();
|
@ -86,7 +86,7 @@
|
||||
"src": "resources/js/clients/payments/forte-ach-payment.js"
|
||||
},
|
||||
"resources/js/clients/payments/forte-credit-card-payment.js": {
|
||||
"file": "assets/forte-credit-card-payment-b605ccf2.js",
|
||||
"file": "assets/forte-credit-card-payment-d2571506.js",
|
||||
"isEntry": true,
|
||||
"src": "resources/js/clients/payments/forte-credit-card-payment.js"
|
||||
},
|
||||
|
@ -41,8 +41,18 @@ class ForteAuthorizeCard {
|
||||
};
|
||||
|
||||
successResponseHandler = (response) => {
|
||||
|
||||
document.getElementById('payment_token').value = response.onetime_token;
|
||||
document.getElementById('card_brand').value = response.card_type;
|
||||
document.getElementById('card_brand').value = response.card_brand;
|
||||
document.getElementById('expire_year').value = response.expire_year;
|
||||
document.getElementById('expire_month').value = response.expire_month;
|
||||
document.getElementById('last_4').value = response.last_4;
|
||||
|
||||
let storeCard = document.querySelector('input[name=token-billing-checkbox]:checked');
|
||||
|
||||
if (storeCard) {
|
||||
document.getElementById("store_card").value = storeCard.value;
|
||||
}
|
||||
|
||||
document.getElementById('server_response').submit();
|
||||
|
||||
@ -62,17 +72,94 @@ class ForteAuthorizeCard {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
handlePayNowAction(token_hashed_id) {
|
||||
document.getElementById('pay-now').disabled = true;
|
||||
document.querySelector('#pay-now > svg').classList.remove('hidden');
|
||||
document.querySelector('#pay-now > span').classList.add('hidden');
|
||||
|
||||
document.getElementById("token").value = token_hashed_id;
|
||||
document.getElementById("server_response").submit();
|
||||
}
|
||||
|
||||
|
||||
handle = () => {
|
||||
Array
|
||||
.from(document.getElementsByClassName('toggle-payment-with-token'))
|
||||
.forEach((element) => element.addEventListener('click', (e) => {
|
||||
document
|
||||
.getElementById('save-card--container').style.display = 'none';
|
||||
document
|
||||
.getElementById('forte--credit-card-container').style.display = 'none';
|
||||
|
||||
document
|
||||
.getElementById('token').value = e.target.dataset.token;
|
||||
}));
|
||||
|
||||
let payWithCreditCardToggle = document.getElementById('toggle-payment-with-credit-card');
|
||||
|
||||
if (payWithCreditCardToggle) {
|
||||
payWithCreditCardToggle
|
||||
.addEventListener('click', () => {
|
||||
document
|
||||
.getElementById('save-card--container').style.display = 'grid';
|
||||
document
|
||||
.getElementById('forte--credit-card-container').style.display = 'flex';
|
||||
|
||||
document
|
||||
.getElementById('token').value = null;
|
||||
});
|
||||
}
|
||||
|
||||
let payNowButton = document.getElementById('pay-now');
|
||||
|
||||
if (payNowButton) {
|
||||
payNowButton.addEventListener('click', (e) => {
|
||||
this.handleAuthorization();
|
||||
payNowButton
|
||||
.addEventListener('click', (e) => {
|
||||
let token = document.getElementById('token');
|
||||
|
||||
token.value
|
||||
? this.handlePayNowAction(token.value)
|
||||
: this.handleAuthorization();
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
const apiLoginId = document.querySelector(
|
||||
|
@ -2,6 +2,13 @@
|
||||
@section('meta_title', ctrans('texts.dashboard'))
|
||||
|
||||
@section('body')
|
||||
|
||||
@if($client->getSetting('custom_message_dashboard'))
|
||||
@component('portal.ninja2020.components.message')
|
||||
<pre>{{ $client->getSetting('custom_message_dashboard') }}</pre>
|
||||
@endcomponent
|
||||
@endif
|
||||
|
||||
<div class="flex flex-col xl:flex-row gap-4">
|
||||
<div class="w-full rounded-md border border-[#E5E7EB] bg-white p-5 text-sm text-[#6C727F]">
|
||||
<h3 class="mb-4 text-xl font-semibold text-[#212529]">{{ $contact->first_name }} {{ $contact->last_name }}</h3>
|
||||
|
@ -12,6 +12,9 @@
|
||||
<form action="{{ route('client.payments.response') }}" method="post" id="server_response">
|
||||
@csrf
|
||||
<input type="hidden" name="card_brand" id="card_brand">
|
||||
<input type="hidden" name="expire_year" id="expire_year">
|
||||
<input type="hidden" name="expire_month" id="expire_month">
|
||||
<input type="hidden" name="last_4" id="last_4">
|
||||
<input type="hidden" name="payment_token" id="payment_token">
|
||||
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
|
||||
<input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}">
|
||||
@ -32,10 +35,39 @@
|
||||
|
||||
@include('portal.ninja2020.gateways.includes.payment_details')
|
||||
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => 'Pay with Credit Card'])
|
||||
@include('portal.ninja2020.gateways.forte.includes.credit_card')
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
|
||||
<ul class="list-none">
|
||||
@if(count($tokens) > 0)
|
||||
@foreach($tokens as $token)
|
||||
<li class="py-2">
|
||||
<label class="mr-4 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
data-token="{{ $token->hashed_id }}"
|
||||
name="payment-type"
|
||||
class="form-radio cursor-pointer toggle-payment-with-token"/>
|
||||
<span class="ml-1 cursor-pointer">**** {{ $token->meta?->last4 }}</span>
|
||||
</label>
|
||||
</li>
|
||||
@endforeach
|
||||
@endisset
|
||||
|
||||
<li class="py-2">
|
||||
<label class="mr-4 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
id="toggle-payment-with-credit-card"
|
||||
class="form-radio cursor-pointer"
|
||||
name="payment-type"
|
||||
checked/>
|
||||
<span class="ml-1 cursor-pointer">{{ __('texts.new_card') }}</span>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
@endcomponent
|
||||
|
||||
@include('portal.ninja2020.gateways.includes.save_card')
|
||||
@include('portal.ninja2020.gateways.forte.includes.credit_card')
|
||||
@include('portal.ninja2020.gateways.includes.pay_now')
|
||||
|
||||
@endsection
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||
style="display: flex!important; justify-content: center!important;" id="authorize--credit-card-container">
|
||||
style="display: flex!important; justify-content: center!important;" id="forte--credit-card-container">
|
||||
<div class="card-js" id="my-card" data-capture-name="true">
|
||||
<input class="name" id="cardholder_name" name="card_holders_name" placeholder="{{ ctrans('texts.name')}}">
|
||||
<input class="card-number my-custom-class" id="card_number">
|
||||
|
@ -51,10 +51,10 @@
|
||||
@include('portal.ninja2020.gateways.includes.payment_details')
|
||||
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
|
||||
<ul class="list-none hover:list-disc">
|
||||
<ul class="list-none">
|
||||
@if(count($tokens) > 0)
|
||||
@foreach($tokens as $token)
|
||||
<li class="py-2 hover:text-blue hover:bg-blue-600">
|
||||
<li class="py-2 cursor-pointer">
|
||||
<label class="mr-4">
|
||||
<input
|
||||
type="radio"
|
||||
@ -67,7 +67,7 @@
|
||||
@endforeach
|
||||
@endisset
|
||||
|
||||
<li class="py-2 hover:text-blue hover:bg-blue-600">
|
||||
<li class="py-2 cursor-pointer">
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
|
@ -2,6 +2,17 @@
|
||||
@section('meta_title', ctrans('texts.payment_methods'))
|
||||
|
||||
@section('body')
|
||||
|
||||
@section('header')
|
||||
@if($errors->any())
|
||||
<div class="alert alert-failure mb-4">
|
||||
@foreach($errors->all() as $error)
|
||||
<p>{{ $error }}</p>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
@endsection
|
||||
|
||||
<div class="flex flex-col">
|
||||
@livewire('payment-methods-table', ['client_id' => $client->id, 'db' => $company->db])
|
||||
</div>
|
||||
|
@ -67,10 +67,8 @@ class PeppolTest extends TestCase
|
||||
$settings->country_id = '276';
|
||||
$settings->currency_id = '3';
|
||||
|
||||
|
||||
$einvoice = new \InvoiceNinja\EInvoice\Models\Peppol\Invoice();
|
||||
|
||||
|
||||
$fib = new FinancialInstitutionBranch();
|
||||
$fib->ID = "DEUTDEMMXXX"; //BIC
|
||||
$fib->Name = 'Deutsche Bank';
|
||||
@ -88,10 +86,13 @@ class PeppolTest extends TestCase
|
||||
$pm->PayeeFinancialAccount = $pfa;
|
||||
$einvoice->PaymentMeans[] = $pm;
|
||||
|
||||
$stub = new \stdClass;
|
||||
$stub->Invoice = $einvoice;
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
'e_invoice' => $einvoice,
|
||||
'e_invoice' => $stub,
|
||||
]);
|
||||
|
||||
$cu = CompanyUserFactory::create($this->user->id, $company->id, $this->account->id);
|
||||
@ -149,11 +150,12 @@ class PeppolTest extends TestCase
|
||||
|
||||
$this->assertEquals(119, $invoice->amount);
|
||||
|
||||
|
||||
$peppol = new Peppol($invoice);
|
||||
$peppol->setInvoiceDefaults();
|
||||
$peppol->run();
|
||||
|
||||
nlog($peppol->toXml());
|
||||
|
||||
$de_invoice = $peppol->getInvoice();
|
||||
|
||||
$this->assertNotNull($de_invoice);
|
||||
@ -207,10 +209,14 @@ class PeppolTest extends TestCase
|
||||
$pm->PayeeFinancialAccount = $pfa;
|
||||
$einvoice->PaymentMeans[] = $pm;
|
||||
|
||||
|
||||
$stub = new \stdClass();
|
||||
$stub->Invoice = $einvoice;
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
'e_invoice' => $einvoice,
|
||||
'e_invoice' => $stub,
|
||||
]);
|
||||
|
||||
$cu = CompanyUserFactory::create($this->user->id, $company->id, $this->account->id);
|
||||
|
@ -314,21 +314,23 @@ class ExpenseApiTest extends TestCase
|
||||
public function testExpenseBulkCategorize()
|
||||
{
|
||||
|
||||
$eXX = Expense::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
]);
|
||||
|
||||
|
||||
$e = Expense::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
]);
|
||||
|
||||
|
||||
$ec = ExpenseCategory::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'name' => 'Test Category',
|
||||
]);
|
||||
|
||||
nlog("expense category id = {$ec->hashed_id}");
|
||||
|
||||
$data = [
|
||||
'category_id' => $ec->hashed_id,
|
||||
'action' => 'bulk_categorize',
|
||||
@ -341,11 +343,32 @@ class ExpenseApiTest extends TestCase
|
||||
])->post('/api/v1/expenses/bulk', $data);
|
||||
|
||||
$arr = $response->json();
|
||||
nlog($arr);
|
||||
|
||||
$this->assertEquals($ec->hashed_id, $arr['data'][0]['category_id']);
|
||||
}
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->get("/api/v1/expenses");
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertGreaterThan(1, count($arr['data']));
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->get("/api/v1/expenses?categories={$ec->hashed_id}");
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertCount(1, $arr['data']);
|
||||
|
||||
}
|
||||
|
||||
public function testAddingExpense()
|
||||
{
|
||||
|
@ -69,7 +69,7 @@ class InvoiceEmailTest extends TestCase
|
||||
$system_log->log = [
|
||||
'history' => [
|
||||
'entity_id' => $this->invoice->hashed_id,
|
||||
'entity_type' => 'invoice',
|
||||
'entity' => 'invoice',
|
||||
'subject' => 'Invoice #1',
|
||||
'events' => [
|
||||
[
|
||||
@ -96,7 +96,7 @@ class InvoiceEmailTest extends TestCase
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals('invoice', $arr[0]['entity_type']);
|
||||
$this->assertEquals('invoice', $arr[0]['entity']);
|
||||
|
||||
$count = SystemLog::where('client_id', $this->client->id)
|
||||
->where('category_id', SystemLog::CATEGORY_MAIL)
|
||||
@ -117,7 +117,7 @@ class InvoiceEmailTest extends TestCase
|
||||
$system_log->log = [
|
||||
'history' => [
|
||||
'entity_id' => $this->invoice->hashed_id,
|
||||
'entity_type' => 'invoice',
|
||||
'entity' => 'invoice',
|
||||
'subject' => 'Invoice #1',
|
||||
'events' => [
|
||||
[
|
||||
@ -147,8 +147,8 @@ class InvoiceEmailTest extends TestCase
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals('invoice', $arr[0]['entity_type']);
|
||||
nlog($arr);
|
||||
$this->assertEquals('invoice', $arr[0]['entity']);
|
||||
$this->assertEquals($this->invoice->hashed_id, $arr[0]['entity_id']);
|
||||
|
||||
$count = SystemLog::where('company_id', $this->company->id)
|
||||
|
@ -224,6 +224,25 @@ class TaskApiTest extends TestCase
|
||||
])->postJson("/api/v1/tasks", $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
$arr = $response->json();
|
||||
|
||||
$data = [
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'description' => 'Test Task',
|
||||
'time_log' => '[""]',
|
||||
'assigned_user' => [],
|
||||
'project' => [],
|
||||
'user' => [],
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->putJson("/api/v1/tasks/".$arr['data']['id'], $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
|
||||
}
|
||||
public function testUserFilters()
|
||||
|
@ -28,7 +28,7 @@ class StorecoveTest extends TestCase
|
||||
use MockAccountData;
|
||||
use DatabaseTransactions;
|
||||
|
||||
private string $routing_id = '';
|
||||
private int $routing_id;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
@ -352,11 +352,11 @@ $x = '<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
$sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
|
||||
$sc->sendDocument($x);
|
||||
$sc->sendDocument($x, 290868);
|
||||
|
||||
}
|
||||
*/
|
||||
public function testCreateCHClient()
|
||||
public function XXestCreateCHClient()
|
||||
{
|
||||
|
||||
Client::unguard();
|
||||
@ -398,29 +398,137 @@ $x = '<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
}
|
||||
|
||||
private function createDEData()
|
||||
private function createESData()
|
||||
{
|
||||
|
||||
$this->routing_id = '290868';
|
||||
$this->routing_id = 293098;
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->company_logo = 'https://pdf.invoicing.co/favicon-v2.png';
|
||||
$settings->website = 'www.invoiceninja.de';
|
||||
$settings->address1 = 'Musterstraße 1';
|
||||
$settings->address2 = 'Etage 2, Büro 3';
|
||||
$settings->city = 'Berlin';
|
||||
$settings->state = 'Berlin';
|
||||
$settings->postal_code = '10115';
|
||||
$settings->address1 = 'Calle Gran Vía, 28';
|
||||
$settings->address2 = 'Edificio Telefónica';
|
||||
$settings->city = 'Madrid';
|
||||
$settings->state = 'Madrid';
|
||||
$settings->postal_code = '28013';
|
||||
$settings->phone = '030 1234567';
|
||||
$settings->email = $this->faker->unique()->safeEmail();
|
||||
$settings->country_id = '276'; // Germany's ISO country code
|
||||
$settings->vat_number = 'DE123456789';
|
||||
$settings->country_id = '724'; // Germany's ISO country code
|
||||
$settings->vat_number = 'ESB16645678';
|
||||
$settings->id_number = 'HRB 12345';
|
||||
$settings->use_credits_payment = 'always';
|
||||
$settings->timezone_id = '1'; // CET (Central European Time)
|
||||
$settings->entity_send_time = 0;
|
||||
$settings->e_invoice_type = 'PEPPOL';
|
||||
$settings->currency_id = '3';
|
||||
$settings->classification = 'business';
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
]);
|
||||
|
||||
$this->user->companies()->attach($company->id, [
|
||||
'account_id' => $this->account->id,
|
||||
'is_owner' => true,
|
||||
'is_admin' => 1,
|
||||
'is_locked' => 0,
|
||||
'permissions' => '',
|
||||
'notifications' => CompanySettings::notificationAdminDefaults(),
|
||||
'settings' => null,
|
||||
]);
|
||||
|
||||
Client::unguard();
|
||||
|
||||
$c =
|
||||
Client::create([
|
||||
'company_id' => $company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'name' => 'Empresa Ejemplo S.A.',
|
||||
'website' => 'https://www.empresa-ejemplo.es',
|
||||
'private_notes' => 'Estas son notas privadas para el cliente de prueba.',
|
||||
'balance' => 0,
|
||||
'paid_to_date' => 0,
|
||||
'vat_number' => 'ESB12345678', // Spanish VAT number with ES prefix
|
||||
'id_number' => 'B12345678', // Typical format for Spanish company registration numbers
|
||||
'custom_value1' => '2024-07-22 10:00:00',
|
||||
'custom_value2' => 'azul', // Spanish for blue
|
||||
'custom_value3' => 'palabraejemplo', // Spanish for sample word
|
||||
'custom_value4' => 'test@ejemplo.com',
|
||||
'address1' => 'Calle Ejemplo 123',
|
||||
'address2' => '2ª Planta, Oficina 45',
|
||||
'city' => 'Madrid',
|
||||
'state' => 'Madrid',
|
||||
'postal_code' => '28013',
|
||||
'country_id' => '724', // Spain
|
||||
'shipping_address1' => 'Calle Ejemplo 123',
|
||||
'shipping_address2' => '2ª Planta, Oficina 45',
|
||||
'shipping_city' => 'Madrid',
|
||||
'shipping_state' => 'Madrid',
|
||||
'shipping_postal_code' => '28013',
|
||||
'shipping_country_id' => '724', // Spain
|
||||
'settings' => ClientSettings::Defaults(),
|
||||
'client_hash' => \Illuminate\Support\Str::random(32),
|
||||
'routing_id' => '',
|
||||
]);
|
||||
|
||||
$item = new InvoiceItem();
|
||||
$item->product_key = "Product Key";
|
||||
$item->notes = "Product Description";
|
||||
$item->cost = 10;
|
||||
$item->quantity = 10;
|
||||
$item->tax_rate1 = 21;
|
||||
$item->tax_name1 = 'IVA';
|
||||
|
||||
$invoice = Invoice::factory()->create([
|
||||
'company_id' => $company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $c->id,
|
||||
'discount' => 0,
|
||||
'uses_inclusive_taxes' => false,
|
||||
'status_id' => 1,
|
||||
'tax_rate1' => 0,
|
||||
'tax_name1' => '',
|
||||
'tax_rate2' => 0,
|
||||
'tax_rate3' => 0,
|
||||
'tax_name2' => '',
|
||||
'tax_name3' => '',
|
||||
'line_items' => [$item],
|
||||
'number' => 'ES-'.rand(1000, 100000),
|
||||
'date' => now()->format('Y-m-d'),
|
||||
'due_date' => now()->addDays(14)->format('Y-m-d'),
|
||||
]);
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
$invoice->service()->markSent()->save();
|
||||
|
||||
return $invoice;
|
||||
|
||||
}
|
||||
|
||||
private function createFRData()
|
||||
{
|
||||
$this->routing_id = 293338;
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->company_logo = 'https://pdf.invoicing.co/favicon-v2.png';
|
||||
$settings->website = 'www.invoiceninja.de';
|
||||
|
||||
$settings->address1 = '10 Rue de la Paix';
|
||||
$settings->address2 = 'Bâtiment A, Bureau 5';
|
||||
$settings->city = 'Paris';
|
||||
$settings->state = 'Île-de-France';
|
||||
$settings->postal_code = '75002';
|
||||
$settings->phone = '01 23456789';
|
||||
$settings->email = $this->faker->unique()->safeEmail();
|
||||
$settings->country_id = '250'; // France's ISO country code
|
||||
$settings->vat_number = 'FR82345678911';
|
||||
$settings->id_number = '12345678900010';
|
||||
$settings->classification = 'business';
|
||||
$settings->use_credits_payment = 'always';
|
||||
$settings->timezone_id = '1'; // CET (Central European Time)
|
||||
$settings->entity_send_time = 0;
|
||||
$settings->e_invoice_type = 'PEPPOL';
|
||||
$settings->currency_id = '3';
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
@ -443,29 +551,30 @@ $x = '<?xml version="1.0" encoding="utf-8"?>
|
||||
Client::create([
|
||||
'company_id' => $company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'name' => 'Beispiel Firma GmbH',
|
||||
'website' => 'https://www.beispiel-firma.de',
|
||||
'private_notes' => 'Dies sind private Notizen zum Testkunden.',
|
||||
'name' => 'Exemple Société S.A.',
|
||||
'website' => 'https://www.exemple-societe.fr',
|
||||
'private_notes' => 'Ceci est une note privée pour le client test.',
|
||||
'balance' => 0,
|
||||
'paid_to_date' => 0,
|
||||
'vat_number' => 'DE654321987',
|
||||
'id_number' => 'HRB 12345', // Typical format for German company registration numbers
|
||||
'vat_number' => 'FR12345678901',
|
||||
'id_number' => '12345678900010', // Typical format for French company registration numbers
|
||||
'custom_value1' => '2024-07-22 10:00:00',
|
||||
'custom_value2' => 'blau',
|
||||
'custom_value3' => 'musterwort',
|
||||
'custom_value2' => 'bleu',
|
||||
'custom_value3' => 'motexemple',
|
||||
'custom_value4' => 'test@example.com',
|
||||
'address1' => 'Musterstraße 123',
|
||||
'address2' => '2. Etage, Büro 45',
|
||||
'city' => 'München',
|
||||
'state' => 'Bayern',
|
||||
'postal_code' => '80331',
|
||||
'country_id' => '276', // Germany
|
||||
'shipping_address1' => 'Musterstraße 123',
|
||||
'shipping_address2' => '2. Etage, Büro 45',
|
||||
'shipping_city' => 'München',
|
||||
'shipping_state' => 'Bayern',
|
||||
'shipping_postal_code' => '80331',
|
||||
'shipping_country_id' => '276', // Germany
|
||||
'address1' => '123 Rue de l\'Exemple',
|
||||
'address2' => '2ème étage, Bureau 45',
|
||||
'city' => 'Paris',
|
||||
'state' => 'Île-de-France',
|
||||
'postal_code' => '75001',
|
||||
'country_id' => '250', // France
|
||||
'shipping_address1' => '123 Rue de l\'Exemple',
|
||||
'shipping_address2' => '2ème étage, Bureau 45',
|
||||
'shipping_city' => 'Paris',
|
||||
'shipping_state' => 'Île-de-France',
|
||||
'shipping_postal_code' => '75001',
|
||||
'shipping_country_id' => '250', // France
|
||||
'classification' => 'business',
|
||||
'settings' => ClientSettings::Defaults(),
|
||||
'client_hash' => \Illuminate\Support\Str::random(32),
|
||||
'routing_id' => '',
|
||||
@ -477,8 +586,8 @@ $x = '<?xml version="1.0" encoding="utf-8"?>
|
||||
$item->notes = "Product Description";
|
||||
$item->cost = 10;
|
||||
$item->quantity = 10;
|
||||
$item->tax_rate1 = 19;
|
||||
$item->tax_name1 = 'mwst';
|
||||
$item->tax_rate1 = 20;
|
||||
$item->tax_name1 = 'VAT';
|
||||
|
||||
$invoice = Invoice::factory()->create([
|
||||
'company_id' => $company->id,
|
||||
@ -495,7 +604,8 @@ $x = '<?xml version="1.0" encoding="utf-8"?>
|
||||
'tax_name3' => '',
|
||||
'line_items' => [$item],
|
||||
'number' => 'DE-'.rand(1000, 100000),
|
||||
'date' => now()->format('Y-m-d')
|
||||
'date' => now()->format('Y-m-d'),
|
||||
'due_date' => now()->addDays(14)->format('Y-m-d'),
|
||||
]);
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
@ -506,7 +616,253 @@ $x = '<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
}
|
||||
|
||||
public function testDeRules()
|
||||
private function createATData(bool $is_gov = false)
|
||||
{
|
||||
|
||||
$this->routing_id = 293801;
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->company_logo = 'https://pdf.invoicing.co/favicon-v2.png';
|
||||
$settings->website = 'www.invoiceninja.at';
|
||||
$settings->address1 = 'Musterstraße 1';
|
||||
$settings->address2 = 'Stockwerk 2, Büro 3';
|
||||
$settings->city = 'Vienna';
|
||||
$settings->state = 'Vienna';
|
||||
$settings->postal_code = '1010';
|
||||
$settings->phone = '+43 1 23456789';
|
||||
$settings->email = $this->faker->unique()->safeEmail();
|
||||
$settings->country_id = '40'; // Austria's ISO country code
|
||||
$settings->vat_number = 'ATU92335648';
|
||||
$settings->id_number = 'FN 123456x';
|
||||
$settings->use_credits_payment = 'always';
|
||||
$settings->timezone_id = '1'; // CET (Central European Time)
|
||||
$settings->entity_send_time = 0;
|
||||
$settings->e_invoice_type = 'PEPPOL';
|
||||
$settings->currency_id = '3';
|
||||
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
]);
|
||||
|
||||
$this->user->companies()->attach($company->id, [
|
||||
'account_id' => $this->account->id,
|
||||
'is_owner' => true,
|
||||
'is_admin' => 1,
|
||||
'is_locked' => 0,
|
||||
'permissions' => '',
|
||||
'notifications' => CompanySettings::notificationAdminDefaults(),
|
||||
'settings' => null,
|
||||
]);
|
||||
|
||||
Client::unguard();
|
||||
|
||||
$c =
|
||||
Client::create([
|
||||
'company_id' => $company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'name' => 'Beispiel Firma GmbH',
|
||||
'website' => 'https://www.beispiel-firma.at',
|
||||
'private_notes' => 'Dies sind private Notizen zum Testkunden.',
|
||||
'balance' => 0,
|
||||
'paid_to_date' => 0,
|
||||
'vat_number' => 'ATU87654321',
|
||||
'id_number' => $is_gov ? 'ATU12312321' : 'FN 123456x', // Example format for Austrian company registration numbers
|
||||
'custom_value1' => '2024-07-22 10:00:00',
|
||||
'custom_value2' => 'blau',
|
||||
'custom_value3' => 'musterwort',
|
||||
'custom_value4' => 'test@example.com',
|
||||
'address1' => 'Musterstraße 123',
|
||||
'address2' => '2. Etage, Büro 45',
|
||||
'city' => 'Vienna',
|
||||
'state' => 'Vienna',
|
||||
'postal_code' => '1010',
|
||||
'country_id' => '40', // Austria
|
||||
'shipping_address1' => 'Musterstraße 123',
|
||||
'shipping_address2' => '2. Etage, Büro 45',
|
||||
'shipping_city' => 'Vienna',
|
||||
'shipping_state' => 'Vienna',
|
||||
'shipping_postal_code' => '1010',
|
||||
'shipping_country_id' => '40', // Austria
|
||||
'settings' => ClientSettings::Defaults(),
|
||||
'client_hash' => \Illuminate\Support\Str::random(32),
|
||||
'routing_id' => '',
|
||||
'classification' => $is_gov ? 'government' : 'business',
|
||||
]);
|
||||
|
||||
|
||||
$item = new InvoiceItem();
|
||||
$item->product_key = "Product Key";
|
||||
$item->notes = "Product Description";
|
||||
$item->cost = 10;
|
||||
$item->quantity = 10;
|
||||
$item->tax_rate1 = 20;
|
||||
$item->tax_name1 = 'VAT';
|
||||
|
||||
$invoice = Invoice::factory()->create([
|
||||
'company_id' => $company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $c->id,
|
||||
'discount' => 0,
|
||||
'uses_inclusive_taxes' => false,
|
||||
'status_id' => 1,
|
||||
'tax_rate1' => 0,
|
||||
'tax_name1' => '',
|
||||
'tax_rate2' => 0,
|
||||
'tax_rate3' => 0,
|
||||
'tax_name2' => '',
|
||||
'tax_name3' => '',
|
||||
'line_items' => [$item],
|
||||
'number' => 'DE-'.rand(1000, 100000),
|
||||
'date' => now()->format('Y-m-d'),
|
||||
'due_date' => now()->addDays(14)->format('Y-m-d'),
|
||||
]);
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
$invoice->service()->markSent()->save();
|
||||
|
||||
return $invoice;
|
||||
|
||||
}
|
||||
|
||||
public function testAtGovernmentRules()
|
||||
{
|
||||
$this->routing_id = 293801;
|
||||
|
||||
$invoice = $this->createATData(true);
|
||||
|
||||
$e_invoice = new \InvoiceNinja\EInvoice\Models\Peppol\Invoice();
|
||||
|
||||
$stub = json_decode('{"Invoice":{"Note":"Nooo","PaymentMeans":[{"ID":{"value":"afdasfasdfasdfas"},"PayeeFinancialAccount":{"Name":"PFA-NAME","ID":{"value":"DE89370400440532013000"},"AliasName":"PFA-Alias","AccountTypeCode":{"value":"CHECKING"},"AccountFormatCode":{"value":"IBAN"},"CurrencyCode":{"value":"EUR"},"FinancialInstitutionBranch":{"ID":{"value":"DEUTDEMMXXX"},"Name":"Deutsche Bank"}}}]}}');
|
||||
foreach($stub as $key => $value) {
|
||||
$e_invoice->{$key} = $value;
|
||||
}
|
||||
|
||||
$invoice->e_invoice = $e_invoice;
|
||||
$invoice->save();
|
||||
|
||||
$this->assertInstanceOf(Invoice::class, $invoice);
|
||||
$this->assertInstanceof(\InvoiceNinja\EInvoice\Models\Peppol\Invoice::class, $e_invoice);
|
||||
|
||||
$p = new Peppol($invoice);
|
||||
|
||||
$p->run();
|
||||
$xml = $p->toXml();
|
||||
nlog($xml);
|
||||
|
||||
$identifiers = $p->getStorecoveMeta();
|
||||
|
||||
$sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
|
||||
$sc->sendDocument($xml, $this->routing_id, $identifiers);
|
||||
|
||||
}
|
||||
|
||||
public function PestAtRules()
|
||||
{
|
||||
$this->routing_id = 293801;
|
||||
|
||||
$invoice = $this->createATData();
|
||||
|
||||
$e_invoice = new \InvoiceNinja\EInvoice\Models\Peppol\Invoice();
|
||||
|
||||
$stub = json_decode('{"Invoice":{"Note":"Nooo","PaymentMeans":[{"ID":{"value":"afdasfasdfasdfas"},"PayeeFinancialAccount":{"Name":"PFA-NAME","ID":{"value":"DE89370400440532013000"},"AliasName":"PFA-Alias","AccountTypeCode":{"value":"CHECKING"},"AccountFormatCode":{"value":"IBAN"},"CurrencyCode":{"value":"EUR"},"FinancialInstitutionBranch":{"ID":{"value":"DEUTDEMMXXX"},"Name":"Deutsche Bank"}}}]}}');
|
||||
foreach($stub as $key => $value) {
|
||||
$e_invoice->{$key} = $value;
|
||||
}
|
||||
|
||||
$invoice->e_invoice = $e_invoice;
|
||||
$invoice->save();
|
||||
|
||||
$this->assertInstanceOf(Invoice::class, $invoice);
|
||||
$this->assertInstanceof(\InvoiceNinja\EInvoice\Models\Peppol\Invoice::class, $e_invoice);
|
||||
|
||||
$p = new Peppol($invoice);
|
||||
|
||||
$p->run();
|
||||
$xml = $p->toXml();
|
||||
nlog($xml);
|
||||
|
||||
$identifiers = $p->getStorecoveMeta();
|
||||
|
||||
$sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
|
||||
$sc->sendDocument($xml, $this->routing_id, $identifiers);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function RestFrRules()
|
||||
{
|
||||
|
||||
$invoice = $this->createFRData();
|
||||
|
||||
$e_invoice = new \InvoiceNinja\EInvoice\Models\Peppol\Invoice();
|
||||
|
||||
$stub = json_decode('{"Invoice":{"Note":"Nooo","PaymentMeans":[{"ID":{"value":"afdasfasdfasdfas"},"PayeeFinancialAccount":{"Name":"PFA-NAME","ID":{"value":"DE89370400440532013000"},"AliasName":"PFA-Alias","AccountTypeCode":{"value":"CHECKING"},"AccountFormatCode":{"value":"IBAN"},"CurrencyCode":{"value":"EUR"},"FinancialInstitutionBranch":{"ID":{"value":"DEUTDEMMXXX"},"Name":"Deutsche Bank"}}}]}}');
|
||||
foreach($stub as $key => $value) {
|
||||
$e_invoice->{$key} = $value;
|
||||
}
|
||||
|
||||
$invoice->e_invoice = $e_invoice;
|
||||
$invoice->save();
|
||||
|
||||
$this->assertInstanceOf(Invoice::class, $invoice);
|
||||
$this->assertInstanceof(\InvoiceNinja\EInvoice\Models\Peppol\Invoice::class, $e_invoice);
|
||||
|
||||
$p = new Peppol($invoice);
|
||||
|
||||
$p->run();
|
||||
$xml = $p->toXml();
|
||||
nlog($xml);
|
||||
|
||||
$identifiers = $p->getStorecoveMeta();
|
||||
|
||||
$sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
|
||||
$sc->sendDocument($xml, $this->routing_id, $identifiers);
|
||||
|
||||
}
|
||||
|
||||
public function RtestEsRules()
|
||||
{
|
||||
|
||||
$invoice = $this->createESData();
|
||||
|
||||
$e_invoice = new \InvoiceNinja\EInvoice\Models\Peppol\Invoice();
|
||||
|
||||
$stub = json_decode('{"Invoice":{"Note":"Nooo","PaymentMeans":[{"ID":{"value":"afdasfasdfasdfas"},"PayeeFinancialAccount":{"Name":"PFA-NAME","ID":{"value":"DE89370400440532013000"},"AliasName":"PFA-Alias","AccountTypeCode":{"value":"CHECKING"},"AccountFormatCode":{"value":"IBAN"},"CurrencyCode":{"value":"EUR"},"FinancialInstitutionBranch":{"ID":{"value":"DEUTDEMMXXX"},"Name":"Deutsche Bank"}}}]}}');
|
||||
foreach($stub as $key => $value) {
|
||||
$e_invoice->{$key} = $value;
|
||||
}
|
||||
|
||||
$invoice->e_invoice = $e_invoice;
|
||||
$invoice->save();
|
||||
|
||||
$this->assertInstanceOf(Invoice::class, $invoice);
|
||||
$this->assertInstanceof(\InvoiceNinja\EInvoice\Models\Peppol\Invoice::class, $e_invoice);
|
||||
|
||||
$p = new Peppol($invoice);
|
||||
|
||||
$p->run();
|
||||
$xml = $p->toXml();
|
||||
nlog($xml);
|
||||
|
||||
$identifiers = [
|
||||
"routing" => [
|
||||
"eIdentifiers" => [
|
||||
[
|
||||
'scheme' => 'ES:VAT',
|
||||
'id' => 'ESB53625999'
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
|
||||
$sc->sendDocument($xml, $this->routing_id, $identifiers);
|
||||
|
||||
}
|
||||
|
||||
public function RtestDeRules()
|
||||
{
|
||||
$invoice = $this->createDEData();
|
||||
|
||||
@ -527,8 +883,20 @@ $x = '<?xml version="1.0" encoding="utf-8"?>
|
||||
$p->run();
|
||||
$xml = $p->toXml();
|
||||
nlog($xml);
|
||||
|
||||
$identifiers = [
|
||||
"routing" => [
|
||||
"eIdentifiers" => [
|
||||
[
|
||||
'scheme' => 'DE:VAT',
|
||||
'id' => 'DE010101010'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
|
||||
$sc->sendDocument($xml);
|
||||
$sc->sendDocument($xml, $this->routing_id, $identifiers);
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ export default defineConfig({
|
||||
rollupOptions: {
|
||||
output: {
|
||||
// This will output a single bundle file
|
||||
entryFileNames: 'bundle.js',
|
||||
chunkFileNames: 'bundle.js'
|
||||
entryFileNames: 'bundle.[hash].js',
|
||||
chunkFileNames: 'bundle.[hash].js'
|
||||
}
|
||||
},
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user