/// <summary> /// Gets the summary of subscriptions for a portal customer. /// </summary> /// <param name="customerId">The customer Id.</param> /// <returns>Subscription Summary.</returns> private async Task <SubscriptionsSummary> GetSubscriptionSummaryAsync(string customerId) { DateTime startTime = DateTime.Now; IEnumerable <CustomerSubscriptionEntity> customerSubscriptions = await ApplicationDomain.Instance.CustomerSubscriptionsRepository.RetrieveAsync(customerId).ConfigureAwait(false); IEnumerable <CustomerPurchaseEntity> customerSubscriptionsHistory = await ApplicationDomain.Instance.CustomerPurchasesRepository.RetrieveAsync(customerId).ConfigureAwait(false); IEnumerable <PartnerOffer> allPartnerOffers = await ApplicationDomain.Instance.OffersRepository.RetrieveAsync().ConfigureAwait(false); IEnumerable <MicrosoftOffer> currentMicrosoftOffers = await ApplicationDomain.Instance.OffersRepository.RetrieveMicrosoftOffersAsync().ConfigureAwait(false); // start building the summary. decimal summaryTotal = 0; // format all responses to client using portal locale. CultureInfo responseCulture = new CultureInfo(ApplicationDomain.Instance.PortalLocalization.Locale); List <SubscriptionViewModel> customerSubscriptionsView = new List <SubscriptionViewModel>(); // iterate through and build the list of customer's subscriptions. foreach (CustomerSubscriptionEntity subscription in customerSubscriptions) { decimal subscriptionTotal = 0; int licenseTotal = 0; List <SubscriptionHistory> historyItems = new List <SubscriptionHistory>(); // collect the list of history items for this subcription. IOrderedEnumerable <CustomerPurchaseEntity> subscriptionHistoryList = customerSubscriptionsHistory .Where(historyItem => historyItem.SubscriptionId == subscription.SubscriptionId) .OrderBy(historyItem => historyItem.TransactionDate); // iterate through and build the SubsriptionHistory for this subscription. foreach (CustomerPurchaseEntity historyItem in subscriptionHistoryList) { decimal orderTotal = Math.Round(historyItem.SeatPrice * historyItem.SeatsBought, responseCulture.NumberFormat.CurrencyDecimalDigits); historyItems.Add(new SubscriptionHistory() { OrderTotal = orderTotal.ToString("C", responseCulture), // Currency format. PricePerSeat = historyItem.SeatPrice.ToString("C", responseCulture), // Currency format. SeatsBought = historyItem.SeatsBought.ToString("G", responseCulture), // General format. OrderDate = historyItem.TransactionDate.ToLocalTime().ToString("d", responseCulture), // Short date format. OperationType = GetOperationType(historyItem.PurchaseType) // Localized Operation type string. }); // Increment the subscription total. licenseTotal += historyItem.SeatsBought; // Increment the subscription total. subscriptionTotal += orderTotal; } PartnerOffer partnerOfferItem = allPartnerOffers.FirstOrDefault(offer => offer.Id == subscription.PartnerOfferId); string subscriptionTitle = partnerOfferItem.Title; string portalOfferId = partnerOfferItem.Id; decimal portalOfferPrice = partnerOfferItem.Price; DateTime subscriptionExpiryDate = subscription.ExpiryDate.ToUniversalTime(); int remainingDays = (subscriptionExpiryDate.Date - DateTime.UtcNow.Date).Days; bool isRenewable = remainingDays <= 30; bool isEditable = DateTime.UtcNow.Date <= subscriptionExpiryDate.Date; // TODO :: Handle Microsoft offer being pulled back due to EOL. // Temporarily mark this partnerOffer item as inactive and dont allow store front customer to manage this subscription. MicrosoftOffer alignedMicrosoftOffer = currentMicrosoftOffers.FirstOrDefault(offer => offer.Offer.Id == partnerOfferItem.MicrosoftOfferId); if (alignedMicrosoftOffer == null) { partnerOfferItem.IsInactive = true; } if (partnerOfferItem.IsInactive) { // in case the offer is inactive (marked for deletion) then dont allow renewals or editing on this subscription tied to this offer. isRenewable = false; isEditable = false; } // Compute the pro rated price per seat for this subcription & return for client side processing during updates. decimal proratedPerSeatPrice = Math.Round(CommerceOperations.CalculateProratedSeatCharge(subscription.ExpiryDate, portalOfferPrice), responseCulture.NumberFormat.CurrencyDecimalDigits); SubscriptionViewModel subscriptionItem = new SubscriptionViewModel() { SubscriptionId = subscription.SubscriptionId, FriendlyName = subscriptionTitle, PortalOfferId = portalOfferId, PortalOfferPrice = portalOfferPrice.ToString("C", responseCulture), IsRenewable = isRenewable, // IsRenewable is true if subscription is going to expire in 30 days. IsEditable = isEditable, // IsEditable is true if today is lesser or equal to subscription expiry date. LicensesTotal = licenseTotal.ToString("G", responseCulture), // General format. SubscriptionTotal = subscriptionTotal.ToString("C", responseCulture), // Currency format. SubscriptionExpiryDate = subscriptionExpiryDate.Date.ToString("d", responseCulture), // Short date format. SubscriptionOrderHistory = historyItems, SubscriptionProRatedPrice = proratedPerSeatPrice }; // add this subcription to the customer's subscription list. customerSubscriptionsView.Add(subscriptionItem); // Increment the summary total. summaryTotal += subscriptionTotal; } // Capture the request for the customer summary for analysis. Dictionary <string, string> eventProperties = new Dictionary <string, string> { { "CustomerId", customerId } }; // Track the event measurements for analysis. Dictionary <string, double> eventMetrics = new Dictionary <string, double> { { "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds }, { "NumberOfSubscriptions", customerSubscriptionsView.Count } }; ApplicationDomain.Instance.TelemetryService.Provider.TrackEvent("GetSubscriptionSummaryAsync", eventProperties, eventMetrics); // Sort List of subscriptions based on portal offer name. return(new SubscriptionsSummary() { Subscriptions = customerSubscriptionsView.OrderBy(subscriptionItem => subscriptionItem.FriendlyName), SummaryTotal = summaryTotal.ToString("C", responseCulture) // Currency format. }); }
/// <summary> /// Gets the subscriptions managed by customers and partners /// </summary> /// <returns>returns managed subscriptions view model</returns> private async Task <ManagedSubscriptionsViewModel> GetManagedSubscriptions() { DateTime startTime = DateTime.Now; string clientCustomerId = Principal.PartnerCenterCustomerId; // responseCulture determines decimals, currency and such CultureInfo responseCulture = new CultureInfo(ApplicationDomain.Instance.PortalLocalization.Locale); // localeSpecificApiClient allows pulling offer names localized to supported portal locales compatible with Offer API supported locales. IPartner localeSpecificPartnerCenterClient = ApplicationDomain.Instance.PartnerCenterClient.With(RequestContextFactory.Instance.Create(ApplicationDomain.Instance.PortalLocalization.OfferLocale)); // Get all subscriptions of customer from PC ResourceCollection <Subscription> customerAllSubscriptions = await localeSpecificPartnerCenterClient.Customers.ById(clientCustomerId).Subscriptions.GetAsync().ConfigureAwait(false); IEnumerable <CustomerSubscriptionEntity> customerSubscriptions = await ApplicationDomain.Instance.CustomerSubscriptionsRepository.RetrieveAsync(clientCustomerId).ConfigureAwait(false); IEnumerable <PartnerOffer> allPartnerOffers = await ApplicationDomain.Instance.OffersRepository.RetrieveAsync().ConfigureAwait(false); IEnumerable <MicrosoftOffer> currentMicrosoftOffers = await ApplicationDomain.Instance.OffersRepository.RetrieveMicrosoftOffersAsync().ConfigureAwait(false); List <SubscriptionViewModel> customerSubscriptionsView = new List <SubscriptionViewModel>(); // iterate through and build the list of customer's subscriptions. foreach (CustomerSubscriptionEntity subscription in customerSubscriptions) { PartnerOffer partnerOfferItem = allPartnerOffers.FirstOrDefault(offer => offer.Id == subscription.PartnerOfferId); string subscriptionTitle = partnerOfferItem.Title; string portalOfferId = partnerOfferItem.Id; decimal portalOfferPrice = partnerOfferItem.Price; DateTime subscriptionExpiryDate = subscription.ExpiryDate.ToUniversalTime(); int remainingDays = (subscriptionExpiryDate.Date - DateTime.UtcNow.Date).Days; bool isRenewable = remainingDays <= 30; // IsRenewable is true if subscription is going to expire in 30 days. bool isEditable = DateTime.UtcNow.Date <= subscriptionExpiryDate.Date; // IsEditable is true if today is lesser or equal to subscription expiry date. // Temporarily mark this partnerOffer item as inactive and dont allow store front customer to manage this subscription. MicrosoftOffer alignedMicrosoftOffer = currentMicrosoftOffers.FirstOrDefault(offer => offer.Offer.Id == partnerOfferItem.MicrosoftOfferId); if (alignedMicrosoftOffer == null) { // The offer is inactive (marked for deletion) then dont allow renewals or editing on this subscription tied to this offer. partnerOfferItem.IsInactive = true; isRenewable = false; isEditable = false; } BrandingConfiguration portalBranding = await ApplicationDomain.Instance.PortalBranding.RetrieveAsync().ConfigureAwait(false); // Compute the pro rated price per seat for this subcription & return for client side processing during updates. decimal proratedPerSeatPrice = Math.Round(CommerceOperations.CalculateProratedSeatCharge(subscription.ExpiryDate, portalOfferPrice, portalBranding.BillingCycle), Resources.Culture.NumberFormat.CurrencyDecimalDigits); SubscriptionViewModel subscriptionItem = new SubscriptionViewModel() { SubscriptionId = subscription.SubscriptionId, FriendlyName = subscriptionTitle, PortalOfferId = portalOfferId, PortalOfferPrice = portalOfferPrice.ToString("C", responseCulture), IsRenewable = isRenewable, IsEditable = isEditable, SubscriptionExpiryDate = subscriptionExpiryDate.Date.ToString("d", responseCulture), SubscriptionProRatedPrice = proratedPerSeatPrice }; // add this subcription to the customer's subscription list. customerSubscriptionsView.Add(subscriptionItem); } List <CustomerSubscriptionModel> customerManagedSubscriptions = new List <CustomerSubscriptionModel>(); List <PartnerSubscriptionModel> partnerManagedSubscriptions = new List <PartnerSubscriptionModel>(); // Divide the subscriptions by customer and partner foreach (Subscription customerSubscriptionFromPC in customerAllSubscriptions.Items) { SubscriptionViewModel subscription = customerSubscriptionsView.FirstOrDefault(sub => sub.SubscriptionId == customerSubscriptionFromPC.Id); // Customer managed subscription found if (subscription != null) { CustomerSubscriptionModel customerSubscription = new CustomerSubscriptionModel() { SubscriptionId = customerSubscriptionFromPC.Id, LicensesTotal = customerSubscriptionFromPC.Quantity.ToString("G", responseCulture), Status = GetStatusType(customerSubscriptionFromPC.Status), CreationDate = customerSubscriptionFromPC.CreationDate.ToString("d", responseCulture), FriendlyName = subscription.FriendlyName, IsRenewable = subscription.IsRenewable, IsEditable = subscription.IsEditable, PortalOfferId = subscription.PortalOfferId, SubscriptionProRatedPrice = subscription.SubscriptionProRatedPrice }; customerManagedSubscriptions.Add(customerSubscription); } else { PartnerSubscriptionModel partnerSubscription = new PartnerSubscriptionModel() { Id = customerSubscriptionFromPC.Id, OfferName = customerSubscriptionFromPC.OfferName, Quantity = customerSubscriptionFromPC.Quantity.ToString("G", responseCulture), Status = GetStatusType(customerSubscriptionFromPC.Status), CreationDate = customerSubscriptionFromPC.CreationDate.ToString("d", responseCulture), }; partnerManagedSubscriptions.Add(partnerSubscription); } } ManagedSubscriptionsViewModel managedSubscriptions = new ManagedSubscriptionsViewModel() { CustomerManagedSubscriptions = customerManagedSubscriptions.OrderByDescending(customerManagedSubscription => customerManagedSubscription.CreationDate), PartnerManagedSubscriptions = partnerManagedSubscriptions.OrderByDescending(partnerManagedSubscription => partnerManagedSubscription.CreationDate) }; // Capture the request for customer managed subscriptions and partner managed subscriptions for analysis. Dictionary <string, string> eventProperties = new Dictionary <string, string> { { "CustomerId", clientCustomerId } }; // Track the event measurements for analysis. Dictionary <string, double> eventMetrics = new Dictionary <string, double> { { "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds }, { "CustomerManagedSubscriptions", customerManagedSubscriptions.Count }, { "PartnerManagedSubscriptions", partnerManagedSubscriptions.Count } }; ApplicationDomain.Instance.TelemetryService.Provider.TrackEvent("GetManagedSubscriptions", eventProperties, eventMetrics); return(managedSubscriptions); }
/// <summary> /// Gets the summary of subscriptions for a portal customer. /// </summary> /// <param name="customerId">The customer Id.</param> /// <returns>Subscription Summary.</returns> private async Task <SubscriptionsSummary> GetSubscriptionSummary(string customerId) { var customerSubscriptionsTask = ApplicationDomain.Instance.CustomerSubscriptionsRepository.RetrieveAsync(customerId); var customerSubscriptionsHistoryTask = ApplicationDomain.Instance.CustomerPurchasesRepository.RetrieveAsync(customerId); var allPartnerOffersTask = ApplicationDomain.Instance.OffersRepository.RetrieveAsync(); await Task.WhenAll(customerSubscriptionsTask, customerSubscriptionsHistoryTask, allPartnerOffersTask); var customerSubscriptionsHistory = customerSubscriptionsHistoryTask.Result; // retrieve all the partner offers to match against them IEnumerable <PartnerOffer> allPartnerOffers = allPartnerOffersTask.Result; // start building the summary. decimal summaryTotal = 0; // format all responses to client using portal locale. CultureInfo responseCulture = new CultureInfo(ApplicationDomain.Instance.PortalLocalization.Locale); List <SubscriptionViewModel> customerSubscriptionsView = new List <SubscriptionViewModel>(); // iterate through and build the list of customer's subscriptions. foreach (var subscription in customerSubscriptionsTask.Result) { decimal subscriptionTotal = 0; int licenseTotal = 0; List <SubscriptionHistory> historyItems = new List <SubscriptionHistory>(); // collect the list of history items for this subcription. var subscriptionHistoryList = customerSubscriptionsHistory .Where(historyItem => historyItem.SubscriptionId == subscription.SubscriptionId) .OrderBy(historyItem => historyItem.TransactionDate); // iterate through and build the SubsriptionHistory for this subscription. foreach (var historyItem in subscriptionHistoryList) { decimal orderTotal = Math.Round(historyItem.SeatPrice * historyItem.SeatsBought, 2); historyItems.Add(new SubscriptionHistory() { OrderTotal = orderTotal.ToString("C", responseCulture), PricePerSeat = historyItem.SeatPrice.ToString("C", responseCulture), // Currency format. SeatsBought = historyItem.SeatsBought.ToString("G", responseCulture), // General format. OrderDate = historyItem.TransactionDate.ToLocalTime().ToString("d", responseCulture), // Short date format. OperationType = this.GetOperationType(historyItem.PurchaseType) // Localized Operation type string. }); // Increment the subscription total. licenseTotal += historyItem.SeatsBought; // Increment the subscription total. subscriptionTotal += orderTotal; } var partnerOfferItem = allPartnerOffers.Where(offer => offer.Id == subscription.PartnerOfferId).FirstOrDefault(); string subscriptionTitle = partnerOfferItem.Title; string portalOfferId = partnerOfferItem.Id; decimal portalOfferPrice = partnerOfferItem.Price; DateTime subscriptionExpiryDate = subscription.ExpiryDate.ToUniversalTime(); int remainingDays = (subscriptionExpiryDate.Date - DateTime.UtcNow.Date).Days; bool isRenewable = remainingDays <= 30; bool isEditable = DateTime.UtcNow.Date <= subscriptionExpiryDate.Date; if (partnerOfferItem.IsInactive) { // in case the offer is inactive (marked for deletion) then dont allow renewals or editing on this subscription tied to this offer. isRenewable = false; isEditable = false; } // Compute the pro rated price per seat for this subcription & return for client side processing during updates. decimal proratedPerSeatPrice = Math.Round(CommerceOperations.CalculateProratedSeatCharge(subscription.ExpiryDate, portalOfferPrice), 2); SubscriptionViewModel subscriptionItem = new SubscriptionViewModel() { SubscriptionId = subscription.SubscriptionId, FriendlyName = subscriptionTitle, PortalOfferId = portalOfferId, PortalOfferPrice = portalOfferPrice.ToString("C", responseCulture), IsRenewable = isRenewable, // IsRenewable is true if subscription is going to expire in 30 days. IsEditable = isEditable, // IsEditable is true if today is lesser or equal to subscription expiry date. LicensesTotal = licenseTotal.ToString("G", responseCulture), // General format. SubscriptionTotal = subscriptionTotal.ToString("C", responseCulture), // Currency format. SubscriptionExpiryDate = subscriptionExpiryDate.Date.ToString("d", responseCulture), // Short date format. SubscriptionOrderHistory = historyItems, SubscriptionProRatedPrice = proratedPerSeatPrice }; // add this subcription to the customer's subscription list. customerSubscriptionsView.Add(subscriptionItem); // Increment the summary total. summaryTotal += subscriptionTotal; } // Sort List of subscriptions based on portal offer name. return(new SubscriptionsSummary() { Subscriptions = customerSubscriptionsView.OrderBy(subscriptionItem => subscriptionItem.FriendlyName), SummaryTotal = summaryTotal.ToString("C", responseCulture) // Currency format. }); }