public async Task <PlaceBidResult> PlaceBidAsync(PlaceBidRequest bidRequest) { var result = new PlaceBidResult(); if (!bidRequest.Event.IsBiddingOpen(DateTime.Now)) { result.ResultType = PlaceBidResultType.BiddingClosed; return(result); } if (bidRequest.Amount < bidRequest.Product.NextMinBidAmount) { result.ResultType = PlaceBidResultType.InvalidAmount; return(result); } try { var previousBid = await GetLatestBidAsync(bidRequest.Product.Id); var bid = new Bid { Product = bidRequest.Product, User = bidRequest.User, Timestamp = DateTime.Now, Amount = bidRequest.Amount }; _dbContext.Bids.Add(bid); await _dbContext.SaveChangesAsync(); bidRequest.Product.CurrentBidAmount = bid.Amount; bidRequest.Product.CurrentHighBidUserId = bidRequest.User.Id; bidRequest.Product.BidCount++; _dbContext.Products.Update(bidRequest.Product); await _dbContext.SaveChangesAsync(); result.ResultType = PlaceBidResultType.Success; result.BidId = bid.Id; await _hubContext.Clients.All.SendAsync("BidPlaced", bidRequest.Product.Name, bidRequest.Amount); if (previousBid != null && previousBid.UserId != bidRequest.User.Id) { await SendOutbidNoticeAsync(bidRequest.Event, bidRequest.Product, previousBid, bid); } return(result); } catch (Exception ex) { _logger.LogError(ex, "Error placing bid for product ID {id} (User: {userId})", bidRequest.Product.Id, bidRequest.User.Id); throw ex; } }
public async Task <IActionResult> Create(string evtSlug, EventUserListViewModel model) { var evt = await _dbContext.Events.SingleOrDefaultAsync(x => x.Slug == evtSlug); if (evt == null) { _logger.LogInformation("Event with slug '{slug}' not found", evtSlug); return(NotFound()); } try { var user = await _userManager.FindByEmailAsync(model.NewUserEmail); if (user == null) { ModelState.AddModelError("NewUserEmail", "User with this email does not exist."); return(await Index(evtSlug)); } var existingUser = await _dbContext.EventUsers.SingleOrDefaultAsync(x => x.EventId == evt.Id && x.UserId == user.Id); if (existingUser != null) { ModelState.AddModelError("NewUserEmail", "User is alredy a member of this event."); return(await Index(evtSlug)); } var evtUser = new EventUser { Event = evt, User = user, IsAdmin = model.NewUserIsAdmin, CreatedOn = DateTime.Now }; _dbContext.EventUsers.Add(evtUser); await _dbContext.SaveChangesAsync(); return(RedirectToAction(nameof(Index), new { slug = evtSlug })); } catch (Exception ex) { _logger.LogError(ex, "Error adding user '{user}' to event {id}", model.NewUserEmail, evt.Id); ModelState.AddModelError("", "Error adding user to event"); return(await Index(evtSlug)); } }
public async Task <IActionResult> BuyNow([FromBody] BuyNowModel model) { var product = await _dbContext.Products.FindAsync(model.ProductId); if (product == null) { _logger.LogInformation("Product {productId} not found", model.ProductId); return(NotFound()); } if (!product.BuyItNowPrice.HasValue) { return(BadRequest("Buy it now not enabled for specified product.")); } var evt = await _dbContext.Events.FindAsync(product.EventId); if (evt == null) { _logger.LogInformation("Event {eventId} not found", product.EventId); return(NotFound()); } var user = await _userManager.GetUserAsync(User); if (product.IsPurchased) { return(BadRequest("Product has already been purchased.")); } try { var placeBidRequest = new PlaceBidRequest { Event = evt, Product = product, User = user, Amount = product.BuyItNowPrice.Value }; var bidResult = await _bidService.PlaceBidAsync(placeBidRequest); // TODO: probably would be wise to move this into the BidService product.PurchasedDate = DateTime.UtcNow; product.PurchasedUserId = user.Id; _dbContext.Products.Update(product); await _dbContext.SaveChangesAsync(); return(Created("", null)); } catch (Exception ex) { _logger.LogError(ex, "Error procesing buy it now for product ID {id}", model.ProductId); return(StatusCode(500)); } }
public async Task <IActionResult> Create(EditEventViewModel model) { if (!ModelState.IsValid) { return(View(model)); } if (!(await _authorizationService.AuthorizeAsync(User, Policies.Admin)).Succeeded) { return(Forbid()); } try { var user = await _userManager.GetUserAsync(User); var evt = new Event { Name = model.Name, Description = model.Description, StartOn = model.StartOn, EndOn = model.EndOn, DisplayOn = model.DisplayOn, HideBidderNames = model.HideBidderNames, DefaultMinimumBidAmount = model.DefaultMinimumBidAmount, Owner = user, CreatedOn = DateTime.UtcNow }; evt.Slug = await GenerateSlug(evt.Name); _dbContext.Events.Add(evt); await _dbContext.SaveChangesAsync(); return(RedirectToAction(nameof(Index))); } catch (Exception ex) { _logger.LogError(ex, "Error creating event '{name}'", model.Name); return(View(model)); } }
public async Task <IActionResult> Create(string evtSlug, EditProductViewModel model) { var evt = await _dbContext.Events.SingleOrDefaultAsync(x => x.Slug == evtSlug); var user = await _userManager.GetUserAsync(User); if (!ModelState.IsValid) { return(View(model)); } if (evt == null) { _logger.LogInformation("Could not find event with slug '{slug}'", evtSlug); return(RedirectToAction("Index", "Events")); } if (!(await _authorizationService.AuthorizeAsync(User, evt, Policies.EventAdmin)).Succeeded) { return(Forbid()); } // Reset event props in case something fails... model.EventId = evt.Id; model.EventSlug = evt.Slug; model.EventName = evt.Name; try { var product = new Product { Event = evt, Name = model.Name, Description = model.Description, StartingPrice = model.StartingPrice, MinimumBidAmount = model.MinimumBidAmount, CurrentBidAmount = model.StartingPrice, BuyItNowPrice = model.BuyItNowPrice }; product.Slug = await GenerateSlugAsync(evt.Id, product.Name); _dbContext.Products.Add(product); await _dbContext.SaveChangesAsync(); // Save images after the product is created because we need the ID if (model.ImageFile != null) { product.ImageFilename = GenerateImageFilename(product, model.ImageFile.FileName); var imagePath = string.Format(Constants.ImagePathFormat, evt.Slug, product.ImageFilename); using (var stream = model.ImageFile.OpenReadStream()) { await _fileService.SaveFileAsync(imagePath, model.ImageFile.ContentType, stream); } _dbContext.Products.Update(product); await _dbContext.SaveChangesAsync(); } if (model.ThumbnailFile != null) { product.ThumbnailFilename = GenerateImageFilename(product, model.ThumbnailFile.FileName, true); var imagePath = string.Format(Constants.ImagePathFormat, evt.Slug, product.ThumbnailFilename); using (var stream = model.ThumbnailFile.OpenReadStream()) { await _fileService.SaveFileAsync(imagePath, model.ThumbnailFile.ContentType, stream); } _dbContext.Products.Update(product); await _dbContext.SaveChangesAsync(); } return(RedirectToAction("Details", "Events", new { slug = evtSlug })); } catch (Exception ex) { _logger.LogError(ex, "Error adding product '{name}' to event ID {evtId}", model.Name, evt.Id); return(View(model)); } }