diff --git a/VERSION.txt b/VERSION.txt
index cdaeb5eb133b..9c4d53bf2eeb 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-5.10.19
\ No newline at end of file
+5.10.20
\ No newline at end of file
diff --git a/app/DataMapper/Tax/BaseRule.php b/app/DataMapper/Tax/BaseRule.php
index 78eb1bd9445b..4448c7525898 100644
--- a/app/DataMapper/Tax/BaseRule.php
+++ b/app/DataMapper/Tax/BaseRule.php
@@ -215,7 +215,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();
diff --git a/app/DataMapper/Tax/DE/Rule.php b/app/DataMapper/Tax/DE/Rule.php
index 726043cf5aa3..34d63bffefa9 100644
--- a/app/DataMapper/Tax/DE/Rule.php
+++ b/app/DataMapper/Tax/DE/Rule.php
@@ -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;
diff --git a/app/Filters/ExpenseFilters.php b/app/Filters/ExpenseFilters.php
index ca2b1b09bdde..2fa80a1eb799 100644
--- a/app/Filters/ExpenseFilters.php
+++ b/app/Filters/ExpenseFilters.php
@@ -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) {
diff --git a/app/Filters/TaskFilters.php b/app/Filters/TaskFilters.php
index 3b26e004742b..c179bb44ab77 100644
--- a/app/Filters/TaskFilters.php
+++ b/app/Filters/TaskFilters.php
@@ -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;
}
diff --git a/app/Http/ViewComposers/Components/Rotessa/ContactComponent.php b/app/Http/ViewComposers/Components/Rotessa/ContactComponent.php
index f1b0c0adf165..dcaff72ab283 100644
--- a/app/Http/ViewComposers/Components/Rotessa/ContactComponent.php
+++ b/app/Http/ViewComposers/Components/Rotessa/ContactComponent.php
@@ -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 );
}
}
diff --git a/app/PaymentDrivers/PayPal/PayPalBasePaymentDriver.php b/app/PaymentDrivers/PayPal/PayPalBasePaymentDriver.php
index e7f6fe01c145..375b9c7420b7 100644
--- a/app/PaymentDrivers/PayPal/PayPalBasePaymentDriver.php
+++ b/app/PaymentDrivers/PayPal/PayPalBasePaymentDriver.php
@@ -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 {
diff --git a/app/Repositories/TaskRepository.php b/app/Repositories/TaskRepository.php
index ec96ed0670b0..96ee297427e9 100644
--- a/app/Repositories/TaskRepository.php
+++ b/app/Repositories/TaskRepository.php
@@ -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();
}
@@ -418,4 +423,4 @@ class TaskRepository extends BaseRepository
}
-}
+}
\ No newline at end of file
diff --git a/app/Services/EDocument/Gateway/Storecove/Storecove.php b/app/Services/EDocument/Gateway/Storecove/Storecove.php
index 0ce0a8561372..397e8813ff2b 100644
--- a/app/Services/EDocument/Gateway/Storecove/Storecove.php
+++ b/app/Services/EDocument/Gateway/Storecove/Storecove.php
@@ -137,14 +137,14 @@ class Storecove {
}
- public function sendDocument($document)
+ public function sendDocument(string $document, int $routing_id, array $identifiers = [])
{
$payload = [
- "legalEntityId"=> 290868,
+ "legalEntityId" => $routing_id,
"idempotencyGuid"=> \Illuminate\Support\Str::uuid(),
"routing" => [
- "eIdentifiers" => [],
+ "eIdentifiers" => $identifiers,
"emails" => ["david@invoiceninja.com"]
],
"document"=> [
diff --git a/app/Services/EDocument/Standards/Peppol.php b/app/Services/EDocument/Standards/Peppol.php
index a0d7b4892f66..d6c6e8f538ee 100644
--- a/app/Services/EDocument/Standards/Peppol.php
+++ b/app/Services/EDocument/Standards/Peppol.php
@@ -57,6 +57,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:
@@ -152,6 +158,13 @@ class Peppol extends AbstractService
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;
+
/**
* @param Invoice $invoice
*/
@@ -159,18 +172,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;
@@ -182,6 +198,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
{
@@ -211,8 +242,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,12 +254,16 @@ 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();
@@ -340,7 +374,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 +406,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;
@@ -739,13 +773,13 @@ class Peppol extends AbstractService
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;
}
@@ -761,10 +795,10 @@ class Peppol extends AbstractService
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;
}
@@ -774,24 +808,48 @@ class Peppol extends AbstractService
return $this;
}
-
+
+ /**
+ * 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
@@ -804,14 +862,28 @@ class Peppol extends AbstractService
//if payment means are included, they must be the same `type`
return $this;
}
-
+
+ /**
+ * ES
+ *
+ * @Pending
+ *
+ * ES:DIRE - routing identifier
+ *
+ * testing. //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.
diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php
index af1ea653f64e..7ae780bf2409 100644
--- a/app/Services/Subscription/SubscriptionService.php
+++ b/app/Services/Subscription/SubscriptionService.php
@@ -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();
}
diff --git a/app/Utils/Traits/Pdf/PDF.php b/app/Utils/Traits/Pdf/PDF.php
index b51b9914cd72..31d1e529c706 100644
--- a/app/Utils/Traits/Pdf/PDF.php
+++ b/app/Utils/Traits/Pdf/PDF.php
@@ -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);
}
diff --git a/config/ninja.php b/config/ninja.php
index 601b526f1601..1655b8a8832b 100644
--- a/config/ninja.php
+++ b/config/ninja.php
@@ -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.20'),
+ 'app_tag' => env('APP_TAG', '5.10.20'),
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false),
diff --git a/lang/en/texts.php b/lang/en/texts.php
index 8a0abf6d6bd4..9df051a9cd38 100644
--- a/lang/en/texts.php
+++ b/lang/en/texts.php
@@ -5311,6 +5311,7 @@ $lang = array(
'customer_type' => 'Customer Type',
'process_date' => 'Process Date',
'forever_free' => 'Forever Free',
+ 'comments_only' => 'Comments Only',
);
return $lang;
diff --git a/lang/es_ES/texts.php b/lang/es_ES/texts.php
index 8bad35c312cb..a35db8b5f2e9 100644
--- a/lang/es_ES/texts.php
+++ b/lang/es_ES/texts.php
@@ -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
Description: :description
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
Descripción: :description
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;
diff --git a/lang/fr_CA/texts.php b/lang/fr_CA/texts.php
index 08e065a4a226..45fa3c61c7e5 100644
--- a/lang/fr_CA/texts.php
+++ b/lang/fr_CA/texts.php
@@ -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,17 @@ 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',
);
return $lang;
diff --git a/lang/hu/texts.php b/lang/hu/texts.php
index b10b6b8f242e..62a6ab89f71f 100644
--- a/lang/hu/texts.php
+++ b/lang/hu/texts.php
@@ -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;
diff --git a/lang/lo_LA/texts.php b/lang/lo_LA/texts.php
index 3677f99b387c..77e3ebacc280 100644
--- a/lang/lo_LA/texts.php
+++ b/lang/lo_LA/texts.php
@@ -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;
diff --git a/lang/pt_BR/texts.php b/lang/pt_BR/texts.php
index 1422bd891ced..8dabd60b1596 100644
--- a/lang/pt_BR/texts.php
+++ b/lang/pt_BR/texts.php
@@ -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;
diff --git a/lang/pt_PT/texts.php b/lang/pt_PT/texts.php
index aa80e867fadc..768cae915cec 100644
--- a/lang/pt_PT/texts.php
+++ b/lang/pt_PT/texts.php
@@ -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',
diff --git a/tests/Feature/EInvoice/PeppolTest.php b/tests/Feature/EInvoice/PeppolTest.php
index 547d688851a7..6c21951a714c 100644
--- a/tests/Feature/EInvoice/PeppolTest.php
+++ b/tests/Feature/EInvoice/PeppolTest.php
@@ -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);
diff --git a/tests/Feature/ExpenseApiTest.php b/tests/Feature/ExpenseApiTest.php
index 81d7dafbf2ab..e6319f092847 100644
--- a/tests/Feature/ExpenseApiTest.php
+++ b/tests/Feature/ExpenseApiTest.php
@@ -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()
{
diff --git a/tests/Integration/Einvoice/Storecove/StorecoveTest.php b/tests/Integration/Einvoice/Storecove/StorecoveTest.php
index 57882e1feb46..d227c6848254 100644
--- a/tests/Integration/Einvoice/Storecove/StorecoveTest.php
+++ b/tests/Integration/Einvoice/Storecove/StorecoveTest.php
@@ -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,7 +352,7 @@ $x = '
$sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
- $sc->sendDocument($x);
+ $sc->sendDocument($x, 290868);
}
*/
@@ -398,10 +398,117 @@ $x = '
}
+ private function createESData()
+ {
+ $this->routing_id = 293098;
+
+ $settings = CompanySettings::defaults();
+ $settings->company_logo = 'https://pdf.invoicing.co/favicon-v2.png';
+ $settings->website = 'www.invoiceninja.de';
+ $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 = '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 createDEData()
{
- $this->routing_id = '290868';
+ $this->routing_id = 290868;
$settings = CompanySettings::defaults();
$settings->company_logo = 'https://pdf.invoicing.co/favicon-v2.png';
@@ -495,7 +602,8 @@ $x = '
'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,6 +614,42 @@ $x = '
}
+ public function testEsRules()
+ {
+
+ $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 = [
+ [
+ 'scheme' => 'ES:VAT',
+ 'id' => 'ESB53625999'
+ ],
+ ];
+
+ $sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
+ $sc->sendDocument($xml, $this->routing_id, $identifiers);
+
+ }
+
public function testDeRules()
{
$invoice = $this->createDEData();
@@ -527,8 +671,16 @@ $x = '
$p->run();
$xml = $p->toXml();
nlog($xml);
- $sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
- $sc->sendDocument($xml);
+
+ $identifiers = [
+ [
+ 'scheme' => 'DE:VAT',
+ 'id' => 'DE010101010'
+ ]
+ ];
+
+ $sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
+ $sc->sendDocument($xml, $this->routing_id, $identifiers);
}