/// <summary> /// UserId, Start, Finish, Type, ObjectId, ObjectTypeId, ObjectName, Duration, PercentCompleted, /// PriorityId, StateId, FinishDate, Highlight, IsNewMessage, IsOverdue, AssignmentId, AssignmentName /// </summary> /// <param name="userId"></param> /// <param name="curDate"></param> /// <param name="fromDate"></param> /// <param name="toDate"></param> /// <param name="objectTypes"></param> /// <param name="highlightedItems"></param> /// <param name="getPastTime"></param> /// <param name="getOffTime"></param> /// <param name="mergeBreaks"></param> /// <param name="strictBorder"></param> /// <returns></returns> public static DataTable GetResourceUtilization( int userId, DateTime curDate, DateTime fromDate, DateTime toDate, ArrayList objectTypes, /*ArrayList arr = new ArrayList();arr.Add(ObjectTypes.Task);arr.Add(ObjectTypes.ToDo);arr.Add(ObjectTypes.CalendarEntry);arr.Add(ObjectTypes.Document);arr.Add(ObjectTypes.Issue);*/ List<KeyValuePair<int, int>> highlightedItems, /* key:ObjectId, value:ObjectTypeId */ bool getPastTime, bool getOffTime, bool mergeBreaks, bool strictBorder) { /* �������� �������: * 1. �������� ������ � ������������, ������ ���������� ����� ����� �������� ������� � ������ ��������� * (��� �������� ����� ��������� ������� ������ �� ������ �������� ��� � �� ����� ���������� ���) * 2. ������ ����������� ���������� TimeType.Past (��������� �����) � TimeType.Off. * �.�. �� ��������� �� ����� - ���������. * 3. �� ��������� �������� ��������� ���������� � ������� ������� ����� (TimeType.Free) * 4. ��������� ���������� � ��������� ������� � �������������� �������. * 5. ������ ��� ����������� �� ������, ��������� ������ ���������� TimeType.CalendarEntry * � ������������ ��������� ��������������� ���� � �������������� ������� * 6. ������ WorkPinnedUp, ��������� ������ ���������� TimeType�.Sticked * � ������������ ��������� ��������������� ���� � �������������� ������� * 7. ������ ������, ���������, ��������� (��������������� � ������ ��������) � * ������������ ���� � ��� � ������� �� ���������� TimeType.WorkUrgent - * TimeTime.WorkLow (� ����������� �� ����������) � ������������ ��������� * ��������������� ���� � �������������� �������. * * �� ������ ����� ������� � ������� �������. * ����� ��� ������������� ����� ����� ������������� �������� �� ����������� * * - �������� "mergeBreaks" ����������, ���� �� ���������� ����������� ��������� ������ * - �������� "strictBorder" ����������, ��� ����� ��������� � �������������� �������, ���� * ������ �������� �� ������� ���������� ���������. ���� true, �� ��������� ����� ������ * ����� �������� �� �������� fromDate � toDate. ���� false, �� ����� ������������ * �������� ��������� ����� ������ */ // round dates to minutes fromDate = fromDate.Date.AddHours(fromDate.Hour).AddMinutes(fromDate.Minute); toDate = toDate.Date.AddHours(toDate.Hour).AddMinutes(toDate.Minute); curDate = curDate.Date.AddHours(curDate.Hour).AddMinutes(curDate.Minute); if (fromDate >= toDate) throw new ArgumentException("fromDate, toDate"); DataTable resultTable; // Resulting table int calendarId = -1; // Calendar Id int userCalendarId = -1; // UserCalendar Id List<TimeType> timeList; // Main array. It contains information about // every minute allocation from the 00:00 of current date // to 24:00 of the toDate int freeTimeCounter; // Counter of free time DateTime curCalDate; // Current Date in Calendar timezone DateTime fromCalDate; // FromDate in Calendar timezone DateTime toCalDate; // ToDate in Calendar timezone int curMinute; // Total minutes elapsed from 00:00 of current day int fromMinute; // Total minutes elapsed from 00:00 of current day to fromDate (curDate < fromdate) // or total minutes elapsed from 00:00 of current day (fromdate > curDate) int toMinute; // Total minutes elapsed from 00:00 of current day to toDate TimeSpan ts; // Auxiliary variable CalendarHelper calendarHelper; // Auxiliary class int intervalDuration; // total minutes from 00:00 of current date to 24:00 of the toDate bool getTasks = objectTypes.Contains(ObjectTypes.Task); bool getTodo = objectTypes.Contains(ObjectTypes.ToDo); bool getIncidents = objectTypes.Contains(ObjectTypes.Issue); bool getDocuments = objectTypes.Contains(ObjectTypes.Document); DataTable objectTable; #region PreStep: initial actions // Resulting DataTable definition resultTable = new DataTable(); resultTable.Locale = CultureInfo.InvariantCulture; resultTable.Columns.Add("UserId", typeof(int)); resultTable.Columns.Add("Start", typeof(DateTime)); resultTable.Columns.Add("Finish", typeof(DateTime)); resultTable.Columns.Add("Type", typeof(TimeType)); resultTable.Columns.Add("ObjectId", typeof(int)); resultTable.Columns.Add("ObjectTypeId", typeof(int)); resultTable.Columns.Add("ObjectName", typeof(string)); resultTable.Columns.Add("Duration", typeof(int)); resultTable.Columns.Add("PercentCompleted", typeof(int)); resultTable.Columns.Add("PriorityId", typeof(int)); resultTable.Columns.Add("StateId", typeof(int)); resultTable.Columns.Add("FinishDate", typeof(DateTime)); resultTable.Columns.Add("Highlight", typeof(bool)); resultTable.Columns.Add("IsNewMessage", typeof(bool)); // for incidents resultTable.Columns.Add("IsOverdue", typeof(bool)); resultTable.Columns.Add("AssignmentId", typeof(string)); resultTable.Columns.Add("AssignmentName", typeof(string)); resultTable.Columns.Add("ProjectTitle", typeof(string)); DateTime fromUtcDate = Security.CurrentUser.CurrentTimeZone.ToUniversalTime(fromDate); DateTime toUtcDate = Security.CurrentUser.CurrentTimeZone.ToUniversalTime(toDate); DateTime curUtcDate = Security.CurrentUser.CurrentTimeZone.ToUniversalTime(curDate); // if we have past time if (fromDate < curDate) { if (curDate < toDate) { if (getPastTime) { AddRow(resultTable, userId, fromDate, curDate, TimeType.Past); } } else // all time is past { if (getPastTime) { AddRow(resultTable, userId, fromDate, toDate, TimeType.Past); } return resultTable; } } // Get User Calendar info using (IDataReader reader = GetUserCalendarByUser(userId)) { if (reader.Read()) { calendarId = (int)reader["CalendarId"]; userCalendarId = (int)reader["UserCalendarId"]; } } // Check user calendar existance if (calendarId < 0) // if calendar doesn't exist { if (getOffTime) { if (strictBorder) { AddRow(resultTable, userId, (fromDate > curDate) ? fromDate : curDate, toDate, TimeType.Off); } else { AddRow(resultTable, userId, curDate, toDate.AddDays(1), // no border in graph TimeType.Off); } } return resultTable; } UserLight ul = UserLight.Load(userId); int timeZoneId = ul.TimeZoneId; // Calendar TimeZone McTimeZone timeZoneInfo = McTimeZone.Load(timeZoneId); if (timeZoneInfo == null) throw new ArgumentException("Unknown TimeZoneId = '" + timeZoneId.ToString() + "'."); TimeZone calendarTimeZone = new Mediachase.Ibn.Data.UserTimeZone("Calendar Time Zone", timeZoneInfo.Bias, timeZoneInfo.DaylightBias, timeZoneInfo.DaylightMonth, timeZoneInfo.DaylightDayOfWeek, timeZoneInfo.DaylightWeek, timeZoneInfo.DaylightHour, timeZoneInfo.StandardBias, timeZoneInfo.StandardMonth, timeZoneInfo.StandardDayOfWeek, timeZoneInfo.StandardWeek, timeZoneInfo.StandardHour); curCalDate = calendarTimeZone.ToLocalTime(curUtcDate); fromCalDate = calendarTimeZone.ToLocalTime(fromUtcDate); toCalDate = calendarTimeZone.ToLocalTime(toUtcDate); curMinute = curCalDate.Hour * 60 + curCalDate.Minute; if (fromDate < curDate) { fromMinute = curMinute; } else { ts = fromCalDate.Subtract(curCalDate.Date); fromMinute = (int)ts.TotalMinutes; } ts = toCalDate.Subtract(curCalDate.Date); toMinute = (int)ts.TotalMinutes; #endregion #region Step 1: Array creation // leveling to the start of date if (toCalDate == toCalDate.Date) ts = toCalDate.Date.Subtract(curCalDate.Date); else ts = toCalDate.Date.AddDays(1).Subtract(curCalDate.Date); intervalDuration = (int)ts.TotalMinutes; if (intervalDuration == 0) { return resultTable; } // Calendar Helper calendarHelper = new CalendarHelper(curCalDate.Date, calendarTimeZone); calendarHelper.FromCalDate = fromCalDate; calendarHelper.ToCalDate = toCalDate; calendarHelper.IntervalDuration = intervalDuration; calendarHelper.HighlightedItems = highlightedItems; // array creation timeList = new List<TimeType>(intervalDuration); #endregion #region Step 2: Default array allocation for (int i = 0; i < intervalDuration; i++) { if (i < curMinute) timeList.Add(TimeType.Past); else timeList.Add(TimeType.Off); } #endregion #region Step 3: Data from calendar ProcessCalendarInfo(timeList, curCalDate, toCalDate, calendarId, userCalendarId, toMinute); #endregion #region Step 4: Add information about time off to resulting table TimeType curType = TimeType.Past; int startMinute = 0; int endMinute; freeTimeCounter = 0; for (int i = 0; i < intervalDuration; i++) { if (timeList[i] == TimeType.Free) freeTimeCounter++; if (timeList[i] != curType) // if type is changed { endMinute = i; if (getOffTime && curType == TimeType.Off && startMinute < toMinute && endMinute > fromMinute) { if (strictBorder) { if (startMinute < fromMinute) startMinute = fromMinute; if (endMinute > toMinute) endMinute = toMinute; } if (startMinute < endMinute) { AddRow(resultTable, userId, calendarHelper.GetUserDate(startMinute), calendarHelper.GetUserDate(endMinute), TimeType.Off); } } startMinute = i; curType = timeList[i]; continue; } } // Last interval if (getOffTime && curType == TimeType.Off && startMinute < toMinute) { endMinute = intervalDuration + 24*60; // hide border if (strictBorder) { if (startMinute < fromMinute) startMinute = fromMinute; if (endMinute > toMinute) endMinute = toMinute; } if (startMinute < endMinute) { AddRow(resultTable, userId, calendarHelper.GetUserDate(startMinute), calendarHelper.GetUserDate(endMinute), TimeType.Off); } } if (freeTimeCounter == 0) return resultTable; //---------------------- #endregion #region Step 5: Process Events if (objectTypes.Contains(ObjectTypes.CalendarEntry)) { int entryType = (int)CalendarView.CalendarFilter.Appointment | (int)CalendarView.CalendarFilter.Event | (int)CalendarView.CalendarFilter.Meeting; DataTable events = CalendarView.GetListCalendarEntriesByUser(curDate.Date, (toDate == toDate.Date) ? toDate : toDate.Date.AddDays(1), true, true, false, entryType, userId); // ID, Type, Title, Description, StartDate, FinishDate, ShowStartDate, ShowFinishDate, StateId foreach (DataRow row in events.Rows) { if ((int)row["StateId"] == (int)ObjectStates.Completed || (int)row["StateId"] == (int)ObjectStates.Suspended) continue; DateTime objectStartDate = calendarHelper.GetCalendarDate((DateTime)row["StartDate"]); DateTime objectFinishDate = calendarHelper.GetCalendarDate((DateTime)row["FinishDate"]); if (objectStartDate >= ((toCalDate.Date == toCalDate) ? toCalDate : toCalDate.Date.AddDays(1)) || objectFinishDate <= curCalDate.Date) continue; // we don't need objects which have dates outside our period // round dates to the diapason boundaries if (objectStartDate < curCalDate.Date) objectStartDate = curCalDate.Date; if (objectFinishDate > ((toCalDate.Date == toCalDate) ? toCalDate : toCalDate.Date.AddDays(1))) objectFinishDate = (toCalDate.Date == toCalDate) ? toCalDate : toCalDate.Date.AddDays(1); // Get number of minutes between objectStartDate/objectFinishDate and curCalDate.Date ts = objectStartDate.Subtract(curCalDate.Date); startMinute = (int)ts.TotalMinutes; ts = objectFinishDate.Subtract(curCalDate.Date); endMinute = (int)ts.TotalMinutes; // feel the array for (int i = startMinute; i < endMinute; i++) { if (timeList[i] != TimeType.Past) // we shouldn't change the past time timeList[i] = TimeType.CalendarEntry; } // Add info to result table if (startMinute < toMinute && endMinute > fromMinute) { int duration = endMinute - startMinute; if (strictBorder) { if (startMinute < fromMinute) startMinute = fromMinute; if (endMinute > toMinute) endMinute = toMinute; } else if (startMinute < curMinute) { startMinute = curMinute; } if (startMinute < endMinute) { AddRow(resultTable, highlightedItems, userId, calendarHelper.GetUserDate(startMinute), calendarHelper.GetUserDate(endMinute), TimeType.CalendarEntry, (int)row["ID"], (int)ObjectTypes.CalendarEntry, row["Title"].ToString(), duration, 0, (int)row["PriorityId"], (int)row["StateId"], (DateTime)row["FinishDate"], null, null, String.Empty, false, false, false); } } } freeTimeCounter = 0; for (int i = 0; i < intervalDuration; i++) { if (timeList[i] == TimeType.Free) freeTimeCounter++; } if (freeTimeCounter == 0) return resultTable; } #endregion #region Step 6: Process WorkPinnedUp objectTable = DBCalendar.GetListStickedObjectsUtc(userId, getTasks, getTodo, getIncidents, getDocuments); ProcessObjectTable(timeList, curCalDate, userId, objectTable, resultTable, freeTimeCounter, fromMinute, toMinute, calendarHelper, mergeBreaks, strictBorder, true); #endregion #region Step 7: Process Tasks, Todo, Incidents objectTable = DBCalendar.GetListObjectsInPriorityOrderUtc(userId, curUtcDate, toUtcDate, getTasks, getTodo, getIncidents, getDocuments); ProcessObjectTable(timeList, curCalDate, userId, objectTable, resultTable, freeTimeCounter, fromMinute, toMinute, calendarHelper, mergeBreaks, strictBorder, false); #endregion return resultTable; }
private static void ProcessObjectTable( List<TimeType> timeList, DateTime curCalDate, int userId, DataTable objectTable, DataTable resultTable, int freeTimeCounter, int fromMinute, int toMinute, CalendarHelper calendarHelper, bool mergeBreaks, bool strictBorder, bool sticked) { // we should extend to left the first work item bool extendToLeft = (mergeBreaks && curCalDate.Date < calendarHelper.FromCalDate.Date) ? true : false; foreach (DataRow row in objectTable.Rows) { // ObjectId, ObjectTypeId, ObjectName, PriorityId, StartDate (UTC), FinishDate (UTC), // CreationDate (UTC), TaskTime, PercentCompleted, TaskTimeLeft, FinishDateLeft (UTC) int duration = (int)row["TaskTimeLeft"]; int originalDuration = duration; int objectId = (int)row["ObjectId"]; int objectTypeId = (int)row["ObjectTypeId"]; int taskTimeLeft = (int)row["TaskTimeLeft"]; string objectName = row["ObjectName"].ToString(); int percentCompleted = (int)row["PercentCompleted"]; int priorityId = (int)row["PriorityId"]; int stateId = (int)row["StateId"]; bool isNewMessage = (bool)row["IsNewMessage"]; bool isOverdue = (bool)row["IsOverdue"]; DateTime finishDate = Security.CurrentUser.CurrentTimeZone.ToLocalTime((DateTime)row["FinishDate"]); string assignmentId = row["AssignmentId"].ToString(); string assignmentName = row["AssignmentName"].ToString(); string projectTitle = string.Empty; if (row["ProjectTitle"] != DBNull.Value) projectTitle = row["ProjectTitle"].ToString(); int realStartMinute = -1; // the position of the first minute allocation TimeType curType; if (!sticked) { switch (priorityId) { case (int)Priority.Urgent: curType = TimeType.WorkUrgent; break; case (int)Priority.VeryHigh: curType = TimeType.WorkVeryHigh; break; case (int)Priority.High: curType = TimeType.WorkHigh; break; case (int)Priority.Low: curType = TimeType.WorkLow; break; default: curType = TimeType.WorkNormal; break; } } else { curType = TimeType.WorkPinnedUp; } DateTime objectStartDate = calendarHelper.GetCalendarDateFromUtc((DateTime)row["StartDate"]); if (objectStartDate < curCalDate.Date) objectStartDate = curCalDate.Date; TimeSpan ts = objectStartDate.Subtract(curCalDate.Date); int minStart = (int)ts.TotalMinutes; bool continueFlag = false; int startMinute = -1; int endMinute; for (int i = minStart; i < calendarHelper.IntervalDuration; i++) { // we should find free time if (timeList[i] == TimeType.Free) { if (realStartMinute == 0) // total start realStartMinute = i; if (startMinute < 0) // start after some breaks startMinute = i; if (originalDuration <= 0) // sticked objects can have 0 duration { AddRow(resultTable, calendarHelper.HighlightedItems, userId, calendarHelper.GetUserDate(startMinute), calendarHelper.GetUserDate(startMinute), curType, objectId, objectTypeId, objectName, taskTimeLeft, percentCompleted, priorityId, stateId, finishDate, assignmentId, assignmentName, projectTitle, mergeBreaks, isNewMessage, isOverdue); continueFlag = true; break; } timeList[i] = curType; duration--; freeTimeCounter--; if (duration == 0 || freeTimeCounter == 0) { endMinute = i + 1; if (startMinute < toMinute && endMinute > fromMinute) { startMinute = CalculateStartMinute(startMinute, realStartMinute, fromMinute, calendarHelper, timeList, ref extendToLeft, mergeBreaks, strictBorder); endMinute = CalculateEndMinute(endMinute, toMinute, calendarHelper, timeList, duration, mergeBreaks, strictBorder); if (startMinute < endMinute) { AddRow(resultTable, calendarHelper.HighlightedItems, userId, calendarHelper.GetUserDate(startMinute), calendarHelper.GetUserDate(endMinute), curType, objectId, objectTypeId, objectName, taskTimeLeft, percentCompleted, priorityId, stateId, finishDate, assignmentId, assignmentName, projectTitle, mergeBreaks, isNewMessage, isOverdue); } } startMinute = -1; break; } } else // free interval break { if (startMinute >= 0) { endMinute = i; if (startMinute < toMinute && endMinute > fromMinute) { startMinute = CalculateStartMinute(startMinute, realStartMinute, fromMinute, calendarHelper, timeList, ref extendToLeft, mergeBreaks, strictBorder); endMinute = CalculateEndMinute(endMinute, toMinute, calendarHelper, timeList, duration, mergeBreaks, strictBorder); if (startMinute < endMinute) { AddRow(resultTable, calendarHelper.HighlightedItems, userId, calendarHelper.GetUserDate(startMinute), calendarHelper.GetUserDate(endMinute), curType, objectId, objectTypeId, objectName, taskTimeLeft, percentCompleted, priorityId, stateId, finishDate, assignmentId, assignmentName, projectTitle, mergeBreaks, isNewMessage, isOverdue); } } startMinute = -1; } } } if (continueFlag) continue; // last interval if (startMinute >= 0) { endMinute = calendarHelper.IntervalDuration; if (startMinute < toMinute && endMinute > fromMinute) { startMinute = CalculateStartMinute(startMinute, realStartMinute, fromMinute, calendarHelper, timeList, ref extendToLeft, mergeBreaks, strictBorder); endMinute = CalculateEndMinute(endMinute, toMinute, calendarHelper, timeList, duration, mergeBreaks, strictBorder); if (startMinute < endMinute) { AddRow(resultTable, calendarHelper.HighlightedItems, userId, calendarHelper.GetUserDate(startMinute), calendarHelper.GetUserDate(endMinute), curType, objectId, objectTypeId, objectName, taskTimeLeft, percentCompleted, priorityId, stateId, finishDate, assignmentId, assignmentName, projectTitle, mergeBreaks, isNewMessage, isOverdue); } } } if (freeTimeCounter == 0) { break; } } }