public async Task <InvokeResult> DeleteServiceTicketTemplateAsync(string id, EntityHeader org, EntityHeader user)
        {
            var template = await _repo.GetServiceTicketTemplateAsync(id);

            await ConfirmNoDepenenciesAsync(template);

            await AuthorizeAsync(template, AuthorizeResult.AuthorizeActions.Delete, user, org);

            await _repo.DeleteServiceTicketTemplateAsync(id);

            return(InvokeResult.Success);
        }
        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));
        }