$result['total'], 'skip' => $skip, 'limit' => $limit, 'quotes' => $result['quotes'], ]); } /** * GET /admin/quotes/stats * * Get dashboard statistics for quotes. */ function handle_get_stats(): void { check_admin_auth(); $db = get_db(); $stats = get_stats($db); json_response($stats); } /** * GET /admin/quotes/{id} * * Get a single quote by ID with items, activities, and notifications. */ function handle_admin_get_quote(string $quote_id): void { check_admin_auth(); $db = get_db(); $quote = get_quote_by_id($db, $quote_id); $response = build_admin_quote_response($db, $quote); json_response($response); } /** * PUT /admin/quotes/{id} * * Update a quote's status and/or expiration (admin only). */ function handle_admin_update_quote(string $quote_id): void { check_admin_auth(); $data = get_json_body(); $db = get_db(); $quote = admin_update_quote($db, $quote_id, $data, 'admin'); $response = build_admin_quote_response($db, $quote); json_response($response); } /** * POST /admin/quotes/{id}/sync-syncro * * Trigger a SyncroRMM sync for a quote. */ function handle_sync_syncro(string $quote_id): void { check_admin_auth(); $db = get_db(); $quote = get_quote_by_id($db, $quote_id); $result = sync_quote_to_syncro($db, $quote); json_response($result); }