diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index d79c90131d3..523985bb7d0 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -11,31 +11,32 @@ namespace App\Console; +use App\Utils\Ninja; +use App\Models\Account; +use App\Jobs\Ninja\QueueSize; +use App\Jobs\Util\DiskCleanup; +use App\Jobs\Util\ReminderJob; use App\Jobs\Cron\AutoBillCron; -use App\Jobs\Cron\RecurringExpensesCron; -use App\Jobs\Cron\RecurringInvoicesCron; +use App\Jobs\Util\VersionCheck; +use App\Jobs\Ninja\TaskScheduler; +use App\Jobs\Util\SchedulerCheck; +use App\Jobs\Ninja\CheckACHStatus; use App\Jobs\Cron\SubscriptionCron; -use App\Jobs\EDocument\EInvoicePullDocs; -use App\Jobs\Invoice\InvoiceCheckLateWebhook; +use App\Jobs\Ninja\MailWebhookSync; +use App\Jobs\Util\QuoteReminderJob; use App\Jobs\Ninja\AdjustEmailQuota; -use App\Jobs\Ninja\BankTransactionSync; -use App\Jobs\Ninja\CheckACHStatus; use App\Jobs\Ninja\CompanySizeCheck; -use App\Jobs\Ninja\QueueSize; use App\Jobs\Ninja\SystemMaintenance; -use App\Jobs\Ninja\TaskScheduler; use App\Jobs\Quote\QuoteCheckExpired; -use App\Jobs\Subscription\CleanStaleInvoiceOrder; -use App\Jobs\Util\DiskCleanup; -use App\Jobs\Util\QuoteReminderJob; -use App\Jobs\Util\ReminderJob; -use App\Jobs\Util\SchedulerCheck; use App\Jobs\Util\UpdateExchangeRates; -use App\Jobs\Util\VersionCheck; -use App\Models\Account; -use App\PaymentDrivers\Rotessa\Jobs\TransactionReport; -use App\Utils\Ninja; +use App\Jobs\Ninja\BankTransactionSync; +use App\Jobs\Cron\RecurringExpensesCron; +use App\Jobs\Cron\RecurringInvoicesCron; +use App\Jobs\EDocument\EInvoicePullDocs; use Illuminate\Console\Scheduling\Schedule; +use App\Jobs\Invoice\InvoiceCheckLateWebhook; +use App\Jobs\Subscription\CleanStaleInvoiceOrder; +use App\PaymentDrivers\Rotessa\Jobs\TransactionReport; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel @@ -121,6 +122,8 @@ protected function schedule(Schedule $schedule) /* Checks ACH verification status and updates state to authorize when verified */ $schedule->job(new CheckACHStatus())->everySixHours()->withoutOverlapping()->name('ach-status-job')->onOneServer(); + $schedule->job(new MailWebhookSync())->everyFourHours(rand(20, 45))->withoutOverlapping()->name('mail-webhook-sync-job')->onOneServer(); + $schedule->command('ninja:check-data --database=db-ninja-01')->dailyAt('02:10')->withoutOverlapping()->name('check-data-db-1-job')->onOneServer(); $schedule->command('ninja:check-data --database=db-ninja-02')->dailyAt('02:20')->withoutOverlapping()->name('check-data-db-2-job')->onOneServer(); diff --git a/app/Jobs/Invoice/ZipInvoices.php b/app/Jobs/Invoice/ZipInvoices.php index ae26fcc90a5..fcf648faea4 100644 --- a/app/Jobs/Invoice/ZipInvoices.php +++ b/app/Jobs/Invoice/ZipInvoices.php @@ -73,7 +73,7 @@ public function handle(): void $invitation = $this->invoices->first()->invitations->first(); if (!$invitation) { - nlog("no Invoice Invitations"); + nlog("ZipInvoices:: no Invoice Invitations"); return; } @@ -118,7 +118,7 @@ public function handle(): void broadcast(new DownloadAvailable($storage_url, $message, $this->user)); } catch (\PhpZip\Exception\ZipException $e) { - nlog('could not make zip => '.$e->getMessage()); + nlog('ZipInvoices:: could not make zip => '.$e->getMessage()); } finally { $zipFile->close(); } diff --git a/app/Jobs/Ninja/AdjustEmailQuota.php b/app/Jobs/Ninja/AdjustEmailQuota.php index 15832893bd4..d12881fe0f0 100644 --- a/app/Jobs/Ninja/AdjustEmailQuota.php +++ b/app/Jobs/Ninja/AdjustEmailQuota.php @@ -63,7 +63,7 @@ public function handle() public function adjust() { Account::query()->cursor()->each(function ($account) { - nlog("resetting email quota for {$account->key}"); + // nlog("resetting email quota for {$account->key}"); $email_count = Cache::get("email_quota".$account->key); diff --git a/app/Jobs/Ninja/MailWebhookSync.php b/app/Jobs/Ninja/MailWebhookSync.php new file mode 100644 index 00000000000..e0bc9ec9e1e --- /dev/null +++ b/app/Jobs/Ninja/MailWebhookSync.php @@ -0,0 +1,174 @@ +scanSentEmails(); + } + } + + private function scanSentEmails() + { + + $query = \App\Models\InvoiceInvitation::whereNotNull('message_id') + ->whereNull('email_status') + ->whereHas('company', function ($q) { + $q->where('settings->email_sending_method', 'default'); + }); + + $this->runIterator($query); + + + $query = \App\Models\QuoteInvitation::whereNotNull('message_id') + ->whereNull('email_status') + ->whereHas('company', function ($q) { + $q->where('settings->email_sending_method', 'default'); + }); + + $this->runIterator($query); + + + $query = \App\Models\RecurringInvoiceInvitation::whereNotNull('message_id') + ->whereNull('email_status') + ->whereHas('company', function ($q) { + $q->where('settings->email_sending_method', 'default'); + }); + + $this->runIterator($query); + + + $query = \App\Models\CreditInvitation::whereNotNull('message_id') + ->whereNull('email_status') + ->whereHas('company', function ($q) { + $q->where('settings->email_sending_method', 'default'); + }); + + $this->runIterator($query); + + + $query = \App\Models\PurchaseOrderInvitation::whereNotNull('message_id') + ->whereNull('email_status') + ->whereHas('company', function ($q) { + $q->where('settings->email_sending_method', 'default'); + }); + + $this->runIterator($query); + + } + + private function runIterator($query) + { + $query->where('created_at' , '<', now()->subHours(1)) + ->each(function ($invite) { + + $postmark = new \Postmark\PostmarkClient(config('services.postmark.token')); + + try { + $messageDetail = $postmark->getOutboundMessageDetails($invite->message_id); + } catch (\Throwable $th) { + $postmark = new \Postmark\PostmarkClient(config('services.postmark-outlook.token')); + $messageDetail = $postmark->getOutboundMessageDetails($invite->message_id); + } + + try { + + if (!$messageDetail) { + return true; + } + + $data = [ + 'RecordType' => 'Delivery', + 'ServerID' => 23, + 'MessageStream' => 'outbound', + 'MessageID' => $invite->message_id, + 'Recipient' => collect($messageDetail->recipients)->first(), + 'Tag' => $invite->company->company_key, + 'DeliveredAt' => '2025-01-01T16:34:52Z', + 'Metadata' => [ + + ] + ]; + + (new \App\Jobs\PostMark\ProcessPostmarkWebhook($data))->handle(); + + $invite->sent_date = now(); + $invite->save(); + + } catch (\Throwable $th) { + nlog("MailWebhookSync:: {$th->getMessage()}"); + } + + }); + + } + + public function middleware() + { + return [new WithoutOverlapping('mail-webhook-sync')]; + } + + public function failed($exception) + { + nlog("MailWebhookSync:: Exception:: => ".$exception->getMessage()); + config(['queue.failed.driver' => null]); + } +} diff --git a/app/Listeners/Mail/MailSentListener.php b/app/Listeners/Mail/MailSentListener.php index a37aba40c0b..51405a50780 100644 --- a/app/Listeners/Mail/MailSentListener.php +++ b/app/Listeners/Mail/MailSentListener.php @@ -61,6 +61,7 @@ public function handle(MessageSent $event) return; } + $invitation->sent_date = now(); $invitation->message_id = str_replace(["<",">"], "", $message_id); $invitation->save(); }