mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
commit
3560f604b4
@ -1 +1 @@
|
|||||||
5.8.11
|
5.8.12
|
@ -229,7 +229,7 @@ class CompanySettings extends BaseSettings
|
|||||||
public $require_quote_signature = false; //@TODO ben to confirm
|
public $require_quote_signature = false; //@TODO ben to confirm
|
||||||
|
|
||||||
//email settings
|
//email settings
|
||||||
public $email_sending_method = 'default'; //enum 'default','gmail','office365' 'client_postmark', 'client_mailgun' //@implemented
|
public $email_sending_method = 'default'; //enum 'default','gmail','office365' 'client_postmark', 'client_mailgun', 'mailgun' //@implemented
|
||||||
|
|
||||||
public $gmail_sending_user_id = '0'; //@implemented
|
public $gmail_sending_user_id = '0'; //@implemented
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ class TaskExport extends BaseExport
|
|||||||
|
|
||||||
$this->storage_array = [];
|
$this->storage_array = [];
|
||||||
});
|
});
|
||||||
// nlog($this->storage_item_array);
|
|
||||||
return array_merge(['columns' => $header], $this->storage_item_array);
|
return array_merge(['columns' => $header], $this->storage_item_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,19 +139,11 @@ class TaskExport extends BaseExport
|
|||||||
} elseif (in_array($key, ['task.start_date', 'task.end_date', 'task.duration'])) {
|
} elseif (in_array($key, ['task.start_date', 'task.end_date', 'task.duration'])) {
|
||||||
$entity[$key] = '';
|
$entity[$key] = '';
|
||||||
} else {
|
} else {
|
||||||
// nlog($key);
|
|
||||||
$entity[$key] = $this->decorator->transform($key, $task);
|
$entity[$key] = $this->decorator->transform($key, $task);
|
||||||
// $entity[$key] = $this->resolveKey($key, $task, $this->entity_transformer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// $entity['task.start_date'] = '';
|
|
||||||
// $entity['task.end_date'] = '';
|
|
||||||
// $entity['task.duration'] = '';
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (is_null($task->time_log) || (is_array(json_decode($task->time_log, 1)) && count(json_decode($task->time_log, 1)) == 0)) {
|
if (is_null($task->time_log) || (is_array(json_decode($task->time_log, 1)) && count(json_decode($task->time_log, 1)) == 0)) {
|
||||||
$this->storage_array[] = $entity;
|
$this->storage_array[] = $entity;
|
||||||
} else {
|
} else {
|
||||||
@ -200,9 +192,9 @@ class TaskExport extends BaseExport
|
|||||||
|
|
||||||
$this->storage_array[] = $entity;
|
$this->storage_array[] = $entity;
|
||||||
|
|
||||||
unset($entity['task.start_date']);
|
$entity['task.start_date'] = '';
|
||||||
unset($entity['task.end_date']);
|
$entity['task.end_date'] = '';
|
||||||
unset($entity['task.duration']);
|
$entity['task.duration'] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,19 +32,19 @@ class HostedMigrationController extends Controller
|
|||||||
if(!$c || $c->is_disabled)
|
if(!$c || $c->is_disabled)
|
||||||
return response()->json(['message' => 'ok'], 200);
|
return response()->json(['message' => 'ok'], 200);
|
||||||
|
|
||||||
if(\App\Models\Invoice::query()->where('company_id', $c->id)->where('created_at', '>', now()->subMonths(2))->first())
|
// if(\App\Models\Invoice::query()->where('company_id', $c->id)->where('created_at', '>', now()->subMonths(2))->first())
|
||||||
return response()->json(['message' => 'New data exists, are you sure? Please log in here https://app.invoicing.co and delete the company if you really need to migrate again.'], 400);
|
// return response()->json(['message' => 'New data exists, are you sure? Please log in here https://app.invoicing.co and delete the company if you really need to migrate again.'], 400);
|
||||||
|
|
||||||
if(\App\Models\Client::query()->where('company_id', $c->id)->where('created_at', '>', now()->subMonths(2))->first())
|
// if(\App\Models\Client::query()->where('company_id', $c->id)->where('created_at', '>', now()->subMonths(2))->first())
|
||||||
return response()->json(['message' => 'New data exists, are you sure? Please log in here https://app.invoicing.co and delete the company if you really need to migrate again.'], 400);
|
// return response()->json(['message' => 'New data exists, are you sure? Please log in here https://app.invoicing.co and delete the company if you really need to migrate again.'], 400);
|
||||||
|
|
||||||
if(\App\Models\Quote::query()->where('company_id', $c->id)->where('created_at', '>', now()->subMonths(2)))
|
// if(\App\Models\Quote::query()->where('company_id', $c->id)->where('created_at', '>', now()->subMonths(2)))
|
||||||
return response()->json(['message' => 'New data exists, are you sure? Please log in here https://app.invoicing.co and delete the company if you really need to migrate again.'], 400);
|
// return response()->json(['message' => 'New data exists, are you sure? Please log in here https://app.invoicing.co and delete the company if you really need to migrate again.'], 400);
|
||||||
|
|
||||||
if(\App\Models\RecurringInvoice::query()->where('company_id', $c->id)->where('created_at', '>', now()->subMonths(2)))
|
// if(\App\Models\RecurringInvoice::query()->where('company_id', $c->id)->where('created_at', '>', now()->subMonths(2)))
|
||||||
return response()->json(['message' => 'New data exists, are you sure? Please log in here https://app.invoicing.co and delete the company if you really need to migrate again.'], 400);
|
// return response()->json(['message' => 'New data exists, are you sure? Please log in here https://app.invoicing.co and delete the company if you really need to migrate again.'], 400);
|
||||||
|
|
||||||
return response()->json(['message' => 'ok'], 200);
|
return response()->json(['message' => 'You have already activated this company on v5!!!!!! This migration may be a BAD idea. Contact us contact@invoiceninja.com to confirm this action.'], 400);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +408,7 @@ class InvoiceController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($invoice->isLocked()) {
|
if ($invoice->isLocked()) {
|
||||||
return response()->json(['message' => ctrans('texts.locked_invoice')], 403);
|
return response()->json(['message' => ctrans('texts.locked_invoice')], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
$old_invoice = $invoice->line_items;
|
$old_invoice = $invoice->line_items;
|
||||||
|
40
app/Http/Controllers/MailgunWebhookController.php
Normal file
40
app/Http/Controllers/MailgunWebhookController.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Jobs\Mailgun\ProcessMailgunWebhook;
|
||||||
|
use App\Jobs\PostMark\ProcessPostmarkWebhook;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MailgunWebhookController.
|
||||||
|
*/
|
||||||
|
class MailgunWebhookController extends BaseController
|
||||||
|
{
|
||||||
|
private $invitation;
|
||||||
|
|
||||||
|
public function __construct() {}
|
||||||
|
|
||||||
|
public function webhook(Request $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
$input = $request->all();
|
||||||
|
|
||||||
|
if (\abs(\time() - $request['signature']['timestamp']) > 15)
|
||||||
|
return response()->json(['message' => 'Success'], 200);
|
||||||
|
|
||||||
|
if(\hash_equals(\hash_hmac('sha256', $input['signature']['timestamp'] . $input['signature']['token'], config('services.mailgun.webhook_signing_key')), $input['signature']['signature']))
|
||||||
|
ProcessMailgunWebhook::dispatch($request->all())->delay(10);
|
||||||
|
|
||||||
|
return response()->json(['message' => 'Success.'], 200);
|
||||||
|
}
|
||||||
|
}
|
@ -57,7 +57,7 @@ class UpdateInvoiceRequest extends Request
|
|||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->file_validation;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['id'] = new LockedInvoiceRule($this->invoice);
|
// $rules['id'] = new LockedInvoiceRule($this->invoice);
|
||||||
|
|
||||||
$rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('invoices')->where('company_id', $user->company()->id)->ignore($this->invoice->id)];
|
$rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('invoices')->where('company_id', $user->company()->id)->ignore($this->invoice->id)];
|
||||||
|
|
||||||
|
@ -117,6 +117,14 @@ class Wave extends BaseImport implements ImportInterface
|
|||||||
|
|
||||||
$this->transformer = new InvoiceTransformer($this->company);
|
$this->transformer = new InvoiceTransformer($this->company);
|
||||||
|
|
||||||
|
foreach($data as $key => $invoice)
|
||||||
|
{
|
||||||
|
if(!isset($invoice['Invoice Number']) || empty($invoice['Invoice Number']))
|
||||||
|
{
|
||||||
|
unset($data[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$invoice_count = $this->ingestInvoices($data, 'Invoice Number');
|
$invoice_count = $this->ingestInvoices($data, 'Invoice Number');
|
||||||
|
|
||||||
$this->entity_count['invoices'] = $invoice_count;
|
$this->entity_count['invoices'] = $invoice_count;
|
||||||
|
@ -258,6 +258,11 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
switch ($this->nmo->settings->email_sending_method) {
|
switch ($this->nmo->settings->email_sending_method) {
|
||||||
case 'default':
|
case 'default':
|
||||||
$this->mailer = config('mail.default');
|
$this->mailer = config('mail.default');
|
||||||
|
// $this->setHostedMailgunMailer(); //should only be activated if hosted platform needs to fall back to mailgun
|
||||||
|
break;
|
||||||
|
case 'mailgun':
|
||||||
|
$this->mailer = 'mailgun';
|
||||||
|
$this->setHostedMailgunMailer();
|
||||||
break;
|
break;
|
||||||
case 'gmail':
|
case 'gmail':
|
||||||
$this->mailer = 'gmail';
|
$this->mailer = 'gmail';
|
||||||
@ -365,6 +370,21 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function setHostedMailgunMailer()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (property_exists($this->nmo->settings, 'email_from_name') && strlen($this->nmo->settings->email_from_name) > 1) {
|
||||||
|
$email_from_name = $this->nmo->settings->email_from_name;
|
||||||
|
} else {
|
||||||
|
$email_from_name = $this->company->present()->name();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->nmo
|
||||||
|
->mailable
|
||||||
|
->from(config('services.mailgun.from.address'), $email_from_name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures Mailgun using client supplied secret
|
* Configures Mailgun using client supplied secret
|
||||||
* as the Mailer
|
* as the Mailer
|
||||||
|
527
app/Jobs/Mailgun/ProcessMailgunWebhook.php
Normal file
527
app/Jobs/Mailgun/ProcessMailgunWebhook.php
Normal file
@ -0,0 +1,527 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Jobs\Mailgun;
|
||||||
|
|
||||||
|
use App\Utils\Ninja;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\SystemLog;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use App\Jobs\Util\SystemLogger;
|
||||||
|
use App\Models\QuoteInvitation;
|
||||||
|
use App\Models\CreditInvitation;
|
||||||
|
use App\Models\InvoiceInvitation;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Turbo124\Beacon\Facades\LightLogs;
|
||||||
|
use App\Models\PurchaseOrderInvitation;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use App\Models\RecurringInvoiceInvitation;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use App\DataMapper\Analytics\Mail\EmailSpam;
|
||||||
|
use App\DataMapper\Analytics\Mail\EmailBounce;
|
||||||
|
use App\Notifications\Ninja\EmailSpamNotification;
|
||||||
|
use App\Notifications\Ninja\EmailBounceNotification;
|
||||||
|
|
||||||
|
class ProcessMailgunWebhook implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $tries = 1;
|
||||||
|
|
||||||
|
public $invitation;
|
||||||
|
|
||||||
|
private $entity;
|
||||||
|
|
||||||
|
private string $message_id = '';
|
||||||
|
|
||||||
|
private array $default_response = [
|
||||||
|
'recipients' => '',
|
||||||
|
'subject' => 'Message not found.',
|
||||||
|
'entity' => '',
|
||||||
|
'entity_id' => '',
|
||||||
|
'events' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct(private array $request)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSystemLog(string $message_id): ?SystemLog
|
||||||
|
{
|
||||||
|
return SystemLog::query()
|
||||||
|
->where('company_id', $this->invitation->company_id)
|
||||||
|
->where('type_id', SystemLog::TYPE_WEBHOOK_RESPONSE)
|
||||||
|
->whereJsonContains('log', ['MessageID' => $this->message_id])
|
||||||
|
->orderBy('id', 'desc')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateSystemLog(SystemLog $system_log, array $data): void
|
||||||
|
{
|
||||||
|
$system_log->log = $data;
|
||||||
|
$system_log->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
nlog($this->request);
|
||||||
|
|
||||||
|
if(!$this->request['event-data']['tags'][0])
|
||||||
|
return;
|
||||||
|
|
||||||
|
MultiDB::findAndSetDbByCompanyKey($this->request['event-data']['tags'][0]);
|
||||||
|
$company = Company::where('company_key', $this->request['event-data']['tags'][0])->first();
|
||||||
|
|
||||||
|
if ($company && $this->request['event-data']['event'] == 'complained' && config('ninja.notification.slack')) {
|
||||||
|
$company->notification(new EmailSpamNotification($company))->ninja();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->message_id = $this->request['event-data']['message']['headers']['message-id'];
|
||||||
|
|
||||||
|
$this->request['MessageID'] = $this->message_id;
|
||||||
|
|
||||||
|
$this->invitation = $this->discoverInvitation($this->message_id);
|
||||||
|
|
||||||
|
if (!$this->invitation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->request['event-details']['delivery-status']['message'])) {
|
||||||
|
$this->invitation->email_error = $this->request['event-details']['delivery-status']['message'];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($this->request['event-data']['event']) {
|
||||||
|
case 'delivered':
|
||||||
|
return $this->processDelivery();
|
||||||
|
case 'failed':
|
||||||
|
return $this->processBounce();
|
||||||
|
case 'complained':
|
||||||
|
return $this->processSpamComplaint();
|
||||||
|
case 'opened':
|
||||||
|
return $this->processOpen();
|
||||||
|
default:
|
||||||
|
# code...
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"signature": {
|
||||||
|
"token": "7f388cf8096aa0bca1477aee9d91e156c61f8fa8282c7f1c0c",
|
||||||
|
"timestamp": "1705376308",
|
||||||
|
"signature": "a22b7c3dd4861e27a1664cef3611a1954c0665cfcaca9b8f35ee216243a4ce3f"
|
||||||
|
},
|
||||||
|
"event-data": {
|
||||||
|
"id": "Ase7i2zsRYeDXztHGENqRA",
|
||||||
|
"timestamp": 1521243339.873676,
|
||||||
|
"log-level": "info",
|
||||||
|
"event": "opened",
|
||||||
|
"message": {
|
||||||
|
"headers": {
|
||||||
|
"message-id": "20130503182626.18666.16540@mail.invoicing.co"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recipient": "alice@example.com",
|
||||||
|
"recipient-domain": "example.com",
|
||||||
|
"ip": "50.56.129.169",
|
||||||
|
"geolocation": {
|
||||||
|
"country": "US",
|
||||||
|
"region": "CA",
|
||||||
|
"city": "San Francisco"
|
||||||
|
},
|
||||||
|
"client-info": {
|
||||||
|
"client-os": "Linux",
|
||||||
|
"device-type": "desktop",
|
||||||
|
"client-name": "Chrome",
|
||||||
|
"client-type": "browser",
|
||||||
|
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31"
|
||||||
|
},
|
||||||
|
"campaigns": [],
|
||||||
|
"tags": [
|
||||||
|
"my_tag_1",
|
||||||
|
"my_tag_2"
|
||||||
|
],
|
||||||
|
"user-variables": {
|
||||||
|
"my_var_1": "Mailgun Variable #1",
|
||||||
|
"my-var-2": "awesome"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
private function processOpen()
|
||||||
|
{
|
||||||
|
$this->invitation->opened_date = now();
|
||||||
|
$this->invitation->save();
|
||||||
|
|
||||||
|
$sl = $this->getSystemLog($this->request['MessageID']);
|
||||||
|
|
||||||
|
/** Prevents Gmail tracking from firing inappropriately */
|
||||||
|
if($this->request['signature']['timestamp'] < $sl->log['signature']['timestamp'] + 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$event = [
|
||||||
|
'bounce_id' => '',
|
||||||
|
'recipient' => $this->request['event-data']['recipient'] ?? '',
|
||||||
|
'status' => $this->request['event-data']['event'] ?? '',
|
||||||
|
'delivery_message' => collect($this->request['event-data']['client-info'])->implode(" ") ?? '',
|
||||||
|
'server' => collect($this->request['event-data']['geolocation'])->implode(" - ") ?? '',
|
||||||
|
'server_ip' => $this->request['event-data']['ip'] ?? '',
|
||||||
|
'date' => \Carbon\Carbon::parse($this->request['event-data']['timestamp'])->format('Y-m-d H:i:s') ?? '',
|
||||||
|
];
|
||||||
|
|
||||||
|
if($sl) {
|
||||||
|
$data = $sl->log;
|
||||||
|
$data['history']['events'][] = $event;
|
||||||
|
$this->updateSystemLog($sl, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"signature": {
|
||||||
|
"token": "70b91a64ed0f1bdf90fb9c6ea7e3c31d5792a3d0945ffc20fe",
|
||||||
|
"timestamp": "1705376276",
|
||||||
|
"signature": "ba96f841fc236e1bf5840b02fad512d0bd15b0731b5e6b154764c7a05f7ee999"
|
||||||
|
},
|
||||||
|
"event-data": {
|
||||||
|
"id": "CPgfbmQMTCKtHW6uIWtuVe",
|
||||||
|
"timestamp": 1521472262.908181,
|
||||||
|
"log-level": "info",
|
||||||
|
"event": "delivered",
|
||||||
|
"delivery-status": {
|
||||||
|
"tls": true,
|
||||||
|
"mx-host": "smtp-in.example.com",
|
||||||
|
"code": 250,
|
||||||
|
"description": "",
|
||||||
|
"session-seconds": 0.4331989288330078,
|
||||||
|
"utf8": true,
|
||||||
|
"attempt-no": 1,
|
||||||
|
"message": "OK",
|
||||||
|
"certificate-verified": true
|
||||||
|
},
|
||||||
|
"flags": {
|
||||||
|
"is-routed": false,
|
||||||
|
"is-authenticated": true,
|
||||||
|
"is-system-test": false,
|
||||||
|
"is-test-mode": false
|
||||||
|
},
|
||||||
|
"envelope": {
|
||||||
|
"transport": "smtp",
|
||||||
|
"sender": "bob@mail.invoicing.co",
|
||||||
|
"sending-ip": "209.61.154.250",
|
||||||
|
"targets": "alice@example.com"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"headers": {
|
||||||
|
"to": "Alice <alice@example.com>",
|
||||||
|
"message-id": "20130503182626.18666.16540@mail.invoicing.co",
|
||||||
|
"from": "Bob <bob@mail.invoicing.co>",
|
||||||
|
"subject": "Test delivered webhook"
|
||||||
|
},
|
||||||
|
"attachments": [],
|
||||||
|
"size": 111
|
||||||
|
},
|
||||||
|
"recipient": "alice@example.com",
|
||||||
|
"recipient-domain": "example.com",
|
||||||
|
"storage": {
|
||||||
|
"url": "https://se.api.mailgun.net/v3/domains/mail.invoicing.co/messages/message_key",
|
||||||
|
"key": "message_key"
|
||||||
|
},
|
||||||
|
"campaigns": [],
|
||||||
|
"tags": [
|
||||||
|
"my_tag_1",
|
||||||
|
"my_tag_2"
|
||||||
|
],
|
||||||
|
"user-variables": {
|
||||||
|
"my_var_1": "Mailgun Variable #1",
|
||||||
|
"my-var-2": "awesome"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
private function processDelivery()
|
||||||
|
{
|
||||||
|
$this->invitation->email_status = 'delivered';
|
||||||
|
$this->invitation->save();
|
||||||
|
|
||||||
|
$sl = $this->getSystemLog($this->request['MessageID']);
|
||||||
|
|
||||||
|
if($sl) {
|
||||||
|
$data = $sl->log;
|
||||||
|
$data['history']['events'][] = $this->getEvent();
|
||||||
|
$this->updateSystemLog($sl, $data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
|
||||||
|
|
||||||
|
SystemLogger::dispatch(
|
||||||
|
$data,
|
||||||
|
SystemLog::CATEGORY_MAIL,
|
||||||
|
SystemLog::EVENT_MAIL_DELIVERY,
|
||||||
|
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
||||||
|
$this->invitation->contact->client,
|
||||||
|
$this->invitation->company
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"signature": {
|
||||||
|
"token": "7494a9089874cda8c478ba7608d15158229d5b8de41ddfdae8",
|
||||||
|
"timestamp": "1705376357",
|
||||||
|
"signature": "a8ba107ac919626526b76e46e43ba40e629833fafab8728d402f28476bad0c7b"
|
||||||
|
},
|
||||||
|
"event-data": {
|
||||||
|
"id": "G9Bn5sl1TC6nu79C8C0bwg",
|
||||||
|
"timestamp": 1521233195.375624,
|
||||||
|
"log-level": "error",
|
||||||
|
"event": "failed",
|
||||||
|
"severity": "permanent",
|
||||||
|
"reason": "suppress-bounce",
|
||||||
|
"delivery-status": {
|
||||||
|
"attempt-no": 1,
|
||||||
|
"message": "",
|
||||||
|
"code": 605,
|
||||||
|
"enhanced-code": "",
|
||||||
|
"description": "Not delivering to previously bounced address",
|
||||||
|
"session-seconds": 0
|
||||||
|
},
|
||||||
|
"flags": {
|
||||||
|
"is-routed": false,
|
||||||
|
"is-authenticated": true,
|
||||||
|
"is-system-test": false,
|
||||||
|
"is-test-mode": false
|
||||||
|
},
|
||||||
|
"envelope": {
|
||||||
|
"sender": "bob@mail.invoicing.co",
|
||||||
|
"transport": "smtp",
|
||||||
|
"targets": "alice@example.com"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"headers": {
|
||||||
|
"to": "Alice <alice@example.com>",
|
||||||
|
"message-id": "20130503192659.13651.20287@mail.invoicing.co",
|
||||||
|
"from": "Bob <bob@mail.invoicing.co>",
|
||||||
|
"subject": "Test permanent_fail webhook"
|
||||||
|
},
|
||||||
|
"attachments": [],
|
||||||
|
"size": 111
|
||||||
|
},
|
||||||
|
"recipient": "alice@example.com",
|
||||||
|
"recipient-domain": "example.com",
|
||||||
|
"storage": {
|
||||||
|
"url": "https://se.api.mailgun.net/v3/domains/mail.invoicing.co/messages/message_key",
|
||||||
|
"key": "message_key"
|
||||||
|
},
|
||||||
|
"campaigns": [],
|
||||||
|
"tags": [
|
||||||
|
"my_tag_1",
|
||||||
|
"my_tag_2"
|
||||||
|
],
|
||||||
|
"user-variables": {
|
||||||
|
"my_var_1": "Mailgun Variable #1",
|
||||||
|
"my-var-2": "awesome"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
private function processBounce()
|
||||||
|
{
|
||||||
|
$this->invitation->email_status = 'bounced';
|
||||||
|
$this->invitation->save();
|
||||||
|
|
||||||
|
$bounce = new EmailBounce(
|
||||||
|
$this->request['event-data']['tags'][0],
|
||||||
|
$this->request['event-data']['envelope']['sender'],
|
||||||
|
$this->message_id
|
||||||
|
);
|
||||||
|
|
||||||
|
LightLogs::create($bounce)->queue();
|
||||||
|
|
||||||
|
$sl = $this->getSystemLog($this->message_id);
|
||||||
|
|
||||||
|
$event = [
|
||||||
|
'bounce_id' => $this->request['event-data']['id'],
|
||||||
|
'recipient' => $this->request['event-data']['recipient'] ?? '',
|
||||||
|
'status' => $this->request['event-data']['event'] ?? '',
|
||||||
|
'delivery_message' => $this->request['event-data']['delivery-status']['description'] ?? $this->request['event-data']['delivery-status']['message'] ?? '',
|
||||||
|
'server' => $this->request['event-data']['delivery-status']['mx-host'] ?? '',
|
||||||
|
'server_ip' => $this->request['event-data']['envelope']['sending-ip'] ?? '',
|
||||||
|
'date' => \Carbon\Carbon::parse($this->request['event-data']['timestamp'])->format('Y-m-d H:i:s') ?? '',
|
||||||
|
];
|
||||||
|
|
||||||
|
if($sl) {
|
||||||
|
$data = $sl->log;
|
||||||
|
$data['history']['events'][] = $event;
|
||||||
|
$this->updateSystemLog($sl, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"signature": {
|
||||||
|
"token": "d7be371deef49c8b187119df295e3eb17fd1974d513a4be2cb",
|
||||||
|
"timestamp": "1705376380",
|
||||||
|
"signature": "52f31c75b492d67be906423279e0effe563e28790ee65ba23a1b30006df649df"
|
||||||
|
},
|
||||||
|
"event-data": {
|
||||||
|
"id": "-Agny091SquKnsrW2NEKUA",
|
||||||
|
"timestamp": 1521233123.501324,
|
||||||
|
"log-level": "warn",
|
||||||
|
"event": "complained",
|
||||||
|
"envelope": {
|
||||||
|
"sending-ip": "173.193.210.33"
|
||||||
|
},
|
||||||
|
"flags": {
|
||||||
|
"is-test-mode": false
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"headers": {
|
||||||
|
"to": "Alice <alice@example.com>",
|
||||||
|
"message-id": "20110215055645.25246.63817@mail.invoicing.co",
|
||||||
|
"from": "Bob <bob@mail.invoicing.co>",
|
||||||
|
"subject": "Test complained webhook"
|
||||||
|
},
|
||||||
|
"attachments": [],
|
||||||
|
"size": 111
|
||||||
|
},
|
||||||
|
"recipient": "alice@example.com",
|
||||||
|
"campaigns": [],
|
||||||
|
"tags": [
|
||||||
|
"my_tag_1",
|
||||||
|
"my_tag_2"
|
||||||
|
],
|
||||||
|
"user-variables": {
|
||||||
|
"my_var_1": "Mailgun Variable #1",
|
||||||
|
"my-var-2": "awesome"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
private function processSpamComplaint()
|
||||||
|
{
|
||||||
|
$this->invitation->email_status = 'spam';
|
||||||
|
$this->invitation->save();
|
||||||
|
|
||||||
|
$spam = new EmailSpam(
|
||||||
|
$this->request['event-data']['tags'][0],
|
||||||
|
$this->request['event-data']['message']['headers']['from'],
|
||||||
|
$this->message_id
|
||||||
|
);
|
||||||
|
|
||||||
|
LightLogs::create($spam)->queue();
|
||||||
|
|
||||||
|
$sl = $this->getSystemLog($this->message_id);
|
||||||
|
|
||||||
|
$event = [
|
||||||
|
'bounce_id' => '',
|
||||||
|
'recipient' => $this->request['event-data']['recipient'] ?? '',
|
||||||
|
'status' => $this->request['event-data']['event'] ?? '',
|
||||||
|
'delivery_message' => 'Spam Complaint',
|
||||||
|
'server' => '',
|
||||||
|
'server_ip' => $this->request['event-data']['envelope']['sending-ip'] ?? '',
|
||||||
|
'date' => \Carbon\Carbon::parse($this->request['event-data']['timestamp'])->format('Y-m-d H:i:s') ?? '',
|
||||||
|
];
|
||||||
|
|
||||||
|
if($sl) {
|
||||||
|
$data = $sl->log;
|
||||||
|
$data['history']['events'][] = $event;
|
||||||
|
$this->updateSystemLog($sl, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function discoverInvitation($message_id)
|
||||||
|
{
|
||||||
|
$invitation = false;
|
||||||
|
|
||||||
|
if ($invitation = InvoiceInvitation::where('message_id', $message_id)->first()) {
|
||||||
|
$this->entity = 'invoice';
|
||||||
|
return $invitation;
|
||||||
|
} elseif ($invitation = QuoteInvitation::where('message_id', $message_id)->first()) {
|
||||||
|
$this->entity = 'quote';
|
||||||
|
return $invitation;
|
||||||
|
} elseif ($invitation = RecurringInvoiceInvitation::where('message_id', $message_id)->first()) {
|
||||||
|
$this->entity = 'recurring_invoice';
|
||||||
|
return $invitation;
|
||||||
|
} elseif ($invitation = CreditInvitation::where('message_id', $message_id)->first()) {
|
||||||
|
$this->entity = 'credit';
|
||||||
|
return $invitation;
|
||||||
|
} elseif ($invitation = PurchaseOrderInvitation::where('message_id', $message_id)->first()) {
|
||||||
|
$this->entity = 'purchase_order';
|
||||||
|
return $invitation;
|
||||||
|
} else {
|
||||||
|
return $invitation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fetchMessage(): array
|
||||||
|
{
|
||||||
|
if(strlen($this->message_id) < 2) {
|
||||||
|
return $this->default_response;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
$recipients = $this->request['event-data']['recipient'] ?? '';
|
||||||
|
$subject = $this->request['event-data']['message']['headers']['subject'] ?? '';
|
||||||
|
|
||||||
|
return [
|
||||||
|
'recipients' => $recipients,
|
||||||
|
'subject' => $subject,
|
||||||
|
'entity' => $this->entity ?? '',
|
||||||
|
'entity_id' => $this->invitation->{$this->entity}->hashed_id ?? '',
|
||||||
|
'events' => [$this->getEvent()],
|
||||||
|
];
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
|
||||||
|
return $this->default_response;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getEvent(): array
|
||||||
|
{
|
||||||
|
$recipients = $this->request['event-data']['recipient'] ?? '';
|
||||||
|
|
||||||
|
return [
|
||||||
|
'bounce_id' => '',
|
||||||
|
'recipient' => $recipients,
|
||||||
|
'status' => $this->request['event-data']['event'] ?? '',
|
||||||
|
'delivery_message' => $this->request['event-details']['delivery-status']['description'] ?? $this->request['event-details']['delivery-status']['message'] ?? '',
|
||||||
|
'server' => $this->request['event-data']['recipient-domain'] ?? '',
|
||||||
|
'server_ip' => $this->request['event-data']['envelope']['sending-ip'] ?? '',
|
||||||
|
'date' => \Carbon\Carbon::parse($this->request['event-data']['timestamp'])->format('Y-m-d H:i:s') ?? '',
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -61,7 +61,7 @@ class MailSentListener implements ShouldQueue
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$invitation->message_id = $message_id;
|
$invitation->message_id = str_replace(["<",">"], "", $message_id);
|
||||||
$invitation->save();
|
$invitation->save();
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@ -76,18 +76,14 @@ class MailSentListener implements ShouldQueue
|
|||||||
|
|
||||||
foreach (MultiDB::$dbs as $db) {
|
foreach (MultiDB::$dbs as $db) {
|
||||||
if ($invitation = InvoiceInvitation::on($db)->where('key', $key)->first()) {
|
if ($invitation = InvoiceInvitation::on($db)->where('key', $key)->first()) {
|
||||||
// $invitation->invoice->sendEvent(Webhook::EVENT_SENT_INVOICE, "client");
|
|
||||||
return $invitation;
|
return $invitation;
|
||||||
} elseif ($invitation = QuoteInvitation::on($db)->where('key', $key)->first()) {
|
} elseif ($invitation = QuoteInvitation::on($db)->where('key', $key)->first()) {
|
||||||
// $invitation->quote->sendEvent(Webhook::EVENT_SENT_QUOTE, "client");
|
|
||||||
return $invitation;
|
return $invitation;
|
||||||
} elseif ($invitation = RecurringInvoiceInvitation::on($db)->where('key', $key)->first()) {
|
} elseif ($invitation = RecurringInvoiceInvitation::on($db)->where('key', $key)->first()) {
|
||||||
return $invitation;
|
return $invitation;
|
||||||
} elseif ($invitation = CreditInvitation::on($db)->where('key', $key)->first()) {
|
} elseif ($invitation = CreditInvitation::on($db)->where('key', $key)->first()) {
|
||||||
// $invitation->credit->sendEvent(Webhook::EVENT_SENT_CREDIT, "client");
|
|
||||||
return $invitation;
|
return $invitation;
|
||||||
} elseif ($invitation = PurchaseOrderInvitation::on($db)->where('key', $key)->first()) {
|
} elseif ($invitation = PurchaseOrderInvitation::on($db)->where('key', $key)->first()) {
|
||||||
// $invitation->purchase_order->sendEvent(Webhook::EVENT_SENT_PURCHASE_ORDER, "vendor");
|
|
||||||
return $invitation;
|
return $invitation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -431,7 +431,7 @@ class Company extends BaseModel
|
|||||||
|
|
||||||
public function bank_integrations(): HasMany
|
public function bank_integrations(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(BankIntegration::class);
|
return $this->hasMany(BankIntegration::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function bank_transactions(): HasMany
|
public function bank_transactions(): HasMany
|
||||||
|
@ -48,7 +48,7 @@ class ExpenseRepository extends BaseRepository
|
|||||||
|
|
||||||
if(isset($data['payment_date']) && $data['payment_date'] == $expense->payment_date) {
|
if(isset($data['payment_date']) && $data['payment_date'] == $expense->payment_date) {
|
||||||
//do nothing
|
//do nothing
|
||||||
} elseif(isset($data['payment_date']) && strlen($data['payment_date']) > 1 && $user->company()->notify_vendor_when_paid && ($data['vendor_id'] || $expense->vendor_id)) {
|
} elseif(isset($data['payment_date']) && strlen($data['payment_date']) > 1 && $user->company()->notify_vendor_when_paid && (isset($data['vendor_id']) || $expense->vendor_id)) {
|
||||||
nlog("ping");
|
nlog("ping");
|
||||||
$this->notify_vendor = true;
|
$this->notify_vendor = true;
|
||||||
}
|
}
|
||||||
|
@ -463,6 +463,21 @@ class Email implements ShouldQueue
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function setHostedMailgunMailer()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (property_exists($this->email_object->settings, 'email_from_name') && strlen($this->email_object->settings->email_from_name) > 1) {
|
||||||
|
$email_from_name = $this->email_object->settings->email_from_name;
|
||||||
|
} else {
|
||||||
|
$email_from_name = $this->company->present()->name();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->mailable
|
||||||
|
->from(config('services.mailgun.from.address'), $email_from_name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the mail driver to use and applies any specific configuration
|
* Sets the mail driver to use and applies any specific configuration
|
||||||
* the the mailable
|
* the the mailable
|
||||||
@ -472,6 +487,11 @@ class Email implements ShouldQueue
|
|||||||
switch ($this->email_object->settings->email_sending_method) {
|
switch ($this->email_object->settings->email_sending_method) {
|
||||||
case 'default':
|
case 'default':
|
||||||
$this->mailer = config('mail.default');
|
$this->mailer = config('mail.default');
|
||||||
|
// $this->setHostedMailgunMailer(); //should only be activated if hosted platform needs to fall back to mailgun
|
||||||
|
break;
|
||||||
|
case 'mailgun':
|
||||||
|
$this->mailer = 'mailgun';
|
||||||
|
$this->setHostedMailgunMailer();
|
||||||
break;
|
break;
|
||||||
case 'gmail':
|
case 'gmail':
|
||||||
$this->mailer = 'gmail';
|
$this->mailer = 'gmail';
|
||||||
|
@ -17,8 +17,8 @@ return [
|
|||||||
'require_https' => env('REQUIRE_HTTPS', true),
|
'require_https' => env('REQUIRE_HTTPS', true),
|
||||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||||
'app_version' => env('APP_VERSION', '5.8.11'),
|
'app_version' => env('APP_VERSION', '5.8.12'),
|
||||||
'app_tag' => env('APP_TAG', '5.8.11'),
|
'app_tag' => env('APP_TAG', '5.8.12'),
|
||||||
'minimum_client_version' => '5.0.16',
|
'minimum_client_version' => '5.0.16',
|
||||||
'terms_version' => '1.0.1',
|
'terms_version' => '1.0.1',
|
||||||
'api_secret' => env('API_SECRET', false),
|
'api_secret' => env('API_SECRET', false),
|
||||||
|
@ -22,7 +22,12 @@ return [
|
|||||||
'domain' => env('MAILGUN_DOMAIN', ''),
|
'domain' => env('MAILGUN_DOMAIN', ''),
|
||||||
'secret' => env('MAILGUN_SECRET', ''),
|
'secret' => env('MAILGUN_SECRET', ''),
|
||||||
'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
|
'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
|
||||||
|
'webhook_signing_key' => env('MAILGUN_WEBHOOK_SIGNING_KEY', ''),
|
||||||
'scheme' => 'https',
|
'scheme' => 'https',
|
||||||
|
'from' => [
|
||||||
|
'address' => env('MAILGUN_FROM_ADDRESS', ''),
|
||||||
|
'name' => env('MAILGUN_FROM_NAME', ''),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
'postmark' => [
|
'postmark' => [
|
||||||
|
13110
openapi/api-docs.yaml
13110
openapi/api-docs.yaml
File diff suppressed because it is too large
Load Diff
@ -36,7 +36,7 @@
|
|||||||
description: 'The currency id of the related invoice'
|
description: 'The currency id of the related invoice'
|
||||||
type: string
|
type: string
|
||||||
example: '1'
|
example: '1'
|
||||||
expense_currency_id:
|
currency_id:
|
||||||
description: 'The currency id of the expense'
|
description: 'The currency id of the expense'
|
||||||
type: string
|
type: string
|
||||||
example: '2'
|
example: '2'
|
||||||
|
@ -47,6 +47,7 @@ use App\Http\Controllers\InAppPurchase\AppleController;
|
|||||||
use App\Http\Controllers\InvoiceController;
|
use App\Http\Controllers\InvoiceController;
|
||||||
use App\Http\Controllers\LicenseController;
|
use App\Http\Controllers\LicenseController;
|
||||||
use App\Http\Controllers\LogoutController;
|
use App\Http\Controllers\LogoutController;
|
||||||
|
use App\Http\Controllers\MailgunWebhookController;
|
||||||
use App\Http\Controllers\MigrationController;
|
use App\Http\Controllers\MigrationController;
|
||||||
use App\Http\Controllers\OneTimeTokenController;
|
use App\Http\Controllers\OneTimeTokenController;
|
||||||
use App\Http\Controllers\PaymentController;
|
use App\Http\Controllers\PaymentController;
|
||||||
@ -417,7 +418,9 @@ Route::match(['get', 'post'], 'payment_notification_webhook/{company_key}/{compa
|
|||||||
->middleware('throttle:1000,1')
|
->middleware('throttle:1000,1')
|
||||||
->name('payment_notification_webhook');
|
->name('payment_notification_webhook');
|
||||||
|
|
||||||
|
|
||||||
Route::post('api/v1/postmark_webhook', [PostMarkController::class, 'webhook'])->middleware('throttle:1000,1');
|
Route::post('api/v1/postmark_webhook', [PostMarkController::class, 'webhook'])->middleware('throttle:1000,1');
|
||||||
|
Route::post('api/v1/mailgun_webhook', [MailgunWebhookController::class, 'webhook'])->middleware('throttle:1000,1');
|
||||||
Route::get('token_hash_router', [OneTimeTokenController::class, 'router'])->middleware('throttle:500,1');
|
Route::get('token_hash_router', [OneTimeTokenController::class, 'router'])->middleware('throttle:500,1');
|
||||||
Route::get('webcron', [WebCronController::class, 'index'])->middleware('throttle:100,1');
|
Route::get('webcron', [WebCronController::class, 'index'])->middleware('throttle:100,1');
|
||||||
Route::post('api/v1/get_migration_account', [HostedMigrationController::class, 'getAccount'])->middleware('guest')->middleware('throttle:100,1');
|
Route::post('api/v1/get_migration_account', [HostedMigrationController::class, 'getAccount'])->middleware('guest')->middleware('throttle:100,1');
|
||||||
|
@ -52,73 +52,73 @@ class CheckLockedInvoiceValidationTest extends TestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testValidationFailsForLockedInvoiceWhenSent()
|
// public function testValidationFailsForLockedInvoiceWhenSent()
|
||||||
{
|
// {
|
||||||
$this->company->settings->lock_invoices = 'when_sent';
|
// $this->company->settings->lock_invoices = 'when_sent';
|
||||||
$this->company->save();
|
// $this->company->save();
|
||||||
|
|
||||||
$settings = $this->client->settings;
|
// $settings = $this->client->settings;
|
||||||
$settings->lock_invoices = 'when_sent';
|
// $settings->lock_invoices = 'when_sent';
|
||||||
$this->client->settings = $settings;
|
// $this->client->settings = $settings;
|
||||||
$this->client->save();
|
// $this->client->save();
|
||||||
|
|
||||||
$this->invoice = $this->invoice->service()->markSent()->save();
|
// $this->invoice = $this->invoice->service()->markSent()->save();
|
||||||
|
|
||||||
$invoice_update = [
|
// $invoice_update = [
|
||||||
'po_number' => 'test',
|
// 'po_number' => 'test',
|
||||||
];
|
// ];
|
||||||
|
|
||||||
$this->assertEquals($this->invoice->status_id, \App\Models\Invoice::STATUS_SENT);
|
// $this->assertEquals($this->invoice->status_id, \App\Models\Invoice::STATUS_SENT);
|
||||||
|
|
||||||
try {
|
// try {
|
||||||
$response = $this->withHeaders([
|
// $response = $this->withHeaders([
|
||||||
'X-API-SECRET' => config('ninja.api_secret'),
|
// 'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
'X-API-TOKEN' => $this->token,
|
// 'X-API-TOKEN' => $this->token,
|
||||||
])->put('/api/v1/invoices/'.$this->encodePrimaryKey($this->invoice->id), $invoice_update);
|
// ])->put('/api/v1/invoices/'.$this->encodePrimaryKey($this->invoice->id), $invoice_update);
|
||||||
} catch (ValidationException $e) {
|
// } catch (ValidationException $e) {
|
||||||
$message = json_decode($e->validator->getMessageBag(), 1);
|
// $message = json_decode($e->validator->getMessageBag(), 1);
|
||||||
|
|
||||||
$this->assertNotNull($message);
|
// $this->assertNotNull($message);
|
||||||
\Log::error($message);
|
// \Log::error($message);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if ($response) {
|
// if ($response) {
|
||||||
$response->assertStatus(302);
|
// $response->assertStatus(302);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public function testValidationFailsForLockedInvoiceWhenPaid()
|
// public function testValidationFailsForLockedInvoiceWhenPaid()
|
||||||
{
|
// {
|
||||||
$this->company->settings->lock_invoices = 'when_paid';
|
// $this->company->settings->lock_invoices = 'when_paid';
|
||||||
$this->company->save();
|
// $this->company->save();
|
||||||
|
|
||||||
$settings = $this->client->settings;
|
// $settings = $this->client->settings;
|
||||||
$settings->lock_invoices = 'when_paid';
|
// $settings->lock_invoices = 'when_paid';
|
||||||
$this->client->settings = $settings;
|
// $this->client->settings = $settings;
|
||||||
$this->client->save();
|
// $this->client->save();
|
||||||
|
|
||||||
$this->invoice = $this->invoice->service()->markPaid()->save();
|
// $this->invoice = $this->invoice->service()->markPaid()->save();
|
||||||
|
|
||||||
$invoice_update = [
|
// $invoice_update = [
|
||||||
'po_number' => 'test',
|
// 'po_number' => 'test',
|
||||||
];
|
// ];
|
||||||
|
|
||||||
$this->assertEquals($this->invoice->status_id, \App\Models\Invoice::STATUS_PAID);
|
// $this->assertEquals($this->invoice->status_id, \App\Models\Invoice::STATUS_PAID);
|
||||||
|
|
||||||
try {
|
// try {
|
||||||
$response = $this->withHeaders([
|
// $response = $this->withHeaders([
|
||||||
'X-API-SECRET' => config('ninja.api_secret'),
|
// 'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
'X-API-TOKEN' => $this->token,
|
// 'X-API-TOKEN' => $this->token,
|
||||||
])->put('/api/v1/invoices/'.$this->encodePrimaryKey($this->invoice->id), $invoice_update);
|
// ])->put('/api/v1/invoices/'.$this->encodePrimaryKey($this->invoice->id), $invoice_update);
|
||||||
} catch (ValidationException $e) {
|
// } catch (ValidationException $e) {
|
||||||
$message = json_decode($e->validator->getMessageBag(), 1);
|
// $message = json_decode($e->validator->getMessageBag(), 1);
|
||||||
|
|
||||||
$this->assertNotNull($message);
|
// $this->assertNotNull($message);
|
||||||
\Log::error($message);
|
// \Log::error($message);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if ($response) {
|
// if ($response) {
|
||||||
$response->assertStatus(302);
|
// $response->assertStatus(302);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user