Wiring up verifactu sending
This commit is contained in:
parent
3d3b5f6938
commit
c5c9c4325e
|
|
@ -39,13 +39,13 @@ class VerifactuAmountCheck implements ValidationRule
|
||||||
|
|
||||||
$company = $user->company();
|
$company = $user->company();
|
||||||
|
|
||||||
if ($company->verifactuEnabled()) {
|
if ($company->verifactuEnabled()) { // Company level check if Verifactu is enabled
|
||||||
|
|
||||||
$client = Client::withTrashed()->find($this->input['client_id']);
|
$client = Client::withTrashed()->find($this->input['client_id']);
|
||||||
|
|
||||||
if($client->country->iso_3166_2 !== 'ES') {
|
if($client->country->iso_3166_2 !== 'ES') { // Client level check if client is in Spain
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$invoice = false;
|
$invoice = false;
|
||||||
$child_invoices = false;
|
$child_invoices = false;
|
||||||
|
|
|
||||||
|
|
@ -278,6 +278,14 @@ class Activity extends StaticModel
|
||||||
public const E_EXPENSE_CREATED = 148;
|
public const E_EXPENSE_CREATED = 148;
|
||||||
|
|
||||||
public const EMAIL_CREDIT = 149;
|
public const EMAIL_CREDIT = 149;
|
||||||
|
|
||||||
|
public const VERIFACTU_INVOICE_SENT = 150;
|
||||||
|
|
||||||
|
public const VERIFACTU_INVOICE_SENT_FAILURE = 151;
|
||||||
|
|
||||||
|
public const VERIFACTU_CANCELLATION_SENT = 152;
|
||||||
|
|
||||||
|
public const VERIFACTU_CANCELLATION_SENT_FAILURE = 153;
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'is_system' => 'boolean',
|
'is_system' => 'boolean',
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,8 @@ class SystemLog extends Model
|
||||||
|
|
||||||
public const CATEGORY_LOG = 6;
|
public const CATEGORY_LOG = 6;
|
||||||
|
|
||||||
|
public const CATEGORY_VERIFACTU = 7;
|
||||||
|
|
||||||
/* Event IDs*/
|
/* Event IDs*/
|
||||||
public const EVENT_PAYMENT_RECONCILIATION_FAILURE = 10;
|
public const EVENT_PAYMENT_RECONCILIATION_FAILURE = 10;
|
||||||
|
|
||||||
|
|
@ -115,6 +117,10 @@ class SystemLog extends Model
|
||||||
|
|
||||||
public const EVENT_INBOUND_MAIL_BLOCKED = 62;
|
public const EVENT_INBOUND_MAIL_BLOCKED = 62;
|
||||||
|
|
||||||
|
public const EVENT_VERIFACTU_FAILURE = 70;
|
||||||
|
|
||||||
|
public const EVENT_VERIFACTU_SUCCESS = 71;
|
||||||
|
|
||||||
/*Type IDs*/
|
/*Type IDs*/
|
||||||
public const TYPE_PAYPAL = 300;
|
public const TYPE_PAYPAL = 300;
|
||||||
|
|
||||||
|
|
@ -180,6 +186,12 @@ class SystemLog extends Model
|
||||||
|
|
||||||
public const TYPE_GENERIC = 900;
|
public const TYPE_GENERIC = 900;
|
||||||
|
|
||||||
|
public const TYPE_VERIFACTU_CANCELLATION = 1000;
|
||||||
|
|
||||||
|
public const TYPE_VERIFACTU_INVOICE = 1001;
|
||||||
|
|
||||||
|
public const TYPE_VERIFACTU_RECTIFICATION = 1002;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'client_id',
|
'client_id',
|
||||||
'company_id',
|
'company_id',
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,16 @@ use Mail;
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
|
use App\Models\Activity;
|
||||||
|
use App\Models\SystemLog;
|
||||||
use App\Libraries\MultiDB;
|
use App\Libraries\MultiDB;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
|
use App\Jobs\Util\SystemLogger;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Mail\Mailables\Address;
|
use Illuminate\Mail\Mailables\Address;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use App\Repositories\ActivityRepository;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
|
@ -63,16 +67,13 @@ class SendToAeat implements ShouldQueue
|
||||||
return [5, 30, 240, 3600, 7200];
|
return [5, 30, 240, 3600, 7200];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle()
|
public function handle(ActivityRepository $activity_repository)
|
||||||
{
|
{
|
||||||
MultiDB::setDB($this->company->db);
|
MultiDB::setDB($this->company->db);
|
||||||
|
|
||||||
$invoice = Invoice::withTrashed()->find($this->invoice_id);
|
$invoice = Invoice::withTrashed()->find($this->invoice_id);
|
||||||
|
|
||||||
switch($this->action) {
|
switch($this->action) {
|
||||||
case 'modify':
|
|
||||||
$this->modifyInvoice($invoice);
|
|
||||||
break;
|
|
||||||
case 'create':
|
case 'create':
|
||||||
$this->createInvoice($invoice);
|
$this->createInvoice($invoice);
|
||||||
break;
|
break;
|
||||||
|
|
@ -92,27 +93,7 @@ class SendToAeat implements ShouldQueue
|
||||||
* @param Invoice $invoice
|
* @param Invoice $invoice
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function modifyInvoice(Invoice $invoice)
|
|
||||||
{
|
|
||||||
|
|
||||||
$verifactu = new Verifactu($invoice);
|
|
||||||
$verifactu->run();
|
|
||||||
|
|
||||||
$envelope = $verifactu->getEnvelope();
|
|
||||||
|
|
||||||
$response = $verifactu->send($envelope);
|
|
||||||
|
|
||||||
nlog($response);
|
|
||||||
|
|
||||||
// if($invoice->amount >= 0) {
|
|
||||||
// $document = (new RegistroAlta($invoice))->run()->getInvoice();
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// $document = (new RegistroRectificacion($invoice))->run()->getInvoice();
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createInvoice(Invoice $invoice)
|
public function createInvoice(Invoice $invoice)
|
||||||
{
|
{
|
||||||
$verifactu = new Verifactu($invoice);
|
$verifactu = new Verifactu($invoice);
|
||||||
|
|
@ -124,6 +105,9 @@ class SendToAeat implements ShouldQueue
|
||||||
|
|
||||||
nlog($response);
|
nlog($response);
|
||||||
|
|
||||||
|
$this->writeActivity($invoice, $response['success'] ? Activity::VERIFACTU_INVOICE_SENT : Activity::VERIFACTU_INVOICE_SENT_FAILURE, $response['message']);
|
||||||
|
$this->systemLog($invoice, $response, $response['success'] ? SystemLog::EVENT_VERIFACTU_SUCCESS : SystemLog::EVENT_VERIFACTU_FAILURE, SystemLog::TYPE_VERIFACTU_INVOICE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cancelInvoice(Invoice $invoice)
|
public function cancelInvoice(Invoice $invoice)
|
||||||
|
|
@ -153,12 +137,15 @@ class SendToAeat implements ShouldQueue
|
||||||
$parent->saveQuietly();
|
$parent->saveQuietly();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//@todo - verifactu logging
|
//@todo - verifactu logging
|
||||||
|
$this->writeActivity($invoice, $response['success'] ? Activity::VERIFACTU_CANCELLATION_SENT : Activity::VERIFACTU_CANCELLATION_SENT_FAILURE, $response['message']);
|
||||||
|
$this->systemLog($invoice, $response, $response['success'] ? SystemLog::EVENT_VERIFACTU_SUCCESS : SystemLog::EVENT_VERIFACTU_FAILURE, SystemLog::TYPE_VERIFACTU_CANCELLATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function middleware()
|
public function middleware()
|
||||||
{
|
{
|
||||||
return [new WithoutOverlapping("send_to_aeat_{$this->company->company_key}")];
|
return [(new WithoutOverlapping("send_to_aeat_{$this->company->company_key}"))->releaseAfter(30)->expireAfter(30)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function failed($exception = null)
|
public function failed($exception = null)
|
||||||
|
|
@ -166,7 +153,34 @@ class SendToAeat implements ShouldQueue
|
||||||
nlog($exception);
|
nlog($exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function writeActivity(Invoice $invoice, int $activity_id, string $notes = ''): void
|
||||||
|
{
|
||||||
|
$activity = new Activity();
|
||||||
|
$activity->user_id = $invoice->user_id;
|
||||||
|
$activity->client_id = $invoice->client_id;
|
||||||
|
$activity->company_id = $invoice->company_id;
|
||||||
|
$activity->account_id = $invoice->company->account_id;
|
||||||
|
$activity->activity_type_id = $activity_id;
|
||||||
|
$activity->invoice_id = $invoice->id;
|
||||||
|
$activity->notes = str_replace('"', '', $notes);
|
||||||
|
$activity->is_system = true;
|
||||||
|
|
||||||
|
$activity->save();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function systemLog(Invoice $invoice, array $data, int $event_id, int $type_id): void
|
||||||
|
{
|
||||||
|
(new SystemLogger(
|
||||||
|
$data,
|
||||||
|
SystemLog::CATEGORY_VERIFACTU,
|
||||||
|
$event_id,
|
||||||
|
$type_id,
|
||||||
|
$invoice->client,
|
||||||
|
$invoice->company
|
||||||
|
)
|
||||||
|
)->handle();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cancellationHash
|
* cancellationHash
|
||||||
|
|
|
||||||
|
|
@ -76,39 +76,56 @@ class HandleCancellation extends AbstractService
|
||||||
private function verifactuCancellation(): Invoice
|
private function verifactuCancellation(): Invoice
|
||||||
{
|
{
|
||||||
|
|
||||||
$replicated_invoice = $this->invoice->replicate();
|
|
||||||
|
|
||||||
$this->invoice = $this->invoice->service()->setStatus(Invoice::STATUS_CANCELLED)->save();
|
$this->invoice = $this->invoice->service()->setStatus(Invoice::STATUS_CANCELLED)->save();
|
||||||
$this->invoice->service()->workFlow()->save();
|
$this->invoice->service()->workFlow()->save();
|
||||||
|
|
||||||
$replicated_invoice->status_id = Invoice::STATUS_DRAFT;
|
// R2 Cancellation - do not create a separate document
|
||||||
$replicated_invoice->date = now()->format('Y-m-d');
|
if($this->invoice->backup->document_type === 'R2'){
|
||||||
$replicated_invoice->due_date = null;
|
|
||||||
$replicated_invoice->partial = 0;
|
|
||||||
$replicated_invoice->partial_due_date = null;
|
|
||||||
$replicated_invoice->number = null;
|
|
||||||
$replicated_invoice->amount = 0;
|
|
||||||
$replicated_invoice->balance = 0;
|
|
||||||
$replicated_invoice->paid_to_date = 0;
|
|
||||||
|
|
||||||
$items = $replicated_invoice->line_items;
|
$parent = Invoice::withTrashed()->find($this->decodePrimaryKey($this->invoice->backup->parent_invoice_id));
|
||||||
|
|
||||||
foreach($items as &$item) {
|
if(!$parent) {
|
||||||
$item->quantity = $item->quantity * -1;
|
return $this->invoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parent->backup->adjustable_amount -= $this->invoice->amount;
|
||||||
|
$parent->backup->child_invoice_ids->reject(fn($id) => $id === $this->invoice->hashed_id);
|
||||||
|
$parent->save();
|
||||||
|
|
||||||
|
$this->invoice->service()->cancelVerifactu();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$replicated_invoice = $this->invoice->replicate();
|
||||||
|
$replicated_invoice->status_id = Invoice::STATUS_DRAFT;
|
||||||
|
$replicated_invoice->date = now()->format('Y-m-d');
|
||||||
|
$replicated_invoice->due_date = null;
|
||||||
|
$replicated_invoice->partial = 0;
|
||||||
|
$replicated_invoice->partial_due_date = null;
|
||||||
|
$replicated_invoice->number = null;
|
||||||
|
$replicated_invoice->amount = 0;
|
||||||
|
$replicated_invoice->balance = 0;
|
||||||
|
$replicated_invoice->paid_to_date = 0;
|
||||||
|
|
||||||
|
$items = $replicated_invoice->line_items;
|
||||||
|
|
||||||
|
foreach($items as &$item) {
|
||||||
|
$item->quantity = $item->quantity * -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$replicated_invoice->line_items = $items;
|
||||||
|
$replicated_invoice->backup->parent_invoice_id = $this->invoice->hashed_id;
|
||||||
|
$replicated_invoice->backup->parent_invoice_number = $this->invoice->number;
|
||||||
|
$replicated_invoice->backup->document_type = 'R2'; // Full Credit Note Generated for the invoice
|
||||||
|
|
||||||
|
$invoice_repository = new InvoiceRepository();
|
||||||
|
$replicated_invoice = $invoice_repository->save([], $replicated_invoice);
|
||||||
|
$replicated_invoice->service()->markSent()->sendVerifactu()->save();
|
||||||
|
|
||||||
|
$this->invoice->backup->child_invoice_ids->push($replicated_invoice->hashed_id);
|
||||||
|
|
||||||
|
$this->invoice->saveQuietly();
|
||||||
}
|
}
|
||||||
|
|
||||||
$replicated_invoice->line_items = $items;
|
|
||||||
$replicated_invoice->backup->parent_invoice_id = $this->invoice->hashed_id;
|
|
||||||
$replicated_invoice->backup->parent_invoice_number = $this->invoice->number;
|
|
||||||
$replicated_invoice->backup->document_type = 'R2'; // Full Credit Note Generated for the invoice
|
|
||||||
|
|
||||||
$invoice_repository = new InvoiceRepository();
|
|
||||||
$replicated_invoice = $invoice_repository->save([], $replicated_invoice);
|
|
||||||
$replicated_invoice->service()->markSent()->sendVerifactu()->save();
|
|
||||||
|
|
||||||
$this->invoice->backup->child_invoice_ids->push($replicated_invoice->hashed_id);
|
|
||||||
|
|
||||||
$this->invoice->saveQuietly();
|
|
||||||
$this->invoice->fresh();
|
$this->invoice->fresh();
|
||||||
|
|
||||||
event(new InvoiceWasCancelled($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new InvoiceWasCancelled($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ use Illuminate\Support\Facades\Storage;
|
||||||
use App\Events\Invoice\InvoiceWasArchived;
|
use App\Events\Invoice\InvoiceWasArchived;
|
||||||
use App\Jobs\Inventory\AdjustProductInventory;
|
use App\Jobs\Inventory\AdjustProductInventory;
|
||||||
use App\Libraries\Currency\Conversion\CurrencyApi;
|
use App\Libraries\Currency\Conversion\CurrencyApi;
|
||||||
|
use App\Services\EDocument\Standards\Verifactu\SendToAeat;
|
||||||
|
|
||||||
class InvoiceService
|
class InvoiceService
|
||||||
{
|
{
|
||||||
|
|
@ -248,7 +249,7 @@ class InvoiceService
|
||||||
$this->invoice = (new MarkInvoiceDeleted($this->invoice))->run();
|
$this->invoice = (new MarkInvoiceDeleted($this->invoice))->run();
|
||||||
|
|
||||||
if($this->invoice->company->verifactuEnabled()) {
|
if($this->invoice->company->verifactuEnabled()) {
|
||||||
$this->deleteVerifactu();
|
$this->cancelVerifactu();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
@ -680,31 +681,24 @@ class InvoiceService
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sendVerifactu
|
* sendVerifactu
|
||||||
* @todo - send the invoice to AEAT
|
|
||||||
* ONLY send when the transaction is ES => ES
|
|
||||||
* Ensure we run all sending syncronously to ensure chronology
|
|
||||||
*
|
*
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function sendVerifactu(): self
|
public function sendVerifactu(): self
|
||||||
{
|
{
|
||||||
// if($this->invoice->company->verifactuEnabled()) {
|
SendToAeat::dispatch($this->invoice->id, $this->invoice->company, 'create');
|
||||||
// (new SendVerifactu($this->invoice))->handle();
|
|
||||||
// }
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* deleteVerifactu
|
* cancelVerifactu
|
||||||
* @todo - handle "cancelling" the invoice in AEAT
|
*
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function deleteVerifactu(): self
|
public function cancelVerifactu(): self
|
||||||
{
|
{
|
||||||
// if($this->invoice->company->verifactuEnabled()) {
|
SendToAeat::dispatch($this->invoice->id, $this->invoice->company, 'cancel');
|
||||||
// (new DeleteVerifactu($this->invoice))->handle();
|
|
||||||
// }
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5576,6 +5576,10 @@ $lang = array(
|
||||||
'restore_disabled_verifactu' => 'You cannot restore an invoice once it has been deleted',
|
'restore_disabled_verifactu' => 'You cannot restore an invoice once it has been deleted',
|
||||||
'delete_disabled_verifactu' => 'You cannot delete an invoice once it has been cancelled or modified',
|
'delete_disabled_verifactu' => 'You cannot delete an invoice once it has been cancelled or modified',
|
||||||
'rectify' => 'Rectificar',
|
'rectify' => 'Rectificar',
|
||||||
|
'verifactu_invoice_send_success' => 'Invoice :invoice for :client sent to AEAT successfully',
|
||||||
|
'verifactu_invoice_sent_failure' => 'Invoice :invoice for :client failed to send to AEAT :notes',
|
||||||
|
'verifactu_cancellation_send_success' => 'Invoice cancellation for :invoice sent to AEAT successfully',
|
||||||
|
'verifactu_cancellation_send_failure' => 'Invoice cancellation for :invoice failed to send to AEAT :notes',
|
||||||
);
|
);
|
||||||
|
|
||||||
return $lang;
|
return $lang;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue