using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using BeWo.Data.Entities;
using BS.Shared.Extensions;
using NHibernate.Criterion;
using NHibernate.SqlCommand;

using BS.Shared.Core;
using BS.Shared;
using BS.Shared.DataContracts.Compact;
using Login = BeWo.Data.Entities.Login;

namespace BeWo.Data.Access
{
    public class SearchDAO : AbstractBaseDAO
    {
        public IEnumerable<ValueListEntry> FindValueListEntry(ValueListEntryType pType)
        {
            return CreateCriteria<ValueListEntry>().Add(Restrictions.Eq(ValueListEntry.PropertyName_Type, pType)).AddOrder(Order.Asc(ValueListEntry.PropertyName_Value)).List<ValueListEntry>();
        }

        public IEnumerable<ValueListEntry> FindValueListEntries(List<ValueListEntryType> pTypes)
        {
            return CreateCriteria<ValueListEntry>().Add(Restrictions.In(ValueListEntry.PropertyName_Type, pTypes)).AddOrder(Order.Asc(ValueListEntry.PropertyName_Value)).List<ValueListEntry>();
        }

        public virtual IEnumerable<Employee> FindEmployee(string pFirstName, string pLastName, string pPersonnelNumber)
        {
            return CreateCriteria<Employee>()
            .Add(Restrictions.Like(Employee.PropertyName_PersonnelNumber, pPersonnelNumber, MatchMode.Anywhere))
            .CreateCriteria(Employee.PropertyName_Person, JoinType.InnerJoin)
                .Add(Restrictions.Like(Person.PropertyName_FirstName, pFirstName, MatchMode.Anywhere))
                .Add(Restrictions.Like(Person.PropertyName_LastName, pLastName, MatchMode.Anywhere))
            .List<Employee>();
        }

	    public virtual Employee FindEmployeeByFullname(string pFullname)
	    {
			var q = Session.CreateSQLQuery(string.Format("SELECT Oid FROM Person WHERE CONCAT_WS(' ', FirstName, LastName) LIKE '%{0}%'", pFullname));
		    var x = q.List<long>();

		    return x.Count > 0 ? DAOFactory.GenericDAO.GetByID<Employee>(x.First()) : null;
	    }

        public virtual IEnumerable<Wohnheim> FindWohnheim(string pwohnheimName, string pWohnheimStrasse, string pWohnheimPlz)
        {
            return CreateCriteria<Wohnheim>()
            .Add(Restrictions.Like(Wohnheim.PropertyName_WohnheimName, pwohnheimName, MatchMode.Anywhere))
            .CreateCriteria(Wohnheim.PropertyName_Wohnheim, JoinType.InnerJoin)
                .Add(Restrictions.Like(Wohnheim.PropertyName_Strasse, pWohnheimStrasse, MatchMode.Anywhere))
                .Add(Restrictions.Like(Wohnheim.PropertyName_PlZ, pWohnheimPlz, MatchMode.Anywhere))
            .List<Wohnheim>();
        }

        public virtual Wohnheim FindWohnheimByFullname(string pWohnheimName)
        {
            var q = Session.CreateSQLQuery(string.Format("SELECT Oid FROM Wohnheim WHERE CONCAT_WS(' ', WohnheimName) LIKE '%{0}%'", pWohnheimName));
            var x = q.List<long>();

            return x.Count > 0 ? DAOFactory.GenericDAO.GetByID<Wohnheim>(x.First()) : null;
        }

        public virtual IEnumerable<Customer> FindCustomer(string pFirstName, string pLastName, string pReferenceNumber)
        {
            return CreateCriteria<Customer>()
            .Add(Restrictions.Like(Customer.PropertyName_ReferenceNumber, pReferenceNumber, MatchMode.Anywhere))
            .CreateCriteria(Customer.PropertyName_Person, JoinType.InnerJoin)
                .Add(Restrictions.Like(Person.PropertyName_FirstName, pFirstName, MatchMode.Anywhere))
                .Add(Restrictions.Like(Person.PropertyName_LastName, pLastName, MatchMode.Anywhere))
            .List<Customer>();
        }

        public virtual IEnumerable<Person> FindPerson(string pFirstName, string pLastName, DateTime? pDateOfBirth, PersonType? pPersonType)
        {
            var lCriteria = CreateCriteria<Person>()
             .Add(Restrictions.Like(Person.PropertyName_FirstName, pFirstName, MatchMode.Anywhere))
             .Add(Restrictions.Like(Person.PropertyName_LastName, pLastName, MatchMode.Anywhere));
            if (pDateOfBirth != null)
                lCriteria.Add(Restrictions.Eq(Person.PropertyName_DateOfBirth, pDateOfBirth));
            if (pPersonType != null)
                lCriteria.Add(Restrictions.Eq(Person.PropertyName_Type, pPersonType));

            return lCriteria.List<Person>();
        }

        public virtual IEnumerable<Organisation> FindOrganisation(string pName, bool pOnlyCostBearer)
        {
            var lCriteria = CreateCriteria<Organisation>()
             .Add(Restrictions.Like(Organisation.PropertyName_Name, pName, MatchMode.Anywhere));

            if (pOnlyCostBearer)
                lCriteria.Add(Restrictions.IsNotNull(Organisation.PropertyName_CostBearer));

            return lCriteria.List<Organisation>();
        }

        public virtual IEnumerable<Team> FindTeams(string pTeamName, string pLeaderFirstName, string pLeaderLastName)
        {
            return CreateCriteria<Team>()
            .Add(Restrictions.Like(Team.PropertyName_Name, pTeamName, MatchMode.Anywhere))
            .CreateCriteria(Team.PropertyName_Leader, JoinType.InnerJoin)
                .CreateCriteria(Employee.PropertyName_Person)
                    .Add(Restrictions.Like(Person.PropertyName_FirstName, pLeaderFirstName, MatchMode.Anywhere))
                    .Add(Restrictions.Like(Person.PropertyName_LastName, pLeaderLastName, MatchMode.Anywhere))
            .List<Team>();
        }

		public virtual IList<Team> FindTeamsOfEmployee(long employeeOid)
		{
			return CreateCriteriaIsActiveOrArchived<Team>()
			.CreateCriteria(Team.PropertyName_MemberList, JoinType.InnerJoin)
				.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, employeeOid))
			.List<Team>();
		}

		public virtual IEnumerable<Team> FindLeadingTeams(long employeeOid)
		{
			return CreateCriteriaIsActiveOrArchived<Team>()
			.CreateCriteria(Team.PropertyName_Leader, JoinType.InnerJoin)
				.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, employeeOid))
			.List<Team>();
		}

        public IEnumerable<ResourceBookingSequence> FindBookings(long pResourceOid, DateTime pSpanStart, DateTime pSpanEnd)
        {
            var lResult = CreateCriteria<ResourceBookingSequence>()
                  .CreateAlias(ResourceBookingSequence.PropertyName_Resource, "r")
                  .CreateAlias(ResourceBookingSequence.PropertyName_Details, "d")
                  .Add(Restrictions.Eq("r." + BeWoEntityBase.PropertyName_Oid, pResourceOid))
                  .Add(Restrictions.Eq("d." + ResourceBooking.PropertyName_SequencePosition, 0))
                  .Add(Restrictions.Disjunction()
                      .Add(Restrictions.Between("d." + ResourceBooking.PropertyName_Start, pSpanStart, pSpanEnd))
                      .Add(Restrictions.Between(ResourceBookingSequence.PropertyName_SequenceEnd, pSpanStart, pSpanEnd))
                      .Add(Restrictions.Conjunction()
                          .Add(Restrictions.Le("d." + ResourceBooking.PropertyName_Start, pSpanStart))
                          .Add(Restrictions.Ge(ResourceBookingSequence.PropertyName_SequenceEnd, pSpanEnd))
                          )
                       )
                  .List<ResourceBookingSequence>();

            return lResult;
        }

        public IEnumerable<ResourceBookingSequence> FindBookings(DateTime pSpanStart, DateTime pSpanEnd)
        {
            var lResult = CreateCriteria<ResourceBookingSequence>()
                  .CreateAlias(ResourceBookingSequence.PropertyName_Details, "d")
                  .Add(Restrictions.Eq("d." + ResourceBooking.PropertyName_SequencePosition, 0))
                  .Add(Restrictions.Disjunction()
                      .Add(Restrictions.Between("d." + ResourceBooking.PropertyName_Start, pSpanStart, pSpanEnd))
                      .Add(Restrictions.Between(ResourceBookingSequence.PropertyName_SequenceEnd, pSpanStart, pSpanEnd))
                      .Add(Restrictions.Conjunction()
                          .Add(Restrictions.Le("d." + ResourceBooking.PropertyName_Start, pSpanStart))
                          .Add(Restrictions.Ge(ResourceBookingSequence.PropertyName_SequenceEnd, pSpanEnd))
                          )
                       )
                  .List<ResourceBookingSequence>();

            return lResult;
        }

        public List<ServiceRecord> FindServiceRecords(long? pEmployeeOid, long? pCostBearer2SupportConceptOid)
        {
            var c = CreateCriteria<ServiceRecord>()
                .CreateAlias(ServiceRecord.PropertyName_Employee, "e", JoinType.InnerJoin);

            if (pCostBearer2SupportConceptOid.HasValue)
            {
                c = c.CreateAlias(ServiceRecord.PropertyName_SupportConcept, "sc", JoinType.InnerJoin)
                     .CreateAlias("sc." + SupportConcept.PropertyName_CostBearer2SupportConceptList, "c2s", JoinType.InnerJoin);
            }

            if (pEmployeeOid.HasValue)
                c = c.Add(Restrictions.Eq("e." + BeWoEntityBase.PropertyName_Oid, pEmployeeOid));
            if (pCostBearer2SupportConceptOid.HasValue)
                c = c.Add(Restrictions.Eq("c2s." + BeWoEntityBase.PropertyName_Oid, pCostBearer2SupportConceptOid));

            return c.List<ServiceRecord>().ToList();
        }

		public List<ServiceRecord> FindServiceRecordsForSupportConcept(long pSupportConceptOid)
		{
			var c = CreateCriteria<ServiceRecord>()
				.CreateAlias(ServiceRecord.PropertyName_SupportConcept, "sc", JoinType.InnerJoin);

			c = c.Add(Restrictions.Eq("sc." + BeWoEntityBase.PropertyName_Oid, pSupportConceptOid));
			return c.List<ServiceRecord>().ToList();
		}

        public IList<SupportConceptApprovalPeriod2Employee> FindSupportConceptApprovalPeriod2Employees(Employee emp)
        {
            var c = CreateCriteria<SupportConceptApprovalPeriod2Employee>()
                .Add(Restrictions.Eq(SupportConceptApprovalPeriod2Employee.PropertyName_Employee, emp));
            return c.List<SupportConceptApprovalPeriod2Employee>().ToList();
        }

        public IEnumerable<ServiceRecord> FindServiceRecordsInSpan(long pCostBearer2SupportConceptOid, DateTimeSpan period)
        {
            var criteria = CreateCriteria<ServiceRecord>()
                .Add(Restrictions.Eq(ServiceRecord.PropertyName_CostBearer2SupportConceptOid, pCostBearer2SupportConceptOid));

            if (period != null)
                criteria =
                    criteria.Add(
                        Restrictions.Or(
                            Restrictions.Between(ServiceRecord.PropertyName_Start, period.StartDateTime, period.EndDateTime),
                            Restrictions.Between(ServiceRecord.PropertyName_End, period.StartDateTime, period.EndDateTime)));

            return criteria.List<ServiceRecord>().ToList();
        }

        public IEnumerable<ServiceRecordHistory> FindServiceRecordHistory(long serviceRecordOid)
        {
            var criteria = CreateCriteria<ServiceRecordHistory>()
                .Add(Restrictions.Eq(ServiceRecordHistory.PropertyName_ServiceRecordOid, serviceRecordOid));


            return criteria.List<ServiceRecordHistory>().ToList();
        }

        public IEnumerable<ServiceRecord> FindEmployeeServiceRecordsWithoutCustomer(long pEmployeeOid, long? days)
        {

            var c = CreateCriteria<ServiceRecord>()
                  .Add(Restrictions.Eq(ServiceRecord.PropertyName_EmployeeOid, pEmployeeOid))
                  .Add(Restrictions.IsNull(ServiceRecord.PropertyName_CostBearer2SupportConceptOid));
			if (days.HasValue)
			{

				var minDate = DateTime.Now.Date.AddDays(-1 * days.Value);
				c.Add(Restrictions.Ge(ServiceRecord.PropertyName_Start, minDate));
			}

            return c.List<ServiceRecord>().ToList();
        }

		public IEnumerable<ServiceRecord> FindEmployeeServiceRecordsWithoutCustomerInSpan(long pEmployeeOid, DateTimeSpan period)
		{
			var criteria = CreateCriteria<ServiceRecord>()
				.Add(Restrictions.Eq(ServiceRecord.PropertyName_EmployeeOid, pEmployeeOid))
				.Add(Restrictions.IsNull(ServiceRecord.PropertyName_CostBearer2SupportConceptOid));

			if (period != null)
			{
				criteria =
					criteria.Add(
						Restrictions.Or(
							Restrictions.Between(ServiceRecord.PropertyName_Start, period.StartDateTime, period.EndDateTime),
							Restrictions.Between(ServiceRecord.PropertyName_End, period.StartDateTime, period.EndDateTime)));
			}

			return criteria.List<ServiceRecord>().ToList();
		}

		public IList<ServiceRecord> FindEmployeeServiceRecords(long pEmployeeOid, DateTimeSpan pSpan, long? customerOid, ServiceRecordTypeId? srTypeFilter)
        {
            var lCriteria = CreateCriteria<ServiceRecord>()
                  .Add(Restrictions.Eq(ServiceRecord.PropertyName_EmployeeOid, pEmployeeOid));

			if (pSpan != null)
				lCriteria.Add(Restrictions.Between(ServiceRecord.PropertyName_Start, pSpan.StartDateTime, pSpan.EndDateTime));
            if (customerOid != null)
                lCriteria.Add(Restrictions.Eq(ServiceRecord.PropertyName_CustomerOid, customerOid.Value));
			if (srTypeFilter.HasValue)
			{
				lCriteria.Add(Restrictions.Eq(ServiceRecord.PropertyName_ServiceRecordType, srTypeFilter.Value));
			}

            var result = lCriteria.List<ServiceRecord>().ToList();

            return result;
        }

        public IList<ServiceRecord> FindCustomerServiceRecords(long customerOid)
        {
            var lCriteria = CreateCriteria<ServiceRecord>()
                  .Add(Restrictions.Eq(ServiceRecord.PropertyName_CustomerOid, customerOid));

            return lCriteria.List<ServiceRecord>();
        }

		public IList<ServiceRecord> FindCustomerServiceRecords(long customerOid, DateTimeSpan pSpan, long? employeeOid, ServiceRecordTypeId? srTypeFilter)
        {
            var lCriteria = CreateCriteria<ServiceRecord>()
                  .Add(Restrictions.Between(ServiceRecord.PropertyName_Start, pSpan.StartDateTime, pSpan.EndDateTime))
                  .Add(Restrictions.Eq(ServiceRecord.PropertyName_CustomerOid, customerOid));

            if (employeeOid != null)
                lCriteria.Add(Restrictions.Eq(ServiceRecord.PropertyName_EmployeeOid, employeeOid.Value));
			if (srTypeFilter.HasValue)
			{
				lCriteria.Add(Restrictions.Eq(ServiceRecord.PropertyName_ServiceRecordType, srTypeFilter.Value));
			}
            return lCriteria.List<ServiceRecord>();
        }

        public IEnumerable<ServiceRecord> FindServiceRecordsInSpan(DateTimeSpan pSpan, ServiceRecordTypeId? srTypeFilter)
        {
            var lCriteria = CreateCriteria<ServiceRecord>()
                  .Add(Restrictions.Between(ServiceRecord.PropertyName_Start, pSpan.StartDateTime, pSpan.EndDateTime));
	        if (srTypeFilter.HasValue)
	        {
				lCriteria.Add(Restrictions.Eq(ServiceRecord.PropertyName_ServiceRecordType, srTypeFilter.Value));
	        }
            return lCriteria.List<ServiceRecord>().ToList();
        }

        public IEnumerable<AccountingTransaction> FindUnassignedAccountingTransactions()
        {
            return CreateCriteria<AccountingTransaction>()
                  .Add(Restrictions.IsNull(AccountingTransaction.PropertyName_CostBearer2SupportConcept))
                .List<AccountingTransaction>().ToList();
        }

        public IEnumerable<SupportConcept> FindSupportConcept(
         string pCustomerFirstName,
         string pCustomerLastName,
         string pCustomerReferenceNumber,
         DateTime? pFrom,
         DateTime? pTill)
        {
            var lCriteria = CreateCriteria<SupportConcept>();

            //if (pFrom != null)
            //    lCriteria.Add(Expression.Ge(SupportConcept.PropertyName_Start, pFrom));
            //if (pTill != null)
            //    lCriteria.Add(Expression.Le(SupportConcept.PropertyName_End, pTill));

            lCriteria = lCriteria.CreateCriteria(SupportConcept.PropertyName_Customer, JoinType.InnerJoin);

            if (!String.IsNullOrEmpty(pCustomerReferenceNumber))
                lCriteria.Add(Restrictions.Eq(Customer.PropertyName_ReferenceNumber, pCustomerReferenceNumber));

            if (!Utils.AreAllNullOrEmpty(pCustomerFirstName, pCustomerLastName))
                lCriteria.CreateCriteria(Customer.PropertyName_Person)
                  .Add(Restrictions.Like(Person.PropertyName_FirstName, pCustomerFirstName, MatchMode.Anywhere))
                  .Add(Restrictions.Like(Person.PropertyName_LastName, pCustomerLastName, MatchMode.Anywhere));

            return lCriteria.List<SupportConcept>();
        }

        public IEnumerable<SupportConcept> FindCurrentSupportConcepts()
        {
            return CreateCriteriaIsActive<SupportConcept>()
                //.Add(Expression.Ge(SupportConcept.PropertyName_End, DateTime.Now))
                .List<SupportConcept>();
        }

        public IEnumerable<SupportConcept> FindSupportConceptsInSpan(DateTimeSpan pSpan)
        {
            return CreateCriteriaIsActive<SupportConcept>()
                //.Add(Expression.Disjunction()
                //     .Add(Expression.Between(SupportConcept.PropertyName_Start, pSpan.StartDateTime, pSpan.EndDateTime))
                //     .Add(Expression.Between(SupportConcept.PropertyName_End, pSpan.StartDateTime, pSpan.EndDateTime))
                //     .Add(Expression.Conjunction()
                //         .Add(Expression.Le(SupportConcept.PropertyName_Start, pSpan.StartDateTime))
                //         .Add(Expression.Ge(SupportConcept.PropertyName_End, pSpan.EndDateTime))
                //         )
                //      )
                 .List<SupportConcept>();
        }

        public IEnumerable<SupportConcept> FindExpiringSupportConcepts(long? employeeOid, DateTime expiredUntil)
        {
            var c = CreateCriteriaIsActive<SupportConcept>();
            if (employeeOid == null)
            {
                return c
                    .CreateCriteria(SupportConcept.PropertyName_CostBearer2SupportConceptList, JoinType.InnerJoin)
                       .Add(Restrictions.Between(CostBearer2SupportConcept.PropertyName_ApprovedEndDate, DateTime.Now, expiredUntil))
                   .List<SupportConcept>();
            }

            return c
                .CreateAlias(SupportConcept.PropertyName_CostBearer2SupportConceptList, "cb2sc", JoinType.InnerJoin)
                .CreateAlias(SupportConcept.PropertyName_Customer, "c", JoinType.InnerJoin)
                .CreateAlias("c.Employee2CustomerList", "e2c", JoinType.InnerJoin)
                .Add(Restrictions.Between("cb2sc." + CostBearer2SupportConcept.PropertyName_ApprovedEndDate, DateTime.Now.Date, expiredUntil))
                .Add(Restrictions.Eq("e2c." + Employee2Customer.PropertyName_EmployeeOid, employeeOid.Value))
                .List<SupportConcept>().Distinct().ToList();
        }

        public IEnumerable<SupportConcept> FindSupportConceptsWithConferenceDate(long? employeeOid, DateTime conferenceDateUntil)
        {
            var c = CreateCriteriaIsActive<SupportConcept>();
            if (employeeOid == null)
            {
                return c
                   .Add(Restrictions.Between(SupportConcept.PropertyName_ConferenceDate, DateTime.Now, conferenceDateUntil))
                   .List<SupportConcept>();
            }

            return c
                .CreateAlias(SupportConcept.PropertyName_Customer, "c", JoinType.InnerJoin)
                .CreateAlias("c.Employee2CustomerList", "e2c", JoinType.InnerJoin)
                .Add(Restrictions.Between(SupportConcept.PropertyName_ConferenceDate, DateTime.Now.Date, conferenceDateUntil))
                .Add(Restrictions.Eq("e2c." + Employee2Customer.PropertyName_EmployeeOid, employeeOid.Value))
                .List<SupportConcept>().Distinct().ToList();
        }

        public IEnumerable<Person> FindPersonsHavingBirthday(DateTime birthdayUntil)
        {
            var ts = birthdayUntil.Subtract(DateTime.Now);
            var days = ts.Days + 1;

            return CreateCriteriaIsActive<Person>()
               .Add(Expression.Sql(new SqlString("dayofyear(CAST(CONCAT(Year(CURDATE()), '-', Month(" + Person.PropertyName_DateOfBirth + "), '-', Day(" + Person.PropertyName_DateOfBirth + ")) AS DATE )) between dayofyear(CURDATE()) and dayofyear(CURDATE()) + " + days)))
               .List<Person>();
        }


        public IEnumerable<Login> FindLastLogins(string loginName)
        {
            return CreateCriteria<Login>()
                .Add(Restrictions.Eq(Login.PropertyName_LoginName, loginName))
                .List<Login>();
        }

        public IEnumerable<Query> FindQuery(QueryType pType)
        {
            return CreateCriteria<Query>().Add(Restrictions.Eq(Query.PropertyName_Type, pType))
                .List<Query>().ToList();
        }

        public IList<AccountingTransaction> FindAccoutingTransactions(DateTimeSpan pSpan)
        {
            var lCriteria = CreateCriteriaIsActive<AccountingTransaction>();

            if (pSpan != null)
                lCriteria.Add(Restrictions.Between(AccountingTransaction.PropertyName_BookingDate, pSpan.StartDateTime, pSpan.EndDateTime));

            var test = lCriteria.List<AccountingTransaction>();

            return test;
        }

        public IEnumerable<AccountingTransaction> FindAccoutingTransactions(DateTimeSpan pSpan,
            long? pSupportConceptOid, long? pSupportConceptCostBearerRelOid)
        {
            var lCriteria = CreateCriteriaIsActive<AccountingTransaction>()
                .CreateAlias(AccountingTransaction.PropertyName_CostBearer2SupportConcept, "cb2sc", JoinType.LeftOuterJoin);

            if (pSpan != null)
                lCriteria.Add(Restrictions.Between(AccountingTransaction.PropertyName_BookingDate, pSpan.StartDateTime, pSpan.EndDateTime));

            if (pSupportConceptCostBearerRelOid != null)
                lCriteria.Add(Restrictions.Eq("cb2sc." + BeWoEntityBase.PropertyName_Oid, pSupportConceptCostBearerRelOid));

            if (pSupportConceptOid != null)
            {
                lCriteria.CreateCriteria("cb2sc." + CostBearer2SupportConcept.PropertyName_SupportConcept)
                    .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, pSupportConceptOid));
            }

            var test = lCriteria.List<AccountingTransaction>();

            return test;
        }

        public IList<Settings> FindSettingsByValuePart(SettingsType pType, string pValuePart)
        {
            return CreateCriteria<Settings>()
                  .Add(Restrictions.Eq(Settings.PropertyName_Type, pType))
                  .Add(Restrictions.Like(Settings.PropertyName_Value, pValuePart, MatchMode.Anywhere))
                  .List<Settings>();
        }

        public IList<FileAttachment> FindFileAttachments(TableID pObjTid, long pObjOid)
        {
            return CreateCriteriaIsActive<FileAttachment>()
                .Add(Restrictions.Eq(FileAttachment.PropertyName_ObjectOid, pObjOid))
                .Add(Restrictions.Eq(FileAttachment.PropertyName_ObjectTid, pObjTid))
                .List<FileAttachment>();
        }

        public IEnumerable<FileAttachmentInfo> FindFileAttachmentInfos(TableID pObjTid, long pObjOid)
        {
            return CreateCriteriaIsActive<FileAttachmentInfo>()
                .Add(Restrictions.Eq(FileAttachmentInfo.PropertyName_ObjectOid, pObjOid))
                .Add(Restrictions.Eq(FileAttachmentInfo.PropertyName_ObjectTid, pObjTid))
                .List<FileAttachmentInfo>();
        }

        public IList<BeWoFolder> FindBeWoFolders(TableID pObjTid, long pObjOid)
        {
            var c = CreateCriteriaIsActive<BeWoFolder>()
                .Add(Restrictions.Eq(BeWoFolder.PropertyName_ObjectTid, pObjTid));

            if (pObjOid > 0)
            {
                c.Add(Restrictions.Eq(BeWoFolder.PropertyName_ObjectOid, pObjOid));
            }
            return c.List<BeWoFolder>();
        }

        //public IList<SupportConcept> FindAllActiveApprovedLVRSupportConcepts()
        //{
        //    return CreateCriteriaIsActive<SupportConcept>()
        //        .CreateCriteria(SupportConcept.PropertyName_CostBearer2SupportConceptList, JoinType.InnerJoin)
        //        .Add(Expression.Eq(CostBearer2SupportConcept.PropertyName_Status, CostBearer2SupportConceptStatus.Approved))
        //        .CreateCriteria(CostBearer2SupportConcept.PropertyName_CostBearer, JoinType.InnerJoin)
        //        .Add(Expression.Eq(CostBearer.PropertyName_SystemEntryID, SystemEntryID.CostBearerLVR))
        //        .List<SupportConcept>();
        //}

        public IList<SupportConcept> FindAllActiveApprovedSupportConcepts()
        {
            return CreateCriteriaIsActive<SupportConcept>()
                .CreateCriteria(SupportConcept.PropertyName_CostBearer2SupportConceptList, JoinType.InnerJoin)
                .Add(Restrictions.Eq(CostBearer2SupportConcept.PropertyName_Status, CostBearer2SupportConceptStatus.Approved))

                .List<SupportConcept>().Distinct().ToList();
        }

        public Employee FindEmployeeWithPersonOid(long pPersonOid)
        {
            var person = DAOFactory.GenericDAO.LoadByID<Person>(pPersonOid);
            if (person != null)
            {
                return CreateCriteria<Employee>()
                    .Add(Restrictions.Eq(Employee.PropertyName_Person, person)).UniqueResult<Employee>();
            }
            return null;
        }

        public Customer FindCustomerWithPersonOid(long pPersonOid)
        {
            var person = DAOFactory.GenericDAO.LoadByID<Person>(pPersonOid);
            if (person != null)
            {
                return CreateCriteria<Customer>()
                    .Add(Restrictions.Eq(Customer.PropertyName_Person, person)).UniqueResult<Customer>();
            }
            return null;
        }

        public IList<Person> GetActivePersonsWithType(PersonType type)
        {
            return CreateCriteriaIsActive<Person>()
                .Add(Restrictions.Eq(Person.PropertyName_Type, type))
                .List<Person>();
        }

        public IEnumerable<Customer> GetAllActiveCustomersWithSupportConceptData()
        {
            return CreateCriteriaIsActiveOrArchived<Customer>()
                .CreateAlias(Customer.PropertyName_SupportConcepts, "sc", JoinType.LeftOuterJoin)
                .CreateCriteria("sc." + SupportConcept.PropertyName_CostBearer2SupportConceptList, JoinType.LeftOuterJoin)
				.Add(Restrictions.Eq("sc." + SupportConcept.PropertyName_IsActive, ActivationTypeId.Active))
                .List<Customer>();
        }

        public IEnumerable<Customer> GetAllActiveCustomersWithAddress()
        {
            return CreateCriteriaIsActive<Customer>()
                .CreateCriteria(Customer.PropertyName_Person, JoinType.LeftOuterJoin)
                .CreateCriteria(Person.PropertyName_Address, JoinType.LeftOuterJoin)
                .List<Customer>();
        }


		public IEnumerable<Customer> GetAllCustomersWithRelatedEmployee()
		{
			return CreateCriteria<Customer>()
				.CreateAlias(Customer.PropertyName_Person, "cp", JoinType.InnerJoin)
				.CreateAlias("cp." + Person.PropertyName_Address, "a", JoinType.LeftOuterJoin)
				.CreateAlias(Customer.PropertyName_Employee2CustomerList, "e2c", JoinType.LeftOuterJoin)
				.CreateAlias("e2c." + Employee2Customer.PropertyName_Employee, "e", JoinType.LeftOuterJoin)
				.CreateCriteria("e2c." + Employee2Customer.PropertyName_ValueList, JoinType.LeftOuterJoin)
				.CreateCriteria("e." + Employee.PropertyName_Person, JoinType.LeftOuterJoin)
				.List<Customer>();
		}

        public IList<ServiceRecord> FindServiceRecordsDetailsForLastDays(long costbearer2SupportConcept, long? days)
        {
            var c = CreateCriteria<ServiceRecord>()
                .Add(Restrictions.Eq(ServiceRecord.PropertyName_CostBearer2SupportConceptOid, costbearer2SupportConcept));

            if (days.HasValue)
            {
                
                var minDate = DateTime.Now.Date.AddDays(-1 * days.Value);
                c.Add(Restrictions.Ge(ServiceRecord.PropertyName_Start, minDate));
            }

            return c.CreateAlias(ServiceRecord.PropertyName_ValueList, "vl", JoinType.LeftOuterJoin)
                .CreateAlias(ServiceRecord.PropertyName_ServiceDescription, "sd", JoinType.InnerJoin)
                .CreateAlias("sd." + ServiceDescription.PropertyName_ServiceCategory, "sc", JoinType.InnerJoin)
                .CreateAlias(ServiceRecord.PropertyName_Employee, "e", JoinType.InnerJoin)
                .CreateCriteria("e." + Employee.PropertyName_Person, JoinType.InnerJoin)
                .List<ServiceRecord>();
        }

        public IList<ServiceRecord> FindServiceRecordsDetailWithServiceInfo(long costbearer2SupportConcept)
        {
            var c = CreateCriteria<ServiceRecord>()
                .Add(Restrictions.Eq(ServiceRecord.PropertyName_CostBearer2SupportConceptOid, costbearer2SupportConcept));

            
            return c.CreateAlias(ServiceRecord.PropertyName_ServiceDescription, "sd", JoinType.InnerJoin)
                .CreateAlias("sd." + ServiceDescription.PropertyName_ServiceCategory, "sc", JoinType.InnerJoin)
                .List<ServiceRecord>();
        }

        public Customer FindCustomerWithServiceRecordsWithDetail(long pCustomerOid)
        {
            return CreateCriteria<Customer>()
                .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, pCustomerOid))
                .CreateAlias(Customer.PropertyName_ServiceRecordList, "sr", JoinType.InnerJoin)
                .CreateCriteria("sr." + ServiceRecord.PropertyName_ValueList, JoinType.LeftOuterJoin)
                .CreateAlias("sr." + ServiceRecord.PropertyName_ServiceDescription, "sd", JoinType.InnerJoin)
                .CreateCriteria("sd." + ServiceDescription.PropertyName_ServiceCategory, JoinType.InnerJoin)
                .CreateAlias("sr." + ServiceRecord.PropertyName_CostBearer2SupportConcept, "c2s", JoinType.InnerJoin)
                .CreateCriteria("c2s." + CostBearer2SupportConcept.PropertyName_SupportConcept, JoinType.InnerJoin)
                .CreateAlias("c2s." + CostBearer2SupportConcept.PropertyName_CostBearer, "cb", JoinType.InnerJoin)
                .CreateAlias("cb." + CostBearer.PropertyName_Organisation, "org", JoinType.InnerJoin)
                .UniqueResult<Customer>();
        }

        public ServiceRecordGroup FindServiceRecordGroup(long pGroupOid)
        {
            return CreateCriteria<ServiceRecordGroup>()
                .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, pGroupOid))
                .CreateCriteria(ServiceRecordGroup.PropertyName_ServiceRecordList, JoinType.InnerJoin)
                .UniqueResult<ServiceRecordGroup>();
        }

        public IEnumerable<SupportConcept> GetAllActiveAndArchivedSupportConceptsCompact()
        {
            return CreateCriteria<SupportConcept>()
                .Add(Restrictions.Or(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active), Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Archived)))
                .CreateAlias(SupportConcept.PropertyName_CostBearer2SupportConceptList, "cb2sc", JoinType.LeftOuterJoin)
                .CreateAlias(SupportConcept.PropertyName_Customer, "c", JoinType.InnerJoin)
                .CreateAlias("c." + Customer.PropertyName_Person, "p", JoinType.InnerJoin)
                .CreateAlias("p." + Person.PropertyName_Address, "a", JoinType.LeftOuterJoin)
                .CreateAlias("c." + Customer.PropertyName_Employee2CustomerList, "e2c", JoinType.LeftOuterJoin)
                .List<SupportConcept>();
        }

		public IEnumerable<SupportConcept> GetAllSupportConceptsCompact()
		{
			return CreateCriteria<SupportConcept>()
				.CreateAlias(SupportConcept.PropertyName_CostBearer2SupportConceptList, "cb2sc", JoinType.LeftOuterJoin)
				.CreateAlias(SupportConcept.PropertyName_Customer, "c", JoinType.InnerJoin)
				.CreateAlias("c." + Customer.PropertyName_Person, "p", JoinType.InnerJoin)
				.CreateAlias("p." + Person.PropertyName_Address, "a", JoinType.LeftOuterJoin)
				.CreateAlias("c." + Customer.PropertyName_Employee2CustomerList, "e2c", JoinType.LeftOuterJoin)
				.List<SupportConcept>();
		}

		public IList<ListedSupportConcept> GetAllActiveAndArchivedListedSupportConceptsCompact()
		{
			return Session.CreateCriteria<ListedSupportConcept>()
				.List<ListedSupportConcept>();
		}

		public IList<ListedSupportConcept> GetAllActiveAndArchivedListedSupportConceptsCompact(List<long> oids)
		{
			return Session.CreateCriteria<ListedSupportConcept>()
				.Add(Restrictions.In("SupportConceptOid", oids))
				.List<ListedSupportConcept>();
		}

        public IList<Customer> GetAllCustomerWithServiceRecordsInSpan(DateTimeSpan pSpan)
        {
            return CreateCriteria<Customer>()
                .CreateCriteria(Customer.PropertyName_ServiceRecordList, JoinType.InnerJoin)
                .Add(Restrictions.Between(ServiceRecord.PropertyName_Start, pSpan.StartDateTime, pSpan.EndDateTime))
                .List<Customer>();
        }

        public IEnumerable<AccountingTransaction> GetAllAccountingTransactionsWithDetails()
        {
            return CreateCriteria<AccountingTransaction>()
                .AddOrder(Order.Desc(AccountingTransaction.PropertyName_BookingDate))
                .CreateAlias(AccountingTransaction.PropertyName_CostBearer2SupportConcept, "cb2sc", JoinType.LeftOuterJoin)
                .CreateCriteria("cb2sc." + CostBearer2SupportConcept.PropertyName_CostBearer, JoinType.LeftOuterJoin)
                .CreateCriteria(CostBearer.PropertyName_Organisation, JoinType.LeftOuterJoin)
                .CreateCriteria("cb2sc." + CostBearer2SupportConcept.PropertyName_SupportConcept, JoinType.LeftOuterJoin)
                .CreateCriteria(SupportConcept.PropertyName_Customer, JoinType.LeftOuterJoin)
                .CreateCriteria(Customer.PropertyName_Person, JoinType.LeftOuterJoin)
                .List<AccountingTransaction>();
        }

        public IEnumerable<SupportConcept> GetAllActiveAndArchivedSupportConcepts()
        {
            return CreateCriteria<SupportConcept>()
                .Add(Restrictions.Or(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active), Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Archived)))
                .CreateAlias(SupportConcept.PropertyName_CostBearer2SupportConceptList, "cb2sc", JoinType.InnerJoin)
                .CreateAlias("cb2sc." + CostBearer2SupportConcept.PropertyName_CostBearer, "cb", JoinType.InnerJoin)
                .CreateAlias("cb." + CostBearer.PropertyName_Organisation, "org", JoinType.InnerJoin)
                .CreateAlias(SupportConcept.PropertyName_Customer, "c", JoinType.InnerJoin)
                .CreateAlias("c." + Customer.PropertyName_Person, "p", JoinType.InnerJoin)
                .List<SupportConcept>();
        }

        public IEnumerable<Customer> GetAllActiveAndArchivedCustomersWithRelatedEmployee()
        {
            return CreateCriteria<Customer>()
                .Add(Restrictions.Or(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active), Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Archived)))
                .CreateAlias(Customer.PropertyName_Person, "cp", JoinType.InnerJoin)
                .CreateAlias("cp." + Person.PropertyName_Address, "a", JoinType.LeftOuterJoin)
                .CreateAlias(Customer.PropertyName_Employee2CustomerList, "e2c", JoinType.LeftOuterJoin)
                .CreateAlias("e2c." + Employee2Customer.PropertyName_Employee, "e", JoinType.LeftOuterJoin)
                .CreateCriteria("e2c." + Employee2Customer.PropertyName_ValueList, JoinType.LeftOuterJoin)
                .CreateCriteria("e." + Employee.PropertyName_Person, JoinType.LeftOuterJoin)
                .List<Customer>();
        }

        public IEnumerable<SettlementInvoice> GetSettlementInvoiceBySupportConceptOid(long supportConceptOid)
        {
            return CreateCriteriaIsActive<SettlementInvoice>()
                .CreateAlias(SettlementInvoice.PropertyName_InvoiceBase, "ib", JoinType.InnerJoin)
                .Add(Restrictions.Eq("ib." + InvoiceBase.PropertyName_SupportConceptOid, supportConceptOid))
                .List<SettlementInvoice>();
        }

		public IList<SettlementInvoice> GetSettlementInvoiceByCostBearer2SupportConceptOid(long costBearer2SupportConceptOid)
		{
			return CreateCriteriaIsActive<SettlementInvoice>()
				.CreateAlias(SettlementInvoice.PropertyName_InvoiceBase, "ib", JoinType.InnerJoin)
				.Add(Restrictions.Eq("ib." + InvoiceBase.PropertyName_CostBearer2SupportConceptOid, costBearer2SupportConceptOid))
				.List<SettlementInvoice>();
		}

        public IEnumerable<SettlementInvoice> GetSettlementInvoicesForCostBearerAndPeriod(long costBearerOid, DateTime periodStart, DateTime periodEnd)
        {
            return CreateCriteriaIsActive<SettlementInvoice>()
               .CreateAlias(SettlementInvoice.PropertyName_InvoiceBase, "ib", JoinType.InnerJoin)
               .CreateAlias("ib." + InvoiceBase.PropertyName_CostBearer2SupportConcept, "cb2sc", JoinType.InnerJoin)
               .CreateAlias("cb2sc." + CostBearer2SupportConcept.PropertyName_CostBearer, "cb", JoinType.InnerJoin)
               .Add(Restrictions.Eq("cb." + BeWoEntityBase.PropertyName_Oid, costBearerOid))
               .Add(Restrictions.Or(
                    Restrictions.Between("ib." + InvoiceBase.PropertyName_AccountingPeriodStart, periodStart, periodEnd),
                    Restrictions.Between("ib." + InvoiceBase.PropertyName_AccountingPeriodEnd, periodStart, periodEnd)))
               .List<SettlementInvoice>();
        }

        public IList<InvoiceBase> GetInvoiceBaseByTypeAndSupportConceptOid(InvoiceType type, long supportConceptOid)
        {
            return SearchInvoiceBase(type, InvoiceBase.PropertyName_SupportConceptOid, supportConceptOid);
        }

        public IEnumerable<InvoiceBase> GetInvoiceBaseByOrganisationOid(InvoiceType type, long organisationOid)
        {
            return SearchInvoiceBase(type, InvoiceBase.PropertyName_RecipientOrganisationOid, organisationOid);
        }

        public IEnumerable<InvoiceBase> GetInvoiceBaseByCustomerOid(InvoiceType type, long customerOid)
        {
            return SearchInvoiceBase(type, InvoiceBase.PropertyName_RecipientCustomerOid, customerOid);
        }

        public IEnumerable<InvoiceBase> GetInvoiceBaseByPersonOid(InvoiceType type, long personOid)
        {
            return SearchInvoiceBase(type, InvoiceBase.PropertyName_RecipientPersonOid, personOid);
        }

        private IList<InvoiceBase> SearchInvoiceBase(InvoiceType type, string propertyname, long fkOid)
        {
            return CreateCriteriaIsActive<InvoiceBase>()
                .Add(Restrictions.Eq(InvoiceBase.PropertyName_Type, type))
                .Add(Restrictions.Eq(propertyname, fkOid))
                .List<InvoiceBase>();
        }

        public SettlementInvoice GetSettlementInvoiceByInvoiceBaseOid(long invoiceBaseOid)
        {
            return CreateCriteriaIsActive<SettlementInvoice>()
                .CreateAlias(SettlementInvoice.PropertyName_InvoiceBase, "ib", JoinType.InnerJoin)
                .Add(Restrictions.Eq("ib." + BeWoEntityBase.PropertyName_Oid, invoiceBaseOid))
                .UniqueResult<SettlementInvoice>();
        }

        public ServiceInvoice GetServiceInvoiceByInvoiceBaseOid(long invoiceBaseOid)
        {
            var res = CreateCriteriaIsActive<ServiceInvoice>()
                .CreateAlias(ServiceInvoice.PropertyName_InvoiceBase, "ib", JoinType.InnerJoin)
                .Add(Restrictions.Eq("ib." + BeWoEntityBase.PropertyName_Oid, invoiceBaseOid))
                .UniqueResult<ServiceInvoice>();

            return res;
        }

        public IEnumerable<AssessmentSheetEntry> GetAssessmentSheetEntriesForCustomer(long customerOid, DateTime startDt, DateTime endDt)
        {
            
            
            return CreateCriteriaIsActive<AssessmentSheetEntry>()
                .CreateAlias(AssessmentSheetEntry.PropertyName_Customer, "c", JoinType.InnerJoin)
                .Add(Restrictions.Eq("c." + BeWoEntityBase.PropertyName_Oid, customerOid))
                .Add(Restrictions.Ge(AssessmentSheetEntry.PropertyName_Day, startDt))
                .Add(Restrictions.Lt(AssessmentSheetEntry.PropertyName_Day, endDt))
                .List<AssessmentSheetEntry>();
        }

        public IList<VarFieldDef> GetVarFieldDefs(TableID tid)
        {
            return CreateCriteriaIsActive<VarFieldDef>()
                .Add(Restrictions.Eq(VarFieldDef.PropertyName_ObjectTid, tid))
                .List<VarFieldDef>();
        }

        public IEnumerable<Task> FindTasksForEmployee(long employeeoid)
        {
            return CreateCriteriaIsActive<Task>()
                .CreateAlias(Task.PropertyName_SupportConcept, "sc", JoinType.InnerJoin)
                .CreateAlias("sc." + SupportConcept.PropertyName_Customer, "c", JoinType.InnerJoin)
                .CreateCriteria(Task.PropertyName_EmployeeList, JoinType.InnerJoin)
                .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, employeeoid))
                .Add(Restrictions.Eq("sc." + BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
                .Add(Restrictions.Eq("c." + BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
                .List<Task>();
        }

        public List<ServiceInvoice> GetServiceInvoices(long costBearerOid, long? supportConceptOid, DateTimeSpan period)
        {
            var criteria = CreateCriteriaIsActive<ServiceInvoice>()
              .CreateAlias(ServiceInvoice.PropertyName_InvoiceBase, "ib", JoinType.InnerJoin)
              .Add(Restrictions.Eq("ib." + InvoiceBase.PropertyName_RecipientCostBearerOid, costBearerOid))
			  .Add(Restrictions.Eq("ib." + BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active));

            if (supportConceptOid.HasValue)
                criteria = criteria
                    .Add(Restrictions.Eq("ib." + InvoiceBase.PropertyName_SupportConceptOid, supportConceptOid.Value));

            if (period != null)
                criteria = criteria
                    .Add(Restrictions.Or(
                                Restrictions.Or(
                                        Restrictions.Between("ib." + InvoiceBase.PropertyName_AccountingPeriodStart, period.StartDateTime, period.EndDateTime),
                                        Restrictions.Between("ib." + InvoiceBase.PropertyName_AccountingPeriodEnd, period.StartDateTime, period.EndDateTime)),
                                Restrictions.And(
                                        Restrictions.Le("ib." + InvoiceBase.PropertyName_AccountingPeriodStart, period.StartDateTime),
                                        Restrictions.Ge("ib." + InvoiceBase.PropertyName_AccountingPeriodEnd, period.EndDateTime))));

            return criteria.List<ServiceInvoice>().ToList();
        }

        public IEnumerable<AssessmentSheetCategory> GetAssessmentSheetCategoryListForCustomer(long customerOid)
        {

            return CreateCriteriaIsActive<AssessmentSheetCategory>()
                .CreateAlias(AssessmentSheetCategory.PropertyName_Customers, "c", JoinType.InnerJoin)
                .Add(Restrictions.Eq("c." + BeWoEntityBase.PropertyName_Oid, customerOid))
                .List<AssessmentSheetCategory>();

        }

        public IEnumerable<AbsenceTime> FindAbsenceTimes(bool fetchEmployees, bool fetchCustomers)
        {
            var criteria = CreateCriteriaIsActive<AbsenceTime>();
              
            if (!fetchEmployees)
                criteria = criteria
                    .Add(Restrictions.IsNull(AbsenceTime.PropertyName_EmployeeOid));
            else if (!fetchCustomers)
                criteria = criteria
                    .Add(Restrictions.IsNull(AbsenceTime.PropertyName_CustomerOid));

            return criteria.List<AbsenceTime>().ToList();

            
        }

        public IEnumerable<Appointment> FindAppointments(long? customerOid, long? employeeOid)
        {
            var criteria = CreateCriteriaIsActive<Appointment>();

            if (employeeOid.HasValue)
                criteria = criteria
                    .Add(Restrictions.Eq(AbsenceTime.PropertyName_EmployeeOid, employeeOid));

            if (customerOid.HasValue)
                criteria = criteria
                    .Add(Restrictions.Eq(AbsenceTime.PropertyName_CustomerOid, customerOid));

            return criteria.List<Appointment>().ToList();
        }

        public ServiceCategory FindDefaultIndividualServiceCategory()
        {
            return CreateCriteriaIsActive<ServiceCategory>()
                .Add(Restrictions.Eq(ServiceCategory.PropertyName_ScopeType, ScopeTypeId.Individual))
                .List<ServiceCategory>().FirstOrDefault();
        }

		public ServiceCategory FindServiceCategoryByName(String name)
		{
			return CreateCriteriaIsActive<ServiceCategory>()
				.Add(Restrictions.Eq(ServiceCategory.PropertyName_Name, name))
				.List<ServiceCategory>().FirstOrDefault();
		}

        public IEnumerable<FileAttachmentInfo> FindFileAttachmentInfoByType(FileAttachmentType type)
        {
            var criteria = CreateCriteria<FileAttachmentInfo>()
                .Add(Restrictions.Eq("Type", type));

            return criteria.List<FileAttachmentInfo>().ToList();
        }

		public IEnumerable<AssessmentSheetEntry> GetAdditionalAssessmentSheetEntries(DateTime dateTime)
		{
			return CreateCriteria<AssessmentSheetEntry>()
				.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_SystemEntryID, SystemEntryID.AdditionalServiceAssessmentSheet))
				.Add(Restrictions.Eq(AssessmentSheetEntry.PropertyName_Day, dateTime.Date))
				.List<AssessmentSheetEntry>();
		}

	    public IEnumerable<ResourceAppointment> GetResourceAppointmentExceptionsWithIndexAndId(string info)
	    {
		    return CreateCriteria<ResourceAppointment>()
				.Add(Restrictions.Like(ResourceAppointment.PropertyName_RecurrenceInfo, info))
				.List<ResourceAppointment>();

	    }

		public IEnumerable<AdditionalServiceBooking> GetAdditionalServiceBookings(long? regionOid, DateTime start, DateTime end)
		{
			var criteria = CreateCriteriaIsActive<AdditionalServiceBooking>()
				.Add(Restrictions.Between("Datum", start, end));

			if (regionOid.HasValue)
				criteria = criteria.CreateAlias(AdditionalServiceBooking.PropertyName_AdditionalServiceRegion, "asr", JoinType.InnerJoin)
					.Add(Restrictions.Eq("asr." + BeWoEntityBase.PropertyName_Oid, regionOid));

			return criteria.List<AdditionalServiceBooking>();
		}

		public IEnumerable<AdditionalServiceBooking> GetAdditionalServiceBookingsForCustomer(long customerOid, DateTime start, DateTime end)
		{
			return CreateCriteriaIsActive<AdditionalServiceBooking>()
				.CreateAlias(AdditionalServiceBooking.PropertyName_Customer2AddServiceBookings, "c2s", JoinType.InnerJoin)
				.Add(Restrictions.Between("Datum", start, end))
				.Add(Restrictions.Eq("c2s.CustomerOid", customerOid))
				.List<AdditionalServiceBooking>();
		}

		public AssessmentSheetCategory GetAddServiceAssessmentSheetCategoryWithName(string name)
		{
			return CreateCriteriaIsActive<AssessmentSheetCategory>()
				.Add(Restrictions.Eq(AssessmentSheetCategory.PropertyName_Description, name))
				.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_SystemEntryID, SystemEntryID.AdditionalServiceAssessmentSheet))
				.List<AssessmentSheetCategory>().FirstOrDefault();
		}

		public IList<ServiceRecord> GetBillableServiceRecords()
		{
			var c = CreateCriteria<ServiceRecord>()
				.CreateAlias(ServiceRecord.PropertyName_ServiceDescription, "sd", JoinType.InnerJoin)
				.CreateAlias("sd." + ServiceDescription.PropertyName_ServiceCategory, "sc", JoinType.InnerJoin)
				.Add(Restrictions.Eq("sc." + ServiceCategory.PropertyName_IsBillable, true));

			return c.List<ServiceRecord>();
		}

		public IEnumerable<ServiceDescription> FindServiceDescriptionForCategory(long categoryOid)
		{
			var c = CreateCriteriaIsActive<ServiceDescription>()
				.CreateAlias(ServiceDescription.PropertyName_ServiceCategory, "sc", JoinType.InnerJoin)
				.Add(Restrictions.Eq("sc."+ BeWoEntityBase.PropertyName_Oid, categoryOid));

			return c.List<ServiceDescription>();
		}

		public IEnumerable<ServiceAccounting> FindServiceAccountingsForServiceDescriptions(IList<long> descriptionOids)
		{
			var c = CreateCriteriaIsActive<ServiceAccounting>()
				.CreateAlias("ServiceDescription", "sd", JoinType.InnerJoin)
				.Add(Restrictions.In("sd." + BeWoEntityBase.PropertyName_Oid, descriptionOids.ToArray()));

			return c.List<ServiceAccounting>();
		}

		public IList<Medikamentenverordnungsliste> GetAllMedikamentenverordnungslistenButNewestByCustomerOid(long customerOid, long newestOid, bool isBedarfsListe)
		{
			var c = CreateCriteria<Medikamentenverordnungsliste>()
				.CreateAlias(Medikamentenverordnungsliste.PropertyName_Customer, "c")
				.Add(Restrictions.Eq("c." + BeWoEntityBase.PropertyName_Oid, customerOid))
				.Add(Restrictions.Not(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, newestOid)))
				.Add(Restrictions.Eq(Medikamentenverordnungsliste.PropertyName_MedListType, isBedarfsListe));

			return c.List<Medikamentenverordnungsliste>();
		}

		public IList<SchedulerAppointment> GetAllOpenAppointmentsForEmployee(long employeeOid)
		{
			var c = CreateCriteria<SchedulerAppointment>()
				.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
				.Add(Restrictions.Not(Restrictions.Eq(SchedulerAppointment.PropertyName_Originator + ".Oid", employeeOid)))
				.CreateCriteria(SchedulerAppointment.PropertyName_EmployeeList)
				.Add(Restrictions.And(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", employeeOid),
					Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_ParticipationAnswer, ParticipationAnswer.Offen)));

			return c.List<SchedulerAppointment>();
		}

	    public IEnumerable<SchedulerAppointment> GetAllParticipationNotificationsForEmployee(long employeeOid)
	    {
			var c = CreateCriteria<SchedulerAppointment>()
				.Add(Restrictions.And(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active), Restrictions.Eq(SchedulerAppointment.PropertyName_Originator + ".Oid", employeeOid)))
				.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
				.CreateCriteria(SchedulerAppointment.PropertyName_EmployeeList)
				.Add(Restrictions.And(Restrictions.And(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_IsPChanged, true), Restrictions.Not(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", employeeOid))), Restrictions.Not(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_ParticipationAnswer, ParticipationAnswer.Offen))))
				.Add(Restrictions.IsNull(Employee2SchedulerAppointment.PropertyName_IsPC_CheckedTs));

		    var result = c.List<SchedulerAppointment>();

			return result;
	    }

		public IEnumerable<Employee2SchedulerAppointment> GetRemovedEmp2AppObjectsBySchAppOid(long schAppOid)
		{
			var c = CreateCriteria<Employee2SchedulerAppointment>()
				.Add(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment, schAppOid));

			return c.List<Employee2SchedulerAppointment>();
		}

	    public IEnumerable<SchedulerAppointment> GetAllActiveAndNotDeclinedForEmployeeAppointments(long employeeOid)
	    {
		    var detachedCriteria = DetachedCriteria.For<Employee2SchedulerAppointment>()
				.Add(Restrictions.And(Restrictions.Not(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", employeeOid)),
									  Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_ParticipationAnswer, ParticipationAnswer.Absage)));
		    detachedCriteria.SetProjection(Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment));

		    var crit = CreateCriteria<SchedulerAppointment>()
			    .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
				.Add(Restrictions.Or(Restrictions.Eq(SchedulerAppointment.PropertyName_Originator + ".Oid", employeeOid), Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria)));

			return crit.List<SchedulerAppointment>();
	    }

	    public bool ResetPasswordCodeExists(string code, long userOid)
	    {
		    var c = CreateCriteria<ApplicationUser>()
			    .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, userOid))
			    .CreateCriteria(ApplicationUser.PropertyName_ResetPasswordInfos)
			    .Add(Restrictions.Eq(ResetPasswordInfo.PropertyName_Code, code));

		    return c.List<ApplicationUser>().Count > 0;
	    }

		public bool OverlappingAppointmentsExist(DateTime start, DateTime end, IEnumerable<long> employees, IEnumerable<long> customers, IEnumerable<long> resources, long originator, long? appointmentOid, string recurrenceId = "", int occurrenceIndex = 0)
	    {
            var criteria = CreateCriteria<SchedulerAppointment>()
                .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
                .Add(Restrictions.Or(
                        Restrictions.Or(
                            Restrictions.And(
                                Restrictions.Gt(SchedulerAppointment.PropertyName_EndDate, start),
                                Restrictions.Lt(SchedulerAppointment.PropertyName_EndDate, end)
                            ),
                            Restrictions.And(
                                Restrictions.Gt(SchedulerAppointment.PropertyName_StartDate, start),
                                Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, end)
                            )
                        ),
                        Restrictions.Or(
                            Restrictions.And(
                                Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, start),
                                Restrictions.Gt(SchedulerAppointment.PropertyName_EndDate, start)
                            ),
                            Restrictions.And(
                                Restrictions.Eq(SchedulerAppointment.PropertyName_StartDate, start),
                                Restrictions.Eq(SchedulerAppointment.PropertyName_EndDate, end)
                            )
                        )
                    )
                );

            // TODO: nicht wichtig - ignorieren
            // TODO: RecurrenceInfo in die Parameter aufnehmen (wie beim Laden der Termine)
            // TODO: Periodicity beachten! OR RecurrenceInfo NOT LIKE '%Range%' AND RecurrenceInfo NOT LIKE '%Index%'
            // OR RecurrenceInfo NOT LIKE '%Range%' AND RecurrenceInfo NOT LIKE '%Index%'

            //var recurrenceBetween = String.Format(
            //    "'{0} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s') " +
            //    "AND(" +
            //       "(" +
            //           "(" +
            //                "TIME({5}) > '{2}' AND TIME({5}) < '{3}'" +
            //            ") " +
            //            "OR(" +
            //                "TIME({4}) > '{2}' AND TIME({4}) < '{3}'" +
            //            ")" +
            //        ") " +
            //        "OR (" +
            //            "(" +
            //                "TIME({4}) > '{2}' AND TIME({5}) < '{2}'" +
            //            ") " +
            //            "OR(" +
            //                "TIME({4}) > '{2}' AND TIME({5}) < '{3}'" +
            //            ")" +
            //          ")" +
            //        ") OR {1} NOT LIKE '%Range=\"%' AND Type <> 3 AND Type <> 4",
            //    start.ToString("yyyy-MM-dd"),
            //    SchedulerAppointment.PropertyName_RecurrenceInfo,
            //    start.ToString("HH:mm:ss"),
            //    end.ToString("HH:mm:ss"),
            //    SchedulerAppointment.PropertyName_StartDate,
            //    SchedulerAppointment.PropertyName_EndDate);

            //criteria = CreateCriteria<SchedulerAppointment>()
            //    .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
            //    .Add(Restrictions.Or(
            //            Restrictions.Or(
            //                Restrictions.Or(
            //                    Restrictions.And(
            //                        Restrictions.Gt(SchedulerAppointment.PropertyName_EndDate, start),
            //                        Restrictions.Lt(SchedulerAppointment.PropertyName_EndDate, end)
            //                    ),
            //                    Restrictions.And(
            //                        Restrictions.Gt(SchedulerAppointment.PropertyName_StartDate, start),
            //                        Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, end)
            //                    )
            //                ),
            //                Restrictions.Or(
            //                    Restrictions.And(
            //                        Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, start),
            //                        Restrictions.Gt(SchedulerAppointment.PropertyName_EndDate, start)
            //                    ),
            //                    Restrictions.And(
            //                        Restrictions.Eq(SchedulerAppointment.PropertyName_StartDate, start),
            //                        Restrictions.Eq(SchedulerAppointment.PropertyName_EndDate, end)
            //                    )
            //                )
            //            ),
            //            Expression.Sql(new SqlString(recurrenceBetween))
            //        )
            //    );

			if (appointmentOid != null)
			{
			    criteria.Add(Restrictions.Not(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, appointmentOid)));
			}

		    var appTmp = criteria.List<SchedulerAppointment>();

            var appointments = appTmp.Where(a =>
			{
				if (a.RecurrenceInfo == null)
				{
				    return true;
				}

				var recId = GetSpecificValueFromRecurrenceInfo(a.RecurrenceInfo, a.RecurrenceInfo.IndexOf("Id=\"") + 4);
				var index = GetSpecificValueFromRecurrenceInfo(a.RecurrenceInfo, a.RecurrenceInfo.IndexOf("Index=\"") + 7);
				int intIndex;
				Int32.TryParse(index, out intIndex);

				return !(recurrenceId.Equals(recId) && occurrenceIndex == intIndex);
			});

			var schedulerAppointments = appointments as IList<SchedulerAppointment> ?? appointments.ToList();

			var oidList = new List<long>();
			foreach (var appointment in schedulerAppointments)
			{
				oidList.AddRange(appointment.EmployeeList.Select(rel => rel.Employee.Oid != null ? rel.Employee.Oid.Value : 0));
			}

			var emp = oidList.Intersect(employees).Any();
			var cus = schedulerAppointments.Any(app => app.CustomerList.Select(c => c.Oid != null ? c.Oid.Value : 0).Intersect(customers).Any());
			var res = schedulerAppointments.Any(app => app.ResourceList.Select(r => r.Oid != null ? r.Oid.Value : 0).Intersect(resources).Any());

			var ori = schedulerAppointments.Any(app => app.Originator.Oid.HasValue && app.Originator.Oid.Value == originator && (app.EmployeeList.Count == 0 || app.EmployeeList.Any(a => a.Employee.Oid.HasValue && a.Employee.Oid.Value == originator)));

			return emp || cus || res || ori;
	    }

		public IEnumerable<SchedulerAppointment> GetAllActiveAppointmentsForEmployeeInInterval(DateTime start, DateTime end, long pEmployeeOid)
	    {
			var detachedCriteria = DetachedCriteria.For<Employee2SchedulerAppointment>()
			    .Add(Restrictions.And(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", pEmployeeOid),
					Restrictions.Not(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_ParticipationAnswer, ParticipationAnswer.Absage))));
			detachedCriteria.SetProjection(Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment));

			var recurrenceBetween = String.Format("'{0} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s')", 
				start.ToString("yyyy-MM-dd"), 
				SchedulerAppointment.PropertyName_RecurrenceInfo);

			var hasResources = String.Format("{0} IN (SELECT newschappoid FROM resource2newschapp)", BeWoEntityBase.PropertyName_Oid);

		    var criteria = CreateCriteria<SchedulerAppointment>()
			    .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
			    .Add(Restrictions.Or(
						Restrictions.And(
							Restrictions.Not(Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "Range", MatchMode.Anywhere)), 
							Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "OccurrenceCount=\"10\"", MatchMode.Anywhere)), 
						Restrictions.Or(
							Restrictions.Or(
								Restrictions.And(Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, end), Restrictions.Ge(SchedulerAppointment.PropertyName_EndDate, start)),
								Restrictions.And(Restrictions.IsNotNull(SchedulerAppointment.PropertyName_RecurrenceInfo), Expression.Sql(new SqlString(recurrenceBetween)))), 
							Restrictions.And(Restrictions.Eq(SchedulerAppointment.PropertyName_Type, 3), Expression.Sql(new SqlString(recurrenceBetween))))))
				.Add(Restrictions.Or(
						Expression.Sql(new SqlString(hasResources)), 
						Restrictions.Or(
							Restrictions.Eq(SchedulerAppointment.PropertyName_Originator + ".Oid", pEmployeeOid), 
							Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria))));

			return criteria.List<SchedulerAppointment>();
	    }

		public IEnumerable<SchedulerAppointment> GetAllActiveAppointmentsInInterval(DateTime start, DateTime end)
		{
			var recurrenceBetween = String.Format("'{0} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s')", start.ToString("yyyy-MM-dd"), SchedulerAppointment.PropertyName_RecurrenceInfo);

			var criteria = CreateCriteria<SchedulerAppointment>()
				.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
				.Add(Restrictions.Or(
						Restrictions.And(Restrictions.Not(Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "Range", MatchMode.Anywhere)), 
							Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "OccurrenceCount=\"10\"", MatchMode.Anywhere)), 
						Restrictions.Or(
							Restrictions.Or(
                                Restrictions.And(Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, end), Restrictions.Ge(SchedulerAppointment.PropertyName_EndDate, start)),
								Restrictions.And(Restrictions.IsNotNull(SchedulerAppointment.PropertyName_RecurrenceInfo), Expression.Sql(new SqlString(recurrenceBetween)))), 
							Restrictions.And(Restrictions.Eq(SchedulerAppointment.PropertyName_Type, 3), Expression.Sql(new SqlString(recurrenceBetween))))));

			return criteria.List<SchedulerAppointment>();
		}

		static string GetSpecificValueFromRecurrenceInfo(string str, int startIndex)
		{
			var valueBuilder = new StringBuilder();

			for (; startIndex < str.Length; startIndex++)
			{
				var cr = str[startIndex];

				if (cr.Equals('"'))
					break;

				valueBuilder.Append(cr);
			}

			return valueBuilder.ToString();
		}

		public ResourceBooking GetFirstResourceBookingFromSequence(long sequenceOid)
	    {
			return CreateCriteria<ResourceBooking>()
				.Add(Restrictions.Eq(ResourceBooking.PropertyName_SequencePosition, 0))
				.CreateAlias(ResourceBooking.PropertyName_Sequence, "s")
				.Add(Restrictions.Eq("s." + BeWoEntityBase.PropertyName_Oid, sequenceOid)).UniqueResult<ResourceBooking>();
	    }

	    public List<int> GetExcludedBookingSequencePositions(long sequenceOid)
	    {
		    var c = CreateCriteria<ResourceBooking>()
			    .Add(Restrictions.Gt(ResourceBooking.PropertyName_SequencePosition, 0))
			    .CreateAlias(ResourceBooking.PropertyName_Sequence, "s")
			    .Add(Restrictions.Eq("s." + BeWoEntityBase.PropertyName_Oid, sequenceOid)).List<ResourceBooking>();

			return c.Select(s => s.SequencePosition).ToList();
	    }

		public IEnumerable<InvoiceBase> GetInvoiceBases(DateTime? startDate, DateTime? endDate)
		{
			var lCriteria = CreateCriteriaIsActive<InvoiceBase>();
			if (startDate.HasValue)
				lCriteria.Add(Restrictions.Ge(InvoiceBase.PropertyName_InvoiceDate, startDate));
			if (endDate.HasValue)
				lCriteria.Add(Restrictions.Le(InvoiceBase.PropertyName_InvoiceDate, endDate));

			return lCriteria.List<InvoiceBase>();
		}

	    public IEnumerable<SupportConcept> GetAllActiveSupportConceptsByCustomers(List<long> customerOids, bool expiredOnesToo = false)
	    {
		    var c = CreateCriteria<SupportConcept>()
				.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
				.CreateAlias(SupportConcept.PropertyName_Customer, "c")
				.Add(Restrictions.In("c." + BeWoEntityBase.PropertyName_Oid, customerOids));

		    if (expiredOnesToo)
		    {
			    
		    }

		    return c.List<SupportConcept>();
	    }

	    public IEnumerable<ServiceRecord> FindServiceRecordsForDays(long? costBearer2SupportConceptOid, int dayCount, long? employeeOid)
	    {
			var minStart = DateTime.Now.AddDays(-dayCount);
		    var c = CreateCriteriaIsActive<ServiceRecord>();

		    if (costBearer2SupportConceptOid.HasValue)
		    {
			    c.Add(Restrictions.Eq(ServiceRecord.PropertyName_CostBearer2SupportConceptOid, costBearer2SupportConceptOid));
		    }
		    else
		    {
				c.Add(Restrictions.Eq(ServiceRecord.PropertyName_EmployeeOid, employeeOid))
				 .Add(Restrictions.IsNull(ServiceRecord.PropertyName_CostBearer2SupportConceptOid));
		    }

		    if (dayCount > 0)
		    {
				c.Add(Restrictions.Ge(ServiceRecord.PropertyName_Start, minStart));
		    }

		    return c.List<ServiceRecord>();
	    }

		// Veraltet
		public IEnumerable<SchedulerAppointment> FindAppointmentsForPrintingForEmployee(long employeeOid, List<DateTime> selectedDates, List<UserRightType> userRights)
	    {
		    var abfrage = string.Format("SELECT Oid FROM newschedulerappointment WHERE IsActive = 1 AND ");
		    var or = string.Empty;

			foreach (var d in selectedDates)
			{
				or += string.Format("StartDate LIKE '{0}%' OR RecurrenceInfo IS NOT NULL AND '{0} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s')", d.ToString("yyyy-MM-dd"), SchedulerAppointment.PropertyName_RecurrenceInfo);
				if (selectedDates.IndexOf(d) < selectedDates.Count - 1)
				{
					or += " OR ";
				}
			}

		    abfrage += or;
		    var sa = Session.CreateSQLQuery(abfrage);
		    var l = sa.List<long>().ToList();

		    var c = CreateCriteria<SchedulerAppointment>()
                .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
			    .Add(Restrictions.In(BeWoEntityBase.PropertyName_Oid, l));

			c.CreateCriteria(SchedulerAppointment.PropertyName_EmployeeList)
			    .Add(Restrictions.And(
				     Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", employeeOid),
				     Restrictions.Not(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_ParticipationAnswer, ParticipationAnswer.Absage))));

		    return c.List<SchedulerAppointment>();
	    }

        public IEnumerable<Textbaustein> GetActiveTextbausteineByServiceCategory(long pServiceCategoryOid)
        {
            var c = CreateCriteriaIsActive<Textbaustein>();

            c.Add(Restrictions.Or(Restrictions.Eq(Textbaustein.PropertyName_ServiceCategory + ".Oid", pServiceCategoryOid), Restrictions.IsNull(Textbaustein.PropertyName_ServiceCategory)));

            return c.List<Textbaustein>();
        }

		public IEnumerable<SchedulerAppointment> GetAllActiveAppointmentsForEmployeeInInterval2(DateTime start, DateTime end, List<long> pEmployeeOids)
		{
			var detachedCriteria = DetachedCriteria.For<Employee2SchedulerAppointment>()
				.Add(Restrictions.And(Restrictions.In(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", pEmployeeOids),
					Restrictions.Not(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_ParticipationAnswer, ParticipationAnswer.Absage))));
			detachedCriteria.SetProjection(Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment));

			var recurrenceBetween = String.Format("'{0} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s')",
				start.ToString("yyyy-MM-dd"),
				SchedulerAppointment.PropertyName_RecurrenceInfo);

			var hasResources = String.Format("{0} IN (SELECT newschappoid FROM resource2newschapp)", BeWoEntityBase.PropertyName_Oid);

			var criteria = CreateCriteria<SchedulerAppointment>()
				.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
				.Add(Restrictions.Or(
						Restrictions.And(
							Restrictions.Not(Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "Range", MatchMode.Anywhere)),
							Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "OccurrenceCount=\"10\"", MatchMode.Anywhere)),
						Restrictions.Or(
							Restrictions.Or(
                                Restrictions.And(Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, end), Restrictions.Ge(SchedulerAppointment.PropertyName_EndDate, start)),
								Restrictions.And(Restrictions.IsNotNull(SchedulerAppointment.PropertyName_RecurrenceInfo), Expression.Sql(new SqlString(recurrenceBetween)))),
							Restrictions.And(Restrictions.Eq(SchedulerAppointment.PropertyName_Type, 3), Expression.Sql(new SqlString(recurrenceBetween))))))
				.Add(Restrictions.Or(
						Expression.Sql(new SqlString(hasResources)),
						Restrictions.Or(
							Restrictions.In(SchedulerAppointment.PropertyName_Originator + ".Oid", pEmployeeOids),
							Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria))));

			return criteria.List<SchedulerAppointment>();
		}

	    public IEnumerable<long> FilterEmployeesWithAppointments(List<long> pEmployeeOids, DateTime pStartTime, DateTime pEndTime)
	    {
			// Testzeitraum vom 10.08.2015 18:00 bis zum 10.08.2015 18:30
		    var result            = new List<long>();
			var appointments      = GetAllActiveAppointmentsForEmployeeInInterval2(pStartTime, pEndTime, pEmployeeOids);
			var gefilterteTermine = appointments.Where(w => w.EmployeeList.Select(s => s.Employee.Oid.Value).Intersect(pEmployeeOids).Any() || !w.EmployeeList.Select(s => s.Employee.Oid.Value).Intersect(pEmployeeOids).Any() && pEmployeeOids.Contains(w.Originator.Oid.Value));

		    foreach (var x in gefilterteTermine)
		    {
				result.AddRangeIfElementsNotIn(x.EmployeeList.Select(s => s.Oid.Value));
				result.AddIfNotIn(x.Originator.Oid.Value);
		    }

		    var c = CreateCriteria<AbsenceTime>()
				.Add(Restrictions.In(AbsenceTime.PropertyName_EmployeeOid, pEmployeeOids))
				.Add(Restrictions.Or(
						Restrictions.Or(
								Restrictions.Or(
										Restrictions.And(
											Restrictions.Eq(AbsenceTime.PropertyName_Start, pStartTime), 
											Restrictions.Eq(AbsenceTime.PropertyName_End, pEndTime)), 
										Restrictions.And(
											Restrictions.And(
												Restrictions.Lt(AbsenceTime.PropertyName_Start, pStartTime), 
												Restrictions.Lt(AbsenceTime.PropertyName_End, pStartTime)),
											Restrictions.Gt(AbsenceTime.PropertyName_End, pEndTime))), 
										Restrictions.And(
											Restrictions.Lt(AbsenceTime.PropertyName_Start, pStartTime), 
											Restrictions.Gt(AbsenceTime.PropertyName_End, pStartTime))),
										Restrictions.And(
											Restrictions.Gt(AbsenceTime.PropertyName_Start, pStartTime),
											Restrictions.Lt(AbsenceTime.PropertyName_End, pEndTime))));

		    var abwesenheiten = c.List<AbsenceTime>();

		    foreach (var abwesenheit in abwesenheiten)
		    {
			    result.AddIfNotIn(abwesenheit.EmployeeOid.Value);
		    }

		    return result;
	    }
 
        public IEnumerable<Task> GetTasksForEmployeeByDate(long employeeOid,DateTime date){
            var c = CreateCriteria<Task>().Add(Restrictions.Between(Task.PropertyName_DueDate, date,date.AddDays(1))).
                CreateCriteria(Task.PropertyName_EmployeeList, JoinType.InnerJoin) 
                .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, employeeOid)).List<Task>();
            

        return c;
        }

        public Wohnheimbuchung GetWohnheimbuchungByWohnheimAndBuchungsdatum(long pWohnheimOid, DateTime pBuchungsdatum)
        {
            var c = CreateCriteriaIsActive<Wohnheimbuchung>();

            c.Add(Restrictions.Eq(Wohnheimbuchung.PropertyName_Buchungsdatum, pBuchungsdatum))
                .Add(Restrictions.Eq(String.Format("{0}.Oid", Wohnheimbuchung.PropertyName_Wohnheim), pWohnheimOid));

            return c.UniqueResult<Wohnheimbuchung>();
        }

        public List<ServiceRecord> FindWohnheimbuchungsServiceRecords(long pWohnheimbuchungsOid)
        {
            var c = CreateCriteria<ServiceRecord>()
                .Add(Restrictions.Eq(ServiceRecord.PropertyName_WohnheimbuchungsOid, pWohnheimbuchungsOid));

            return c.List<ServiceRecord>().ToList();
        }

        public bool CheckIfUserGroupIsLastWithUserGroupEditingRights(List<long> pUserGroupOids)
        {
            var dc = DetachedCriteria.For<UserGroup>()
                .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active))
                .SetProjection(Projections.Property(BeWoEntityBase.PropertyName_Oid));

            var c = CreateCriteriaIsActive<RightRelation>()
                .Add(Restrictions.Not(Restrictions.In(RightRelation.PropertyName_UserGroupOid, pUserGroupOids)))
                .Add(Restrictions.In(RightRelation.PropertyName_RightType, new[] { UserRightType.UserGroupView_View, UserRightType.UserGroupView_Edit, UserRightType.ViewAll, UserRightType.EditAll }))
                .Add(Subqueries.PropertyIn(RightRelation.PropertyName_UserGroupOid, dc));

            var result = c.List<RightRelation>();
            var nachUserGroupOidSortiert = new Dictionary<long, List<UserRightType>>();

            foreach (var relation in result)
            {
                nachUserGroupOidSortiert.AddOrUpdateValueInDictionary(relation.UserGroupOid.Value, relation.RightType);
            }

            var minRights2 = nachUserGroupOidSortiert.Any(intersection => 
                            intersection.Value.Contains(UserRightType.UserGroupView_Edit) && intersection.Value.Contains(UserRightType.ViewAll) ||
                            intersection.Value.Contains(UserRightType.UserGroupView_Edit) && intersection.Value.Contains(UserRightType.UserGroupView_View) ||
                            intersection.Value.Contains(UserRightType.EditAll) && intersection.Value.Contains(UserRightType.ViewAll) ||
                            intersection.Value.Contains(UserRightType.EditAll) && intersection.Value.Contains(UserRightType.UserGroupView_View));
            
            return minRights2 == false;
        }

        public ServiceDescription FindServiceDescriptionForWohnheimbuchungsServiceRecord(long pWohnheimbuchungsOid)
        {
            var dc = DetachedCriteria.For<ServiceRecord>()
                .Add(Restrictions.Eq(ServiceRecord.PropertyName_WohnheimbuchungsOid, pWohnheimbuchungsOid))
                .SetProjection(Projections.Property(ServiceRecord.PropertyName_ServiceDescription + ".Oid"));

            var c = CreateCriteriaIsActive<ServiceDescription>()
                .Add(Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, dc)).SetMaxResults(1);

            return c.List<ServiceDescription>().FirstOrDefault();
        }

        public IEnumerable<Bargeldkasse> FindBargeldkasse(TableID objectTid, long objectOid)
        {
            var c = CreateCriteriaIsActive<Bargeldkasse>()
                .Add(Restrictions.Eq(Bargeldkasse.PropertyName_ObjectTid, objectTid))
                .Add(Restrictions.Eq(Bargeldkasse.PropertyName_ObjectOid, objectOid));

            return c.List<Bargeldkasse>().ToList();
        }

        public IEnumerable<MedRecord> FindMedRecordsForCustomer(long pCustomerOid)
        {
            var c = CreateCriteriaIsActive<MedRecord>()
                .Add(Restrictions.Eq(MedRecord.PropertyName_Customer + ".Oid", pCustomerOid));

            return c.List<MedRecord>().ToList();
        }

        public IEnumerable<Customer> FindAllChatActiveCustomers()
        {
            var c = CreateCriteriaIsActive<CustomerAPPCode>()
                .Add(Restrictions.Eq(CustomerAPPCode.PropertyName_IsChatAktiv, 1));

            var codes = c.List<CustomerAPPCode>().Select(s => s.CustomerOid.Value).ToArray();

            var c2 = CreateCriteriaIsActive<Customer>()
                .Add(Restrictions.In(BeWoEntityBase.PropertyName_Oid, codes));

            return c2.List<Customer>();
        }

        public IEnumerable<ChatMessage> FindAllChatMessages(long senderOid, long empfaengerOid)
        {
            var c = CreateCriteriaIsActive<ChatMessage>()
                .Add(Restrictions.Eq(ChatMessage.PropertyName_SenderPersonOid, senderOid))
                .Add(Restrictions.Eq(ChatMessage.PropertyName_EmpfängerPersonOid, empfaengerOid));

            return c.List<ChatMessage>();
        }

        public IEnumerable<Employee> FindAllChatActiveEmployees()
        {
            var c = CreateCriteriaIsActive<EmployeeAPPCode>()
                .Add(Restrictions.Eq(EmployeeAPPCode.PropertyName_IsChatAktiv, 1));

            var codes = c.List<EmployeeAPPCode>().Select(s => s.EmployeeOid.Value).ToArray();

            var c2 = CreateCriteriaIsActive<Employee>()
                .Add(Restrictions.In(BeWoEntityBase.PropertyName_Oid, codes));

            return c2.List<Employee>();
        }

        public IEnumerable<EmployeeAPPCode> FindAllEmployeeAppCodes(long oid)
        {
            var c = CreateCriteriaIsActive<EmployeeAPPCode>()
                .Add(Restrictions.Eq(EmployeeAPPCode.PropertyName_EmployeeOid, oid));
                

            return c.List<EmployeeAPPCode>();
        }

        public IEnumerable<CustomerAPPCode> FindAllCustomerAppCodes(long oid)
        {
            var c = CreateCriteriaIsActive<CustomerAPPCode>()
                .Add(Restrictions.Eq(CustomerAPPCode.PropertyName_CustomerOid, oid));


            return c.List<CustomerAPPCode>();
        }





	}
}
