Ingest .xml and attach to entity
This commit is contained in:
parent
cdddfa341e
commit
a3718170c7
|
|
@ -29,18 +29,39 @@ class InvoiceSyncCast implements CastsAttributes
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$is = new InvoiceSync();
|
$is = new InvoiceSync($data);
|
||||||
$is->qb_id = $data['qb_id'];
|
// $is->qb_id = $data['qb_id'];
|
||||||
|
// $is->email = $data['email'];
|
||||||
|
|
||||||
return $is;
|
return $is;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set($model, string $key, $value, array $attributes)
|
public function set($model, string $key, $value, array $attributes)
|
||||||
{
|
{
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
if(isset($value->qb_id) && strlen($value->qb_id) >= 1)
|
||||||
|
$data['qb_id'] = $value->qb_id;
|
||||||
|
|
||||||
|
if (isset($value->email) && $value->email !== null) {
|
||||||
|
|
||||||
|
$data['email'] = [
|
||||||
|
'body' => $value->email->body ?? '',
|
||||||
|
'subject' => $value->email->subject ?? '',
|
||||||
|
'template' => $value->email->template ?? '',
|
||||||
|
'entity' => $value->email->entity ?? '',
|
||||||
|
'entity_id' => $value->email->entity_id ?? '',
|
||||||
|
'cc_email' => $value->email->cc_email ?? '',
|
||||||
|
'action' => $value->email->action ?? '',
|
||||||
|
'ids' => $value->email->ids ?? '',
|
||||||
|
'type' => $value->email->email_type ?? '',
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
$key => json_encode([
|
$key => json_encode($data)
|
||||||
'qb_id' => $value->qb_id,
|
|
||||||
])
|
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,27 @@ class InvoiceSync implements Castable
|
||||||
{
|
{
|
||||||
public string $qb_id;
|
public string $qb_id;
|
||||||
|
|
||||||
|
public mixed $email;
|
||||||
|
|
||||||
public function __construct(array $attributes = [])
|
public function __construct(array $attributes = [])
|
||||||
{
|
{
|
||||||
|
|
||||||
$this->qb_id = $attributes['qb_id'] ?? '';
|
$this->qb_id = $attributes['qb_id'] ?? '';
|
||||||
|
$this->email = new \stdClass();
|
||||||
|
|
||||||
|
if(isset($attributes['email']))
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->email->body = $attributes['email']['body'] ?? '';
|
||||||
|
$this->email->subject = $attributes['email']['subject'] ?? '';
|
||||||
|
$this->email->template = $attributes['email']['template'] ?? '';
|
||||||
|
$this->email->entity = $attributes['email']['entity'] ?? '';
|
||||||
|
$this->email->entity_id = $attributes['email']['entity_id'] ?? '';
|
||||||
|
$this->email->cc_email = $attributes['email']['cc_email'] ?? '';
|
||||||
|
$this->email->action = $attributes['email']['action'] ?? '';
|
||||||
|
$this->email->ids = $attributes['email']['ids'] ?? [];
|
||||||
|
$this->email->email_type = $attributes['email']['type'] ?? '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\DataMapper\InvoiceSync;
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
|
|
@ -69,6 +70,28 @@ class EmailController extends BaseController
|
||||||
|
|
||||||
/** @var \App\Models\User $user */
|
/** @var \App\Models\User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
$company = $entity_obj->company;
|
||||||
|
|
||||||
|
//Only handle Peppol Invoices for now.
|
||||||
|
if($entity_obj instanceof Invoice && !isset($entity_obj->sync->email)){
|
||||||
|
// if($entity_obj instanceof Invoice && $company->isPeppolSender()){
|
||||||
|
|
||||||
|
$sync = $entity_obj->sync ?? new InvoiceSync();
|
||||||
|
$sync->email->body = strlen($body) > 3 ? $body : null;
|
||||||
|
$sync->email->subject = strlen($subject) > 3 ? $subject : null;
|
||||||
|
$sync->email->template = $request->input('template');
|
||||||
|
$sync->email->entity = $request->input('entity');
|
||||||
|
$sync->email->entity_id = $request->input('entity_id');
|
||||||
|
$sync->email->cc_email = $request->cc_email;
|
||||||
|
$entity_obj->sync = $sync;
|
||||||
|
$entity_obj->saveQuietly();
|
||||||
|
$entity_obj->service()->markSent()->save();
|
||||||
|
|
||||||
|
\App\Services\EDocument\Jobs\SendEDocument::dispatch(get_class($entity_obj), $entity_obj->id, $company->db);
|
||||||
|
|
||||||
|
nlog($sync);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->cc_email && (Ninja::isSelfHost() || $user->account->isPremium())) {
|
if ($request->cc_email && (Ninja::isSelfHost() || $user->account->isPremium())) {
|
||||||
|
|
||||||
|
|
@ -92,6 +115,19 @@ class EmailController extends BaseController
|
||||||
|
|
||||||
$entity_obj = $entity_obj->fresh();
|
$entity_obj = $entity_obj->fresh();
|
||||||
$entity_obj->last_sent_date = now();
|
$entity_obj->last_sent_date = now();
|
||||||
|
|
||||||
|
if(!empty($entity_obj->sync))
|
||||||
|
{
|
||||||
|
$sync = $entity_obj->sync;
|
||||||
|
if (empty($sync->qb_id)) {
|
||||||
|
$sync = null;
|
||||||
|
} else {
|
||||||
|
unset($sync->email);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entity_obj->sync = $sync;
|
||||||
|
}
|
||||||
|
|
||||||
$entity_obj->save();
|
$entity_obj->save();
|
||||||
|
|
||||||
/*Only notify the admin ONCE, not once per contact/invite*/
|
/*Only notify the admin ONCE, not once per contact/invite*/
|
||||||
|
|
@ -139,21 +175,7 @@ class EmailController extends BaseController
|
||||||
return $this->itemResponse($entity_obj->fresh());
|
return $this->itemResponse($entity_obj->fresh());
|
||||||
}
|
}
|
||||||
|
|
||||||
// private function sendPurchaseOrder($entity_obj, $data, $template)
|
private function resolveClass(string $entity): string
|
||||||
// {
|
|
||||||
// $this->entity_type = PurchaseOrder::class;
|
|
||||||
|
|
||||||
// $this->entity_transformer = PurchaseOrderTransformer::class;
|
|
||||||
|
|
||||||
// $data['template'] = $template;
|
|
||||||
|
|
||||||
// PurchaseOrderEmail::dispatch($entity_obj, $entity_obj->company, $data);
|
|
||||||
// $entity_obj->sendEvent(Webhook::EVENT_SENT_PURCHASE_ORDER, "vendor");
|
|
||||||
|
|
||||||
// return $this->itemResponse($entity_obj);
|
|
||||||
// }
|
|
||||||
|
|
||||||
private function resolveClass(string $entity): string
|
|
||||||
{
|
{
|
||||||
$class = '';
|
$class = '';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,13 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Utils\Ninja;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Libraries\MultiDB;
|
use App\Libraries\MultiDB;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use App\Utils\Traits\SavesDocuments;
|
||||||
use App\Jobs\Mailgun\ProcessMailgunWebhook;
|
use App\Jobs\Mailgun\ProcessMailgunWebhook;
|
||||||
|
use App\Http\Requests\Email\SendEmailRequest;
|
||||||
use App\Jobs\Mailgun\ProcessMailgunInboundWebhook;
|
use App\Jobs\Mailgun\ProcessMailgunInboundWebhook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -22,6 +25,8 @@ use App\Jobs\Mailgun\ProcessMailgunInboundWebhook;
|
||||||
*/
|
*/
|
||||||
class MailgunController extends BaseController
|
class MailgunController extends BaseController
|
||||||
{
|
{
|
||||||
|
use SavesDocuments;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -120,14 +125,68 @@ class MailgunController extends BaseController
|
||||||
{
|
{
|
||||||
$input = $request->all();
|
$input = $request->all();
|
||||||
|
|
||||||
|
|
||||||
|
$authorizedByHash = \hash_equals(\hash_hmac('sha256', $input['timestamp'] . $input['token'], config('services.mailgun.webhook_signing_key')), $input['signature']);
|
||||||
|
$authorizedByToken = $request->has('token') && $request->get('token') == config('ninja.inbound_mailbox.inbound_webhook_token');
|
||||||
|
if (!$authorizedByHash && !$authorizedByToken) {
|
||||||
|
return response()->json(['message' => 'Unauthorized'], 403);
|
||||||
|
}
|
||||||
|
|
||||||
nlog($input);
|
nlog($input);
|
||||||
if($input['recipient'] == config('ninja.storecove_email_catchall') && stripos('no-reply@mailer.storecove.com', $input['from']) !== false){
|
nlog("checks");
|
||||||
|
/** Peppol invoice xml ingest */
|
||||||
foreach ($request->files as $file) {
|
if(stripos($input['recipient'], "peppol_") !== false && stripos($input['from'], 'no-reply@mailer.storecove.com') !== false){
|
||||||
// Process each file
|
|
||||||
nlog($file);
|
$email_parts = explode("@", $input['recipient']);
|
||||||
|
nlog($email_parts);
|
||||||
|
|
||||||
|
$parts = explode("_", $email_parts[0]);
|
||||||
|
|
||||||
|
nlog($parts);
|
||||||
|
|
||||||
|
if(count($parts) != 4 && $parts[0] != 'peppol' && stripos('db-ninja-0', $parts[3]) !== false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$entity = ucfirst($parts[1]);
|
||||||
|
$entity_id = $parts[2];
|
||||||
|
$db = $parts[3];
|
||||||
|
|
||||||
|
MultiDB::setDB($db);
|
||||||
|
|
||||||
|
$class = "\\App\\Models\\".ucfirst(\Illuminate\Support\Str::camel($entity));
|
||||||
|
|
||||||
|
/** @var \App\Models\Invoice $entity */
|
||||||
|
$entity = $class::query()->withTrashed()->find($entity_id);
|
||||||
|
|
||||||
|
if(!$entity){
|
||||||
|
nlog("could not resolve entity for mailgun webhook");
|
||||||
|
nlog($input);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($request->files as $file) {
|
||||||
|
$this->saveDocuments($file, $entity, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(empty($entity->sync))
|
||||||
|
return; //just save the document, do not email it!
|
||||||
|
|
||||||
|
$sync = $entity->sync;
|
||||||
|
|
||||||
|
$request = new SendEmailRequest([
|
||||||
|
'entity' => $sync->email->entity,
|
||||||
|
'entity_id' => $entity->id,
|
||||||
|
'template' => $sync->email->template,
|
||||||
|
'subject' => $sync->email->subject,
|
||||||
|
'body' => $sync->email->body,
|
||||||
|
'cc_email' => $sync->email->cc_email,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$request->setUserResolver(fn () => $entity->user); // Or auth()->user()
|
||||||
|
|
||||||
|
app(\App\Http\Controllers\EmailController::class)->send($request);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!array_key_exists('sender', $input) || !array_key_exists('recipient', $input) || !array_key_exists('message-url', $input)) {
|
if (!array_key_exists('sender', $input) || !array_key_exists('recipient', $input) || !array_key_exists('message-url', $input)) {
|
||||||
|
|
@ -137,11 +196,7 @@ class MailgunController extends BaseController
|
||||||
|
|
||||||
// @turbo124 TODO: how to check for services.mailgun.webhook_signing_key on company level, when custom credentials are defined
|
// @turbo124 TODO: how to check for services.mailgun.webhook_signing_key on company level, when custom credentials are defined
|
||||||
// TODO: validation for client mail credentials by recipient
|
// TODO: validation for client mail credentials by recipient
|
||||||
$authorizedByHash = \hash_equals(\hash_hmac('sha256', $input['timestamp'] . $input['token'], config('services.mailgun.webhook_signing_key')), $input['signature']);
|
|
||||||
$authorizedByToken = $request->has('token') && $request->get('token') == config('ninja.inbound_mailbox.inbound_webhook_token');
|
|
||||||
if (!$authorizedByHash && !$authorizedByToken)
|
|
||||||
return response()->json(['message' => 'Unauthorized'], 403);
|
|
||||||
|
|
||||||
/** @var \App\Models\Company $company */
|
/** @var \App\Models\Company $company */
|
||||||
$company = MultiDB::findAndSetDbByExpenseMailbox($input["recipient"]);
|
$company = MultiDB::findAndSetDbByExpenseMailbox($input["recipient"]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ class SendEmailRequest extends Request
|
||||||
public function messages()
|
public function messages()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'template.in' => 'Template :input is anot a valid template.',
|
'template.in' => 'Template :input is not a valid template.',
|
||||||
'entity.in' => 'Entity :input is not a valid entity.'
|
'entity.in' => 'Entity :input is not a valid entity.'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -980,4 +980,9 @@ class Company extends BaseModel
|
||||||
return new CompanyService($this);
|
return new CompanyService($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isPeppolSender()
|
||||||
|
{
|
||||||
|
return Ninja::isHosted() && $this->account->isPaid() && $this->account->isEnterpriseClient() && $this->account->e_invoice_quota > 0 && $this->settings->e_invoice_type == 'PEPPOL' && $this->tax_data->acts_as_sender;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -630,7 +630,7 @@ class Mutator implements MutatorInterface
|
||||||
*/
|
*/
|
||||||
private function setEmailRouting(string $email): self
|
private function setEmailRouting(string $email): self
|
||||||
{
|
{
|
||||||
$email = "peppol@mail.invoicing.co";
|
$email = "peppol_invoice_{$this->invoice->id}_{$this->invoice->company->db}@mail.invoicing.co";
|
||||||
$meta = $this->getStorecoveMeta();
|
$meta = $this->getStorecoveMeta();
|
||||||
|
|
||||||
if(isset($meta['routing']['emails'])) {
|
if(isset($meta['routing']['emails'])) {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
@extends('portal.ninja2020.layout.clean')
|
@extends('portal.ninja2020.layout.clean')
|
||||||
@section('meta_title', ctrans('texts.login'))
|
@section('meta_title', ctrans('texts.login'))
|
||||||
|
|
||||||
|
@section('head')
|
||||||
|
|
||||||
@component('portal.ninja2020.components.test')
|
@component('portal.ninja2020.components.test')
|
||||||
<input type="hidden" id="test_email" value="{{ config('ninja.testvars.username') }}">
|
<input type="hidden" id="test_email" value="{{ config('ninja.testvars.username') }}">
|
||||||
<input type="hidden" id="test_password" value="{{ config('ninja.testvars.password') }}">
|
<input type="hidden" id="test_password" value="{{ config('ninja.testvars.password') }}">
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
<div class="grid lg:grid-cols-3 mx-6 md:mx-0">
|
<div class="grid lg:grid-cols-3 mx-6 md:mx-0">
|
||||||
@if($account && !$account->isPaid())
|
@if($account && !$account->isPaid())
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,8 @@
|
||||||
<title>@yield('meta_title', '')</title>
|
<title>@yield('meta_title', '')</title>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@yield('head')
|
||||||
|
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="description" content="@yield('meta_description')"/>
|
<meta name="description" content="@yield('meta_description')"/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue