protected void btnBulkSendToNAV_Click(object sender, EventArgs e)
        {
            try
            {
                var config = SPContext.Current.GetNavWebServiceConnection();
                if (config.IsEmpty())
                {
                    throw new Exception("NAV connection info has not been specified!");
                }

                if (!IsCurrentUserAManagerForWorker())
                {
                    throw new Exception("Only Manager can Send timesheets to NAV for current user!");
                }

                // get timesheets to Send to NAV
                var approvedRosters = this.GetTimesheetsByStatus(10); // 10 = 'Approved'
                if (!approvedRosters.Any())
                {
                    throw new Exception("There is nothing to send to NAV");
                }

                // get mapping
                var _mappingSettings = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize <List <Roster.Presentation.Layouts.MapElem> >(config.Mapping);

                var calendarPeriod = Utils.GetCalendarViewPeriod(SPContext.Current.Web.GetDateOptions(Request), "week");
                var listDbFields   = new RosterConfigService().GetList(TableIDs.TIMESHEET_ROSTERS).ListMetadataFields.Select(fld => fld.GetDbField());

                // init Servicea
                CreateTimeSheetLines_Service srv = new CreateTimeSheetLines_Service();
                srv.Url         = config.CreateTimesheetUrl;
                srv.Credentials = new NetworkCredential(config.User, config.Password);
                ProcessTimeSheets procSrv = new ProcessTimeSheets();
                procSrv.Url         = config.ProcessTimesheetsUrl;
                procSrv.Credentials = new NetworkCredential(config.User, config.Password);

                Dictionary <Guid, string> errors = new Dictionary <Guid, string>();
                List <Guid> successIDs           = new List <Guid>();
                foreach (var roster in approvedRosters)
                {
                    string batchNo = Guid.NewGuid().ToString("N").Substring(0, 20);
                    try
                    {
                        var newLine = new CreateTimeSheetLines();
                        // generic values
                        newLine.Key = "0";
                        newLine.External_Time_Sheet_No            = batchNo;
                        newLine.Time_Sheet_Starting_Date          = calendarPeriod.Item1.Date;
                        newLine.Time_Sheet_Starting_DateSpecified = true;
                        // fill Line from timesheet roster
                        newLine.FillFromRoster(roster, listDbFields, _mappingSettings);

                        // create entry in NAV temp table
                        srv.Create(ref newLine);
                        // process timesheet entry
                        procSrv.ProcessTimeSheet(batchNo, false);

                        successIDs.Add(roster.Id);
                    }
                    catch (Exception ex)
                    {
                        errors.Add(roster.Id, ex.Message);
                    }
                }

                // init StoredProcedure params
                var paramCollection = new List <Tuple <string, object> >();
                paramCollection.Add(new Tuple <string, object>("@id", String.Join(",", successIDs)));
                paramCollection.Add(new Tuple <string, object>("@reason", string.Format("Bulk submit to NAV at {0}", DateTime.Now.ToString())));
                paramCollection.Add(new Tuple <string, object>("@message", ""));
                // set new STATUS
                string message = new RosterDataService().ExecuteProcedure("[dbo].[SubmitedToNAV]", paramCollection);

                if (errors.Any())
                {
                    throw new Exception(String.Join("<br/>", errors.Select(er => string.Format("Error submitting roster '{0}': {1}", er.Key, er.Value))));
                }

                txtNotification.Value = "Success";
            }
            catch (Exception ex)
            {
                txtErrorMsg.Value = ex.Message;
            }
        }
        public static void FillFromRoster(this CreateTimeSheetLines line, RosterEvent roster, IEnumerable <DbField> timesheetFields, List <Roster.Presentation.Layouts.MapElem> mapping)
        {
            var rosterProps = roster.RosterEventDictionary;

            Func <Layouts.MapElem, IEnumerable <DbField>, string> getLookupValueFunc = delegate(Layouts.MapElem map, IEnumerable <DbField> fields) {
                string _val = string.Empty;
                if (map != null)
                {
                    string[] fldNameParts = map.FieldName.Split('$');
                    var      lookupFld    = fields.FirstOrDefault(fld => fld.InternalName == map.FieldName || fld.Id == fldNameParts[0].ToGuid()) as DbFieldLookup;
                    _val = (fldNameParts.Length == 2) ?
                           rosterProps[string.Format("{0}_{1}", lookupFld.ListId, fldNameParts[1])].ToSafeString() :
                           rosterProps[map.FieldName].ToSafeString();
                }
                return(_val);
            };

            // set Description
            var descrMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.Description));

            if (descrMap != null)
            {
                line.Description = rosterProps[descrMap.FieldName].ToSafeString();
            }

            // set Type
            var typeMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.Type));

            if (typeMap != null)
            {
                string rosterType = rosterProps[typeMap.FieldName].ToSafeString().XmlToList().FirstOrDefault();
                line.Type = EnumHelper.GetEnumByDescription <Roster.Presentation.Controls.NAVproxy.Type>(
                    string.IsNullOrEmpty(rosterType) ? "_blank_" : rosterType
                    );
                line.TypeSpecified = (line.Type != Roster.Presentation.Controls.NAVproxy.Type._blank_);
            }

            // set Resource_No
            var resNoMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.Resource_No));

            line.Resource_No = getLookupValueFunc(resNoMap, timesheetFields);

            // set Job_No
            var jobNoMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.Job_No));

            line.Job_No = getLookupValueFunc(jobNoMap, timesheetFields);

            // set Job_Task_No
            var jobTaskNoMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.Job_Task_No));

            line.Job_Task_No = getLookupValueFunc(jobTaskNoMap, timesheetFields);

            // set Cause_of_Absence_Code
            var coaCoMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.Cause_of_Absence_Code));

            line.Cause_of_Absence_Code = getLookupValueFunc(coaCoMap, timesheetFields);

            // set Work_Type_Code
            var workTypeMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.Work_Type_Code));

            line.Work_Type_Code = getLookupValueFunc(workTypeMap, timesheetFields);

            // set Chargeable
            var chargMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.Chargeable));

            if (chargMap != null)
            {
                line.Chargeable          = rosterProps[chargMap.FieldName].ToBoolean();
                line.ChargeableSpecified = true;
            }

            // set Non_Roster_Day
            var nonRosMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.Non_Roster_Day));

            if (nonRosMap != null)
            {
                line.Non_Roster_Day          = rosterProps[nonRosMap.FieldName].ToBoolean();
                line.Non_Roster_DaySpecified = true;
            }

            // set Start_Time
            var startMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.Start_Time));

            if (startMap != null)
            {
                line.Start_Time          = (DateTime)rosterProps[startMap.FieldName];
                line.Start_TimeSpecified = true;
            }

            // set End_Time
            var endMap = mapping.FirstOrDefault(m => m.WebParam == EnumHelper.GetEnumDescription(CreateTimeSheetLines_Fields.End_Time));

            if (endMap != null)
            {
                line.End_Time          = (DateTime)rosterProps[endMap.FieldName];
                line.End_TimeSpecified = true;
            }

            // QTY1-7
            DateTime rosterStartDate = (DateTime)rosterProps[FieldNames.START_DATE];
            DateTime rosterEndDate   = (DateTime)rosterProps[FieldNames.END_DATE];
            double   qty             = Math.Round((rosterEndDate - rosterStartDate).TotalHours, 2, MidpointRounding.AwayFromZero);
            int      qtyIndex        = (rosterStartDate - line.Time_Sheet_Starting_Date).Days + 1;

            switch (qtyIndex)
            {
            case 1:
                line.Qty1 = (decimal)qty; line.Qty1Specified = true; break;

            case 2:
                line.Qty2 = (decimal)qty; line.Qty2Specified = true; break;

            case 3:
                line.Qty3 = (decimal)qty; line.Qty3Specified = true; break;

            case 4:
                line.Qty4 = (decimal)qty; line.Qty4Specified = true; break;

            case 5:
                line.Qty5 = (decimal)qty; line.Qty5Specified = true; break;

            case 6:
                line.Qty6 = (decimal)qty; line.Qty6Specified = true; break;

            case 7:
                line.Qty7 = (decimal)qty; line.Qty7Specified = true; break;

            default:
                break;
            }

            // -------------------------
            // You need to set Specified = true before your initial call to Create.
            // The same goes for all value types – if you don’t set Specified to true, then the value doesn’t get transferred to NAV Web Services,
            // this is a behavior of the proxy classes generated by Visual Studio.
            // When you get the record back from NAV – all value type fields will have their corresponding Specified field set to true and thus you can modify and send it back.
            // -------------------------
        }