Reward (before service)

PHOTO EMBED

Sat Aug 03 2024 23:50:30 GMT+0000 (Coordinated Universal Time)

Saved by @iamkatmakhafola

//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();
            }
        }

        [HttpGet]
        [Route("UnredeemedRewards/{memberId}")]
        public async Task<IActionResult> UnredeemedRewards(int memberId)
        {
            try
            {
                var rewards = await _appDbContext.Reward_Members
                    .Where(r => r.Member_ID == memberId && !r.IsRedeemed)
                    .Select(rm => new
                    {
                        rm.Reward_ID,
                        rm.IsRedeemed,
                        RewardTypeName = rm.Reward.Reward_Type.Reward_Type_Name,
                        RewardCriteria = rm.Reward.Reward_Type.Reward_Criteria,
                        RewardIssueDate = rm.Reward.Reward_Issue_Date
                    })
                    .ToListAsync();

                return Ok(rewards);
            }
            catch (Exception ex)
            {
                return BadRequest($"An error occurred: {ex.Message}");
            }
        }

        [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 == "Placed a Booking")
            {
                qualifyingMembers = await GetMembersWithAtLeastOneBooking();
            }
            else if (criteria == "Completed 10 Bookings in a Month")
            {
                qualifyingMembers = await GetMembersWithBookingsInMonth(10);
            }
            else if (criteria == "Made 20 Bookings in Last 3 Months")
            {
                qualifyingMembers = await GetFrequentBookers(20, 3);
            }
            else if (criteria == "Member for Over a Year")
            {
                qualifyingMembers = await GetLoyalMembers();
            }

            return qualifyingMembers;
        }

        private async Task<List<Member>> GetMembersWithAtLeastOneBooking()
        {
            var qualifyingMembers = await _appDbContext.Members
                .Where(m => _appDbContext.Bookings
                    .Any(b => b.Member_ID == m.Member_ID))
                .ToListAsync();

            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;
        }
    }
}

//RewardPostViewModel
namespace av_motion_api.ViewModels
{
    public class RewardPostViewModel
    {
        public int RewardId { get; set; }
    }
}
content_copyCOPY