public ServiceTicketHolder(ServiceTicket ticket)
 {
     TicketId           = ticket.TicketId;
     AuthenticationType = ticket.AuthenticationType;
     Assertion          = new AssertionHolder(ticket.Assertion);
     Claims             = ticket.Claims.Select(x => new ClaimHolder(x));
 }
            public ServiceTicket grantServiceTicket(string id, Service service, ExpirationPolicy expirationPolicy, bool credentialsProvided)
            {
                ServiceTicket t = this.getTicket().grantServiceTicket(id, service, expirationPolicy, credentialsProvided);

                this.updateTicket();
                return(t);
            }
示例#3
0
        public ActionResult Edit(ServiceTicket serviceticket)
        {
            if (ModelState.IsValid)
            {
                this.serviceTicketRepository.InsertOrUpdate(serviceticket);
                this.serviceTicketRepository.Save();
                return(RedirectToAction(
                           "Details",
                           new
                {
                    id = serviceticket.ID
                }));
            }

            this.ViewBag.PossibleCustomers        = this.customerRepository.All;
            this.ViewBag.PossibleCreatedBies      = this.employeeRepository.All;
            this.ViewBag.PossibleAssignedToes     = this.employeeRepository.All;
            this.ViewBag.PossibleEscalationLevels = new Dictionary <string, string>
            {
                { "1", "Level 1" },
                { "2", "Level 2" },
                { "3", "Level 3" }
            };

            return(this.View());
        }
示例#4
0
        /// <summary>
        /// Create an identity from a service created service ticket
        /// </summary>
        public static AuthorizedIdent Create(ServiceTicket ticket)
        {
            ServiceTicket tik;

            if (ticket == null)
            {
                return(null);
            }
            else
            {
                Session ses = new Sessions(null).GetInfo(ticket.Ident);
                if (ses == null)
                {
                    return(null);
                }

                tik          = new ServiceTicket();
                tik.Username = ses.Username; tik.HostAddress = ses.Address;
                tik.Ident    = ses.Identifier;
            }

            if (tik.Username != ticket.Username)
            {
                return(null);
            }
            else if (tik.HostAddress != ticket.HostAddress)
            {
                return(null);
            }
            else
            {
                return(new AuthorizedIdent(tik.Username));
            }
        }
        protected AuthenticationTicket BuildAuthenticationTicket(ServiceTicket ticket)
        {
            if (ticket == null)
            {
                return(null);
            }
            var assertion = ticket.Assertion;
            var principal = new CasPrincipal(assertion, ticket.AuthenticationType);
            var identity  = (principal.Identity as ClaimsIdentity);

            if (identity != null)
            {
                foreach (var claim in ticket.Claims)
                {
                    if (identity.HasClaim(claim.Type, claim.Value))
                    {
                        continue;
                    }
                    identity.AddClaim(claim.ToClaim());
                }
            }
            return(new AuthenticationTicket(
                       principal,
                       new AuthenticationProperties {
                IssuedUtc = assertion.ValidFrom,
                ExpiresUtc = assertion.ValidUntil
            },
                       ticket.AuthenticationType));
        }
        public void ScheduleActionCorrectlyUpdatesRepositories()
        {
            this.SetupController();

            // Arrange
            var scheduleItems = new List <ScheduleItem>();

            scheduleItems.Add(new ScheduleItem {
                ServiceTicketID = 1
            });
            //mockScheduleItemRepo.SetReturnValue("get_All", scheduleItems.AsQueryable<ScheduleItem>());
            mockScheduleItemRepo.SetReturnValue("InsertOrUpdate", null);
            mockScheduleItemRepo.SetReturnValue("Delete", null);
            mockScheduleItemRepo.ExpectAndReturn("Save", null);

            ServiceTicket ticket = new ServiceTicket {
                ID = 0
            };

            mockServiceTicketRepo.SetReturnValue("Find", ticket);
            mockServiceTicketRepo.ExpectAndReturn("Save", null);

            // Act
            controller.AssignSchedule(1, 101, 0);

            // Assert
            Assert.AreEqual(101, ticket.AssignedToID);
            mockScheduleItemRepo.Verify();
            mockServiceTicketRepo.Verify();
        }
示例#7
0
        private void btnAddEdit4_Click(object sender, EventArgs e)
        {
            currentServiceTicketInfo = new ServiceTicket()
            {
                ClientID = int.Parse(tbTicketClientID.Text),
                Title    = tbTicketTitle.Text,
                Problem  = tbProblem.Text
            };

            if (btnAddEdit4.Text == "Добавить")
            {
                var client = service.ClientRepository.Get(currentServiceTicketInfo.ClientID);
                if (client == null)
                {
                    MessageBox.Show("Клиента с таким ID не существует.");
                    return;
                }
                currentServiceTicketInfo.Price = Math.Round(double.Parse(tbTicketPrice.Text) * (100.0 - client.Discount) / 100, 2);

                service.ServiceTicketRepository.Add(currentServiceTicketInfo);
            }
            else
            {
                currentServiceTicketInfo.ID    = int.Parse(dgvServiceTickets.SelectedRows[0].Cells[0].Value.ToString());
                currentServiceTicketInfo.Price = double.Parse(tbTicketPrice.Text);
                service.ServiceTicketRepository.Update(currentServiceTicketInfo);
            }
            RefreshDataGridView(DataGridViewTab.ServiceTicket);
            ClearSelection(DataGridViewTab.ServiceTicket);
            SetEntityInformation(true);
        }
示例#8
0
        private void ClearSelection(DataGridViewTab tab)
        {
            switch (tab)
            {
            case DataGridViewTab.Products:
                dgvProducts.ClearSelection();
                currentProductInfo = new Product();
                break;

            case DataGridViewTab.Orders:
                dgvOrders.ClearSelection();
                currentOrderInfo = new Order();
                break;

            case DataGridViewTab.Clients:
                dgvClients.ClearSelection();
                currentClientInfo = new Client();
                break;

            case DataGridViewTab.ServiceTicket:
                dgvServiceTickets.ClearSelection();
                currentServiceTicketInfo = new ServiceTicket();
                break;
            }
        }
示例#9
0
        public async Task <ServiceTicket> GetNextServiceTicket()
        {
            ServiceTicket newTicket = new ServiceTicket();

            var lastTicket = await _serviceTicket.AsQueryable <ServiceTicket>().OrderByDescending(x => x.TicketNumber).FirstOrDefaultAsync();


            if (lastTicket == null)
            {
                ServiceTicket ticket = new ServiceTicket();
                ticket.TicketNumber = 1;
                ticket.DateCreated  = DateTime.Now;
                ticket.Status       = 1;
                newTicket           = await Create(ticket);
            }
            else
            {
                ServiceTicket ticket = new ServiceTicket();
                ticket.TicketNumber = lastTicket.TicketNumber + 1;
                ticket.DateCreated  = DateTime.Now;
                ticket.Status       = 1;
                newTicket           = await Create(ticket);
            }

            return(newTicket);
        }
示例#10
0
        private async void GooglePlusPersonQueryCompleted(ServiceTicket ticket, NSObject obj, NSError error)
        {
            if (error != null)
            {
                HideLoadingView();
                //InvokeOnMainThread(() => new UIAlertView("Error", "Could not get user information.\nError: " + error.LocalizedDescription, null, "Ok", null).Show());
                InvokeOnMainThread(() => new UIAlertView("Login Failed", "The social network login failed for your account", null, "Ok", null).Show());
                CrashReporter.Report(new Exception(error.LocalizedDescription));
                return;
            }

            var person = (PlusPerson)obj;

            AppSettings.UserEmail     = SignIn.SharedInstance.Authentication.UserEmail;
            AppSettings.UserFirstName = person.Name.GivenName;
            AppSettings.UserLastName  = person.Name.FamilyName;
            AppSettings.UserPhoto     = person.Image.Url;

            bool registerSuccessful = await RegisterUser();

            if (!registerSuccessful)
            {
                GoToCreateAccountScreen();
                return;
            }

            UserTrackingReporter.TrackUser(Constant.CATEGORY_LOGIN, "Google login completed");

            ShowHomeScreen();
        }
示例#11
0
        private static AuthenticationTicket BuildAuthenticationTicket(ServiceTicket ticket)
        {
            var assertion = ticket.Assertion;
            var principal = new CasPrincipal(assertion, ticket.AuthenticationType);

            if (!(principal.Identity is ClaimsIdentity identity))
            {
                return(new AuthenticationTicket(
                           principal,
                           new AuthenticationProperties
                {
                    IssuedUtc = assertion.ValidFrom,
                    ExpiresUtc = assertion.ValidUntil
                },
                           ticket.AuthenticationType));
            }

            identity.AddClaims(ticket.Claims);

            return(new AuthenticationTicket(
                       principal,
                       new AuthenticationProperties
            {
                IssuedUtc = assertion.ValidFrom,
                ExpiresUtc = assertion.ValidUntil
            },
                       ticket.AuthenticationType));
        }
        public bool UpdateServiceTicket(ServiceTicket serviceTicket)
        {
            var existingTicket = db.ServiceTickets.FirstOrDefault(p => p.Id == serviceTicket.Id);

            if (existingTicket != null)
            {
                existingTicket.ServiceTemplateId = serviceTicket.ServiceTemplateId;
                existingTicket.EventTaskListId   = serviceTicket.EventTaskListId;
                existingTicket.EventDate         = serviceTicket.EventDate;
                existingTicket.ReferenceNumber   = serviceTicket.ReferenceNumber;
                existingTicket.VisitFromTime     = serviceTicket.VisitFromTime.Value.ToLocalTime();
                existingTicket.VisitToTime       = serviceTicket.VisitToTime.Value.ToLocalTime();
                existingTicket.JsonFields        = serviceTicket.JsonFields;
                existingTicket.ApprovedById      = serviceTicket.ApprovedById;
                existingTicket.ApprovedDate      = serviceTicket.ApprovedDate;
                existingTicket.Condition         = serviceTicket.Condition;
                existingTicket.Notes             = serviceTicket.Notes;
                existingTicket.WhyNotCompleted   = serviceTicket.WhyNotCompleted;
            }
            else
            {
                db.ServiceTickets.Add(serviceTicket);
            }

            db.SaveChanges();

            return(true);
        }
        public IHttpActionResult GetServiceTicket(int id)
        {
            var serviceTemplate = db.ServiceTemplates.FirstOrDefault(s => s.Id == id);
            var property        = new Property()
            {
                Name     = "Property Name",
                Address1 = "Address",
                City     = new City(),
                State    = "ST",
                Zip      = "00000"
            };

            if (serviceTemplate == null || property == null)
            {
                return(NotFound());
            }

            var serviceTicket = new ServiceTicket();

            serviceTicket.EventTaskListId   = id;
            serviceTicket.EventDate         = DateTime.Now;
            serviceTicket.VisitFromTime     = DateTime.Today.AddHours(8);
            serviceTicket.VisitToTime       = DateTime.Today.AddHours(10);
            serviceTicket.ServiceTemplateId = serviceTemplate.Id;
            serviceTicket.JsonFields        = serviceTemplate.JsonFields;

            var serviceMembers = from e in db.Employees
                                 orderby e.FirstName, e.LastName
                select new ServiceMemberViewModel()
            {
                EmployeeId   = e.Id,
                FirstName    = e.FirstName,
                LastName     = e.LastName,
                IsCrewMember = true,
                Selected     = db.ServiceMembers.Any(s => s.EmployeeId == e.Id && s.ServiceTicketId == serviceTicket.Id)
            };

            var ticket = serviceTicket.MapTo <ServiceTicketViewModel>();

            ticket.TemplateName     = serviceTemplate.Name;
            ticket.TemplateUseTasks = serviceTemplate.UseTasks;
            ticket.TemplateUrl      = serviceTemplate.Url;
            ticket.PropertyName     = property.Name;
            ticket.Address1         = property.Address1;
            ticket.Address2         = property.Address2;
            ticket.City             = property.City != null ? property.City.Name : "";
            ticket.State            = property.State;
            ticket.Zip = property.Zip;
            if (property.Customer != null)
            {
                ticket.AccessDetails = property.Customer.AccessDetails;
                ticket.CustomerName  = property.Customer.FirstName + " " + property.Customer.LastName;
            }
            ticket.Members          = serviceMembers.ToList();
            ticket.ShowAllEmployees = true;

            return(Ok(ticket));
        }
示例#14
0
        public IActionResult CreateServiceTicket([FromBody] ServiceTicket theTicket)
        {
            System.Console.WriteLine("User is creating ticket");

            DbContext.ServiceTickets.Add(theTicket);
            DbContext.SaveChanges();

            return(Json(theTicket)); // return JSON object
        }
        public ServiceTicket GetServiceTicket(int id)
        {
            ServiceTicket serviceTicket = db.ServiceTickets.FirstOrDefault(s => s.Id == id);

            if (serviceTicket == null)
            {
                return(null);
            }
            return(serviceTicket);
        }
        public async Task <InvokeResult <string> > AddServiceTicketAsync(ServiceTicket serviceTicket, EntityHeader org, EntityHeader user)
        {
            ValidationCheck(serviceTicket, Actions.Create);

            await AuthorizeAsync(serviceTicket, AuthorizeResult.AuthorizeActions.Create, user, org);

            await _repo.AddServiceTicketAsync(serviceTicket);

            return(InvokeResult <string> .Create(serviceTicket.TicketId));
        }
        public ServiceTicket GetServiceTicket(int eventTaskListId, DateTime eventDate)
        {
            ServiceTicket serviceTicket = db.ServiceTickets.FirstOrDefault(s => s.EventTaskListId == eventTaskListId && s.EventDate == eventDate);

            if (serviceTicket == null)
            {
                return(null);
            }
            return(serviceTicket);
        }
示例#18
0
        public ActionResult Create(ServiceTicket serviceticket)
        {
            if (ModelState.IsValid)
            {
                serviceticket.Opened = DateTime.Now;

                var createdBy =
                    this.employeeRepository.All.Where(e => e.Identity == "NORTHAMERICA\\drobbins").FirstOrDefault();

                if (createdBy != null)
                {
                    serviceticket.CreatedByID = createdBy.ID;
                }

                var serviceLogEntry = new ServiceLogEntry
                {
                    ServiceTicket = serviceticket,
                    CreatedAt     = DateTime.Now,
                    CreatedBy     = serviceticket.CreatedBy,
                    CreatedByID   = serviceticket.CreatedByID,
                    Description   = "Created",
                };

                this.serviceLogEntryRepository.InsertOrUpdate(serviceLogEntry);
                this.serviceLogEntryRepository.Save();

                return(RedirectToAction(
                           "Details",
                           new
                {
                    serviceticket.ID
                }));
            }
            else
            {
                ViewBag.PossibleCustomers        = this.customerRepository.All;
                ViewBag.PossibleCreatedBies      = this.employeeRepository.All;
                ViewBag.PossibleAssignedToes     = this.employeeRepository.All;
                ViewBag.PossibleEscalationLevels = new Dictionary <string, string>
                {
                    { "1", "Level 1" },
                    { "2", "Level 2" },
                    { "3", "Level 3" }
                };

                var newTicket = new ServiceTicket
                {
                    CreatedBy =
                        this.employeeRepository.All.Where(e => e.Identity == "NORTHAMERICA\\drobbins").FirstOrDefault(),
                };

                return(View(newTicket));
            }
        }
 public void InsertOrUpdate(ServiceTicket serviceticket)
 {
     if (serviceticket.ID == default(int))
     {
         this.context.ServiceTickets.Add(serviceticket);
     }
     else
     {
         this.context.Entry(serviceticket).State = EntityState.Modified;
     }
 }
示例#20
0
        public DetailResponse <ServiceTicket> CreateServiceTicketAsync()
        {
            var ticket = new ServiceTicket()
            {
                Id = Guid.NewGuid().ToId(),
            };

            SetAuditProperties(ticket);
            SetOwnedProperties(ticket);

            return(DetailResponse <ServiceTicket> .Create(ticket));
        }
        private DateTime?CalculateVisitTime(ServiceTicket serviceTicket)
        {
            var time = this.scheduleItemRepository.All.SingleOrDefault(e => e.ServiceTicketID == serviceTicket.ID);

            if (time == null)
            {
                return(null);
            }

            var number = new Random((int)DateTime.Now.Ticks).Next(0, 30);

            return(time.Start.AddMinutes(number % 2 == 0 ? number : -1 * number));
        }
示例#22
0
        public async Task <IActionResult> Update(string id, ServiceTicket ticketIn)
        {
            var ticket = await _ticketService.Get(id);

            if (ticket == null)
            {
                return(NotFound());
            }

            await _ticketService.Update(id, ticketIn);

            return(NoContent());
        }
示例#23
0
        public JsonResult Delete(ServiceTicket service)
        {
            int result = serviceTicketService.Delete(service.Id);

            _hubContext.Clients.All.SendAsync("dataChangeNotification", null);
            if (result != 0)
            {
                return(Json(new { messageType = "success", note = AppGlobal.DeleteSuccessMessage }));
            }
            else
            {
                return(Json(new { messageType = "error", note = AppGlobal.DeleteFailMessage }));
            }
        }
示例#24
0
        private void FileServiceInit(AuthorizedIdent ident, bool reload)
        {
            if (reload || m_fdss[ident.Name] == null)
            {
                FileDataWebGateway fds = new FileDataWebGateway();
                fds.Url = String.Format("http://{0}/FrontDeskServices/filedataservice.asmx",
                                        Globals.FileSystemAddress);
                string        password = new Users(null).GetPassword(ident.Name);
                ServiceTicket tik      = fds.Authenticate(ident.Name, password);
                fds.ServiceTicketValue = tik;

                m_fdss[m_ident.Name] = fds;
            }
        }
        public async Task <InvokeResult> UpdateServiceTicketAsync(ServiceTicket serviceTicket, EntityHeader org, EntityHeader user)
        {
            ValidationCheck(serviceTicket, Actions.Update);

            serviceTicket.LastUpdatedBy   = user;
            serviceTicket.LastUpdatedDate = DateTime.UtcNow.ToJSONString();

            await AuthorizeAsync(serviceTicket, AuthorizeResult.AuthorizeActions.Create, user, org);

            await _repo.UpdateServiceTicketAsync(serviceTicket);


            return(InvokeResult.Success);
        }
        private static AuthenticationTicket BuildAuthenticationTicket(ServiceTicket ticket)
        {
            var assertion = ticket.Assertion;
            var identity  = new CasIdentity(assertion, ticket.AuthenticationType);

            identity.AddClaims(ticket.Claims);
            return(new AuthenticationTicket(
                       identity,
                       new AuthenticationProperties
            {
                IssuedUtc = assertion.ValidFrom,
                ExpiresUtc = assertion.ValidUntil
            }));
        }
        private string GetTicketNotificationContent(ServiceTicket ticket)
        {
            var redirectUri = $"{GetWebURI()}/home/links?viewtype=fsliteticket&viewid={ticket.Id}";

            var bldr = new StringBuilder();

            bldr.AppendLine("You have been assigned to a service ticket<br />");

            bldr.AppendLine($"<h4>{ticket.Subject}<h4 />");
            bldr.AppendLine($"<p>{ticket.Description}</p>");

            bldr.AppendLine($"Click <a href='{redirectUri}'>here</a> for more information.");

            return(bldr.ToString());
        }
示例#28
0
        public JsonResult Update(ServiceTicket service)
        {
            service.Initialization(ObjectInitType.Update, "", HttpContext);
            int result = serviceTicketService.Update(service.Id, service);

            _hubContext.Clients.All.SendAsync("dataChangeNotification", null);
            if (result != 0)
            {
                return(Json(new { messageType = "success", note = AppGlobal.UpdateSuccessMessage }));
            }
            else
            {
                return(Json(new { messageType = "error", note = AppGlobal.UpdateFailMessage }));
            }
        }
示例#29
0
        public void SerializeServiceTicket()
        {
            // Arrange
            var assertion = new Assertion("test");
            var claims    = new List <Claim> {
                new Claim(ClaimTypes.Name, Guid.NewGuid().ToString())
            };
            var ticket = new ServiceTicket(Guid.NewGuid().ToString(), assertion, claims.Select(x => new ClaimWrapper(x)), "TEST");

            // Act
            var json = JsonConvert.SerializeObject(ticket, Formatting.Indented, SerializerSettings);

            // Assert
            Assert.NotNull(json);
            _output.WriteLine(json);
        }
示例#30
0
        public ActionResult Create()
        {
            ViewBag.PossibleCustomers        = this.customerRepository.All;
            ViewBag.PossibleCreatedBies      = this.employeeRepository.All;
            ViewBag.PossibleAssignedToes     = this.employeeRepository.All;
            ViewBag.PossibleEscalationLevels = new Dictionary <string, string> {
                { "1", "Level 1" }, { "2", "Level 2" }, { "3", "Level 3" }
            };

            var newTicket = new ServiceTicket
            {
                CreatedBy = this.employeeRepository.All.Where(e => e.Identity == "NORTHAMERICA\\drobbins").FirstOrDefault(),
            };

            return(View(newTicket));
        }
        /**
     * Determines the principal id to use for a {@link RegisteredService} using the following rules: 
     * 
     * <ul>
     *  <li> If the service is marked to allow anonymous access, a persistent id is returned. </li>
     *  <li> If the attribute name matches {@link RegisteredService#DEFAULT_USERNAME_ATTRIBUTE}, then the default principal id is returned.</li>
     *  <li>If the service is set to ignore attributes, or the username attribute exists in the allowed attributes for the service, 
     *      the corresponding attribute value will be returned.
     *  </li>
     *   <li>Otherwise, the default principal's id is returned as the username attribute with an additional warning.</li>
     * </ul>
     * 
     * @param principal The principal object to be validated and constructed
     * @param registeredService Requesting service for which a principal is being validated. 
     * @param serviceTicket An instance of the service ticket used for validation
     * 
     * @return The principal id to use for the requesting registered service
     */
        private string determinePrincipalIdForRegisteredService(Principal principal, RegisteredService registeredService,
                                                                 ServiceTicket serviceTicket)
        {
            string principalId = null;
            string serviceUsernameAttribute = registeredService.getUsernameAttribute();

            if (registeredService.isAnonymousAccess())
            {
                principalId = this.persistentIdGenerator.generate(principal, serviceTicket.getService());
            }
            else if (string.IsNullOrEmpty(serviceUsernameAttribute))
            {
                principalId = principal.getId();
            }
            else
            {
                if ((registeredService.isIgnoreAttributes() || registeredService.getAllowedAttributes().Contains(serviceUsernameAttribute)) &&
                    principal.getAttributes().ContainsKey(serviceUsernameAttribute))
                {
                    principalId = principal.getAttributes().First(x => x.Key == registeredService.getUsernameAttribute()).Value.ToString();
                }
                else
                {
                    principalId = principal.getId();
                    Object[] errorLogParameters = new Object[] { principalId, registeredService.getUsernameAttribute(),
                                                                     principal.getAttributes(), registeredService.getServiceId(), principalId };
                    //log.warn("Principal [{}] did not have attribute [{}] among attributes [{}] so CAS cannot "
                    //        + "provide on the validation response the user attribute the registered service [{}] expects. "
                    //        + "CAS will instead return the default username attribute [{}]", errorLogParameters);
                }

            }

            //log.debug("Principal id to return for service [{}] is [{}]. The default principal id is [{}].", 
            //          new Object[] {registeredService.getName(), principal.getId(), principalId});
            return principalId;
        }
示例#32
0
文件: DataAccess.cs 项目: slai/cwkb
        public List<Ticket> GetTickets(int[] ids, bool loadNotes = false, bool loadTimeEntries = false)
        {
            var cmd = new SqlCommand();
            cmd.Connection = _conn;

            //http://stackoverflow.com/questions/337704/parameterizing-a-sql-in-clause/337792#337792
            var idsMap = new Dictionary<string, int>();
            for (var i = 0; i < ids.Length; i++)
                idsMap["@id" + i.ToString()] = ids[i];

            cmd.CommandText = @"SELECT SR_Service.SR_Service_RecID, SR_Service.Entered_By, SR_Service.Summary,
                                       SR_Service.Date_Entered, SR_Service.Date_Closed,
                                       SR_Service.Last_Update, SR_Service.Updated_By,
                                       Company.Company_Name AS __Company_Name, SR_Status.Description AS __Status,
                                       PM_Phase.Description AS __Phase_Desc, PM_Project.Project_ID AS __Project_Name
                                FROM dbo.SR_Service
                                    INNER JOIN dbo.SR_Status ON SR_Status.SR_Status_RecID = SR_Service.SR_Status_RecID
                                    INNER JOIN dbo.Company ON Company.Company_RecID = SR_Service.Company_RecID
                                    LEFT OUTER JOIN PM_Phase ON PM_Phase.PM_Phase_RecID = SR_Service.PM_Phase_RecID
                                    LEFT OUTER JOIN PM_Project ON PM_Project.PM_Project_RecID = PM_Phase.PM_Project_RecID
                                WHERE SR_Service_RecID IN (" + string.Join(",", idsMap.Keys) + ")";

            foreach (var k in idsMap.Keys)
                cmd.Parameters.AddWithValue(k, idsMap[k]);

            var results = new List<Ticket>();
            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    try
                    {
                        Ticket e = null;
                        // If __Project_Name is not null, then this ticket is a project ticket
                        if (!(reader["__Project_Name"] is DBNull))
                            e = new ProjectTicket(reader);
                        else
                            e = new ServiceTicket(reader);
                        results.Add(e);
                    }
                    catch (Exception ex)
                    {
                        // TODO: log
                    }
                }
            }

            // now get ticket notes
            if (loadNotes)
            {
                var ticketIds = from t in results select t.Id;
                var notes = GetTicketNotes(ticketIds.ToArray());
                foreach (var t in results)
                {
                    if (notes.ContainsKey(t.Id))
                        t.LoadNotes(notes[t.Id]);
                }
            }

            // now get ticket time entries
            if (loadTimeEntries)
            {
                var ticketIds = from t in results select t.Id;
                var entries = GetTimeEntriesForTickets(ticketIds.ToArray());
                foreach (var t in results)
                {
                    if (entries.ContainsKey(t.Id))
                        t.LoadTimeEntries(entries[t.Id]);
                }
            }

            return results;
        }