diff --git a/app/Http/Controllers/EInvoiceController.php b/app/Http/Controllers/EInvoiceController.php index 45a364373c..eaebed3b99 100644 --- a/app/Http/Controllers/EInvoiceController.php +++ b/app/Http/Controllers/EInvoiceController.php @@ -44,7 +44,7 @@ class EInvoiceController extends BaseController $el = new EntityLevel(); $data = []; - + match ($request->entity) { 'invoices' => $data = $el->checkInvoice($request->getEntity()), 'clients' => $data = $el->checkClient($request->getEntity()), diff --git a/app/Http/Requests/EInvoice/ValidateEInvoiceRequest.php b/app/Http/Requests/EInvoice/ValidateEInvoiceRequest.php index 4eed99725d..db7455b09f 100644 --- a/app/Http/Requests/EInvoice/ValidateEInvoiceRequest.php +++ b/app/Http/Requests/EInvoice/ValidateEInvoiceRequest.php @@ -75,7 +75,6 @@ class ValidateEInvoiceRequest extends Request return false; } - $class = Invoice::class; match ($this->entity) { diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php index 573698cd69..024fb684e5 100644 --- a/app/Models/BaseModel.php +++ b/app/Models/BaseModel.php @@ -330,7 +330,7 @@ class BaseModel extends Model } // special catch here for einvoicing eventing - if ($event_id == Webhook::EVENT_SENT_INVOICE && ($this instanceof Invoice) && is_null($this->backup) && $this->client->peppolSendingEnabled()) { + if ($event_id == Webhook::EVENT_SENT_INVOICE && ($this instanceof Invoice) && $this->backup->guid == "" && $this->client->peppolSendingEnabled()) { \App\Services\EDocument\Jobs\SendEDocument::dispatch(get_class($this), $this->id, $this->company->db); } diff --git a/app/Models/User.php b/app/Models/User.php index dc987eb7a7..77b4af4f2f 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -570,8 +570,8 @@ class User extends Authenticatable implements MustVerifyEmail * * Note, returning FALSE here means the user does NOT have the permission we want to exclude * - * @param array $matched_permission - * @param array $excluded_permissions + * @param array $matched_permission = [] + * @param array $excluded_permissions = [] * @return bool */ public function hasExcludedPermissions(array $matched_permission = [], array $excluded_permissions = []): bool diff --git a/app/Services/EDocument/Standards/Peppol.php b/app/Services/EDocument/Standards/Peppol.php index dddb274736..72498af1da 100644 --- a/app/Services/EDocument/Standards/Peppol.php +++ b/app/Services/EDocument/Standards/Peppol.php @@ -158,6 +158,7 @@ class Peppol extends AbstractService public function __construct(public Invoice $invoice) { + $this->company = $invoice->company; $this->calc = $this->invoice->calc(); $this->e = new EInvoice(); diff --git a/app/Services/EDocument/Standards/Verifactu/Models/FacturaRectificativa.php b/app/Services/EDocument/Standards/Verifactu/Models/FacturaRectificativa.php index c426f450e7..36c1e8e6b0 100644 --- a/app/Services/EDocument/Standards/Verifactu/Models/FacturaRectificativa.php +++ b/app/Services/EDocument/Standards/Verifactu/Models/FacturaRectificativa.php @@ -119,36 +119,6 @@ class FacturaRectificativa extends BaseXmlModel return $idFacturaRectificada; } - /** - * Create a FacturaRectificativa instance for a substitutive rectification - * - * @param string $nif The NIF of the rectified invoice - * @param string $numSerie The series number of the rectified invoice - * @param string $fecha The date of the rectified invoice - * @return static - */ - public static function createForSubstitutive(string $nif, string $numSerie, string $fecha): static - { - $instance = new static('S', 0.0, 0.0); - $instance->setRectifiedInvoice($nif, $numSerie, $fecha); - return $instance; - } - - /** - * Create a FacturaRectificativa instance for a complete rectification - * - * @param string $nif The NIF of the rectified invoice - * @param string $numSerie The series number of the rectified invoice - * @param string $fecha The date of the rectified invoice - * @return static - */ - public static function createForComplete(string $nif, string $numSerie, string $fecha): static - { - $instance = new static('I', 0.0, 0.0); - $instance->setRectifiedInvoice($nif, $numSerie, $fecha); - return $instance; - } - public static function fromDOMElement(\DOMElement $element): self { // This method is required by BaseXmlModel but not used in this context diff --git a/app/Services/EDocument/Standards/Verifactu/Models/Invoice.php b/app/Services/EDocument/Standards/Verifactu/Models/Invoice.php index 2211997c09..2dc94e40a8 100644 --- a/app/Services/EDocument/Standards/Verifactu/Models/Invoice.php +++ b/app/Services/EDocument/Standards/Verifactu/Models/Invoice.php @@ -576,59 +576,6 @@ class Invoice extends BaseXmlModel implements XmlModelInterface return $this; } - /** - * Helper method to create a complete rectification invoice with ImporteRectificacion - * - * @param float $importeRectificacion The rectification amount - * @param string $descripcionOperacion Description of the rectification operation - * @return self - */ - public function makeCompleteRectificationWithAmount(float $importeRectificacion, string $descripcionOperacion = 'Rectificación completa de factura'): self - { - return $this->makeRectificativeWithAmount(self::TIPO_RECTIFICATIVA_COMPLETA, $importeRectificacion, $descripcionOperacion); - } - - /** - * Helper method to create a substitutive rectification invoice with ImporteRectificacion - * - * @param float $importeRectificacion The rectification amount - * @param string $descripcionOperacion Description of the rectification operation - * @return self - */ - public function makeSubstitutiveRectificationWithAmount(float $importeRectificacion, string $descripcionOperacion = 'Rectificación sustitutiva de factura'): self - { - return $this->makeRectificativeWithAmount(self::TIPO_RECTIFICATIVA_SUSTITUTIVA, $importeRectificacion, $descripcionOperacion); - } - - /** - * Helper method to create a substitutive rectification invoice that automatically calculates ImporteRectificacion - * from the difference between the original and new amounts - * - * @param float $originalAmount The original invoice amount - * @param float $newAmount The new invoice amount - * @param string $descripcionOperacion Description of the rectification operation - * @return self - */ - public function makeSubstitutiveRectificationFromDifference(float $originalAmount, float $newAmount, string $descripcionOperacion = 'Rectificación sustitutiva de factura'): self - { - $importeRectificacion = $newAmount - $originalAmount; - - return $this->makeRectificativeWithAmount(self::TIPO_RECTIFICATIVA_SUSTITUTIVA, $importeRectificacion, $descripcionOperacion); - } - - /** - * Calculate and set ImporteRectificacion based on the difference between amounts - * - * @param float $originalAmount The original invoice amount - * @param float $newAmount The new invoice amount - * @return self - */ - public function calculateImporteRectificacion(float $originalAmount, float $newAmount): self - { - $this->importeRectificacion = $newAmount - $originalAmount; - return $this; - } - /** @@ -652,11 +599,11 @@ class Invoice extends BaseXmlModel implements XmlModelInterface throw new \InvalidArgumentException('DescripcionOperacion is required'); } - if ($this->cuotaTotal === null || $this->cuotaTotal < 0) { + if ($this->cuotaTotal < 0) { throw new \InvalidArgumentException('CuotaTotal must be a positive number'); } - if ($this->importeTotal === null || $this->importeTotal < 0) { + if ($this->importeTotal < 0) { throw new \InvalidArgumentException('ImporteTotal must be a positive number'); } @@ -1042,32 +989,17 @@ class Invoice extends BaseXmlModel implements XmlModelInterface $root->appendChild($this->createElement($doc, 'ImporteTotal', (string)$this->importeTotal)); // 13. Encadenamiento (always present for R1 invoices) - if ($this->encadenamiento !== null) { + // if ($this->encadenamiento !== null) { $root->appendChild($this->encadenamiento->toXml($doc)); - } else { - // Create default Encadenamiento if not set - $encadenamientoElement = $this->createElement($doc, 'Encadenamiento'); - $encadenamientoElement->appendChild($this->createElement($doc, 'PrimerRegistro', 'S')); - $root->appendChild($encadenamientoElement); - } + // } else { + // // Create default Encadenamiento if not set + // $encadenamientoElement = $this->createElement($doc, 'Encadenamiento'); + // $encadenamientoElement->appendChild($this->createElement($doc, 'PrimerRegistro', 'S')); + // $root->appendChild($encadenamientoElement); + // } // 14. SistemaInformatico (always present for R1 invoices) - if ($this->sistemaInformatico !== null) { - $root->appendChild($this->sistemaInformatico->toXml($doc)); - } else { - // Create default SistemaInformatico if not set - $sistemaInformaticoElement = $this->createElement($doc, 'SistemaInformatico'); - $sistemaInformaticoElement->appendChild($this->createElement($doc, 'NombreRazon', $this->nombreRazonEmisor)); - $sistemaInformaticoElement->appendChild($this->createElement($doc, 'NIF', $this->idEmisorFactura)); - $sistemaInformaticoElement->appendChild($this->createElement($doc, 'NombreSistemaInformatico', 'InvoiceNinja')); - $sistemaInformaticoElement->appendChild($this->createElement($doc, 'IdSistemaInformatico', '77')); - $sistemaInformaticoElement->appendChild($this->createElement($doc, 'Version', '1.0.03')); - $sistemaInformaticoElement->appendChild($this->createElement($doc, 'NumeroInstalacion', '383')); - $sistemaInformaticoElement->appendChild($this->createElement($doc, 'TipoUsoPosibleSoloVerifactu', 'N')); - $sistemaInformaticoElement->appendChild($this->createElement($doc, 'TipoUsoPosibleMultiOT', 'S')); - $sistemaInformaticoElement->appendChild($this->createElement($doc, 'IndicadorMultiplesOT', 'S')); - $root->appendChild($sistemaInformaticoElement); - } + $root->appendChild($this->sistemaInformatico->toXml($doc)); // 15. FechaHoraHusoGenRegistro $root->appendChild($this->createElement($doc, 'FechaHoraHusoGenRegistro', $this->fechaHoraHusoGenRegistro)); diff --git a/app/Services/EDocument/Standards/Verifactu/SendToAeat.php b/app/Services/EDocument/Standards/Verifactu/SendToAeat.php index 26bc09be92..e72828d48b 100644 --- a/app/Services/EDocument/Standards/Verifactu/SendToAeat.php +++ b/app/Services/EDocument/Standards/Verifactu/SendToAeat.php @@ -11,20 +11,21 @@ namespace App\Services\EDocument\Standards\Verifactu; +use Mail; use App\Utils\Ninja; +use App\Models\Company; use App\Models\Invoice; use App\Libraries\MultiDB; -use App\Models\Company; use Illuminate\Bus\Queueable; -use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; +use Illuminate\Support\Facades\Cache; +use Illuminate\Mail\Mailables\Address; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use App\Services\EDocument\Standards\Verifactu; use Illuminate\Queue\Middleware\WithoutOverlapping; -use Mail; -use Illuminate\Mail\Mailables\Address; class SendToAeat implements ShouldQueue { @@ -38,9 +39,11 @@ class SendToAeat implements ShouldQueue public $deleteWhenMissingModels = true; /** - * Modification Invoices - (modify) Generates a F3 document which replaces the original invoice. And becomes the new invoice. + * Modification Invoices - (modify) + * - If Amount > 0 - We generates a F3 document which replaces the original invoice. And becomes the new invoice. + * - If Amount < 0 - We generate a R2 document which is a negative modification on the original invoice. * Create Invoices - (create) Generates a F1 document. - * Cancellation Invoices - (cancel) Generates a R3 document with full negative values of the original invoice. + * Cancellation Invoices - (cancel) Generates a R3 document with full negative values of the original invoice. */ /** @@ -66,6 +69,50 @@ class SendToAeat implements ShouldQueue $invoice = Invoice::withTrashed()->find($this->invoice_id); + switch($this->action) { + case 'modify': + $this->modifyInvoice($invoice); + break; + case 'create': + $this->createInvoice($invoice); + break; + case 'cancel': + $this->cancelInvoice($invoice); + break; + } + + } + + public function modifyInvoice(Invoice $invoice) + { + $verifactu = new Verifactu($invoice); + $verifactu->run(); + } + + public function createInvoice(Invoice $invoice) + { + $verifactu = new Verifactu($invoice); + $verifactu->run(); + } + + public function cancelInvoice(Invoice $invoice) + { + + $verifactu = new Verifactu($invoice); + $document = (new RegistroAlta($invoice))->run()->getInvoice(); + + $last_hash = $invoice->company->verifactu_logs()->first(); + + $huella = $this->cancellationHash($document, $last_hash->hash); + + $cancellation = $document->createCancellation(); + $cancellation->setHuella($huella); + + $soapXml = $cancellation->toSoapEnvelope(); + + $response = $verifactu->send($soapXml); + + nlog($response); } public function middleware() @@ -77,4 +124,31 @@ class SendToAeat implements ShouldQueue { nlog($exception); } + + + + /** + * cancellationHash + * + * @param mixed $document + * @param string $huella + * @return string + */ + private function cancellationHash($document, string $huella): string + { + + $idEmisorFacturaAnulada = $document->getIdFactura()->getIdEmisorFactura(); + $numSerieFacturaAnulada = $document->getIdFactura()->getNumSerieFactura(); + $fechaExpedicionFacturaAnulada = $document->getIdFactura()->getFechaExpedicionFactura(); + $fechaHoraHusoGenRegistro = $document->getFechaHoraHusoGenRegistro(); + + $hashInput = "IDEmisorFacturaAnulada={$idEmisorFacturaAnulada}&" . + "NumSerieFacturaAnulada={$numSerieFacturaAnulada}&" . + "FechaExpedicionFacturaAnulada={$fechaExpedicionFacturaAnulada}&" . + "Huella={$huella}&" . + "FechaHoraHusoGenRegistro={$fechaHoraHusoGenRegistro}"; + + return strtoupper(hash('sha256', $hashInput)); + + } } \ No newline at end of file diff --git a/tests/Feature/CreditTest.php b/tests/Feature/CreditTest.php index 46ae60caf7..b38b89fc7b 100644 --- a/tests/Feature/CreditTest.php +++ b/tests/Feature/CreditTest.php @@ -98,12 +98,14 @@ class CreditTest extends TestCase $ii->product_key = 'xx'; $ii->notes = 'yy'; - $credit_array['line_items'] = [$ii]; + + $credit_array['line_items'] = []; + $credit_array['line_items'][] = (array)$ii; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/credits', $credit_array); + ])->postJson('/api/v1/credits', $credit_array); $response->assertStatus(200); $arr = $response->json(); @@ -176,12 +178,14 @@ class CreditTest extends TestCase $ii->product_key = 'xx'; $ii->notes = 'yy'; - $credit_array['line_items'] = [$ii]; + +$credit_array['line_items'] = []; +$credit_array['line_items'][] = (array)$ii; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/credits', $credit_array); + ])->postJson('/api/v1/credits', $credit_array); $response->assertStatus(200); $arr = $response->json(); @@ -581,7 +585,7 @@ class CreditTest extends TestCase $response = $this->withHeaders([ 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/credits/bulk', $data) + ])->postJson('/api/v1/credits/bulk', $data) ->assertStatus(200); @@ -593,7 +597,7 @@ class CreditTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/credits/bulk', $data) + ])->postJson('/api/v1/credits/bulk', $data) ->assertStatus(200); $data = [ @@ -604,7 +608,7 @@ class CreditTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/credits/bulk', $data) + ])->postJson('/api/v1/credits/bulk', $data) ->assertStatus(200); } @@ -698,7 +702,7 @@ class CreditTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/credits/', $credit) + ])->postJson('/api/v1/credits/', $credit) ->assertStatus(200); } @@ -733,16 +737,16 @@ class CreditTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/credits', $data); + ])->postJson('/api/v1/credits', $data); $response->assertStatus(200); $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/credits', $data); + ])->postJson('/api/v1/credits', $data); - $response->assertStatus(302); + $response->assertStatus(422); } public function testCreditPut() @@ -780,8 +784,8 @@ class CreditTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/credits/', $data); + ])->postJson('/api/v1/credits/', $data); - $response->assertStatus(302); + $response->assertStatus(422); } } diff --git a/tests/Feature/EInvoice/PeppolTest.php b/tests/Feature/EInvoice/PeppolTest.php index 5bcf0c02e6..77e8c72cdf 100644 --- a/tests/Feature/EInvoice/PeppolTest.php +++ b/tests/Feature/EInvoice/PeppolTest.php @@ -11,6 +11,7 @@ namespace Tests\Feature\EInvoice; +use Faker\Factory; use Tests\TestCase; use App\Models\Client; use App\Models\Company; @@ -23,6 +24,7 @@ use App\DataMapper\Tax\TaxModel; use App\DataMapper\ClientSettings; use App\DataMapper\CompanySettings; use App\Factory\CompanyUserFactory; +use App\Repositories\InvoiceRepository; use InvoiceNinja\EInvoice\EInvoice; use InvoiceNinja\EInvoice\Symfony\Encode; use App\Services\EDocument\Standards\Peppol; @@ -46,6 +48,9 @@ class PeppolTest extends TestCase protected int $iterations = 10; + + public $faker; + protected function setUp(): void { parent::setUp(); @@ -54,6 +59,8 @@ class PeppolTest extends TestCase $this->markTestSkipped('Skip test for GH Actions'); } + $this->faker = Factory::create(); + $this->makeTestData(); $this->withoutMiddleware( @@ -109,6 +116,7 @@ class PeppolTest extends TestCase $this->company->save(); $company = $this->company; + /** @var Client $client */ $client = Client::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, @@ -121,15 +129,23 @@ class PeppolTest extends TestCase 'id_number' => $params['client_id_number'] ?? '', ]); + $client->setRelation('company', $company); + + /** @var ClientContact $contact */ $contact = ClientContact::factory()->create([ 'client_id' => $client->id, 'company_id' =>$client->company_id, 'user_id' => $client->user_id, 'first_name' => $this->faker->firstName(), 'last_name' => $this->faker->lastName(), - 'email' => $this->faker->safeEmail() + 'email' => $this->faker->safeEmail(), + 'is_primary' => true, + 'send_email' => true, ]); + $client->setRelation('contacts', [$contact]); + + /** @var Invoice $invoice */ $invoice = \App\Models\Invoice::factory()->create([ 'client_id' => $client->id, 'company_id' => $this->company->id, @@ -143,8 +159,10 @@ class PeppolTest extends TestCase 'tax_name2' => '', 'tax_rate3' => 0, 'tax_name3' => '', + 'status_id' => Invoice::STATUS_DRAFT, ]); + $items = $invoice->line_items; foreach($items as &$item) @@ -160,6 +178,9 @@ class PeppolTest extends TestCase $invoice->line_items = array_values($items); $invoice = $invoice->calc()->getInvoice(); + $invoice->setRelation('client', $client); + $invoice->setRelation('company', $company); + return compact('company', 'client', 'invoice'); } @@ -179,7 +200,6 @@ class PeppolTest extends TestCase 'is_tax_exempt' => false, ]; - $entity_data = $this->setupTestData($scenario); $invoice = $entity_data['invoice']; @@ -257,6 +277,17 @@ class PeppolTest extends TestCase $company->settings = $settings; $company->save(); + $invoice->setRelation('company', $company); + $invoice->setRelation('client', $entity_data['client']); + $invoice->save(); + + $repo = new InvoiceRepository(); + $invoice = $repo->save([], $invoice); + + $invoice = $invoice->service()->markSent()->save(); + + $this->assertGreaterThan(0, $invoice->invitations()->count()); + $data = [ 'entity' => 'invoices', 'entity_id' => $invoice->hashed_id @@ -511,6 +542,10 @@ class PeppolTest extends TestCase ]; $invoice->save(); + $repo = new InvoiceRepository(); + $invoice = $repo->save([], $invoice); + $invoice = $invoice->service()->markSent()->save(); + $company = $entity_data['company']; $settings = $company->settings; diff --git a/tests/Feature/EInvoice/Verifactu/VerifactuFeatureTest.php b/tests/Feature/EInvoice/Verifactu/VerifactuFeatureTest.php index de19c48ca1..5699ceb776 100644 --- a/tests/Feature/EInvoice/Verifactu/VerifactuFeatureTest.php +++ b/tests/Feature/EInvoice/Verifactu/VerifactuFeatureTest.php @@ -30,7 +30,8 @@ use App\Services\EDocument\Standards\Verifactu\Models\Invoice as VerifactuInvoic class VerifactuFeatureTest extends TestCase { - private $account; + /** @var Account $account */ + private Account $account; private $company; private $user; private $cu; @@ -50,24 +51,32 @@ class VerifactuFeatureTest extends TestCase parent::setUp(); $this->faker = Faker::create(); + + $this->markTestSkipped('not now'); } private function buildData($settings = null) { - $this->account = Account::factory()->create([ + /** @var Account $a */ + $a = Account::factory()->create([ 'hosted_client_count' => 1000, 'hosted_company_count' => 1000, ]); - $this->account->num_users = 3; - $this->account->save(); + $a->num_users = 3; + $a->save(); - $this->user = User::factory()->create([ + $this->account = $a; + + /** @var User $u */ + $u = User::factory()->create([ 'account_id' => $this->account->id, 'confirmation_code' => 'xyz123', 'email' => $this->faker->unique()->safeEmail(), ]); + $this->user = $u; + if(!$settings) { $settings = CompanySettings::defaults(); $settings->client_online_payment_notification = false; @@ -268,6 +277,7 @@ class VerifactuFeatureTest extends TestCase $invoice->number = 'TEST0033343459'; $invoice->save(); + /** @var Invoice $_inv */ $_inv = Invoice::factory()->create([ 'user_id' => $invoice->user_id, 'company_id' => $invoice->company_id, @@ -292,7 +302,6 @@ class VerifactuFeatureTest extends TestCase $huella = $this->cancellationHash($document, $xx->hash); $cancellation = $document->createCancellation(); - // $cancellation->setFechaHoraHusoGenRegistro('2025-08-09T23:57:25+00:00'); $cancellation->setHuella($huella); $soapXml = $cancellation->toSoapEnvelope(); diff --git a/tests/Unit/PermissionsTest.php b/tests/Unit/PermissionsTest.php index a04b82ef95..a76139410c 100644 --- a/tests/Unit/PermissionsTest.php +++ b/tests/Unit/PermissionsTest.php @@ -37,6 +37,8 @@ class PermissionsTest extends TestCase public $token; + private Account $account; + protected function setUp(): void { parent::setUp(); @@ -47,25 +49,25 @@ class PermissionsTest extends TestCase $this->faker = \Faker\Factory::create(); - $account = Account::factory()->create([ + $acc = Account::factory()->create([ 'hosted_client_count' => 1000, 'hosted_company_count' => 1000, ]); - $account->num_users = 3; - $account->save(); + $acc->num_users = 3; + $acc->save(); $this->company = Company::factory()->create([ - 'account_id' => $account->id, + 'account_id' => $acc->id, ]); $this->user = User::factory()->create([ - 'account_id' => $account->id, + 'account_id' => $acc->id, 'confirmation_code' => '123', 'email' => $this->faker->safeEmail(), ]); - $this->cu = CompanyUserFactory::create($this->user->id, $this->company->id, $account->id); + $this->cu = CompanyUserFactory::create($this->user->id, $this->company->id, $acc->id); $this->cu->is_owner = false; $this->cu->is_admin = false; $this->cu->is_locked = false; @@ -77,21 +79,25 @@ class PermissionsTest extends TestCase $company_token = new CompanyToken(); $company_token->user_id = $this->user->id; $company_token->company_id = $this->company->id; - $company_token->account_id = $account->id; + $company_token->account_id = $acc->id; $company_token->name = 'test token'; $company_token->token = $this->token; $company_token->is_system = true; $company_token->save(); + + $this->account = $acc; } public function testClientOverviewPermissions() { + /** @var User $u */ $u = User::factory()->create([ 'account_id' => $this->company->account_id, 'confirmation_code' => '123', 'email' => $this->faker->safeEmail(), ]); + /** @var Client $c */ $c = Client::factory()->create([ 'company_id' => $this->company->id, 'user_id' => $u->id, @@ -131,6 +137,9 @@ class PermissionsTest extends TestCase $this->assertEquals(2, count($data)); + $u->forceDelete(); + + $this->account->forceDelete(); } @@ -148,6 +157,10 @@ class PermissionsTest extends TestCase $this->assertTrue($this->user->hasExcludedPermissions(["view_client"])); + + $this->account->forceDelete(); + + } public function testHasExcludedPermissions2() @@ -177,6 +190,8 @@ class PermissionsTest extends TestCase $this->assertFalse($this->user->hasExcludedPermissions(["view_client"], ['view_invoice'])); + $this->account->forceDelete(); + } public function testIntersectPermissions() @@ -209,6 +224,10 @@ class PermissionsTest extends TestCase $this->assertFalse($this->user->hasIntersectPermissions(["createbank_transaction"])); $this->assertTrue($this->user->hasIntersectPermissions(["create_bank_transaction"])); $this->assertTrue($this->user->hasIntersectPermissions(['create_bank_transaction','edit_bank_transaction','view_bank_transaction'])); + + + $this->account->forceDelete(); + } public function testViewClientPermission() @@ -265,6 +284,9 @@ class PermissionsTest extends TestCase $low_cu->save(); $this->assertTrue($this->user->hasPermission('view_recurring_invoice')); + + $this->account->forceDelete(); + } public function testPermissionResolution() @@ -312,6 +334,8 @@ class PermissionsTest extends TestCase $this->assertEquals('invoice', \Illuminate\Support\Str::snake(class_basename(Invoice::class))); $this->assertEquals('recurring_invoice', \Illuminate\Support\Str::snake(class_basename(RecurringInvoice::class))); + + $this->account->forceDelete(); } public function testExactPermissions() @@ -328,6 +352,9 @@ class PermissionsTest extends TestCase $this->assertFalse($this->user->hasExactPermissionAndAll("view_client")); $this->assertFalse($this->user->hasExactPermissionAndAll("view_all")); + + $this->account->forceDelete(); + } public function testViewAllValidPermissions() @@ -338,6 +365,9 @@ class PermissionsTest extends TestCase $this->assertTrue($this->user->hasExactPermissionAndAll("view_client")); $this->assertTrue($this->user->hasExactPermissionAndAll("view_all")); + + $this->account->forceDelete(); + } public function testReturnTypesOfStripos() @@ -368,5 +398,9 @@ class PermissionsTest extends TestCase $this->assertTrue(is_int(stripos($all_permission, "view_client")) !== false); $this->assertTrue(is_int(stripos($all_permission, "view_client"))); + + + $this->account->forceDelete(); + } }