From 8c2b97dce5e1471c787552dfec4d29095ea0372a Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 29 Aug 2024 15:16:01 +1000 Subject: [PATCH] EInvoice sending activity --- .../ClientPortal/InvitationController.php | 1 + app/Livewire/EInvoice/Portal.php | 12 +-- app/Models/Activity.php | 7 +- app/Services/EDocument/Jobs/SendEDocument.php | 83 ++++++++++++++++++- config/ninja.php | 1 + lang/en/texts.php | 1 + routes/api.php | 1 - 7 files changed, 91 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/ClientPortal/InvitationController.php b/app/Http/Controllers/ClientPortal/InvitationController.php index ea4b65c97156..4ef3afb5cbc5 100644 --- a/app/Http/Controllers/ClientPortal/InvitationController.php +++ b/app/Http/Controllers/ClientPortal/InvitationController.php @@ -117,6 +117,7 @@ class InvitationController extends Controller if(!auth()->guard('contact')->check()) { $this->middleware('auth:contact'); + /** @var \App\Models\InvoiceInvitation | \App\Models\QuoteInvitation | \App\Models\CreditInvitation | \App\Models\RecurringInvoiceInvitation $invitation */ return redirect()->route('client.login', ['intended' => route('client.'.$entity.'.show', [$entity => $this->encodePrimaryKey($invitation->{$key}), 'silent' => $is_silent])]); } diff --git a/app/Livewire/EInvoice/Portal.php b/app/Livewire/EInvoice/Portal.php index 8756168029ab..44cccb92072c 100644 --- a/app/Livewire/EInvoice/Portal.php +++ b/app/Livewire/EInvoice/Portal.php @@ -23,13 +23,13 @@ class Portal extends Component public array $companies; - // private string $api_url = 'https://invoicing.co' - - private string $api_url = 'http://ninja.test:8000'; + private string $api_url = ''; public function mount() { + $this->api_url = config('ninja.hosted_ninja_url'); + $this->getCompanies(); } @@ -99,15 +99,12 @@ class Portal extends Component $register_company = array_merge($company, $register_company); } - nlog("{$this->api_url}/api/einvoice/createLegalEntity"); - nlog($register_company); - $r = Http::withHeaders($this->getHeaders()) ->post("{$this->api_url}/api/einvoice/createLegalEntity", $register_company); if($r->successful()) { - nlog($r->json()); + nlog($r->body()); $response = $r->json(); @@ -123,7 +120,6 @@ class Portal extends Component if($r->failed()) nlog($r->getBody()->getContents()); - $error = json_decode($r->getBody()->getContents(),true); session()->flash('error', $error['message']); diff --git a/app/Models/Activity.php b/app/Models/Activity.php index cc57c9a0af39..392260fb83cb 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -265,9 +265,11 @@ class Activity extends StaticModel public const QUOTE_REMINDER1_SENT = 142; - public const AUTOBILL_SUCCESS = 143; //:invoice auto billing succeeded + public const AUTOBILL_SUCCESS = 143; - public const AUTOBILL_FAILURE = 144; //:invoice autobilling failed :note + public const AUTOBILL_FAILURE = 144; + + public const EMAIL_EINVOICE_SUCCESS = 145; protected $casts = [ 'is_system' => 'boolean', @@ -284,7 +286,6 @@ class Activity extends StaticModel 'backup', ]; - public function getHashedIdAttribute(): string { return $this->encodePrimaryKey($this->id); diff --git a/app/Services/EDocument/Jobs/SendEDocument.php b/app/Services/EDocument/Jobs/SendEDocument.php index 55550c1aa282..3e0409bcac86 100644 --- a/app/Services/EDocument/Jobs/SendEDocument.php +++ b/app/Services/EDocument/Jobs/SendEDocument.php @@ -11,15 +11,19 @@ namespace App\Services\EDocument\Jobes; -use App\Libraries\MultiDB; -use App\Models\Invoice; use App\Utils\Ninja; +use App\Models\Invoice; +use App\Libraries\MultiDB; +use App\Models\Activity; use Illuminate\Bus\Queueable; +use Illuminate\Support\Facades\Http; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use App\Services\EDocument\Standards\Peppol; use Illuminate\Queue\Middleware\WithoutOverlapping; +use App\Services\EDocument\Gateway\Storecove\Storecove; class SendEDocument implements ShouldQueue { @@ -53,15 +57,88 @@ class SendEDocument implements ShouldQueue if(Ninja::isSelfHost() && ($model instanceof Invoice) && $model->company->legal_entity_id) { + + $p = new Peppol($model); + + $p->run(); + $xml = $p->toXml(); + $identifiers = $p->getStorecoveMeta(); + + $payload = [ + 'legal_entity_id' => $model->company->legal_entity_id, + 'document' => base64_encode($xml), + 'tenant_id' => $model->company->company_key, + 'identifiers' => $identifiers, + ]; + + $r = Http::withHeaders($this->getHeaders()) + ->post(config('ninja.hosted_ninja_url')."/api/einvoice/submission", $payload); + + if($r->successful()) { + nlog("Model {$model->number} was successfully sent for third party processing via hosted Invoice Ninja"); + + $data = $r->json(); + return $this->writeActivity($model, $data['guid']); + + } + + if($r->failed()) { + nlog("Model {$model->number} failed to be accepted by invoice ninja, error follows:"); + nlog($r->getBody()->getContents()); + } + //self hosted sender } if(Ninja::isHosted() && ($model instanceof Invoice) && $model->company->legal_entity_id) { //hosted sender + $p = new Peppol($model); + + $p->run(); + $xml = $p->toXml(); + $identifiers = $p->getStorecoveMeta(); + + $sc = new \App\Services\EDocument\Gateway\Storecove\Storecove(); + $r = $sc->sendDocument($xml, $model->company->legal_entity_id, $identifiers); + + if(is_string($r)) + return $this->writeActivity($model, $r); + + if($r->failed()) { + nlog("Model {$model->number} failed to be accepted by invoice ninja, error follows:"); + nlog($r->getBody()->getContents()); + } + } - return; + } + + private function writeActivity($model, string $guid) + { + $activity = new Activity(); + $activity->user_id = $model->user_id; + $activity->client_id = $model->client_id ?? $model->vendor_id; + $activity->company_id = $model->company_id; + $activity->activity_type_id = Activity::EMAIL_EINVOICE_SUCCESS; + $activity->invoice_id = $model->id; + $activity->notes = $guid; + $activity->save(); + + } + + /** + * Self hosted request headers + * + * @return array + */ + private function getHeaders(): array + { + return [ + 'X-API-SELF-HOST-TOKEN' => config('ninja.license_key'), + "X-Requested-With" => "XMLHttpRequest", + "Content-Type" => "application/json", + ]; } public function failed($exception = null) diff --git a/config/ninja.php b/config/ninja.php index d152f711c57c..81179044c820 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -46,6 +46,7 @@ return [ 'preconfigured_install' => env('PRECONFIGURED_INSTALL', false), 'update_secret' => env('UPDATE_SECRET', ''), 'license_key' => env('LICENSE_KEY', false), + 'hosted_ninja_url' => env('HOSTED_NINJA_URL', 'https://invoicing.co'), // Settings used by invoiceninja.com 'disks' => [ 'backup' => env('BACKUP_DISK', 's3'), diff --git a/lang/en/texts.php b/lang/en/texts.php index 372bccf2f5e6..43f9083b172b 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -5324,6 +5324,7 @@ $lang = array( 'activity_142' => 'Quote :number Reminder 1 Sent', 'activity_143' => 'Auto Bill succeeded for Invoice :invoice', 'activity_144' => 'Auto Bill failed for Invoice :invoice. :notes', + 'activity_145' => 'EInvoice :invoice for :client was e-delivered. :notes', ); return $lang; diff --git a/routes/api.php b/routes/api.php index c0c02ceef096..64052728f120 100644 --- a/routes/api.php +++ b/routes/api.php @@ -216,7 +216,6 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale'] Route::get('credit/{invitation_key}/download', [CreditController::class, 'downloadPdf'])->name('credits.downloadPdf'); Route::get('credit/{invitation_key}/download_e_credit', [CreditController::class, 'downloadECredit'])->name('credits.downloadECredit'); - Route::resource('designs', DesignController::class); // name = (payments. index / create / show / update / destroy / edit Route::post('designs/bulk', [DesignController::class, 'bulk'])->name('designs.bulk'); Route::post('designs/set/default', [DesignController::class, 'default'])->name('designs.default');