private void BuildClientsByHourData(Report101InfoViewModel result)
        {
            //query
            //group by flat hour
            var querySortedEnd = from low in shiftLinesOfWork
                                 where low.StartDate.Year > 1
                                 orderby low.StartDate
                                 group low by low.StartDate.AddMinutes(-low.StartDate.Minute);

            foreach (var group in querySortedEnd)
            {
                ClientsByHour cbh = new ClientsByHour();
                cbh.Hour = string.Format("{0:h:mm tt}", group.Key);

                cbh.Clients = group.Sum(x => x.Clients);

                result.ClientsByHourTotals.Add(cbh);
            }
        }
        public Report101InfoViewModel Load101Report(string filepath, BackgroundWorker load101Worker)
        {
            var           fileReader = ServiceContainer.GetService <IFileReaderService>();
            List <string> lines      = fileReader.ReadLines(filepath);

            //int total_facturas = HowManyInvoices(lines);
            //int loaded_facturas = 0;

            //at least 5 lines always there
            if (lines.Count <= 5)
            {
                throw new Exception("El reporte está vacío.");
            }

            //make sure first line says "Electronic Journal"
            string firstLine = lines[0];

            //string lineTitle = firstLine.Split(';')[5];

            if (!firstLine.Contains("\"Electronic Journal\""))
            {
                throw new Exception("Este no es el reporte 101.");
            }

            activeLinesOfWork   = new Dictionary <int, LineOfWork>();
            shiftLinesOfWork    = new List <LineOfWork>();
            abrir_cajon_counter = 0;

            List <string> current_operation_lines = new List <string>();

            //skip 2 lines

            //first build the lines of work

            for (int i = 2; i < lines.Count; i++)
            {
                string currentLine = lines[i];

                if (currentLine.Contains("----------------------------------------"))
                {
                    ProcessOperation(current_operation_lines);

                    current_operation_lines.Clear();

                    continue;
                }
                else
                {
                    current_operation_lines.Add(currentLine);
                }

                load101Worker.ReportProgress(i * 100 / lines.Count);
            }

            load101Worker.ReportProgress(0);

            //now process all the information
            Report101InfoViewModel result = new Report101InfoViewModel();

            result.FilePath        = filepath;
            result.OpenDrawerCount = abrir_cajon_counter;

            int count = 0;

            foreach (var low in shiftLinesOfWork)
            {
                result.TotalSales    += low.Total;
                result.TotalDiscount += low.Discount;
                result.TotalClients  += low.Clients;
                result.LinesOfWork.Add(low);

                var span = low.FacturaDate - low.StartDate;

                bool recibo_found = false;

                for (int i = 0; i < low.OperationTrack.Count; i++)
                {
                    if (low.OperationTrack[i] == Report101Operation.Print)
                    {
                        recibo_found = true;
                    }

                    else if (low.OperationTrack[i] == Report101Operation.Void)
                    {
                        result.VoidCount++;
                        if (recibo_found)
                        {
                            result.CriticalVoidCount++;
                            if (string.IsNullOrEmpty(result.CriticalVoidFacturas))
                            {
                                result.CriticalVoidFacturas = low.FacturaNumber.ToString();
                            }
                            else
                            {
                                result.CriticalVoidFacturas += ", " + low.FacturaNumber;
                            }
                        }
                    }
                }

                load101Worker.ReportProgress(++count * 100 / shiftLinesOfWork.Count);
            }

            //service time data
            var groupQuery = from low in shiftLinesOfWork
                             let span = GetSpanKey(low)
                                        where span >= 0
                                        orderby span
                                        group low by span;

            foreach (var group in groupQuery)
            {
                ServiceTimeTotal stt = new ServiceTimeTotal();

                int minutes = group.Key * 5;
                stt.ServiceTimeMinutes = minutes > 60 ? "> 60" : minutes.ToString();
                stt.Quantity           = group.Count();

                result.ServiceTimeTotals.Add(stt);
            }

            BuildClientsByHourData(result);

            return(result);
        }