public async Task <bool> ActivateProFeatures(int jobId, string userId) { var job = _context.Jobs .Include(m => m.CreatedBy) .Include(m => m.ProActivation) .FirstOrDefault(m => m.Id == jobId); if (job == null) { throw new ArgumentException("An invalid job id was passed to the service"); } // NB the user activating is not necessarily the job creator, but could be an admin. var user = _context.Users.FirstOrDefault(u => u.Id == userId); if (user == null) { throw new ArgumentException("An invalid user id was passed to the app service"); } var isAdmin = await _userManager.IsInRoleAsync(user, "Admin"); if (!isAdmin && user.Credits == 0 && _appOptions.PaymentsEnabled) { return(false); } // Allow reactivation by admin if (job.ProActivation != null && !isAdmin) { throw new ArgumentException("The analysis has already been activated"); } // Submit processing for GeoTIFF output var request = new JobSubmission() { Title = job.Name, Description = job.Description, UserName = job.CreatedBy.UserName, East = job.LongitudeEast, West = job.LongitudeWest, North = job.LatitudeNorth, South = job.LatitudeSouth, Priority = 2 }; var processorReference = await _processor.StartProJob(request); if (String.IsNullOrEmpty(processorReference)) { return(false); } if (!isAdmin && _appOptions.PaymentsEnabled) { user.Credits = user.Credits - 1; } var activation = new ProActivation() { //Id = Guid.NewGuid(), UserIdOfPurchaser = user.Id, TimeOfPurchase = DateTime.Now, CreditsSpent = 1, ProcessingStatus = JobStatus.Submitted, JobProcessorReference = processorReference }; job.ProActivation = activation; _context.Update(job); _context.Update(user); _context.SaveChanges(); Hangfire.RecurringJob.AddOrUpdate("prostatus_" + job.Id, () => UpdateProStatusAsync(job.Id), Cron.Minutely); if (!isAdmin && _appOptions.PaymentsEnabled) { _notifyService.AddJobNotification(NotificationLevel.Success, job.Id, "You used 1 credit to upgrade '{0}' to premium.", new string[] { job.Name }); if (user.Credits <= 3 && user.Credits > 0) { _notifyService.AddUserNotification(NotificationLevel.Information, user.Id, "Your credits are running low. You only have enough for {0} more premium activations.", new string[] { user.Credits.ToString() }); } else if (user.Credits == 0) { _notifyService.AddUserNotification(NotificationLevel.Information, user.Id, "You're out of credits, and will not be able to activate premium datasets unless you top up.", new string[] {}); } } else if (!_appOptions.PaymentsEnabled) { _notifyService.AddJobNotification(NotificationLevel.Success, job.Id, "Your request for a high-resolution data package for '{0}' has entered the queue.", new string[] { job.Name }); } return(true); }