diff --git a/app/Console/Commands/CreateSingleAccount.php b/app/Console/Commands/CreateSingleAccount.php index 0909f4dfeb..767bee033a 100644 --- a/app/Console/Commands/CreateSingleAccount.php +++ b/app/Console/Commands/CreateSingleAccount.php @@ -33,6 +33,7 @@ use App\Models\TaxRate; use App\Libraries\MultiDB; use App\Models\TaskStatus; use App\Models\CompanyToken; +use App\Models\Subscription; use App\Models\ClientContact; use App\Models\VendorContact; use App\Models\CompanyGateway; @@ -600,8 +601,45 @@ class CreateSingleAccount extends Command $sub->frequency_id = RecurringInvoice::FREQUENCY_ANNUALLY; $sub->save(); + + if($config = config('admin-api.products')){ + + foreach($config as $key => $product){ + + if(!$p = Product::where('product_key', $key)->first()){ + + $p = Product::factory()->create([ + 'user_id' => $user->id, + 'company_id' => $company->id, + 'product_key' => $key, + 'notes' => $product['description'], + 'price' => $product['price'] + ]); + + if(!Subscription::find($product['subscription_id'])){ + + $sub = SubscriptionFactory::create($company->id, $user->id); + $sub->id = $product['subscription_id']; + $sub->name = $product['description']; + $sub->recurring_product_ids = "{$p->hashed_id}"; + $sub->webhook_configuration = $webhook_config; + $sub->allow_plan_changes = true; + $sub->frequency_id = $product['term'] == 'month' ? RecurringInvoice::FREQUENCY_MONTHLY : RecurringInvoice::FREQUENCY_ANNUALLY; + $sub->max_seats_limit = $product['users'] ?? 1; + $sub->per_seat_enabled = true; + $sub->save(); + + } + } + + } + + } + + } + private function createClient($company, $user) { // dispatch(function () use ($company, $user) { diff --git a/app/DataMapper/Analytics/JobFailureAnalytics.php b/app/DataMapper/Analytics/JobFailureAnalytics.php new file mode 100644 index 0000000000..05ff2aad8c --- /dev/null +++ b/app/DataMapper/Analytics/JobFailureAnalytics.php @@ -0,0 +1,60 @@ +string_metric5 = $string_metric5; + $this->string_metric6 = $string_metric6; + } +} diff --git a/app/Jobs/RecurringInvoice/UpdateRecurring.php b/app/Jobs/RecurringInvoice/UpdateRecurring.php index d3d3c1a2ce..b4403696dd 100644 --- a/app/Jobs/RecurringInvoice/UpdateRecurring.php +++ b/app/Jobs/RecurringInvoice/UpdateRecurring.php @@ -15,25 +15,17 @@ namespace App\Jobs\RecurringInvoice; use App\Models\User; use App\Models\Company; use App\Libraries\MultiDB; -use Illuminate\Bus\Queueable; use App\Models\RecurringInvoice; use App\Events\Socket\RefetchEntity; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Foundation\Bus\Dispatchable; +use App\Jobs\BaseJob; -class UpdateRecurring implements ShouldQueue +class UpdateRecurring extends BaseJob { - use Dispatchable; - use InteractsWithQueue; - use Queueable; - use SerializesModels; - public $tries = 1; public function __construct(public array $ids, public Company $company, public User $user, protected string $action, protected float $percentage = 0) { + nlog("UpdateRecurring job constructed with IDs: " . implode(',', $ids) . " Action: {$action}"); } /** @@ -43,8 +35,11 @@ class UpdateRecurring implements ShouldQueue */ public function handle(): void { + nlog("UpdateRecurring job STARTING - this proves it's being executed"); + MultiDB::setDb($this->company->db); + nlog("UpdateRecurring"); $this->user->setCompany($this->company); RecurringInvoice::query()->where('company_id', $this->company->id) @@ -62,9 +57,32 @@ class UpdateRecurring implements ShouldQueue }); event(new RefetchEntity('recurring_invoices', null, $this->user)); + + nlog("UpdateRecurring job COMPLETED successfully"); } - public function failed($exception = null) + protected function getJobProperties(): array { + return [ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'action' => $this->action, + 'ids_count' => count($this->ids), + 'ids' => $this->ids, + 'percentage' => $this->percentage, + ]; + } + + protected function handleSpecificFailure(\Throwable $exception = null): void + { + nlog("UpdateRecurring specific failure handler called"); + if ($exception) { + nlog("UpdateRecurring failed with: " . $exception->getMessage()); + } + } + + protected function shouldDisableFailedJobStorage(): bool + { + return true; // Matches existing behavior } } diff --git a/app/Listeners/Job/GlobalJobFailureListener.php b/app/Listeners/Job/GlobalJobFailureListener.php new file mode 100644 index 0000000000..849ac07e27 --- /dev/null +++ b/app/Listeners/Job/GlobalJobFailureListener.php @@ -0,0 +1,31 @@ +job->resolveName(); + $exception = $event->exception->getMessage(); + + Lightlogs::create(new JobFailureAnalytics($name, $exception))->send(); + } +} \ No newline at end of file diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index fddf14945b..7b4fd01db5 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -288,6 +288,8 @@ use App\Listeners\RecurringExpense\RecurringExpenseRestoredActivity; use App\Listeners\RecurringInvoice\RecurringInvoiceArchivedActivity; use App\Listeners\RecurringInvoice\RecurringInvoiceRestoredActivity; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; +use App\Listeners\Job\GlobalJobFailureListener; +use Illuminate\Queue\Events\JobFailed; class EventServiceProvider extends ServiceProvider { @@ -496,6 +498,9 @@ class EventServiceProvider extends ServiceProvider InvitationWasViewed::class => [ InvitationViewedListener::class, ], + JobFailed::class => [ + GlobalJobFailureListener::class, + ], PaymentWasEmailed::class => [ PaymentEmailedActivity::class, ],