public async Task <InvokeResult <ServiceTicket> > SetTicketViewedStatusAsync(string id, bool viewed, EntityHeader org, EntityHeader user)
        {
            var ticket = await _repo.GetServiceTicketAsync(id);

            var date = DateTime.UtcNow.ToJSONString();

            await AuthorizeAsync(ticket, AuthorizeResult.AuthorizeActions.Update, user, org, "SetViewStatus");

            if (viewed == ticket.IsViewed)
            {
                return(InvokeResult <ServiceTicket> .FromError(viewed?$"Aleady been marked as viewed." : "Already been marked as not viewed"));
            }

            ticket.IsViewed = viewed;
            if (viewed)
            {
                if (!EntityHeader.IsNullOrEmpty(ticket.AssignedTo) && user.Id != ticket.AssignedTo.Id)
                {
                    return(InvokeResult <ServiceTicket> .FromError($"Assigned to {ticket.AssignedTo.Text} but attempted to be viewed by {user.Text}.  Only the assigned user can mark as viewed."));
                }

                ticket.ViewedDate = DateTime.UtcNow.ToJSONString();
                ticket.ViewedBy   = user;

                var history = new ServiceTicketStatusHistory()
                {
                    AddedBy   = user,
                    DateStamp = date,
                    Status    = ticket.Status.Text,
                    Note      = $"Viewed by [{user.Text}]"
                };
                ticket.History.Insert(0, history);
            }
            else
            {
                ticket.ViewedDate = null;
                ticket.ViewedBy   = null;

                var history = new ServiceTicketStatusHistory()
                {
                    AddedBy   = user,
                    DateStamp = date,
                    Status    = ticket.Status.Text,
                    Note      = $"Cleared viewed by [{user.Text}]"
                };
                ticket.History.Insert(0, history);
            }

            ticket.LastUpdatedBy   = user;
            ticket.LastUpdatedDate = date;
            await _repo.UpdateServiceTicketAsync(ticket);

            return(InvokeResult <ServiceTicket> .Create(ticket));
        }
        public async Task <InvokeResult <ServiceTicket> > SetTicketClosedStatusAsync(string id, bool isClosed, EntityHeader org, EntityHeader user)
        {
            var ticket = await _repo.GetServiceTicketAsync(id);

            var date = DateTime.UtcNow.ToJSONString();

            await AuthorizeAsync(ticket, AuthorizeResult.AuthorizeActions.Update, user, org, "SetClosedStatus");

            if (isClosed == ticket.IsClosed)
            {
                return(InvokeResult <ServiceTicket> .FromError(isClosed?$"Aleady been marked as closed." : "Already been marked as not closed"));
            }

            ticket.IsClosed = isClosed;
            if (isClosed)
            {
                ticket.ClosedDate = DateTime.UtcNow.ToJSONString();
                ticket.ClosedBy   = user;

                var history = new ServiceTicketStatusHistory()
                {
                    AddedBy   = user,
                    DateStamp = date,
                    Status    = ticket.Status.Text,
                    Note      = $"Closed by [{user.Text}]"
                };
                ticket.History.Insert(0, history);
            }
            else
            {
                ticket.ClosedDate = null;
                ticket.ClosedBy   = null;

                var history = new ServiceTicketStatusHistory()
                {
                    AddedBy   = user,
                    DateStamp = date,
                    Status    = ticket.Status.Text,
                    Note      = $"Re-opened by [{user.Text}]"
                };
                ticket.History.Insert(0, history);
            }

            ticket.LastUpdatedBy   = user;
            ticket.LastUpdatedDate = date;
            await _repo.UpdateServiceTicketAsync(ticket);

            return(InvokeResult <ServiceTicket> .Create(ticket));
        }
        public async Task <InvokeResult <ServiceTicket> > SetAssignedToAsync(string id, EntityHeader assignedTouser, EntityHeader org, EntityHeader user)
        {
            var ticket = await _repo.GetServiceTicketAsync(id);

            await AuthorizeAsync(ticket, AuthorizeResult.AuthorizeActions.Update, user, org);

            var existingAssigned = EntityHeader.IsNullOrEmpty(ticket.AssignedTo) ? "unassigned" : ticket.AssignedTo.Text;
            var newAssigned      = EntityHeader.IsNullOrEmpty(assignedTouser) ? "unassigned" : assignedTouser.Text;

            var historyItem = new ServiceTicketStatusHistory()
            {
                AddedBy   = user,
                DateStamp = DateTime.UtcNow.ToJSONString(),
                Status    = ticket.Status.Text,
                Note      = $"Ticket assigned from [{existingAssigned}] to [{newAssigned}]"
            };

            ticket.History.Insert(0, historyItem);

            ticket.AssignedTo = assignedTouser;
            await _repo.UpdateServiceTicketAsync(ticket);

            return(InvokeResult <ServiceTicket> .Create(ticket));
        }
        public async Task <InvokeResult <ServiceTicket> > SetTicketStatusAsync(string id, EntityHeader newStatus, EntityHeader org, EntityHeader user)
        {
            var date = DateTime.UtcNow.ToJSONString();

            var ticket = await _repo.GetServiceTicketAsync(id);

            if (newStatus.Id == ticket.Status.Id)
            {
                return(InvokeResult <ServiceTicket> .FromError($"Already in {newStatus}"));
            }

            await AuthorizeAsync(ticket, AuthorizeResult.AuthorizeActions.Update, user, org, "SetStatus");

            var history = new ServiceTicketStatusHistory()
            {
                AddedBy   = user,
                DateStamp = date,
                Status    = newStatus.Text,
                Note      = $"Status changed from [{ticket.Status.Text}] to [{newStatus.Text}]"
            };

            ticket.History.Insert(0, history);

            var statusDefinition = await _ticketStatusRepo.GetTicketStatusDefinitionAsync(ticket.StatusType.Id);

            var status = statusDefinition.Items.First(stat => stat.Key == newStatus.Id);

            if (!EntityHeader.IsNullOrEmpty(status.TimeAllowedInStatusTimeSpan) &&
                status.TimeAllowedInStatusTimeSpan.Value != TimeSpanIntervals.NotApplicable &&
                status.TimeAllowedInStatusQuantity.HasValue)
            {
                TimeSpan ts = TimeSpan.Zero;
                switch (status.TimeAllowedInStatusTimeSpan.Value)
                {
                case TimeSpanIntervals.Minutes: ts = TimeSpan.FromMinutes(status.TimeAllowedInStatusQuantity.Value); break;

                case TimeSpanIntervals.Hours: ts = TimeSpan.FromHours(status.TimeAllowedInStatusQuantity.Value); break;

                case TimeSpanIntervals.Days: ts = TimeSpan.FromDays(status.TimeAllowedInStatusQuantity.Value); break;
                }

                ticket.StatusDueDate = DateTime.UtcNow.Add(ts).ToJSONString();

                history = new ServiceTicketStatusHistory()
                {
                    AddedBy       = user,
                    DateStamp     = date,
                    Status        = newStatus.Text,
                    StatusDueDate = ticket.StatusDueDate,
                    Note          = $"New status due date set to [{ticket.StatusDueDate.ToDateTime().ToLocalTime()}]"
                };
                ticket.History.Insert(0, history);
            }
            else
            {
                ticket.StatusDueDate = null;
            }

            if (status.IsClosed != ticket.IsClosed)
            {
                ticket.IsClosed   = status.IsClosed;
                ticket.ClosedDate = ticket.IsClosed ? date : null;
                ticket.ClosedBy   = user;

                history = new ServiceTicketStatusHistory()
                {
                    AddedBy   = user,
                    DateStamp = date,
                    Status    = newStatus.Text,
                    Note      = ticket.IsClosed ? $"Closed by [{user.Text}]" : $"Reopened by [{user.Text}]"
                };

                ticket.History.Insert(0, history);
            }

            ticket.Status     = newStatus;
            ticket.StatusDate = date;

            ticket.LastUpdatedBy   = user;
            ticket.LastUpdatedDate = date;

            await _repo.UpdateServiceTicketAsync(ticket);

            return(InvokeResult <ServiceTicket> .Create(ticket));
        }
        public async Task <ServiceTicket> GetServiceTicketAsync(string id, EntityHeader org, EntityHeader user)
        {
            Console.WriteLine("Starting getting ticket");
            Console.WriteLine("=====================================");

            var sw     = Stopwatch.StartNew();
            var ticket = await _repo.GetServiceTicketAsync(id);

            Console.WriteLine("Loaded service ticket: " + sw.Elapsed.TotalMilliseconds);

            await AuthorizeAsync(ticket, AuthorizeResult.AuthorizeActions.Read, user, org);

            Console.WriteLine("Authorized: " + sw.Elapsed.TotalMilliseconds);
            var sw2 = Stopwatch.StartNew();

            if (!EntityHeader.IsNullOrEmpty(ticket.DeviceRepo))
            {
                var repo = await _repoManager.GetDeviceRepositoryWithSecretsAsync(ticket.DeviceRepo.Id, org, user);

                Console.WriteLine("Loaded device repo: " + sw2.Elapsed.TotalMilliseconds);
                sw2 = Stopwatch.StartNew();
                if (!EntityHeader.IsNullOrEmpty(ticket.Device))
                {
                    ticket.Device.Value = await _deviceManager.GetDeviceByIdAsync(repo, ticket.Device.Id, org, user, true);
                }

                Console.WriteLine("Device load time: " + sw2.Elapsed.TotalMilliseconds);
            }

            var statusType = await _ticketStatusRepo.GetTicketStatusDefinitionAsync(ticket.StatusType.Id);

            ticket.StatusType = EntityHeader <TicketStatusDefinition> .Create(statusType);

            if (!EntityHeader.IsNullOrEmpty(ticket.ServiceBoard))
            {
                ticket.ServiceBoard.Value = await _serviceBoardRepo.GetServiceBoardAsync(ticket.ServiceBoard.Id);
            }

            Console.WriteLine("Loaded board: " + sw.Elapsed.TotalMilliseconds);

            if (!EntityHeader.IsNullOrEmpty(ticket.Template))
            {
                ticket.Template.Value = await _templateRepo.GetServiceTicketTemplateAsync(ticket.Template.Id);

                if (!EntityHeader.IsNullOrEmpty(ticket.Template.Value.TemplateCategory))
                {
                    ticket.Template.Value.TemplateCategory.Value = await _templateCategoryRepo.GetTemplateCategoryAsync(ticket.Template.Value.TemplateCategory.Id);
                }
            }

            Console.WriteLine("Total load time: " + sw.Elapsed.TotalMilliseconds);

            if (!ticket.IsViewed && !EntityHeader.IsNullOrEmpty(ticket.AssignedTo) && ticket.AssignedTo.Id == user.Id)
            {
                ticket.IsViewed   = true;
                ticket.ViewedBy   = user;
                ticket.ViewedDate = DateTime.UtcNow.ToJSONString();
                var history = new ServiceTicketStatusHistory()
                {
                    AddedBy   = user,
                    DateStamp = ticket.ViewedDate,
                    Status    = ticket.Status.Text,
                    Note      = $"Viewed by [{user.Text}]"
                };

                ticket.History.Insert(0, history);
                await _repo.UpdateServiceTicketAsync(ticket);
            }

            return(ticket);
        }