/// <summary> /// The render subject. /// </summary> /// <param name="model"> /// The model. /// </param> /// <returns> /// The <see cref="string"/>. /// </returns> private string RenderSubject(DailyDealsContract model) { string subject = null; if (model != null && model.Deals != null && model.Deals.Any()) { DealContract contract = model.Deals.First(); if (contract.DealType == DealType.CardLinked) { if (contract.CardLinkInfos.Any() && (!string.IsNullOrEmpty(contract.CardLinkInfos[0].DiscountAmount) || !string.IsNullOrEmpty(contract.CardLinkInfos[0].Discount)) && !string.IsNullOrEmpty(contract.BusinessName)) { subject = string.Format("Save {0} at {1}", !string.IsNullOrEmpty(contract.CardLinkInfos[0].DiscountAmount) ? contract.CardLinkInfos[0].DiscountAmount : contract.CardLinkInfos[0].Discount, contract.BusinessName); } } else { if (!string.IsNullOrEmpty(contract.Discount) && !string.IsNullOrEmpty(contract.BusinessName)) { subject = string.Format("Save {0} at {1}", contract.Discount, contract.BusinessName); } } if (string.IsNullOrEmpty(subject)) { subject = model.Deals.First().Title; } } return(subject); }
/// <summary> /// Generate Email Model method /// </summary> /// <returns> The <see cref="DealsEmailModel"/>. </returns> /// <exception cref="ModelContentException"> The input is insufficient for email model creation </exception> public DailyDealsContract GenerateModel(EmailTemplateData modelData) { DailyDealsContract dailyDealsContract = null; DealsTemplateData dailyDealsModelData = modelData as DealsTemplateData; if (dailyDealsModelData != null) { var dealsList = dailyDealsModelData.Deals == null ? null : dailyDealsModelData.Deals.ToList(); DealContract[] dealsContract = null; if (dealsList != null) { if (dailyDealsModelData.DealEmailType == DealEmailType.WeeklyDeal && dealsList.Count() <= 3) { throw new ModelContentException(string.Format("Number of deals is: {0}. This is insufficient for email model creation", dealsList.Count())); } dealsContract = new DealContract[dealsList.Count]; for (int i = 0; i < dealsList.Count; ++i) { DealContract dealContract = ConvertDeal(dealsList[i]); if (dealContract != null) { dealsContract[i] = dealContract; } } if (dailyDealsModelData.DealEmailType == DealEmailType.WeeklyDeal && dealsContract.Length <= 3) { throw new ModelContentException(string.Format("Number of deals is: {0}. This is insufficient for email model creation", dealsList.Count())); } } var location = Users.Dal.DataModel.Location.Parse(dailyDealsModelData.LocationId); var locationStr = string.Empty; if (location.Type == LocationType.Postal || location.Type == LocationType.City) { Log.Info("Getting Location for user: {0}, locationId: {1}", dailyDealsModelData.EmailAddress, dailyDealsModelData.LocationId); var geoCodePoint = GeoSpatial.GetGeoData(WebUtility.HtmlEncode(string.Format("{0} {1} {2}", location.CountryCode, location.AdminDistrict, location.Value)), GeoSpatial.GeoSource.VirtualEarth); if (geoCodePoint != null && geoCodePoint.Location != null) { locationStr = geoCodePoint.Location.Locality; Log.Info("Retrieved Location info : {0} for user: {1}, locationId: {2}", locationStr, dailyDealsModelData.EmailAddress, dailyDealsModelData.LocationId); } else { Log.Warn("Couldn't fetch location data for user: {0}, locationId: {1}", dailyDealsModelData.EmailAddress, location); } } dailyDealsContract = new DailyDealsContract { UnsubscribeUrl = dailyDealsModelData.UnsubscribeUrl, Deals = dealsContract, Location = locationStr }; } return(dailyDealsContract); }
private void SendPositionHistoryEvent(Position position, PositionHistoryTypeContract historyType, decimal chargedPnl, string orderAdditionalInfo, Order dealOrder = null, decimal?dealVolume = null, PositionOpenMetadata metadata = null) { DealContract deal = null; if (dealOrder != null && dealVolume != null) { var sign = position.Volume > 0 ? 1 : -1; var accountBaseAssetAccuracy = AssetsConstants.DefaultAssetAccuracy; var fpl = Math.Round((dealOrder.ExecutionPrice.Value - position.OpenPrice) * dealOrder.FxRate * dealVolume.Value * sign, accountBaseAssetAccuracy); var balanceDelta = fpl - Math.Round(chargedPnl, accountBaseAssetAccuracy); var dealId = historyType == PositionHistoryTypeContract.Close ? position.Id : _identityGenerator.GenerateAlphanumericId(); deal = new DealContract { DealId = dealId, PositionId = position.Id, Volume = dealVolume.Value, Created = dealOrder.Executed.Value, OpenTradeId = position.OpenTradeId, OpenOrderType = position.OpenOrderType.ToType <OrderTypeContract>(), OpenOrderVolume = position.OpenOrderVolume, OpenOrderExpectedPrice = position.ExpectedOpenPrice, CloseTradeId = dealOrder.Id, CloseOrderType = dealOrder.OrderType.ToType <OrderTypeContract>(), CloseOrderVolume = dealOrder.Volume, CloseOrderExpectedPrice = dealOrder.Price, OpenPrice = position.OpenPrice, OpenFxPrice = position.OpenFxPrice, ClosePrice = dealOrder.ExecutionPrice.Value, CloseFxPrice = dealOrder.FxRate, Fpl = fpl, PnlOfTheLastDay = balanceDelta, AdditionalInfo = dealOrder.AdditionalInfo, Originator = dealOrder.Originator.ToType <OriginatorTypeContract>() }; var account = _accountsCacheService.Get(position.AccountId); _cqrsSender.PublishEvent(new PositionClosedEvent(account.Id, account.ClientId, deal.DealId, position.AssetPairId, balanceDelta)); _accountUpdateService.FreezeUnconfirmedMargin(position.AccountId, deal.DealId, balanceDelta) .GetAwaiter().GetResult(); //todo consider making this async or pass to broker } var positionContract = _convertService.Convert <Position, PositionContract>(position, o => o.ConfigureMap(MemberList.Destination).ForMember(x => x.TotalPnL, c => c.Ignore())); positionContract.TotalPnL = position.GetFpl(); var historyEvent = new PositionHistoryEvent { PositionSnapshot = positionContract, Deal = deal, EventType = historyType, Timestamp = _dateService.Now(), ActivitiesMetadata = metadata?.ToJson(), OrderAdditionalInfo = orderAdditionalInfo, }; _rabbitMqNotifyService.PositionHistory(historyEvent); }
/// <summary> /// The convert deal. /// </summary> /// <param name="deal"> /// The deal. /// </param> /// <returns> /// The <see cref="DealContract"/>. /// </returns> private DealContract ConvertDeal(Deal deal) { DealContract dealContract = new DealContract { Id = deal.Id, BusinessName = deal.Business == null ? string.Empty : deal.Business.Name, Description = deal.Description, DealType = deal.DealType == 7 ? DealType.CardLinked : DealType.Prepaid, // TODO - fix when email will be international Price = deal.Price <= 0 ? string.Empty : Math.Ceiling(deal.Price).ToString("C0", CultureInfo.CreateSpecificCulture("en-US")), OriginalPrice = deal.DealInfo == null || deal.DealInfo.VoucherValue <= 0 ? string.Empty : Math.Ceiling(deal.DealInfo.VoucherValue).ToString("C0", CultureInfo.CreateSpecificCulture("en-US")), Title = deal.Title, TransactionUrl = deal.TransactionUrl, LargeImageUrl = deal.ImageUrl + "&size=12", MediumImageUrl = deal.ImageUrl + "&size=4", // TODO - add this information when we are getting it from the ingestion Website = string.Empty }; if (dealContract.DealType == DealType.CardLinked && deal.CardLinkInfos != null && deal.CardLinkInfos.Any()) { dealContract.Attribution = null; //omit the attribution for clo deals for now dealContract.CardLinkInfos = new CardLinkInfo[deal.CardLinkInfos.Count]; for (int i = 0; i < deal.CardLinkInfos.Count; i++) { dealContract.CardLinkInfos[i] = new CardLinkInfo { MinimumSpend = deal.CardLinkInfos[i].MinimumPurchase <= 0 ? string.Empty : string.Format("{0}+", Math.Ceiling(deal.CardLinkInfos[i].MinimumPurchase) .ToString("C0", CultureInfo.CreateSpecificCulture("en-US"))), DiscountAmount = deal.CardLinkInfos[i].DiscountAmount <= 0 ? string.Empty : string.Format("{0}", Math.Ceiling(deal.CardLinkInfos[i].DiscountAmount) .ToString("C0", CultureInfo.CreateSpecificCulture("en-US"))), Discount = deal.CardLinkInfos[i].DiscountPercent <= 0 ? string.Empty : string.Format("{0}%", deal.CardLinkInfos[i].DiscountPercent.ToString("F0", CultureInfo .InvariantCulture)) }; } //If it's a CLO, check to see if there's either a discount or discountamount bool validDeal = dealContract.CardLinkInfos.Any(cardlinkInfo => !string.IsNullOrEmpty(cardlinkInfo.Discount) || !string.IsNullOrEmpty(cardlinkInfo.DiscountAmount)); //If it's not a valid deal, return null so that this deal is not included in the deals email. if (!validDeal) { dealContract = null; } } else if (dealContract.DealType == DealType.Prepaid && deal.DealInfo != null) { dealContract.Attribution = deal.Attribution; dealContract.Discount = deal.DealInfo.VoucherDiscountPercent <= 0 ? string.Empty : string.Format("{0}%", deal.DealInfo.VoucherDiscountPercent.ToString("F0", CultureInfo.InvariantCulture)); //If the discount is missing for the PrePaid deal, return null so that this deal is not included in the deals email. if (string.IsNullOrEmpty(dealContract.Discount)) { dealContract = null; } } return(dealContract); }