public static OfferDto CreateNew(RioDbContext dbContext, int postingID, OfferUpsertDto offerUpsertDto) { if (!offerUpsertDto.TradeID.HasValue) { var trade = Trade.CreateNew(dbContext, postingID, offerUpsertDto.CreateAccountID); offerUpsertDto.TradeID = trade.TradeID; } var offer = new Offer { TradeID = offerUpsertDto.TradeID.Value, OfferNotes = offerUpsertDto.OfferNotes, CreateAccountID = offerUpsertDto.CreateAccountID, OfferDate = DateTime.UtcNow, Price = offerUpsertDto.Price, Quantity = offerUpsertDto.Quantity, OfferStatusID = offerUpsertDto.OfferStatusID }; dbContext.Offer.Add(offer); dbContext.SaveChanges(); dbContext.Entry(offer).Reload(); return(GetByOfferID(dbContext, offer.OfferID)); }
public IActionResult New([FromRoute] int postingID, [FromBody] OfferUpsertDto offerUpsertDto) { if (!_rioConfiguration.ALLOW_TRADING) { return(BadRequest()); } var posting = Posting.GetByPostingID(_dbContext, postingID); if (!ModelState.IsValid) { return(BadRequest(ModelState)); } if ((posting.PostingType.PostingTypeID == (int)PostingTypeEnum.OfferToSell) && (offerUpsertDto.OfferStatusID == (int)OfferStatusEnum.Pending || offerUpsertDto.OfferStatusID == (int)OfferStatusEnum.Accepted) && posting.AvailableQuantity < offerUpsertDto.Quantity) { ModelState.AddModelError("Quantity", "Exceeds remaining balance in posting"); return(BadRequest(ModelState)); } if (offerUpsertDto.OfferStatusID != (int)OfferStatusEnum.Rescinded && Posting.HasOpenOfferByAccountID(_dbContext, posting, offerUpsertDto.CreateAccountID)) { ModelState.AddModelError("Posting", "You currently have an open offer on this posting. Please wait until the other party responds to the current offer."); return(BadRequest(ModelState)); } var offer = Offer.CreateNew(_dbContext, postingID, offerUpsertDto); var smtpClient = HttpContext.RequestServices.GetRequiredService <SitkaSmtpClientService>(); var currentTrade = Trade.GetByTradeID(_dbContext, offer.Trade.TradeID); var rioUrl = _rioConfiguration.WEB_URL; // update trades status if needed switch (offerUpsertDto.OfferStatusID) { case (int)OfferStatusEnum.Accepted: var tradeDto = Trade.Update(_dbContext, offer.Trade.TradeID, TradeStatusEnum.Accepted); // write a water transfer record var waterTransfer = WaterTransfer.CreateNew(_dbContext, offer, tradeDto, posting); offer.WaterTransferID = waterTransfer.WaterTransferID; var mailMessages = GenerateAcceptedOfferEmail(rioUrl, offer, currentTrade, posting, waterTransfer, smtpClient); foreach (var mailMessage in mailMessages) { SendEmailMessage(smtpClient, mailMessage); } break; case (int)OfferStatusEnum.Rejected: UpdateTradeStatusSendEmail(offer, smtpClient, GenerateRejectedOfferEmail(rioUrl, offer, currentTrade, posting, smtpClient), TradeStatusEnum.Rejected); break; case (int)OfferStatusEnum.Rescinded: UpdateTradeStatusSendEmail(offer, smtpClient, GenerateRescindedOfferEmail(rioUrl, offer, currentTrade, posting, smtpClient), TradeStatusEnum.Rescinded); break; default: SendEmailMessage(smtpClient, GeneratePendingOfferEmail(rioUrl, currentTrade, offer, posting, smtpClient)); break; } // get current balance of posting var acreFeetOfAcceptedTrades = Posting.CalculateAcreFeetOfAcceptedTrades(_dbContext, postingID); var postingStatusToUpdateTo = (int)PostingStatusEnum.Open; if (posting.Quantity == acreFeetOfAcceptedTrades) { postingStatusToUpdateTo = (int)PostingStatusEnum.Closed; // expire all other outstanding offers var postingCreateAccountID = posting.CreateAccount.AccountID; var activeTradesForPosting = Trade.GetPendingTradesForPostingID(_dbContext, postingID).ToList(); foreach (var activeTrade in activeTradesForPosting) { var offerStatus = activeTrade.OfferCreateAccount.AccountID == postingCreateAccountID ? OfferStatusEnum.Rescinded : OfferStatusEnum.Rejected; var offerUpsertDtoForRescindReject = new OfferUpsertDto { TradeID = activeTrade.TradeID, Price = activeTrade.Price, CreateAccountID = postingCreateAccountID, Quantity = activeTrade.Quantity, OfferStatusID = (int)offerStatus, OfferNotes = $"Offer {offerStatus} because original posting is now closed" }; var resultingOffer = Offer.CreateNew(_dbContext, postingID, offerUpsertDtoForRescindReject); switch (offerStatus) { case OfferStatusEnum.Rejected: UpdateTradeStatusSendEmail(resultingOffer, smtpClient, GenerateRejectedOfferEmail(rioUrl, resultingOffer, Trade.GetByTradeID(_dbContext, activeTrade.TradeID), posting, smtpClient), TradeStatusEnum.Rejected); break; case OfferStatusEnum.Rescinded: UpdateTradeStatusSendEmail(resultingOffer, smtpClient, GenerateRescindedOfferEmail(rioUrl, resultingOffer, Trade.GetByTradeID(_dbContext, activeTrade.TradeID), posting, smtpClient), TradeStatusEnum.Rescinded); break; } } } Posting.UpdateStatus(_dbContext, postingID, new PostingUpdateStatusDto { PostingStatusID = postingStatusToUpdateTo }, posting.Quantity - acreFeetOfAcceptedTrades); return(Ok(offer)); }