Functional tests of spanish environment

This commit is contained in:
David Bomba 2025-08-11 09:54:53 +10:00
parent 1e8727c4a4
commit 555eb80018
7 changed files with 183 additions and 81 deletions

View File

@ -204,6 +204,12 @@ class UpdateCompanyRequest extends Request
$settings[$protected_var] = str_replace("script", "", $settings[$protected_var]);
}
}
if($this->company->settings->e_invoice_type == 'verifactu') {
$settings['lock_invoices'] = 'when_sent';
$settings['e_invoice_type'] = 'verifactu';
}
}
if (isset($settings['email_style_custom'])) {

View File

@ -12,6 +12,7 @@
namespace App\Http\Requests\Invoice;
use App\Http\Requests\Request;
use App\Http\ValidationRules\Invoice\RestoreDisabledRule;
use App\Utils\Traits\Invoice\ActionsInvoice;
use App\Utils\Traits\MakesHash;
@ -37,7 +38,7 @@ class ActionInvoiceRequest extends Request
public function rules()
{
return [
'action' => 'required',
'action' => ['required', new RestoreDisabledRule()],
];
}

View File

@ -13,6 +13,7 @@ namespace App\Http\Requests\Invoice;
use App\Http\Requests\Request;
use App\Exceptions\DuplicatePaymentException;
use App\Http\ValidationRules\Invoice\RestoreDisabledRule;
class BulkInvoiceRequest extends Request
{
@ -24,7 +25,7 @@ class BulkInvoiceRequest extends Request
public function rules()
{
return [
'action' => 'required|string',
'action' => ['required', 'string', new RestoreDisabledRule()],
'ids' => 'required|array',
'email_type' => 'sometimes|in:reminder1,reminder2,reminder3,reminder_endless,custom1,custom2,custom3,invoice,quote,credit,payment,payment_partial,statement,purchase_order',
'template' => 'sometimes|string',

View File

@ -0,0 +1,40 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\ValidationRules\Invoice;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Class RestoreDisabledRule.
*/
class RestoreDisabledRule implements ValidationRule
{
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (empty($value) || $value != 'restore') {
return;
}
$user = auth()->user();
$company = $user->company();
/** For verifactu, we do not allow restores */
if($company->settings->e_invoice_type == 'verifactu') {
$fail(ctrans('texts.restore_disabled_verifactu'));
}
}
}

View File

@ -5573,6 +5573,7 @@ $lang = array(
'invalid_csv_data' => 'Invalid CSV data, your import was cancelled.',
'selected_products' => 'Selected Products',
'create_company_error_unauthorized' => 'You are not authorized to create a company. Only the account owner can create a company.',
'restore_disabled_verifactu' => 'You cannot restore an invoice once it has been deleted',
);
return $lang;

View File

@ -0,0 +1,131 @@
<?php
/**
* 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://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Feature\EInvoice\Verifactu;
use Tests\TestCase;
use App\Models\Client;
use App\Models\Invoice;
use App\Models\Project;
use Tests\MockAccountData;
use App\Models\Subscription;
use App\Models\ClientContact;
use App\Utils\Traits\MakesHash;
use App\Models\RecurringInvoice;
use App\Factory\InvoiceItemFactory;
use App\Helpers\Invoice\InvoiceSum;
use Illuminate\Support\Facades\Config;
use App\Repositories\InvoiceRepository;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Session;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class VerifactuApiTest extends TestCase
{
use MakesHash;
use DatabaseTransactions;
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();
$this->faker = \Faker\Factory::create();
$this->makeTestData();
}
public function test_restore_invoice_validation()
{
$settings = $this->company->settings;
$settings->e_invoice_type = 'verifactu';
$this->company->settings = $settings;
$this->company->save();
$data = [
'action' => 'delete',
'ids' => [$this->invoice->hashed_id]
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/invoices/bulk', $data);
$response->assertStatus(200);
$arr = $response->json();
$this->assertTrue($arr['data'][0]['is_deleted']);
$data = [
'action' => 'restore',
'ids' => [$this->invoice->hashed_id]
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/invoices/bulk', $data);
$response->assertStatus(422);
}
/**
* test_update_company_settings
*
* Verifactu we do not allow the user to change from the verifactu system nor, do we allow changing the locking feature of invoices
* @return void
*/
public function test_update_company_settings()
{
// Ensure LARAVEL_START is defined for the middleware
if (!defined('LARAVEL_START')) {
define('LARAVEL_START', microtime(true));
}
Config::set('ninja.environment', 'hosted');
$settings = $this->company->settings;
$settings->e_invoice_type = 'verifactu';
$this->company->settings = $settings;
$this->company->save();
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/companies/'.$this->company->hashed_id, $this->company->toArray())
->assertStatus(200);
$settings = $this->company->settings;
$settings->e_invoice_type = 'Facturae_3.2.2';
$this->company->settings = $settings;
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/companies/'.$this->company->hashed_id, $this->company->toArray())
->assertStatus(200);
$arr = $response->json();
$this->assertEquals($arr['data']['settings']['e_invoice_type'], 'verifactu');
$this->assertEquals($arr['data']['settings']['lock_invoices'], 'when_sent');
}
}

View File

@ -746,81 +746,3 @@ class VerifactuFeatureTest extends TestCase
$this->assertStringContainsString('</soapenv:Envelope>', $soapXml);
}
}
// $soapXml = <<<XML
// <?xml version="1.0" encoding="UTF-8"?>
// <soapenv:Envelope
// xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
// xmlns:sum="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd"
// xmlns:sum1="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd">
// <soapenv:Header/>
// <soapenv:Body>
// <sum:RegFactuSistemaFacturacion>
// <sum:Cabecera>
// <sum1:ObligadoEmision>
// <sum1:NombreRazon>CERTIFICADO FISICA PRUEBAS</sum1:NombreRazon>
// <sum1:NIF>A39200019</sum1:NIF>
// </sum1:ObligadoEmision>
// </sum:Cabecera>
// <sum:RegistroFactura>
// <sum1:RegistroAlta>
// <sum1:IDVersion>1.0</sum1:IDVersion>
// <sum1:IDFactura>
// <sum1:IDEmisorFactura>A39200019</sum1:IDEmisorFactura>
// <sum1:NumSerieFactura>TEST0033343444</sum1:NumSerieFactura>
// <sum1:FechaExpedicionFactura>09-08-2025</sum1:FechaExpedicionFactura>
// </sum1:IDFactura>
// <sum1:NombreRazonEmisor>CERTIFICADO FISICA PRUEBAS</sum1:NombreRazonEmisor>
// <sum1:TipoFactura>F3</sum1:TipoFactura>
// <sum1:TipoRectificativa>S</sum1:TipoRectificativa>
// <sum1:FacturasSustituidas>
// <sum1:IDFacturaSustituida>
// <sum1:IDEmisorFactura>A39200019</sum1:IDEmisorFactura>
// <sum1:NumSerieFactura>TEST0033343443</sum1:NumSerieFactura>
// <sum1:FechaExpedicionFactura>09-08-2025</sum1:FechaExpedicionFactura>
// </sum1:IDFacturaSustituida>
// </sum1:FacturasSustituidas>
// <sum1:ImporteRectificacion>
// <sum1:BaseRectificada>100.00</sum1:BaseRectificada>
// <sum1:CuotaRectificada>21.00</sum1:CuotaRectificada>
// <sum1:CuotaRecargoRectificado>0.00</sum1:CuotaRecargoRectificado>
// </sum1:ImporteRectificacion>
// <sum1:DescripcionOperacion>Rectificación por error en factura anterior</sum1:DescripcionOperacion>
// <sum1:Desglose>
// <sum1:DetalleDesglose>
// <sum1:Impuesto>01</sum1:Impuesto>
// <sum1:ClaveRegimen>01</sum1:ClaveRegimen>
// <sum1:CalificacionOperacion>S1</sum1:CalificacionOperacion>
// <sum1:TipoImpositivo>21.00</sum1:TipoImpositivo>
// <sum1:BaseImponibleOimporteNoSujeto>97.00</sum1:BaseImponibleOimporteNoSujeto>
// <sum1:CuotaRepercutida>20.37</sum1:CuotaRepercutida>
// </sum1:DetalleDesglose>
// </sum1:Desglose>
// <sum1:CuotaTotal>47.05</sum1:CuotaTotal>
// <sum1:ImporteTotal>144.05</sum1:ImporteTotal>
// <sum1:Encadenamiento>
// <sum1:PrimerRegistro>S</sum1:PrimerRegistro>
// </sum1:Encadenamiento>
// <sum1:SistemaInformatico>
// <sum1:NombreRazon>CERTIFICADO FISICA PRUEBAS</sum1:NombreRazon>
// <sum1:NIF>A39200019</sum1:NIF>
// <sum1:NombreSistemaInformatico>InvoiceNinja</sum1:NombreSistemaInformatico>
// <sum1:IdSistemaInformatico>77</sum1:IdSistemaInformatico>
// <sum1:Version>1.0.03</sum1:Version>
// <sum1:NumeroInstalacion>383</sum1:NumeroInstalacion>
// <sum1:TipoUsoPosibleSoloVerifactu>N</sum1:TipoUsoPosibleSoloVerifactu>
// <sum1:TipoUsoPosibleMultiOT>S</sum1:TipoUsoPosibleMultiOT>
// <sum1:IndicadorMultiplesOT>S</sum1:IndicadorMultiplesOT>
// </sum1:SistemaInformatico>
// <sum1:FechaHoraHusoGenRegistro>2025-08-09T23:18:44+02:00</sum1:FechaHoraHusoGenRegistro>
// <sum1:TipoHuella>01</sum1:TipoHuella>
// <sum1:Huella>E7558C33FE3496551F38FEB582F4879B1D9F6C073489628A8DC275E12298941F</sum1:Huella>
// </sum1:RegistroAlta>
// </sum:RegistroFactura>
// </sum:RegFactuSistemaFacturacion>
// </soapenv:Body>
// </soapenv:Envelope>
// XML;