Integration of Verifactu with UI
This commit is contained in:
parent
af926a394c
commit
1252cdf7ae
|
|
@ -330,8 +330,13 @@ class BaseModel extends Model
|
|||
}
|
||||
|
||||
// special catch here for einvoicing eventing
|
||||
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);
|
||||
if ($event_id == Webhook::EVENT_SENT_INVOICE && ($this instanceof Invoice) && $this->backup->guid == "") {
|
||||
if($this->client->peppolSendingEnabled()) {
|
||||
\App\Services\EDocument\Jobs\SendEDocument::dispatch(get_class($this), $this->id, $this->company->db);
|
||||
}
|
||||
elseif($this->company->verifactuEnabled()) {
|
||||
$this->service()->sendVerifactu();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
<?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\Models;
|
||||
|
||||
|
|
@ -57,7 +66,6 @@ use Laracasts\Presenter\PresentableTrait;
|
|||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Quote> $quotes
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Expense> $expenses
|
||||
*
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Project extends BaseModel
|
||||
|
|
@ -134,17 +142,17 @@ class Project extends BaseModel
|
|||
return $this->hasMany(Task::class);
|
||||
}
|
||||
|
||||
public function expenses(): HasMany
|
||||
public function expenses(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(Expense::class);
|
||||
}
|
||||
|
||||
public function invoices(): HasMany
|
||||
public function invoices(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(Invoice::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function quotes(): HasMany
|
||||
public function quotes(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(Quote::class);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ class Verifactu extends AbstractService
|
|||
|
||||
$response = $this->aeat_client->send($soapXml);
|
||||
|
||||
if($response['success']){
|
||||
if($response['success'] || $response['status'] == 'ParcialmenteCorrecto'){
|
||||
$this->writeLog($response);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ class AeatClient
|
|||
$this->certificate = $this->certificate ?? config('services.verifactu.certificate');
|
||||
$this->ssl_key = $this->ssl_key ?? config('services.verifactu.ssl_key');
|
||||
|
||||
if(config('services.verifactu.test_mode')) {
|
||||
$this->setTestMode();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ class SendToAeat implements ShouldQueue
|
|||
|
||||
/**
|
||||
* 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.
|
||||
|
|
@ -111,7 +110,12 @@ class SendToAeat implements ShouldQueue
|
|||
|
||||
nlog($response);
|
||||
|
||||
$this->writeActivity($invoice, $response['success'] ? Activity::VERIFACTU_INVOICE_SENT : Activity::VERIFACTU_INVOICE_SENT_FAILURE, $response['message']);
|
||||
$message = '';
|
||||
if (isset($response['errors'][0]['message'])) {
|
||||
$message = $response['errors'][0]['message'];
|
||||
}
|
||||
|
||||
$this->writeActivity($invoice, $response['success'] ? Activity::VERIFACTU_INVOICE_SENT : Activity::VERIFACTU_INVOICE_SENT_FAILURE, $message);
|
||||
$this->systemLog($invoice, $response, $response['success'] ? SystemLog::EVENT_VERIFACTU_SUCCESS : SystemLog::EVENT_VERIFACTU_FAILURE, SystemLog::TYPE_VERIFACTU_INVOICE);
|
||||
|
||||
}
|
||||
|
|
@ -120,6 +124,7 @@ class SendToAeat implements ShouldQueue
|
|||
{
|
||||
|
||||
$verifactu = new Verifactu($invoice);
|
||||
|
||||
$document = (new RegistroAlta($invoice))->run()->getInvoice();
|
||||
|
||||
$last_hash = $invoice->company->verifactu_logs()->first();
|
||||
|
|
@ -127,25 +132,36 @@ class SendToAeat implements ShouldQueue
|
|||
$huella = $this->cancellationHash($document, $last_hash->hash);
|
||||
|
||||
$cancellation = $document->createCancellation();
|
||||
|
||||
$cancellation->setHuella($huella);
|
||||
|
||||
$soapXml = $cancellation->toSoapEnvelope();
|
||||
|
||||
$response = $verifactu->send($soapXml);
|
||||
$response = $verifactu->setInvoice($document)
|
||||
->setHuella($huella)
|
||||
->setPreviousHash($last_hash->hash)
|
||||
->send($soapXml);
|
||||
|
||||
nlog($response);
|
||||
|
||||
$message = '';
|
||||
|
||||
if($response['success']) {
|
||||
//if successful, we need to pop this invoice from the child array of the parent invoice!
|
||||
//if successful, we need to pop this invoice from the child array of the parent invoice!
|
||||
$parent = Invoice::withTrashed()->find($invoice->backup->parent_invoice_id);
|
||||
if($parent) {
|
||||
$parent->backup->child_invoice_ids = $parent->backup->child_invoice_ids->reject(fn($id) => $id === $invoice->hashed_id);
|
||||
$parent->saveQuietly();
|
||||
}
|
||||
|
||||
if($parent) {
|
||||
$parent->backup->child_invoice_ids = $parent->backup->child_invoice_ids->reject(fn($id) => $id === $invoice->hashed_id);
|
||||
$parent->saveQuietly();
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($response['errors'][0]['message'])){
|
||||
$message = $response['errors'][0]['message'];
|
||||
}
|
||||
|
||||
//@todo - verifactu logging
|
||||
$this->writeActivity($invoice, $response['success'] ? Activity::VERIFACTU_CANCELLATION_SENT : Activity::VERIFACTU_CANCELLATION_SENT_FAILURE, $response['message']);
|
||||
$this->writeActivity($invoice, $response['success'] ? Activity::VERIFACTU_CANCELLATION_SENT : Activity::VERIFACTU_CANCELLATION_SENT_FAILURE, $message);
|
||||
$this->systemLog($invoice, $response, $response['success'] ? SystemLog::EVENT_VERIFACTU_SUCCESS : SystemLog::EVENT_VERIFACTU_FAILURE, SystemLog::TYPE_VERIFACTU_CANCELLATION);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,11 +17,13 @@ use App\Repositories\InvoiceRepository;
|
|||
use App\Services\AbstractService;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use stdClass;
|
||||
|
||||
class HandleCancellation extends AbstractService
|
||||
{
|
||||
use GeneratesCounter;
|
||||
use MakesHash;
|
||||
|
||||
public function __construct(private Invoice $invoice, private ?string $reason = null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -678,7 +678,6 @@ class InvoiceService
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sendVerifactu
|
||||
*
|
||||
|
|
|
|||
|
|
@ -81,8 +81,13 @@ class TriggeredActions extends AbstractService
|
|||
$company->save();
|
||||
}
|
||||
|
||||
if($this->request->has('retry_e_send') && $this->request->input('retry_e_send') == 'true' && strlen($this->invoice->backup->guid ?? '') == 0 && $this->invoice->client->peppolSendingEnabled()) {
|
||||
\App\Services\EDocument\Jobs\SendEDocument::dispatch(get_class($this->invoice), $this->invoice->id, $this->invoice->company->db);
|
||||
if($this->request->has('retry_e_send') && $this->request->input('retry_e_send') == 'true' && strlen($this->invoice->backup->guid ?? '') == 0) {
|
||||
if($this->invoice->client->peppolSendingEnabled()) {
|
||||
\App\Services\EDocument\Jobs\SendEDocument::dispatch(get_class($this->invoice), $this->invoice->id, $this->invoice->company->db);
|
||||
}
|
||||
elseif($this->invoice->company->verifactuEnabled()) {
|
||||
$this->invoice->service()->sendVerifactu();
|
||||
}
|
||||
}
|
||||
|
||||
if($this->request->has('redirect')) {
|
||||
|
|
|
|||
|
|
@ -5168,16 +5168,16 @@
|
|||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v11.45.1",
|
||||
"version": "v11.45.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "b09ba32795b8e71df10856a2694706663984a239"
|
||||
"reference": "d134bf11e2208c0c5bd488cf19e612ca176b820a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/b09ba32795b8e71df10856a2694706663984a239",
|
||||
"reference": "b09ba32795b8e71df10856a2694706663984a239",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/d134bf11e2208c0c5bd488cf19e612ca176b820a",
|
||||
"reference": "d134bf11e2208c0c5bd488cf19e612ca176b820a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -5285,7 +5285,7 @@
|
|||
"league/flysystem-read-only": "^3.25.1",
|
||||
"league/flysystem-sftp-v3": "^3.25.1",
|
||||
"mockery/mockery": "^1.6.10",
|
||||
"orchestra/testbench-core": "^9.13.2",
|
||||
"orchestra/testbench-core": "^9.16.0",
|
||||
"pda/pheanstalk": "^5.0.6",
|
||||
"php-http/discovery": "^1.15",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
|
|
@ -5379,7 +5379,7 @@
|
|||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2025-06-03T14:01:40+00:00"
|
||||
"time": "2025-08-13T20:28:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/octane",
|
||||
|
|
@ -8238,16 +8238,16 @@
|
|||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v5.6.0",
|
||||
"version": "v5.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56"
|
||||
"reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/221b0d0fdf1369c71047ad1d18bb5880017bbc56",
|
||||
"reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
|
||||
"reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -8266,7 +8266,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.0-dev"
|
||||
"dev-master": "5.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
|
@ -8290,9 +8290,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.0"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1"
|
||||
},
|
||||
"time": "2025-07-27T20:03:57+00:00"
|
||||
"time": "2025-08-13T20:13:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nordigen/nordigen-php",
|
||||
|
|
@ -8675,16 +8675,16 @@
|
|||
},
|
||||
{
|
||||
"name": "open-telemetry/context",
|
||||
"version": "1.3.0",
|
||||
"version": "1.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opentelemetry-php/context.git",
|
||||
"reference": "4d5d98f1d4311a55b8d07e3d4c06d2430b4e6efc"
|
||||
"reference": "438f71812242db3f196fb4c717c6f92cbc819be6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opentelemetry-php/context/zipball/4d5d98f1d4311a55b8d07e3d4c06d2430b4e6efc",
|
||||
"reference": "4d5d98f1d4311a55b8d07e3d4c06d2430b4e6efc",
|
||||
"url": "https://api.github.com/repos/opentelemetry-php/context/zipball/438f71812242db3f196fb4c717c6f92cbc819be6",
|
||||
"reference": "438f71812242db3f196fb4c717c6f92cbc819be6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -8730,7 +8730,7 @@
|
|||
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
|
||||
"source": "https://github.com/open-telemetry/opentelemetry-php"
|
||||
},
|
||||
"time": "2025-08-04T03:25:06+00:00"
|
||||
"time": "2025-08-13T01:12:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/constant_time_encoding",
|
||||
|
|
@ -20559,23 +20559,23 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/recursion-context",
|
||||
"version": "6.0.2",
|
||||
"version": "6.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/recursion-context.git",
|
||||
"reference": "694d156164372abbd149a4b85ccda2e4670c0e16"
|
||||
"reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16",
|
||||
"reference": "694d156164372abbd149a4b85ccda2e4670c0e16",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc",
|
||||
"reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^11.0"
|
||||
"phpunit/phpunit": "^11.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
|
@ -20611,15 +20611,27 @@
|
|||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
|
||||
"security": "https://github.com/sebastianbergmann/recursion-context/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2"
|
||||
"source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://liberapay.com/sebastianbergmann",
|
||||
"type": "liberapay"
|
||||
},
|
||||
{
|
||||
"url": "https://thanks.dev/u/gh/sebastianbergmann",
|
||||
"type": "thanks_dev"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-03T05:10:34+00:00"
|
||||
"time": "2025-08-13T04:42:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/type",
|
||||
|
|
|
|||
|
|
@ -151,5 +151,6 @@ return [
|
|||
'certificate' => env('VERIFACTU_CERTIFICATE', ''),
|
||||
'ssl_key' => env('VERIFACTU_SSL_KEY', ''),
|
||||
'sender_name' => env('VERIFACTU_SENDER_NAME', 'CERTIFICADO FISICA PRUEBAS'),
|
||||
'test_mode' => env('VERIFACTU_TEST_MODE', false),
|
||||
],
|
||||
];
|
||||
Loading…
Reference in New Issue