Пример #1
0
        public void ClearRemovesAllDays()
        {
            DateTime dateTime1 = new DateTime(2015, 7, 28, 9, 58, 0);
            DateTime dateTime2 = new DateTime(2014, 1, 22, 23, 19, 0);

            msdyn_timeentry timeEntry1 = new msdyn_timeentry();

            timeEntry1.msdyn_timeentryId = new Guid();
            timeEntry1.msdyn_description = "entry 1";
            timeEntry1.msdyn_date        = dateTime1;
            timeEntry1.msdyn_duration    = 2;

            msdyn_timeentry timeEntry2 = new msdyn_timeentry();

            timeEntry2.msdyn_timeentryId = new Guid();
            timeEntry2.msdyn_description = "entry 2";
            timeEntry2.msdyn_date        = dateTime2;
            timeEntry2.msdyn_duration    = 2;

            TimeCollectionViewModel viewModel = new TimeCollectionViewModel();

            viewModel.AddTimeEntries(new msdyn_timeentry[] { timeEntry1, timeEntry2 });

            viewModel.ClearTimes();
            Assert.AreEqual(0, viewModel.Days.Count);
        }
Пример #2
0
        /// <summary>
        /// Defaults the msdyn_date_utc field of the time entry provided based off the current date filter.
        /// </summary>
        /// <param name="timeEntry">The msdyn_timeentry record to default.</p</param>
        public void DefaultDateFromCurrentFilter(msdyn_timeentry timeEntry)
        {
            DateTime filterLastDate = filter.EndDate;
            DateTime utcToday       = DateTime.UtcNow;

            timeEntry.msdyn_date_utc = DateTime.Compare(filterLastDate, utcToday) > 0 ? utcToday : filterLastDate;
        }
Пример #3
0
        /// <summary>
        /// Save selected Time, if Id is null it will create a new one,
        /// otherwise it will update the selected Time.
        /// </summary>
        /// <returns></returns>
        public override async Tasks.Task <bool> ForcedSave()
        {
            bool            result = false;
            msdyn_timeentry time   = this.Time;

            if (time != null)
            {
                BookableResource bookableResource = await TimeHelper.GetBookableResourceForUser(await this.DataAccess.GetLoggedUserId(true));

                if (TimeHelper.isBookableResourceValid(bookableResource))
                {
                    time.msdyn_bookableresource = new EntityReference(BookableResource.EntityLogicalName, bookableResource.BookableResourceId.GetValueOrDefault());

                    // If Time can't be saved, don't allow the client to save,
                    // return false so user can make the corresponding corrections.
                    if (this.CanTimeBeSaved(time))
                    {
                        // If Time doesn't have an Id, it need to be created
                        if (time.Id == null || time.Id == Guid.Empty)
                        {
                            // Always clear the time entry id when creating a new entry
                            // because CRM validation treats Guid.Empty as an invalid id for a new record.
                            Guid?timeEntryId = await this.DataAccess.Create(time);

                            if (timeEntryId != null && timeEntryId != Guid.Empty)
                            {
                                time.Id = (Guid)timeEntryId;
                                result  = true;
                            }
                            else
                            {
                                result = false;
                            }
                        }
                        else
                        {
                            result = await this.DataAccess.Update(time);
                        }

                        // Update status of Time
                        if (this.HasPendingDataToSave)
                        {
                            this.HasPendingDataToSave = !result;
                        }

                        // If the validation method hasn't thrown an error message but save failed, throw an error message here.
                        if (!result)
                        {
                            await MessageCenter.ShowErrorMessage(AppResources.SaveError);
                        }
                    }
                    else
                    {
                        result = false;
                    }
                }
            }

            return(result);
        }
Пример #4
0
        public void LoadTimesFromMultipleDays()
        {
            DateTime dateTime1 = new DateTime(2015, 7, 28, 9, 58, 0);
            DateTime dateTime2 = new DateTime(2014, 1, 22, 23, 19, 0);

            msdyn_timeentry timeEntry1 = new msdyn_timeentry();

            timeEntry1.msdyn_timeentryId = new Guid();
            timeEntry1.msdyn_description = "entry 1";
            timeEntry1.msdyn_date        = dateTime1;
            timeEntry1.msdyn_duration    = 2;

            msdyn_timeentry timeEntry2 = new msdyn_timeentry();

            timeEntry2.msdyn_timeentryId = new Guid();
            timeEntry2.msdyn_description = "entry 2";
            timeEntry2.msdyn_date        = dateTime2;
            timeEntry2.msdyn_duration    = 2;

            TimeCollectionViewModel viewModel = new TimeCollectionViewModel();

            viewModel.AddTimeEntries(new msdyn_timeentry[] { timeEntry1, timeEntry2 });

            // Validate
            IEnumerable <TimeCollection> days = viewModel.Days;

            Assert.AreEqual(2, days.Count(), "Incorrect number of days");
        }
Пример #5
0
        public void CanMarkTimeEntryAsSelected()
        {
            msdyn_timeentry timeEntry = new msdyn_timeentry();

            timeEntry.Selected = true;
            Assert.IsTrue(timeEntry.Selected);
        }
Пример #6
0
        public async Tasks.Task TimeEntryIDsAreConcatenatedForSubmit()
        {
            string guid1 = "BF65EFF9-89AF-4961-9C73-C178071A06AE";
            string guid2 = "B42423C5-F993-410B-95FC-B3085A91DE4B";

            msdyn_timeentry entry1 = new msdyn_timeentry();

            entry1.Id = Guid.Parse(guid1);
            msdyn_timeentry entry2 = new msdyn_timeentry();

            entry2.Id = Guid.Parse(guid2);

            TimeEntrySubmitter submitter = new TimeEntrySubmitter();

            submitter.addTimeEntry(entry1);
            submitter.addTimeEntry(entry2);

            DataAccessTestable dat = new DataAccessTestable();

            submitter.DataAccess = dat;

            string ids = "";

            dat.addExecuteHandler((OrganizationRequest or) =>
            {
                ids = (string)or.Parameters[TimeEntrySubmitter.TimeEntryIdsParameterName];
            });

            await submitter.ExecuteAction();

            // Validate
            Assert.AreEqual(string.Format("{0},{1}", entry1.Id, entry2.Id), ids);
        }
Пример #7
0
        /// <summary>
        /// Validates if time entry can be saved.
        /// </summary>
        /// <param name="Time">The time entry for which to validate.</param>
        /// <returns>True if the time entry can be saved, false otherwise.</returns>
        public virtual bool CanTimeBeSaved(msdyn_timeentry timeEntry)
        {
            // Check that the date field is filled.
            if (timeEntry.msdyn_date == null)
            {
                MessageCenter.ShowErrorMessage(AppResources.DateInvalidWarning).DoNotAwait();
                return(false);
            }

            // Check that the total duration (including this new time entry) does not exceed 24 hours for a particular day.
            Dictionary <DateTime, int> durationsPerDay = TimeCollectionViewModel.DurationPerDay;
            DateTime date = (DateTime)timeEntry.msdyn_date;  // Use msdyn_date since that is the one stored in the entity.

            if (durationsPerDay.ContainsKey(date))
            {
                // Subtract the selected time entry saved duration for update scenario to prevent double adding the total durations.
                if (this.Time.msdyn_timeentryId != null || this.Time.msdyn_timeentryId != Guid.Empty)
                {
                    durationsPerDay[date] -= (int)this.Time.msdyn_duration;
                }

                if ((durationsPerDay[date] + timeEntry.msdyn_duration) > (24 * 60))
                {
                    MessageCenter.ShowErrorMessage(AppResources.TimeExceeded).DoNotAwait();
                    return(false);
                }
            }

            return(true);
        }
Пример #8
0
        private void initDeleteAction()
        {
            deleteAction = new MenuItem
            {
                Text          = AppResources.Delete,
                IsDestructive = true
            };

            deleteAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));

            deleteAction.Clicked += async(sender, e) =>
            {
                MenuItem mi = (MenuItem)sender;

                msdyn_timeentry time      = (msdyn_timeentry)mi.BindingContext;
                TimeViewModel   model     = new TimeViewModel(time);
                BaseViewModel   viewModel = (BaseViewModel)this.HostPage.BindingContext;

                viewModel.IsBusy = true;
                await model.Delete();

                MessagingCenter.Send <Page>(this.HostPage, Message.RefreshMainPage);
                viewModel.IsBusy = false;
            };
        }
Пример #9
0
        public void TimeEntryDurationValidationTest()
        {
            // Prepare the time entries for test purposes.
            DateTime dateTime = DateTime.Today;

            msdyn_timeentry timeEntry1 = new msdyn_timeentry();

            timeEntry1.msdyn_timeentryId = new Guid();
            timeEntry1.msdyn_description = "entry 1";
            timeEntry1.msdyn_date        = dateTime;
            timeEntry1.msdyn_duration    = 20 * 60; // 20 hours.

            msdyn_timeentry timeEntry2 = new msdyn_timeentry();

            timeEntry2.msdyn_timeentryId = new Guid();
            timeEntry2.msdyn_description = "entry 2";
            timeEntry2.msdyn_date        = dateTime;
            timeEntry2.msdyn_duration    = 4 * 60 + 1; // 4 hours and 1 minute.

            TimeViewModel           entry     = new TimeViewModel(timeEntry1);
            TimeCollectionViewModel viewModel = new TimeCollectionViewModel();

            viewModel.AddTimeEntries(new msdyn_timeentry[] { timeEntry1, timeEntry2 });

            Assert.IsFalse(entry.CanTimeBeSaved(timeEntry1), "The time entry should not be able to save since the total duration is 24:01");

            timeEntry1.msdyn_duration = 19 * 60 + 59;    // 19 hours and 59 minutes.
            Assert.IsTrue(entry.CanTimeBeSaved(timeEntry1), "The time entry should be able to save since the total duration is 24:00");
        }
Пример #10
0
        /// <summary>
        /// Open a new instance of TimeDetailPage.
        /// </summary>
        /// <param name="timeEntry">Time entry to show on the detail page.</param>
        /// <param name="navigation">Navigation to push the page on.</param>
        /// <returns></returns>
        public static async System.Threading.Tasks.Task NavigateToTimeDetailsView(msdyn_timeentry timeEntry, INavigation navigation)
        {
            TimeDetailsPage timeDetailPage = new TimeDetailsPage();
            await navigation.PushAsync(timeDetailPage);

            await timeDetailPage.Initialize(new TimeViewModel(timeEntry));
        }
Пример #11
0
        public void GetNullEntryStatus()
        {
            msdyn_timeentry timeEntry = new msdyn_timeentry();

            // Value is null by default

            Assert.IsNull(timeEntry.EntryStatus);
        }
Пример #12
0
        private void ListView_ItemSelectedMultiSelect(object sender, SelectedItemChangedEventArgs e)
        {
            msdyn_timeentry selectedTime = e.SelectedItem as msdyn_timeentry;

            if (selectedTime != null)
            {
                // Switch selection status
                selectedTime.Selected = !selectedTime.Selected;

                listView.SelectedItem = null;
            }
        }
Пример #13
0
 private void addDurationPerDateToDictionary(msdyn_timeentry entry, DateTime date)
 {
     // If an entry for that day doesn't exist already, create and store the duration.
     if (!DurationPerDay.ContainsKey(date))
     {
         DurationPerDay.Add(date, (int)entry.msdyn_duration);
     }
     // Else, add up the duration with the tally of duration for the day.
     else
     {
         DurationPerDay[date] += (int)entry.msdyn_duration;
     }
 }
Пример #14
0
        public void SetNullEntryStatus()
        {
            msdyn_timeentry timeEntry = new msdyn_timeentry();

            //Submitted = 192350003,
            timeEntry.msdyn_entryStatus = new Microsoft.Xrm.Sdk.Samples.OptionSetValue(192350003);

            // Change to Null
            timeEntry.EntryStatus = null;

            // Validate
            Assert.IsNull(timeEntry.EntryStatus);
        }
Пример #15
0
        public void EntryStatusGetTest()
        {
            msdyn_timeentry timeEntry = new msdyn_timeentry();

            // Check msdyn_timeentry_msdyn_entrystatus.cs for values
            //Approved = 192350002,
            //Returned = 192350001,
            //Draft = 192350000,
            //Submitted = 192350003,
            timeEntry.msdyn_entryStatus = new Microsoft.Xrm.Sdk.Samples.OptionSetValue(192350000);

            Assert.AreEqual(msdyn_timeentry_msdyn_entrystatus.Draft, timeEntry.EntryStatus);
        }
Пример #16
0
        public void SetDefaultValuesOnlyWorksOnNewEntries()
        {
            msdyn_timeentry timeEntry = new msdyn_timeentry();
            TimeViewModel   entry     = new TimeViewModel(timeEntry);

            timeEntry.Id = Guid.NewGuid();
            entry.SetDefaultValues();

            Assert.IsNull(timeEntry.msdyn_date);
            Assert.IsNull(timeEntry.msdyn_duration);
            Assert.IsNull(timeEntry.msdyn_type);
            Assert.IsNull(timeEntry.msdyn_entryStatus);
        }
Пример #17
0
        private async void ListView_ItemSelectedNormal(object sender, SelectedItemChangedEventArgs e)
        {
            // async void is OK here, since this is a top level event handler
            msdyn_timeentry selectedTime = e.SelectedItem as msdyn_timeentry;

            if (selectedTime != null)
            {
                await this.NavigateToTimeDetailsView(selectedTime);

                // Deselect the item
                listView.SelectedItem = null;
            }
        }
Пример #18
0
        public void SetDefaultValuesTest()
        {
            msdyn_timeentry timeEntry = new msdyn_timeentry();
            TimeViewModel   entry     = new TimeViewModel(timeEntry);
            DateTime        todayUTC  = DateTime.Today;

            entry.SetDefaultValues();

            // validate entry data
            Assert.AreEqual(new DateTime(todayUTC.Year, todayUTC.Month, todayUTC.Day, 12, 0, 0), timeEntry.msdyn_date, "Incorrect default date of noon today.");
            Assert.AreEqual(60, timeEntry.msdyn_duration, "Incorrect default duration");
            Assert.AreEqual((int)msdyn_timeentrytype.Work, timeEntry.msdyn_type.Value, "Incorrect default time entry type");
            Assert.AreEqual((int)msdyn_timeentry_msdyn_entrystatus.Draft, timeEntry.msdyn_entryStatus.Value, "Incorrect default time entry status");
        }
Пример #19
0
        public void CanEditTimeEntryTest()
        {
            msdyn_timeentry timeEntry = new msdyn_timeentry();
            TimeViewModel   entry     = new TimeViewModel(timeEntry);

            Assert.IsTrue(entry.CanEdit(), "A time entry that hasn't been saved (has null values) should be editable.");

            timeEntry.Id = Guid.NewGuid();
            entry.SetDefaultValues();
            Assert.IsTrue(entry.CanEdit(), "A time entry that has been saved with values should be editable.");

            timeEntry.msdyn_entryStatus = new OptionSetValue((int)msdyn_timeentry_msdyn_entrystatus.Submitted);
            Assert.IsFalse(entry.CanEdit(), "A time entry that has been submitted with values should be editable.");
        }
Пример #20
0
        public async Tasks.Task DefaultDateFromCurrentFilter()
        {
            msdyn_timeentry timeEntry = new msdyn_timeentry();
            // Today - the day of the week (gives sunday) + 7 = Sunday next week.
            DateTime expectedDate = DateTime.Today - TimeSpan.FromDays((int)DateTime.Today.DayOfWeek) + TimeSpan.FromDays(7);

            // Act.
            TimeCollectionViewModel viewModel = new TimeCollectionViewModel();

            viewModel.DataAccess = new DataAccessTestable();
            await viewModel.IncrementDateFilter();

            // Assert.
            viewModel.DefaultDateFromCurrentFilter(timeEntry);
        }
Пример #21
0
        /// <summary>
        /// Recall a time entry.
        /// </summary>
        /// <returns></returns>
        public virtual async Tasks.Task <bool> Recall()
        {
            msdyn_timeentry time = this.Time;

            if (!this.IsSubmitted())
            {
                return(false);
            }

            TimeEntryRecaller recaller = new TimeEntryRecaller();

            recaller.DataAccess = this.DataAccess;
            recaller.addTimeEntry(time);

            return(await recaller.ExecuteAction());
        }
Пример #22
0
        private void addTimeEntryWithDateToTimeCollection(msdyn_timeentry entry, DateTime date)
        {
            TimeCollection timeCollection;

            // Get or create the correct TimeCollection
            if (this.timesToDays.ContainsKey(date))
            {
                timeCollection = this.timesToDays[date];
            }
            else
            {
                timeCollection = new TimeCollection(date);
                this.timesToDays.Add(date, timeCollection);
            }

            timeCollection.Add(entry);
        }
Пример #23
0
        /// <summary>
        /// If the Time is not yet created, just delete from memory. otherwise delete from server
        /// </summary>
        /// <param name="omitWarningMessage">True if deletion would happen without a confirmation from the user</param>
        /// <returns>True if the Time was deleted</returns>
        public async Tasks.Task <bool> Delete(bool omitWarningMessage = false)
        {
            msdyn_timeentry time = this.Time;

            if (time != null)
            {
                if (time.Id != Guid.Empty && this.CanEdit())
                {
                    if (omitWarningMessage || await MessageCenter.ShowDialog(AppResources.DeleteWarningTime, null, null))
                    {
                        return(await this.DataAccess.Delete(time.LogicalName, time.Id));
                    }
                    return(false);
                }
                return(true);
            }
            return(false);
        }
Пример #24
0
        public void EntryStatusSetTest()
        {
            // Change a Submitted to Returned and validate

            // Create a submitted entry
            msdyn_timeentry timeEntry = new msdyn_timeentry();

            //Submitted = 192350003,
            timeEntry.msdyn_entryStatus = new Microsoft.Xrm.Sdk.Samples.OptionSetValue(192350003);

            // Change to Returned
            //Returned = 192350001,
            timeEntry.EntryStatus = msdyn_timeentry_msdyn_entrystatus.Returned;

            // Validate
            //Returned = 192350001,
            Assert.AreEqual(new Microsoft.Xrm.Sdk.Samples.OptionSetValue(192350001).Value, timeEntry.msdyn_entryStatus.Value);
        }
        /// <summary>
        /// Returns the title string given the time entry
        /// </summary>
        /// <param name="value">msdyn_timeentrytype</param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns>title string</returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            msdyn_timeentry time = value as msdyn_timeentry;

            if (time == null)
            {
                return(string.Empty);
            }
            else if (time.msdyn_project != null && time.msdyn_project.Name != null)
            {
                return(time.msdyn_project.Name);
            }
            else
            {
                msdyn_timeentrytype currentValue = (msdyn_timeentrytype)Enum.ToObject(typeof(msdyn_timeentrytype), time.msdyn_type.Value);
                return(currentValue.ToString());
            }
        }
Пример #26
0
        public async Tasks.Task SubmitMarksEntriesAsSubmitted()
        {
            DataAccessTestable dat       = new DataAccessTestable();
            TimeEntrySubmitter submitter = new TimeEntrySubmitter();

            submitter.DataAccess = dat;

            msdyn_timeentry entry = new msdyn_timeentry();

            submitter.addTimeEntry(entry);

            dat.addExecuteHandler((OrganizationRequest or) =>
            {
                entry.msdyn_entryStatus = new OptionSetValue((int)msdyn_timeentry_msdyn_entrystatus.Submitted);
            });

            await submitter.ExecuteAction();

            Assert.AreEqual((int)msdyn_timeentry_msdyn_entrystatus.Submitted, entry.msdyn_entryStatus.Value);
        }
        /// <summary>
        /// Returns the icon given the entry type
        /// </summary>
        /// <param name="value">msdyn_timeentrytype</param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns>Icon based on expense type</returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Color result = Color.FromHex("7F7F7F");

            if (value == null)
            {
                return(result);
            }

            msdyn_timeentry time = value as msdyn_timeentry;

            if ((msdyn_timeentrytype)time.msdyn_type.Value == msdyn_timeentrytype.Work &&
                time.msdyn_project != null &&
                time.msdyn_project.Id != null)
            {
                result = GetColor(GetIndexWithProjectGUID(time.msdyn_project.Id.Value, culture.NumberFormat));
            }

            return(result);
        }
Пример #28
0
        /// <summary>
        /// Submit the time entry.
        /// </summary>
        /// <returns>true if the submission succeeded; otherwise, false.</returns>
        public virtual async Tasks.Task <bool> Submit()
        {
            if (this.CanEdit())
            {
                msdyn_timeentry time   = this.Time;
                bool            result = await this.Save();

                if (result)
                {
                    TimeEntrySubmitter submitter = new TimeEntrySubmitter();
                    submitter.DataAccess = this.DataAccess;
                    submitter.addTimeEntry(this.Time);

                    return(await submitter.ExecuteAction());
                }
                else
                {
                    await MessageCenter.ShowErrorMessage(AppResources.SaveError);
                }
            }
            return(false);
        }
Пример #29
0
        /// <summary>
        /// Adds a button to create new time entries.
        /// </summary>
        private void addCreateNewTimeButton()
        {
            if (null == createNewTimeButton)
            {
                createNewTimeButton = ToolbarHelper.createAddTimeEntryButton();

                createNewTimeButton.Clicked += async(sender, args) =>
                {
                    msdyn_timeentry timeEntry = new msdyn_timeentry();

                    // Create a time entry using the current month and navigate to details page.
                    if (this.viewModel != null)
                    {
                        this.viewModel.DefaultDateFromCurrentFilter(timeEntry);
                    }

                    await NavigateToTimeDetailsView(timeEntry);
                };
            }

            this.ToolbarItems.Add(createNewTimeButton);
        }
Пример #30
0
        protected override void OnBindingContextChanged()
        {
            base.OnBindingContextChanged();
            msdyn_timeentry time = (msdyn_timeentry)this.BindingContext;

            if (time == null)
            {
                return;
            }

            msdyn_timeentry_msdyn_entrystatus?status = time.EntryStatus;

            if (status != null)
            {
                if (status == msdyn_timeentry_msdyn_entrystatus.Submitted)
                {
                    moreAction.Text = AppResources.Recall;
                }
                else
                {
                    moreAction.Text = AppResources.Submit;
                }
            }

            if (status == msdyn_timeentry_msdyn_entrystatus.Draft)
            {
                if (!this.ContextActions.Contains(deleteAction))
                {
                    this.ContextActions.Add(deleteAction);
                }
            }
            else
            {
                if (this.ContextActions.Contains(deleteAction))
                {
                    this.ContextActions.Remove(deleteAction);
                }
            }
        }