/// <summary> /// Метод запуска операции на выполнение, «входная» точка операции /// ПЕРЕГРУЖЕННЫЙ, СТРОГО ТИПИЗИРОВАННЫЙ МЕТОД /// ВЫЗЫВАЕТСЯ ЯДРОМ АВТОМАТИЧЕСКИ /// </summary> /// <param name="request">Запрос на выполнение операции</param> /// <param name="context">Контекст выполнения операции</param> /// <returns>Результат выполнения</returns> public virtual XResponse Execute(SaveObjectInternalRequest request, IXExecutionContext context) { // #1: Проверка прав // Примечание: делаем это здесь, а не в гварде, ради человеческой диагностики XSecurityManager sec_man = XSecurityManager.Instance; IEnumerator enumerator = request.DataSet.GetModifiedObjectsEnumerator(false); DomainObjectData xobj; while (enumerator.MoveNext()) { xobj = (DomainObjectData)enumerator.Current; if (xobj.ToDelete) { sec_man.DemandDeleteObjectPrivilege(xobj); } else { sec_man.DemandSaveObjectPrivilege(xobj); } } // #2: Запись данных XStorageGateway.Save(context, request.DataSet, request.TransactionID); // #3: Вызовем post-call-процедуры (если таковые определены) //executePostCalls(request.PostCalls, context); // Специального результата операция не возвращает return(new XResponse()); }
/// <summary> /// ћетод запуска операции на выполнение, Ђвходна¤ї точка операции /// ѕ≈–≈√–”∆≈ЌЌџ…, —“–ќ√ќ “»ѕ»«»–ќ¬јЌЌџ… ћ≈“ќƒ /// ¬џ«џ¬ј≈“—я яƒ–ќћ ј¬“ќћј“»„≈— » /// </summary> /// <param name="request">«апрос на выполнение операции</param> /// <param name="context"> онтекст выполнени¤ операции</param> /// <returns>–езультат выполнени¤</returns> public virtual XResponse Execute(SaveObjectInternalRequest request, IXExecutionContext context) { ITUser user = (ITUser)XSecurityManager.Instance.GetCurrentUser(); if (!user.IsServiceAccount) { string signature = getSignatureText(user); // если текущий пользователь не сервисный аккаунт, то можно добавл¤ть подписи к текстовым пол¤м // измен¤ем модифицируемые объекты IEnumerator enumerator = request.DataSet.GetModifiedObjectsEnumerator(true); while (enumerator.MoveNext()) { DomainObjectData xobj = (DomainObjectData)enumerator.Current; modifyObjectProps(xobj, signature); } } // вызываем стандартную команду SaveObject request.Name = "SaveObject"; return(context.ExecCommand(request, true)); }
public XResponse Execute(SaveObjectInternalRequest request, IXExecutionContext context) { ITUser user = (ITUser)XSecurityManager.Instance.GetCurrentUser(); ArrayList aObjects = request.DataSet.GetModifiedObjectsByType("TimeLoss", true); foreach (DomainObjectData xobj in aObjects) { if (!xobj.HasUpdatedProp("Worker") && xobj.IsNew) { xobj.SetUpdatedPropValue("Worker", user.EmployeeID); } // получим папку, проверим у папки отсутствие флага IsLocked object vValue = xobj.GetPropValue("Folder", DomainObjectDataSetWalkingStrategies.UseUpdatedPropsThanLoadedProps); DomainObjectData xobjFolder = null; if (vValue is Guid) { xobjFolder = xobj.Context.Get(context.Connection, xobj, "Folder", DomainObjectDataSetWalkingStrategies.UseUpdatedPropsThanLoadedProps, true); // проверим состояние папки. если она закрыта или в ожидании закрытия, то запретим списание if ((FolderStates)xobjFolder.GetLoadedPropValue("State") == FolderStates.Closed || (FolderStates)xobjFolder.GetLoadedPropValue("State") == FolderStates.WaitingToClose || (FolderStates)xobjFolder.GetLoadedPropValue("State") == FolderStates.Frozen) { throw new XSecurityException("Списания в папку в состоянии \"Закрыто\" или \"Ожидание закрытия\" запрещены. По вопросам списаний обращайтесь к менеджеру."); } // проверим наличие у папки специального аттрибута, запрещающего списание if ((bool)xobjFolder.GetPropValue("IsLocked", DomainObjectDataSetWalkingStrategies.UseUpdatedPropsThanLoadedProps)) { throw new XSecurityException("<b>Списания в данную папку запрещены.</b><br/>По вопросам списаний обращайтесь к менеджеру."); } FolderPrivilegeManager manager = (XSecurityManager.Instance.SecurityProvider as SecurityProvider).FolderPrivilegeManager; // у пользователя должны быть права на списание в данной папке if (!manager.HasFolderPrivilege(user, FolderPrivileges.SpentTimeByProject, xobjFolder, context.Connection)) { throw new XSecurityException("<b>Пользователь должен обладать в проекте привилегией \"Списание времение на проект\".</b><br/>По вопросам списаний обращайтесь к менеджеру."); } // если у пользователя нет привилегии «Разрешение списания на папку с неоднозначным определением направления» // проверим - является ли данная папка папкой с неоднозначным определением направления if (!manager.HasFolderPrivilege(user, FolderPrivileges.TimeLossOnUnspecifiedDirection, xobjFolder, context.Connection)) { using (XDbCommand c = context.Connection.CreateCommand()) { c.CommandType = CommandType.Text; c.CommandText = @" IF ( SELECT t.AccountRelated FROM dbo.ActivityType t WITH(NOLOCK) JOIN dbo.Folder fT WITH(NOLOCK) ON fT.ActivityType = t.ObjectID WHERE fT.ObjectID = @FolderID ) = 0 SELECT 1 ELSE SELECT TOP 1 t.DirsQnt FROM ( SELECT fU.ObjectID, fU.LRLevel, ( SELECT COUNT(*) FROM dbo.FolderDirection fd WITH(NOLOCK) WHERE fd.Folder = fU.ObjectID ) AS DirsQnt FROM dbo.Folder fT WITH(NOLOCK) JOIN dbo.Folder fU WITH(NOLOCK) ON fU.Customer = fT.Customer AND fU.LIndex <= fT.LIndex AND fU.RIndex >= fT.RIndex WHERE fT.ObjectID = @FolderID ) t WHERE DirsQnt > 0 ORDER BY LRLevel DESC "; c.Parameters.Add("FolderID", DbType.Guid, ParameterDirection.Input, false, vValue); object oResult = c.ExecuteScalar(); string sReport = null; if (null == oResult || DBNull.Value == oResult) { sReport = "для которой не определено ни одного направления"; } else if (1 != (int)oResult) { sReport = "для которой определено более одного направления"; } if (null != sReport) { throw new XSecurityException( "<b>Списания в данную папку запрещены.</b><br/>" + "У Вас нет прав списывать в папку, " + sReport + ". " + "По вопросам списаний <b>обращайтесь к менеджеру</b>."); } } } } // если в объекте заданы "виртуальные" свойства if (xobj.HasUpdatedProp("LossFixedStart") && xobj.GetUpdatedPropValue("LossFixedStart") is DateTime && xobj.HasUpdatedProp("LossFixedEnd") && xobj.GetUpdatedPropValue("LossFixedEnd") is DateTime) { if (!xobj.IsNew) { throw new ApplicationException("Задание диапазона допустимо только при создании объекта \"Списание времени\""); } // получим даты начала и окончания периода DateTime dtPeriodStart = (DateTime)xobj.GetUpdatedPropValue("LossFixedStart"); DateTime dtPeriodEnd = (DateTime)xobj.GetUpdatedPropValue("LossFixedEnd"); if (dtPeriodStart > dtPeriodEnd) { DateTime dtTemp = dtPeriodEnd; dtPeriodEnd = dtPeriodStart; dtPeriodStart = dtTemp; } Guid employeeID = (Guid)xobj.GetUpdatedPropValue("Worker"); // проверим, что в данном периоде отсутствуют списания XDbCommand cmd = context.Connection.CreateCommand(""); cmd.CommandText = @"SELECT DISTINCT CONVERT(varchar, x.SpentDate, 104) FROM ( SELECT ts.RegDate AS SpentDate FROM TimeSpent ts JOIN Task t ON ts.Task = t.ObjectID WHERE t.Worker = @EmployeeID AND ts.RegDate >= @dtPeriodStart AND ts.RegDate < @dtPeriodEnd UNION SELECT ts.LossFixed AS SpentDate FROM TimeLoss ts WHERE ts.Worker = @EmployeeID AND ts.LossFixed >= @dtPeriodStart AND ts.LossFixed < @dtPeriodEnd ) x" ; cmd.Parameters.Add("EmployeeID", DbType.Guid, ParameterDirection.Input, false, employeeID); cmd.Parameters.Add("dtPeriodStart", DbType.Date, ParameterDirection.Input, false, dtPeriodStart); // AddDays(1) - т.к. в условии запроса знак "меньше" cmd.Parameters.Add("dtPeriodEnd", DbType.Date, ParameterDirection.Input, false, dtPeriodEnd.AddDays(1)); using (IDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { StringBuilder bld = new StringBuilder(); do { if (bld.Length > 0) { bld.Append(", "); } bld.Append(reader.GetString(0)); } while(reader.Read()); throw new XBusinessLogicException( String.Format("У вас уже имеются списания на следующие даты в заданном периоде ({0},{1}): {2}", dtPeriodStart.ToShortDateString(), dtPeriodEnd.ToShortDateString(), bld.ToString()) ); } } // Получаем "набор пар" дата - норма сотрудника на дату Dictionary <DateTime, int> dictDateRates = new Dictionary <DateTime, int>(); dictDateRates = GetDayRates(context.Connection, dtPeriodStart, dtPeriodEnd, employeeID); // пойдем по всем дням периода (dtPeriodEnd, dtPeriodStart) // и для каждой даты создадим новый объект Списание времени с количеством времени равном рабочему дню // При этом, будем игнорировать даты, попадающие на выходные/праздники TimeSpan period = (dtPeriodEnd - dtPeriodStart); for (int nOffSet = 0; nOffSet <= period.TotalDays; ++nOffSet) { int nRate = 0; DateTime dtDate = dtPeriodStart.AddDays(nOffSet); // Если удалось получить норму сотрудника на соотв. дату, то создадим объект if (dictDateRates.TryGetValue(dtDate, out nRate)) { // Если полученная норма больше 0, тогда создадим списание if (nRate > 0) { DomainObjectData xobjNew = createTimeLossObject(request.DataSet, xobj, user); xobjNew.SetUpdatedPropValue("LossFixed", dtDate); // списание длиной в количество минут в рабочем дне xobjNew.SetUpdatedPropValue("LostTime", nRate); } } } // исходный объект надо удалить request.DataSet.Remove(xobj); } } XSecurityManager sec_man = XSecurityManager.Instance; IEnumerator enumerator = request.DataSet.GetModifiedObjectsEnumerator(false); DomainObjectData xobject; while (enumerator.MoveNext()) { xobject = (DomainObjectData)enumerator.Current; if (xobject.ToDelete) { sec_man.DemandDeleteObjectPrivilege(xobject); } else { sec_man.DemandSaveObjectPrivilege(xobject); } } // #1: Запись данных XStorageGateway.Save(context, request.DataSet, request.TransactionID); // Специального результата операция не возвращает return(new XResponse()); }