public async Task <ApiResponse> Post([FromBody] PostTicketDTO arg)
        {
            try
            {
                var ticketId = await ticketService.CreateAsync(arg);

                return(new ApiResponse(InfoMessages.TicketCreated, ticketId, HttpStatusCode.OK.ToInt()));
            }
            catch (ValidationException ex)
            {
                throw new ApiException(ex.Errors, ex.StatusCode);
            }
            catch (CustomException ex)
            {
                throw new ApiException(ex, ex.StatusCode);
            }
            catch (Exception ex)
            {
                throw new ApiException(ex);
            }
        }
        public async Task <GetTicketDTO> CreateAsync(PostTicketDTO entity)
        {
            var ticket = mapper.Map <Ticket>(entity);

            #region SetOtherProps
            ticket.Identifier = "#" + Guid.NewGuid().ToString().Substring(0, 8);

            ticket.CustomerOrganizationId = appUser.CustomerOrganizationId;

            ticket.OpenedById = appUser.Id.ToString();

            //the ticket first status is open, so we selected the TicketStatus that its title is "open"
            ticket.TicketStatusId = (await db.TicketStatus.FirstOrDefaultAsync(f => f.Title == "باز")).Id;

            //If no priority has set by the user the priority with title "medium" is selected automatically
            ticket.PriorityId ??= (await db.Priorities.FirstOrDefaultAsync(f => f.Title == "متوسط")).Id;
            #endregion

            #region SettingTicketPipelineRules
            var thisTicketIssuePipeline = await db.TicketManagingPipelines.
                                          Where(w =>
                                                (w.CustomerOrganizationId == ticket.CustomerOrganizationId ||
                                                 w.CustomerOrganizationId == 0) && //for example intraorganizational tickets has no CustomerOrganizationId because they are not related to a customer
                                                w.TicketIssueId == ticket.TicketIssueId)
                                          .ToListAsync();

            if (thisTicketIssuePipeline != null && thisTicketIssuePipeline.Count() != 0)
            {
                var stepCount = thisTicketIssuePipeline.Count();
                var pipeline  = thisTicketIssuePipeline.FirstOrDefault(f => f.Step == 1);//when a ticket is created it is in the step 1

                ticket.CurrentStep  = 1;
                ticket.MaximumSteps = stepCount;

                if (pipeline != null)
                {
                    //if for this step the pipeline declared a groupid it will assign to the nominee group of ticket
                    //and we skip through
                    if (pipeline.NomineeGroupId != 0)
                    {
                        ticket.NomineeGroupId = pipeline.NomineeGroupId;
                    }

                    //if in pipeline it has mentioned that for this step it should set to the corrosponding groupId
                    //based on IssueId this section will do that
                    else if (pipeline.SetToNomineeGroupBasedOnIssueUrl)
                    {
                        //if the ticket has not issue id assigning a nominee will never perform.
                        if (ticket.IssueUrlId != null)
                        {
                            //if the issueUrl is not a real one then assigning a nominee will never perform.
                            var issueUrl = await db.IssueUrls.FirstOrDefaultAsync(f => f.Id == ticket.IssueUrlId);

                            if (issueUrl != null)
                            {
                                ticket.NomineeGroupId = issueUrl.GroupId;
                            }
                        }
                    }

                    //if in pipeline it has mentioned that for this step it should set to the corrosponding userId
                    //based on IssueId this section will do that
                    else if (pipeline.SetToNomineePersonBasedOnIssueUrl)
                    {
                        //if the ticket has not issue id assigning a nominee will never perform.
                        if (ticket.IssueUrlId != null)
                        {
                            //if the issueUrl is not a real one then assigning a nominee will never perform.
                            var issueUrl = await db.IssueUrls.FirstOrDefaultAsync(f => f.Id == ticket.IssueUrlId);

                            //it will set the ticket to first user corrosponding to issueurl
                            if (issueUrl != null)
                            {
                                ticket.AssigneeId = issueUrl.Users.FirstOrDefault().UserId;
                            }
                        }
                    }
                }
            }

            #endregion

            await using var transaction = await db.Database.BeginTransactionAsync();

            try
            {
                var addedTicket = db.Tickets.Add(ticket);
                var ticketId    = addedTicket.Entity.Id;

                db.TicketTicketLabels.AddRange(
                    entity.Labels.Select(s => new TicketTicketLabel {
                    TicketId = ticketId, TicketLabelId = s
                }).ToList()
                    );

                //a user just can send public messages
                // but other roles can make their massage public or private
                //(private means it is just visible to employees and not customers)
                var isMessagePublic = appUser.Roles.Any(a => a == Roles.User) ?
                                      true :
                                      entity.IsMessagePublic;

                db.Conversations.Add(
                    new Conversation
                {
                    Message  = entity.Message,
                    IsPublic = isMessagePublic,
                    TicketId = ticketId
                });

                //todo: handle attachment

                await transaction.CommitAsync();

                await db.SaveChangesAsync();

                var dto = mapper.Map <GetTicketDTO>(addedTicket.Entity);

                return(dto);
            }
            catch (Exception ex)
            {
                throw;
            }
        }