FlowAPI / FlowAPI.Application /Services /HabitService.cs
danylokhodus's picture
fix: treat null/empty SubscriptionTier as Free tier in all limit checks
0a579ad
Raw
History Blame Contribute Delete
3.61 kB
using FlowAPI.Application.DTOs.Habit;
using FlowAPI.Application.Interfaces;
using FlowAPI.Domain.Entities;
namespace FlowAPI.Application.Services
{
public class HabitService : IHabitService
{
private readonly IHabitRecordRepository _repo;
private readonly IUserRepository _userRepo;
private readonly IAchievementService _achievementService;
public HabitService(IHabitRecordRepository repo, IUserRepository userRepo, IAchievementService achievementService)
{
_repo = repo;
_userRepo = userRepo;
_achievementService = achievementService;
}
public async Task<IEnumerable<HabitRecordResponseDto>> GetAllByUserIdAsync(Guid userId)
{
var records = await _repo.GetAllByUserIdAsync(userId);
return records.Select(MapToDto);
}
public async Task<HabitRecordResponseDto> RecordHabitAsync(CreateHabitRecordDto dto)
{
var user = await _userRepo.GetByIdAsync(dto.UserId);
if (user == null) throw new Exception("User not found.");
var targetDate = dto.CheckedDate ?? DateTime.UtcNow;
var existing = await _repo.GetRecordForDateAsync(dto.UserId, dto.HabitName, targetDate.Date);
if (existing is not null) return MapToDto(existing);
var tier = user.SubscriptionTier?.Trim();
bool isFree = string.IsNullOrEmpty(tier) || tier == "Free";
if (isFree)
{
var allRecords = await _repo.GetAllByUserIdAsync(dto.UserId);
var distinctHabits = allRecords.Select(r => r.HabitName).Distinct().ToList();
if (!distinctHabits.Contains(dto.HabitName) && distinctHabits.Count >= 3)
{
throw new InvalidOperationException("Free tier is limited to 3 habits.");
}
}
var record = new HabitRecord
{
Id = Guid.NewGuid(),
UserId = dto.UserId,
HabitName = dto.HabitName,
CheckedDate = targetDate
};
var created = await _repo.CreateAsync(record);
await _achievementService.ProcessEventAsync(dto.UserId, "HabitTracked");
return MapToDto(created);
}
public async Task<int> GetStreakAsync(Guid userId, string habitName)
{
var records = await _repo.GetAllByUserIdAsync(userId);
var habitRecords = records
.Where(r => r.HabitName == habitName)
.OrderByDescending(r => r.CheckedDate)
.ToList();
if (!habitRecords.Any()) return 0;
int streak = 0;
DateTime expectedDate = DateTime.UtcNow.Date;
foreach (var record in habitRecords)
{
if (record.CheckedDate.Date == expectedDate)
{
streak++;
expectedDate = expectedDate.AddDays(-1);
}
else if (record.CheckedDate.Date > expectedDate)
{
continue;
}
else
{
break;
}
}
return streak;
}
private static HabitRecordResponseDto MapToDto(HabitRecord record) => new()
{
Id = record.Id,
UserId = record.UserId,
HabitName = record.HabitName,
CheckedDate = record.CheckedDate
};
}
}