TimesheetWidget.xaml.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Linq;
  5. using System.Windows.Controls;
  6. using Comal.Classes;
  7. using InABox.Clients;
  8. using InABox.Configuration;
  9. using InABox.Core;
  10. using PRSDesktop.WidgetGroups;
  11. namespace PRSDesktop
  12. {
  13. public class TimesheetWidgetProperties : IUserConfigurationSettings, IDashboardProperties { }
  14. public class TimesheetWidgetElement : DashboardElement<TimesheetWidget, HumanResources, TimesheetWidgetProperties> { }
  15. /// <summary>
  16. /// Interaction logic for TimesheetWidget.xaml
  17. /// </summary>
  18. public partial class TimesheetWidget : UserControl, IDashboardWidget<HumanResources, TimesheetWidgetProperties>
  19. {
  20. private DateTime _date = DateTime.Today;
  21. private Guid _groupid = CoreUtils.FullGuid;
  22. private CoreTable activities;
  23. private CoreTable employees;
  24. private readonly DataTable report = new();
  25. private CoreTable timesheets;
  26. public TimesheetWidget()
  27. {
  28. InitializeComponent();
  29. report.Columns.Add("ID", typeof(Guid));
  30. report.Columns.Add("Name", typeof(string));
  31. report.Columns.Add("Leave", typeof(string));
  32. report.Columns.Add("LateStart", typeof(TimeSpan));
  33. report.Columns.Add("EarlyFinish", typeof(TimeSpan));
  34. report.Columns.Add("ClockIn", typeof(string));
  35. report.Columns.Add("ClockOut", typeof(string));
  36. report.PrimaryKey = new[] { report.Columns[0] };
  37. }
  38. public DateTime Date
  39. {
  40. get => _date;
  41. set
  42. {
  43. _date = value;
  44. LoadTimeSheets();
  45. }
  46. }
  47. public Guid GroupID
  48. {
  49. get => _groupid;
  50. set
  51. {
  52. _groupid = value;
  53. LoadEmployees(value);
  54. }
  55. }
  56. public TimesheetWidgetProperties Properties { get; set; }
  57. public event LoadSettings<TimesheetWidgetProperties>? LoadSettings;
  58. public event SaveSettings<TimesheetWidgetProperties>? SaveSettings;
  59. public void Setup()
  60. {
  61. LoadEmployees(GroupID);
  62. LoadActivities();
  63. }
  64. public void Refresh()
  65. {
  66. LoadTimeSheets();
  67. }
  68. public void Shutdown()
  69. {
  70. }
  71. private void ClearReport()
  72. {
  73. Report.ItemsSource = null;
  74. }
  75. private void LoadEmployees(Guid id)
  76. {
  77. ClearReport();
  78. employees = null;
  79. new Client<Employee>().Query(
  80. id != CoreUtils.FullGuid ? new Filter<Employee>(x => x.Group.ID).IsEqualTo(id) : null,
  81. null,
  82. null,
  83. (o, e) =>
  84. {
  85. employees = o;
  86. CheckData();
  87. }
  88. );
  89. }
  90. private void LoadActivities()
  91. {
  92. ClearReport();
  93. activities = null;
  94. new Client<Activity>().Query(
  95. new Filter<Activity>(x => x.IsLeave).IsEqualTo(true),
  96. new Columns<Activity>(
  97. x => x.ID,
  98. x => x.Description
  99. ),
  100. null,
  101. (o, e) =>
  102. {
  103. activities = o;
  104. CheckData();
  105. }
  106. );
  107. }
  108. private void LoadTimeSheets()
  109. {
  110. ClearReport();
  111. timesheets = null;
  112. new Client<TimeSheet>().Query(
  113. new Filter<TimeSheet>(x => x.Date).IsEqualTo(_date),
  114. null,
  115. new SortOrder<TimeSheet>(x => x.EmployeeLink.Name),
  116. (o, e) =>
  117. {
  118. timesheets = o;
  119. CheckData();
  120. }
  121. );
  122. }
  123. private void CheckData()
  124. {
  125. if (employees != null && activities != null && timesheets != null)
  126. ProcessData();
  127. }
  128. private string Codify(string name)
  129. {
  130. var result = "";
  131. var comps = name.ToUpper().Split(' ');
  132. foreach (var comp in comps)
  133. if (comp.Any())
  134. result += comp.First();
  135. return string.IsNullOrWhiteSpace(result) ? "??" : result;
  136. }
  137. private void ProcessData()
  138. {
  139. try
  140. {
  141. report.Rows.Clear();
  142. foreach (var time in timesheets.Rows)
  143. {
  144. var empid = time.Get<TimeSheet, Guid>(x => x.EmployeeLink.ID);
  145. var empname = time.Get<TimeSheet, string>(x => x.EmployeeLink.Name);
  146. if (report.Rows.Find(empid) == null)
  147. {
  148. var emprow = employees.Rows.FirstOrDefault(r => r.Get<Employee, Guid>(c => c.ID).Equals(empid));
  149. if (emprow != null)
  150. {
  151. var userid = emprow.Get<Employee, string>(x => x.UserLink.UserID);
  152. var date = time.Get<TimeSheet, DateTime>(c => c.Date);
  153. var roster = EmployeeRosterItem.FromJSON(emprow.Get<Employee, String>(c => c.Roster));
  154. var rosterday = RosterUtils.GetRoster(roster, emprow.Get<Employee, DateTime>(c => c.RosterStart), date);
  155. var shifts = RosterUtils.GetBlocks(rosterday, date, TimeSpan.Zero, TimeSpan.FromDays(1));
  156. var shiftstart = shifts.Aggregate(TimeSpan.MaxValue, (time, block) => block.Start < time ? block.Start : time);
  157. var shiftend = shifts.Aggregate(TimeSpan.Zero, (time, block) => block.Finish > time ? block.Finish : time);
  158. var rows = timesheets.Rows.Where(r => r.Get<TimeSheet, Guid>(c => c.EmployeeLink.ID).Equals(empid));
  159. var start = new TimeSpan(long.MaxValue);
  160. TimeSpan? late = null;
  161. var finish = new TimeSpan(long.MinValue);
  162. TimeSpan? early = null;
  163. var leave = "";
  164. var clockin = "";
  165. var clockout = "";
  166. var leaves = new List<string>();
  167. foreach (var row in rows)
  168. {
  169. var activity = row.Get<TimeSheet, Guid>(x => x.ActivityLink.ID);
  170. var activityrow = activities.Rows.FirstOrDefault(r => r.Get<Activity, Guid>(c => c.ID).Equals(activity));
  171. if (activityrow != null)
  172. {
  173. var thisleave = Codify(activityrow.Get<Activity, string>(x => x.Description));
  174. if (!leaves.Contains(thisleave))
  175. leaves.Add(thisleave);
  176. }
  177. leave = string.Join(",", leaves);
  178. var createdby = row.Get<TimeSheet, string>(x => x.CreatedBy);
  179. if (createdby == null)
  180. createdby = "";
  181. if (shiftstart.Ticks != 0)
  182. {
  183. var thisstart = row.Get<TimeSheet, TimeSpan>(x => x.Start);
  184. if (thisstart < start)
  185. {
  186. start = thisstart;
  187. if (start > shiftstart)
  188. late = !late.HasValue || start < late.Value ? start : late;
  189. else
  190. late = null;
  191. clockin = createdby.Equals(userid) ? "" : createdby;
  192. }
  193. }
  194. if (shiftend.Ticks != 0)
  195. {
  196. var thisfinish = row.Get<TimeSheet, TimeSpan>(x => x.Finish);
  197. if (thisfinish.Ticks == 0)
  198. {
  199. shiftend = new TimeSpan(0);
  200. early = null;
  201. }
  202. else
  203. {
  204. if (thisfinish > finish)
  205. {
  206. finish = thisfinish;
  207. if (finish < shiftend)
  208. early = !early.HasValue || finish > early.Value ? finish : early;
  209. else
  210. early = null;
  211. clockout = createdby.Equals(userid) ? "" : createdby;
  212. }
  213. }
  214. }
  215. }
  216. leave = string.Join(",", leaves);
  217. if (!string.IsNullOrEmpty(leave) || late.HasValue || early.HasValue || !string.IsNullOrEmpty(clockin) ||
  218. !string.IsNullOrEmpty(clockout))
  219. report.Rows.Add(empid, empname, leave, late, early, clockin, clockout);
  220. }
  221. }
  222. }
  223. }
  224. catch (Exception e)
  225. {
  226. Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
  227. }
  228. Dispatcher.Invoke(() => { Report.ItemsSource = report; });
  229. }
  230. }
  231. }