//Controller
using av_motion_api.Data;
using av_motion_api.Models;
using av_motion_api.ViewModels;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace av_motion_api.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class RewardController : ControllerBase
{
private readonly AppDbContext _appDbContext;
public RewardController(AppDbContext appDbContext)
{
_appDbContext = appDbContext;
}
[HttpGet]
[Route("getAllRewardTypes")]
public async Task<IActionResult> GetAllRewardTypes()
{
try
{
var rewardTypes = await _appDbContext.Reward_Types.ToListAsync();
return Ok(rewardTypes);
}
catch (Exception)
{
return BadRequest();
}
}
[HttpGet]
[Route("getRewardTypeById/{id}")]
public async Task<IActionResult> GetRewardTypeById(int id)
{
try
{
var rewardType = await _appDbContext.Reward_Types.FindAsync(id);
if (rewardType == null)
{
return NotFound();
}
return Ok(rewardType);
}
catch (Exception)
{
return BadRequest();
}
}
[HttpPost]
[Route("createRewardType")]
public async Task<IActionResult> CreateRewardType(RewardTypeViewModel rt)
{
try
{
var existingRewardType = await _appDbContext.Reward_Types
.FirstOrDefaultAsync(r => r.Reward_Type_Name == rt.Reward_Type_Name);
if (existingRewardType != null)
{
return Conflict(new { message = "Reward type already exists." });
}
var rewardType = new Reward_Type
{
Reward_Type_Name = rt.Reward_Type_Name,
Reward_Criteria = rt.Reward_Criteria
};
_appDbContext.Reward_Types.Add(rewardType);
await _appDbContext.SaveChangesAsync();
return CreatedAtAction(nameof(GetRewardTypeById), new { id = rewardType.Reward_Type_ID }, rewardType);
}
catch (Exception)
{
return BadRequest();
}
}
[HttpPut]
[Route("updateRewardType/{id}")]
public async Task<IActionResult> UpdateRewardType(int id, [FromBody] RewardTypeViewModel rt)
{
try
{
var rewardType = await _appDbContext.Reward_Types.FindAsync(id);
if(rewardType == null)
{
return NotFound();
}
var existingRewardType = await _appDbContext.Reward_Types
.FirstOrDefaultAsync(r => r.Reward_Type_Name == rt.Reward_Type_Name && r.Reward_Type_ID != id);
if (existingRewardType != null)
{
return Conflict(new { message = "Reward type already exists." });
}
rewardType.Reward_Type_Name = rt.Reward_Type_Name;
rewardType.Reward_Criteria = rt.Reward_Criteria;
_appDbContext.Entry(rewardType).State = EntityState.Modified;
await _appDbContext.SaveChangesAsync();
return NoContent();
}
catch (Exception)
{
return BadRequest();
}
}
[HttpDelete]
[Route("deleteRewardType/{id}")]
public async Task<IActionResult> DeleteRewardType(int id)
{
try
{
var rewardType = await _appDbContext.Reward_Types.FindAsync(id);
if(rewardType == null)
{
return NotFound();
}
_appDbContext.Reward_Types.Remove(rewardType);
await _appDbContext.SaveChangesAsync();
return NoContent();
}
catch (Exception)
{
return BadRequest();
}
}
[HttpGet]
[Route("getRewardById/{id}")]
public async Task<IActionResult> GetRewardById(int id)
{
try
{
var reward = await _appDbContext.Rewards.FindAsync(id);
if (reward == null)
{
return NotFound();
}
return Ok(reward);
}
catch (Exception)
{
return BadRequest();
}
}
[HttpGet]
[Route("getAllRewards")]
public async Task<IActionResult> GetAllRewards()
{
try
{
var rewards = await _appDbContext.Rewards
.Join(_appDbContext.Reward_Types,
reward => reward.Reward_Type_ID,
rewardType => rewardType.Reward_Type_ID,
(reward, rewardType) => new RewardViewModel
{
Reward_ID = reward.Reward_ID,
Reward_Issue_Date = reward.Reward_Issue_Date,
Reward_Type_Name = rewardType.Reward_Type_Name,
IsPosted = reward.IsPosted
})
.ToListAsync();
return Ok(rewards);
}
catch (Exception)
{
return BadRequest();
}
}
[HttpPost]
[Route("redeemReward")]
public async Task<IActionResult> RedeemReward([FromBody] RewardRedeemViewModel request)
{
try
{
// Fetch the reward by ID
var reward = await _appDbContext.Reward_Members
.FirstOrDefaultAsync(r => r.Reward_ID == request.RewardId && r.Member_ID == request.MemberId);
if (reward == null)
{
return NotFound("Reward not found or not eligible for the member.");
}
// Check if the reward is already redeemed
if (reward.IsRedeemed)
{
return BadRequest("Reward is already redeemed.");
}
// Mark the reward as redeemed
reward.IsRedeemed = true;
_appDbContext.Entry(reward).State = EntityState.Modified;
await _appDbContext.SaveChangesAsync();
return Ok(new { Status = "Success", Message = "Reward redeemed successfully!" });
}
catch (Exception)
{
return BadRequest("An error occurred while redeeming the reward.");
}
}
[HttpPost]
[Route("setReward")]
public async Task<IActionResult> SetReward(RewardSetViewModel r)
{
try
{
var reward = new Reward
{
Reward_Issue_Date = r.Reward_Issue_Date,
Reward_Type_ID = r.Reward_Type_ID,
IsPosted = r.IsPosted
};
_appDbContext.Rewards.Add(reward);
await _appDbContext.SaveChangesAsync();
return CreatedAtAction(nameof(GetRewardById), new { id = reward.Reward_ID }, reward);
}
catch (Exception)
{
return BadRequest();
}
}
[HttpPost]
[Route("postReward")]
public async Task<IActionResult> PostReward([FromBody] RewardPostViewModel request)
{
try
{
// Fetch the reward by ID
var reward = await _appDbContext.Rewards
.FirstOrDefaultAsync(r => r.Reward_ID == request.RewardId);
if (reward == null)
{
return NotFound("Reward not found.");
}
// Check if the reward is already posted
if (reward.IsPosted)
{
return BadRequest("Reward is already posted.");
}
// Mark the reward as posted
reward.IsPosted = true;
_appDbContext.Entry(reward).State = EntityState.Modified;
await _appDbContext.SaveChangesAsync();
// Fetch members who qualify for this reward based on the criteria
var rewardType = await _appDbContext.Reward_Types.FindAsync(reward.Reward_Type_ID);
var qualifyingMembers = await GetQualifyingMembers(rewardType.Reward_Criteria);
// Add qualifying members to the Reward_Member table
foreach (var member in qualifyingMembers)
{
var rewardMember = new Reward_Member
{
Member_ID = member.Member_ID,
Reward_ID = reward.Reward_ID,
IsRedeemed = false
};
_appDbContext.Reward_Members.Add(rewardMember);
}
await _appDbContext.SaveChangesAsync();
return Ok(new { Status = "Success", Message = "Reward posted successfully!" });
}
catch (Exception)
{
return BadRequest("An error occurred while posting the reward.");
}
}
//Predined Reward Types Methods
private async Task<List<Member>> GetQualifyingMembers(string criteria)
{
var qualifyingMembers = new List<Member>();
if (criteria == "Completed 10 Bookings in a Month")
{
qualifyingMembers = await GetMembersWithBookingsInMonth(10);
}
else if (criteria == "Member for Over a Year")
{
qualifyingMembers = await GetLoyalMembers();
}
else if (criteria == "Made 20 Bookings in Last 3 Months")
{
qualifyingMembers = await GetFrequentBookers(20, 3);
}
//else if (criteria == "Perfect Attendance for a Month")
//{
// qualifyingMembers = await GetPerfectAttendanceMembers();
//}
//else if (criteria == "Consistent Attendance for a Quarter")
//{
// qualifyingMembers = await GetConsistentAttendanceMembers();
//}
return qualifyingMembers;
}
private async Task<List<Member>> GetMembersWithBookingsInMonth(int bookingCount)
{
var oneMonthAgo = DateTime.Now.AddMonths(-1);
var qualifyingMembers = await _appDbContext.Members
.Where(m => _appDbContext.Bookings
.Where(b => b.Member_ID == m.Member_ID)
.Join(_appDbContext.Booking_Time_Slots,
b => b.Booking_ID,
bts => bts.Booking_ID,
(b, bts) => bts.Time_Slot_ID)
.Join(_appDbContext.Time_Slots,
btsId => btsId,
ts => ts.Time_Slot_ID,
(btsId, ts) => ts)
.Count(ts => ts.Slot_Date >= oneMonthAgo) >= bookingCount)
.ToListAsync();
return qualifyingMembers;
}
private async Task<List<Member>> GetLoyalMembers()
{
var oneYearAgo = DateTime.Now.AddYears(-1);
var qualifyingMembers = await _appDbContext.Members
.Join(_appDbContext.Contracts,
m => m.Contract_ID,
c => c.Contract_ID,
(m, c) => new { Member = m, Contract = c })
.Where(mc => mc.Contract.Subscription_Date <= oneYearAgo)
.Select(mc => mc.Member)
.ToListAsync();
return qualifyingMembers;
}
private async Task<List<Member>> GetFrequentBookers(int bookingCount, int months)
{
var dateLimit = DateTime.Now.AddMonths(-months);
var qualifyingMembers = await _appDbContext.Members
.Where(m => _appDbContext.Bookings
.Where(b => b.Member_ID == m.Member_ID)
.Join(_appDbContext.Booking_Time_Slots,
b => b.Booking_ID,
bts => bts.Booking_ID,
(b, bts) => bts.Time_Slot_ID)
.Join(_appDbContext.Time_Slots,
btsId => btsId,
ts => ts.Time_Slot_ID,
(btsId, ts) => ts)
.Count(ts => ts.Slot_Date >= dateLimit) >= bookingCount)
.ToListAsync();
return qualifyingMembers;
}
//private async Task<List<Member>> GetPerfectAttendanceMembers()
//{
// var startDate = DateTime.Now.AddMonths(-1);
// var qualifyingMembers = await _appDbContext.Members
// .Where(m => _appDbContext.Attendance_Lists
// .Count(a => a.Member_ID == m.Member_ID && a.Slot_Date >= startDate && a.Members_Present > 0) == 30)
// .ToListAsync();
// return qualifyingMembers;
//}
//private async Task<List<Member>> GetConsistentAttendanceMembers()
//{
// var startDate = DateTime.Now.AddMonths(-3);
// var qualifyingMembers = await _appDbContext.Members
// .Where(m => _appDbContext.Attendance_Lists
// .Count(a => a.Member_ID == m.Member_ID && a.Slot_Date >= startDate && a.Members_Present > 0) >= 12)
// .ToListAsync();
// return qualifyingMembers;
//}
}
}