|
@@ -138,6 +138,12 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
EmployeeSelector.Settings = Properties.EmployeeSettings;
|
|
|
EmployeeSelector.Selection = Properties.EmployeeSelection;
|
|
|
|
|
|
+ ViewType.ItemsSource = Enum.GetValues<EmployeeResourcePlannerViewType>()
|
|
|
+ .Select(x => new KeyValuePair<EmployeeResourcePlannerViewType, string>(x, x.ToString()));
|
|
|
+ ViewType.SelectedValuePath = "Key";
|
|
|
+ ViewType.DisplayMemberPath = "Value";
|
|
|
+ ViewType.SelectedValue = Properties.ViewType;
|
|
|
+
|
|
|
LeaveType.SelectedIndex = Properties.IncludeUnApprovedLeave ? 1 : 0;
|
|
|
|
|
|
FromDate.DateTime = DateTime.Today;
|
|
@@ -186,6 +192,15 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
{
|
|
|
}
|
|
|
|
|
|
+ private TimeSpan GetPeriod()
|
|
|
+ {
|
|
|
+ return Properties.ViewType switch
|
|
|
+ {
|
|
|
+ EmployeeResourcePlannerViewType.Week => TimeSpan.FromDays(7),
|
|
|
+ EmployeeResourcePlannerViewType.Day or _ => TimeSpan.FromDays(1)
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
public void Refresh()
|
|
|
{
|
|
|
using (new WaitCursor())
|
|
@@ -197,11 +212,18 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
DateTime todate = ToDate.DateTime.HasValue ? ToDate.DateTime.Value.Date : DateTime.Today.AddYears(1);
|
|
|
|
|
|
MultiQuery query = new MultiQuery();
|
|
|
+
|
|
|
+ var period = GetPeriod();
|
|
|
+ if(Properties.ViewType == EmployeeResourcePlannerViewType.Week)
|
|
|
+ {
|
|
|
+ fromdate = fromdate.AddDays(-(((int)fromdate.DayOfWeek - 1) % 7));
|
|
|
+ todate = todate.AddDays(-(((int)todate.DayOfWeek - 1) % 7));
|
|
|
+ }
|
|
|
|
|
|
query.Add<Assignment>(
|
|
|
new Filter<Assignment>(x => x.EmployeeLink.ID).InList(empids)
|
|
|
.And(x => x.Date).IsGreaterThanOrEqualTo(fromdate)
|
|
|
- .And(x => x.Date).IsLessThanOrEqualTo(todate),
|
|
|
+ .And(x => x.Date).IsLessThanOrEqualTo(todate + period),
|
|
|
AssignmentModel.Columns,
|
|
|
new SortOrder<Assignment>(x => x.EmployeeLink.ID).ThenBy(x => x.Date).ThenBy(x => x.Booked.Duration, SortDirection.Descending)
|
|
|
);
|
|
@@ -212,6 +234,13 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
var assignments = query.Get<Assignment>().Rows.Select(r => new AssignmentModel(r)).ToArray();
|
|
|
|
|
|
var data = new DataTable();
|
|
|
+
|
|
|
+ var standardHours = Properties.ViewType switch
|
|
|
+ {
|
|
|
+ EmployeeResourcePlannerViewType.Week => 38.0,
|
|
|
+ EmployeeResourcePlannerViewType.Day or _ => 7.5
|
|
|
+ };
|
|
|
+
|
|
|
if(Settings.DisplayMode == EmployeePlannerDisplayMode.EmployeeColumns)
|
|
|
{
|
|
|
data.Columns.Add("Date", typeof(DateTime));
|
|
@@ -221,7 +250,7 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
data.Columns.Add(employee.ID.ToString(), typeof(object));
|
|
|
}
|
|
|
|
|
|
- for (var curdate = fromdate; curdate <= todate; curdate = curdate.AddDays(1))
|
|
|
+ for (var curdate = fromdate; curdate <= todate; curdate += period)
|
|
|
{
|
|
|
var leavevalue = GetStandardLeave(curdate, _standardleaves);
|
|
|
var values = new List<object> { curdate };
|
|
@@ -229,10 +258,10 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
{
|
|
|
var value = new EmployeeResourcePlannerValue();
|
|
|
// Note use of short-circuiting here.
|
|
|
- var bOK = CheckAssignments(employee, curdate, assignments, value)
|
|
|
- || CheckRoster(employee, curdate, value)
|
|
|
+ var bOK = CheckAssignments(employee, curdate, curdate + period, assignments, value)
|
|
|
|| CheckStandardLeave(leavevalue, value)
|
|
|
- || CheckLeaveRequest(employee, curdate, _leaverequests, value);
|
|
|
+ || CheckLeaveRequest(employee, curdate, curdate + period, _leaverequests, value)
|
|
|
+ || CheckRoster(employee, curdate, curdate + period, standardHours, value);
|
|
|
|
|
|
values.Add(value);
|
|
|
}
|
|
@@ -245,7 +274,7 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
data.Columns.Add("Employee", typeof(object));
|
|
|
|
|
|
var dates = new List<DateTime>();
|
|
|
- for (var curdate = fromdate; curdate <= todate; curdate = curdate.AddDays(1))
|
|
|
+ for (var curdate = fromdate; curdate <= todate; curdate += period)
|
|
|
{
|
|
|
data.Columns.Add(dates.Count.ToString(), typeof(object));
|
|
|
dates.Add(curdate);
|
|
@@ -255,14 +284,14 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
foreach (var employee in _employees)
|
|
|
{
|
|
|
var values = new List<object> { employee };
|
|
|
- for (var curdate = fromdate; curdate <= todate; curdate = curdate.AddDays(1))
|
|
|
+ for (var curdate = fromdate; curdate <= todate; curdate += period)
|
|
|
{
|
|
|
var leavevalue = GetStandardLeave(curdate, _standardleaves);
|
|
|
var value = new EmployeeResourcePlannerValue();
|
|
|
- var bOK = CheckAssignments(employee, curdate, assignments, value);
|
|
|
- bOK = bOK || CheckRoster(employee, curdate, value);
|
|
|
- bOK = bOK || CheckStandardLeave(leavevalue, value);
|
|
|
- bOK = bOK || CheckLeaveRequest(employee, curdate, _leaverequests, value);
|
|
|
+ var bOK = CheckAssignments(employee, curdate, curdate + period, assignments, value)
|
|
|
+ || CheckStandardLeave(leavevalue, value)
|
|
|
+ || CheckLeaveRequest(employee, curdate, curdate + period, _leaverequests, value)
|
|
|
+ || CheckRoster(employee, curdate, curdate + period, standardHours, value);
|
|
|
|
|
|
values.Add(value);
|
|
|
}
|
|
@@ -276,16 +305,16 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static bool CheckAssignments(EmployeeResourceModel employee, DateTime curdate, AssignmentModel[] assignments, EmployeeResourcePlannerValue value)
|
|
|
+ private static bool CheckAssignments(EmployeeResourceModel employee, DateTime from, DateTime to, AssignmentModel[] assignments, EmployeeResourcePlannerValue value)
|
|
|
{
|
|
|
- var dateAssignments = assignments.Where(x => (x.EmployeeID == employee.ID) && (x.Date == curdate.Date)).ToArray();
|
|
|
+ var dateAssignments = assignments.Where(x => (x.EmployeeID == employee.ID) && (x.Date >= from.Date && x.Date < to.Date)).ToArray();
|
|
|
if (dateAssignments.Length == 0)
|
|
|
return false;
|
|
|
|
|
|
value.IDs = assignments.Select(x => x.ID).ToArray();
|
|
|
value.Text = dateAssignments.Length == 1
|
|
|
? (dateAssignments[0].ID != Guid.Empty ? (dateAssignments[0].JobNumber ?? "") : "XX")
|
|
|
- : $"{dateAssignments.Length} jobs";
|
|
|
+ : $"{dateAssignments.Select(x => x.JobID).Distinct().Count()} jobs";
|
|
|
value.Assignments = dateAssignments;
|
|
|
|
|
|
value.Color = Colors.LightGreen.ToString();
|
|
@@ -293,24 +322,38 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- private static bool CheckRoster(EmployeeResourceModel employee, DateTime curdate, EmployeeResourcePlannerValue value)
|
|
|
+ private static bool CheckRoster(EmployeeResourceModel employee, DateTime from, DateTime to, double standardHours, EmployeeResourcePlannerValue value)
|
|
|
{
|
|
|
value.Text = "";
|
|
|
- var roster = RosterUtils.GetRoster(employee.Roster, employee.Start, curdate);
|
|
|
|
|
|
- var color1 = Colors.LightGray;
|
|
|
- var color2 = Colors.LightGray;
|
|
|
- if (roster?.Enabled == true)
|
|
|
+ var totalRostered = 0.0;
|
|
|
+
|
|
|
+ for(var date = from; date < to; date = date.AddDays(1))
|
|
|
{
|
|
|
- color1 = Colors.LightYellow;
|
|
|
- if (roster.Duration >= 5.0F)
|
|
|
- color2 = Colors.LightYellow;
|
|
|
+ var roster = RosterUtils.GetRoster(employee.Roster, employee.RosterStart, date);
|
|
|
+ if(roster?.Enabled == true)
|
|
|
+ {
|
|
|
+ totalRostered += roster.Duration;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- value.Foreground = new SolidColorBrush(ImageUtils.GetForegroundColor(ImageUtils.MixColors(color1, 0.5, color2))) { Opacity = 0.8 };
|
|
|
- value.Background = new LinearGradientBrush(color1,color2,90.0F) { Opacity = 0.8 };
|
|
|
+ var color1 = Colors.LightGray;
|
|
|
+ var color2 = Colors.LightYellow;
|
|
|
+
|
|
|
+ var percent = Math.Min(totalRostered / standardHours, 1.0);
|
|
|
+
|
|
|
+ value.Foreground = new SolidColorBrush(ImageUtils.MixColors(color1, 1 - percent, color2)) { Opacity = 0.8 };
|
|
|
|
|
|
- return roster?.Enabled == false;
|
|
|
+ var brush = new LinearGradientBrush { Opacity = 0.8 };
|
|
|
+ brush.StartPoint = new Point(0,0);
|
|
|
+ brush.GradientStops.Add(new GradientStop(Colors.LightYellow, 0.0));
|
|
|
+ brush.GradientStops.Add(new GradientStop(ImageUtils.MixColors(Colors.LightYellow, percent, Colors.LightGray), percent));
|
|
|
+ brush.GradientStops.Add(new GradientStop(Colors.LightGray, 1.0));
|
|
|
+ brush.EndPoint = new Point(1,0);
|
|
|
+
|
|
|
+ value.Background = brush;
|
|
|
+
|
|
|
+ return totalRostered.IsEffectivelyEqual(0.0);
|
|
|
}
|
|
|
|
|
|
private static EmployeeResourcePlannerValue? GetStandardLeave(DateTime curdate, StandardLeaveModel[] standardleaves)
|
|
@@ -333,12 +376,12 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- private bool CheckLeaveRequest(EmployeeResourceModel employee, DateTime curdate, LeaveRequestModel[] leaverequests, EmployeeResourcePlannerValue value)
|
|
|
+ private bool CheckLeaveRequest(EmployeeResourceModel employee, DateTime from, DateTime to, LeaveRequestModel[] leaverequests, EmployeeResourcePlannerValue value)
|
|
|
{
|
|
|
var leaverequest = leaverequests.FirstOrDefault(c =>
|
|
|
(c.EmployeeID == employee.ID)
|
|
|
- && (c.From <= curdate)
|
|
|
- && (c.To.Add(c.ToTime) > curdate)
|
|
|
+ && (c.From < to)
|
|
|
+ && (c.To.Add(c.ToTime) >= from)
|
|
|
&& (Properties.IncludeUnApprovedLeave || c.Status == LeaveRequestStatus.Approved));
|
|
|
|
|
|
if (leaverequest == null)
|
|
@@ -592,6 +635,8 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
var items = new List<Guid>();
|
|
|
from = DateTime.MaxValue;
|
|
|
to = DateTime.MinValue;
|
|
|
+
|
|
|
+ var period = GetPeriod();
|
|
|
foreach (var cell in dataGrid.GetSelectedCells())
|
|
|
{
|
|
|
var row = (cell.RowData as DataRowView)!;
|
|
@@ -625,8 +670,8 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
{
|
|
|
if (date < from)
|
|
|
from = date;
|
|
|
- if (date > to)
|
|
|
- to = date;
|
|
|
+ if (date + period > to)
|
|
|
+ to = date + period;
|
|
|
}
|
|
|
|
|
|
foreach(var id in (row[binding.Path.Path] as EmployeeResourcePlannerValue)!.IDs)
|
|
@@ -648,17 +693,17 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
var updates = new List<Assignment>();
|
|
|
foreach (var id in ids)
|
|
|
{
|
|
|
- for (DateTime curdate = from; curdate <= to; curdate = curdate.AddDays(1))
|
|
|
+ for (DateTime curdate = from; curdate < to; curdate = curdate.AddDays(1))
|
|
|
{
|
|
|
var employee = _employees.FirstOrDefault(x => x.ID == id);
|
|
|
if (employee != null)
|
|
|
{
|
|
|
bool bAvail =
|
|
|
(GetStandardLeave(curdate, _standardleaves) == null)
|
|
|
- && !CheckLeaveRequest(employee, curdate, _leaverequests, new EmployeeResourcePlannerValue());
|
|
|
+ && !CheckLeaveRequest(employee, curdate, curdate.AddDays(1), _leaverequests, new EmployeeResourcePlannerValue());
|
|
|
|
|
|
- var roster = bAvail ? RosterUtils.GetRoster(employee.Roster, employee.Start, curdate) : null;
|
|
|
- if (roster?.Enabled == true)
|
|
|
+ var roster = bAvail ? RosterUtils.GetRoster(employee.Roster, employee.RosterStart, curdate) : null;
|
|
|
+ if (roster?.Enabled == true && roster.Finish > roster.Start)
|
|
|
{
|
|
|
var assign = new Assignment();
|
|
|
assign.Date = curdate;
|
|
@@ -671,7 +716,7 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
updates.Add(assign);
|
|
|
}
|
|
|
|
|
|
- if (roster?.SplitShift == true)
|
|
|
+ if (roster?.SplitShift == true && roster.Finish2 > roster.Start2)
|
|
|
{
|
|
|
var assign = new Assignment();
|
|
|
assign.Date = curdate;
|
|
@@ -736,6 +781,15 @@ public partial class EmployeeResourcePlanner : UserControl, IPropertiesPanel<Emp
|
|
|
Refresh();
|
|
|
}
|
|
|
|
|
|
+ private void ViewType_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
|
+ {
|
|
|
+ if (EventSuppressor.IsSet(Suppress.This))
|
|
|
+ return;
|
|
|
+ Properties.ViewType = (EmployeeResourcePlannerViewType)ViewType.SelectedValue;
|
|
|
+ DoSaveSettings();
|
|
|
+ Refresh();
|
|
|
+ }
|
|
|
+
|
|
|
private void LeaveType_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
|
{
|
|
|
if (EventSuppressor.IsSet(Suppress.This))
|