예제 #1
0
        public override void Execute(XTriggerArgs args, IXExecutionContext context)
        {
            DomainObjectData xobj = args.TriggeredObject;
            // если изменилось значение признака "Архивное", проверим отсутствие у подразделения работающих сотрудников или не архивных департаментов.
            bool bUpdateIsArchive = xobj.HasUpdatedProp("IsArchive");

            if (bUpdateIsArchive)
            {
                bool newValue = (bool)xobj.GetUpdatedPropValue("IsArchive");
                if (!xobj.IsNew && newValue)
                {
                    //	1. Проверим, что все сотрудники (во всех вложенных департаментах) уволены
                    XDbCommand cmd = context.Connection.CreateCommand(@"
							SELECT 1 
							FROM dbo.Department d_s WITH(NOLOCK)
								JOIN dbo.Department d WITH(NOLOCK) ON d.LIndex >= d_s.LIndex AND d.RIndex <= d_s.RIndex AND d.Organization = d_s.Organization
									JOIN Employee e WITH(NOLOCK) ON (d.ObjectID = e.Department) and (e.WorkEndDate is null)
							WHERE d_s.ObjectID = @ObjectID
							"                            );
                    cmd.Parameters.Add("ObjectID", DbType.Guid, ParameterDirection.Input, false, xobj.ObjectID);
                    if (cmd.ExecuteScalar() != null)
                    {
                        throw new XBusinessLogicException("Департамент не может быть переведен с состояние \"Архивное\", так как содержит работающих сотрудников");
                    }
                }
                // добавим в датаграмму подчиненные департаменты
                UpdateChildDepartments(context.Connection, args.DataSet, xobj.ObjectID, newValue);
            }
        }
예제 #2
0
        /// <summary>
        /// Создает объект "Списание времение" на основании шаблона
        /// </summary>
        private DomainObjectData createTimeLossObject(DomainObjectDataSet dataSet, DomainObjectData template, ITUser user)
        {
            DomainObjectData xobj = dataSet.CreateStubNew("TimeLoss");

            xobj.SetUpdatedPropValue("Cause", template.GetUpdatedPropValue("Cause"));
            if (template.HasUpdatedProp("Worker"))
            {
                xobj.SetUpdatedPropValue("Worker", template.GetUpdatedPropValue("Worker"));
            }
            else
            {
                xobj.SetUpdatedPropValue("Worker", user.EmployeeID);
            }
            if (template.HasUpdatedProp("Folder"))
            {
                xobj.SetUpdatedPropValue("Folder", template.GetUpdatedPropValue("Folder"));
            }
            return(xobj);
        }
예제 #3
0
        public override void Execute(XTriggerArgs args, IXExecutionContext context)
        {
            DomainObjectData xobj = args.TriggeredObject;
            // Признак изменения Временной нетрудоспособности
            bool bUpdatedTemporaryDisability = xobj.HasUpdatedProp("TemporaryDisability");
            // Признак изменения Даты начала работы
            bool bUpdateWorkBeginDay = xobj.HasUpdatedProp("WorkBeginDate");
            // Признак изменения Даты окончания работы
            bool bUpdateWorkEndDay = xobj.HasUpdatedProp("WorkEndDate");

            // Если что-то менялось, то запишем это событие в историю
            if (bUpdatedTemporaryDisability)
            {
                bool oldValue = (bool)xobj.GetLoadedPropValueOrLoad(context.Connection, "TemporaryDisability");
                bool newValue = (bool)xobj.GetUpdatedPropValue("TemporaryDisability");
                // Если свойство действительно обновилось, то запишем в "историю"
                if (oldValue != newValue)
                {
                    setEmployeeHistoryEvent(args, EmployeeHistoryEvents.TemporaryDisability);
                    // Если сотрудник получил признак "Временная нетрудоспособность", то надо автоматически задать
                    // норму рабочего времени 0
                    if (newValue)
                    {
                        setEmployeeRate(args, "Временная нетрудоспособность", DateTime.Now);
                    }
                }
            }
            if (bUpdateWorkBeginDay)
            {
                setEmployeeHistoryEvent(args, EmployeeHistoryEvents.WorkBeginDay);
            }
            if (bUpdateWorkEndDay)
            {
                setEmployeeHistoryEvent(args, EmployeeHistoryEvents.WorkEndDay);
                // Если для сотрудника задали "Дату окончания работы", то надо автоматически задать
                // норму рабочего времени 0
                if (xobj.GetUpdatedPropValue("WorkEndDate") != DBNull.Value)
                {
                    setEmployeeRate(args, "Уволен", (DateTime)xobj.GetUpdatedPropValue("WorkEndDate"));
                }
            }
        }
예제 #4
0
        private void checkAndSyncReverseProps(DomainObjectDataSet dataSet)
        {
            IEnumerator enumerator = dataSet.GetModifiedObjectsEnumerator(true);
            object      vPropValue;

            while (enumerator.MoveNext())
            {
                DomainObjectData xobj = (DomainObjectData)enumerator.Current;
                foreach (string sPropName in xobj.UpdatedPropNames)
                {
                    XPropInfoBase propInfo = xobj.TypeInfo.GetProp(sPropName);
                    Debug.Assert(propInfo != null);
                    if (propInfo.VarType != XPropType.vt_object)
                    {
                        continue;
                    }

                    XPropInfoObject propInfoObj = (XPropInfoObject)propInfo;
                    if (propInfoObj.Capacity == XPropCapacity.CollectionMembership || propInfoObj.Capacity == XPropCapacity.Link)
                    {
                        Guid[] values = (Guid[])xobj.GetUpdatedPropValue(sPropName);
                        if (values.Length > 0)
                        {
                            foreach (Guid valueObjectID in values)
                            {
                                bool             bError    = false;
                                DomainObjectData xobjValue = dataSet.Find(propInfoObj.ReferedType.Name, valueObjectID);
                                // объект-значение объектного свойства sPropName есть в контексте и он будет сохраняться
                                if (xobjValue != null && xobjValue.HasNewData)
                                {
                                    // если текущее свойство "членство в коллекции" и в объекте-значении есть обратное свойство (коллекция),
                                    // проверим, что обратное свойство содержит ссылку на текущий объект (xobj)
                                    if (propInfoObj.Capacity == XPropCapacity.CollectionMembership && xobjValue.HasUpdatedProp(propInfoObj.ReverseProp.Name))
                                    {
                                        Guid[] propRevValues = (Guid[])xobjValue.GetUpdatedPropValue(propInfoObj.ReverseProp.Name);
                                        Debug.Assert(propRevValues != null);
                                        // если обратное свойство (коллекция) не содержит ссылку на текущий объект - исключение
                                        if (Array.IndexOf(propRevValues, xobj.ObjectID) == -1)
                                        {
                                            bError = true;
                                        }
                                    }
                                    // если текущее свойство линк, то установим обратное свойство - объектный скаляр
                                    else if (propInfoObj.Capacity == XPropCapacity.Link)
                                    {
                                        vPropValue = xobjValue.GetUpdatedPropValue(propInfoObj.ReverseProp.Name);
                                        // если обратное свойство (скаляр) установлено, то проверим, что оно ссылается на текущий объект
                                        if (vPropValue != null)
                                        {
                                            Debug.Assert(vPropValue is Guid);
                                            if ((vPropValue is DBNull) || ((Guid)vPropValue) != xobj.ObjectID)
                                            {
                                                bError = true;
                                            }
                                        }
                                        // обратное свойство неустановлено - установим его на текущий объект
                                        else
                                        {
                                            xobjValue.SetUpdatedPropValue(propInfoObj.ReverseProp.Name, xobj.ObjectID);
                                        }
                                    }
                                    if (bError)
                                    {
                                        throw new XInvalidXmlForestException(
                                                  String.Format("Не согласованы свойства объектов: {0}[ID='{1}'], свойство {2} и {3}[ID='{4}'], свойство {5}",
                                                                xobj.ObjectType,                                                // 0
                                                                xobj.ObjectID,                                                  // 1
                                                                sPropName,                                                      // 2
                                                                xobjValue.ObjectType,                                           // 3
                                                                xobjValue.ObjectID,                                             // 4
                                                                propInfoObj.ReverseProp.Name                                    // 5
                                                                ));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #5
0
        public XResponse Execute(MoveFolderRequest request, IXExecutionContext context)
        {
            XDbCommand          cmd;
            DomainObjectDataSet dataSet = new DomainObjectDataSet(context.Connection.MetadataManager.XModel);

            foreach (Guid oid in request.ObjectsID)
            {
                DomainObjectData xobj = dataSet.CreateStubLoaded("Folder", oid, -1);
                if (request.NewParent != Guid.Empty)
                {
                    // задана родительская папка
                    xobj.SetUpdatedPropValue("Parent", request.NewParent);
                    // родительская папка задана, однако, она может принадлежать другому клиенту и/или типу проектных затрат
                    cmd = context.Connection.CreateCommand(@"
						SELECT 
							CASE WHEN f1.Customer <> f2.Customer THEN f1.Customer ELSE cast(NULL as uniqueidentifier) END AS Customer, 
							CASE WHEN f1.ActivityType <> f2.ActivityType THEN f1.ActivityType ELSE cast(NULL as uniqueidentifier) END AS ActivityType
						FROM Folder f1, Folder f2
						WHERE f1.ObjectID = @NewParentID AND f2.ObjectID = @ObjectID 
							AND (f1.Customer <> f2.Customer OR f1.ActivityType <> f2.ActivityType)
						"                        );
                    cmd.Parameters.Add("NewParentID", DbType.Guid, ParameterDirection.Input, false, request.NewParent);
                    cmd.Parameters.Add("ObjectID", DbType.Guid, ParameterDirection.Input, false, oid);
                    using (IDataReader reader = cmd.ExecuteReader())
                    {
                        int nIndex;
                        if (reader.Read())
                        {
                            nIndex = reader.GetOrdinal("Customer");
                            if (!reader.IsDBNull(nIndex))
                            {
                                xobj.SetUpdatedPropValue("Customer", reader.GetGuid(nIndex));
                            }
                            nIndex = reader.GetOrdinal("ActivityType");
                            if (!reader.IsDBNull(nIndex))
                            {
                                xobj.SetUpdatedPropValue("ActivityType", reader.GetGuid(nIndex));
                            }
                        }
                    }
                    // Далее мы проверяем следующее:
                    //	каталог может быть подчинен папке любого типа, однако проект только проекту,
                    //	а пресейл и тендер вообще никому
                    cmd.CommandText = @"
						SELECT f1.Type AS FolderType, f2.Type AS ParentFolderType, 
							f1.LIndex, f1.RIndex,
							f2.LIndex AS ParentLIndex, f2.RIndex AS ParentRIndex
						FROM Folder f1, Folder f2
						WHERE f1.ObjectID = @ObjectID AND f2.ObjectID = @NewParentID
						"                        ;
                    // Примечание: используем созданную ранее команду с параметрами NewParentID и ObjectID
                    using (IDataReader reader = cmd.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            FolderTypeEnum folderType       = (FolderTypeEnum)reader.GetInt16(reader.GetOrdinal("FolderType"));
                            FolderTypeEnum parentFolderType = (FolderTypeEnum)reader.GetInt16(reader.GetOrdinal("ParentFolderType"));
                            // Если у папки не изменилась ссылка на организацию клиента, то проверим, что ее не переносят в одну из дочерних папок
                            if (!xobj.HasUpdatedProp("Customer"))
                            {
                                // Примечание: LIndex/RIndex будут пересчитываться в триггере
                                int nLIndex       = reader.GetInt32(reader.GetOrdinal("LIndex"));
                                int nRIndex       = reader.GetInt32(reader.GetOrdinal("RIndex"));
                                int nParentLIndex = reader.GetInt32(reader.GetOrdinal("ParentLIndex"));
                                int nParentRIndex = reader.GetInt32(reader.GetOrdinal("ParentRIndex"));
                                // Проверим, что новый родитель не является дочерним (рекурсивно) узлом переносимой папки
                                if (nParentLIndex >= nLIndex && nParentRIndex <= nRIndex)
                                {
                                    throw new XBusinessLogicException(FolderTypeEnumItem.GetItem(folderType).Description + " не может быть перенесен в подчиненный " + FolderTypeEnumItem.GetItem(parentFolderType).Description.ToLower());
                                }
                            }
                            if (folderType == FolderTypeEnum.Project)
                            {
                                if (parentFolderType != FolderTypeEnum.Project)
                                {
                                    throw new XBusinessLogicException("Проект не может быть перенесен в " + FolderTypeEnumItem.GetItem(parentFolderType).Description.ToLower());
                                }
                            }
                            else if (folderType == FolderTypeEnum.Tender || folderType == FolderTypeEnum.Presale)
                            {
                                throw new XBusinessLogicException("Тендер (тендерная активность) и пресейл (пресейл-активноть) не могут быть перенесены в папку");
                            }
                        }
                    }
                }
                else
                {
                    // перенос в корень
                    xobj.SetUpdatedPropValue("Parent", DBNull.Value);
                    // однако при этом мог измениться клиент или тип проектных затрат
                    if (request.NewActivityType != Guid.Empty)
                    {
                        // если изменился тип проектных затрат, то ссылка на клиента также должна быть задана (даже если он не изменился)
                        if (request.NewCustomer == Guid.Empty)
                        {
                            throw new ArgumentException("Если задана ссылка на тип проектных затрат, то должна быть задана ссылка на организацию-клиента");
                        }

                        // также нужно проверить, что выбранный типа проектных затрат поддерживает тип переносимой папки
                        cmd = context.Connection.CreateCommand(@"
							SELECT 1 FROM ActivityType 
							WHERE ObjectID = @ActivityTypeID AND FolderType & (SELECT [Type] FROM Folder WHERE ObjectID = @ObjectID) > 0
							"                            );
                        cmd.Parameters.Add("ActivityTypeID", DbType.Guid, ParameterDirection.Input, false, request.NewActivityType);
                        cmd.Parameters.Add("ObjectID", DbType.Guid, ParameterDirection.Input, false, oid);
                        if (cmd.ExecuteScalar() == null)
                        {
                            throw new XBusinessLogicException("Перенос папки невозможен. Выбранный тип проектных затрат не может содержать папку переносимого типа.");
                        }

                        xobj.SetUpdatedPropValue("ActivityType", request.NewActivityType);
                        xobj.SetUpdatedPropValue("Customer", request.NewCustomer);
                    }
                    else if (request.NewCustomer != Guid.Empty)
                    {
                        // Если выбрали организацию без изменения типа проектных затрат, то подразумевается, что он (ActivityTyoe) остается прежним,
                        // однако такое возможно только при переносе либо между организациями-клиентами, либо между организациями-владельцами.
                        cmd = context.Connection.CreateCommand(@"
							SELECT 1 FROM Organization c1, Organization c2 
							WHERE c1.ObjectID = (SELECT Customer FROM Folder WHERE ObjectID = @ObjectID)
								AND c2.ObjectID = @NewCustomerID AND c1.Home <> c2.Home
							"                            );
                        cmd.Parameters.Add("NewCustomerID", DbType.Guid, ParameterDirection.Input, false, request.NewCustomer);
                        cmd.Parameters.Add("ObjectID", DbType.Guid, ParameterDirection.Input, false, oid);
                        if (cmd.ExecuteScalar() != null)
                        {
                            throw new XBusinessLogicException("Перенос папки невозможен. Для переноса папок между разными типами проектных затрат следует выбрать узел, соответствующий требуемому типу проектных затрат.");
                        }

                        xobj.SetUpdatedPropValue("Customer", request.NewCustomer);
                    }
                    else
                    {
                        // Parent = Null, Customer = Null, ActivityType = Null - такого быть не может
                        throw new ArgumentException("При незаданной ссылке на родительскую папку должны быть заданы ссылки на Клиента и/или Тип проектных затрат");
                    }
                }

                XSecurityManager.Instance.DemandSaveObjectPrivilege(xobj);
            }
            XStorageGateway.Save(context, dataSet, Guid.NewGuid());

            // если все сохранилось хорошо, то отработали триггеры, изменяющие LIndex/RIndex, и возможно Customer.
            // Если у переносимой папки изменилась ссылка на тип проектных затрат ,
            // то необходимо изменить эту ссылку всем подчиненным папкам (если они есть)
            StringBuilder cmdBuilder = new StringBuilder();

            cmdBuilder.AppendFormat(
                @"UPDATE f
SET f.ActivityType = p.ActivityType
FROM Folder f
	JOIN Folder p ON f.LIndex > p.LIndex AND f.RIndex < p.RIndex AND f.Customer = p.Customer
WHERE p.ObjectID IN ("
                );
            cmd = context.Connection.CreateCommand();
            string sParamName;
            int    nParamIndex = 0;

            foreach (Guid oid in request.ObjectsID)
            {
                ++nParamIndex;
                sParamName = "ObjectID" + nParamIndex;
                cmd.Parameters.Add(sParamName, XPropType.vt_uuid, ParameterDirection.Input, false, oid);
                cmdBuilder.Append(context.Connection.GetParameterName(sParamName));
                cmdBuilder.Append(",");
            }
            // Отрежим последнюю запятую
            cmdBuilder.Length--;
            cmdBuilder.Append(")");
            cmd.CommandText = cmdBuilder.ToString();
            cmd.ExecuteNonQuery();

            // Если у переносимой папки были заданы направления, которые не соответствуют направлениям новой
            // родительской папки, то удалим эти направления
            if (request.NewParent != Guid.Empty)
            {
                cmdBuilder = new StringBuilder();


                cmd         = context.Connection.CreateCommand();
                nParamIndex = 0;
                foreach (Guid oid in request.ObjectsID)
                {
                    ++nParamIndex;
                    sParamName = "FolderID" + nParamIndex;
                    cmd.Parameters.Add(sParamName, XPropType.vt_uuid, ParameterDirection.Input, false, oid);
                    cmdBuilder.Append(context.Connection.GetParameterName(sParamName));
                    cmdBuilder.Append(",");
                }
                // Отрежим последнюю запятую
                cmdBuilder.Length--;
                cmd.CommandText = @"IF (EXISTS(
	                    SELECT top 1 fd.Direction
	                    FROM dbo.FolderDirection fd
	                    WHERE (fd.Direction not in 
	                        (
		                    SELECT Direction
		                    FROM dbo.FolderDirection
		                    WHERE  Folder = @ParentID) 
	                        AND fd.Folder IN ("     + cmdBuilder.ToString() + @"))  OR
                        EXISTS(
                            SELECT COUNT(*) 
                            FROM dbo.FolderDirection
                            WHERE Folder IN (" + cmdBuilder.ToString() + @")
                            HAVING COUNT(*)>1))) AND EXISTS( SELECT TOP 1 * FROM dbo.Folder WHERE ObjectID = @ParentID )
                                               
                        BEGIN
	                        DELETE fd
	                        FROM
	                        FolderDirection fd
	                        WHERE fd.Folder IN ("     + cmdBuilder.ToString() +
                                  @")
                        END"
                ;
                cmd.Parameters.Add("ParentID", DbType.Guid, ParameterDirection.Input, false, request.NewParent);
                cmd.ExecuteNonQuery();
            }

            return(new XResponse());
        }
예제 #6
0
        public override void Execute(XTriggerArgs args, Croc.XmlFramework.Core.IXExecutionContext context)
        {
            DomainObjectData xobj            = args.TriggeredObject;
            bool             bUpdatedState   = xobj.HasUpdatedProp("State");
            bool             bUpdateIsLocked = xobj.HasUpdatedProp("IsLocked");

            if (!bUpdatedState && !bUpdateIsLocked)
            {
                return;
            }
            // если здесь значит изменилось хотя бы одно из полей: Состояние (State), Дата блокирования списаний (BlockDate)
            // Теперь надо зачитать предыдущие значения из БД, но только тех свойств, которые обновляются
            preloadProps(xobj, bUpdatedState, bUpdateIsLocked, context);
            if (bUpdateIsLocked)
            {
                bool oldValue = (bool)xobj.GetLoadedPropValue("IsLocked");
                bool newValue = (bool)xobj.GetUpdatedPropValue("IsLocked");
                if (oldValue != newValue)
                {
                    // изменение признака допустимости списания
                    DomainObjectData xobjHistory = getFolderHistoryObject(args.DataSet, xobj);
                    xobjHistory.SetUpdatedPropValue("Event", newValue?FolderHistoryEvents.IsLockedSetToTrue:FolderHistoryEvents.IsLockedSetToFalse);
                }
            }

            if (bUpdatedState)
            {
                FolderStates stateOld = (FolderStates)xobj.GetLoadedPropValue("State");
                FolderStates stateNew = (FolderStates)xobj.GetUpdatedPropValue("State");
                if (stateOld != stateNew)
                {
                    // состояние изменилось
                    //	- проверим на запрещенные переходы
                    checkFolderStateChanging(stateOld, stateNew);
                    DomainObjectData    xobjHistory = getFolderHistoryObject(args.DataSet, xobj);
                    FolderHistoryEvents eventType;
                    if (stateNew == FolderStates.Closed)
                    {
                        eventType = FolderHistoryEvents.Closing;
                    }
                    else if (stateNew == FolderStates.Frozen)
                    {
                        eventType = FolderHistoryEvents.Frozing;
                    }
                    else if (stateNew == FolderStates.WaitingToClose)
                    {
                        eventType = FolderHistoryEvents.WaitingToClose;
                    }
                    else                        // if (stateNew == FolderStates.Open)
                    {
                        eventType = FolderHistoryEvents.Opening;
                    }
                    xobjHistory.SetUpdatedPropValue("Event", eventType);

                    // обработаем переход в состояние "Закрыто":
                    if (!xobj.IsNew && (stateNew == FolderStates.Closed || stateNew == FolderStates.WaitingToClose))
                    {
                        //	1. Проверим, что все инциденты (во всех вложенных папках) находятся в конечных состояниях
                        XDbCommand cmd = context.Connection.CreateCommand(@"
							SELECT 1 
							FROM Folder f_s WITH(NOLOCK)
								JOIN Folder f WITH(NOLOCK) ON f.LIndex >= f_s.LIndex AND f.RIndex <= f_s.RIndex AND f.Customer = f_s.Customer
									JOIN Incident i WITH(NOLOCK) ON f.ObjectID = i.Folder
										JOIN IncidentState i_st WITH(NOLOCK) ON i.State = i_st.ObjectID AND i_st.Category IN (1,2)	
							WHERE f_s.ObjectID = @ObjectID
							"                            );
                        cmd.Parameters.Add("ObjectID", DbType.Guid, ParameterDirection.Input, false, xobj.ObjectID);
                        if (cmd.ExecuteScalar() != null)
                        {
                            throw new XBusinessLogicException("Папка не может быть переведена в состояние \"Закрыто\" или \"Ожидание закрытия\", так как содержит незавершенные инциденты");
                        }
                    }

                    // добавим в датаграмму подчиненные папки с установленным состоянием новым состояние
                    // Обработка папок зависит от нового состояния
                    fillDataSetWithChildFoldersWithUpdatedState(context.Connection, args.DataSet, xobj.ObjectID, stateNew);
                }
            }
        }
예제 #7
0
        public override void Execute(XTriggerArgs args, IXExecutionContext context)
        {
            DomainObjectData xobjTask = args.TriggeredObject;

            // для нового объекта, если не задан планировщик, или
            // если изменилось запланированное время при обновлении установим планировщиком задания текущего сотрудника
            if (xobjTask.IsNew && xobjTask.GetUpdatedPropValue("Planner") == null || !xobjTask.IsNew && xobjTask.HasUpdatedProp("PlannedTime"))
            {
                xobjTask.SetUpdatedPropValue("Planner", ((ITUser)XSecurityManager.Instance.GetCurrentUser()).EmployeeID);
            }
        }
예제 #8
0
        public bool HasFolderPrivilege(ITUser user, FolderPrivileges privilege, DomainObjectData xobjFolder, XStorageConnection con)
        {
            // т.к. компонент может использоваться не только через методы XSecurityManager: GetObjectRights, HasSaveObjectRights, etc.
            if (user.IsUnrestricted)
            {
                return(true);
            }
            string sPrivilege = FolderPrivilegesItem.GetItem(privilege).Name;

            Guid         orgID;
            Guid         activityTypeID;
            FolderStates folderState;

            if (xobjFolder.IsNew)
            {
                if (!xobjFolder.HasUpdatedProp("Customer") || xobjFolder.GetUpdatedPropValue("Customer") == DBNull.Value)
                {
                    return(false);
                }
                orgID = (Guid)xobjFolder.GetUpdatedPropValue("Customer");

                if (!xobjFolder.HasUpdatedProp("ActivityType") || xobjFolder.GetUpdatedPropValue("ActivityType") == DBNull.Value)
                {
                    return(false);
                }
                activityTypeID = (Guid)xobjFolder.GetUpdatedPropValue("ActivityType");

                if (!xobjFolder.HasUpdatedProp("State") || xobjFolder.GetUpdatedPropValue("State") == DBNull.Value)
                {
                    return(false);
                }
                folderState = (FolderStates)xobjFolder.GetUpdatedPropValue("State");
            }
            else
            {
                if (!xobjFolder.HasLoadedProp("Customer") || !xobjFolder.HasLoadedProp("ActivityType") || !xobjFolder.HasLoadedProp("Parent") || !xobjFolder.HasLoadedProp("State"))
                {
                    xobjFolder.Load(con);
                }

                orgID          = (Guid)xobjFolder.GetLoadedPropValue("Customer");
                activityTypeID = (Guid)xobjFolder.GetLoadedPropValue("ActivityType");
                folderState    = (FolderStates)xobjFolder.GetLoadedPropValue("State");
            }

            // в закрытой папке ни у кого нет никаких привилегий
            if (folderState == FolderStates.Closed)
            {
                return(false);
            }

            if (user.ManageOrganization(orgID) || user.ManageActivityType(activityTypeID))
            {
                return(true);
            }

            if (!xobjFolder.IsNew)
            {
                // для объекта из БД, проверим определение привилегий для участника проекта заданной и вышестоящих папок
                if (m_folderPrivilegesDefinitionContainer.GetPrivileges(user, xobjFolder.ObjectID, con).Contains(sPrivilege))
                {
                    return(true);
                }
            }
            else
            {
                // Для нового объекта зачитывать привилегии из БД бессмысленно -
                // проверим ссылку на родителя, если она задана, то зачитаем его привилегии
                object vValue = xobjFolder.GetUpdatedPropValue("Parent");
                if (vValue is Guid)
                {
                    if (m_folderPrivilegesDefinitionContainer.GetPrivileges(user, (Guid)vValue, con).Contains(sPrivilege))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }