AndanDo provides comprehensive revenue tracking and analytics to help hosts understand their business performance, identify trends, and optimize their tours.
public async Task<TourReservationStatsDto> GetTourReservationStatsAsync( int tourId, int recentDays = 30, CancellationToken cancellationToken = default){ var sql = $@" SELECT CAST(r.CreatedAt AS date) AS DayDate, COUNT(*) AS ReservationCount, COALESCE(SUM(r.AmountPaid), 0) AS TotalAmount, SUM(CASE WHEN r.PaymentStatus = 1 THEN 1 ELSE 0 END) AS PaidCount, SUM(CASE WHEN r.PaymentStatus <> 1 THEN 1 ELSE 0 END) AS PendingCount, COALESCE(SUM(r.AmountPaid), 0) AS PaidAmount, COALESCE(SUM(r.TotalAmount - ISNULL(r.AmountPaid, 0)), 0) AS PendingAmount FROM {reservationTable} r WHERE r.TourId = @TourId AND r.CreatedAt >= DATEADD(day, -@RecentDays, SYSUTCDATETIME()) GROUP BY CAST(r.CreatedAt AS date) ORDER BY DayDate ASC;"; // Returns daily breakdown and totals}
public async Task<decimal> GetOwnerEarningsAsync( int ownerUserId, CancellationToken cancellationToken = default){ var sql = $@" SELECT COALESCE(SUM(r.AmountPaid), 0) FROM {reservationTable} r INNER JOIN {tourTable} t ON t.TourId = r.TourId WHERE t.OwnerUserId = @OwnerUserId"; var result = await ExecuteScalarAsync<decimal>(sql, new { OwnerUserId = ownerUserId }); return result;}
public async Task<(int TotalServices, int RecentServices)> GetOwnerTourStatsAsync( int ownerUserId, int recentDays = 7, CancellationToken cancellationToken = default){ var totalSql = $@" SELECT COUNT(*) FROM {tourTable} WHERE OwnerUserId = @OwnerUserId AND IsActive = 1"; var recentSql = $@" SELECT COUNT(*) FROM {tourTable} WHERE OwnerUserId = @OwnerUserId AND IsActive = 1 AND CreatedAt >= DATEADD(day, -@RecentDays, SYSUTCDATETIME())"; // Returns (total, recent)}
public sealed record TourReservationDayStat( DateTime Date, int Count, decimal Amount, int PaidCount, int PendingCount, decimal PaidAmount, decimal PendingAmount);
The DayStat record includes separate tracking for paid and pending payments.
public async Task<(DateTime? StartDate, DateTime? EndDate)> GetTourDateRangeAsync( int tourId, CancellationToken cancellationToken = default){ const string sql = @" SELECT MIN(FechaInicio) AS StartDate, MAX(FechaFin) AS EndDate FROM TourFechas WHERE EventoId = @TourId"; // Returns date range from TourFechas table}
The default analysis window is 30 days, but this can be customized in the GetTourReservationStatsAsync call.