using System; using System.Collections.Generic; using System.Data; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Threading.Tasks; using Google.Apis.Auth.OAuth2; using Google.Cloud.Firestore; using Google.Cloud.Firestore.V1; using Grpc.Auth; using Grpc.Core; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Microsoft.Net.Http.Headers; using Newtonsoft.Json; using Teso_API.Methods.Controllers; using Teso_API.Models; namespace Teso_API.Controllers { [AllowAnonymous, Route("coupons")] [ApiController] public class CouponsController : ControllerBase { private readonly TESOContext _context; private FirestoreDb db; public CouponsController(TESOContext context) { _context = context; db = new FirestoreDbBuilder { ProjectId = ServerLocation.credentials.project_id, ChannelCredentials = GoogleCredential.FromJson(JsonConvert.SerializeObject(ServerLocation.credentials)).ToChannelCredentials(), }.Build(); } [Authorize] [Route("acquiredcoupons"), HttpGet] public async Task>> GetCouponsHeads() { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; string connString = ServerLocation.connection; string sprocname = "[dbo].[usp_acquiredCoupons_Get]"; using (SqlConnection conn = new SqlConnection(connString)) { try { string result = ""; conn.Open(); using (SqlCommand cmd = new SqlCommand(sprocname, conn)) { cmd.CommandType = System.Data.CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@userGUID", userID); cmd.ExecuteNonQuery(); using (SqlDataReader sdr = cmd.ExecuteReader()) { while (sdr.Read()) { result += sdr[0]; } } } conn.Close(); List coupons = JsonConvert.DeserializeObject>(result); return coupons; } catch (Exception ex) { conn.Close(); return null; } } } //set Expiration after algorithm design [Authorize] [Route("proximity"), HttpPost] public async Task>> ProximityCoupons(ProximityPosition position) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; List businesses = await _context.CouponsHeads.AsQueryable().Where(p => p.Type == "TESCP004" || p.Type == "TESCP003" && p.State == "active" && p.Expiration > DateTime.Now).Select(b => b.BusinessId).Distinct().ToListAsync(); List coupons = new List(); List declined = await _context.CouponsDeclineds.AsQueryable().Where(u => u.UserGuid == userID).Select(p => p.CouponId).ToListAsync(); List acquired = await _context.UserCouponBanks.AsQueryable().Where(u => u.UserGuid == userID).Select(p => p.CouponId).ToListAsync(); foreach (string p in businesses) { var param = new SqlParameter[] { new SqlParameter() { ParameterName = "@Status", SqlDbType = System.Data.SqlDbType.VarChar, Direction = System.Data.ParameterDirection.Input, Value = "active" }, new SqlParameter() { ParameterName = "@businessID", SqlDbType = System.Data.SqlDbType.VarChar, Direction = System.Data.ParameterDirection.Input, Value = p } }; TesoBusinessDetail tesoBusiness = await _context.TesoBusinessDetails.AsQueryable().Where(b => b.BusinessId == p).FirstOrDefaultAsync(); if (tesoBusiness != null && !String.IsNullOrEmpty(tesoBusiness.BusinessLat) && !String.IsNullOrEmpty(tesoBusiness.BusinessLng)) { Position businessPosition = new Position { Latitude = double.Parse(tesoBusiness.BusinessLat), Longitude = double.Parse(tesoBusiness.BusinessLng) }; Position position1 = new Position { Latitude = position.latitude, Longitude = position.longitude }; HaversineClass haversine = new HaversineClass(); double distance = haversine.Distance(pos1: position1, pos2: businessPosition, type: DistanceType.Miles); if (distance <= 1.0) { List cc = await _context.ProximityCoupons.FromSqlRaw("Select ch.couponID,ch.businessID as BusinessBusinessID,ch.productID as targetID,p.pname as targetName," + "p.productImage as targetImage,p.unitPrice as targetCost,p.pdescription as targetDescription,cd.condition as condition," + "ch.lowerlimit as LowerLimit,ch.upperlimit as UpperLimit, ch.expiration as Expiration,ch.businessID as BusinessID,ch.quantity as Quantity," + "ch.state as State, cT.typeName as Type from CouponsHead ch Inner Join TesoBusinessDetail b on b.businessID = ch.businessID Inner Join Products p on p.productId = ch.productID Inner Join " + "CouponTypes cT on cT.typeCode = ch.type Inner Join CouponCondition cd on cd.couponID = ch.couponID where ch.businessID = @businessID and ch.state = @Status", param).AsQueryable() .Where(d => !declined.Contains(d.CouponId) && d.Expiration > DateTime.Now && !acquired.Contains(d.CouponId) && d.Type.ToLower().Contains("proximity")) .ToListAsync(); coupons.AddRange(cc); } } } return coupons; } [Authorize] [Route("declineCoupon"), HttpPost] public async Task DeclineCoupons(CouponsHead coupon) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; CouponsDeclined declined = new CouponsDeclined(); declined.DateDeclined = DateTime.Now; declined.CouponId = coupon.CouponId; declined.UserGuid = userID; declined.CountId = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + userID; _context.CouponsDeclineds.Add(declined); try { await _context.SaveChangesAsync(); } catch (DbUpdateException) { return Conflict(); } return Ok(); } [Authorize] [Route("acceptCoupon"), HttpPost] public async Task AcceptCoupons(CouponsHead coupon) { CouponsHead head = await _context.CouponsHeads.AsQueryable().Where(d => d.CouponId == coupon.CouponId).FirstOrDefaultAsync(); if (head.Quantity > 0 && (head.Quantity - coupon.Quantity) >= 0) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; string username = jwtToken.Claims.First(claim => claim.Type == "username").Value; List banked = new List(); List couponAcquisitions = new List(); string shopName = await _context.TesoBusinessDetails.AsQueryable().Where(b => b.BusinessId == coupon.BusinessId).Select(b => b.BusinessName).FirstOrDefaultAsync(); string couponType = coupon.Type; Product product = await _context.Products.AsQueryable().Where(b => b.ProductId == coupon.TargetProduct).FirstOrDefaultAsync(); double priceDiscounted = double.Parse(product.UnitPrice.ToString()) * (coupon.LowerLimit / 100); int cost = CouponRateCalculator.GetRate(priceDiscounted); for (int i = 0; i < coupon.Quantity; i++) { CouponAcquisition acquisition = new CouponAcquisition(); acquisition.Dateacquired = DateTime.Now; acquisition.CouponId = coupon.CouponId; acquisition.UserGuid = userID; acquisition.CountId = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 100000000) + userID + i; if (couponType == "TESCP001" || couponType == "TESCP004") { acquisition.Worth = 100; } else { acquisition.Worth = coupon.LowerLimit; } acquisition.SilverCost = cost; acquisition.Mode = "purchased"; acquisition.Expiration = coupon.Expiration; couponAcquisitions.Add(acquisition); UserCouponBank bank = new UserCouponBank(); bank.CountId = coupon.CouponId + String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + userID; bank.CouponId = coupon.CouponId; bank.UserGuid = userID; if (couponType == "TESCP001" || couponType == "TESCP004") { bank.Worth = 100; bank.Expiration = DateTime.Now.AddMinutes(60); } else { bank.Worth = coupon.LowerLimit; bank.Expiration = await _context.CouponsHeads.AsQueryable().Where(i => i.CouponId == coupon.CouponId).Select(e => e.Expiration).FirstOrDefaultAsync(); } acquisition.Expiration = bank.Expiration; banked.Add(bank); } UserFinance finance = await _context.UserFinances.AsQueryable().Where(u => u.UserGUID == userID).FirstOrDefaultAsync(); finance.Silver = finance.Silver - (cost * coupon.Quantity.Value); UserTransaction transaction = new UserTransaction(); transaction.RealCash = 0; transaction.CoinType = await _context.CoinTypes.AsQueryable().Where(c => c.TypeName.ToLower().Contains("silver")).Select(s => s.TypeCode).AsNoTracking().FirstOrDefaultAsync(); ; transaction.Comments = "coupon acquisition ... coupon id " + coupon.CouponId; transaction.CoinAmount = cost * coupon.Quantity.Value; transaction.Timestamp = DateTime.Now; transaction.TransactionID = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + userID; transaction.UserGUID = userID; transaction.TransactionType = await _context.TransactionTypes.AsQueryable().Where(c => c.TypeName.ToLower().Contains("silver debit")).Select(c => c.TypeCode).AsNoTracking().FirstOrDefaultAsync(); head.Quantity -= coupon.Quantity; await SilverBankOperations.DepositToBank(transaction.CoinAmount.Value, _context); _context.CouponAcquisitions.AddRange(couponAcquisitions); _context.UserCouponBanks.AddRange(banked); _context.UserTransactions.Add(transaction); string message; string message2; if (coupon.Quantity > 1) { message = "You acquired " + coupon.Quantity + " " + couponType + " vouchers for " + product.Name + " from " + shopName + " with " + cost.ToString() + " silver coins "; message2 = username + " acquired " + coupon.Quantity + " " + couponType + " vouchers for " + product.Name + " from " + shopName; } else { message = "You acquired a " + couponType + " voucher for " + product.Name + " from " + shopName + " with " + cost.ToString() + " silver coins "; message2 = username + " acquired " + coupon.Quantity + " " + couponType + " vouchers for " + product.Name + " from " + shopName; } if (couponType == "TESCP001" || couponType == "TESCP004") message = message + "which expires in 60 minutes"; try { await _context.SaveChangesAsync(); DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(userID).Collection(userID).Document(); Dictionary user = new Dictionary { { "notificationType", "redeemable" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", message }, { "couponID", coupon.CouponId }, { "productImage", product.ProductImage }, }; DocumentReference BusdocRef = db.Collection(ServerLocation.business_notifications).Document(product.BusinessId).Collection(product.BusinessId).Document(); Dictionary Bususer = new Dictionary { { "notificationType", "couponAcquisition" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", message2 }, { "couponID", coupon.CouponId }, { "userID", userID}, }; await docRef.SetAsync(user); await BusdocRef.SetAsync(Bususer); } catch (DbUpdateException) { return Conflict(); } return Ok(message); } else { return StatusCode(999); } } [Authorize] [Route("qrCoupon"), HttpPost] public async Task>> GetShopCoupons([FromBody] string businessID) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; try { DailyVisit visit = await _context.DailyVisits.AsQueryable().Where(u => u.UserGuid == userID && u.Timestamp.Value.Month == DateTime.Now.Month && u.Timestamp.Value.Day == DateTime.Now.Day && u.Timestamp.Value.Year == DateTime.Now.Year).FirstOrDefaultAsync(); if (visit == null) { visit = new DailyVisit { BusinessId = businessID, CountId = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + userID, Timestamp = DateTime.Now, UserGuid = userID }; _context.DailyVisits.Add(visit); await _context.SaveChangesAsync(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } var param = new SqlParameter[] { new SqlParameter() { ParameterName = "@user", SqlDbType = System.Data.SqlDbType.VarChar, Direction = System.Data.ParameterDirection.Input, Value = userID }, new SqlParameter() { ParameterName = "@businessID", SqlDbType = System.Data.SqlDbType.VarChar, Direction = System.Data.ParameterDirection.Input, Value = businessID } }; string connString = ServerLocation.connection; string sprocname = "[dbo].[usp_scanqrcode_Get]"; using (SqlConnection conn = new SqlConnection(connString)) { try { string result = ""; conn.Open(); using (SqlCommand cmd = new SqlCommand(sprocname, conn)) { cmd.CommandType = System.Data.CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@userGUID", userID); cmd.Parameters.AddWithValue("@businessID", businessID); cmd.ExecuteNonQuery(); using (SqlDataReader sdr = cmd.ExecuteReader()) { while (sdr.Read()) { result += sdr[0]; } } } conn.Close(); List coupons = JsonConvert.DeserializeObject>(result); return coupons; } catch (Exception ex) { conn.Close(); return null; } } //List coupons = new List(); //List acquired = await _context.Details.FromSqlRaw("Select ch.couponID as CouponID,ch.businessID as BusinessId,ct.TypeName as Type,ch.quantity as Quantity," + // "ch.expiration as Expiration,ca.worth as Worth,ch.state as State,ch.businessID as IssuerBusinessID,ch.productID as TargetProductID,ch.lowerLimit as LowerLimit,ch.upperLimit as UpperLimit " + // ",ch.productID as ProductCost,ca.countID as CountID, cd.condition as condition From CouponsHead ch Inner Join CouponTypes ct on ch.type = ct.typeCode Inner Join UserCouponBank ca on ca.couponID = ch.couponID " + // "Inner Join Products p on p.productID = ch.productID Inner Join CouponCondition cd on ch.couponID = cd.CouponID where ca.userGUID = @user and ch.businessID = @businessID", param) // .AsQueryable().Where(e => e.Expiration > DateTime.Now && e.State == "active").ToListAsync(); //coupons.AddRange(acquired); //List shop = await _context.Details.FromSqlRaw("Select ch.couponID as CouponID,ch.businessID as BusinessId,ct.TypeName as Type,ch.quantity as Quantity," + // "ch.expiration as Expiration,(Cast(0.0 as float)) as Worth,ch.state as State,ch.businessID as IssuerBusinessID,ch.productID as TargetProductID,ch.lowerLimit as LowerLimit,ch.upperLimit as UpperLimit" + // ",ch.productID as ProductCost,'null' as CountID, cd.condition as condition From CouponsHead ch Inner Join CouponTypes ct on ch.type = ct.typeCode Inner Join Products p on p.productID = ch.productID " + // "Inner Join CouponCondition cd on ch.couponID = cd.CouponID where ch.businessID = @businessID", param).AsQueryable() // .Where(e => !acquired.Contains(e) && e.Expiration > DateTime.Now && e.State == "active").ToListAsync(); //coupons.AddRange(shop); //foreach (CouponDetails details in coupons) //{ // details.Issuer = await _context.TesoBusinessDetails.AsQueryable().Where(b => b.BusinessId == details.BusinessId).FirstOrDefaultAsync(); // details.Target = await _context.Products.AsQueryable().Where(b => b.ProductId == details.ProductCost).FirstOrDefaultAsync(); // if (String.IsNullOrEmpty(details.condition)) details.condition = "none"; //} } [Authorize] [Route("viewCoupon"), HttpPost] public async Task ViewCoupons(CouponsHead head) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; CouponDetails coupon = new CouponDetails(); coupon.BusinessId = head.BusinessId; coupon.CouponId = head.CouponId; coupon.Expiration = head.Expiration; coupon.lowerLimit = await _context.CouponsHeads.AsQueryable().Where(d => d.CouponId == head.CouponId).Select(e => e.LowerLimit).FirstOrDefaultAsync(); coupon.upperLimit = await _context.CouponsHeads.AsQueryable().Where(d => d.CouponId == head.CouponId).Select(e => e.UpperLimit).FirstOrDefaultAsync(); coupon.Quantity = head.Quantity; coupon.State = head.State; coupon.Target = await _context.Products.AsQueryable().Where(p => p.ProductId == head.TargetProduct).FirstOrDefaultAsync(); coupon.Issuer = await _context.TesoBusinessDetails.AsQueryable().Where(p => p.BusinessId == head.BusinessId).FirstOrDefaultAsync(); coupon.Type = head.Type; DocumentReference docRef = db.Collection("recentlyViewed").Document("users").Collection(userID).Document(coupon.CouponId); Dictionary user = new Dictionary { {"couponId", coupon.CouponId }, {"businessId",coupon.Issuer.BusinessId }, { "type", coupon.Type}, { "quantity", coupon.Quantity }, { "expiration",coupon.Expiration.Value.ToString("yyyy-MM-dd HH:mm:ss")}, { "worth",coupon.Worth}, { "state", coupon.State}, { "productCost", coupon.Target.UnitPrice.ToString()}, {"businessName",coupon.Issuer.BusinessName}, {"businessDescription",coupon.Issuer.BusinessDescription}, {"businessCategory",coupon.Issuer.BusinessCategory}, {"businessAddress",coupon.Issuer.BusinessAddress}, {"businessContact",coupon.Issuer.BusinessContact}, {"businessLogo",coupon.Issuer.BusinessLogo}, {"businessLat",coupon.Issuer.BusinessLat}, {"businessLng",coupon.Issuer.BusinessLng}, {"productId",coupon.Target.ProductId}, {"name",coupon.Target.Name}, {"description",coupon.Target.Description}, {"category",coupon.Target.Category}, {"unitPrice",coupon.Target.UnitPrice.ToString()}, {"productImage",coupon.Target.ProductImage}, {"lowerLimit",coupon.lowerLimit.ToString()}, {"upperLimit",coupon.upperLimit.ToString()}, {"dateViewed",new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, }; if (TrendingExists(head.TargetProduct)) { TrendingProduct trend = await _context.TrendingProducts.AsQueryable().Where(p => p.ProductId == head.TargetProduct).FirstOrDefaultAsync(); trend.Views += 1; } else { TrendingProduct trend = new TrendingProduct(); trend.ProductId = coupon.Target.ProductId; trend.Views = 1; _context.TrendingProducts.Add(trend); } try { await _context.SaveChangesAsync(); await docRef.SetAsync(user); } catch (DbUpdateException) { return StatusCode(500); } return Ok(); } [Authorize] [Route("giftCoupon"), HttpPost] public async Task GiftCoupons(CouponsHead details) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; TesoUserDetail userT = await _context.TesoUserDetails.AsQueryable().Where(u => u.UserGUID == userID).FirstOrDefaultAsync(); UserCouponBank userCoupon = await _context.UserCouponBanks.AsQueryable().Where(c => c.CountId == details.State).FirstOrDefaultAsync(); Product product = await _context.Products.AsQueryable().Where(p => p.ProductId == details.TargetProduct).FirstOrDefaultAsync(); string type = await _context.CouponsHeads.AsQueryable().Where(c => c.CouponId == details.CouponId).Select(t => t.Type).AsNoTracking().FirstOrDefaultAsync(); UserCouponBank recipient = new UserCouponBank(); recipient.CountId = details.CouponId + String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + details.Type; recipient.CouponId = details.CouponId; recipient.UserGuid = details.Type; recipient.Worth = (details.LowerLimit / 100) * userCoupon.Worth; recipient.Expiration = userCoupon.Expiration; userCoupon.Worth -= recipient.Worth; CouponAcquisition acquisition = new CouponAcquisition(); acquisition.CountId = details.CouponId + String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + details.Type; acquisition.CouponId = details.CouponId; acquisition.Dateacquired = DateTime.Now; acquisition.Expiration = userCoupon.Expiration; acquisition.Mode = "gifted"; acquisition.SilverCost = 0; acquisition.UserGuid = recipient.UserGuid; acquisition.Worth = recipient.Worth; if (userCoupon.Worth == 0 || type == "TESCP001" || type == "TESCP004") { _context.Remove(userCoupon); } _context.UserCouponBanks.Add(recipient); _context.CouponAcquisitions.Add(acquisition); try { await _context.SaveChangesAsync(); string message = ""; if (type == "TESCP001" || type == "TESCP004") { message = userT.Firstname + " " + userT.Surname + " has gifted you a " + details.BusinessId + "'s Freebie voucher for " + product.Name; } else { message = userT.Firstname + " " + userT.Surname + " has gifted you a " + details.BusinessId + "'s voucher worth " + recipient.Worth.ToString() + " % OFF for " + product.Name; } DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(recipient.UserGuid).Collection(recipient.UserGuid).Document(); Dictionary user = new Dictionary { { "notificationType", "gifted" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", message }, { "couponID", details.CouponId }, { "productImage", product.ProductImage }, { "recipient", recipient.UserGuid }, }; await docRef.SetAsync(user); } catch (Exception ex) { return BadRequest(); } return Ok(); } [Authorize] [Route("productCoupon"), HttpPost] public async Task>> GetProductCoupons([FromBody] string productID) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; List coupons = await (from c in _context.CouponsHeads.AsQueryable() join ct in _context.CouponTypes on c.Type equals ct.TypeCode join p in _context.Products on c.TargetProduct equals p.ProductId join con in _context.CouponConditions on c.CouponId equals con.CouponId into Conditions from cond in Conditions.DefaultIfEmpty() where p.ProductId == productID && c.Quantity > 0 && c.State == "active" && (c.Type == "TESCP001" || c.Type == "TESCP002") select new CouponDetails() { BusinessId = p.BusinessId, condition = cond.Condition, countID = c.CouponId, CouponId = c.CouponId, Expiration = c.Expiration, Issuer = _context.TesoBusinessDetails.AsQueryable().Where(b => b.BusinessId == p.BusinessId).FirstOrDefault(), lowerLimit = c.LowerLimit, ProductCost = p.ProductId, Quantity = c.Quantity, State = c.State, Target = p, Type = ct.TypeName, upperLimit = c.UpperLimit, Worth = 0 } ).ToListAsync(); //List coupons = await _context.Details.FromSqlRaw("Select ch.couponID as CouponID,ch.businessID as BusinessId,ct.TypeName as Type,ch.quantity as Quantity," + // "ch.expiration as Expiration,(Cast(0.0 as float)) as Worth,ch.state as State,ch.businessID as IssuerBusinessID,ch.productID as TargetProductID,ch.lowerLimit as LowerLimit,ch.upperLimit as UpperLimit" + // ",ch.productID as ProductCost,'null' as CountID, cd.condition as condition From CouponsHead ch Inner Join CouponTypes ct on ch.type = ct.typeCode Inner Join Products p on p.productID = ch.productID " + // "Inner Join CouponCondition cd on ch.couponID = cd.CouponID where ch.productID = @productID", param).AsQueryable() // .Where(e => e.Expiration > DateTime.Now && e.State == "active").ToListAsync(); //foreach (CouponDetails details in coupons) //{ // details.Issuer = await _context.TesoBusinessDetails.AsQueryable().Where(b => b.BusinessId == details.BusinessId).FirstOrDefaultAsync(); // details.Target = await _context.Products.AsQueryable().Where(b => b.ProductId == details.ProductCost).FirstOrDefaultAsync(); // if (String.IsNullOrEmpty(details.condition)) details.condition = "none"; //} return coupons; } [Route("redeemCoupon"), HttpPost] public async Task> RedeemCoupons(CouponDetails coupon) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; string username = jwtToken.Claims.First(claim => claim.Type == "username").Value; try { UserCouponBank bank = await _context.UserCouponBanks.AsQueryable().Where(u => u.UserGuid == userID && u.CouponId == coupon.CouponId).FirstOrDefaultAsync(); string type = await _context.CouponsHeads.AsQueryable().Where(c => c.CouponId == coupon.CouponId).Select(t => t.Type).AsNoTracking().FirstOrDefaultAsync(); CouponAcquisition acquiredMain = new CouponAcquisition(); CouponAcquisition acquired = await _context.CouponAcquisitions.AsQueryable().Where(u => u.UserGuid == userID && u.CouponId == coupon.CouponId).FirstOrDefaultAsync(); int calculated = 0; if (acquired.Mode == "gifted") { acquiredMain = await _context.CouponAcquisitions.AsQueryable().Where(u => u.Mode.ToLower() == "purchased" && u.CouponId == coupon.CouponId).FirstOrDefaultAsync(); int refund; if (type == "TESCP001" || type == "TESCP004") { refund = acquiredMain.SilverCost.Value; } else { double percentageWorth = (acquired.Worth.Value / acquiredMain.Worth.Value); calculated = RedemptionReturn.CalculateReturns(acquired.SilverCost.Value); refund = (int)Math.Round((calculated - (calculated / percentageWorth) * 100), MidpointRounding.ToPositiveInfinity); } if (refund > 0) { UserFinance finance = await _context.UserFinances.AsQueryable().Where(u => u.UserGUID == acquiredMain.UserGuid).FirstOrDefaultAsync(); finance.Silver += refund; } UserTransaction transaction = new UserTransaction(); transaction.RealCash = 0; transaction.CoinType = await _context.CoinTypes.AsQueryable().Where(c => c.TypeName.ToLower().Contains("silver")).Select(s => s.TypeCode).AsNoTracking().FirstOrDefaultAsync(); ; transaction.Comments = "coupon redemption ... coupon id " + coupon.CouponId; transaction.CoinAmount = refund; transaction.Timestamp = DateTime.Now; transaction.TransactionID = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + userID; transaction.UserGUID = userID; transaction.TransactionType = await _context.TransactionTypes.AsQueryable().Where(c => c.TypeName.ToLower().Contains("silver credit")).Select(c => c.TypeCode).AsNoTracking().FirstOrDefaultAsync(); _context.UserTransactions.Add(transaction); bool possible = await SilverBankOperations.WithdrawFromBank(refund, _context); if (!possible) return StatusCode(500); } else { if (type == "TESCP001" || type == "TESCP004" || type == "TESCP005" || type == "TESCP006") { calculated = acquired.SilverCost.Value; } else { calculated = RedemptionReturn.CalculateReturns(acquired.SilverCost.Value); } UserFinance finance = await _context.UserFinances.AsQueryable().Where(u => u.UserGUID == acquired.UserGuid).FirstOrDefaultAsync(); finance.Silver += calculated; UserTransaction transaction = new UserTransaction(); transaction.RealCash = 0; transaction.CoinType = await _context.CoinTypes.AsQueryable().Where(c => c.TypeName.ToLower().Contains("silver")).Select(s => s.TypeCode).AsNoTracking().FirstOrDefaultAsync(); ; transaction.Comments = "coupon redemption ... coupon id " + coupon.CouponId; transaction.CoinAmount = calculated; transaction.Timestamp = DateTime.Now; transaction.TransactionID = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + userID; transaction.UserGUID = userID; transaction.TransactionType = await _context.TransactionTypes.AsQueryable().Where(c => c.TypeName.ToLower().Contains("silver credit")).Select(c => c.TypeCode).AsNoTracking().FirstOrDefaultAsync(); _context.UserTransactions.Add(transaction); bool possible = await SilverBankOperations.WithdrawFromBank(calculated, _context); if (!possible) return StatusCode(500); } double price = double.Parse(coupon.Target.UnitPrice.Value.ToString()); double worth = price - (price * bank.Worth.Value / 100); CouponRedemption redeemed = new CouponRedemption { CountId = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + userID, CouponId = coupon.CouponId, Discount = bank.Worth, UserGuid = userID, Timestamp = DateTime.Now, Worth = decimal.Parse(worth.ToString()) }; DailyVisit visit = await _context.DailyVisits.AsQueryable().Where(u => u.UserGuid == userID && u.Timestamp.Value.Month == DateTime.Now.Month && u.Timestamp.Value.Day == DateTime.Now.Day && u.Timestamp.Value.Year == DateTime.Now.Year).FirstOrDefaultAsync(); if (visit == null) { visit = new DailyVisit { BusinessId = coupon.BusinessId, CountId = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + userID, Timestamp = DateTime.Now, UserGuid = userID }; _context.DailyVisits.Add(visit); } _context.UserCouponBanks.Remove(bank); _context.CouponRedemptions.Add(redeemed); await _context.SaveChangesAsync(); if (acquired.Mode == "gifted") { DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(acquiredMain.UserGuid).Collection(acquiredMain.UserGuid).Document(); Dictionary user = new Dictionary { { "notificationType", "gifted" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", username + " redeemed a coupon you gifted them therefore you get silver coins back" }, { "couponID", coupon.CouponId }, { "productImage", coupon.Target.ProductImage }, { "recipient", acquiredMain.UserGuid }, }; DocumentReference docRef1 = db.Collection(ServerLocation.user_notifications).Document(userID).Collection(userID).Document(); Dictionary user1 = new Dictionary { { "notificationType", "redeemable" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", "You successfully redeemed a coupon" }, { "couponID", coupon.CouponId }, { "productImage", coupon.Target.ProductImage }, }; await docRef.SetAsync(user); await docRef1.SetAsync(user1); } else { DocumentReference docRef1 = db.Collection(ServerLocation.user_notifications).Document(userID).Collection(userID).Document(); Dictionary user1 = new Dictionary { { "notificationType", "redeemable" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", "You successfully redeemed a coupon" }, { "couponID", coupon.CouponId }, { "productImage", coupon.Target.ProductImage }, }; await docRef1.SetAsync(user1); } if (coupon.BusinessId == ServerLocation.tesoghanaID) { string businessMessage = username + " just redeemed a coupon from the shop"; DocumentReference BusdocRef = db.Collection(ServerLocation.business_notifications).Document(coupon.Issuer.BusinessId).Collection(coupon.Issuer.BusinessId).Document(); Dictionary Bususer = new Dictionary { { "notificationType", "couponRedemption" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", businessMessage }, { "couponID", coupon.CouponId }, { "userID", userID}, }; string businessMessageTeso = username + " just redeemed a coupon at " + coupon.Issuer.BusinessName; DocumentReference BusdocRef2 = db.Collection(ServerLocation.business_notifications).Document(coupon.BusinessId).Collection(coupon.BusinessId).Document(); Dictionary Bususer2 = new Dictionary { { "notificationType", "couponRedemption" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", businessMessageTeso }, { "couponID", coupon.CouponId }, { "userID", userID}, }; await BusdocRef2.SetAsync(Bususer2); await BusdocRef.SetAsync(Bususer); } else { string businessMessage = username + " just redeemed a coupon from the shop"; DocumentReference BusdocRef = db.Collection(ServerLocation.business_notifications).Document(coupon.Issuer.BusinessId).Collection(coupon.Issuer.BusinessId).Document(); Dictionary Bususer = new Dictionary { { "notificationType", "couponRedemption" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", businessMessage }, { "couponID", coupon.CouponId }, { "userID", userID}, }; await BusdocRef.SetAsync(Bususer); } return Ok(calculated); } catch (DbUpdateException) { return Conflict(); } } [Authorize] [Route("acceptPersonalized"), HttpPost] public async Task AcceptPerosnalizedCoupons(CouponsHead coupon) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; string username = jwtToken.Claims.First(claim => claim.Type == "username").Value; string shopname = await _context.TesoBusinessDetails.AsQueryable().Where(i => i.BusinessId == coupon.BusinessId).Select(n => n.BusinessName).FirstOrDefaultAsync(); Product product = await _context.Products.AsQueryable().Where(p => p.ProductId == coupon.TargetProduct).FirstOrDefaultAsync(); DocumentReference deleteRef = db.Collection(ServerLocation.user_notifications).Document(userID).Collection(userID).Document(coupon.CouponId); if (coupon.Expiration > DateTime.Now) { CouponsHead couponsHead = new CouponsHead(); couponsHead.BusinessId = coupon.BusinessId; couponsHead.CouponId = "TESCP" + String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + coupon.BusinessId; couponsHead.Expiration = coupon.Expiration; couponsHead.Quantity = 1; couponsHead.State = "active"; couponsHead.TargetProduct = coupon.TargetProduct; couponsHead.Type = coupon.Type; couponsHead.LowerLimit = coupon.LowerLimit; couponsHead.UpperLimit = coupon.UpperLimit; couponsHead.Generated = coupon.Generated; CouponCondition condition = new CouponCondition(); condition.CouponId = couponsHead.CouponId; if (!String.IsNullOrEmpty(coupon.State)) { condition.Condition = coupon.State; } else { condition.Condition = "none"; } _context.CouponAcquisitions.Add(new CouponAcquisition { CountId = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 100000000) + userID, CouponId = couponsHead.CouponId, Dateacquired = DateTime.Now, Expiration = coupon.Expiration, Mode = "personalized", SilverCost = 0, UserGuid = userID, Worth = couponsHead.UpperLimit, }); _context.UserCouponBanks.Add(new UserCouponBank { CountId = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 100000000) + userID, CouponId = couponsHead.CouponId, Expiration = coupon.Expiration, Worth = couponsHead.UpperLimit, UserGuid = userID }); _context.CouponsHeads.Add(couponsHead); _context.CouponConditions.Add(condition); try { await _context.SaveChangesAsync(); DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(userID).Collection(userID).Document(); Dictionary user = new Dictionary { { "notificationType", "redeemable" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", $"Congrats you just accepted a personalized coupon from {shopname}" }, { "couponID", coupon.CouponId }, { "productImage", product.ProductImage }, }; DocumentReference BusdocRef = db.Collection(ServerLocation.business_notifications).Document(product.BusinessId).Collection(product.BusinessId).Document(); Dictionary Bususer = new Dictionary { { "notificationType", "couponAcquisition" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "message", $"{username} just accepted a personalized coupon you sent them!!" }, { "couponID", couponsHead.CouponId }, { "userID", userID}, }; await docRef.SetAsync(user); await deleteRef.DeleteAsync(); await BusdocRef.SetAsync(Bususer); } catch (Exception e) { Console.WriteLine(e.ToString()); return StatusCode(500); } return Ok(); } else { await deleteRef.DeleteAsync(); return StatusCode(400); } } [Authorize] [Route("campaign_coupons"), HttpPost] public async Task>> GetCampaignCoupons([FromBody] string campaignID) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; List coupons = await (from c in _context.CouponsHeads.AsQueryable() join ct in _context.CouponTypes on c.Type equals ct.TypeCode join cam in _context.Campaigns on c.TargetProduct equals cam.TargetProduct into campaignList from campaignItem in campaignList.DefaultIfEmpty() join p in _context.Products on campaignItem.TargetProduct equals p.ProductId join con in _context.CouponConditions on c.CouponId equals con.CouponId where campaignItem.CampaignId == campaignID && c.Quantity > 0 && c.State == "active" && (c.Type == "TESCP001" || c.Type == "TESCP002") select new CouponDetails() { BusinessId = campaignItem.BusinessId, condition = con.Condition, countID = c.CouponId, CouponId = c.CouponId, Expiration = c.Expiration, Issuer = _context.TesoBusinessDetails.AsQueryable().Where(b => b.BusinessId == campaignItem.BusinessId).FirstOrDefault(), lowerLimit = c.LowerLimit, ProductCost = p.ProductId, Quantity = c.Quantity, State = c.State, Target = p, Type = ct.TypeName, upperLimit = c.UpperLimit, Worth = 0 } ).ToListAsync(); return coupons; } private bool TrendingExists(string id) { return _context.TrendingProducts.Any(e => e.ProductId == id); } } }