Files
Core_Be/Repos/FeedRepository.cs
T
Dhananjaya99 bffc9b1686 first commit
2026-09-28 11:44:26 +05:30

221 lines
8.2 KiB
C#

using Fitness_core_BE.Exceptions;
using Fitness_core_BE.Interfaces;
using Fitness_core_BE.Models;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;
namespace Fitness_core_BE.Repos
{
public class FeedRepository : IFeedRepository
{
// FeedPost/FeedLike are central-bucket (poster identity spans gyms); Staff and
// CustomerSubscriptions used to scope a feed to one client live in the tenant DB.
private readonly CentralDbContext _central;
private readonly TenantDbContext _dbContext;
public FeedRepository(CentralDbContext central, TenantDbContext dbContext)
{
_central = central;
_dbContext = dbContext;
}
public async Task<FeedPost> GetFeedPostByIdAsync(Guid creatorId, Guid postId)
{
FeedPost feedPost = await _central.FeedPosts
.Where(p => p.FKUserId == creatorId && p.FeedPostId == postId)
.FirstOrDefaultAsync();
if (feedPost == null)
throw new NotFoundException("Post : " + postId + " not found");
return feedPost;
}
public async Task<List<FeedPost>> GetFeedListAsync(int skip, int take)
{
return await _central.FeedPosts
.Include(fp => fp.User)
.Where(fp => fp.IsActive)
.OrderByDescending(fp => fp.CreatedAt)
.Skip(skip)
.Take(take)
.ToListAsync();
}
public async Task<bool> IsLikedAsync(Guid postId, Guid userId)
{
return await _central.FeedLikes
.AnyAsync(x => x.FKFeedPostId == postId && x.FKUserId == userId);
}
public async Task AddLikeAsync(Guid postId, Guid userId)
{
_central.FeedLikes.Add(new FeedLike
{
FKFeedPostId = postId,
FKUserId = userId
});
}
public async Task RemoveLikeAsync(Guid postId, Guid userId)
{
var like = await _central.FeedLikes
.FirstOrDefaultAsync(x => x.FKFeedPostId == postId && x.FKUserId == userId);
if (like != null)
{
_central.FeedLikes.Remove(like);
}
}
public async Task<int> GetLikeCountAsync(Guid postId)
{
return await _central.FeedLikes
.CountAsync(x => x.FKFeedPostId == postId);
}
public async Task<object> CreateFeedAsync(FeedPost feedPost, CancellationToken ct = default)
{
await _central.FeedPosts.AddAsync(feedPost, ct);
return true;
}
public async Task<List<FeedPost>> GetFeedByClientAsync(Guid clientId)
{
// Client (central) and Staff (tenant) can't be joined in one query anymore --
// resolve the set of poster user ids (owner + staff) first, then filter posts.
var posterUserIds = new List<Guid>();
var clientOwnerUserId = await _central.Client
.Where(client => client.ClientId == clientId)
.Select(client => (Guid?)client.FKUserId)
.FirstOrDefaultAsync();
if (clientOwnerUserId != null)
posterUserIds.Add(clientOwnerUserId.Value);
var staffUserIds = await _dbContext.Staff
.Where(staff => staff.FKClientId == clientId)
.Select(staff => staff.FKUserId)
.ToListAsync();
posterUserIds.AddRange(staffUserIds);
return await _central.FeedPosts
.Include(fp => fp.User)
.Where(fp => fp.IsActive && posterUserIds.Contains(fp.FKUserId))
.OrderByDescending(fp => fp.CreatedAt)
.ToListAsync();
}
public async Task<(Guid? ClientId, List<FeedPost> Posts)> GetFeedForCustomerAsync(
Guid customerUserId,
int skip,
int take,
CancellationToken ct = default)
{
var cusId = await _central.Customer
.Where(customer => customer.FKUserId == customerUserId)
.Select(customer => (Guid?)customer.CusId)
.FirstOrDefaultAsync(ct);
var clientId = Guid.Empty;
if (cusId != null)
{
clientId = await _dbContext.CustomerSubscriptions
.Where(subscription =>
subscription.FKCustomerId == cusId.Value &&
subscription.IsActive)
.Select(subscription => subscription.CustomerPlan.FKClientId)
.FirstOrDefaultAsync(ct);
}
// No active gym: there's no single gym feed to scope to, so fall back to the
// platform-wide feed (every active post) instead of showing nothing.
if (clientId == Guid.Empty)
{
var globalPosts = await _central.FeedPosts
.AsNoTracking()
.Include(post => post.User)
.Where(post => post.IsActive)
.OrderByDescending(post => post.CreatedAt)
.Skip(skip)
.Take(take)
.ToListAsync(ct);
return (null, globalPosts);
}
// Poster set for this customer's gym = owner + staff (mirrors GetFeedByClientAsync,
// the client-owner's own view) -- otherwise a staff member's post would show up on
// the gym's own dashboard but never reach that gym's customers.
var posterUserIds = new List<Guid>();
var clientOwnerUserId = await _central.Client
.Where(client => client.ClientId == clientId)
.Select(client => (Guid?)client.FKUserId)
.FirstOrDefaultAsync(ct);
if (clientOwnerUserId != null)
posterUserIds.Add(clientOwnerUserId.Value);
var staffUserIds = await _dbContext.Staff
.Where(staff => staff.FKClientId == clientId)
.Select(staff => staff.FKUserId)
.ToListAsync(ct);
posterUserIds.AddRange(staffUserIds);
// Show the gym's own posts alongside this customer's own posts, so a customer
// who creates a post can see it here too, not just their gym's feed.
var posts = await _central.FeedPosts
.AsNoTracking()
.Include(post => post.User)
.Where(post => post.IsActive && (posterUserIds.Contains(post.FKUserId) || post.FKUserId == customerUserId))
.OrderByDescending(post => post.CreatedAt)
.Skip(skip)
.Take(take)
.ToListAsync(ct);
return (clientId, posts);
}
public async Task<List<Guid>> GetActiveCustomerIdsByPosterUserIdAsync(Guid posterUserId, CancellationToken ct = default)
{
var clientId = await _central.Client
.Where(client => client.FKUserId == posterUserId)
.Select(client => (Guid?)client.ClientId)
.FirstOrDefaultAsync(ct);
if (clientId == null || clientId == Guid.Empty)
return new List<Guid>();
return await _dbContext.CustomerSubscriptions
.Where(subscription => subscription.IsActive && subscription.CustomerPlan.FKClientId == clientId)
.Select(subscription => subscription.FKCustomerId)
.Distinct()
.ToListAsync(ct);
}
public async Task<object> DeletePostPostIdAsync(Guid creatorId, Guid postId)
{
FeedPost post = await _central.FeedPosts
.Where(p => p.FeedPostId == postId && p.FKUserId == creatorId)
.FirstOrDefaultAsync();
if (post == null)
throw new NotFoundException("Post : " + postId + "not found");
post.IsActive = false;
try
{
_central.Update(post);
return new { process = "success" };
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
}
}