Example #1
0
        private void ExportAbsenceEntriesToCSV(MongoCursor <BsonDocument> cursor)
        {
            foreach (BsonDocument document in cursor)
            {
                var csvLine = new TroToVismaCsvLine();

                if (!document.Contains("user"))
                {
                    throw new Exception("Absence entry is missing pserson");
                }

                if (!document.Contains("absenceentrytype"))
                {
                    throw new Exception("Absence entry is missing absence type");
                }

                ObjectId userId        = (ObjectId)document["user"][0];
                ObjectId absenceTypeId = (ObjectId)document["absenceentrytype"][0];

                BsonDocument userDocument = database.GetCollection("user").FindOne(Query.EQ(DBQuery.Id, userId));

                BsonDocument absenceTypeDocument = database.GetCollection("absenceentrytype").FindOne(Query.EQ(DBQuery.Id, absenceTypeId));

                if (userDocument == null)
                {
                    throw new Exception("Person not found for absence entry");
                }

                if (absenceTypeDocument == null)
                {
                    throw new Exception("Absence type not found for absence entry");
                }

                BsonDocument profitcenterDocument = database.GetCollection("profitcenter").FindOne(Query.EQ(DBQuery.Id, userDocument["profitcenter"][0]));

                csvLine.Values[(int)TroToVismaColumns.Paytype] = (string)absenceTypeDocument["identifier"];

                TimeSpan duration = (DateTime)document["endtimestamp"] - (DateTime)document["starttimestamp"];

                // Hours + minutes in one value with the accuracy of two decimal spaces.
                Double hours = (double)duration.Hours + Math.Round(((double)duration.Minutes) / 60, 2);

                csvLine.Values[(int)TroToVismaColumns.Hours]           = Convert.ToString(hours, new CultureInfo("fi-FI"));
                csvLine.Values[(int)TroToVismaColumns.Days]            = "0";
                csvLine.Values[(int)TroToVismaColumns.PersonnelNumber] = (string)userDocument["identifier"];
                csvLine.Values[(int)TroToVismaColumns.Paytype]         = (string)absenceTypeDocument["identifier"];
                csvLine.Values[(int)TroToVismaColumns.Amount]          = "0";
                csvLine.Values[(int)TroToVismaColumns.Euro]            = "0";
                csvLine.Values[(int)TroToVismaColumns.ProfitCenter]    = (string)profitcenterDocument["identifier"];

                DateTime date = (DateTime)document["starttimestamp"];
                csvLine.Values[(int)TroToVismaColumns.StartDate] = string.Format("{0:00}.{1:00}.{2:0000}", date.Day, date.Month, date.Year);

                rawCsvLines.Add(csvLine);
            }
        }
Example #2
0
        private void ExportTimesheetFragmentsToCsv(List <TimesheetEntryFragment> timesheetEntryFragments)
        {
            foreach (TimesheetEntryFragment fragment in timesheetEntryFragments)
            {
                var csvLine = new TroToVismaCsvLine();

                csvLine.Values[(int)TroToVismaColumns.PersonnelNumber] = fragment.WorkerId;
                csvLine.Values[(int)TroToVismaColumns.Paytype]         = Convert.ToString(fragment.PayType);
                csvLine.Values[(int)TroToVismaColumns.Hours]           = Convert.ToString((fragment.End - fragment.Start).Hours);
                csvLine.Values[(int)TroToVismaColumns.Days]            = "0"; // Todo: Figure out if this is ok.
                csvLine.Values[(int)TroToVismaColumns.Amount]          = Convert.ToString(fragment.Detail["amount"]);
                csvLine.Values[(int)TroToVismaColumns.Euro]            = Convert.ToString(fragment.Detail["sum"], CultureInfo.InvariantCulture);
                csvLine.Values[(int)TroToVismaColumns.StartDate]       = string.Format("{0:0000}-{1:00}-{2:00}", fragment.Start.Year, fragment.Start.Month, fragment.Start.Day);

                exportedLines.Add(csvLine);
            }
        }
Example #3
0
        private void AddPayType(TimesheetEntryFragment fragment, string payType, double payTypeFactor, bool isPrimary)
        {
            var csvLine = new TroToVismaCsvLine();

            csvLine.Values[(int)TroToVismaColumns.PersonnelNumber] = fragment.WorkerId;

            csvLine.Values[(int)TroToVismaColumns.Paytype] = payType;

            TimeSpan duration = fragment.End - fragment.Start;

            // Hours + minutes in one value with the accuracy of two decimal spaces.
            Double hours = Math.Round(((double)duration.Hours + ((double)duration.Minutes) / 60) * payTypeFactor, 2) + ((int)duration.TotalDays * 24);

            csvLine.Values[(int)TroToVismaColumns.Hours] = Convert.ToString(hours, new CultureInfo("fi-FI"));
            csvLine.Values[(int)TroToVismaColumns.Days]  = "0";

            // Amount and sum are only added to the primary pay type.
            if (fragment.Detail != null && isPrimary)
            {
                csvLine.Values[(int)TroToVismaColumns.Amount] = Convert.ToString(fragment.Detail.GetValue("amount", 0));
                csvLine.Values[(int)TroToVismaColumns.Euro]   = Convert.ToString(fragment.Detail.GetValue("sum", 0), new CultureInfo("fi-FI"));
            }
            else
            {
                csvLine.Values[(int)TroToVismaColumns.Amount] = "0";
                csvLine.Values[(int)TroToVismaColumns.Euro]   = "0";
            }

            csvLine.Values[(int)TroToVismaColumns.StartDate]    = string.Format("{0:00}.{1:00}.{2:0000}", fragment.Start.Day, fragment.Start.Month, fragment.Start.Year);
            csvLine.Values[(int)TroToVismaColumns.ProfitCenter] = fragment.WorkerProfitCenter;

            if (fragment.Detail != null && (bool)fragment.Detail.GetValue("substractlunchbreak", false))
            {
                csvLine.Values[(int)TroToVismaColumns.LunchBreak] = "true";
            }
            else
            {
                csvLine.Values[(int)TroToVismaColumns.LunchBreak] = "false";
            }

            rawCsvLines.Add(csvLine);
        }
Example #4
0
        /// <summary>
        /// Postprocess stage will take the expored data, group it to users, days and payment types. The grouping is
        /// done at this stage mostly for historical reasons but it does provide a decent debug option to observe the
        /// raw data befor postporcess stage.
        /// </summary>
        private void PostProcessData()
        {
            // Dictionary of dictoinaries of DailyHourTotalsHelpers
            // user
            //      date
            //          paytype
            //              helper object with row totals

            var dailyTotals = new DataTree();

            // Count hour totals using helper object
            for (int i = rawCsvLines.Count - 1; i >= 0; i--)
            {
                TroToVismaCsvLine line = rawCsvLines[i];

                string payType      = line.Values[(int)TroToVismaColumns.Paytype];
                string userId       = line.Values[(int)TroToVismaColumns.PersonnelNumber];
                string date         = line.Values[(int)TroToVismaColumns.StartDate];
                string profitCenter = line.Values[(int)TroToVismaColumns.ProfitCenter];
                bool   lunchBreak   = ((string)line.Values[(int)TroToVismaColumns.LunchBreak] == "true");
                double hours        = Convert.ToDouble(line.Values[(int)TroToVismaColumns.Hours], new CultureInfo("fi-FI"));
                double euro         = Convert.ToDouble(line.Values[(int)TroToVismaColumns.Euro], new CultureInfo("fi-FI"));
                int    days         = Convert.ToInt32(line.Values[(int)TroToVismaColumns.Days]);
                int    amount       = Convert.ToInt32(line.Values[(int)TroToVismaColumns.Amount]);

                decimal currentHours  = 0;
                decimal currentEuro   = 0;
                int     currentDays   = 0;
                int     currentAmount = 0;

                if (dailyTotals[userId][date][payType]["hours"].Exists)
                {
                    currentHours = (decimal)dailyTotals[userId][date][payType]["hours"];
                }

                if (dailyTotals[userId][date][payType]["euro"].Exists)
                {
                    currentEuro = (decimal)dailyTotals[userId][date][payType]["euro"];
                }

                if (dailyTotals[userId][date][payType]["days"].Exists)
                {
                    currentDays = (int)dailyTotals[userId][date][payType]["days"];
                }

                if (dailyTotals[userId][date][payType]["amount"].Exists)
                {
                    currentAmount = (int)dailyTotals[userId][date][payType]["amount"];
                }

                dailyTotals[userId][date][payType]["hours"]  = (decimal)(currentHours + Convert.ToDecimal(hours));
                dailyTotals[userId][date][payType]["euro"]   = (decimal)(currentEuro + Convert.ToDecimal(euro));
                dailyTotals[userId][date][payType]["days"]   = currentDays + days;
                dailyTotals[userId][date][payType]["amount"] = currentAmount + amount;

                if (lunchBreak)
                {
                    dailyTotals[userId][date][payType]["lunchbreak"] = true;
                }

                dailyTotals[userId]["profitcenter"] = profitCenter;
            }

            // Add lunch breaks for applicable pay types
            foreach (DataTree user in dailyTotals)
            {
                foreach (DataTree date in user)
                {
                    // Lunch breaks for basic hours are special and contain pay
                    double basicHours  = (double)(decimal)date[IntegrationHelpers.PayTypeBasic]["hours"].GetValueOrDefault((decimal)0);
                    double overtime50  = (double)(decimal)date[IntegrationHelpers.PayTypeOvertime50]["hours"].GetValueOrDefault((decimal)0);
                    double overtime100 = (double)(decimal)date[IntegrationHelpers.PayTypeOvertime100]["hours"].GetValueOrDefault((decimal)0);

                    double totalBasicHours = basicHours + overtime50 + overtime100;

                    // Lunc break is substracted if basic hours amount is greater than (and not equal) to 6h. The corner case
                    // was verified from Visma
                    if (totalBasicHours > MinDayLengthWithLunchBreak)
                    {
                        logger.LogTrace("Adding lunch break", user.Name, date.Name, "Hours before lunch break" + basicHours, "Basic hours");
                        date[IntegrationHelpers.PayTypeBasic]["hours"]      = (decimal)(basicHours - LunchBreakLength);
                        date[IntegrationHelpers.PayTypeBasic]["lunchbreak"] = true;
                    }

                    foreach (DataTree payType in date)
                    {
                        if (!payType.Contains("lunchbreak"))
                        {
                            continue;
                        }

                        double hours = (double)(decimal)payType["hours"].GetValueOrDefault((decimal)0);

                        if (hours > MinDayLengthWithLunchBreak)
                        {
                            logger.LogTrace("Adding lunch break", user.Name, date.Name, "Hours before lunch break" + basicHours, "PayType: " + payType.Name);
                            payType["hours"]      = (decimal)(basicHours - LunchBreakLength);
                            payType["lunchbreak"] = true;
                        }
                    }
                }
            }

            foreach (DataTree user in dailyTotals)
            {
                foreach (DataTree date in user)
                {
                    foreach (DataTree payType in date)
                    {
                        var csvLine = new TroToVismaCsvLine();

                        csvLine.Values[(int)TroToVismaColumns.Hours]           = Convert.ToString((double)(decimal)payType["hours"].GetValueOrDefault(0), new CultureInfo("fi-FI"));
                        csvLine.Values[(int)TroToVismaColumns.Days]            = Convert.ToString(payType["days"].GetValueOrDefault(0));
                        csvLine.Values[(int)TroToVismaColumns.PersonnelNumber] = user.Name;
                        csvLine.Values[(int)TroToVismaColumns.Paytype]         = payType.Name;
                        csvLine.Values[(int)TroToVismaColumns.Amount]          = Convert.ToString((double)(decimal)payType["amount"].GetValueOrDefault(0), new CultureInfo("fi-FI"));
                        csvLine.Values[(int)TroToVismaColumns.Euro]            = Convert.ToString((double)(decimal)payType["euro"].GetValueOrDefault(0), new CultureInfo("fi-FI"));
                        csvLine.Values[(int)TroToVismaColumns.StartDate]       = date.Name;
                        csvLine.Values[(int)TroToVismaColumns.ProfitCenter]    = user["profitcenter"];

                        processedCsvLines.Add(csvLine);
                    }
                }
            }

            WriteAnnotatedHoursToDisk(dailyTotals);
            WriteAnnotatedTotalHoursToDisk(dailyTotals);
        }
Example #5
0
        private void ExportDailyEntriesToCSV(MongoCursor <BsonDocument> cursor)
        {
            foreach (BsonDocument document in cursor)
            {
                var csvLine = new TroToVismaCsvLine();

                ObjectId userId = (ObjectId)document["user"][0];

                BsonDocument userDocument = database.GetCollection("user").FindOne(Query.EQ(DBQuery.Id, userId));

                BsonDocument dayEntryType = database.GetCollection("dayentrytype").FindOne(Query.EQ(DBQuery.Id, document["dayentrytype"][0]));


                if (userDocument == null)
                {
                    throw new Exception("User not found for daily entry");
                }

                if (dayEntryType == null)
                {
                    throw new Exception("Entry type not for daily entry");
                }

                BsonDocument profitcenterDocument = database.GetCollection("profitcenter").FindOne(Query.EQ(DBQuery.Id, userDocument["profitcenter"][0]));

                if (profitcenterDocument == null)
                {
                    throw new Exception("Profit center not for daily entry");
                }

                csvLine.Values[(int)TroToVismaColumns.PersonnelNumber] = (string)userDocument["identifier"];
                csvLine.Values[(int)TroToVismaColumns.Paytype]         = (string)dayEntryType["identifier"];
                csvLine.Values[(int)TroToVismaColumns.Hours]           = "0";

                csvLine.Values[(int)TroToVismaColumns.Euro]   = "0";
                csvLine.Values[(int)TroToVismaColumns.Amount] = "0";
                csvLine.Values[(int)TroToVismaColumns.Days]   = "0";

                // Daily entry amount is set as either euro, pieces or days edepending no daily entry type
                if (dayEntryType.GetValue("unit", string.Empty) == "euro")
                {
                    csvLine.Values[(int)TroToVismaColumns.Euro] = Convert.ToString((int)document.GetValue("amount", 0));
                }
                else if (dayEntryType.GetValue("unit", string.Empty) == "pcs")
                {
                    csvLine.Values[(int)TroToVismaColumns.Amount] = Convert.ToString((int)document.GetValue("amount", 0));
                }
                else
                {
                    csvLine.Values[(int)TroToVismaColumns.Days] = Convert.ToString((int)document.GetValue("amount", 0));
                }

                csvLine.Values[(int)TroToVismaColumns.ProfitCenter] = (string)profitcenterDocument["identifier"];

                // XXX: Implemented a quick temporary fix for DT-394. The correct fix is to implement date picker to always return
                //      dates with UTC time 0:00 for correct date.
                DateTime date = ((DateTime)document["date"]).AddHours(12);
                csvLine.Values[(int)TroToVismaColumns.StartDate] = string.Format("{0:00}.{1:00}.{2:0000}", date.Day, date.Month, date.Year);

                rawCsvLines.Add(csvLine);
            }
        }