Example #1
0
        /// <summary>
        /// Read all log entries from Xml file.
        /// </summary>
        /// <param name="dataXml"></param>
        static public void ReadLogEntries(XmlDocument dataXml)
        {
            // Load indvidual time log entries
            XmlNodeList dayNodes = dataXml.SelectNodes("/ptt_data/time_logs/day");

            foreach (XmlNode dayNode in dayNodes)
            {
                XmlAttribute attr    = dayNode.Attributes["date"];
                DateTime     logDate = DateTime.Parse(attr.Value);
                SortableBindingList <TimeLogEntry> logEntries = new SortableBindingList <TimeLogEntry>();
                TimeLogEntry.AllTimeLogEntries[logDate] = logEntries;

                XmlNodeList logNodes = dayNode.SelectNodes("log");
                foreach (XmlNode node in logNodes)
                {
                    TimeLogEntry entry = new TimeLogEntry(node, logDate);
                    logEntries.Add(entry);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Print Report showing daily activity (optionally showing all tasks)
        /// </summary>
        /// <param name="e"></param>
        private void PrintActivityPage(PrintPageEventArgs e, Point drawLocation)
        {
            bool skipRestOfPage = m_needToShowOverallTotals;

            while (!skipRestOfPage && drawLocation.Y < e.MarginBounds.Bottom && m_currentDateBeingPrinted <= m_endDate)
            {
                LogFileManager.LoadDataFileIfNotAlreadyLoaded(m_currentDateBeingPrinted);
                SortableBindingList <TimeLogEntry> logs = TimeLogEntry.LogsForDay(m_currentDateBeingPrinted);
                if (null == logs || 0 == logs.Count)
                {
                    if (!m_skipDaysWithoutTasks)
                    {
                        PrintDayHeaderLine(e, ref drawLocation);
                        e.Graphics.DrawString(Properties.Resources.ReportStrNoActivity, m_detailFont, m_detailBrush, drawLocation);
                        drawLocation.Y    += m_detailFont.Height;
                        m_lastDayDisplayed = m_currentDateBeingPrinted;
                    }
                    // Move to next day
                    m_currentDateBeingPrinted = m_currentDateBeingPrinted.AddDays(1);
                    m_customersSeenForDay.Clear();
                    m_indexOfTaskInCurrentDay = 0;
                    continue;
                }
                // If not already past end and do not need to show summary from last page
                else if (!m_needToShowSummary && m_indexOfTaskInCurrentDay < logs.Count)
                {
                    TimeLogEntry log = logs[m_indexOfTaskInCurrentDay];
                    if (!m_customersSeenForDay.Contains(log.Customer.Name))
                    {
                        m_customersSeenForDay.Add(log.Customer.Name);
                    }
                    // Add to overall totals
                    TimeSpan[] timeSpans = null;
                    if (!m_customerSummaryData.ContainsKey(log.Customer.Name))
                    {
                        timeSpans = new TimeSpan[2];
                        m_customerSummaryData[log.Customer.Name] = timeSpans;
                    }
                    else
                    {
                        timeSpans = m_customerSummaryData[log.Customer.Name];
                    }
                    if (log.IsBillable)
                    {
                        timeSpans[BILLABLE_TIME_INDEX] += log.Duration;
                    }
                    else
                    {
                        timeSpans[NON_BILLABLE_TIME_INDEX] += log.Duration;
                    }

                    if (m_lastDayDisplayed != m_currentDateBeingPrinted)
                    {
                        PrintDayHeaderLine(e, ref drawLocation);
                        m_lastDayDisplayed = m_currentDateBeingPrinted;
                    }
                    if (m_showTasks)
                    {
                        //		{0} for {1} from {2} to {3}. Duration{4}({5})  Billable:{6}
                        string durationStr = string.Format("{0}:{1}",
                                                           log.Duration.Hours.ToString(), log.Duration.Minutes.ToString("00"));
                        string durationPercentStr = string.Format("{0}.{1}",
                                                                  log.Duration.Hours.ToString(), ((int)(log.Duration.Minutes * 100) / 60).ToString("00"));
                        string billiableFlagStr = "";
                        if (!log.IsBillable)
                        {
                            billiableFlagStr = Properties.Resources.ReportStrNotBillableReportTag;
                        }
                        string taskLine = string.Format(Properties.Resources.ReportStrActivityLine,
                                                        log.Task.Name,
                                                        log.Customer.Name,
                                                        log.StartTime.ToShortTimeString(),
                                                        log.StopTime.ToShortTimeString(),
                                                        durationStr,
                                                        durationPercentStr,
                                                        billiableFlagStr);
                        e.Graphics.DrawString(taskLine, m_detailFont, m_detailBrush, drawLocation);
                        drawLocation.Y += m_detailFont.Height;
                    }
                    // Move to next item (could bump to next day)
                    ++m_indexOfTaskInCurrentDay;
                }
                Point startPoint;
                Point endPoint;
                if (null != logs && m_indexOfTaskInCurrentDay >= logs.Count)
                {
                    if (0 < m_customersSeenForDay.Count)
                    {
                        m_needToShowSummary = true;
                        // See if there is enough room to display the summary (# customers + 1 for totals + 1 for horz line + 1 for header)
                        int summaryHeight = m_summaryFont.Height * (3 + m_customersSeenForDay.Count);
                        if (drawLocation.Y + summaryHeight > e.MarginBounds.Bottom)
                        {
                            // Must wait for next page
                            skipRestOfPage = true;
                            break;
                        }
                        m_needToShowSummary = false; // we are going to print it so clear flag
                        // OK, we have enough room for the summary

                        DrawSummaryHeader(ref drawLocation, e, Properties.Resources.ReportStrCustomerColHeader);

                        TimeSpan dailyTotalTime       = new TimeSpan();
                        TimeSpan dailyBillableTime    = new TimeSpan();
                        TimeSpan dailyNonBillableTime = new TimeSpan();
                        // Sort customers alphabetically
                        m_customersSeenForDay.Sort();
                        foreach (string customerName in m_customersSeenForDay)
                        {
                            TimeSpan billableTime    = new TimeSpan();
                            TimeSpan nonBillableTime = new TimeSpan();
                            // Total up time for this customer
                            foreach (TimeLogEntry log in logs)
                            {
                                if (log.Customer.Name == customerName)
                                {
                                    if (log.IsBillable)
                                    {
                                        billableTime      += log.Duration;
                                        dailyBillableTime += log.Duration;
                                    }
                                    else
                                    {
                                        nonBillableTime      += log.Duration;
                                        dailyNonBillableTime += log.Duration;
                                    }
                                }
                            }
                            DrawSummaryLine(ref drawLocation, e, customerName, billableTime, nonBillableTime);
                        }
                        // Update the overall totals

                        m_overallBillableTime    += dailyBillableTime;
                        m_overallNonBillableTime += dailyNonBillableTime;

                        DrawSummaryLine(ref drawLocation, e, Properties.Resources.ReportStrTotalTitle,
                                        dailyBillableTime, dailyNonBillableTime);
                        // Draw a dividing line between details and summary (if showing details)
                        startPoint    = drawLocation;
                        startPoint.Y += m_summaryFont.Height / 2;
                        endPoint      = new Point(e.MarginBounds.Left + e.MarginBounds.Width / 2, drawLocation.Y + m_summaryFont.Height / 2);
                        e.Graphics.DrawLine(m_linePen, startPoint, endPoint);
                        drawLocation.Y += m_summaryFont.Height;
                    }
                    m_indexOfTaskInCurrentDay = 0;
                    m_currentDateBeingPrinted = m_currentDateBeingPrinted.AddDays(1);
                    m_customersSeenForDay.Clear();
                }
            }
            e.HasMorePages = skipRestOfPage || (m_currentDateBeingPrinted < m_endDate);
            // See if we need to display the grand totals
            if (m_needToShowOverallTotals || !e.HasMorePages)
            {
                m_needToShowOverallTotals = true;
                // See if there is enough room to display the summary (# customers + 1 for totals + 1 for horz line + 1 for header)
                int summaryHeight = m_summaryFont.Height * (3 + m_customerSummaryData.Count);
                if (drawLocation.Y + summaryHeight > e.MarginBounds.Bottom)
                {
                    e.HasMorePages = true; // Must put summary on last page
                }
                else
                {
                    m_needToShowOverallTotals = false; // we are going to print it so clear flag

                    if (drawLocation.Y > e.MarginBounds.Top)
                    {
                        drawLocation.Y += m_summaryFont.Height;
                    }
                    // draw a horz line all the way across
                    Point startPoint = drawLocation;
                    startPoint.Y += m_summaryFont.Height / 2;
                    Point endPoint = new Point(e.MarginBounds.Right, drawLocation.Y + m_summaryFont.Height / 2);
                    e.Graphics.DrawLine(m_linePen, startPoint, endPoint);
                    drawLocation.Y += m_summaryFont.Height;

                    DrawSummaryHeader(ref drawLocation, e, Properties.Resources.ReportStrCustomerColHeader);

                    // Sort customers alphabetically
                    List <string> allCustomerNames = new List <string>();
                    foreach (string key in m_customerSummaryData.Keys)
                    {
                        allCustomerNames.Add(key);
                    }
                    allCustomerNames.Sort();
                    // Now show each customer's totals
                    TimeSpan overallBillable    = new TimeSpan();
                    TimeSpan overallNonBillable = new TimeSpan();
                    TimeSpan overallTotal       = new TimeSpan();
                    foreach (string name in allCustomerNames)
                    {
                        TimeSpan[] timeSpans = m_customerSummaryData[name];

                        DrawSummaryLine(ref drawLocation, e, name,
                                        timeSpans[BILLABLE_TIME_INDEX],
                                        timeSpans[NON_BILLABLE_TIME_INDEX]);
                        // Add to global total
                        overallBillable    += timeSpans[BILLABLE_TIME_INDEX];
                        overallNonBillable += timeSpans[NON_BILLABLE_TIME_INDEX];
                        overallTotal       += timeSpans[BILLABLE_TIME_INDEX] + timeSpans[NON_BILLABLE_TIME_INDEX];
                    }
                    DrawSummaryLine(ref drawLocation, e, Properties.Resources.ReportStrTotalTitle,
                                    overallBillable, overallNonBillable);

                    e.HasMorePages = false; // this is the end
                }
            }
        }
Example #3
0
 /// <summary>
 /// Run through all tasks in given time period and calculate sums.
 /// </summary>
 private void CalculateSummaries()
 {
     if (m_showTasks)
     {
         m_taskSummaryData = new Dictionary <string, Dictionary <string, TimeSpan[]> >();
     }
     while (m_currentDateBeingPrinted <= m_endDate)
     {
         LogFileManager.LoadDataFileIfNotAlreadyLoaded(m_currentDateBeingPrinted);
         SortableBindingList <TimeLogEntry> logs = TimeLogEntry.LogsForDay(m_currentDateBeingPrinted);
         if (null != logs && 0 != logs.Count)
         {
             foreach (TimeLogEntry log in logs)
             {
                 if (m_showTasks)
                 {
                     // Update task level totals
                     Dictionary <string, TimeSpan[]> taskList = null;
                     // Get the task list for this customer (or create one)
                     if (m_taskSummaryData.ContainsKey(log.Customer.Name))
                     {
                         taskList = m_taskSummaryData[log.Customer.Name];
                     }
                     else
                     {
                         taskList = new Dictionary <string, TimeSpan[]>();
                         m_taskSummaryData[log.Customer.Name] = taskList;
                     }
                     // See if this task exists yet
                     TimeSpan[] taskTimes = null;
                     if (taskList.ContainsKey(log.Task.Name))
                     {
                         taskTimes = taskList[log.Task.Name];
                     }
                     else
                     {
                         taskTimes = new TimeSpan[2];
                     }
                     if (log.IsBillable)
                     {
                         taskTimes[0] += log.Duration;
                     }
                     else
                     {
                         taskTimes[1] += log.Duration;
                     }
                     taskList[log.Task.Name] = taskTimes;
                 }
                 // Update customer level totals
                 TimeSpan[] customerTotals = null;
                 if (m_customerSummaryData.ContainsKey(log.Customer.Name))
                 {
                     customerTotals = m_customerSummaryData[log.Customer.Name];
                 }
                 else
                 {
                     customerTotals = new TimeSpan[2];
                     m_customerSummaryData[log.Customer.Name] = customerTotals;
                 }
                 if (log.IsBillable)
                 {
                     customerTotals[0] += log.Duration;
                 }
                 else
                 {
                     customerTotals[1] += log.Duration;
                 }
             }
         }
         // Move to next day
         m_currentDateBeingPrinted = m_currentDateBeingPrinted.AddDays(1);
     }
     // Sort customer names
     foreach (string s in m_customerSummaryData.Keys)
     {
         m_customersSeenForDay.Add(s);
     }
     m_customersSeenForDay.Sort();
     // Get ready to run through the list
     m_customerEnumerator = m_customersSeenForDay.GetEnumerator();
     m_needNextCustomer   = true;
     m_needToShowSummary  = true;
 }
Example #4
0
        /// <summary>
        /// Adjust existing log times based on the new log entry.
        /// </summary>
        /// <param name="newLog">The log just added.</param>
        static public void AdjustTimeEntriesForNewItem(TimeLogEntry newLog)
        {
            SortableBindingList <TimeLogEntry> currentList = LogsForDay(newLog.StartTime);

            // First adjust for any overlaps with the new entry taking precedence
            for (int rowIdx = currentList.Count - 1; rowIdx >= 0; --rowIdx)
            {
                TimeLogEntry log = currentList[rowIdx];
                if (object.ReferenceEquals(log, newLog))
                {
                    continue;                                      // skip yourself
                }
                // Is the current log is within the new one?
                if (newLog.StartTime < log.StartTime && newLog.StopTime > log.StopTime)
                {
                    // 2 Options, delete this log or split up new one
                    // (I hate putting UI into this class but it would be more work than it is worth to have a callback or something)
                    System.Windows.Forms.DialogResult result = System.Windows.Forms.MessageBox.Show("An old log entry falls in the time period specified for this new log.  Do you want to delete the old log entry?  If you choose No the new entry will be split around it.",
                                                                                                    "Log Overlap", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
                    if (System.Windows.Forms.DialogResult.Yes == result)
                    {
                        // Delete old line
                        currentList.RemoveAt(rowIdx);
                    }
                    else
                    {
                        // Split new line into multiple lines
                        TimeLogEntry newAdjustmentLog = TimeLogEntry.CreateNewLogEntryFromExisingLog(newLog);
                        // New log will be the last one
                        newAdjustmentLog.StartTime = newLog.StartTime;
                        newAdjustmentLog.StopTime  = log.StartTime.AddSeconds(-1);
                        newLog.StartTime           = log.StopTime.AddSeconds(1);
                    }
                }
                // Is the new log inside of this log?
                else if (newLog.StartTime > log.StartTime && newLog.StartTime < log.StopTime)
                {
                    // The new log starts in the middle of this log so adjust
                    // First see if the new log is entirely contained in the old log
                    if (newLog.StopTime < log.StopTime)
                    {
                        // Yes the new log is smack in the middle of the old one.
                        // So, split the old one into 2 entries
                        TimeLogEntry newAdjustmentLog = TimeLogEntry.CreateNewLogEntryFromExisingLog(log);
                        newAdjustmentLog.StartTime = newLog.StopTime.AddSeconds(1);
                        log.StopTime = newLog.StartTime.AddSeconds(-1);
                        // Swap interruption time if needed
                        TimeSpan zeroTimeSpan = new TimeSpan();
                        if (zeroTimeSpan > log.Duration)
                        {
                            if (log.InterruptionTime > newAdjustmentLog.Duration)
                            {
                                // Divide evenly between both
                                TimeSpan halfOfInterruption = new TimeSpan(log.InterruptionTime.Ticks / 2);
                                log.InterruptionTime = halfOfInterruption;
                                newAdjustmentLog.InterruptionTime = halfOfInterruption;
                            }
                            else
                            {
                                // Just swap who gets the interrupt time
                                newAdjustmentLog.InterruptionTime = log.InterruptionTime;
                                log.InterruptionTime = zeroTimeSpan;
                            }
                        }
                        break; // no need to continue
                    }
                    else
                    {
                        log.StopTime = newLog.StartTime.AddSeconds(-1);
                    }
                }
                else if (newLog.StopTime > log.StartTime && newLog.StopTime < log.StopTime)
                {
                    log.StartTime = newLog.StopTime.AddSeconds(1);
                }
            }
        }
Example #5
0
 static public void SortLogs(SortableBindingList <TimeLogEntry> currentList)
 {
     currentList.Sort("StartTime", ListSortDirection.Ascending);
 }