prefix . 'prautoblogger_generation_log'; $first_of_month = gmdate( 'Y-m-01 00:00:00' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $result = $wpdb->get_var( $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared "SELECT COALESCE(SUM(estimated_cost), 0) FROM {$table} WHERE created_at >= %s AND response_status = 'success'", $first_of_month ) ); return (float) $result; } /** * Get daily spend for the last N days (for the metrics dashboard chart). * * @param int $days Number of days to look back. * * @return array Associative array of date => total_cost. */ public function get_daily_spend( int $days = 30 ): array { global $wpdb; if ( null === $wpdb ) { return array(); } $table = $wpdb->prefix . 'prautoblogger_generation_log'; $start_date = gmdate( 'Y-m-d', time() - ( $days * DAY_IN_SECONDS ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $results = $wpdb->get_results( $wpdb->prepare( "SELECT DATE(created_at) as day, SUM(estimated_cost) as total_cost // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared FROM {$table} WHERE created_at >= %s AND response_status = 'success' GROUP BY DATE(created_at) ORDER BY day ASC", $start_date . ' 00:00:00' ), ARRAY_A ); $daily = array(); foreach ( ( $results ?: array() ) as $row ) { $daily[ $row['day'] ] = (float) $row['total_cost']; } return $daily; } /** * Get spend breakdown by pipeline stage for a given period. * * @param string $start_date Start date (Y-m-d). * @param string $end_date End date (Y-m-d). * * @return array Breakdown by stage. */ public function get_spend_by_stage( string $start_date, string $end_date ): array { global $wpdb; if ( null === $wpdb ) { return array(); } $table = $wpdb->prefix . 'prautoblogger_generation_log'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $results = $wpdb->get_results( $wpdb->prepare( "SELECT stage, SUM(estimated_cost) as total_cost, SUM(prompt_tokens + completion_tokens) as total_tokens, COUNT(*) as call_count // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared FROM {$table} WHERE created_at BETWEEN %s AND %s AND response_status = 'success' GROUP BY stage", $start_date . ' 00:00:00', $end_date . ' 23:59:59' ), ARRAY_A ); $breakdown = array(); foreach ( ( $results ?: array() ) as $row ) { $breakdown[ $row['stage'] ] = array( 'cost' => (float) $row['total_cost'], 'tokens' => (int) $row['total_tokens'], 'calls' => (int) $row['call_count'], ); } return $breakdown; } /** * Get budget utilization percentage for the current month. * * @return float Percentage (0-100+). Can exceed 100 if overspent. */ public function get_budget_utilization(): float { $budget = (float) get_option( 'prautoblogger_monthly_budget_usd', 50.00 ); if ( $budget <= 0 ) { return 0.0; } return ( $this->get_monthly_spend() / $budget ) * 100.0; } }