Introduces App\Support\DashboardSchedule (modelled on LHITS_Dashboard's pattern) as a single settings-driven registry for recurring Artisan jobs, replacing the two hard-coded Schedule::command() lines in routes/console.php. Migrated unchanged: - integrations_refresh (integrations:refresh), every_30_seconds, withoutOverlapping(5) - alerts_scan (alerts:scan), every_30_seconds, withoutOverlapping(5) New: - etsy_sync (etsy:sync), every_15_minutes - forces a fresh pull of Etsy receipts/listings into the existing IntegrationCache entries, decoupled from the bundled integrations:refresh job so it can be tuned/disabled independently of Parcel2Go/BamBuddy/dryer refreshes. - etsy_token_refresh (etsy:refresh-token), every_45_minutes - proactively refreshes the Etsy OAuth token (tokens last ~1hr) via a new public Etsy::refreshAccessToken() wrapper around the existing on-demand accessToken() refresh logic, so the connection survives quiet periods. Frequency is persisted to storage/app/dashboard-schedules.json (no app_settings table exists in this app, unlike LHITS's AppSetting-backed store) and surfaced in a new 'Scheduler' section on the existing Settings page (ScheduleSettingsController + routes), with per-job frequency dropdowns and manual 'Run now' buttons, matching the page's existing Tailwind conventions. Tests: SchedulerTest (registry/frequency behavior), ScheduleSettingsTest (settings UI + authorization), EtsySyncScheduledJobsTest (new commands, Http::fake only, no live Etsy calls).
57 lines
4.1 KiB
PHP
57 lines
4.1 KiB
PHP
<?php
|
|
|
|
use App\Http\Controllers\AuthController;
|
|
use App\Http\Controllers\BambuddyController;
|
|
use App\Http\Controllers\DashboardController;
|
|
use App\Http\Controllers\DryerController;
|
|
use App\Http\Controllers\EtsyController;
|
|
use App\Http\Controllers\EtsySettingsController;
|
|
use App\Http\Controllers\IntegrationSettingsController;
|
|
use App\Http\Controllers\NotificationController;
|
|
use App\Http\Controllers\Parcel2GoConnectionController;
|
|
use App\Http\Controllers\PrinterController;
|
|
use App\Http\Controllers\ScheduleSettingsController;
|
|
use App\Http\Controllers\ShippingController;
|
|
use App\Http\Controllers\UserController;
|
|
use App\Http\Middleware\EnsureAccountActive;
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
Route::middleware('guest')->group(function (): void {
|
|
Route::get('/login', [AuthController::class, 'create'])->name('login');
|
|
Route::post('/login', [AuthController::class, 'store'])->middleware('throttle:5,1')->name('login.store');
|
|
});
|
|
|
|
Route::middleware(['auth', EnsureAccountActive::class])->group(function (): void {
|
|
Route::post('/logout', [AuthController::class, 'destroy'])->name('logout');
|
|
Route::get('/', DashboardController::class)->name('dashboard');
|
|
Route::get('/notifications', [NotificationController::class, 'index'])->name('notifications.index');
|
|
Route::post('/notifications/read', [NotificationController::class, 'readAll'])->name('notifications.read-all');
|
|
Route::post('/notifications/{notification}/read', [NotificationController::class, 'read'])->name('notifications.read');
|
|
Route::get('/printers', BambuddyController::class)->name('printers.index');
|
|
Route::delete('/printers/{printer}', [PrinterController::class, 'destroy'])->name('printers.destroy');
|
|
Route::get('/shipping', [ShippingController::class, 'index'])->name('shipping');
|
|
Route::post('/shipping/quotes', [ShippingController::class, 'quote'])->name('shipping.quote');
|
|
Route::post('/shipping/collections/dates', [ShippingController::class, 'collectionDates'])->name('shipping.collection-dates');
|
|
Route::post('/shipping/collections/book', [ShippingController::class, 'bookCollection'])->name('shipping.book-collection');
|
|
Route::post('/shipping/collections/reset', [ShippingController::class, 'resetBooking'])->name('shipping.reset-booking');
|
|
Route::get('/shipping/labels/{orderLineId}', [ShippingController::class, 'label'])->name('shipping.label');
|
|
Route::post('/shipping/parcel2go/connect', [Parcel2GoConnectionController::class, 'connect'])->name('parcel2go.connect');
|
|
Route::get('/shipping/parcel2go/callback', [Parcel2GoConnectionController::class, 'callback'])->name('parcel2go.callback');
|
|
Route::get('/etsy', [EtsyController::class, 'index'])->name('etsy.index');
|
|
Route::post('/etsy/connect', [EtsyController::class, 'connect'])->name('etsy.connect');
|
|
Route::get('/etsy/callback', [EtsyController::class, 'callback'])->name('etsy.callback');
|
|
Route::get('/settings', [EtsySettingsController::class, 'index'])->name('settings.index');
|
|
Route::put('/settings/etsy', [EtsySettingsController::class, 'update'])->name('settings.etsy.update');
|
|
Route::put('/settings/integrations/{provider}', [IntegrationSettingsController::class, 'update'])->name('settings.integrations.update');
|
|
Route::put('/settings/schedules', [ScheduleSettingsController::class, 'update'])->name('settings.schedules.update');
|
|
Route::post('/settings/schedules/{job}/run', [ScheduleSettingsController::class, 'run'])->name('settings.schedules.run');
|
|
Route::get('/dryer', [DryerController::class, 'index'])->name('dryer');
|
|
Route::get('/dryer/status', [DryerController::class, 'status'])->name('dryer.status');
|
|
Route::post('/dryer/control', [DryerController::class, 'control'])->name('dryer.control');
|
|
Route::post('/dryer/faults/acknowledge', [DryerController::class, 'acknowledge'])->name('dryer.acknowledge');
|
|
Route::get('/users', [UserController::class, 'index'])->name('users.index');
|
|
Route::post('/users', [UserController::class, 'store'])->name('users.store');
|
|
Route::patch('/users/{user}', [UserController::class, 'update'])->name('users.update');
|
|
Route::delete('/users/{user}', [UserController::class, 'destroy'])->name('users.destroy');
|
|
});
|