/// <summary> /// Suspend the subscription /// </summary> /// <param name="subscriptionId"></param> /// <returns></returns> public async Task <Subscription> SuspendAsync(Guid subscriptionId, Guid operationId) { Subscription subscription; try { // Get the subscription that matches the subscriptionId provided subscription = await GetAsync(subscriptionId); } catch (Exception) { throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Suspend.ToVerb()), UserErrorCode.ResourceNotFound); } CheckSubscriptionInReadyState(subscription); _logger.LogInformation($"Operation {operationId}: Suspend subscription {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName}."); // Soft delete the subscription from db subscription.OperationId = operationId; subscription.ProvisioningStatus = nameof(ProvisioningState.ArmTemplatePending); subscription.ProvisioningType = nameof(ProvisioningType.Suspend); subscription.LastUpdatedTime = DateTime.UtcNow; _context.Subscriptions.Update(subscription); await _context._SaveChangesAsync(); _logger.LogInformation($"Operation {operationId}: Subscription {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName} is suspended."); return(subscription); }
/// <summary> /// Activate a subscription. /// </summary> /// <param name="subscriptionId">The id of the subscription to activate.</param> /// <param name="activatedBy">The id of the user who activated this subscription.</param> /// <returns>The activated subscription.</returns> public async Task <Subscription> ActivateAsync(Guid subscriptionId, string activatedBy = "system") { Subscription subscription; try { // Get the subscription that matches the subscriptionId provided subscription = await GetAsync(subscriptionId); } catch (Exception) { throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Activate.ToVerb()), UserErrorCode.ResourceNotFound); } _logger.LogInformation($"Activate subscription {subscriptionId}."); subscription.Status = nameof(FulfillmentState.Subscribed); subscription.ActivatedTime = DateTime.UtcNow; subscription.ActivatedBy = activatedBy; _context.Subscriptions.Update(subscription); await _context._SaveChangesAsync(); _logger.LogInformation($"Activated subscription {subscriptionId}. Activated by: {activatedBy}."); return(subscription); }
public void CheckSubscriptionInReadyState(Subscription subscription) { if (!subscription.Status.Equals(nameof(FulfillmentState.Subscribed))) { throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscription.SubscriptionId, SubscriptionAction.Update.ToVerb(), invalidFulfillmentState: nameof(subscription.Status))); } if (!subscription.ProvisioningStatus.Equals(nameof(ProvisioningState.Succeeded))) { throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscription.SubscriptionId, SubscriptionAction.Update.ToVerb(), invalidProvisioningState: true)); } _logger.LogInformation($"Subscription {subscription.SubscriptionId} is in the Subscribed fulfillment state and Succeeded provisioining state."); }
/// <summary> /// Soft delete a subscription. /// </summary> /// <param name="subscriptionId">The id of the subscription to soft delete.</param> /// <returns>The subscription with updated status and unsubscribed_time.</returns> public async Task <Subscription> UnsubscribeAsync(Guid subscriptionId, Guid operationId) { Subscription subscription; try { // Get the subscription that matches the subscriptionId provided subscription = await GetAsync(subscriptionId); } catch (Exception) { throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Unsubscribe.ToVerb()), UserErrorCode.ResourceNotFound); } CheckSubscriptionInReadyState(subscription); _logger.LogInformation($"Operation {operationId}: Unsubscribe subscription {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName}."); // Soft delete the subscription from db subscription.OperationId = operationId; subscription.ProvisioningStatus = nameof(ProvisioningState.ArmTemplatePending); subscription.ProvisioningType = nameof(ProvisioningType.Unsubscribe); subscription.LastUpdatedTime = DateTime.UtcNow; using (var transaction = await _context.BeginTransactionAsync()) { var subscriptionMeterUsages = await _context.SubscriptionCustomMeterUsages.Where(s => s.IsEnabled && s.SubscriptionId == subscriptionId).ToListAsync(); foreach (var usage in subscriptionMeterUsages) { usage.UnsubscribedTime = subscription.LastUpdatedTime.Value; _context.SubscriptionCustomMeterUsages.Update(usage); } await _context._SaveChangesAsync(); _context.Subscriptions.Update(subscription); await _context._SaveChangesAsync(); transaction.Commit(); } _logger.LogInformation($"Operation {operationId}: Subscription {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName} is unsubscribed."); return(subscription); }
/// <summary> /// Delete data from a subscription /// </summary> /// <param name="subscriptionId">the subscription id</param> /// <returns>Purged subscription</returns> public async Task <Subscription> DeleteDataAsync(Guid subscriptionId) { Subscription subscription; try { // Get the subscription that matches the subscriptionId provided subscription = await GetAsync(subscriptionId); } catch (Exception) { throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.DeleteData.ToVerb()), UserErrorCode.ResourceNotFound); } if (subscription == null) { throw new NotSupportedException($"Subscription {subscriptionId} doesn't exist or you don't have permission to access it."); } if (!subscription.ProvisioningStatus.Equals(nameof(ProvisioningState.Succeeded))) { throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.DeleteData.ToVerb(), invalidProvisioningState: true)); } if (!subscription.Status.Equals(nameof(FulfillmentState.Unsubscribed))) { throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.DeleteData.ToVerb(), requiredFulfillmentState: nameof(FulfillmentState.Unsubscribed))); } _logger.LogInformation($"Delete data for subscription {subscriptionId}."); subscription.ProvisioningStatus = nameof(ProvisioningState.ArmTemplatePending); subscription.ProvisioningType = nameof(ProvisioningType.DeleteData); subscription.LastUpdatedTime = DateTime.UtcNow; _context.Subscriptions.Update(subscription); await _context._SaveChangesAsync(); _logger.LogInformation($"Data deleted for subscription {subscriptionId}."); return(subscription); }
/// <summary> /// Reinstate the subscription /// </summary> /// <param name="subscriptionId"></param> /// <returns></returns> public async Task <Subscription> ReinstateAsync(Guid subscriptionId, Guid operationId) { Subscription subscription; try { // Get the subscription that matches the subscriptionId provided subscription = await GetAsync(subscriptionId); } catch (Exception) { throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Reinstate.ToVerb()), UserErrorCode.ResourceNotFound); } if (!subscription.ProvisioningStatus.Equals(nameof(ProvisioningState.Succeeded))) { throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Reinstate.ToVerb(), invalidProvisioningState: true)); } if (!subscription.Status.Equals(nameof(FulfillmentState.Suspended))) { throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Reinstate.ToVerb(), requiredFulfillmentState: nameof(FulfillmentState.Suspended))); } _logger.LogInformation($"Operation {operationId}: Reinstate subscription {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName}."); // Soft delete the subscription from db subscription.OperationId = operationId; subscription.ProvisioningStatus = nameof(ProvisioningState.ArmTemplatePending); subscription.ProvisioningType = nameof(ProvisioningType.Reinstate); subscription.LastUpdatedTime = DateTime.UtcNow; _context.Subscriptions.Update(subscription); await _context._SaveChangesAsync(); _logger.LogInformation($"Operation {operationId}: Reinstate {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName} is suspended."); return(subscription); }
/// <summary> /// Updates a subscription. /// </summary> /// <param name="subscription">The updated subscription.</param> /// <returns>The updated subscription.</returns> public async Task <Subscription> UpdateAsync(Subscription subscription, Guid operationId) { if (subscription is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(Subscription).Name), UserErrorCode.PayloadNotProvided); } _logger.LogInformation(LoggingUtils.ComposeUpdateResourceMessage(typeof(Subscription).Name, subscription.Name, offerName: subscription.OfferName, planName: subscription.PlanName, payload: JsonSerializer.Serialize(subscription))); var newPlanName = subscription.PlanName; var newQuantity = subscription.Quantity; Subscription subscriptionDb; try { // Get the subscription that matches the subscriptionId provided subscriptionDb = await GetAsync(subscription.SubscriptionId); } catch (Exception) { throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscription.SubscriptionId, SubscriptionAction.Update.ToVerb()), UserErrorCode.ResourceNotFound); } CheckSubscriptionInReadyState(subscriptionDb); // Get the offer and plan associated with the subscriptionId provided var offer = await _context.Offers.FindAsync(subscriptionDb.OfferId); var plan = await _context.Plans.FindAsync(subscriptionDb.PlanId); if (newPlanName != plan.PlanName && subscriptionDb.Quantity != newQuantity) { throw new ArgumentException("Cannot update plan and quantity at the same time."); } // Check if the plan has been upgraded or downgraded if (newPlanName != plan.PlanName) { _logger.LogInformation($"Updating subscription {subscription.SubscriptionId} from plan {plan.PlanName} to {newPlanName}."); // Get the new plan to change to var newPlan = await _planService.GetAsync(offer.OfferName, newPlanName); // Update the FK to the new plan subscription.OperationId = operationId; subscriptionDb.PlanId = newPlan.Id; subscriptionDb.ProvisioningStatus = nameof(ProvisioningState.ArmTemplatePending); subscriptionDb.ProvisioningType = nameof(ProvisioningType.Update); } else if (subscriptionDb.Quantity != subscription.Quantity) { _logger.LogInformation($"Updating subscription {subscription.SubscriptionId} from quantity {subscriptionDb.Quantity} to {subscription.Quantity}"); subscriptionDb.Quantity = newQuantity; //TODO: what to do? } // Set the updated time subscriptionDb.LastUpdatedTime = DateTime.UtcNow; // Update subscriptionDb values and save changes in db _context.Subscriptions.Update(subscriptionDb); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceUpdatedMessage(typeof(Subscription).Name, subscription.Name, offerName: subscription.OfferName, planName: subscription.PlanName)); return(subscriptionDb); }