using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;

using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.Core;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Plugins;
using BeWo.Service.ServiceContracts;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using BS.Shared.Services;
using Newtonsoft.Json;
using NHibernate;

using Utils = BeWo.Service.Core.Utils;

namespace BeWo.Service.ServiceImplementations
{
	[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
	public class CustomerServiceImp : ICustomerService
	{
		public void ArchiveCustomer(long pOid, long pVersion)
		{
			var c = DAOFactory.GenericDAO.LoadByID<Customer>(pOid);
			c.Person.IsActive = ActivationTypeId.Archived;


			ServiceLogic.SetActivationType<Customer>(pOid, pVersion, ActivationTypeId.Archived);

			foreach (var sc in c.SupportConcepts)
				ServiceLogic.SetActivationType<SupportConcept>(sc.Oid.Value, sc.Version.Value, ActivationTypeId.Archived);

			MakeCustomerHistoryEntry(c, null, StatementType.Archived, null, null, null);

		}

		public void ArchivePerson(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<Person>(pOid, pVersion, ActivationTypeId.Archived);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void ArchiveOrganisation(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<Organisation>(pOid, pVersion, ActivationTypeId.Archived);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void ArchiveSupportConcept(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<SupportConcept>(pOid, pVersion, ActivationTypeId.Archived);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateAbsenceReason(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<AbsenceReason>(new Dictionary<long, long> {{pOid, pVersion}}, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateAbsenceReasons(Dictionary<long, long> pOid2Version)
		{
			try
			{
				ServiceLogic.SetActivationType<AbsenceReason>(pOid2Version, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateCustomer(long pOid, long pVersion)
		{
			var customer = DAOFactory.GenericDAO.LoadByID<Customer>(pOid);
			customer.Person.IsActive = ActivationTypeId.Deleted;

			ServiceLogic.SetActivationType<Customer>(pOid, pVersion, ActivationTypeId.Deleted);

			foreach (var sc in customer.SupportConcepts)
				ServiceLogic.SetActivationType<SupportConcept>(sc.Oid.Value, sc.Version.Value, ActivationTypeId.Deleted);

			MakeCustomerHistoryEntry(customer, null, StatementType.Delete, null, null, null);
		}

		public void DeactivateOrganisation(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<Organisation>(pOid, pVersion, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateOrganisations(Dictionary<long, long> pOid2Version)
		{
			try
			{
				ServiceLogic.SetActivationType<Organisation>(pOid2Version, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivatePerson(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<Person>(pOid, pVersion, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivatePersons(Dictionary<long, long> pOid2Version)
		{
			try
			{
				ServiceLogic.SetActivationType<Person>(pOid2Version, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateSupportConcept(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<SupportConcept>(pOid, pVersion, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateSupportConcepts(Dictionary<long, long> pOid2Version)
		{
			try
			{
				ServiceLogic.SetActivationType<SupportConcept>(pOid2Version, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteAbsenceReason(long pOid, long pVersion)
		{
			try
			{
				DeleteAbsenceReasons(new Dictionary<long, long> {{pOid, pVersion}});
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteAbsenceReasons(Dictionary<long, long> pOid2Version)
		{
			try
			{
				List<AbsenceReason> lOriginals = DAOFactory.GenericDAO.LoadByIDs<AbsenceReason>(pOid2Version.Select(e => e.Key));
				lOriginals.DoForEach(or => MapperFactory.AbsenceReasonDC_AbsenceReason.ConcurrencyCheck(pOid2Version[or.Oid.Value], or));

				DAOFactory.GenericDAO.Delete(lOriginals);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteCustomer(long pOid, long pVersion)
		{
			try
			{
				DeleteCustomers(new Dictionary<long, long> {{pOid, pVersion}});
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteCustomers(Dictionary<long, long> pOid2Version)
		{
			try
			{
				pOid2Version.Keys.DoForEach(oid => SettingsLogic.RemoveFromAllHistories<Customer>(oid));
				List<Customer> lOriginals = DAOFactory.GenericDAO.LoadByIDs<Customer>(pOid2Version.Select(e => e.Key));
				lOriginals.DoForEach(or => MapperFactory.CustomerDC_Customer.ConcurrencyCheck(pOid2Version[or.Oid.Value], or));

				foreach (Customer lOriginal in lOriginals)
					MakeCustomerHistoryEntry(lOriginal, null, StatementType.Delete, null, null, null);

				DAOFactory.GenericDAO.Delete(lOriginals);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteCustomersAbsenceTime(long pOid, long pVersion)
		{
			try
			{
				DeleteCustomersAbsenceTimes(pOid, new Dictionary<long, long> {{pOid, pVersion}});
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteCustomersAbsenceTimes(long pCustomerOid, Dictionary<long, long> pOid2Version)
		{
			try
			{
				var lCustomer = DAOFactory.GenericDAO.LoadByID<Customer>(pCustomerOid);

				IEnumerable<AbsenceTime> lOriginals = lCustomer.AbsenceTimes.Where(at => pOid2Version.Keys.Contains(at.Oid.Value));
				lOriginals.DoForEach(or => MapperFactory.AbsenceTimeDC_AbsenceTime.ConcurrencyCheck(pOid2Version[or.Oid.Value], or));

				lCustomer.AbsenceTimes.RemoveRange(lOriginals);

				DAOFactory.GenericDAO.Update(lCustomer);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactCustomerDC> FindCustomer(string pFirstName, string pLastName, string pReferenceNumber)
		{
			try
			{
				return MapperFactory.CompactCustomerDC_Customer.MapToNewDCs(DAOFactory.SearchDAO.FindCustomer(pFirstName, pLastName, pReferenceNumber));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactOrganisationDC> FindOrganisation(string pName, bool pOnlyCostBearer)
		{
			try
			{
				return MapperFactory.CompactOrganisationDC_Organisation.MapToNewDCs(DAOFactory.SearchDAO.FindOrganisation(pName, pOnlyCostBearer));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactPersonDC> FindPerson(string pFirstName, string pLastName, DateTime? pDateOfBirth, PersonType? pPersonType)
		{
			try
			{
				return MapperFactory.CompactPersonDC_Person.MapToNewDCs(DAOFactory.SearchDAO.FindPerson(pFirstName, pLastName, pDateOfBirth, pPersonType));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactSupportConceptDC> FindSupportConcept(string pCustomerFirstName, string pCustomerLastName, string pCustomerReferenceNumber, DateTime? pFrom, DateTime? pTill)
		{
			return MapperFactory.CompactSupportConceptDC_SupportConcept.MapToNewDCs(DAOFactory.SearchDAO.FindSupportConcept(pCustomerFirstName, pCustomerLastName, pCustomerReferenceNumber, pFrom, pTill));
		}

		public List<AbsenceReasonDC> GetAllAbsenceReasons()
		{
			try
			{
				return MapperFactory.AbsenceReasonDC_AbsenceReason.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<AbsenceReason>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactCustomerDC> GetAllActiveAndArchivedCustomersCompact(long currentEmployeeOid)
		{
			try
			{
				var s = PluginLoader.FindClass<CustomerService>();

				return s.GetAllActiveAndArchivedCustomersCompact(currentEmployeeOid);
				
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactCustomerDC> GetAllCustomersCompact(long currentEmployeeOid)
		{
			try
			{
				var s = PluginLoader.FindClass<CustomerService>();

				return s.GetAllCustomersCompact(false, currentEmployeeOid);

			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactPersonDC> GetAllActiveAndArchivedPersonsByTypeCompact(PersonType pType)
		{
			try
			{
				IList<Person> persons =
					DAOFactory.GenericDAO.GetAllActiveAndArchived<Person>().Where(p => p.Type == pType).ToList();

				var result = new List<CompactPersonDC>();

				foreach (Person person in persons)
				{
					if (person.Organisation2Persons.Count == 0)
					{
						CompactPersonDC dc = MapperFactory.CompactPersonDC_Person.MapToNewDC(person);
						result.Add(dc);

						if (pType == PersonType.Others)
							AddContacts(dc, person, null);
					}
					foreach (Organisation2Person o2p in person.Organisation2Persons)
					{
						CompactPersonDC dc = MapperFactory.CompactPersonDC_Person.MapToNewDC(person);
						result.Add(dc);

						if (pType == PersonType.Others)
						{
							AddContacts(dc, person, o2p);

							dc.Organisation = o2p.Organisation.Name;
							if (o2p.Organisation.Address != null)
							{
								dc.Street = o2p.Organisation.Address.Street;
								dc.PostalCode = o2p.Organisation.Address.PostalCode;
								dc.Town = o2p.Organisation.Address.Town;
							}
						}
					}
				}

				return result;

				//return MapperFactory.CompactPersonDC_Person.MapToNewDCs(DAOFactory.GenericDAO.GetAllActiveAndArchived<Person>().Where(p => p.Type == pType));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactPersonDC> GetAllPersonsByTypeCompact(PersonType pType)
		{
			try
			{
				IList<Person> persons = DAOFactory.GenericDAO.GetAll<Person>().Where(p => p.Type == pType).ToList();

				var result = new List<CompactPersonDC>();

				foreach (var person in persons)
				{
					if (person.Organisation2Persons.Count == 0)
					{
						var dc = MapperFactory.CompactPersonDC_Person.MapToNewDC(person);
						result.Add(dc);

						if (pType == PersonType.Others)
							AddContacts(dc, person, null);
					}
					foreach (var o2p in person.Organisation2Persons)
					{
						var dc = MapperFactory.CompactPersonDC_Person.MapToNewDC(person);
						result.Add(dc);

						if (pType == PersonType.Others)
						{
							AddContacts(dc, person, o2p);

							dc.Organisation = o2p.Organisation.Name;
							if (o2p.Organisation.Address != null)
							{
								dc.Street = o2p.Organisation.Address.Street;
								dc.PostalCode = o2p.Organisation.Address.PostalCode;
								dc.Town = o2p.Organisation.Address.Town;
							}
						}
					}
				}

				return result;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactPersonDC> GetAllActiveAndArchivedPersonsCompact()
		{
			try
			{
				return MapperFactory.CompactPersonDC_Person.MapToNewDCs(DAOFactory.GenericDAO.GetAllActiveAndArchived<Person>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}

			;
		}

		public List<CompactSupportConceptDC> GetAllActiveAndArchivedSupportConceptsCompact(long currentEmployeeOid)
		{
			try
			{
				return GetAllActiveAndArchivedSupportConceptsCompact1(currentEmployeeOid);

			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactSupportConceptDC> GetAllSupportConceptsCompact(long currentEmployeeOid)
		{
			try
			{
				return GetAllSupportConceptsCompact1(currentEmployeeOid);

			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactSupportConceptDC> GetAllSupportConceptsCompact1(long currentEmployeeOid)
		{
			try
			{
				var result = new List<CompactSupportConceptDC>();

				var list = DAOFactory.SearchDAO.GetAllSupportConceptsCompact();
				var scProcessed = new Dictionary<long, bool>();
				foreach (var item in list)
				{
					if (item != null && item.Oid != null && !scProcessed.ContainsKey(item.Oid.Value))
					{
						var dc = CreateCompactSupportConceptDC(item, currentEmployeeOid);
						result.Add(dc);

						scProcessed.Add(item.Oid.Value, true);
					}
				}
				return result;

			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactSupportConceptDC> GetAllActiveAndArchivedSupportConceptsCompact1(long currentEmployeeOid)
		{
			var result = new List<CompactSupportConceptDC>();

			IEnumerable<SupportConcept> list = DAOFactory.SearchDAO.GetAllActiveAndArchivedSupportConceptsCompact();
			var scProcessed = new Dictionary<long, bool>();
			foreach (SupportConcept item in list)
			{
				if (!scProcessed.ContainsKey(item.Oid.Value))
				{
					CompactSupportConceptDC dc = CreateCompactSupportConceptDC(item, currentEmployeeOid);
					result.Add(dc);

					scProcessed.Add(item.Oid.Value, true);
				}
			}
			return result;
		}

		public List<CompactSupportConceptDC> GetAllActiveAndArchivedSupportConceptsCompact2(long currentEmployeeOid)
		{
				
			IList<ListedSupportConcept> list = DAOFactory.SearchDAO.GetAllActiveAndArchivedListedSupportConceptsCompact();

			return BuildCompactSupportConceptList(list, currentEmployeeOid);

		}

		private List<CompactSupportConceptDC> BuildCompactSupportConceptList(IList<ListedSupportConcept> list, long? currentEmployeeOid)
		{
			var result = new List<CompactSupportConceptDC>();
			var scDict = new Dictionary<long, CompactSupportConceptDC>();
			foreach (ListedSupportConcept item in list)
			{
				CompactSupportConceptDC dc = null;
				if (scDict.ContainsKey(item.SupportConceptOid))
				{
					dc = scDict[item.SupportConceptOid];
				}
				else
				{
					dc = new CompactSupportConceptDC();

					dc.SupportConceptOid = item.SupportConceptOid;
					dc.ActivationType = item.IsActive;
					dc.Version = item.Version;

					dc.Customer = new CompactCustomerDC();

					dc.Customer.CustomerOid = item.CustomerOid;
					dc.Customer.FirstName = item.FirstName;
					dc.Customer.LastName = item.LastName;
					dc.Customer.DateOfBirth = item.DateOfBirth;
					dc.Customer.Street = item.Street;
					dc.Customer.PostalCode = item.PostalCode;
					dc.Customer.Town = item.Town;

					result.Add(dc);

					scDict.Add(item.SupportConceptOid, dc);
				}
				if (dc.CostBearerList == null)
				{
					dc.CostBearerList = new List<CompactCostBearerDC>();
					dc.CostBearerRelOids = new List<long>();
					dc.CustomerReferenceNumbers = new List<String>();
				}

				if (item.CostBearer2SupportConceptOid.HasValue && !dc.CostBearerRelOids.Contains(item.CostBearer2SupportConceptOid.Value))
				{
					var costBearer = new CompactCostBearerDC();

					if (item.OrganisationOid.HasValue)
					{
						var orgDC = new CompactOrganisationDC();
						orgDC.Name = item.OrganisationName;
						orgDC.OrganisationOid = item.OrganisationOid.Value;

						costBearer.Organisation = orgDC;
					}

					costBearer.CostBearerID = item.CostBearerID;
					costBearer.CostBearerOid = item.CostBearerOid.Value;
					costBearer.CostBearer2SupportConceptOid = item.CostBearer2SupportConceptOid.Value;
					costBearer.SupportConceptStatus = (CostBearer2SupportConceptStatus)item.Status;
					costBearer.RequestedStartDate = item.RequestedStartDate;
					costBearer.RequestedEndDate = item.RequestedEndDate;
					costBearer.ApprovedStartDate = item.ApprovedStartDate;
					costBearer.ApprovedEndDate = item.ApprovedEndDate;
					//costBearer.ApprovedFLS = iCBRel.ApprovedFLS;
					//costBearer.ApprovedFLSTotal = iCBRel.ApprovedFLSTotal;
					costBearer.CustomerReferenceNumber = item.CustomerReferenceNumber;

					dc.CostBearerList.Add(costBearer);
					dc.CustomerReferenceNumbers.Add(item.CustomerReferenceNumber);
					dc.CostBearerRelOids.Add(item.CostBearer2SupportConceptOid.Value);



					if (currentEmployeeOid.HasValue && !dc.IsRelatedToEmployee && item.EmployeeOid.HasValue && item.EmployeeOid.Value == currentEmployeeOid.Value)
					{
						dc.IsRelatedToEmployee = true;
					}
				}
			}

			return result;
		}

		public List<CompactCustomerDC> GetAllActiveCustomersCompact(bool fetchReferenceNumbers, long? currentEmployeeOid)
		{
			try
			{
				var s = PluginLoader.FindClass<CustomerService>();

				return s.GetAllActiveCustomersCompact(fetchReferenceNumbers, currentEmployeeOid);

			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactCustomerDC> GetAllActiveCompactCustomers()
		{
			try
			{
				IList<Customer> customers = DAOFactory.GenericDAO.GetAllActive<Customer>();
				List<CompactCustomerDC> result = customers.Select(customer => MapperFactory.CompactCustomerDC_Customer.MapToNewDC(customer)).ToList();

				return result;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactCustomerDC> GetAllCompactCustomers()
		{
			try
			{
				var customers = DAOFactory.GenericDAO.GetAll<Customer>();
				var result = customers.Select(customer => MapperFactory.CompactCustomerDC_Customer.MapToNewDC(customer)).ToList();

				return result;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		} 

		public List<CompactPersonDC> GetAllActivePersonsByTypeCompact(PersonType pType)
		{
			try
			{
				return MapperFactory.CompactPersonDC_Person.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<Person>().Where(p => p.Type == pType));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}

			;
		}

		public List<CompactPersonDC> GetAllActivePersonsCompact()
		{
			try
			{
				return MapperFactory.CompactPersonDC_Person.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<Person>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactSupportConceptDC> GetAllActiveSupportConceptsCompact()
		{
			try
			{
				return MapperFactory.CompactSupportConceptDC_SupportConcept.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<SupportConcept>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactOrganisationDC> GetAllCostBearerCompact()
		{
			try
			{
				return GetAllActiveOrganisationsCompact().Where(o => o.CostBearerOid != null).ToList();
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}

			;
		}

		public List<CompactOrganisationDC> GetAllActiveOrganisationsCompact()
		{
			try
			{
				IList<Organisation> list = DAOFactory.GenericDAO.GetAllActive<Organisation>();

				return CreateCompactOrganisations(list);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactOrganisationDC> GetAllActiveAndArchivedOrganisationsCompact()
		{
			try
			{
				IList<Organisation> list = DAOFactory.GenericDAO.GetAllActiveAndArchived<Organisation>();

				return CreateCompactOrganisations(list);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactOrganisationDC> GetAllOrganisationsCompact()
		{
			try
			{
				var list = DAOFactory.GenericDAO.GetAll<Organisation>();

				return CreateCompactOrganisations(list);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public CustomerDC GetCustomerWithPersonOid(long pPersonOid)
		{
			try
			{
				return MapperFactory.CustomerDC_Customer.MapToNewDC(DAOFactory.SearchDAO.FindCustomerWithPersonOid(pPersonOid));
			}
			catch (Exception)
			{
				throw new FaultException<BeWoFault>(
					new BeWoFault(String.Format("Klient mit Id {0} wurde nicht gefunden!", pPersonOid)));
			}
		}

		public List<CompactCustomerDC> GetLastOpenedCustomers()
		{
			try
			{
				return MapperFactory.CompactCustomerDC_Customer.MapToNewDCs(SettingsLogic.GetLastOpened<Customer>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactOrganisationDC> GetLastOpenedOrganisations()
		{
			try
			{
				return MapperFactory.CompactOrganisationDC_Organisation.MapToNewDCs(SettingsLogic.GetLastOpened<Organisation>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactPersonDC> GetLastOpenedPersons()
		{
			try
			{
				return MapperFactory.CompactPersonDC_Person.MapToNewDCs(SettingsLogic.GetLastOpened<Person>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactSupportConceptDC> GetLastOpenedSupportConcepts()
		{
			try
			{
				var result = new List<CompactSupportConceptDC>();
				IList<SupportConcept> list = SettingsLogic.GetLastOpened<SupportConcept>();
				var scProcessed = new Dictionary<long, bool>();
				foreach (SupportConcept item in list)
				{
					if (!scProcessed.ContainsKey(item.Oid.Value))
					{
						CompactSupportConceptDC dc = CreateCompactSupportConceptDC(item, null);
						result.Add(dc);

						scProcessed.Add(item.Oid.Value, true);
					}
				}

				return result;

				//var oids = SettingsLogic.GetLastOpenedOids<SupportConcept>();

				//IList<ListedSupportConcept> list = DAOFactory.SearchDAO.GetAllActiveAndArchivedListedSupportConceptsCompact(oids);


				//return SortByOids(BuildCompactSupportConceptList(list, null), oids);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		private List<CompactSupportConceptDC> SortByOids(IList<CompactSupportConceptDC> list, List<long> oids)
		{
			var result = new List<CompactSupportConceptDC>();

			foreach (var oid in oids)
			{
				foreach (var listedSupportConcept in list)
				{
					if (listedSupportConcept.SupportConceptOid == oid)
						result.Add(listedSupportConcept);
				}
			}
			return result;
		}

		public void InsertAbsenceReasons(List<AbsenceReasonDC> pAbsenceReasonDC)
		{
			try
			{
				DAOFactory.GenericDAO.Insert(MapperFactory.AbsenceReasonDC_AbsenceReason.MapToNewEntities(pAbsenceReasonDC));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public long InsertNewCustomer(CustomerDC pCustomerDC)
		{
			try
			{
				Customer lCustomer = MapperFactory.CustomerDC_Customer.MapToNewEntity(pCustomerDC);
				DAOFactory.GenericDAO.Insert(lCustomer);

				var lOriginal = DAOFactory.GenericDAO.LoadByID<Customer>(lCustomer.Oid.Value);

				object[] Lists = GetFromNHibernateDecoupledCustomerRelatedLists(lOriginal);
				MakeCustomerHistoryEntry(lCustomer, lCustomer.Oid.Value, StatementType.Insert, Lists[0] as List<Customer2Person>, Lists[1] as List<Customer2Organisation>, Lists[2] as List<Employee2Customer>);

				return lCustomer.Oid.Value;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public long InsertNewOrganisation(OrganisationDC pOrganisationDC)
		{
			try
			{
				Organisation pOrganisation = MapperFactory.OrganisationDC_OrganisationMapper.MapToNewEntity(pOrganisationDC);
				DAOFactory.GenericDAO.Insert(pOrganisation);
				return pOrganisation.Oid.Value;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public long InsertNewPerson(PersonDC pPersonDC)
		{
			try
			{
				Person pPerson = MapperFactory.PersonDC_Person.MapToNewEntity(pPersonDC);
				DAOFactory.GenericDAO.Insert(pPerson);
				return pPerson.Oid.Value;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public long InsertNewSupportConcept(SupportConceptDC pSupportConcept)
		{
			try
			{
				CheckDefaultServiceCategory(pSupportConcept);

				SupportConcept lSupportConcept = MapperFactory.SupportConceptDC_SupportConcept.MapToNewEntity(pSupportConcept);

				lSupportConcept.Customer.Customer2CostBearerList.AddRange(lSupportConcept.CostBearer2SupportConceptList.Where(cb2sc => !lSupportConcept.Customer.Customer2CostBearerList.Exists(c2cb => c2cb.CostBearer.Equals(cb2sc.CostBearer))).Select(c2cb => new Customer2CostBearer {CostBearer = c2cb.CostBearer, ReferenceNumber = c2cb.CustomerReferenceNumber}));

				DAOFactory.GenericDAO.Insert(lSupportConcept);

				return lSupportConcept.Oid.Value;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public CustomerDC LoadCustomer(long pCustomerOid)
		{
			try
			{
				SettingsLogic.AddToUsersHistory<Customer>(pCustomerOid);
				var dc = MapperFactory.CustomerDC_Customer.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Customer>(pCustomerOid));

				return dc;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public OrganisationDC LoadOrganisation(long pOrganisationOid)
		{
			try
			{
				SettingsLogic.AddToUsersHistory<Organisation>(pOrganisationOid);
				return MapperFactory.OrganisationDC_OrganisationMapper.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Organisation>(pOrganisationOid));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public CompactOrganisationDC LoadOrganisationCompact(long pOrganisationOid)
		{
			try
			{
				return MapperFactory.CompactOrganisationDC_Organisation.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Organisation>(pOrganisationOid));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public PersonDC LoadPerson(long pPersonOid)
		{
			try
			{
				SettingsLogic.AddToUsersHistory<Person>(pPersonOid);
				return MapperFactory.PersonDC_Person.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Person>(pPersonOid));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public CompactPersonDC LoadPersonCompact(long pPersonOid)
		{
			try
			{
				return MapperFactory.CompactPersonDC_Person.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Person>(pPersonOid));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public SupportConceptDC LoadSupportConcept(long pOid)
		{
			try
			{
				SettingsLogic.AddToUsersHistory<SupportConcept>(pOid);
				return MapperFactory.SupportConceptDC_SupportConcept.MapToNewDC(DAOFactory.GenericDAO.LoadByID<SupportConcept>(pOid));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void MoveCustomerToRecycleBin(long pOid, long pVersion)
		{
			ServiceLogic.SetActivationType<Customer>(pOid, pVersion, ActivationTypeId.InRecycleBin);
		}

		// private void SetCustomerActivationType(long pOid, long pVersion, ActivationTypeId activationType)
		// {
		// try
		// {
		// SettingsLogic.RemoveFromAllHistories<Customer>(pOid);

		// Customer customer = DAOFactory.GenericDAO.LoadByID<Customer>(pOid);
		// if (customer.SystemEntryID == null)
		// {

		// customer.IsActive = activationType;
		// if (customer.Person != null)
		// customer.Person.IsActive = activationType;

		// ServiceLogic.ConcurrencyCheck(pVersion, customer);
		// DAOFactory.GenericDAO.Update(customer);
		// }

		// }
		// catch (Exception e)
		// {
		// throw(BeWo.Service.Core.Utils.ThrowBeWoFaultException(e));
		// }
		// }

		public void MovePersonToRecycleBin(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<Person>(pOid, pVersion, ActivationTypeId.InRecycleBin);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void MoveSupportConceptToRecycleBin(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<SupportConcept>(pOid, pVersion, ActivationTypeId.InRecycleBin);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void UpdateAbsenceReasons(List<AbsenceReasonDC> pAbsenceReasons)
		{
			try
			{
				List<AbsenceReason> lOriginals = DAOFactory.GenericDAO.LoadByIDs<AbsenceReason>(pAbsenceReasons.Select(ar => ar.AbsenceReasonOid.Value));
				MapperFactory.AbsenceReasonDC_AbsenceReason.MergeWithEntitys(pAbsenceReasons, lOriginals);
				DAOFactory.GenericDAO.Update(lOriginals);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public long UpdateCustomer(CustomerDC pCustomerDC)
		{
			try
			{
				var lOriginal = DAOFactory.GenericDAO.LoadByID<Customer>(pCustomerDC.CustomerOid.Value);

				object[] Lists = GetFromNHibernateDecoupledCustomerRelatedLists(lOriginal);

				MapperFactory.CustomerDC_Customer.MergeWithEntity(pCustomerDC, lOriginal);

				DAOFactory.GenericDAO.Update(lOriginal);

				MakeCustomerHistoryEntry(lOriginal, null, StatementType.Update, Lists[0] as List<Customer2Person>, Lists[1] as List<Customer2Organisation>, Lists[2] as List<Employee2Customer>);

				CheckUpdatedReferenceNumbers(pCustomerDC, lOriginal);

				return lOriginal.Oid.Value;
			}
			catch (StaleObjectStateException)
			{
				throw new FaultException<BeWoFault>(new BeWoFault("Wurde in der Zwischenzeit geändert", BeWoFaultType.Concurrency));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		private void CheckUpdatedReferenceNumbers(CustomerDC newCustomer, Customer originalCustomer)
		{
			foreach (var cc in newCustomer.CostBearers)
			{
				CopyReferenceNumber(cc, originalCustomer);
			}
		}

		private void CopyReferenceNumber(CustomerCostBearerRelationDC ccDC, Customer originalCustomer)
		{
			foreach (var sc in originalCustomer.SupportConcepts)
			{
				foreach (var c2s in sc.CostBearer2SupportConceptList)
				{
					if (c2s.CostBearer.Oid == ccDC.CostBearer.CostBearerOid)
					{
						if (String.IsNullOrEmpty(c2s.CustomerReferenceNumber) && !String.IsNullOrEmpty(ccDC.ReferenceNumber))
						{
							c2s.CustomerReferenceNumber = ccDC.ReferenceNumber;
							DAOFactory.GenericDAO.Update(c2s);
						}
					}
				}
			}
		}

		

		public void UpdateCustomersAbsenceTimes(long pCustomerOid, List<AbsenceTimeDC> pAbsenceTimes)
		{
			try
			{
				var lCustomer = DAOFactory.GenericDAO.LoadByID<Customer>(pCustomerOid);
				MapperFactory.AbsenceTimeDC_AbsenceTime.MergeWithEntitys(pAbsenceTimes, lCustomer.AbsenceTimes.Where(at => pAbsenceTimes.SingleOrDefault(dc => dc.AbsenceTimeOid == at.Oid) != null).ToList());
				DAOFactory.GenericDAO.Update(lCustomer);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public long UpdateOrganisation(OrganisationDC pOrganisationDC)
		{
			try
			{
				var lOrigial = DAOFactory.GenericDAO.LoadByID<Organisation>(pOrganisationDC.OrganisationOid.Value);
				MapperFactory.OrganisationDC_OrganisationMapper.MergeWithEntity(pOrganisationDC, lOrigial);
				DAOFactory.GenericDAO.Update(lOrigial);
				return lOrigial.Oid.Value;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public long UpdatePerson(PersonDC pPersonDC)
		{
			try
			{
				var lOrigial = DAOFactory.GenericDAO.LoadByID<Person>(pPersonDC.PersonOid.Value);
				MapperFactory.PersonDC_Person.MergeWithEntity(pPersonDC, lOrigial);
				DAOFactory.GenericDAO.Update(lOrigial);
				return lOrigial.Oid.Value;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public bool ServiceRecordOutOfSupportConcept(SupportConceptDC pSupportConcept)
		{
			if (!pSupportConcept.SupportConceptOid.HasValue)
				return false;

			bool hasRecordsOutOfConcept = false;
			
			IEnumerable<ServiceRecord> allRecords = DAOFactory.SearchDAO.FindServiceRecordsForSupportConcept(pSupportConcept.SupportConceptOid.Value);
			//var records = new List<ServiceRecord>();

			//foreach (ServiceRecord item in allRecords)
			//	foreach (SupportConceptCostBearerRelDC element in pSupportConcept.CostBearerRelations)
			//		if (item.CostBearer2SupportConceptOid.HasValue && element.CostBearer2SupportConceptOid.HasValue)
			//			if (element.CostBearer2SupportConceptOid.Value.Equals(item.CostBearer2SupportConceptOid.Value))
			//			{
			//				records.Add(item);
			//			}

			bool discontinue = false;
			foreach (SupportConceptCostBearerRelDC rel in pSupportConcept.CostBearerRelations)
			{
				DateTime? start = rel.StartDate;
				DateTime? end = rel.EndDate;

				if (end.HasValue && end < DateTime.MaxValue.Date)
					end = end.Value.AddDays(1).Date;
				if (start.HasValue && end.HasValue)
				{
					if (
						allRecords.Any(
							element =>
								element.Start < start ||
								element.End >= end &&
								element.CostBearer2SupportConcept.CostBearer.Oid.Value.Equals(rel.CostBearer.CostBearerOid.Value)))
					{
						discontinue = true;
						hasRecordsOutOfConcept = true;
					}
					if (discontinue)
						break;
				}
			}

			return hasRecordsOutOfConcept;
		}

		public long UpdateSupportConcept(SupportConceptDC pSupportConcept)
		{
			try
			{
				// Alle dazugehörigen ServiceRecords holen

				CheckDefaultServiceCategory(pSupportConcept);

				var lOriginal = DAOFactory.GenericDAO.LoadByID<SupportConcept>(pSupportConcept.SupportConceptOid.Value);
				MapperFactory.SupportConceptDC_SupportConcept.MergeWithEntity(pSupportConcept, lOriginal);

				lOriginal.Customer.Customer2CostBearerList.AddRange(lOriginal.CostBearer2SupportConceptList.Where(cb2sc => !lOriginal.Customer.Customer2CostBearerList.Exists(c2cb => c2cb.CostBearer.Equals(cb2sc.CostBearer))).Select(c2cb => new Customer2CostBearer {CostBearer = c2cb.CostBearer, ReferenceNumber = c2cb.CustomerReferenceNumber}));

				DAOFactory.GenericDAO.Update(lOriginal);

				return lOriginal.Oid.Value;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<AssessmentSheetCategoryDC> LoadCustomerAssessmentSheetCategoryList(long pCustomerOid)
		{
			try
			{
				IEnumerable<AssessmentSheetCategory> list = DAOFactory.SearchDAO.GetAssessmentSheetCategoryListForCustomer(pCustomerOid);

				return MapperFactory.AssessmentSheetCategoryDC_AssessmentSheetCategory.MapToNewDCs(list);
			}
			catch (Exception e)
			{
				throw (Utils.CreateBeWoFaultException(e));
			}
		}

		public List<AppointmentDC> LoadAppointments(long? customerOid, long? employeeOid)
		{
			try
			{
				return MapperFactory.AppointmentDC_Appointment.MapToNewDCs(DAOFactory.SearchDAO.FindAppointments(customerOid, employeeOid));
			}
			catch (Exception e)
			{
				throw (Utils.CreateBeWoFaultException(e));
			}
		}

		public List<AppointmentCategoryDC> GetAllAppointmentCategories()
		{
			try
			{
				return MapperFactory.AppointmentCategoryDC_AppointmentCategory.MapToNewDCs(
					DAOFactory.GenericDAO.GetAllActive<AppointmentCategory>());
			}
			catch (Exception e)
			{
				throw (Utils.CreateBeWoFaultException(e));
			}
		}

		public List<long> InsertNewAppointmentCategories(List<AppointmentCategoryDC> pAppointmentCategories)
		{
			try
			{
				List<AppointmentCategory> lAppointmentCategories = MapperFactory.AppointmentCategoryDC_AppointmentCategory.MapToNewEntities(pAppointmentCategories);
				DAOFactory.GenericDAO.Insert(lAppointmentCategories);
				return lAppointmentCategories.Select(r => r.Oid.Value).ToList();
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<long> UpdateAppointmentCategories(List<AppointmentCategoryDC> pAppointmentCategories)
		{
			try
			{
				List<AppointmentCategory> lOriginals = DAOFactory.GenericDAO.LoadByIDs<AppointmentCategory>(pAppointmentCategories.Select(b => b.AppointmentCategoryOid.Value));
				MapperFactory.AppointmentCategoryDC_AppointmentCategory.MergeWithEntitys(pAppointmentCategories, lOriginals);
				DAOFactory.GenericDAO.Update(lOriginals);
				return lOriginals.Select(b => b.Oid.Value).ToList();
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateAppointmentCategories(Dictionary<long, long> pOid2Version)
		{
			try
			{
				ServiceLogic.SetActivationType<AppointmentCategory>(pOid2Version, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<AppointmentDC> InsertNewAppointments(List<AppointmentDC> pAppointments)
		{
			try
			{
				List<Appointment> lAppointments = MapperFactory.AppointmentDC_Appointment.MapToNewEntities(pAppointments);
				DAOFactory.GenericDAO.Insert(lAppointments);

				return MapperFactory.AppointmentDC_Appointment.MapToNewDCs(lAppointments);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<AppointmentDC> UpdateAppointments(List<AppointmentDC> pAppointments)
		{
			try
			{
				List<Appointment> lOriginals = DAOFactory.GenericDAO.LoadByIDs<Appointment>(pAppointments.Select(b => b.AppointmentOid.Value));
				MapperFactory.AppointmentDC_Appointment.MergeWithEntitys(pAppointments, lOriginals);
				DAOFactory.GenericDAO.Update(lOriginals);
				return MapperFactory.AppointmentDC_Appointment.MapToNewDCs(lOriginals);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateAppointments(Dictionary<long, long> pOid2Version)
		{
			try
			{
				ServiceLogic.SetActivationType<Appointment>(pOid2Version, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<AbsenceTimeDC> InsertAbsenceTimes(List<AbsenceTimeDC> pDCList)
		{
			try
			{
				List<AppointmentAbsenceTime> times = MapperFactory.AbsenceTimeDC_AppointmentAbsenceTime.MapToNewEntities(pDCList);
				DAOFactory.GenericDAO.Insert(times);

				return MapperFactory.AbsenceTimeDC_AppointmentAbsenceTime.MapToNewDCs(times);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<AbsenceTimeDC> UpdateAbsenceTimes(List<AbsenceTimeDC> pDCList)
		{
			try
			{
				List<AppointmentAbsenceTime> lOriginals = DAOFactory.GenericDAO.LoadByIDs<AppointmentAbsenceTime>(pDCList.Select(b => b.AbsenceTimeOid.Value));
				MapperFactory.AbsenceTimeDC_AppointmentAbsenceTime.MergeWithEntitys(pDCList, lOriginals);
				DAOFactory.GenericDAO.Update(lOriginals);

				return MapperFactory.AbsenceTimeDC_AppointmentAbsenceTime.MapToNewDCs(lOriginals);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateAbsenceTimes(Dictionary<long, long> pOid2Version)
		{
			try
			{
				ServiceLogic.SetActivationType<AbsenceTime>(pOid2Version, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<ValueListEntryDC> GetAllCustomerGoals(long pCustomerOid)
		{
			try
			{
				var customer = DAOFactory.GenericDAO.LoadByID<Customer>(pCustomerOid);
				var goals = new List<ValueListEntryDC>();
				foreach (SupportConcept sc in customer.SupportConcepts)
				{
					if (sc.IsActive != ActivationTypeId.Deleted)
					{
						var list = new List<ValueListEntryType>();
						list.Add(ValueListEntryType.SupportConceptGoalType);
						list.Add(ValueListEntryType.SupportConceptGoalCategoryType);
						list.Add(ValueListEntryType.SupportConceptIndividualGoalCategoryType);
						list.Add(ValueListEntryType.SupportConceptIndividualGoalType);

						goals.AddRange(MapperFactory.ValueListEntryDC_ValueListEntry.MapToNewDCs(sc.ValueList.FindByTypes(list).Select(e2o => e2o.Entry)));
					}
				}
				var test = goals.Distinct().ToList();
				return test;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public CompactSupportConceptDC LoadCompactSupportConceptDC(long pOid, long? currentEmployeeOid)
		{
			var supportConcept = DAOFactory.GenericDAO.GetByID<SupportConcept>(pOid);

			return CreateCompactSupportConceptDC(supportConcept, currentEmployeeOid);
		}

		public CompactCustomerDC GetCompactCustomerDC(long pOid)
		{
			var customer = DAOFactory.GenericDAO.GetByID<Customer>(pOid);
			return MapperFactory.CompactCustomerDC_Customer.MapToNewDC(customer);
		}

		public List<CustomerDC> GetAllActiveCustomers()
		{
			try
			{
				return MapperFactory.CustomerDC_Customer.MapToNewDCs(DAOFactory.GenericDAO.GetAll<Customer>().Where(c => c.IsActive.Equals(ActivationTypeId.Active)));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CustomerDC> GetCustomersById(IEnumerable<long> idList)
		{
			try
			{
				return MapperFactory.CustomerDC_Customer.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs<Customer>(idList));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<SupportConceptDC> GetSupportConceptsById(IEnumerable<long> idList)
		{
			try
			{
				return MapperFactory.SupportConceptDC_SupportConcept.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs<SupportConcept>(idList));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<PersonDC> GetAllActivePersons()
		{
			try
			{
				return MapperFactory.PersonDC_Person.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<Person>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<OrganisationDC> GetAllOrganisations()
		{
			try
			{
				return MapperFactory.OrganisationDC_OrganisationMapper.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<Organisation>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<PersonDC> GetPersonsById(IEnumerable<long> idList)
		{
			try
			{
				return MapperFactory.PersonDC_Person.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs<Person>(idList));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<OrganisationDC> GetOrganisationsById(IEnumerable<long> idList)
		{
			try
			{
				return MapperFactory.OrganisationDC_OrganisationMapper.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs<Organisation>(idList));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<AppointmentDC> GetAppointmentsById(IEnumerable<long> idList)
		{
			try
			{
				return MapperFactory.AppointmentDC_Appointment.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs<Appointment>(idList));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateMedArten(Dictionary<long, long> pOid2Version)
		{
			try
			{
				ServiceLogic.SetActivationType<MedArt>(pOid2Version, ActivationTypeId.Deleted);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteMedArten(Dictionary<long, long> pOid2Version)
		{
			try
			{
				var lOriginals = DAOFactory.GenericDAO.LoadByIDs<MedArt>(pOid2Version.Keys);
				DAOFactory.GenericDAO.Delete(lOriginals);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<MedArtDC> GetAllMedArten()
		{
			try
			{
				return MapperFactory.MedArtDC_MedArt.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<MedArt>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<MedArtDC> GetMedArtenById(IEnumerable<long> idList)
		{
			try
			{
				return MapperFactory.MedArtDC_MedArt.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs<MedArt>(idList));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<MedArtDC> InsertMedArten(IEnumerable<MedArtDC> pDCList)
		{
			try
			{
				var arten = MapperFactory.MedArtDC_MedArt.MapToNewEntities(pDCList);
				DAOFactory.GenericDAO.Insert(arten);

				return MapperFactory.MedArtDC_MedArt.MapToNewDCs(arten);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<MedArtDC> UpdateMedArten(List<MedArtDC> pDCList)
		{
			try
			{
				var lOriginals = DAOFactory.GenericDAO.LoadByIDs<MedArt>(pDCList.Select(b => b.MedArtOid.Value));
				MapperFactory.MedArtDC_MedArt.MergeWithEntitys(pDCList, lOriginals);
				DAOFactory.GenericDAO.Update(lOriginals);

				return MapperFactory.MedArtDC_MedArt.MapToNewDCs(lOriginals);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<MedikamentenverordnungDC> GetAllMedikamentenverordnungen()
		{
			try
			{
				return MapperFactory.MedikamentenverordnungDC_Medikamentenverordnung.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<Medikamentenverordnung>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<MedikamentenverordnungDC> GetMedikamentenverordnungenById(IEnumerable<long> idList)
		{
			try
			{
				return MapperFactory.MedikamentenverordnungDC_Medikamentenverordnung.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs<Medikamentenverordnung>(idList));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<MedikamentenverordnungDC> InsertMedikamentenverordnungen(List<MedikamentenverordnungDC> pDCList)
		{
			try
			{
				var verordnungen = MapperFactory.MedikamentenverordnungDC_Medikamentenverordnung.MapToNewEntities(pDCList);
				DAOFactory.GenericDAO.Insert(verordnungen);

				return MapperFactory.MedikamentenverordnungDC_Medikamentenverordnung.MapToNewDCs(verordnungen);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<MedikamentenverordnungDC> UpdateMedikamentenverordnungen(List<MedikamentenverordnungDC> pDCList)
		{
			try
			{
				var lOriginals = DAOFactory.GenericDAO.LoadByIDs<Medikamentenverordnung>(pDCList.Select(b => b.MedikamentenverordnungOid.Value));
				MapperFactory.MedikamentenverordnungDC_Medikamentenverordnung.MergeWithEntitys(pDCList, lOriginals);
				DAOFactory.GenericDAO.Update(lOriginals);

				return MapperFactory.MedikamentenverordnungDC_Medikamentenverordnung.MapToNewDCs(lOriginals);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeactivateMedikamentenverordnungen()
		{
			
		}

		public List<MedikamentenverordnungDC> GetMedikamentenverordnungenForCustomer(long pCustomerOid)
		{
			throw new NotImplementedException();
		}

		public List<MedikamentenverordnungslisteDC> InsertMedikamentenverordnungslisten(IEnumerable<MedikamentenverordnungslisteDC> pDCList)
		{
			try
			{
				var verordnungslisten = MapperFactory.MedikamentenverordnungslisteDC_Medikamentenverordnungsliste.MapToNewEntities(pDCList);
				DAOFactory.GenericDAO.Insert(verordnungslisten);
				var gemappteNeue = MapperFactory.MedikamentenverordnungslisteDC_Medikamentenverordnungsliste.MapToNewDCs(verordnungslisten);

				var neueste = 0L;
				foreach (var item in gemappteNeue)
				{
					var oid = item.MedikamentenverordnungslistenOid;
					if (oid.HasValue && oid.Value > neueste)
						neueste = oid.Value;
				}

				var honeyMooMoo = DAOFactory.SearchDAO.GetAllMedikamentenverordnungslistenButNewestByCustomerOid(gemappteNeue.First(f => f.MedikamentenverordnungslistenOid.Value.Equals(neueste)).Customer.CustomerOid, neueste, gemappteNeue.First(f => f.MedikamentenverordnungslistenOid.Value.Equals(neueste)).MedListType);
				
				foreach (var mvl in honeyMooMoo)
					mvl.Gueltig = false;

				DAOFactory.GenericDAO.Update(honeyMooMoo);

				var erg = MapperFactory.MedikamentenverordnungslisteDC_Medikamentenverordnungsliste.MapToNewDCs(honeyMooMoo);
				erg.Add(gemappteNeue.First(f => f.MedikamentenverordnungslistenOid.Equals(neueste)));

				return erg;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteMedikamentenverordnungsliste(long listenOid)
		{
			try
			{
				var lOriginal = DAOFactory.GenericDAO.LoadByID<Medikamentenverordnungsliste>(listenOid);
				DAOFactory.GenericDAO.Delete(lOriginal);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public MedikamentenverordnungslisteDC UpdateMedikamentenverordnungsliste(MedikamentenverordnungslisteDC pDCList)
		{
			try
			{
				var lOriginal = DAOFactory.GenericDAO.LoadByID<Medikamentenverordnungsliste>(pDCList.MedikamentenverordnungslistenOid.Value);
				MapperFactory.MedikamentenverordnungslisteDC_Medikamentenverordnungsliste.MergeWithEntity(pDCList, lOriginal);
				DAOFactory.GenericDAO.Update(lOriginal);

				return MapperFactory.MedikamentenverordnungslisteDC_Medikamentenverordnungsliste.MapToNewDC(lOriginal);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		private static void AddContacts(CompactPersonDC dc, Person person, Organisation2Person o2p)
		{
			if (o2p != null)
			{
				if (o2p.Contacts != null)
				{
					foreach (Contact contact in o2p.Contacts)
					{
						if (contact.Type == ContactType.business_Phone)
						{
							dc.Communication1 = contact.Value;
						}

						if (contact.Type == ContactType.business_Mail)
						{
							dc.Communication3 = contact.Value;
						}
					}
				}

				if (o2p.Organisation != null && o2p.Organisation.Contacts != null)
				{
					if (String.IsNullOrEmpty(dc.Communication1))
					{
						foreach (Contact contact in o2p.Organisation.Contacts)
						{
							if (contact.Type == ContactType.business_Phone)
							{
								dc.Communication1 = contact.Value;
							}
						}
					}
					if (String.IsNullOrEmpty(dc.Communication2))
					{
						//foreach (var contact in org.Contacts)
						//{
						//    if (contact.Type == ContactType.b)
						//    {
						//        dc.Communication2 = contact.Value;
						//    }
						//}
					}
					if (String.IsNullOrEmpty(dc.Communication3))
					{
						foreach (Contact contact in o2p.Organisation.Contacts)
						{
							if (contact.Type == ContactType.business_Mail)
							{
								dc.Communication3 = contact.Value;
							}
						}
					}
				}
			}


			if (String.IsNullOrEmpty(dc.Communication1))
			{
				if (person.Contacts != null)
				{
					foreach (Contact contact in person.Contacts)
					{
						if (contact.Type == ContactType.private_Phone)
						{
							dc.Communication1 = contact.Value;
						}
					}
				}
			}
			if (String.IsNullOrEmpty(dc.Communication2))
			{
				if (person.Contacts != null)
				{
					foreach (Contact contact in person.Contacts)
					{
						if (contact.Type == ContactType.private_MobilePhone)
						{
							dc.Communication2 = contact.Value;
						}
					}
				}
			}
			if (String.IsNullOrEmpty(dc.Communication3))
			{
				if (person.Contacts != null)
				{
					foreach (Contact contact in person.Contacts)
					{
						if (contact.Type == ContactType.private_Mail)
						{
							dc.Communication3 = contact.Value;
						}
					}
				}
			}
		}

		private List<CompactOrganisationDC> CreateCompactOrganisations(IList<Organisation> list)
		{
			var result = new List<CompactOrganisationDC>();
			foreach (Organisation org in list)
			{
				CompactOrganisationDC dc = MapperFactory.CompactOrganisationDC_Organisation.MapToNewDC(org);

				if (org.Address != null)
				{
					dc.Street = org.Address.Street;
					dc.PostalCode = org.Address.PostalCode;
					dc.Town = org.Address.Town;
				}

				result.Add(dc);
			}
			return result;
		}

		private static void CheckDefaultServiceCategory(SupportConceptDC pSupportConcept)
		{
			if (pSupportConcept.ServiceAccountings != null)
			{
				ServiceCategoryDC defaultCat = null;

				foreach (ServiceAccountingDC sa in pSupportConcept.ServiceAccountings)
				{
					if (sa.ServiceDescription.ScopeType == ScopeTypeId.Individual)
					{
						if (sa.ServiceDescription.Category == null)
						{
							if (defaultCat == null)
							{
								ServiceCategory defaultCatEntity = DAOFactory.SearchDAO.FindDefaultIndividualServiceCategory();

								if (defaultCatEntity == null)
								{
									defaultCatEntity = new ServiceCategory();
									defaultCatEntity.Name = "Individuelle Leistungen";
									defaultCatEntity.ScopeType = ScopeTypeId.Individual;
									defaultCatEntity.IsBillable = true;
									defaultCatEntity.BillableAmount = 100;
									DAOFactory.GenericDAO.Insert(defaultCatEntity);
								}
								defaultCat = MapperFactory.ServiceCategoryDC_ServiceCategory.MapToNewDC(defaultCatEntity);
							}
							sa.ServiceDescription.Category = defaultCat;
						}
					}
				}
			}
		}

		//private void CheckDefaultGoalCategory(SupportConceptDC pSupportConcept)
		//{
		//    if (pSupportConcept.Goals != null)
		//    {
		//        ServiceCategoryDC defaultGoal = null;

		//        foreach (var goal in pSupportConcept.Goals)
		//        {
		//            if (goal.Type == ValueListEntryType.SupportConceptIndividualGoalType)
		//            {
		//                if (goal.ServiceDescription.Category == null)
		//                {
		//                    if (defaultCat == null)
		//                    {
		//                        var defaultCatEntity = DAOFactory.SearchDAO.FindDefaultIndividualServiceCategory();

		//                        if (defaultCatEntity == null)
		//                        {
		//                            defaultCatEntity = new ServiceCategory();
		//                            defaultCatEntity.Name = "Individuelle Leistungen";
		//                            defaultCatEntity.ScopeType = ServiceScopeType.Individual;
		//                            defaultCatEntity.IsBillable = true;
		//                            defaultCatEntity.BillableAmount = 100;
		//                            DAOFactory.GenericDAO.Insert(defaultCatEntity);
		//                        }
		//                        defaultCat = MapperFactory.ServiceCategoryDC_ServiceCategory.MapToNewDC(defaultCatEntity);
		//                    }
		//                    sa.ServiceDescription.Category = defaultCat;
		//                }
		//            }
		//        }
		//    }
		//}


		private static CompactSupportConceptDC CreateCompactSupportConceptDC(SupportConcept pEntity, long? currentEmployeeOid)
		{
			var dc = new CompactSupportConceptDC();

			dc.SupportConceptOid = pEntity.Oid.Value;
			dc.SupportConceptVersion = pEntity.Version.Value;

			Customer cust = pEntity.Customer;

			var customerDC = new CompactCustomerDC();

			customerDC.CustomerOid = cust.Oid.Value;
			customerDC.CustomerVersion = cust.Version.Value;
			customerDC.FirstName = cust.Person.FirstName;
			customerDC.LastName = cust.Person.LastName;
			customerDC.DateOfBirth = cust.Person.DateOfBirth;
			customerDC.Sex = cust.Person.Sex;
			customerDC.ActivationType = cust.IsActive;
			customerDC.TerminationDate = cust.TerminationDate;

			if (cust.Person.Address != null)
			{
				customerDC.Street = cust.Person.Address.Street;
				customerDC.PostalCode = cust.Person.Address.PostalCode;
				customerDC.Town = cust.Person.Address.Town;
			}

			dc.Customer = customerDC;

			dc.ActivationType = pEntity.IsActive;
			dc.ConferenceDate = pEntity.ConferenceDate;

			foreach (CostBearer2SupportConcept iCBRel in pEntity.CostBearer2SupportConceptList)
			{
				if (!dc.CostBearerRelOids.Contains(iCBRel.Oid.Value))
				{
					var costBearer = new CompactCostBearerDC();

					if (iCBRel.CostBearer.Organisation != null)
					{
						var orgDC = new CompactOrganisationDC();
						orgDC.Name = iCBRel.CostBearer.Organisation.Name;
						orgDC.OrganisationOid = iCBRel.CostBearer.Organisation.Oid.Value;

						costBearer.Organisation = orgDC;

						// costBearer.Street = iCBRel.CostBearer.Organisation.Address.Street;
						// costBearer.PostalCode = iCBRel.CostBearer.Organisation.Address.PostalCode;
						// costBearer.Town = iCBRel.CostBearer.Organisation.Address.Town;
					}

					costBearer.IsCalculatingWithFactor = iCBRel.CostBearer.IsCalculatingWithFactor;
					costBearer.CostBearerID = iCBRel.CostBearer.ID;
					costBearer.CostBearerOid = iCBRel.CostBearer.Oid.Value;
					costBearer.CostBearer2SupportConceptOid = iCBRel.Oid.Value;
					costBearer.SupportConceptStatus = iCBRel.Status;
					costBearer.RequestedStartDate = iCBRel.RequestedStartDate;
					costBearer.RequestedEndDate = iCBRel.RequestedEndDate;
					costBearer.ApprovedStartDate = iCBRel.ApprovedStartDate;
					costBearer.ApprovedEndDate = iCBRel.ApprovedEndDate;
					//costBearer.ApprovedFLS = iCBRel.ApprovedFLS;
					//costBearer.ApprovedFLSTotal = iCBRel.ApprovedFLSTotal;
					costBearer.CustomerReferenceNumber = iCBRel.CustomerReferenceNumber;

					dc.CostBearerList.Add(costBearer);
					dc.CustomerReferenceNumbers.Add(iCBRel.CustomerReferenceNumber);
					dc.CostBearerRelOids.Add(iCBRel.Oid.Value);
				}
			}

			if (currentEmployeeOid != null)
			{
				foreach (Employee2Customer e2c in cust.Employee2CustomerList)
				{
					if (!dc.IsRelatedToEmployee)
					{
						if (currentEmployeeOid.Value == e2c.EmployeeOid.Value)
						{
							dc.IsRelatedToEmployee = true;
						}
					}
				}
			}

			return dc;
		}

		private static void MakeCustomerHistoryEntry(Customer lOriginal, long? Oid, StatementType statementType, List<Customer2Person> originalCustomer2PersonList, List<Customer2Organisation> originalC2OList, List<Employee2Customer> originale2CList)
		{
		    var lCustomerHistory = new CustomerHistory
		    {
		        ChangeType          = statementType,
		        Childs              = lOriginal.Childs,
		        CostCenter          = lOriginal.CostCenter,
		        CustomerInsTs       = lOriginal.InsTs,
		        CustomerInsUser     = lOriginal.InsUser,
		        CustomerOid         = Oid ?? lOriginal.Oid,
		        CustomerUdpUser     = lOriginal.UdpUser,
		        CustomerVersion     = lOriginal.Version.Value,
		        DebitorNumber       = lOriginal.DebitorNumber,
		        Diagnosis           = lOriginal.Diagnosis,
		        Environment         = lOriginal.Environment,
		        EquityContribution  = lOriginal.EquityContribution,
		        ICD10Diagnosis      = lOriginal.ICD10Diagnosis,
		        IsAdvisedOrAttended = lOriginal.IsAdvisedOrAttended,
		        Medication          = lOriginal.Medication,
		        Notice              = lOriginal.Notice,
		        Person              = lOriginal.Person,
		        ReferenceNumber     = lOriginal.ReferenceNumber,
		        TerminationDate     = lOriginal.TerminationDate,
		        AssistanceBegin     = lOriginal.AssistanceBegin
		        //Jugendamt         = lOriginal.Jugendamt,
		        //Ansprechpartner   = lOriginal.Ansprechpartner
		    };

			DAOFactory.GenericDAO.Insert(lCustomerHistory);

			MakeHistoryEntry(lOriginal.Customer2PersonList, originalCustomer2PersonList, lOriginal.Oid, statementType);
			MakeHistoryEntry(lOriginal.Customer2OrganisationList, originalC2OList, lOriginal.Oid, statementType);
			MakeHistoryEntry(lOriginal.Employee2CustomerList, originale2CList, lOriginal.Oid, statementType);
		}

		private static void MakeHistoryEntry<T>(IList<T> lNewList, List<T> lOriginalList, long? customerOid, StatementType sType) where T : BeWoEntityBase
		{
			if (sType.Equals(StatementType.Delete) || sType.Equals(StatementType.Insert) || sType.Equals(StatementType.Archived) || sType.Equals(StatementType.Reactivate))
			{
				foreach (T newObject in lNewList)
					MakeActualHistoryEntry(newObject, sType, customerOid);

				return;
			}

			List<long?> OidOfOriginalsList = lOriginalList.Select(element => element.Oid.Value).Select(oid => (long?) oid).ToList();
			List<long?> OidOfNewsList = lNewList.Select(element => element.Oid.Value).Select(oid => (long?) oid).ToList();

			if (lOriginalList.Count <= 0 && lNewList.Count <= 0)
				return;

			foreach (T newObject in lNewList)
			{
				if (!OidOfOriginalsList.Contains(newObject.Oid))
					MakeActualHistoryEntry(newObject, StatementType.Insert, customerOid);
				else
				{
					T TObject = lOriginalList.Find(t => t.Oid.Equals(newObject.Oid));
					if (TObject.Version != newObject.Version)
						MakeActualHistoryEntry(newObject, StatementType.Update, customerOid);
				}
			}

			foreach (T oldObject in lOriginalList.Where(oldObject => !OidOfNewsList.Contains(oldObject.Oid)))
				MakeActualHistoryEntry(oldObject, StatementType.Delete, customerOid);
		}

		private static void MakeActualHistoryEntry<T>(T entityObj, StatementType sType, long? customerOid)
		{
			Customer customer = null;
			if (customerOid != null)
				customer = DAOFactory.GenericDAO.LoadByID<Customer>(customerOid.Value);

			if (entityObj is Customer2Person)
			{
				var customer2Person = entityObj as Customer2Person;
				var historyEntry = new Customer2PersonHistory
				{
					ChangeType = sType,
					Customer2PersonInsTs = customer2Person.InsTs,
					Customer2PersonInsUser = customer2Person.InsUser,
					Customer2PersonOid = customer2Person.Oid,
					Customer2PersonUdpUser = customer2Person.UdpUser,
					Customer2PersonVersion = customer2Person.Version.Value,
					Notice = customer2Person.Notice,
					Person = customer2Person.Person,
					CustomerOid = customer.Oid
				};

				DAOFactory.GenericDAO.Insert(historyEntry);
			}
			else if (entityObj is Customer2Organisation)
			{
				var customer2Organisation = entityObj as Customer2Organisation;
				var historyEntry = new Customer2OrganisationHistory
				{
					ChangeType = sType,
					Organisation = customer2Organisation.Organisation,
					Notice = customer2Organisation.Notice,
					Customer2OrganisationInsTs = customer2Organisation.InsTs,
					Customer2OrganisationOid = customer2Organisation.Oid,
					Customer2OrganisationInsUser = customer2Organisation.InsUser,
					Customer2OrganisationUdpUser = customer2Organisation.UdpUser,
					Customer2OrganisationVersion = customer2Organisation.Version.Value,
					Info1 = customer2Organisation.Info1,
					Info2 = customer2Organisation.Info2,
					Info3 = customer2Organisation.Info3,
					Info4 = customer2Organisation.Info4,
					Info5 = customer2Organisation.Info5,
					CustomerOid = customer.Oid
				};

				DAOFactory.GenericDAO.Insert(historyEntry);
			}
			else if (entityObj is Employee2Customer)
			{
				var employee2Customer = entityObj as Employee2Customer;
				var historyEntry = new Employee2CustomerHistory
				{
					ChangeType = sType,
					Customer = customer,
					CustomerOid = customer.Oid,
					Employee = employee2Customer.Employee,
					EmployeeOid = employee2Customer.EmployeeOid,
					Employee2CustomerInsTs = employee2Customer.InsTs,
					Employee2CustomerInsUser = employee2Customer.InsUser,
					Employee2CustomerOid = employee2Customer.Oid.Value,
					Employee2CustomerUdpUser = employee2Customer.UdpUser,
					Employee2CustomerVersion = employee2Customer.Version.Value,
					Notice = employee2Customer.Notice
				};

				DAOFactory.GenericDAO.Insert(historyEntry);
			}
		}

		private static object[] GetFromNHibernateDecoupledCustomerRelatedLists(Customer customer)
		{
			var CustomerRelatedListsList = new object[3];

			List<Customer2Person> originalC2PList = customer.Customer2PersonList.Select(element => new Customer2Person
			{
				Person = element.Person,
				Notice = element.Notice,
				Oid = element.Oid,
				InsTs = element.InsTs,
				InsUser = element.InsUser,
				UdpUser = element.UdpUser,
				ValueList = element.ValueList,
				Version = element.Version
			}).ToList();

			List<Customer2Organisation> originalC2OList =
				customer.Customer2OrganisationList.Select(element => new Customer2Organisation
				{
					Info1 = element.Info1,
					Info2 = element.Info2,
					Info3 = element.Info3,
					Info4 = element.Info4,
					Info5 = element.Info5,
					Notice = element.Notice,
					Oid = element.Oid,
					InsTs = element.InsTs,
					InsUser = element.InsUser,
					UdpUser = element.UdpUser,
					Organisation = element.Organisation,
					ValueList = element.ValueList,
					Version = element.Version
				}).ToList();

			List<Employee2Customer> original2CList =
				customer.Employee2CustomerList.Select(element => new Employee2Customer
				{
					Customer = customer,
					CustomerOid = element.CustomerOid,
					Employee = element.Employee,
					EmployeeOid = element.EmployeeOid,
					Notice = element.Notice,
					Oid = element.Oid,
					InsTs = element.InsTs,
					InsUser = element.InsUser,
					UdpUser = element.UdpUser,
					ValueList = element.ValueList,
					Version = element.Version
				}).ToList();

			CustomerRelatedListsList[0] = originalC2PList;
			CustomerRelatedListsList[1] = originalC2OList;
			CustomerRelatedListsList[2] = original2CList;

			return CustomerRelatedListsList;
		}

		public List<SupportConceptDC> GetAllActiveSupportConceptsByCustomers(IEnumerable<long> pCustomerOids)
		{
			try
			{
				var result = new List<SupportConceptDC>();
				var supportConcepts = DAOFactory.SearchDAO.GetAllActiveSupportConceptsByCustomers(pCustomerOids.ToList());

				result.AddRange(MapperFactory.SupportConceptDC_SupportConcept.MapToNewDCs(supportConcepts));

				return result;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CompactCustomerDC> GetCompactCustomersById(IEnumerable<long> pCustomerOids)
		{
			try
			{
				var result = new List<CompactCustomerDC>();

				var customers = DAOFactory.GenericDAO.LoadByIDs<Customer>(pCustomerOids);
				result.AddRange(MapperFactory.CompactCustomerDC_Customer.MapToNewDCs(customers));

				return result;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<ValueListEntryDC> GetSupportConceptGoalParents(IEnumerable<long> pParentItemOids)
		{
			try
			{
				var result = new List<ValueListEntryDC>();

				var parents = DAOFactory.GenericDAO.LoadByIDs<ValueListEntry>(pParentItemOids);
				result.AddRange(MapperFactory.ValueListEntryDC_ValueListEntry.MapToNewDCs(parents));

				return result;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<DarreichungsformDC> GetAllDarreichungsformen()
		{
			try
			{
				return MapperFactory.DarreichungsformDC_Darreichungsform.MapToNewDCs(DAOFactory.GenericDAO.GetAll<Darreichungsform>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<DarreichungsformDC> GetDarreichungsformenById(List<long> pIds)
		{
			try
			{
				return pIds.Select(id => MapperFactory.DarreichungsformDC_Darreichungsform.MapToNewDC(DAOFactory.GenericDAO.GetByID<Darreichungsform>(id))).ToList();
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<DepotRhythmusDC> GetAllDepotRhythmen()
		{
			try
			{
				return MapperFactory.DepotRhythmusDC_DepotRhythmus.MapToNewDCs(DAOFactory.GenericDAO.GetAll<DepotRhythmus>());
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<DepotRhythmusDC> GetDepotRhythmusById(List<long> pIds)
		{
			try
			{
				return pIds.Select(id => MapperFactory.DepotRhythmusDC_DepotRhythmus.MapToNewDC(DAOFactory.GenericDAO.GetByID<DepotRhythmus>(id))).ToList();
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<CustomerDC> GetActiveCustomersById(List<long> pCustomerOids)
		{
			try
			{
				return MapperFactory.CustomerDC_Customer.MapToNewDCs(DAOFactory.GenericDAO.GetActiveByIDs<Customer>(pCustomerOids));
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public List<SupportConceptDC> GetAllActiveAndUnexpiredSupportConceptsByCustomers(IEnumerable<long> pCustomerOids)
		{
			try
			{
				var result = new List<SupportConceptDC>();
				var supportConcepts = DAOFactory.SearchDAO.GetAllActiveSupportConceptsByCustomers(pCustomerOids.ToList());

				result.AddRange(MapperFactory.SupportConceptDC_SupportConcept.MapToNewDCs(supportConcepts));

				return result;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void ReactivateCustomer(long pOid, long pVersion)
		{
			var c = DAOFactory.GenericDAO.LoadByID<Customer>(pOid);
			c.Person.IsActive = ActivationTypeId.Active;

			foreach (var sc in c.SupportConcepts)
			{
				ServiceLogic.SetActivationType<SupportConcept>(sc.Oid.Value, sc.Version.Value, ActivationTypeId.Active);
			}

			ServiceLogic.SetActivationType<Customer>(pOid, pVersion, ActivationTypeId.Active);

			MakeCustomerHistoryEntry(c, null, StatementType.Reactivate, null, null, null);
		}

		public void ReactivateSupportConcept(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<SupportConcept>(pOid, pVersion, ActivationTypeId.Active);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void ReactivateOrganisation(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<Organisation>(pOid, pVersion, ActivationTypeId.Active);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void ReactivatePerson(long pOid, long pVersion)
		{
			try
			{
				ServiceLogic.SetActivationType<Person>(pOid, pVersion, ActivationTypeId.Active);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

	    public void ArchiveWohnheim(long pOid, long pVersion)// => GOGO
        {
            try
            {
                var e = DAOFactory.GenericDAO.LoadByID<Wohnheim>(pOid);
                e.IsActive = ActivationTypeId.Archived;

                ServiceLogic.SetActivationType<Wohnheim>(pOid, pVersion, ActivationTypeId.Archived);

            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateWohnheim(long pOid, long pVersion)// => GOGO
        {
            try
            {
                ServiceLogic.SetActivationType<Employee>(pOid, pVersion, ActivationTypeId.Deleted);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactWohnheimDC> GetAllActiveAndArchivedWohnheimCompact()// =>GOGO
        {
            try
            {
                return MapperFactory.CompactWohnheimDC_Wohnheim.MapToNewDCs(DAOFactory.GenericDAO.GetAllActiveAndArchived<Wohnheim>());
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public long UpdateWohnheim(WohnheimDC dc)// => GOGO
        {
            try
            {
                var original = DAOFactory.GenericDAO.LoadByID<Wohnheim>(dc.WohnheimOid.Value);

                MapperFactory.WohnheimDC_Wohnheim.MergeWithEntity(dc, original);
                DAOFactory.GenericDAO.Update(original);

                return original.Oid.Value;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactWohnheimDC> GetLastOpenedWohnheim() // => GOGO
        {
            try
            {
                var list = MapperFactory.CompactWohnheimDC_Wohnheim.MapToNewDCs(SettingsLogic.GetLastOpened<Wohnheim>());

                return list;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public long InsertNewWohnheim(WohnheimDC pWohnheimDC)// = GOGO
        {
            try
            {
     
                Wohnheim lWohnheim= MapperFactory.WohnheimDC_Wohnheim.MapToNewEntity(pWohnheimDC);
                DAOFactory.GenericDAO.Insert(lWohnheim);
                return lWohnheim.Oid.Value;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public WohnheimDC LoadWohnheim(long pWohnheimOid) // => GOGO
        {
            try
            {
                SettingsLogic.AddToUsersHistory<Wohnheim>(pWohnheimOid);
                return MapperFactory.WohnheimDC_Wohnheim.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Wohnheim>(pWohnheimOid));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<WohnheimbuchungDC> GetAllActiveWohnheimbuchungen()
        {
            try
            {
                var wohnheimbuchungen = DAOFactory.GenericDAO.GetAllActive<Wohnheimbuchung>();

                return MapperFactory.WohnheimbuchungDC_Wohnheimbuchung.MapToNewDCs(wohnheimbuchungen);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public WohnheimbuchungDC GetWohnheimbuchung(long oid)
        {
            try
            {
                return MapperFactory.WohnheimbuchungDC_Wohnheimbuchung.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Wohnheimbuchung>(oid));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public long UpdateWohnheimbuchung(WohnheimbuchungDC buchung)
        {
            try
            {
                var original = DAOFactory.GenericDAO.LoadByID<Wohnheimbuchung>(buchung.WohnheimbuchungOid.Value);
                MapperFactory.WohnheimbuchungDC_Wohnheimbuchung.MergeWithEntity(buchung, original);
                DAOFactory.GenericDAO.Update(original);

                return original.Oid.Value;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public long InsertWohnheimbuchung(WohnheimbuchungDC buchung)
	    {
            try
            {
                var blubb = MapperFactory.WohnheimbuchungDC_Wohnheimbuchung.MapToNewEntity(buchung);
                DAOFactory.GenericDAO.Insert(blubb);
                return blubb.Oid.Value;
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

        public List<CompactWohnheimDC> GetAllActiveWohnheimeCompact()
        {
            try
            {
                var wohnheime = DAOFactory.GenericDAO.GetAllActive<Wohnheim>();

                return MapperFactory.CompactWohnheimDC_Wohnheim.MapToNewDCs(wohnheime);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public WohnheimbuchungDC GetWohnheimbuchungByWohnheimAndBuchungsdatum(long pWohnheimOid, DateTime pBuchungsdatum)
	    {
	        try
	        {
	            var wohnheimbuchung = DAOFactory.SearchDAO.GetWohnheimbuchungByWohnheimAndBuchungsdatum(pWohnheimOid, pBuchungsdatum);

	            return wohnheimbuchung == null ? null : MapperFactory.WohnheimbuchungDC_Wohnheimbuchung.MapToNewDC(wohnheimbuchung);
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    public List<ServiceRecordDC> FindWohnheimbuchungsServiceRecords(long pWohnheimbuchungsOid)
	    {
	        try
	        {
	            var servicerecords = DAOFactory.SearchDAO.FindWohnheimbuchungsServiceRecords(pWohnheimbuchungsOid);

                return MapperFactory.ServiceRecordDC_ServiceRecord.MapToNewDCs(servicerecords);
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    public void DeleteWohnheimbuchung(long pWohnheimbuchungsOid, long pWohnheimbuchungsVersion)
	    {
            try
            {
                var lOriginal = DAOFactory.GenericDAO.LoadByID<Wohnheimbuchung>(pWohnheimbuchungsOid);

                MapperFactory.WohnheimbuchungDC_Wohnheimbuchung.ConcurrencyCheck(pWohnheimbuchungsVersion, lOriginal);

                DAOFactory.GenericDAO.Delete(lOriginal);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    public List<SupportConceptDC> GetAllActiveSupportConcepts()
	    {
            try
            {
                var supportConcepts = DAOFactory.GenericDAO.GetAllActive<SupportConcept>();

                return MapperFactory.SupportConceptDC_SupportConcept.MapToNewDCs(supportConcepts);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    public List<long> CreateServiceRecordsFromWohnheimbuchung(long pWohnheimbuchungsOid, long pServiceDescriptionOid)
	    {
	        try
	        {
	            var buchung = DAOFactory.GenericDAO.GetByID<Wohnheimbuchung>(pWohnheimbuchungsOid);

                var mitarbeiterRelationen = buchung.Employee2WohnheimbuchungList.OrderBy(a => a.StartDate).ThenBy(a => a.EndDate).ToList();
                var hilfeplaeneRelationen = buchung.Costbearer2SupportConcept2WohnheimbuchungList.OrderBy(a => a.StartDate).ThenBy(a => a.EndDate).ToList();

                var mitarbeiterTimeSpans   = CreateWohnheimbuchungsMitarbeiterTimeSpans(mitarbeiterRelationen);
                var hilfeplanTimeSpans     = CreateWohnheimbuchungsHilfeplanTimeSpans(hilfeplaeneRelationen);
                var serviceRecordTimeSpans = ComplexWohnheimbuchungsRelationHelper.CalculateServiceRecordTimeSpans(mitarbeiterTimeSpans, hilfeplanTimeSpans);

                var employees                  = buchung.Employee2WohnheimbuchungList.Select(s => s.Employee).ToList();
                var costbearer2supportconcepts = buchung.Costbearer2SupportConcept2WohnheimbuchungList;

                var newServiceRecords = new List<ServiceRecord>();

                var factory = PluginLoader.FindClass<ServiceRecordStatisticFactory>() ?? new ServiceRecordStatisticFactory();

	            foreach (var srTimeSpan in serviceRecordTimeSpans)
	            {
                    var employeeList = employees.Where(w => srTimeSpan.RelatedEmployees.Contains(w.Oid.Value)).Distinct().ToList();
                    var wohnheimbuchung2Costbearer2SupportConceptList = costbearer2supportconcepts.Where(w => srTimeSpan.RelatedSupportConcepts.Contains(w.CostBearer2SupportConcept.Oid.Value)).Distinct().ToList();

	                var intervalldauer = (srTimeSpan.Zeitspanne.EndDate - srTimeSpan.Zeitspanne.StartDate).TotalMinutes*employeeList.Count;

	                var statisticsList = new Dictionary<long, SupportConceptStatisticsDC>();

	                var FLSgesamt     = 0m;
                    var geleisteteFLS = 0m;

                    wohnheimbuchung2Costbearer2SupportConceptList.DoForEach(d => statisticsList.Add(d.CostBearer2SupportConcept.Oid.Value, factory.CreateSupportConceptStatistics(d.CostBearer2SupportConcept.Oid.Value, DateTime.Now)));
	                var serviceDescription = DAOFactory.GenericDAO.GetByID<ServiceDescription>(5);

	                var costbearer2SupportConcept2offeneFLS = new Dictionary<long, decimal>();
	                wohnheimbuchung2Costbearer2SupportConceptList.DoForEach(d => costbearer2SupportConcept2offeneFLS.Add(d.CostBearer2SupportConcept.Oid.Value, 0m));

                    foreach(var stat in statisticsList)
                    {
                        decimal tmpFLSgesamt = 0;
                        decimal tmpGeleistet = 0;

                        if (stat.Value.PeriodStatistics.Any(a => a.SupportConceptApprovalPeriod.ServiceCategory != null && a.SupportConceptApprovalPeriod.ServiceCategory.ServiceCategoryOid == serviceDescription.ServiceCategory.Oid))
                        {
                            tmpFLSgesamt = stat.Value.PeriodStatistics.Where(w => w.SupportConceptApprovalPeriod.ServiceCategory != null && w.SupportConceptApprovalPeriod.ServiceCategory.ServiceCategoryOid.Value == serviceDescription.ServiceCategory.Oid.Value).Sum(s => s.MinutesApprovedTotal);
                            tmpGeleistet = stat.Value.PeriodStatistics.Where(w => w.SupportConceptApprovalPeriod.ServiceCategory != null && w.SupportConceptApprovalPeriod.ServiceCategory.ServiceCategoryOid.Value == serviceDescription.ServiceCategory.Oid.Value).Sum(s => s.MinutesProvidedTotal);
                        }
                        else
                        {
                            tmpFLSgesamt = stat.Value.PeriodStatistics.Where(w => w.SupportConceptApprovalPeriod.ServiceCategory == null).Sum(s => s.MinutesApprovedTotal);
                            tmpGeleistet = stat.Value.PeriodStatistics.Where(w => w.SupportConceptApprovalPeriod.ServiceCategory == null).Sum(s => s.MinutesProvidedTotal);
                        }

                        geleisteteFLS += tmpGeleistet;
                        FLSgesamt     += tmpFLSgesamt;

                        costbearer2SupportConcept2offeneFLS[stat.Key] = (tmpFLSgesamt - tmpGeleistet) / 60;
                    }

                    FLSgesamt     /= 60;
                    geleisteteFLS /= 60;

	                var offeneFLS  = FLSgesamt - geleisteteFLS;
	                var dienstzeit = intervalldauer/employeeList.Count;
	                var zeiten     = new Dictionary<Wohnheimbuchung2Costbearer2SupportConcept, int>();

                    var anteilsliste = new Dictionary<long, decimal>();

	                foreach (var item in wohnheimbuchung2Costbearer2SupportConceptList)
	                {

                        var offen = costbearer2SupportConcept2offeneFLS[item.CostBearer2SupportConcept.Oid.Value];
	                    var anteil = 0m;

	                    if (offeneFLS > 0)
	                    {
	                        anteil = offen/offeneFLS;
	                    }

                        anteilsliste.Add(item.Oid.Value, anteil);
	                }

                    var wb2cb2sc2Anteil = new Dictionary<long, decimal>();

	                if (anteilsliste.Any(a => a.Value > .5m) && employeeList.Count > 1)
	                {
	                    var ueberschuss = 0m;
	                    var restanteil  = 0m;

	                    foreach (var anteil in anteilsliste)
	                    {
	                        if (anteil.Value > .5m)
	                        {
	                            ueberschuss = anteil.Value - .5m;
	                            restanteil  = 1m - anteil.Value;
	                            wb2cb2sc2Anteil.Add(anteil.Key, .5m);
	                        }
	                        else
	                        {
	                            wb2cb2sc2Anteil.Add(anteil.Key, (anteil.Value/restanteil*ueberschuss) + anteil.Value);
	                        }
	                    }
	                }

	                anteilsliste = wb2cb2sc2Anteil.Count == anteilsliste.Count ? wb2cb2sc2Anteil.OrderByDescending(obd => obd.Value).ToDictionary(d => d.Key, d => d.Value) : anteilsliste;

	                if (anteilsliste.Any())
	                {
	                    foreach (var wb2cb2sc in wohnheimbuchung2Costbearer2SupportConceptList)
	                    {
	                        var anteil = anteilsliste[wb2cb2sc.Oid.Value];
	                        var customerIntervall = Convert.ToDecimal(intervalldauer)*anteil;
                            
                            var gerundeterCustomerIntervall = Convert.ToInt32(Math.Round(customerIntervall, 0, MidpointRounding.AwayFromZero));
                            //var gerundeterCustomerIntervall = Convert.ToInt32(Math.Round(customerIntervall / 10, 0, MidpointRounding.AwayFromZero) * 10);

	                        var customer = wb2cb2sc.CostBearer2SupportConcept.SupportConcept.Customer.Person.ToString();

                            zeiten.Add(wb2cb2sc, gerundeterCustomerIntervall);
	                    }
	                }

	                zeiten = zeiten.OrderByDescending(o => o.Value).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
	                var neueZeiten = new List<WohnheimbuchungsIntervallStruct>();

	                var bisherigeZeit    = 0;
	                var employeeIterator = 0;

	                foreach (var item in zeiten)
	                {
	                    if (bisherigeZeit + item.Value < dienstzeit)
	                    {
	                        bisherigeZeit += item.Value;
	                        neueZeiten.Add(new WohnheimbuchungsIntervallStruct {Wohnheimbuchung2Costbearer2SupportConcept = item.Key, Employee = employeeList[employeeIterator], Intervall = item.Value});
	                    }
	                    else
	                    {
	                        var z1 = dienstzeit - bisherigeZeit;
	                        var z2 = item.Value - z1;

                            neueZeiten.Add(new WohnheimbuchungsIntervallStruct{Wohnheimbuchung2Costbearer2SupportConcept = item.Key, Employee = employeeList[employeeIterator], Intervall = z1});

	                        if (employeeIterator < employeeList.Count - 1)
	                        {
	                            employeeIterator++;
	                        }

                            neueZeiten.Add(new WohnheimbuchungsIntervallStruct{Wohnheimbuchung2Costbearer2SupportConcept = item.Key, Employee = employeeList[employeeIterator],Intervall = z2});

	                        bisherigeZeit = 0;
	                    }
	                }

	                neueZeiten = neueZeiten.Where(w => w.Intervall > 0).ToList();

	                var startTime = srTimeSpan.Zeitspanne.StartDate;
	                foreach (var item in neueZeiten)
	                {
                        var sr = new ServiceRecord
                        {
                            CostBearer2SupportConcept = item.Wohnheimbuchung2Costbearer2SupportConcept.CostBearer2SupportConcept,
                            CostBearer2SupportConceptOid = item.Wohnheimbuchung2Costbearer2SupportConcept.CostBearer2SupportConcept.Oid,
                            Customer = item.Wohnheimbuchung2Costbearer2SupportConcept.CostBearer2SupportConcept.SupportConcept.Customer,
                            CustomerOid = item.Wohnheimbuchung2Costbearer2SupportConcept.CostBearer2SupportConcept.SupportConcept.Customer.Oid,
                            DistanceInMeter = 0,
                            Employee = item.Employee,
                            EmployeeOid = item.Employee.Oid,

                            Start = startTime,
                            End = startTime.AddMinutes(item.Intervall),

                            Notice = item.Wohnheimbuchung2Costbearer2SupportConcept.Notice,
                            ServiceDescription = serviceDescription,
                            ServiceRecordType = ServiceRecordTypeId.Wohnheimbuchung,
                            SupportConcept = item.Wohnheimbuchung2Costbearer2SupportConcept.CostBearer2SupportConcept.SupportConcept,
                            WohnheimbuchungsOid = buchung.Oid
                        };

	                    startTime = startTime.AddMinutes(item.Intervall) >= srTimeSpan.Zeitspanne.EndDate ? srTimeSpan.Zeitspanne.StartDate : startTime.AddMinutes(item.Intervall);

                        var currentlyValidRate = item.Wohnheimbuchung2Costbearer2SupportConcept.CostBearer2SupportConcept.CostBearer.GetCurrentlyValidRate(CostRatePeriodType.MinutesIntervall);
	                    var minutenIntervall   = Convert.ToInt32(currentlyValidRate != null ? currentlyValidRate.CostRateValue : 0m);

                        var costbearerID = item.Wohnheimbuchung2Costbearer2SupportConcept.CostBearer2SupportConcept.CostBearer.ID;

                        if (minutenIntervall > 0)
                        {
                            var calc = Calculations.GetInstance(costbearerID);
                            sr.RoundedDuration = calc.GetRoundedDuration(minutenIntervall, Convert.ToDecimal(item.Intervall));
                        }

                        newServiceRecords.Add(sr);
	                }
                }

                var bestehendeEintraege = DAOFactory.SearchDAO.FindWohnheimbuchungsServiceRecords(pWohnheimbuchungsOid);
	            if (bestehendeEintraege.Count > 0)
	            {
	                OperationsServiceImp.InternalDeleteServicerecords(bestehendeEintraege.ToDictionary(k => k.Oid.Value, v => v.Version.Value));
	            }

	            return OperationsServiceImp.InternalInsertNewServiceRecords(newServiceRecords);
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    private IEnumerable<ComplexWohnheimbuchungsRelationHelper> CreateWohnheimbuchungsMitarbeiterTimeSpans(IEnumerable<Wohnheimbuchung2Employee> pMitarbeiter)
	    {
	        var result = new List<ComplexWohnheimbuchungsRelationHelper>();

            var employeeRelations = pMitarbeiter.OrderBy(a => a.StartDate.Value).ThenBy(a => a.EndDate.Value).ToList();
            MitarbeiterIntervallListe = employeeRelations.Select(
                item => new WohnheimbuchungsIntervall(
                    item.Oid.Value,
                    new DateTimeSpan { IsCalculatingHoursAndMinutesByDates = true, StartDate = item.StartDate.Value, EndDate = item.EndDate.Value },
                    WohnheimbuchungsintervallTyp.Employee,
                    new List<long> { item.Employee.Oid.Value })
                ).ToList();

            foreach (var intervall in MitarbeiterIntervallListe.Where(intervall => MitarbeiterIntervallListe.Where(w => w.RelationOid != intervall.RelationOid).Any(a => intervall.Span.Overlaps(a.Span))))
            {
                AlleMitarbeiterUeberschneidungen.AddOrUpdateValueInDictionary(intervall.RelationOid, MitarbeiterIntervallListe.Where(w => w.RelationOid != intervall.RelationOid && intervall.Span.Overlaps(w.Span)).ToList());
            }

            var aussortiereMitarbeiterRelOids = new List<long>();

            foreach (var intervall in MitarbeiterIntervallListe)
            {
                if (aussortiereMitarbeiterRelOids.Contains(intervall.RelationOid))
                {
                    continue;
                }

                if (AlleMitarbeiterUeberschneidungen.ContainsKey(intervall.RelationOid))
                {
                    OverlappingElements = new Dictionary<long, WohnheimbuchungsIntervall>();
                    GetOverlappingRelations(intervall);

                    var relatedElements = OverlappingElements.Values;

                    aussortiereMitarbeiterRelOids.AddRange(relatedElements.Select(s => s.RelationOid));
                    aussortiereMitarbeiterRelOids.Add(intervall.RelationOid);

                    var tmpList = new List<SimpleWohnheimbuchungsRelationHelper>();
                    tmpList.AddRange(relatedElements.Select(s => new SimpleWohnheimbuchungsRelationHelper { Datum = s.Span.StartDate, RelatedObjects = new List<long>(s.RelatedObjects) }));
                    tmpList.AddRange(relatedElements.Select(s => new SimpleWohnheimbuchungsRelationHelper { Datum = s.Span.EndDate, RelatedObjects = new List<long>(s.RelatedObjects) }));
                    tmpList.AddRange(relatedElements.Select(s => new SimpleWohnheimbuchungsRelationHelper { Datum = s.Span.StartDate, RelatedObjects = new List<long>(s.RelatedObjects) }));
                    tmpList.AddRange(relatedElements.Select(s => new SimpleWohnheimbuchungsRelationHelper { Datum = s.Span.EndDate, RelatedObjects = new List<long>(s.RelatedObjects) }));
                    tmpList = tmpList.OrderBy(o => o.Datum).ToList();

                    for (var i = 0; i < tmpList.Count; i++)
                    {
                        if ((i + 1) >= tmpList.Count)
                        {
                            break;
                        }

                        if (tmpList[i].Datum == tmpList[i + 1].Datum)
                        {
                            continue;
                        }

                        var current = new DateTimeSpan { IsCalculatingHoursAndMinutesByDates = true, StartDate = tmpList[i].Datum, EndDate = tmpList[i + 1].Datum };
                        var withCurrentOverlappingElements = relatedElements.Where(w => w.Span.Overlaps(current)).ToList();
                        var employeeOids = new List<long>();
                        employeeOids = withCurrentOverlappingElements.Aggregate(employeeOids, (current1, a) => current1.Union(a.RelatedObjects).ToList());

                        result.Add(new ComplexWohnheimbuchungsRelationHelper(current, employeeOids, new List<long>()));
                    }
                }
                else
                {
                    result.Add(new ComplexWohnheimbuchungsRelationHelper(intervall.Span, intervall.RelatedObjects, new List<long>()));
                }
            }

	        return result;
	    }

        private List<ComplexWohnheimbuchungsRelationHelper> CreateWohnheimbuchungsHilfeplanTimeSpans(IEnumerable<Wohnheimbuchung2Costbearer2SupportConcept> pHilfeplaene)
        {
            var result = new List<ComplexWohnheimbuchungsRelationHelper>();

            var hilfeplaene = pHilfeplaene.OrderBy(o => o.StartDate).ThenBy(t => t.EndDate).ToList();
            HilfeplanIntervallListe = hilfeplaene.Select(
                item => new WohnheimbuchungsIntervall(
                    item.Oid.Value,
                    new DateTimeSpan { IsCalculatingHoursAndMinutesByDates = true, StartDate = item.StartDate.Value, EndDate = item.EndDate.Value },
                    WohnheimbuchungsintervallTyp.SupportConcept,
                    new List<long> { item.CostBearer2SupportConcept.Oid.Value })).ToList();

            foreach (var intervall in HilfeplanIntervallListe.Where(intervall => MitarbeiterIntervallListe.Where(w => w.RelationOid != intervall.RelationOid).Any(a => intervall.Span.Overlaps(a.Span))))
            {
                AlleHilfeplanUeberschneidungen.AddOrUpdateValueInDictionary(intervall.RelationOid, HilfeplanIntervallListe.Where(w => w.RelationOid != intervall.RelationOid && intervall.Span.Overlaps(w.Span)).ToList());
            }

            var aussortiereHilfeplanRelOids = new List<long>();

            foreach (var intervall in HilfeplanIntervallListe)
            {
                if (aussortiereHilfeplanRelOids.Contains(intervall.RelationOid))
                {
                    continue;
                }

                if (AlleHilfeplanUeberschneidungen.ContainsKey(intervall.RelationOid))
                {
                    OverlappingElements = new Dictionary<long, WohnheimbuchungsIntervall>();

                    GetOverlappingRelations(intervall);

                    var relatedElements = OverlappingElements.Values;

                    aussortiereHilfeplanRelOids.AddRange(relatedElements.Select(s => s.RelationOid));
                    aussortiereHilfeplanRelOids.Add(intervall.RelationOid);

                    var tmpList = new List<SimpleWohnheimbuchungsRelationHelper>();
                    tmpList.AddRange(relatedElements.Select(s => new SimpleWohnheimbuchungsRelationHelper { Datum = s.Span.StartDate, RelatedObjects = new List<long>(s.RelatedObjects) }));
                    tmpList.AddRange(relatedElements.Select(s => new SimpleWohnheimbuchungsRelationHelper { Datum = s.Span.EndDate, RelatedObjects = new List<long>(s.RelatedObjects) }));
                    tmpList.AddRange(relatedElements.Select(s => new SimpleWohnheimbuchungsRelationHelper { Datum = s.Span.StartDate, RelatedObjects = new List<long>(s.RelatedObjects) }));
                    tmpList.AddRange(relatedElements.Select(s => new SimpleWohnheimbuchungsRelationHelper { Datum = s.Span.EndDate, RelatedObjects = new List<long>(s.RelatedObjects) }));
                    tmpList = tmpList.OrderBy(o => o.Datum).ToList();

                    for (var i = 0; i < tmpList.Count; i++)
                    {
                        if ((i + 1) >= tmpList.Count)
                        {
                            break;
                        }

                        if (tmpList[i].Datum == tmpList[i + 1].Datum)
                        {
                            continue;
                        }

                        var current = new DateTimeSpan { IsCalculatingHoursAndMinutesByDates = true, StartDate = tmpList[i].Datum, EndDate = tmpList[i + 1].Datum };
                        var withCurrentOverlappingElements = relatedElements.Where(w => w.Span.Overlaps(current)).ToList();
                        var supportConceptOids = new List<long>();
                        supportConceptOids = withCurrentOverlappingElements.Aggregate(supportConceptOids, (current1, a) => current1.Union(a.RelatedObjects).ToList());

                        result.Add(new ComplexWohnheimbuchungsRelationHelper(current, new List<long>(), supportConceptOids));
                    }
                }
                else
                {
                    result.Add(new ComplexWohnheimbuchungsRelationHelper(intervall.Span, new List<long>(), intervall.RelatedObjects));
                }
            }

            return result;
        }

        private readonly Dictionary<long, List<WohnheimbuchungsIntervall>> AlleMitarbeiterUeberschneidungen = new Dictionary<long, List<WohnheimbuchungsIntervall>>();
        private List<WohnheimbuchungsIntervall> MitarbeiterIntervallListe = new List<WohnheimbuchungsIntervall>();

        readonly Dictionary<long, List<WohnheimbuchungsIntervall>> AlleHilfeplanUeberschneidungen = new Dictionary<long, List<WohnheimbuchungsIntervall>>();
        List<WohnheimbuchungsIntervall> HilfeplanIntervallListe = new List<WohnheimbuchungsIntervall>();

        private Dictionary<long, WohnheimbuchungsIntervall> OverlappingElements = new Dictionary<long, WohnheimbuchungsIntervall>();

        private void GetOverlappingRelations(WohnheimbuchungsIntervall pIntervall)
        {
            OverlappingElements.AddAndIgnoreDuplicates(pIntervall.RelationOid, pIntervall);

            var kinder = pIntervall.Typ == WohnheimbuchungsintervallTyp.Employee ?
                MitarbeiterIntervallListe.Where(w => pIntervall.Span.Overlaps(w.Span)).ToList() :
                HilfeplanIntervallListe.Where(w => pIntervall.Span.Overlaps(w.Span)).ToList();

            foreach (var kind in kinder.Where(k => !OverlappingElements.ContainsKey(k.RelationOid)))
            {
                GetOverlappingRelations(kind);
            }
        }

	    public ServiceDescriptionDC FindServiceDescriptionForWohnheimbuchungsServiceRecord(long pWohnheimbuchungsOid)
	    {
	        try
	        {
	            var sd = DAOFactory.SearchDAO.FindServiceDescriptionForWohnheimbuchungsServiceRecord(pWohnheimbuchungsOid);

	            return sd == null ? null : MapperFactory.ServiceDescriptionDC_ServiceDescription.MapToNewDC(sd);
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    public List<CustomerPersonRelationDC> LoadCustomerPersonRelationsByOid(IEnumerable<long> pOids)
	    {
	        try
	        {
	            var customerPersonRels = DAOFactory.GenericDAO.LoadByIDs<Customer2Person>(pOids);

	            return MapperFactory.CustomerPersonRelationDC_Customer2Person.MapToNewDCs(customerPersonRels);
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

        public List<CustomerOrganisationRelationDC> LoadCustomerOrganisationRelationsByOid(IEnumerable<long> pOids)
        {
            try
            {
                var customerOrganisationRels = DAOFactory.GenericDAO.LoadByIDs<Customer2Organisation>(pOids);

                return MapperFactory.CustomerOrganisationRelationDC_Customer2Organisation.MapToNewDCs(customerOrganisationRels);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

	    public List<long> InsertMedRecords(List<MedRecordDC> pDCList)
	    {
            try
            {
                var medRecords = MapperFactory.MedRecordDC_MedRecord.MapToNewEntities(pDCList);
                DAOFactory.GenericDAO.Insert(medRecords);

                return medRecords.Select(r => r.Oid.Value).ToList();
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    public List<MedRecordDC> GetMedRecordsForCustomer(long pCustomerOid)
	    {
	        try
	        {
	            var medRecords = DAOFactory.SearchDAO.FindMedRecordsForCustomer(pCustomerOid);

	            return MapperFactory.MedRecordDC_MedRecord.MapToNewDCs(medRecords);
	        }
	        catch (Exception e)
	        {
	            throw Utils.CreateBeWoFaultException(e);
	        }
	    }

	    public List<MedRecordDC> UpdateMedRecords(List<MedRecordDC> pDCList)
	    {
	        try
	        {
                var lOriginals = DAOFactory.GenericDAO.LoadByIDs<MedRecord>(pDCList.Select(b => b.MedRecordOid.Value));
                MapperFactory.MedRecordDC_MedRecord.MergeWithEntitys(pDCList, lOriginals);
                DAOFactory.GenericDAO.Update(lOriginals);

                return MapperFactory.MedRecordDC_MedRecord.MapToNewDCs(lOriginals);
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    public void DeactivateMedRecords(Dictionary<long, long> pOid2Version)
	    {
	        try
	        {
                ServiceLogic.SetActivationType<MedRecord>(pOid2Version, ActivationTypeId.Deleted);
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    public void DeleteMedRecord(long pOid, long pVersion)
	    {
	        try
	        {
	            var lOriginal = DAOFactory.GenericDAO.LoadByID<MedRecord>(pOid);
                MapperFactory.MedRecordDC_MedRecord.ConcurrencyCheck(pVersion, lOriginal);

                DAOFactory.GenericDAO.Delete(lOriginal);
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    public string AndroidGetCustomerCompact(long pCustomerOid)
	    {
	        try
	        {
	            var customer = DAOFactory.GenericDAO.GetByID<Customer>(pCustomerOid);

	            return SerializeObject(MapperFactory.CompactCustomerDC_CustomerCompact.MapToNewDC(customer));
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

	    public List<CompactCustomerDC> GetAllChatActiveCustomersCompact()
	    {
	        try
	        {
	            var customers = DAOFactory.SearchDAO.FindAllChatActiveCustomers();

	            return MapperFactory.CompactCustomerDC_Customer.MapToNewDCs(customers);
	        }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
	    }

        public List<ChatMessageDC> FindAllChatMessages(long senderOid, long empfaengerOid)
        {
            try
            {
                var messages = DAOFactory.SearchDAO.FindAllChatMessages(senderOid, empfaengerOid);

                return MapperFactory.ChatMessagesDC_ChatMessages.MapToNewDCs(messages);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CustomerAPPCodeDC> GetAllCustomerAppCodes(long pCustomerOid)
        {

            var liste = DAOFactory.SearchDAO.FindAllCustomerAppCodes(pCustomerOid);


            return MapperFactory.CustomerAPPCodeDC_CustomerAPPCode.MapToNewDCs(liste);

        }

        public Byte[] GetCustomerImage(long customerOid)
        {
            try
            {
    
                var customer = DAOFactory.GenericDAO.GetByID<Customer>(customerOid);

                return customer.CustomerImage;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        private static String SerializeObject(object obj)
        {
            return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
        }
	}

    internal struct WohnheimbuchungsIntervallStruct
    {
        public Wohnheimbuchung2Costbearer2SupportConcept Wohnheimbuchung2Costbearer2SupportConcept;
        public Employee                                  Employee;
        public double                                    Intervall;
    }
}