Example #1
0
 private void checkFolderStateChanging(FolderStates stateOld, FolderStates stateNew)
 {
     // TODO: требуется уточнение графа переходов состояний Папки
     if (stateOld == FolderStates.Frozen && stateNew != FolderStates.Open && stateNew != FolderStates.WaitingToClose)
     {
         throw new XBusinessLogicException("Папка из состояния \"" + FolderStatesItem.Frozen.Description + "\" может перейти только в состояния \"" + FolderStatesItem.Open.Description + "\" или \"" + FolderStatesItem.WaitingToClose.Description + "\"");
     }
     if (stateNew == FolderStates.Frozen && stateOld != FolderStates.Open && stateOld != FolderStates.WaitingToClose)
     {
         throw new XBusinessLogicException("В состояние \"" + FolderStatesItem.Frozen.Description + "\" папка может перейти только из состояний \"" + FolderStatesItem.Open.Description + "\" или \"" + FolderStatesItem.WaitingToClose.Description + "\"");
     }
 }
Example #2
0
        protected override void buildReport(Croc.XmlFramework.ReportService.Layouts.ReportLayoutData data)
        {
            Guid        folderID = (Guid)data.Params.GetParam("ID").Value;
            IDictionary f        = null;



            using (IDataReader r = data.DataProvider.GetDataReader("dsMain", data.CustomData))
            {
                if (r.Read())
                {
                    f = _GetDataFromDataRow(r);
                }
            }

            if (null == f)
            {
                // Проект не найден
                writeEmptyBody(data.RepGen, "Проект не найден");
                return;
            }
            data.RepGen.WriteLayoutMaster();
            data.RepGen.StartPageSequence();
            data.RepGen.StartPageBody();

            data.RepGen.Header("<fo:basic-link color=\"#ffffff\" external-destination=\"x-tree.aspx?METANAME=Main&amp;LocateFolderByID=" + folderID.ToString() + "\" target=\"_blank\" show-destination=\"new\">" + xmlEncode(f["Name"]) + "</fo:basic-link>");
            data.RepGen.TStart(false, "CELL_CLASS", false);
            data.RepGen.TAddColumn(null, align.ALIGN_LEFT, valign.VALIGN_TOP, "30%");
            data.RepGen.TAddColumn(null, align.ALIGN_LEFT, valign.VALIGN_TOP, "70%");

            // основные свойства проекта
            data.RepGen.TRStart();
            data.RepGen.TRAddCell("Клиент", null, 1, 1, "BOLD");
            data.RepGen.TRAddCell(xmlEncode(f["CustomerName"]), null);
            data.RepGen.TREnd();
            data.RepGen.TRStart();
            data.RepGen.TRAddCell("Название", null, 1, 1, "BOLD");
            data.RepGen.TRAddCell(_GetFolderAnchor(f["Name"], (Guid)f["ObjectID"], false), null);
            data.RepGen.TREnd();
            if (null != f["Description"])
            {
                data.RepGen.TRStart();
                data.RepGen.TRAddCell("Описание", null, 1, 1, "BOLD");
                data.RepGen.TRAddCell(_LongText(f["Description"]), null);
                data.RepGen.TREnd();
            }
            if (null != f["FirstDate"])
            {
                data.RepGen.TRStart();
                data.RepGen.TRAddCell("Дата начала", null, 1, 1, "BOLD");
                data.RepGen.TRAddCell(xmlEncode(((DateTime)f["FirstDate"]).ToLongDateString()) + " (" + getUserMailAnchor(f["FirstName"] + ", " + f["FirstDep"], f["FirstMail"], (Guid)f["FirstID"], folderID) + ")", null);
                data.RepGen.TREnd();
            }
            if (null != f["LastDate"])
            {
                data.RepGen.TRStart();
                data.RepGen.TRAddCell("Дата последней активности", null, 1, 1, "BOLD");
                data.RepGen.TRAddCell(xmlEncode(((DateTime)f["LastDate"]).ToLongDateString()) + " (" + getUserMailAnchor(f["LastName"] + ", " + f["LastDep"], f["LastMail"], (Guid)f["LastID"], folderID) + ")", null);
                data.RepGen.TREnd();
            }

            FolderStates folderState = (FolderStates)f["State"];

            data.RepGen.TRStart();
            data.RepGen.TRAddCell("Состояние", null, 1, 1, "BOLD");
            data.RepGen.TRAddCell(xmlEncode(FolderStatesItem.GetItem(folderState).Description), null);
            data.RepGen.TREnd();

            FolderTypeEnum folderType = (FolderTypeEnum)f["Type"];

            data.RepGen.TRStart();
            data.RepGen.TRAddCell("Тип", null, 1, 1, "BOLD");
            data.RepGen.TRAddCell(xmlEncode(FolderTypeEnumItem.GetItem(folderType).Description), null);
            data.RepGen.TREnd();

            data.RepGen.TRStart();
            data.RepGen.TRAddCell("Тип проектной активности", null, 1, 1, "BOLD");
            data.RepGen.TRAddCell(xmlEncode(f["ActivityTypeName"]), null);
            data.RepGen.TREnd();

            // Код проекта:
            //	- только для активности;
            //	- м.б. не задан: в этом случае показываем что данных нет
            if (folderType != FolderTypeEnum.Directory)
            {
                data.RepGen.TRStart();
                data.RepGen.TRAddCell("Код", null, 1, 1, "BOLD");
                if (null != f["ExternalID"])
                {
                    data.RepGen.TRAddCell(xmlEncode(f["ExternalID"]), null);
                }
                else
                {
                    data.RepGen.TRAddCell(xmlEncode("(не задан)"), null);
                }
                data.RepGen.TREnd();
            }

            if (null != f["DefaultIncidentTypeName"])
            {
                data.RepGen.TRStart();
                data.RepGen.TRAddCell("Тип инцидента по умолчанию", null, 1, 1, "BOLD");
                data.RepGen.TRAddCell(xmlEncode(f["DefaultIncidentTypeName"]), null);
                data.RepGen.TREnd();
            }
            if ("0" != f["IsLocked"].ToString())
            {
                data.RepGen.TRStart();
                data.RepGen.TRAddCell("", null, 1, 1, "BOLD");
                data.RepGen.TRAddCell("Списания на папку заблокированы", null, 1, 1, "BOLD-RED");
                data.RepGen.TREnd();
            }
            int nTotalSpent = (int)f["SummarySpent"];

            if (0 != nTotalSpent)
            {
                data.RepGen.TRStart();
                data.RepGen.TRAddCell("Суммарные трудозатраты", null, 1, 1, "BOLD");
                data.RepGen.TRAddCell(
                    string.Format("<fo:basic-link external-destination=\"x-get-report.aspx?name=r-ProjectIncidentsAndExpenses.xml&amp;Folder={1}\">{0}</fo:basic-link>", xmlEncode(_FormatTimeStringAtServer(nTotalSpent, int.MaxValue)), folderID)
                    , null);
                data.RepGen.TREnd();
            }

            // Направления
            StringBuilder directions = new StringBuilder();

            using (IDataReader r = data.DataProvider.GetDataReader("dsDirections", data.CustomData))
            {
                while (r.Read())
                {
                    directions.AppendFormat("<fo:block>{0}</fo:block>", xmlEncode(r.GetString(0)));
                }
            }
            if (directions.Length != 0)
            {
                // Шапка
                data.RepGen.TRStart();
                data.RepGen.TRAddCell("Направления", null, 1, 1, "BOLD");
                data.RepGen.TRAddCell(directions.ToString(), null);
                data.RepGen.TREnd();
            }

            data.RepGen.TEnd();

            // проектная команда
            insertAdditionalProjectReports(data, folderID);

            // история
            insertFolderHistory(data, folderID);

            // инциденты
            insertWorkStaff(data, folderID);

            data.RepGen.EndPageBody();
            data.RepGen.EndPageSequence();
        }
Example #3
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);
                }
            }
        }
Example #4
0
        private void fillDataSetWithChildFoldersWithUpdatedState(XStorageConnection con, DomainObjectDataSet dataSet, Guid objectID, FolderStates folderState)
        {
            // зачитаем идентификаторы всех подчиненных папок, состояние которых отличается от требуемого
            XDbCommand cmd = con.CreateCommand(@"
				SELECT f.ObjectID
				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
				WHERE f_s.ObjectID = @ObjectID AND f.State <> @TargetState
				"                );

            // закрытие закрывает все вложенные папки без учета их состояния:
            // if (folderState == FolderStates.Closed) - Nothing to do

            // замораживание замораживает открытые и ожидающие закрытия
            if (folderState == FolderStates.Frozen)
            {
                cmd.CommandText = cmd.CommandText + " AND f.State IN (" + FolderStatesItem.Open.IntValue + "," + FolderStatesItem.WaitingToClose.IntValue + ")";
            }
            // перевод в "ожидание закрытие" применим только для открытых (т.е. замороженные и закрытые не трогаются)
            //else if (folderState == FolderStates.WaitingToClose)
            //cmd.CommandText = cmd.CommandText + " AND f.State = " + FolderStatesItem.Open.IntValue;

            cmd.Parameters.Add("ObjectID", DbType.Guid, ParameterDirection.Input, false, objectID);
            cmd.Parameters.Add("TargetState", DbType.Int16, ParameterDirection.Input, false, (Int16)folderState);
            using (IDataReader reader = cmd.ExecuteReader())
            {
                DomainObjectData xobjSubFolder;
                while (reader.Read())
                {
                    xobjSubFolder = dataSet.GetLoadedStub("Folder", reader.GetGuid(0));
                    xobjSubFolder.SetUpdatedPropValue("State", folderState);
                }
            }
        }