public async Task <InvokeResult> HandleDeviceExceptionAsync(DeviceException exception, EntityHeader org, EntityHeader user) { if (exception == null) { throw new ArgumentNullException(nameof(exception)); } if (org == null) { throw new ArgumentNullException(nameof(org)); } if (user == null) { throw new ArgumentNullException(nameof(user)); } Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine("Handling Device Exception."); var repo = await _repoManager.GetDeviceRepositoryWithSecretsAsync(exception.DeviceRepositoryId, org, user); var device = await _deviceManager.GetDeviceByDeviceIdAsync(repo, exception.DeviceUniqueId, org, user); var deviceConfig = await _deviceConfigManager.GetDeviceConfigurationAsync(device.DeviceConfiguration.Id, org, user); var deviceErrorCode = deviceConfig.ErrorCodes.FirstOrDefault(err => err.Key == exception.ErrorCode); if (deviceErrorCode == null) { return(InvokeResult.FromError($"Could not find error code [{exception.ErrorCode}] on device configuration [{deviceConfig.Name}] for device [{device.Name}]")); } if (!EntityHeader.IsNullOrEmpty(deviceErrorCode.ServiceTicketTemplate)) { Console.WriteLine("Generating service ticket (every occurence."); var request = new CreateServiceTicketRequest() { TemplateId = deviceErrorCode.ServiceTicketTemplate.Id, DeviceId = device.DeviceId, Details = exception.Details, DontCreateIfOpenForDevice = !deviceErrorCode.TriggerOnEachOccurrence, RepoId = repo.Id }; var result = await CreateServiceTicketAsync(request, org, user); if (!result.Successful) { return(result.ToInvokeResult()); } } else { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("No service ticket, skipping."); } var deviceError = device.Errors.Where(err => err.DeviceErrorCode == exception.ErrorCode).FirstOrDefault(); if (deviceError == null) { deviceError = new DeviceError() { Count = 1, DeviceErrorCode = exception.ErrorCode, FirstSeen = DateTime.UtcNow.ToJSONString(), LastDetails = exception.Details, Timestamp = DateTime.UtcNow.ToJSONString(), Expires = deviceErrorCode.AutoexpireTimespan.Value.AddTimeSpan(deviceErrorCode.AutoexpireTimespanQuantity.Value) }; device.Errors.Add(deviceError); } if (!EntityHeader.IsNullOrEmpty(deviceErrorCode.DistroList)) { if (deviceError == null || String.IsNullOrEmpty(deviceError.NextNotification) || (deviceError.NextNotification.ToDateTime().ToUniversalTime() < DateTime.UtcNow)) { var result = await _distroManager.GetListAsync(deviceErrorCode.DistroList.Id, org, user); var subject = String.IsNullOrEmpty(deviceErrorCode.EmailSubject) ? deviceErrorCode.Name : deviceErrorCode.EmailSubject.Replace("[DEVICEID]", device.DeviceId).Replace("[DEVICENAME]", device.Name); foreach (var notificationUser in result.AppUsers) { var appUser = await _userManager.FindByIdAsync(notificationUser.Id); if (deviceErrorCode.SendEmail) { var body = $"The error code [{deviceErrorCode.Key}] was detected on the device {device.Name}<br>{deviceErrorCode.Description}<br>{exception.Details}"; if (exception.AdditionalDetails.Any()) { body += "<br>"; body += "<b>Additional Details:<br /><b>"; body += "<ul>"; foreach (var detail in exception.AdditionalDetails) { body += $"<li>{detail}</li>"; } body += "</ul>"; } await _emailSender.SendAsync(appUser.Email, subject, body); } if (deviceErrorCode.SendSMS) { var body = $"Device {device.Name} generated error code [${deviceErrorCode.Key}] {deviceErrorCode.Description} {exception.Details}"; await _smsSender.SendAsync(appUser.PhoneNumber, body); } } if (EntityHeader.IsNullOrEmpty(deviceErrorCode.NotificationIntervalTimeSpan)) { deviceError.NextNotification = null; } else if (deviceErrorCode.NotificationIntervalQuantity.HasValue && deviceErrorCode.NotificationIntervalTimeSpan.Value != TimeSpanIntervals.NotApplicable) { deviceError.NextNotification = deviceErrorCode.NotificationIntervalTimeSpan.Value.AddTimeSpan(deviceErrorCode.NotificationIntervalQuantity.Value); } else { deviceError.NextNotification = null; Logger.AddCustomEvent(Core.PlatformSupport.LogLevel.Error, "ServiceTicketManager__HandleDeviceExceptionAsync", "Invalid quantity on NotificationIntervalQuantity", device.DeviceId.ToKVP("deviceId"), exception.ErrorCode.ToKVP("errorCode")); } } else { if (String.IsNullOrEmpty(deviceError.NextNotification)) { Console.WriteLine("NExt Notification is null...."); } else { Console.WriteLine("When to send next notification: " + deviceError.NextNotification); } } } else { Console.WriteLine("No distro, skipping."); } Console.ResetColor(); await _deviceManager.UpdateDeviceAsync(repo, device, org, user); return(InvokeResult.Success); }
public Task <InvokeResult <string> > CreateTicketAsync([FromBody] CreateServiceTicketRequest request) { return(_ticketCreator.CreateServiceTicketAsync(request, OrgEntityHeader, UserEntityHeader)); }
public async Task <InvokeResult <string> > CreateServiceTicketAsync(CreateServiceTicketRequest createServiceTicketRequest, EntityHeader org, EntityHeader user) { if (createServiceTicketRequest == null) { throw new ArgumentNullException(nameof(createServiceTicketRequest)); } if (String.IsNullOrEmpty(createServiceTicketRequest.RepoId)) { throw new ArgumentNullException(createServiceTicketRequest.RepoId); } if (String.IsNullOrEmpty(createServiceTicketRequest.DeviceId) && String.IsNullOrEmpty(createServiceTicketRequest.DeviceUniqueId)) { throw new ArgumentNullException(nameof(createServiceTicketRequest.DeviceId) + " and " + nameof(createServiceTicketRequest.DeviceUniqueId)); } if (String.IsNullOrEmpty(createServiceTicketRequest.TemplateId) && String.IsNullOrEmpty(createServiceTicketRequest.TemplateKey)) { throw new ArgumentNullException(nameof(createServiceTicketRequest.TemplateId) + " and " + nameof(createServiceTicketRequest.TemplateKey)); } ServiceTicketTemplate template; if (String.IsNullOrEmpty(createServiceTicketRequest.TemplateKey)) { template = await _templateRepo.GetServiceTicketTemplateAsync(createServiceTicketRequest.TemplateId); if (template == null) { throw new NullReferenceException($"Could not load ticket template for {createServiceTicketRequest.TemplateId}"); } } else { template = await _templateRepo.GetServiceTicketTemplateByKeyAsync(org.Id, createServiceTicketRequest.TemplateKey); if (template == null) { throw new NullReferenceException($"Could not load ticket template for {createServiceTicketRequest.TemplateKey}"); } } org ??= template.OwnerOrganization; user ??= template.DefaultContact ?? template.CreatedBy; if (org == null) { throw new NullReferenceException(nameof(org)); } if (user == null) { throw new NullReferenceException(nameof(user)); } var repo = await _repoManager.GetDeviceRepositoryWithSecretsAsync(createServiceTicketRequest.RepoId, org, user); if (repo == null) { throw new InvalidOperationException($"Could not find repository for id {createServiceTicketRequest.RepoId}"); } if (org != null && template.OwnerOrganization != org) { throw new InvalidOperationException("Template, org mismatch."); } Console.WriteLine("+++1"); Device device = null; if (!String.IsNullOrEmpty(createServiceTicketRequest.DeviceId)) { device = await _deviceManager.GetDeviceByDeviceIdAsync(repo, createServiceTicketRequest.DeviceId, template.OwnerOrganization, user ?? template.DefaultContact); if (device == null) { device = await _deviceManager.GetDeviceByIdAsync(repo, createServiceTicketRequest.DeviceId, template.OwnerOrganization, user ?? template.DefaultContact); if (device == null) // still null { throw new ArgumentNullException($"Could not find device with device id {createServiceTicketRequest.DeviceId}."); } } } else if (!String.IsNullOrEmpty(createServiceTicketRequest.DeviceUniqueId)) { device = await _deviceManager.GetDeviceByIdAsync(repo, createServiceTicketRequest.DeviceUniqueId, template.OwnerOrganization, user ?? template.DefaultContact); if (device == null) { throw new ArgumentNullException($"Could not find device with device id {createServiceTicketRequest.DeviceUniqueId}."); } } else { throw new ArgumentNullException("Must supply either DeviceId or DeviceUniqueId to create a service ticket."); } if (org != null && device.OwnerOrganization != org) { throw new InvalidOperationException("Device, org mismatch."); } Console.WriteLine("+++2"); var stateSet = await _ticketStatusRepo.GetTicketStatusDefinitionAsync(template.StatusType.Id); var defaultState = stateSet.Items.Where(st => st.IsDefault).First(); var assignedToUser = device.AssignedUser; if (assignedToUser == null) { assignedToUser = repo.AssignedUser; } if (assignedToUser == null) { assignedToUser = template.DefaultContact; } var currentTimeStamp = DateTime.UtcNow.ToJSONString(); EntityHeader <ServiceBoard> boardEH = null; Console.WriteLine("+++3"); var ticketId = Guid.NewGuid().ToString(); if (!String.IsNullOrEmpty(createServiceTicketRequest.BoardId)) { var board = await _serviceBoardRepo.GetServiceBoardAsync(createServiceTicketRequest.BoardId); boardEH = new EntityHeader <ServiceBoard>() { Id = board.Id, Text = board.Name }; var ticketNumber = await _serviceBoardRepo.GetNextTicketNumber(createServiceTicketRequest.BoardId); ticketId = $"{board.BoardAbbreviation}-{ticketNumber}"; if (assignedToUser == null && !EntityHeader.IsNullOrEmpty(board.PrimaryContact)) { assignedToUser = board.PrimaryContact; } } else if (!EntityHeader.IsNullOrEmpty(repo.ServiceBoard)) { boardEH = new EntityHeader <ServiceBoard>() { Id = repo.ServiceBoard.Id, Text = repo.ServiceBoard.Text }; var board = await _serviceBoardRepo.GetServiceBoardAsync(repo.ServiceBoard.Id); var ticketNumber = await _serviceBoardRepo.GetNextTicketNumber(repo.ServiceBoard.Id); ticketId = $"{board.BoardAbbreviation}-{ticketNumber}"; } Console.WriteLine("+++4"); string dueDate = null; if (!EntityHeader.IsNullOrEmpty(template.TimeToCompleteTimeSpan) && template.TimeToCompleteTimeSpan.Value != TimeSpanIntervals.NotApplicable && template.TimeToCompleteQuantity.HasValue) { TimeSpan ts = TimeSpan.Zero; switch (template.TimeToCompleteTimeSpan.Value) { case TimeSpanIntervals.Minutes: ts = TimeSpan.FromMinutes(template.TimeToCompleteQuantity.Value); break; case TimeSpanIntervals.Hours: ts = TimeSpan.FromHours(template.TimeToCompleteQuantity.Value); break; case TimeSpanIntervals.Days: ts = TimeSpan.FromDays(template.TimeToCompleteQuantity.Value); break; } dueDate = DateTime.UtcNow.Add(ts).ToJSONString(); } string statusDueDate = null; if (EntityHeader.IsNullOrEmpty(defaultState.TimeAllowedInStatusTimeSpan) && defaultState.TimeAllowedInStatusTimeSpan.Value != TimeSpanIntervals.NotApplicable && defaultState.TimeAllowedInStatusQuantity.HasValue) { TimeSpan ts = TimeSpan.Zero; switch (defaultState.TimeAllowedInStatusTimeSpan.Value) { case TimeSpanIntervals.Minutes: ts = TimeSpan.FromMinutes(defaultState.TimeAllowedInStatusQuantity.Value); break; case TimeSpanIntervals.Hours: ts = TimeSpan.FromHours(defaultState.TimeAllowedInStatusQuantity.Value); break; case TimeSpanIntervals.Days: ts = TimeSpan.FromDays(defaultState.TimeAllowedInStatusQuantity.Value); break; } statusDueDate = DateTime.UtcNow.Add(ts).ToJSONString(); } Console.WriteLine("+++5"); var ticket = new ServiceTicket() { Key = template.Key, TicketId = ticketId, DeviceRepo = EntityHeader.Create(repo.Id, repo.Name), CreationDate = currentTimeStamp, LastUpdatedDate = currentTimeStamp, DueDate = dueDate, Name = $"{template.Name} ({device.DeviceId})", Address = device.Address, IsClosed = false, Description = template.Description, Subject = String.IsNullOrEmpty(createServiceTicketRequest.Subject) ? $"{template.Name} ({device.DeviceId})" : createServiceTicketRequest.Subject, AssignedTo = assignedToUser, Template = new EntityHeader <ServiceTicketTemplate>() { Id = template.Id, Text = template.Name }, ServiceBoard = boardEH, Device = new EntityHeader <IoT.DeviceManagement.Core.Models.Device>() { Id = device.Id, Text = device.Name }, Status = EntityHeader.Create(defaultState.Key, defaultState.Name), StatusDate = DateTime.UtcNow.ToJSONString(), OwnerOrganization = template.OwnerOrganization, HoursEstimate = template.HoursEstimate, CostEstimate = template.CostEstimate, SkillLevel = template.SkillLevel, Urgency = template.Urgency, Tools = template.Tools, PartsKits = template.PartsKits, ServiceParts = template.ServiceParts, Instructions = template.Instructions, StatusType = template.StatusType, StatusDueDate = statusDueDate, Resources = template.Resources, TroubleshootingSteps = template.TroubleshootingSteps, CreatedBy = user, LastUpdatedBy = user }; ticket.StatusType.Value = stateSet; ticket.History.Add(new ServiceTicketStatusHistory() { AddedBy = user, DateStamp = DateTime.UtcNow.ToJSONString(), Status = ticket.Status.Text, Note = $"Created service ticket with {defaultState.Name} status." }); Console.WriteLine("+++6"); ticket.Notes.Add(new ServiceTicketNote() { AddedBy = user, DateStamp = currentTimeStamp, Note = assignedToUser != null ? $"Service ticket created and assigned to {assignedToUser.Text}." : "Service ticket created and not assigned to technician." }); if (!String.IsNullOrEmpty(createServiceTicketRequest.Details)) { ticket.Notes.Add(new ServiceTicketNote() { Id = Guid.NewGuid().ToString(), Note = createServiceTicketRequest.Details, AddedBy = ticket.CreatedBy, DateStamp = DateTime.UtcNow.ToJSONString() }); } Console.WriteLine("+++7"); await _repo.AddServiceTicketAsync(ticket); Console.WriteLine("+++8"); await SendTicketNotificationAsync(ticket); Console.WriteLine("+++9"); return(InvokeResult <string> .Create(ticket.TicketId)); }