|
|
@@ -24,8 +24,11 @@ using SelectionChangedEventArgs = System.Windows.Controls.SelectionChangedEventA
|
|
|
using PRS.Shared;
|
|
|
using Columns = InABox.Core.Columns;
|
|
|
using InABox.Wpf;
|
|
|
+using MYOB.AccountRight.SDK.Extensions;
|
|
|
using Syncfusion.Data.Extensions;
|
|
|
using NPOI.OpenXmlFormats.Spreadsheet;
|
|
|
+using Syncfusion.UI.Xaml.Scheduler;
|
|
|
+using Color = System.Drawing.Color;
|
|
|
|
|
|
namespace PRSDesktop;
|
|
|
|
|
|
@@ -1233,4 +1236,226 @@ public partial class JobResourcePlanner : UserControl
|
|
|
AssignedEmployees.Items = AssignedEmployees.Items.OrderBy(x => x.Name).ToList();
|
|
|
}
|
|
|
|
|
|
+ private void Data_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
|
+ {
|
|
|
+ Settings.Visibility = Data.SelectedTab == JobView
|
|
|
+ ? Visibility.Visible
|
|
|
+ : Visibility.Collapsed;
|
|
|
+ }
|
|
|
+
|
|
|
+ ScheduleAppointmentCollection appointments = new();
|
|
|
+
|
|
|
+ private void Schedule_OnQueryAppointments(object? sender, QueryAppointmentsEventArgs e)
|
|
|
+ {
|
|
|
+ appointments.Clear();
|
|
|
+ var cols = Columns.Required<JobStage>()
|
|
|
+ .Add(x => x.ID)
|
|
|
+ .Add(x => x.StartDate)
|
|
|
+ .Add(x => x.EndDate)
|
|
|
+ .Add(x=>x.Name)
|
|
|
+ .Add(x => x.Job.ID)
|
|
|
+ .Add(x => x.Job.JobNumber)
|
|
|
+ .Add(x => x.Job.Name)
|
|
|
+ .Add(x => x.Type.ID)
|
|
|
+ .Add(x => x.Type.Color)
|
|
|
+ .Add(x => x.Type.Description)
|
|
|
+ .Add(x => x.Type.Color)
|
|
|
+ .Add(x=>x.Calendar.ID)
|
|
|
+ .Add(x=>x.Calendar.Name)
|
|
|
+ .Add(x=>x.Calendar.Monday)
|
|
|
+ .Add(x=>x.Calendar.Tuesday)
|
|
|
+ .Add(x=>x.Calendar.Wednesday)
|
|
|
+ .Add(x=>x.Calendar.Thursday)
|
|
|
+ .Add(x=>x.Calendar.Friday)
|
|
|
+ .Add(x=>x.Calendar.Saturday)
|
|
|
+ .Add(x=>x.Calendar.Sunday)
|
|
|
+ .Add(x => x.Apprentices)
|
|
|
+ .Add(x=>x.ApprenticeHours)
|
|
|
+ .Add(x=>x.Supervisors)
|
|
|
+ .Add(x=>x.SupervisionHours)
|
|
|
+ .Add(x=>x.Tradespersons)
|
|
|
+ .Add(x=>x.TradesHours);
|
|
|
+
|
|
|
+ var stages = Client.Query<JobStage>(
|
|
|
+ new Filter<JobStage>(x => x.StartDate).IsLessThanOrEqualTo(e.VisibleDateRange.ActualEndDate)
|
|
|
+ .And(x => x.EndDate).IsGreaterThanOrEqualTo(e.VisibleDateRange.ActualStartDate),
|
|
|
+ cols
|
|
|
+ ).ToObjects<JobStage>()
|
|
|
+ .ToArray();
|
|
|
+
|
|
|
+ foreach (var stage in stages)
|
|
|
+ CreateAppointment(stage);
|
|
|
+ Schedule.ItemsSource = appointments;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void CreateAppointment(JobStage stage)
|
|
|
+ {
|
|
|
+ var model = new StageModel(stage);
|
|
|
+ appointments.Add(model);
|
|
|
+ }
|
|
|
+
|
|
|
+ private class StageModel : ScheduleAppointment
|
|
|
+ {
|
|
|
+
|
|
|
+ public StageModel(JobStage stage)
|
|
|
+ {
|
|
|
+ Stage = stage;
|
|
|
+ }
|
|
|
+
|
|
|
+ private JobStage _stage;
|
|
|
+ public JobStage Stage
|
|
|
+ {
|
|
|
+ get => _stage;
|
|
|
+ set
|
|
|
+ {
|
|
|
+ _stage = value;
|
|
|
+ Reload();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Reload()
|
|
|
+ {
|
|
|
+ var color = !string.IsNullOrWhiteSpace(_stage.Type.Color)
|
|
|
+ ? (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString(_stage.Type.Color)
|
|
|
+ : Colors.Transparent;
|
|
|
+
|
|
|
+ StartTime = _stage.StartDate;
|
|
|
+ EndTime = _stage.EndDate;
|
|
|
+ IsAllDay = true;
|
|
|
+ AppointmentBackground = new SolidColorBrush(color);
|
|
|
+ Foreground = new SolidColorBrush(color.GetForegroundColor());
|
|
|
+ Subject = $"{_stage.Job.JobNumber}: {_stage.Job.Name}";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Schedule_AppointmentEditorOpening(object? sender, AppointmentEditorOpeningEventArgs e)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ void CreateMenu<T>(ItemsControl menu, CalendarMenuName name, string header, Action<T?>? action, T data)
|
|
|
+ {
|
|
|
+ var item = new MenuItem();
|
|
|
+ item.Name = name.ToString();
|
|
|
+ item.Header = header;
|
|
|
+ if (action != null)
|
|
|
+ item.Click += (o,args) => action(data);
|
|
|
+ menu.Items.Add(item);
|
|
|
+ }
|
|
|
+
|
|
|
+ private StageModel? _copiedModel;
|
|
|
+
|
|
|
+
|
|
|
+ private void CreateJobStage(JobStageType type)
|
|
|
+ {
|
|
|
+ if (Schedule.SelectedDate is null)
|
|
|
+ return;
|
|
|
+
|
|
|
+ var stage = new JobStage
|
|
|
+ {
|
|
|
+ StartDate = Schedule.SelectedDate.Value,
|
|
|
+ EndDate = Schedule.SelectedDate.Value,
|
|
|
+ Name = type.Description
|
|
|
+ };
|
|
|
+ stage.Type.CopyFrom(type);
|
|
|
+ if (new JobStagesGrid().EditItems([stage]))
|
|
|
+ {
|
|
|
+ CreateAppointment(stage);
|
|
|
+ _copiedModel = null;
|
|
|
+ }
|
|
|
+ if (!types?.Any(x => x.ID == stage.Type.ID) == false)
|
|
|
+ types = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void EditJobStage(StageModel? stage)
|
|
|
+ {
|
|
|
+ if (stage is null)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (new JobStagesGrid().EditItems([stage.Stage]))
|
|
|
+ {
|
|
|
+ stage.Reload();
|
|
|
+ _copiedModel = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void DeleteJobStage(StageModel? stage)
|
|
|
+ {
|
|
|
+ if (stage is null)
|
|
|
+ return;
|
|
|
+ //Schedule.ItemsSource = null;
|
|
|
+ appointments.Remove(stage);
|
|
|
+ new Client<JobStage>().Delete(stage.Stage,"Deleted from Project Planner");
|
|
|
+ _copiedModel = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void CopyJobStage(StageModel? stage)
|
|
|
+ {
|
|
|
+ _copiedModel = stage;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void PasteJobStage(StageModel? stage)
|
|
|
+ {
|
|
|
+ if (stage is null || Schedule.SelectedDate is null)
|
|
|
+ return;
|
|
|
+ var newstage = stage.Stage.Clone();
|
|
|
+ newstage.ID = Guid.Empty;
|
|
|
+ newstage.OriginalValues?.TryRemove("ID", out _);
|
|
|
+
|
|
|
+ var span = newstage.EndDate - newstage.StartDate;
|
|
|
+ newstage.StartDate = Schedule.SelectedDate.Value;
|
|
|
+ newstage.EndDate = newstage.StartDate + span;
|
|
|
+
|
|
|
+ new Client<JobStage>().Save(newstage,"Created from Project Planner");
|
|
|
+ CreateAppointment(newstage);
|
|
|
+ _copiedModel = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<JobStageType>? types;
|
|
|
+
|
|
|
+ private void Schedule_OnSchedulerContextMenuOpening(object? sender, SchedulerContextMenuOpeningEventArgs e)
|
|
|
+ {
|
|
|
+ e.ContextMenu.Items.Clear();
|
|
|
+ if ((e.MenuType == SchedulerContextMenuType.Appointment) && (e.MenuInfo.Appointment is StageModel model))
|
|
|
+ {
|
|
|
+ CreateMenu(e.ContextMenu, CalendarMenuName.Edit, "Edit Booking", EditJobStage, model);
|
|
|
+ CreateMenu(e.ContextMenu, CalendarMenuName.Copy, "Copy Booking", CopyJobStage, model);
|
|
|
+ e.ContextMenu.Items.Add(new Separator());
|
|
|
+ CreateMenu(e.ContextMenu, CalendarMenuName.Edit, "Delete Booking", DeleteJobStage, model);
|
|
|
+ }
|
|
|
+ else if (e.MenuType == SchedulerContextMenuType.MonthCell)
|
|
|
+ {
|
|
|
+ types ??= new Client<JobStageType>().Query(null, Columns.All<JobStageType>()).ToList<JobStageType>();
|
|
|
+ if (types.Any())
|
|
|
+ {
|
|
|
+ var header = new MenuItem() { Header = "Create Booking..." };
|
|
|
+ foreach (var type in types)
|
|
|
+ CreateMenu(header, CalendarMenuName.CreateNew, type.Description, CreateJobStage, type);
|
|
|
+ e.ContextMenu.Items.Add(header);
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ CreateMenu(e.ContextMenu, CalendarMenuName.CreateNew, "Create Booking", CreateJobStage, new JobStageType());
|
|
|
+
|
|
|
+ if (_copiedModel != null)
|
|
|
+ {
|
|
|
+ e.ContextMenu.Items.Add(new Separator());
|
|
|
+ CreateMenu(e.ContextMenu, CalendarMenuName.Paste, "Paste Booking", PasteJobStage, _copiedModel);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void Schedule_OnAppointmentDropping(object? sender, AppointmentDroppingEventArgs e)
|
|
|
+ {
|
|
|
+ if (e.Appointment is StageModel model)
|
|
|
+ {
|
|
|
+ var duration = model.Stage.EndDate - model.Stage.StartDate;
|
|
|
+ model.Stage.StartDate = e.DropTime;
|
|
|
+ model.Stage.EndDate = e.DropTime + duration;
|
|
|
+ model.Reload();
|
|
|
+ new Client<JobStage>().Save(model.Stage,"Reallocated By Project Planner", (o,e) => { });
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|