diff --git a/0_Framework/Application/Tools.cs b/0_Framework/Application/Tools.cs index 2b9fd519..35558af3 100644 --- a/0_Framework/Application/Tools.cs +++ b/0_Framework/Application/Tools.cs @@ -1696,6 +1696,32 @@ public static class Tools return message; } + public static string ToFarsiDaysAndHoursAndMinutes(this TimeSpan timeSpan, string emptyValue = "") + { + var hours = (int)timeSpan.TotalHours; + var minutes = timeSpan.Minutes; + var days = hours / 24; + hours = hours % 24; + string message = ""; + + if (days > 0) + message += days + " " + "روز"; + if (hours > 0) + if (message == "") + message += hours + " " + "ساعت"; + else + message += " و " + hours + " " + "ساعت"; + if (minutes > 0) + if (message == "") + message += minutes + " " + "دقیقه"; + else + message += " و " + minutes + " " + "دقیقه"; + + if (message == "") + message = emptyValue; + return message; + } + public static bool ArePropertiesEqual(this T obj1, T obj2) { // If either object is null, they can't be equal diff --git a/Company.Domain/RollCallAgg/IRollCallRepository.cs b/Company.Domain/RollCallAgg/IRollCallRepository.cs index 40d03a36..6b234a9c 100644 --- a/Company.Domain/RollCallAgg/IRollCallRepository.cs +++ b/Company.Domain/RollCallAgg/IRollCallRepository.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -74,5 +75,10 @@ namespace Company.Domain.RollCallAgg string CheckRepeat(long employeeId, long workshopId); RollCallViewModel GetDetails(long rollCallId); + List GetRangeByWorkshopIdEmployeeIdForDate(long workshopId, long employeeId, + DateTime date); + + List GetWorkshopEmployeeRollCallsWithUndefinedForDate(long workshopId, long employeeId, DateTime georgianDateTime); + void RemoveEmployeeRollCallsWithUndefinedInDate(long workshopId, long employeeId, DateTime date); } } diff --git a/CompanyManagment.App.Contracts/Leave/GroupLeavePrintViewModel.cs b/CompanyManagment.App.Contracts/Leave/GroupLeavePrintViewModel.cs index d0314ba8..5226bfee 100644 --- a/CompanyManagment.App.Contracts/Leave/GroupLeavePrintViewModel.cs +++ b/CompanyManagment.App.Contracts/Leave/GroupLeavePrintViewModel.cs @@ -9,4 +9,5 @@ public class GroupLeavePrintViewModel public List LeaveIdList { get; set; } public int StartPrint { get; set; } public int EndPrint { get; set; } + public string TotalLeaveMessage { get; set; } } diff --git a/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs b/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs index 3e37bfdb..edb854ee 100644 --- a/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs +++ b/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs @@ -16,7 +16,9 @@ public interface ILeaveApplication List search(LeaveSearchModel searchModel); LeavePrintViewModel PrintOne(long id); List PrintAll(List id); - OperationResult RemoveLeave(long id); + GroupLeavePrintViewModel PrintPersonnelLeaveList(List id); + + OperationResult RemoveLeave(long id); LeaveViewModel LeavOnChekout(DateTime starContract, DateTime endContract, long employeeId, long workshopId); List searchClient(LeaveSearchModel search); @@ -31,5 +33,7 @@ public interface ILeaveApplication #region Pooya OperationResult ValidateNewLeaveWithExistingRollCalls(long workshopId, long employeeId, string paidLeaveType, DateTime start, DateTime end); - #endregion + TimeSpan GetEmployeeLeaveTimeSpanInDates(long workshopId, long employeeId, string startFa, string endFa); + + #endregion } \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs index e855e935..4fe562d4 100644 --- a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs +++ b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs @@ -93,16 +93,16 @@ namespace CompanyManagment.App.Contracts.RollCall /// OperationResult ManualEdit(CreateOrEditEmployeeRollCall command); + OperationResult ManualEditForUndefined(CreateOrEditEmployeeRollCall command); - - /// - /// این متد تمام حضور غیاب های کات شده توسط بک گراند سرویس را به صورت تعداد روزانه برمیگرداند - /// - /// - /// لیستی از تعداد و روز آن - List GetRollCallWorkFlowsCutByBgService(long workshopId, DateTime start, DateTime end); + /// + /// این متد تمام حضور غیاب های کات شده توسط بک گراند سرویس را به صورت تعداد روزانه برمیگرداند + /// + /// + /// لیستی از تعداد و روز آن + List GetRollCallWorkFlowsCutByBgService(long workshopId, DateTime start, DateTime end); IEnumerable GetNotSlicedRollCallsByWorkshopId(long workshopId, DateTime durationStart, DateTime durationEnd); RollCallViewModel GetDetails(long rollCallId); @@ -111,6 +111,8 @@ namespace CompanyManagment.App.Contracts.RollCall List GetWorkshopAbsentHistory(long workshopId, DateTime startSearch, DateTime endSearch); OperationResult SetModifyTypeToNone(long rollCallId); - OperationResult SetModifyTypeToEditByEmployer(long rollCallId); - } + + OperationResult SetModifyTypeToEditByEmployerForRollCallsInDate(long workshopId, long employeeId, string absenceDate); + List GetWorkshopEmployeeRollCallsWithUndefinedForDate(long workshopId, long employeeId, string date); + } } diff --git a/CompanyManagment.Application/LeaveApplication.cs b/CompanyManagment.Application/LeaveApplication.cs index 1b719506..161c6a25 100644 --- a/CompanyManagment.Application/LeaveApplication.cs +++ b/CompanyManagment.Application/LeaveApplication.cs @@ -371,7 +371,20 @@ public class LeaveApplication : ILeaveApplication return _leaveRepository.PrintOne(id); } - + + public GroupLeavePrintViewModel PrintPersonnelLeaveList(List id) + { + var leaves = _leaveRepository.PrintAll(id); + + + var totalLeave = CalculateTotalLeaveTimeSpan(leaves); + + return new GroupLeavePrintViewModel() + { + LeaveList = leaves, + TotalLeaveMessage = totalLeave.ToFarsiDaysAndHoursAndMinutes() + }; + } public OperationResult RemoveLeave(long id) { diff --git a/CompanyManagment.Application/RollCallApplication.cs b/CompanyManagment.Application/RollCallApplication.cs index 0b8390d4..7f8bdc0e 100644 --- a/CompanyManagment.Application/RollCallApplication.cs +++ b/CompanyManagment.Application/RollCallApplication.cs @@ -569,6 +569,240 @@ public class RollCallApplication : IRollCallApplication return operation.Succcedded(); } + public OperationResult ManualEditForUndefined(CreateOrEditEmployeeRollCall command) + { + var operation = new OperationResult(); + + + DateTime date = command.DateFa.ToGeorgianDateTime(); + if (date == Tools.GetUndefinedDateTime()) + return operation.Failed("فرمت تاریخ وارد شده صحیح نمی باشد"); + + if (date >= DateTime.Now.Date) + { + return operation.Failed("امکان اضافه کردن حضور غیاب برای روز جاری و روز های آینده وجود ندارد"); + } + //from new + var twoDaysEarlier = date.AddDays(-2).Date; + var twoDaysLater = date.AddDays(2).Date >= DateTime.Today + ? (date.AddDays(1).Date >= DateTime.Today ? DateTime.Today : date.AddDays(1).Date) + : date.AddDays(2).Date; + //--- + + if (command.WorkshopId < 1) + { + return operation.Failed("خطای سیستمی"); + } + + if (command.RollCallRecords == null || command.RollCallRecords.Count == 0) + return operation.Failed("خطای سیستمی"); + + if (_leaveRepository.HasDailyLeave(command.EmployeeId, command.WorkshopId, date)) + return operation.Failed("در روز مرخصی کارمند نمی توانید حضور غیاب ثبت کنید"); + + var employeeStatuses = _rollCallEmployeeRepository.GetByEmployeeIdWithStatuses(command.EmployeeId) + .FirstOrDefault(x => x.WorkshopId == command.WorkshopId)?.Statuses; + var employeeRollCalls = _rollCallRepository.GetEmployeeRollCallsHistoryAllInDates(command.WorkshopId, command.EmployeeId, twoDaysEarlier, twoDaysLater); + + //comented from new + //var employeeRollCalls = _rollCallRepository.GetWorkshopEmployeeRollCallsForDate(command.WorkshopId, command.EmployeeId, date); + + //comented from new + //if (employeeRollCalls.Any(x => x.EndDate == null)) + // return operation.Failed("به دلیل عدم ثبت خروج پرسنل در این تاریخ، شما قادر به افزودن رکورد جدید نمی باشید"); + + + if (command.RollCallRecords.Any(x => string.IsNullOrWhiteSpace(x.StartTime) || string.IsNullOrWhiteSpace(x.EndTime))) + return operation.Failed("ساعات شروع و پایان نمیتوانند خالی باشد"); + DateTime day = command.DateFa.ToGeorgianDateTime(); + + + var workshopSettings = _customizeWorkshopSettingsRepository.GetBy(command.WorkshopId); + var employeeSettings = + _customizeWorkshopEmployeeSettingsRepository.GetByEmployeeIdAndWorkshopIdIncludeGroupSettings( + command.WorkshopId, command.EmployeeId)?.WorkshopShiftStatus; + + if (employeeSettings == null && workshopSettings.WorkshopShiftStatus != WorkshopShiftStatus.Regular) + { + return operation.Failed("لطفا ابتدا برای این پرسنل گروهبندی انجام دهید "); + } + + List<(TimeOnly start, TimeOnly end, long rollCallId)> preprocessedRollCalls = new(); + try + { + preprocessedRollCalls = command.RollCallRecords.Select(x => + { + + if (!TimeOnly.TryParseExact(x.StartTime, "HH:mm", out TimeOnly start)) + throw new Exception(); + if (!TimeOnly.TryParseExact(x.EndTime, "HH:mm", out TimeOnly end)) + throw new Exception(); + return (start, end, x.RollCallId); + + }).ToList(); + } + catch (Exception e) + { + + return operation.Failed("فرمت ساعات ورودی نادرست می باشد"); + } + + List<(DateTime Start, DateTime End, long RollCallId)> result = new(); + + if (workshopSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular || employeeSettings == WorkshopShiftStatus.Regular) + { + + TimeOnly offset = + _rollCallDomainService.GetEmployeeOffSetForRegularSettings(command.EmployeeId, command.WorkshopId); + + var startWorkingPeriod = day.Date + offset.ToTimeSpan(); + + if (offset > new TimeOnly(12, 0, 0)) + startWorkingPeriod = startWorkingPeriod.AddDays(-1); + foreach (var preprocessedRollCall in preprocessedRollCalls) + { + DateTime startDateTime = startWorkingPeriod.Date.Add(preprocessedRollCall.start.ToTimeSpan()); + + if (preprocessedRollCall.start.ToTimeSpan() < offset.ToTimeSpan()) + { + startDateTime = startDateTime.AddDays(1); + } + + DateTime endDateTime = startDateTime.Date + preprocessedRollCall.end.ToTimeSpan(); + + if (startDateTime > endDateTime) + { + endDateTime = endDateTime.AddDays(1); + } + + if (result.Any(x => endDateTime > x.Start && startDateTime < x.End)) + return operation.Failed("بازه های وارد شده با هم تداخل دارند"); + + result.Add(new(startDateTime, endDateTime, preprocessedRollCall.rollCallId)); + } + + } + else + { + #region RollCallTimes validation and parse to DateTime + + + if (day == Tools.GetUndefinedDateTime()) + return operation.Failed("خطای سیستمی"); + DateTime previousEnd = new DateTime(); + preprocessedRollCalls = preprocessedRollCalls.OrderBy(x => x.start).ToList(); + + + foreach (var item in preprocessedRollCalls) + { + (DateTime Start, DateTime End, long RollCallId) rollCallWithDateTime = + new() + { + Start = new DateTime(DateOnly.FromDateTime(day), item.start), + End = new DateTime(DateOnly.FromDateTime(day), item.end), + RollCallId = item.rollCallId + + }; + + if (previousEnd != new DateTime()) + { + if (rollCallWithDateTime.Start < previousEnd) + { + rollCallWithDateTime.Start = rollCallWithDateTime.Start.AddDays(1); + } + + if (rollCallWithDateTime.Start == previousEnd) + return operation.Failed("ساعت ورود نمی تواند با ساعت خروج حضور غیاب دیگری در آن روز برابر باشد"); + + } + + while (rollCallWithDateTime.Start >= rollCallWithDateTime.End) + { + rollCallWithDateTime.End = rollCallWithDateTime.End.AddDays(1); + } + + result.Add(rollCallWithDateTime); + previousEnd = rollCallWithDateTime.End; + } + + var firstShiftStart = result.OrderBy(x => x.Start).FirstOrDefault().Start; + var lastShiftEnd = result.OrderByDescending(x => x.Start).FirstOrDefault().End; + var lastShiftStart = result.OrderByDescending(x => x.Start).FirstOrDefault().Start; + + if (firstShiftStart.AddDays(1) < lastShiftEnd) + return operation.Failed("بازه زمانی وارد شده نا معتبر است"); + + + if (firstShiftStart.Date != lastShiftStart.Date) + return operation.Failed("شروع رکورد حضور غیاب نمی تواند در روز های بعد از تاریخ تعیین شده باشد"); + + #endregion + } + + if (result.Sum(x => (x.End - x.Start).TotalHours) > 24) + { + return operation.Failed("بازه زمانی نمیتواند بیشتر از 24 ساعت باشد"); + } + + //from new + foreach (var activity in result) + { + + //مرخصی روزانه در بالا چک شده است + var leave = _leaveRepository.GetByWorkshopIdEmployeeIdInDates(command.WorkshopId, command.EmployeeId, activity.Start, activity.End) + .Where(x => x.PaidLeaveType == "ساعتی"); + if (leave.Any()) + return operation.Failed("کارمند در بازه انتخاب شده مرخصی ساعتی دارد"); + } + + + if (result.Any(x => + x.Start.Date < date.Date.AddDays(-1) || + x.End.Date > date.Date.AddDays(1))) + { + return operation.Failed("حضور غیاب در حال ویرایش را نمیتوانید بیشتر از یک روز از ثبت حضور غیاب عقب تر یا جلو تر ببرید"); + } + + //مهم + //رول کال روز جاری + #region NewValidation + var currentDayRollCall = employeeRollCalls.FirstOrDefault(x => x.EndDate == null); + + if (currentDayRollCall != null && result.Any(x => x.End >= currentDayRollCall.StartDate)) + return operation.Failed("بازه های وارد شده با حضور غیاب جاری تداخل زمانی دارد"); + #endregion + + + + if (result.Any(x => employeeRollCalls.Any(y => y.DateGr.Date != command.DateFa.ToGeorgianDateTime().Date && + x.End >= y.StartDate.Value && x.Start <= y.EndDate.Value))) + + return operation.Failed("بازه های وارد شده با حضور غیاب های مربوط به روز های قبل و بعد تداخل زمانی دارد"); + + var checkoutViewModels = _checkoutRepository.SimpleSearch(new CheckoutSearchModel() { WorkshopId = command.WorkshopId, EmployeeId = command.EmployeeId }); + + if (checkoutViewModels.Any(x => x.HasRollCall && x.WorkshopId == command.WorkshopId && x.EmployeeId == command.EmployeeId && + result.Any(y => (y.Start.Date >= x.ContractStartGr.Date) + && (y.Start.Date <= x.ContractEndGr.Date)))) + return operation.Failed("برای بازه های وارد شده فیش حقوقی ثبت شده است"); + //--- + + + if (result == null || !result.All(x => employeeStatuses.Any(y => x.Start >= y.StartDateGr || x.End <= y.EndDateGr))) + return operation.Failed("کارمند در بازه وارد شده غیر فعال است"); + + + var name = _rollCallEmployeeRepository.GetByEmployeeIdAndWorkshopId(command.EmployeeId, command.WorkshopId).EmployeeFullName; + var rollCallsAsEntityModels = result.Select(x => new RollCall(command.WorkshopId, command.EmployeeId, name, x.Start, x.End, + Convert.ToInt32(x.Start.ToFarsi().Substring(0, 4)), Convert.ToInt32(x.Start.ToFarsi().Substring(5, 2)), _rollCallDomainService, RollCallModifyType.EditByEmployer)).ToList(); + _rollCallRepository.RemoveEmployeeRollCallsWithUndefinedInDate(command.WorkshopId, command.EmployeeId, date); + + + _rollCallRepository.AddRange(rollCallsAsEntityModels); + _rollCallRepository.SaveChanges(); + return operation.Succcedded(); + } + #endregion public List GetWorkshopEmployeeRollCallsForDate(long workshopId, long employeeId, string dateFa) @@ -606,22 +840,34 @@ public class RollCallApplication : IRollCallApplication return operation.Succcedded(); } - public OperationResult SetModifyTypeToEditByEmployer(long rollCallId) + + //استفاده شده در تایید حضور و غیاب های قطع شده توسط سیستم + public OperationResult SetModifyTypeToEditByEmployerForRollCallsInDate(long workshopId, long employeeId, string absenceDateFa) { var operation = new OperationResult(); - var rollCall = _rollCallRepository.Get(rollCallId); + if (absenceDateFa.TryToGeorgianDateTime(out var absenceDate) == false) + return operation.Failed("تاریخ به درستی وارد نشده است"); - if (rollCall == null) + var rollCalls = _rollCallRepository.GetRangeByWorkshopIdEmployeeIdForDate(workshopId, employeeId, absenceDate); + + if (rollCalls == null) return operation.Failed("چنین آیتمی یافت نشد"); - - rollCall.SetModifyType(RollCallModifyType.EditByEmployer); + foreach (var item in rollCalls) + item.SetModifyType(RollCallModifyType.EditByEmployer); _rollCallRepository.SaveChanges(); return operation.Succcedded(); } + public List GetWorkshopEmployeeRollCallsWithUndefinedForDate(long workshopId, long employeeId, string dateFa) + { + if (dateFa.TryToGeorgianDateTime(out var date) == false) + return new(); + return _rollCallRepository.GetWorkshopEmployeeRollCallsWithUndefinedForDate(workshopId, employeeId, date); + + } public List GetRollCallWorkFlowsCutByBgService(long workshopId, DateTime start, DateTime end) diff --git a/CompanyManagment.EFCore/Repository/RollCallRepository.cs b/CompanyManagment.EFCore/Repository/RollCallRepository.cs index b6a6e4df..89025bf4 100644 --- a/CompanyManagment.EFCore/Repository/RollCallRepository.cs +++ b/CompanyManagment.EFCore/Repository/RollCallRepository.cs @@ -3,6 +3,7 @@ using _0_Framework.Domain.CustomizeCheckoutShared.Base; using _0_Framework.Domain.CustomizeCheckoutShared.Enums; using _0_Framework.Domain.CustomizeCheckoutShared.ValueObjects; using _0_Framework.InfraStructure; +using Company.Domain.EmployeeAgg; using Company.Domain.RollCallAgg; using Company.Domain.RollCallEmployeeAgg; using Company.Domain.WorkshopAgg; @@ -1381,5 +1382,14 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos TotalWorkingHoursSpan = x.EndDate == null ? new() : x.EndDate.Value - x.StartDate.Value }).ToList(); } + + public void RemoveEmployeeRollCallsWithUndefinedInDate(long workshopId, long employeeId, DateTime date) + { + + var rollCalls = _context.RollCalls.IgnoreQueryFilters().Where(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId && x.ShiftDate == date.Date); + if (!rollCalls.Any()) + return; + _context.RollCalls.RemoveRange(rollCalls); + } } diff --git a/ServiceHost/Areas/Client/Pages/Company/Employees/Leave.cshtml b/ServiceHost/Areas/Client/Pages/Company/Employees/Leave.cshtml index c33ec523..bdaf270f 100644 --- a/ServiceHost/Areas/Client/Pages/Company/Employees/Leave.cshtml +++ b/ServiceHost/Areas/Client/Pages/Company/Employees/Leave.cshtml @@ -115,6 +115,16 @@ .blackSelect { background-color: #cbd5e1; } + + + #allTimeLeaves { + background-color: #ccfbf1; + padding: 5px 10px; + font-size: 14px; + font-weight: 600; + border-radius: 10px; + border: 1px solid #5eead4; + } } @@ -356,8 +366,8 @@ -
-
-
+
-
-
- @* @if (@Model.LeaveSearch.Count > 0) + + @* @if (@Model.LeaveSearch.Count > 0) { *@ - - - @* } *@ + + + @* } *@
@@ -492,20 +503,20 @@ @{ if (itemLeave.LeaveType == "استحقاقی") { - - - استحقاقی - - + + + استحقاقی + + } if (itemLeave.LeaveType == "استعلاجی") { - - - استعلاجی - - + + + استعلاجی + + } } @@ -905,11 +916,11 @@ @{ if (Model.Year == 0) { - سال + سال } else { - @Model.SearchModel.Year + @Model.SearchModel.Year } } @@ -923,50 +934,50 @@ @{ if (Model.Month == 0) { - ماه + ماه } else { - @switch (@Model.SearchModel.Month) + @switch (@Model.SearchModel.Month) { case 01: - فروردین + فروردین break; case 02: - اردیبهشت + اردیبهشت break; case 03: - خرداد + خرداد break; case 04: - تیر + تیر break; case 05: - مرداد + مرداد break; case 06: - شهریور + شهریور break; case 07: - مهر + مهر break; case 08: - آبان + آبان break; case 09: - آذر + آذر break; case 10: - دی + دی break; case 11: - بهمن + بهمن break; case 12: - اسفند + اسفند break; default: - ماه + ماه break; } } @@ -1035,8 +1046,9 @@ - + \ No newline at end of file diff --git a/ServiceHost/Areas/Client/Pages/Company/WorkFlow/ModalEditRollCallAction.cshtml b/ServiceHost/Areas/Client/Pages/Company/WorkFlow/ModalEditRollCallAction.cshtml new file mode 100644 index 00000000..8591aba4 --- /dev/null +++ b/ServiceHost/Areas/Client/Pages/Company/WorkFlow/ModalEditRollCallAction.cshtml @@ -0,0 +1,203 @@ +@model CompanyManagment.App.Contracts.RollCall.EmployeeRollCallsViewModel +@{ + string clientVersion = _0_Framework.Application.Version.StyleVersion; + var index = 0; + var count = Model.RollCalls.Count; + string countString; + + + + +} + +
+ + +
+ + + + + + + \ No newline at end of file diff --git a/ServiceHost/Areas/Client/Pages/Company/WorkFlow/ModalEditRollCallUndefined.cshtml b/ServiceHost/Areas/Client/Pages/Company/WorkFlow/ModalEditRollCallUndefined.cshtml new file mode 100644 index 00000000..13ddd7a0 --- /dev/null +++ b/ServiceHost/Areas/Client/Pages/Company/WorkFlow/ModalEditRollCallUndefined.cshtml @@ -0,0 +1,319 @@ +@model CompanyManagment.App.Contracts.RollCall.EmployeeRollCallsViewModel +@{ + string clientVersion = _0_Framework.Application.Version.StyleVersion; + var index = 0; + var count = Model.RollCalls.Count; + string countString; + string txtString; + + + + +} + +
+ + +
+ + + + + + diff --git a/ServiceHost/Areas/Client/Pages/Company/WorkFlow/RollCall.cshtml b/ServiceHost/Areas/Client/Pages/Company/WorkFlow/RollCall.cshtml index 8846bc1d..2d2f3398 100644 --- a/ServiceHost/Areas/Client/Pages/Company/WorkFlow/RollCall.cshtml +++ b/ServiceHost/Areas/Client/Pages/Company/WorkFlow/RollCall.cshtml @@ -60,7 +60,7 @@
-
+
- @*
-
-
-
-
-
-
-
-
غیبت
-
-
-
- +@*
+
+
+
+
+
+
+
غیبت
- -
-
- @*
- - -
*@ - -
+
+
+ Loading...
+
-
-
-
-
-
-
قطع شده توسط سیستم
-
-
-
- -
-
- -
-
-
-
+
+
+
- -
-
-
-
-
-
عدم ثبت ساعت استراحت
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
-
-
-
-
تعیین وضعیت تردد پرسنل فوری
-
-
-
- -
-
- -
-
-
-
-
-
- - @*
-
-
-
-
-
رفع تداخل مرخصی و تردد پرسنل
-
-
-
- -
-
- -
-
-
-
-
-
*@ -
+ +
+
+
+
+
+
قطع شده توسط سیستم
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
عدم ثبت ساعت استراحت
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
تعیین وضعیت تردد پرسنل فوری
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
رفع تداخل مرخصی و تردد پرسنل
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
*@ + +
diff --git a/ServiceHost/Areas/Client/Pages/Company/WorkFlow/RollCall.cshtml.cs b/ServiceHost/Areas/Client/Pages/Company/WorkFlow/RollCall.cshtml.cs index 061a0ebf..74162b08 100644 --- a/ServiceHost/Areas/Client/Pages/Company/WorkFlow/RollCall.cshtml.cs +++ b/ServiceHost/Areas/Client/Pages/Company/WorkFlow/RollCall.cshtml.cs @@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System.Security.Claims; using _0_Framework.Infrastructure; -using Microsoft.Build.Exceptions; +using CompanyManagment.App.Contracts.RollCallEmployee; using WorkFlow.Application.Contracts.RollCallConfirmedAbsence; using WorkFlow.Application.Contracts.RollCallConfirmedWithoutLunchBreak; using WorkFlow.Application.Contracts.Shared; @@ -25,6 +25,7 @@ namespace ServiceHost.Areas.Client.Pages.Company.WorkFlow private readonly IAuthHelper _authHelper; private readonly IRollCallApplication _rollCallApplication; private readonly IRollCallServiceApplication _rollCallServiceApplication; + private readonly IRollCallEmployeeApplication _rollCallEmployeeApplication; private readonly IHttpContextAccessor _contextAccessor; private readonly long _workshopId; @@ -36,7 +37,7 @@ namespace ServiceHost.Areas.Client.Pages.Company.WorkFlow public int CountRollCallsOverlappingLeave; public int Count; - public RollCallModel(IPasswordHasher passwordHasher, IWorkshopApplication workshopApplication, IAuthHelper authHelper, IWorkFlowApplication workflowApplication, IRollCallApplication rollCallApplication, IRollCallServiceApplication rollCallServiceApplication, IHttpContextAccessor contextAccessor, ILeaveApplication leaveApplication) + public RollCallModel(IPasswordHasher passwordHasher, IWorkshopApplication workshopApplication, IAuthHelper authHelper, IWorkFlowApplication workflowApplication, IRollCallApplication rollCallApplication, IRollCallServiceApplication rollCallServiceApplication, IHttpContextAccessor contextAccessor, ILeaveApplication leaveApplication, IRollCallEmployeeApplication rollCallEmployeeApplication) { _passwordHasher = passwordHasher; _workshopApplication = workshopApplication; @@ -46,12 +47,13 @@ namespace ServiceHost.Areas.Client.Pages.Company.WorkFlow _rollCallServiceApplication = rollCallServiceApplication; _contextAccessor = contextAccessor; _leaveApplication = leaveApplication; + _rollCallEmployeeApplication = rollCallEmployeeApplication; var workshopHash = _contextAccessor.HttpContext?.User.FindFirstValue("WorkshopSlug"); _workshopId = _passwordHasher.SlugDecrypt(workshopHash); if (_workshopId < 1) - throw new InternalLoggerException("اختلال در کارگاه"); + throw new InvalidDataException("اختلال در کارگاه"); } public async Task OnGet() @@ -250,9 +252,9 @@ namespace ServiceHost.Areas.Client.Pages.Company.WorkFlow }); } - public IActionResult OnPostConfirmCutByBgService(long rollCallId) + public IActionResult OnPostConfirmCutByBgService(long employeeId, string absenceDate) { - var result = _rollCallApplication.SetModifyTypeToEditByEmployer(rollCallId); + var result = _rollCallApplication.SetModifyTypeToEditByEmployerForRollCallsInDate(_workshopId,employeeId, absenceDate); return new JsonResult(new { @@ -275,5 +277,81 @@ namespace ServiceHost.Areas.Client.Pages.Company.WorkFlow message = result.Message }); } - } + + public IActionResult OnGetEditRollCall(long employeeId, string date) + { + var result = _rollCallApplication.GetWorkshopEmployeeRollCallsForDate(_workshopId, employeeId, date); + //var dates = _rollCallApplication.GetEditableDatesForManualEdit(date.ToGeorgianDateTime()); + var name = _rollCallEmployeeApplication.GetByEmployeeIdAndWorkshopId(employeeId, _workshopId); + var command = new EmployeeRollCallsViewModel() + { + EmployeeFullName = name.EmployeeFullName, + EmployeeId = employeeId, + DateFa = date, + //EditableDates = dates, + RollCalls = result + }; + + return Partial("../RollCall/ModalEditRollCall", command); + } + + public IActionResult OnPostManualCreateOrEdit(CreateOrEditEmployeeRollCall command) + { + command.WorkshopId = _workshopId; + var result = _rollCallApplication.ManualEdit(command); + + return new JsonResult(new + { + success = result.IsSuccedded, + message = result.Message, + }); + } + + public IActionResult OnGetEditRollCallAction(long employeeId, string date) + { + var result = _rollCallApplication.GetWorkshopEmployeeRollCallsWithUndefinedForDate(_workshopId, employeeId, date); + //var dates = _rollCallApplication.GetEditableDatesForManualEdit(date.ToGeorgianDateTime()); + var name = _rollCallEmployeeApplication.GetByEmployeeIdAndWorkshopId(employeeId, _workshopId); + var command = new EmployeeRollCallsViewModel() + { + EmployeeFullName = name.EmployeeFullName, + EmployeeId = employeeId, + DateFa = date, + //EditableDates = dates, + RollCalls = result, + + }; + + return Partial("ModalEditRollCallAction", command); + } + + public IActionResult OnGetEditRollCallForUndefined(long employeeId, string date) + { + var result = _rollCallApplication.GetWorkshopEmployeeRollCallsWithUndefinedForDate(_workshopId, employeeId, date); + //var dates = _rollCallApplication.GetEditableDatesForManualEdit(date.ToGeorgianDateTime()); + var name = _rollCallEmployeeApplication.GetByEmployeeIdAndWorkshopId(employeeId, _workshopId); + var command = new EmployeeRollCallsViewModel() + { + EmployeeFullName = name.EmployeeFullName, + EmployeeId = employeeId, + DateFa = date, + //EditableDates = dates, + RollCalls = result + }; + + return Partial("ModalEditRollCallUndefined", command); + } + + public IActionResult OnPostManualCreateOrEditForUndefined(CreateOrEditEmployeeRollCall command) + { + command.WorkshopId = _workshopId; + var result = _rollCallApplication.ManualEditForUndefined(command); + + return new JsonResult(new + { + success = result.IsSuccedded, + message = result.Message, + }); + } + } } diff --git a/ServiceHost/appsettings.Development.json b/ServiceHost/appsettings.Development.json index e8a307ae..58da1be8 100644 --- a/ServiceHost/appsettings.Development.json +++ b/ServiceHost/appsettings.Development.json @@ -12,10 +12,10 @@ //"MesbahDb": "Data Source=DESKTOP-NUE119G\\MSNEW;Initial Catalog=Mesbah_db;Integrated Security=True" //server - "MesbahDb": "Data Source=171.22.24.15;Initial Catalog=mesbah_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]is[3019]#@ATt;TrustServerCertificate=true;" + //"MesbahDb": "Data Source=171.22.24.15;Initial Catalog=mesbah_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]is[3019]#@ATt;TrustServerCertificate=true;" //local - //"MesbahDb": "Data Source=.;Initial Catalog=mesbah_db;Integrated Security=True;TrustServerCertificate=true;" + "MesbahDb": "Data Source=.;Initial Catalog=mesbah_db;Integrated Security=True;TrustServerCertificate=true;" }, "GoogleRecaptchaV3": { "SiteKey": "6Lfhp_AnAAAAAB79WkrMoHd1k8ir4m8VvfjE7FTH", diff --git a/ServiceHost/wwwroot/AssetsClient/pages/RollCall/js/ModalEditRollCall.js b/ServiceHost/wwwroot/AssetsClient/pages/RollCall/js/ModalEditRollCall.js index 45a3229b..f5228e18 100644 --- a/ServiceHost/wwwroot/AssetsClient/pages/RollCall/js/ModalEditRollCall.js +++ b/ServiceHost/wwwroot/AssetsClient/pages/RollCall/js/ModalEditRollCall.js @@ -250,6 +250,12 @@ function timeValidCheck(value) { //} $('.btn-register').click(function () { + var urlPostEditRollCall = ``; + if (urlPathname.indexOf('/Client/Company/WorkFlow/RollCall') > -1) { + urlPostEditRollCall = saveRollCallWorkTimeFromWorkFlowAjax; + } else { + urlPostEditRollCall = saveRollCallWorkTimeAjax; + } var dateFa = $('#dateFa').val().replaceAll("/", ""); var dateEmployeeID = $('#employeeID').val() + '-' + dateFa; @@ -262,7 +268,7 @@ $('.btn-register').click(function () { async: false, dataType: 'json', type: 'POST', - url: saveRollCallWorkTimeAjax, + url: urlPostEditRollCall, headers: { "RequestVerificationToken": antiForgeryToken }, data: data, success: function (response) { diff --git a/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/css/ModalEditRollCallAction.css b/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/css/ModalEditRollCallAction.css new file mode 100644 index 00000000..8a1ccfd7 --- /dev/null +++ b/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/css/ModalEditRollCallAction.css @@ -0,0 +1,103 @@ +.errored { + animation: shake 300ms; + color: #eb3434 !important; + background-color: #fef2f2 !important; + border: 1px solid #eb3434 !important; +} + +.modalRollCallWidth { + max-width: 550px; +} + +.modal-dialog, .modal-content { + height: 420px; +} + +.timeWorkTitle { + color: #5C5C5C; + font-weight: 600; + font-size: 12px; + margin: auto 6px; + white-space: nowrap; +} + +.groupBox { + background-color: #F5F5F5; + border-radius: 10px; + border: 1px solid #E7E7E7; + padding: 6px; + margin: 6px 3px; +} + +.groupBox .form-control { + background-color: #ffffff; +} + +.groupBox .form-control::placeholder { + color: #bfbfbf; + opacity: 1; /* Firefox */ +} + +.groupBox .form-control::-ms-input-placeholder { /* Edge 12-18 */ + color: #bfbfbf; +} + +.btnAddTimeWork { + display: flex; + align-items: center; + justify-content: center; + background-color: #84CC16; + border-radius: 5px; + color: #ffffff; + font-size: 12px; + font-weight: 500; + padding: 4px 8px; +} + +.btnRemoveTimeWork { + display: flex; + align-items: center; + justify-content: center; + background-color: #F87171; + border-radius: 7px; + padding: 3px; + width: 30px; + height: 30px; +} + +.ShowMessage { + position: absolute; + background: #dfdfdf; + width: 100%; + top: 0; + right: 0; + height: 100%; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; +} + +.heightControll { + height: 190px; + overflow-y: scroll; +} + +.confrim-btn { + background-color: #84CC16; + color: #ffffff; + text-align: center; + font-size: 12px; + width: 135px; + padding: .2rem; +} + + +.edit-btn { + background-color: #22AAEE; + color: #ffffff; + text-align: center; + font-size: 12px; + width: 135px; + padding: .2rem; +} \ No newline at end of file diff --git a/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/css/RollCall.css b/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/css/RollCall.css index 3817c7af..c1be8f1e 100644 --- a/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/css/RollCall.css +++ b/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/css/RollCall.css @@ -55,18 +55,18 @@ } .countNumber { - background-color: #ccfbf1; + margin: 0 0 0 12px; + font-size: 12px; + background-color: #dd2a2a; width: 24px; - display: flex; height: 24px; + display: flex; align-items: center; justify-content: center; - border-radius: 4px; - border: 1px solid #5eead4; - margin: 0 0 0 12px; - color: #097474; - font-size: 14px; - font-weight: 700; + border-radius: 40px; + color: #fff; + font-weight: 600; + padding: 2px 0 0 0; } /* Vertical selector styling */ @@ -545,4 +545,35 @@ input:checked + .sliderEUP:before { .employee-name { font-weight: 800; } + + + + + + + + /* responsive Mobile */ + #navbar-animmenu { + width: 100%; + } + + #navbar-animmenu ul { + display: flex; + height: auto; + overflow: scroll; + } + + .verti-selector { + display: none + } + + #navbar-animmenu li.active { + background-color: #fff; + width: 100%; + } + + #accountList { + width: 100%; + height: auto; + } } \ No newline at end of file diff --git a/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/js/ModalEditRollCallAction.js b/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/js/ModalEditRollCallAction.js new file mode 100644 index 00000000..97f14bad --- /dev/null +++ b/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/js/ModalEditRollCallAction.js @@ -0,0 +1,390 @@ +var urlPathname = location.pathname; + +$(document).ready(function () { + + $("#modalWorkshopFullname").text($('#caseHistoryWorkshopFullname').text()); + $('.btn-register').addClass('disable'); + + $(".form-control-date").each(function () { + new Cleave(this, { + date: true, + delimiter: '/', + datePattern: ['Y', 'm', 'd'] + }); + }); + + $(".dateTime").each(function () { + new Cleave(this, { + time: true, + timePattern: ['h', 'm'] + }); + }); + + // updateDateInput(0); + + $(".btnAddTimeWork").on("click", function () { + var currentCount = $('.groupBox').length; + var $inputs = $('.dateTime'); + var allFilled = true; + + $inputs.each(function () { + if ($(this).val() === '') { + allFilled = false; + $('.btn-register').addClass('disable'); + showAlert('ابتدا ساعت شروع و پایان را وارد نمائید.', $(this)); + } + }); + + if (!allFilled) { + return false; + } + + + if (currentCount < 5) { + var namePlacementPersian = ""; + + switch (currentCount + 1) { + case 2: + namePlacementPersian = "دوم"; + break; + case 3: + namePlacementPersian = "سوم"; + break; + case 4: + namePlacementPersian = "چهارم"; + break; + case 5: + namePlacementPersian = "پنجم"; + break; + default: + } + + var timeWorkHtml = ` +
+
+
+
نوبت ${namePlacementPersian}
+
+
+
از
+ +
+
+
الی
+ +
+
+ +
+
+
`; + + $('#appendChildTimeWorkHtml').append(timeWorkHtml); + + new Cleave(`input[name="Command.RollCallRecords[${currentCount}].StartTime"]`, { + time: true, + timePattern: ['h', 'm'] + }); + + new Cleave(`input[name="Command.RollCallRecords[${currentCount}].EndTime"]`, { + time: true, + timePattern: ['h', 'm'] + }); + + updateAddButtonText(currentCount + 1); + + if (currentCount + 1 === 5) { + $(".btnAddTimeWork").hide(); + } + + + // Update Remove button enable/disable state + updateRemoveButtons(); + } + }); + $(document).on("click", ".btnRemoveTimeWork", function () { + $(this).closest(".groupBox").remove(); + var currentCount = $('.groupBox').length; + + updateAddButtonText(currentCount); + + if (currentCount < 5) { + $(".btnAddTimeWork").show(); + } + + // Update Remove button enable/disable state + updateRemoveButtons(); + }); +}); +function updateRemoveButtons() { + $(".btnRemoveTimeWork").addClass("disable"); + $(".btnRemoveTimeWork").last().removeClass("disable"); +} + +//function updateDateInput(daysToAdd) { +// var today = new Date(); +// today.setDate(today.getDate() + daysToAdd); +// var jalaaliDate = jalaali.toJalaali(today); +// var formattedDate = jalaaliDate.jy + '/' + (jalaaliDate.jm < 10 ? '0' + jalaaliDate.jm : jalaaliDate.jm) + '/' + (jalaaliDate.jd < 10 ? '0' + jalaaliDate.jd : jalaaliDate.jd); +// $('.form-control-date').val(formattedDate); +//} + +//updateAddButtonText(1); +function updateAddButtonText(currentCount) { + if (currentCount === 1) { + $('.btnAppendChildTimeWork').text('افزودن نوبت دوم'); + } else if (currentCount === 2) { + $('.btnAppendChildTimeWork').text('افزودن نوبت سوم'); + } else if (currentCount === 3) { + $('.btnAppendChildTimeWork').text('افزودن نوبت چهارم'); + } else if (currentCount === 4) { + $('.btnAppendChildTimeWork').text('افزودن نوبت پنجم'); + } + + let allFilled = true; + $('.dateTime').each(function () { + const value = $(this).val().trim(); + if (value === "" || !timeValidCheck(value)) { + allFilled = false; + return false; // Break the loop + } + }); + + if (allFilled) { + $('.btn-register').removeClass('disable'); + } else { + $('.btn-register').addClass('disable'); + } +} + +$(document).on('keyup', ".dateTime", function () { + let $input = $(this); + let value = $input.val(); + let lengthValue = value.length; + let currentCount = $('.groupBox').length; + + if (lengthValue >= 5) { + if (!timeValidCheck(value)) { + showAlert('ساعت را به درستی وارد نمائید', $input); + updateAddButtonText(currentCount); + } else { + clearAlert($input); + // validateAllTimes(); + updateAddButtonText(currentCount); + + // focusNextTimeInput($input); + } + } else { + updateAddButtonText(currentCount); + } +}); + +//function focusNextTimeInput(currentInput) { +// var inputs = $(".dateTime"); +// var currentIndex = inputs.index(currentInput); + +// if (currentIndex !== -1 && currentIndex < inputs.length - 1) { +// $(inputs[currentIndex + 1]).focus(); +// } +//} + +function showAlert(message, inputElement) { + inputElement.addClass("errored"); + $('.alert-msg').show().find('p').text(message); + setTimeout(function () { + clearAlert(inputElement); + }, 3500); +} + +function clearAlert(inputElement) { + inputElement.removeClass("errored"); + $('.alert-msg').hide().find('p').text(''); +} + +function timeValidCheck(value) { + const timePattern = /^([01]\d|2[0-3]):([0-5]\d)$/; + return timePattern.test(value); +} + +//function validateAllTimes() { +// let timeRanges = []; + +// $(".groupBox").each(function () { +// let startTime = $(this).find('input[name*="StartTime"]').val(); +// let endTime = $(this).find('input[name*="EndTime"]').val(); + +// if (startTime.length === 5 && endTime.length === 5) { +// let startParts = startTime.split(':'); +// let endParts = endTime.split(':'); +// let startInMinutes = parseInt(startParts[0]) * 60 + parseInt(startParts[1]); +// let endInMinutes = parseInt(endParts[0]) * 60 + parseInt(endParts[1]); +// timeRanges.push({ start: startInMinutes, end: endInMinutes }); +// } +// }); + +// // Check for conflicts and order +// for (let i = 0; i < timeRanges.length; i++) { +// for (let j = 0; j < i; j++) { +// if (timeRanges[i].start >= timeRanges[i].end) { +// showAlert('زمان شروع باید قبل از زمان پایان باشد', $(".groupBox").eq(i).find('input[name*="StartTime"]')); +// return; +// } + +// // Check for overlap with previous entries +// if (timeRanges[i].start < timeRanges[j].end && timeRanges[i].end > timeRanges[j].start) { +// showAlert('زمان‌ها نباید تداخل داشته باشند', $(".groupBox").eq(i).find('input[name*="StartTime"]')); +// return; +// } +// // Check if the current start time is before the previous start time +// if (i > 0 && timeRanges[i].start < timeRanges[i - 1].start) { +// showAlert('ساعت جدید نباید کوچکتر از ساعت‌های قبلی باشد', $(".groupBox").eq(i).find('input[name*="StartTime"]')); +// return; +// } +// } +// } +//} + +$('.btn-register').click(function () { + var urlPostEditRollCall = ``; + if (urlPathname.indexOf('/Client/Company/WorkFlow/RollCall') > -1) { + urlPostEditRollCall = saveRollCallWorkTimeFromWorkFlowAjax; + } else { + urlPostEditRollCall = saveRollCallWorkTimeAjax; + } + + var dateFa = $('#dateFa').val().replaceAll("/", ""); + var dateEmployeeID = $('#employeeID').val() + '-' + dateFa; + + var loading = $('.btn-register .spinner-loading'); + + var data = $('#create-form').serialize(); + + $.ajax({ + async: false, + dataType: 'json', + type: 'POST', + url: urlPostEditRollCall, + headers: { "RequestVerificationToken": antiForgeryToken }, + data: data, + success: function (response) { + + if (response.success) { + loading.show(); + $('.alert-success-msg').show(); + $('.alert-success-msg p').text(response.message); + setTimeout(function () { + $('.alert-success-msg').hide(); + $('.alert-success-msg p').text(''); + loading.hide(); + }, 2000); + + if (urlPathname.indexOf('/Client/Company/WorkFlow/RollCall') > -1) { + _RefreshCountMenu(); + CountWorkFlowOfAbsentAndCut(); + //LoadWorkFlowsCutList(); + //loadWorkFlowsAbsentsList(); + //loadWorkFlowEmployeesWithoutLunchBreakList(); + //loadUndefinedRollCallsList(); + //loadOverlappingLeavesList(); + + var menuActive = $('#navbar-animmenu li.active').data('menu'); + switch (menuActive) { + case "absent": + /*loadWorkFlowsAbsentsList();*/ + $(`[data-absent-employee-date="${dateEmployeeID}"]`).remove(); + updateIndexesWorkFlow(`absent_${dateFa}`); + updateMainWorkFlow(`absentMain_${dateFa}`); + break; + case "cut": + //LoadWorkFlowsCutList(); + $(`[data-cut-employee-date="${dateEmployeeID}"]`).remove(); + updateIndexesWorkFlow(`cut_${dateFa}`); + updateMainWorkFlow(`cutMain_${dateFa}`); + break; + case "lunchBreak": + //loadWorkFlowEmployeesWithoutLunchBreakList(); + $(`[data-break-employee-date="${dateEmployeeID}"]`).remove(); + updateIndexesWorkFlow(`break_${dateFa}`); + updateMainWorkFlow(`breakMain_${dateFa}`); + break; + case "undefined": + //loadUndefinedRollCallsList(); + $(`[data-undefined-employee-date="${dateEmployeeID}"]`).remove(); + updateIndexesWorkFlow(`undefined_${dateFa}`); + updateMainWorkFlow(`undefinedMain_${dateFa}`); + break; + case "overlappingLeave": + //loadOverlappingLeavesList(); + $(`[data-leave-employee-date="${dateEmployeeID}"]`).remove(); + updateIndexesWorkFlow(`leave_${dateFa}`); + updateMainWorkFlow(`leaveMain_${dateFa}`); + break; + default: + } + + + $('#MainModal').modal('hide'); + } + + if (urlPathname.indexOf('/Client/Company/RollCall/CaseHistory') > -1) { + hasData = true; + dateIndex = 0; + dateEmployeeIndex = null; + $('#caseHistoryLoadData').html(''); + caseHistoryLoadAjax(); + loadUntilHeightExceeds(); + $('#MainModal').modal('hide'); + } + + + + //loading.show(); + //$('.alert-success-msg').show(); + //$('.alert-success-msg p').text(response.message); + //setTimeout(function () { + // $('.alert-success-msg').hide(); + // $('.alert-success-msg p').text(''); + // loading.hide(); + // //$('#MainModal').modal('hide'); + // window.location.reload(); + //}, 2000); + + //setTimeout(function () { + // window.location.reload(); + // //hasData = true; + // //dateIndex = 0; + // //dateEmployeeIndex = null; + // //$('#caseHistoryLoadData').html(''); + // //caseHistoryLoadAjax(); + // //loadUntilHeightExceeds(); + //}, 1000); + + } else { + $('.alert-msg').show(); + $('.alert-msg p').text(response.message); + setTimeout(function () { + $('.alert-msg').hide(); + $('.alert-msg p').text(''); + loading.hide(); + }, 3500); + } + }, + error: function (err) { + loading.hide(); + console.log(err); + } + }); +}); + +function toggleHeightControl() { + if ($('#employeeSelectAddModal').val() !== '0' && $('.form-control-date').val().length >= 10) { + $('.heightControll').removeClass('disable'); + } else { + $('.heightControll').addClass('disable'); + } +} \ No newline at end of file diff --git a/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/js/ModalEditRollCallUndefined.js b/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/js/ModalEditRollCallUndefined.js new file mode 100644 index 00000000..4a0c6caf --- /dev/null +++ b/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/js/ModalEditRollCallUndefined.js @@ -0,0 +1,384 @@ +var urlPathname = location.pathname; + +$(document).ready(function () { + + $("#modalWorkshopFullname").text($('#caseHistoryWorkshopFullname').text()); + $('.btn-register').addClass('disable'); + + $(".form-control-date").each(function () { + new Cleave(this, { + date: true, + delimiter: '/', + datePattern: ['Y', 'm', 'd'] + }); + }); + + $(".dateTime").each(function () { + new Cleave(this, { + time: true, + timePattern: ['h', 'm'] + }); + }); + + // updateDateInput(0); + + $(".btnAddTimeWork").on("click", function () { + var currentCount = $('.groupBox').length; + var $inputs = $('.dateTime'); + var allFilled = true; + + $inputs.each(function () { + if ($(this).val() === '') { + allFilled = false; + $('.btn-register').addClass('disable'); + showAlert('ابتدا ساعت شروع و پایان را وارد نمائید.', $(this)); + } + }); + + if (!allFilled) { + return false; + } + + + if (currentCount < 5) { + var namePlacementPersian = ""; + + switch (currentCount + 1) { + case 2: + namePlacementPersian = "دوم"; + break; + case 3: + namePlacementPersian = "سوم"; + break; + case 4: + namePlacementPersian = "چهارم"; + break; + case 5: + namePlacementPersian = "پنجم"; + break; + default: + } + + var timeWorkHtml = ` +
+
+
+
نوبت ${namePlacementPersian}
+
+
+
از
+ +
+
+
الی
+ +
+
+ +
+
+
`; + + $('#appendChildTimeWorkHtml').append(timeWorkHtml); + + new Cleave(`input[name="Command.RollCallRecords[${currentCount}].StartTime"]`, { + time: true, + timePattern: ['h', 'm'] + }); + + new Cleave(`input[name="Command.RollCallRecords[${currentCount}].EndTime"]`, { + time: true, + timePattern: ['h', 'm'] + }); + + updateAddButtonText(currentCount + 1); + + if (currentCount + 1 === 5) { + $(".btnAddTimeWork").hide(); + } + + + // Update Remove button enable/disable state + updateRemoveButtons(); + } + }); + $(document).on("click", ".btnRemoveTimeWork", function () { + $(this).closest(".groupBox").remove(); + var currentCount = $('.groupBox').length; + + updateAddButtonText(currentCount); + + if (currentCount < 5) { + $(".btnAddTimeWork").show(); + } + + // Update Remove button enable/disable state + updateRemoveButtons(); + }); +}); +function updateRemoveButtons() { + $(".btnRemoveTimeWork").addClass("disable"); + $(".btnRemoveTimeWork").last().removeClass("disable"); +} + +//function updateDateInput(daysToAdd) { +// var today = new Date(); +// today.setDate(today.getDate() + daysToAdd); +// var jalaaliDate = jalaali.toJalaali(today); +// var formattedDate = jalaaliDate.jy + '/' + (jalaaliDate.jm < 10 ? '0' + jalaaliDate.jm : jalaaliDate.jm) + '/' + (jalaaliDate.jd < 10 ? '0' + jalaaliDate.jd : jalaaliDate.jd); +// $('.form-control-date').val(formattedDate); +//} + +//updateAddButtonText(1); +function updateAddButtonText(currentCount) { + if (currentCount === 1) { + $('.btnAppendChildTimeWork').text('افزودن نوبت دوم'); + } else if (currentCount === 2) { + $('.btnAppendChildTimeWork').text('افزودن نوبت سوم'); + } else if (currentCount === 3) { + $('.btnAppendChildTimeWork').text('افزودن نوبت چهارم'); + } else if (currentCount === 4) { + $('.btnAppendChildTimeWork').text('افزودن نوبت پنجم'); + } + + let allFilled = true; + $('.dateTime').each(function () { + const value = $(this).val().trim(); + if (value === "" || !timeValidCheck(value)) { + allFilled = false; + return false; // Break the loop + } + }); + + if (allFilled) { + $('.btn-register').removeClass('disable'); + } else { + $('.btn-register').addClass('disable'); + } +} + +$(document).on('keyup', ".dateTime", function () { + let $input = $(this); + let value = $input.val(); + let lengthValue = value.length; + let currentCount = $('.groupBox').length; + + if (lengthValue >= 5) { + if (!timeValidCheck(value)) { + showAlert('ساعت را به درستی وارد نمائید', $input); + updateAddButtonText(currentCount); + } else { + clearAlert($input); + // validateAllTimes(); + updateAddButtonText(currentCount); + + // focusNextTimeInput($input); + } + } else { + updateAddButtonText(currentCount); + } +}); + +//function focusNextTimeInput(currentInput) { +// var inputs = $(".dateTime"); +// var currentIndex = inputs.index(currentInput); + +// if (currentIndex !== -1 && currentIndex < inputs.length - 1) { +// $(inputs[currentIndex + 1]).focus(); +// } +//} + +function showAlert(message, inputElement) { + inputElement.addClass("errored"); + $('.alert-msg').show().find('p').text(message); + setTimeout(function () { + clearAlert(inputElement); + }, 3500); +} + +function clearAlert(inputElement) { + inputElement.removeClass("errored"); + $('.alert-msg').hide().find('p').text(''); +} + +function timeValidCheck(value) { + const timePattern = /^([01]\d|2[0-3]):([0-5]\d)$/; + return timePattern.test(value); +} + +//function validateAllTimes() { +// let timeRanges = []; + +// $(".groupBox").each(function () { +// let startTime = $(this).find('input[name*="StartTime"]').val(); +// let endTime = $(this).find('input[name*="EndTime"]').val(); + +// if (startTime.length === 5 && endTime.length === 5) { +// let startParts = startTime.split(':'); +// let endParts = endTime.split(':'); +// let startInMinutes = parseInt(startParts[0]) * 60 + parseInt(startParts[1]); +// let endInMinutes = parseInt(endParts[0]) * 60 + parseInt(endParts[1]); +// timeRanges.push({ start: startInMinutes, end: endInMinutes }); +// } +// }); + +// // Check for conflicts and order +// for (let i = 0; i < timeRanges.length; i++) { +// for (let j = 0; j < i; j++) { +// if (timeRanges[i].start >= timeRanges[i].end) { +// showAlert('زمان شروع باید قبل از زمان پایان باشد', $(".groupBox").eq(i).find('input[name*="StartTime"]')); +// return; +// } + +// // Check for overlap with previous entries +// if (timeRanges[i].start < timeRanges[j].end && timeRanges[i].end > timeRanges[j].start) { +// showAlert('زمان‌ها نباید تداخل داشته باشند', $(".groupBox").eq(i).find('input[name*="StartTime"]')); +// return; +// } +// // Check if the current start time is before the previous start time +// if (i > 0 && timeRanges[i].start < timeRanges[i - 1].start) { +// showAlert('ساعت جدید نباید کوچکتر از ساعت‌های قبلی باشد', $(".groupBox").eq(i).find('input[name*="StartTime"]')); +// return; +// } +// } +// } +//} + +$('.btn-register').click(function () { + + var dateFa = $('#dateFa').val().replaceAll("/", ""); + var dateEmployeeID = $('#employeeID').val() + '-' + dateFa; + + var loading = $('.btn-register .spinner-loading'); + + var data = $('#create-form').serialize(); + + $.ajax({ + async: false, + dataType: 'json', + type: 'POST', + url: saveRollCallWorkTimeAjax, + headers: { "RequestVerificationToken": antiForgeryToken }, + data: data, + success: function (response) { + + if (response.success) { + loading.show(); + $('.alert-success-msg').show(); + $('.alert-success-msg p').text(response.message); + setTimeout(function () { + $('.alert-success-msg').hide(); + $('.alert-success-msg p').text(''); + loading.hide(); + }, 2000); + + if (urlPathname.indexOf('/Client/Company/WorkFlow/RollCall') > -1) { + _RefreshCountMenu(); + CountWorkFlowOfAbsentAndCut(); + //LoadWorkFlowsCutList(); + //loadWorkFlowsAbsentsList(); + //loadWorkFlowEmployeesWithoutLunchBreakList(); + //loadUndefinedRollCallsList(); + //loadOverlappingLeavesList(); + + var menuActive = $('#navbar-animmenu li.active').data('menu'); + switch (menuActive) { + case "absent": + /*loadWorkFlowsAbsentsList();*/ + $(`[data-absent-employee-date="${dateEmployeeID}"]`).remove(); + updateIndexesWorkFlow(`absent_${dateFa}`); + updateMainWorkFlow(`absentMain_${dateFa}`); + break; + case "cut": + //LoadWorkFlowsCutList(); + $(`[data-cut-employee-date="${dateEmployeeID}"]`).remove(); + updateIndexesWorkFlow(`cut_${dateFa}`); + updateMainWorkFlow(`cutMain_${dateFa}`); + break; + case "lunchBreak": + //loadWorkFlowEmployeesWithoutLunchBreakList(); + $(`[data-break-employee-date="${dateEmployeeID}"]`).remove(); + updateIndexesWorkFlow(`break_${dateFa}`); + updateMainWorkFlow(`breakMain_${dateFa}`); + break; + case "undefined": + //loadUndefinedRollCallsList(); + $(`[data-undefined-employee-date="${dateEmployeeID}"]`).remove(); + updateIndexesWorkFlow(`undefined_${dateFa}`); + updateMainWorkFlow(`undefinedMain_${dateFa}`); + break; + case "overlappingLeave": + //loadOverlappingLeavesList(); + $(`[data-leave-employee-date="${dateEmployeeID}"]`).remove(); + updateIndexesWorkFlow(`leave_${dateFa}`); + updateMainWorkFlow(`leaveMain_${dateFa}`); + break; + default: + } + + + $('#MainModal').modal('hide'); + } + + if (urlPathname.indexOf('/Client/Company/RollCall/CaseHistory') > -1) { + hasData = true; + dateIndex = 0; + dateEmployeeIndex = null; + $('#caseHistoryLoadData').html(''); + caseHistoryLoadAjax(); + loadUntilHeightExceeds(); + $('#MainModal').modal('hide'); + } + + + + //loading.show(); + //$('.alert-success-msg').show(); + //$('.alert-success-msg p').text(response.message); + //setTimeout(function () { + // $('.alert-success-msg').hide(); + // $('.alert-success-msg p').text(''); + // loading.hide(); + // //$('#MainModal').modal('hide'); + // window.location.reload(); + //}, 2000); + + //setTimeout(function () { + // window.location.reload(); + // //hasData = true; + // //dateIndex = 0; + // //dateEmployeeIndex = null; + // //$('#caseHistoryLoadData').html(''); + // //caseHistoryLoadAjax(); + // //loadUntilHeightExceeds(); + //}, 1000); + + } else { + $('.alert-msg').show(); + $('.alert-msg p').text(response.message); + setTimeout(function () { + $('.alert-msg').hide(); + $('.alert-msg p').text(''); + loading.hide(); + }, 3500); + } + }, + error: function (err) { + loading.hide(); + console.log(err); + } + }); +}); + +function toggleHeightControl() { + if ($('#employeeSelectAddModal').val() !== '0' && $('.form-control-date').val().length >= 10) { + $('.heightControll').removeClass('disable'); + } else { + $('.heightControll').addClass('disable'); + } +} \ No newline at end of file diff --git a/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/js/RollCall.js b/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/js/RollCall.js index e8a5734d..c515dd8e 100644 --- a/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/js/RollCall.js +++ b/ServiceHost/wwwroot/AssetsClient/pages/WorkFlow/js/RollCall.js @@ -250,7 +250,7 @@ function loadEmployeeListByWorkFlowsAbsents(date) { headers: { "RequestVerificationToken": antiForgeryToken }, success: function (response) { var data = response.data; - + console.log(data); if (response.success) { if (data.rollCallWorkFlowPerDayViewModels.length > 0) { @@ -272,14 +272,14 @@ function loadEmployeeListByWorkFlowsAbsents(date) {
نام پرسنل
${rollCallItem.employeeName} -

${rollCallItem.message}

+

پیغام:
-
${rollCallItem.message}
+
@@ -422,6 +422,7 @@ function loadEmployeeListByWorkFlowsCut(date) { headers: { "RequestVerificationToken": antiForgeryToken }, success: function (response) { var data = response.data; + if (response.success) { if (data.rollCallWorkFlowPerDayViewModels.length > 0) { @@ -444,14 +445,25 @@ function loadEmployeeListByWorkFlowsCut(date) {
نام پرسنل
${rollCallItem.employeeName} -

${rollCallItem.message}

+
+
`; + rollCallItem.timesList.forEach(function (timeItem) { + html += `
${timeItem.startTimeAndEndTimeAsMessage}
`; + }); + html += `
+
پیغام:
-
${rollCallItem.message}
+
+
`; + rollCallItem.timesList.forEach(function (timeItem) { + html += `
${timeItem.startTimeAndEndTimeAsMessage}
`; + }); + html += `
@@ -459,7 +471,7 @@ function loadEmployeeListByWorkFlowsCut(date) {
- @@ -800,7 +812,7 @@ function loadEmployeeListByUndefinedRollCalls(date) {
- @@ -1103,7 +1115,15 @@ function confirmAbsent(employeeId, dateFa) { } function showModalEditRollCall(employeeId, dateFa) { - window.location.href = `#showmodal=/Client/Company/RollCall/CaseHistory?employeeId=${employeeId}&date=${dateFa}&handler=Edit`; + window.location.href = `#showmodal=/Client/Company/WorkFlow/RollCall?employeeId=${employeeId}&date=${dateFa}&handler=EditRollCall`; +} + +function showModalEditRollCallAction(employeeId, dateFa) { + window.location.href = `#showmodal=/Client/Company/WorkFlow/RollCall?employeeId=${employeeId}&date=${dateFa}&handler=EditRollCallAction`; +} + +function showModalEditRollCallUndefined(employeeId, dateFa) { + window.location.href = `#showmodal=/Client/Company/WorkFlow/RollCall?employeeId=${employeeId}&date=${dateFa}&handler=EditRollCallForUndefined`; } function confirmCutAlert(rollCallId, employeeId, dateFa) { @@ -1125,14 +1145,14 @@ function confirmCutAlert(rollCallId, employeeId, dateFa) { } function confirmCut(rollCallId, employeeId, dateFa) { - var dateEmployeeID = employeeId + '-' + dateFa; + var dateEmployeeID = employeeId + '-' + dateFa.replaceAll("/", ""); $.ajax({ async: false, dataType: 'json', type: 'POST', url: postAjaxConfirmedCut, headers: { "RequestVerificationToken": antiForgeryToken }, - data: { 'rollCallId': Number(rollCallId) }, + data: { 'employeeId': Number(employeeId), 'absenceDate': dateFa }, success: function (response) { if (response.success) { CountWorkFlowOfAbsentAndCut(); @@ -1170,32 +1190,32 @@ function confirmCut(rollCallId, employeeId, dateFa) { case "absent": /*loadWorkFlowsAbsentsList();*/ $(`[data-absent-employee-date="${dateEmployeeID}"]`).remove(); - updateIndexesWorkFlow(`absent_${dateFa}`); - updateMainWorkFlow(`absentMain_${dateFa}`); + updateIndexesWorkFlow(`absent_${dateFa.replaceAll("/", "") }`); + updateMainWorkFlow(`absentMain_${dateFa.replaceAll("/", "") }`); break; case "cut": //LoadWorkFlowsCutList(); $(`[data-cut-employee-date="${dateEmployeeID}"]`).remove(); - updateIndexesWorkFlow(`cut_${dateFa}`); - updateMainWorkFlow(`cutMain_${dateFa}`); + updateIndexesWorkFlow(`cut_${dateFa.replaceAll("/", "") }`); + updateMainWorkFlow(`cutMain_${dateFa.replaceAll("/", "") }`); break; case "lunchBreak": //loadWorkFlowEmployeesWithoutLunchBreakList(); $(`[data-break-employee-date="${dateEmployeeID}"]`).remove(); - updateIndexesWorkFlow(`break_${dateFa}`); - updateMainWorkFlow(`breakMain_${dateFa}`); + updateIndexesWorkFlow(`break_${dateFa.replaceAll("/", "") }`); + updateMainWorkFlow(`breakMain_${dateFa.replaceAll("/", "") }`); break; case "undefined": //loadUndefinedRollCallsList(); $(`[data-undefined-employee-date="${dateEmployeeID}"]`).remove(); - updateIndexesWorkFlow(`undefined_${dateFa}`); - updateMainWorkFlow(`undefinedMain_${dateFa}`); + updateIndexesWorkFlow(`undefined_${dateFa.replaceAll("/", "") }`); + updateMainWorkFlow(`undefinedMain_${dateFa.replaceAll("/", "") }`); break; case "overlappingLeave": //loadOverlappingLeavesList(); $(`[data-leave-employee-date="${dateEmployeeID}"]`).remove(); - updateIndexesWorkFlow(`leave_${dateFa}`); - updateMainWorkFlow(`leaveMain_${dateFa}`); + updateIndexesWorkFlow(`leave_${dateFa.replaceAll("/", "") }`); + updateMainWorkFlow(`leaveMain_${dateFa.replaceAll("/", "") }`); break; default: } @@ -1394,11 +1414,12 @@ function updateMainWorkFlow(dateDiv) { $(this).text(text - 1); if (text - 1 === 0) { + $(`#${dateDiv}`).next().remove(); $(`#${dateDiv}`).remove(); - //$(`.openActionMain .Rtable-cell.width1 .Rtable-cell--content span`).each(function () { - // $(this).text(indexMain++); - //}); + $(`.Rtable-cell.width1 .Rtable-cell--content span`).each(function () { + $(this).text(indexMain++); + }); } }); } \ No newline at end of file diff --git a/WorkFlow/Application/WorkFlow.Application.Contracts/Shared/NotSlicedRollCallWorkFlowViewModel.cs b/WorkFlow/Application/WorkFlow.Application.Contracts/Shared/NotSlicedRollCallWorkFlowViewModel.cs new file mode 100644 index 00000000..b1af9464 --- /dev/null +++ b/WorkFlow/Application/WorkFlow.Application.Contracts/Shared/NotSlicedRollCallWorkFlowViewModel.cs @@ -0,0 +1,10 @@ +#nullable disable +namespace WorkFlow.Application.Contracts.Shared; + +public class NotSlicedRollCallWorkFlowViewModel +{ + public DateTime RollCallDate { get; set; } + public long EmployeeId { get; set; } + public string EmployeeName { get; set; } + public long RollCallId { get; set; } +} \ No newline at end of file diff --git a/WorkFlow/Application/WorkFlow.Application.Contracts/Shared/RollCallWorkFlowTimesViewModel.cs b/WorkFlow/Application/WorkFlow.Application.Contracts/Shared/RollCallWorkFlowTimesViewModel.cs new file mode 100644 index 00000000..2cb84259 --- /dev/null +++ b/WorkFlow/Application/WorkFlow.Application.Contracts/Shared/RollCallWorkFlowTimesViewModel.cs @@ -0,0 +1,8 @@ +#nullable disable +namespace WorkFlow.Application.Contracts.Shared; + +public class RollCallWorkFlowTimesViewModel +{ + public string StartTimeAndEndTimeAsMessage { get; set; } + public long RollCallId { get; set; } +} \ No newline at end of file diff --git a/WorkFlow/Application/WorkFlow.Application.Contracts/Shared/RollCallWorkFlowViewModel.cs b/WorkFlow/Application/WorkFlow.Application.Contracts/Shared/RollCallWorkFlowViewModel.cs index 08d325fa..f5fa0da4 100644 --- a/WorkFlow/Application/WorkFlow.Application.Contracts/Shared/RollCallWorkFlowViewModel.cs +++ b/WorkFlow/Application/WorkFlow.Application.Contracts/Shared/RollCallWorkFlowViewModel.cs @@ -6,7 +6,7 @@ public class RollCallWorkFlowViewModel public long EmployeeId { get; set; } public string EmployeeName { get; set; } public long WorkshopId { get; set; } - public string Message { get; set; } - public long RollCallId { get; set; } + public List TimesList { get; set; } + public DateTime RollCallDate { get; set; } -} +} \ No newline at end of file diff --git a/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow/IWorkFlowApplication.cs b/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow/IWorkFlowApplication.cs index 14f557b0..0e3186a3 100644 --- a/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow/IWorkFlowApplication.cs +++ b/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow/IWorkFlowApplication.cs @@ -7,32 +7,32 @@ namespace WorkFlow.Application.Contracts.WorkFlow; public interface IWorkFlowApplication { - Task CreateRollCallConfirmedAbsence(CreateRollCallConfirmedAbsence command); - Task CreateRollCallConfirmedWithoutLunchBreak(CreateRollCallConfirmedWithoutLunchBreak command); + Task CreateRollCallConfirmedAbsence(CreateRollCallConfirmedAbsence command); + Task CreateRollCallConfirmedWithoutLunchBreak(CreateRollCallConfirmedWithoutLunchBreak command); - Task GetCountAllWorkFlows(long workshopId); - Task GetRollCallAbsentsWorkFlows(long workshopId); - Task GetCountCutRollCallByBgService(long workshopId); - Task GetAllWorkFlowCount(long workshopId); - Task GetAllWorkFlowCountAsync(long workshopId); + Task GetCountAllWorkFlows(long workshopId); + Task GetRollCallAbsentsWorkFlows(long workshopId); + Task GetCountCutRollCallByBgService(long workshopId); + Task GetAllWorkFlowCount(long workshopId); + Task GetAllWorkFlowCountAsync(long workshopId); - Task GetAbsentRollCallWorkFlowsByDate(long workshopId, DateTime date); - Task GetEmployeesWithoutLunchBreakByDate(long workshopId, DateTime date); - Task GetRollCallWorkFlowsCutByBgServiceByDate(long workshopId, DateTime date); - Task GetUndefinedRollCallsByDate(long workshopId, DateTime date); + Task GetAbsentRollCallWorkFlowsByDate(long workshopId, DateTime date); + Task GetEmployeesWithoutLunchBreakByDate(long workshopId, DateTime date); + Task GetRollCallWorkFlowsCutByBgServiceByDate(long workshopId, DateTime date); + Task GetUndefinedRollCallsByDate(long workshopId, DateTime date); - Task GetRollCallsOverlappingLeaveByDate(long workshopId, - DateTime date); + Task GetRollCallsOverlappingLeaveByDate(long workshopId, + DateTime date); Task> GetConfirmAbsencesBy(long workshopId, DateTime start, DateTime end); Task> GetRollCallsOverlappingLeaves(long workshopId); Task> GetRollCallWorkFlowsCutByBgService(long workshopId); - Task> GetAbsentRollCallWorkFlows(long workshopId); - Task> GetUndefinedRollCalls(long workshopId); + Task> GetAbsentRollCallWorkFlows(long workshopId); + Task> GetUndefinedRollCalls(long workshopId); Task> GetEmployeesWithoutLunchBreak(long workshopId); - Task> GetEmployeesWithoutGroup(long workshopId); + Task> GetEmployeesWithoutGroup(long workshopId); } \ No newline at end of file diff --git a/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj b/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj index 2d7877cc..231fd693 100644 --- a/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj +++ b/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj @@ -7,6 +7,7 @@ + diff --git a/WorkFlow/Application/WorkFlow.Application/WorkFlowApplication.cs b/WorkFlow/Application/WorkFlow.Application/WorkFlowApplication.cs index 6394d09a..3be03ab7 100644 --- a/WorkFlow/Application/WorkFlow.Application/WorkFlowApplication.cs +++ b/WorkFlow/Application/WorkFlow.Application/WorkFlowApplication.cs @@ -1,4 +1,6 @@ using _0_Framework.Application; +using _0_Framework.Domain.CustomizeCheckoutShared.Enums; +using Company.Domain.RollCallAgg.DomainService; using WorkFlow.Application.Contracts.RollCallConfirmedAbsence; using WorkFlow.Application.Contracts.RollCallConfirmedWithoutLunchBreak; using WorkFlow.Application.Contracts.Shared; @@ -17,15 +19,17 @@ public class WorkFlowApplication : IWorkFlowApplication private readonly IWorkFlowRollCallACL _rollCallACL; private readonly IWorkFlowCheckoutACL _checkoutACL; private readonly IWorkFlowCustomizedWorkshopSettingsACL _customizedWorkshopSettingsACL; + private readonly IRollCallDomainService _rollCallDomainService; private readonly IRollCallConfirmedWithoutLunchBreakRepository _rollCallConfirmedWithoutLunchBreakRepository; - public WorkFlowApplication(IRollCallConfirmedAbsenceRepository absenceRepository, IWorkFlowRollCallACL rollCallACL, IWorkFlowCheckoutACL checkoutACL, IWorkFlowCustomizedWorkshopSettingsACL customizedWorkshopSettingsACL, IRollCallConfirmedWithoutLunchBreakRepository rollCallConfirmedWithoutLunchBreakRepository) + public WorkFlowApplication(IRollCallConfirmedAbsenceRepository absenceRepository, IWorkFlowRollCallACL rollCallACL, IWorkFlowCheckoutACL checkoutACL, IWorkFlowCustomizedWorkshopSettingsACL customizedWorkshopSettingsACL, IRollCallConfirmedWithoutLunchBreakRepository rollCallConfirmedWithoutLunchBreakRepository, IRollCallDomainService rollCallDomainService) { _absenceRepository = absenceRepository; _rollCallACL = rollCallACL; _checkoutACL = checkoutACL; _customizedWorkshopSettingsACL = customizedWorkshopSettingsACL; _rollCallConfirmedWithoutLunchBreakRepository = rollCallConfirmedWithoutLunchBreakRepository; + _rollCallDomainService = rollCallDomainService; } public async Task CreateRollCallConfirmedAbsence(CreateRollCallConfirmedAbsence command) @@ -89,18 +93,22 @@ public class WorkFlowApplication : IWorkFlowApplication count += (await GetAbsentRollCallWorkFlows(workshopId))?.Count ?? 0; count += (await GetRollCallWorkFlowsCutByBgService(workshopId))?.Count ?? 0; count += (await GetEmployeesWithoutLunchBreak(workshopId))?.Count ?? 0; - //count += (await GetRollCallsOverlappingLeaves(workshopId))?.Count ?? 0; + count += (await GetRollCallsOverlappingLeaves(workshopId))?.Count ?? 0; count += (await GetUndefinedRollCalls(workshopId))?.Count ?? 0; return count; } - public Task GetAllWorkFlowCountAsync(long workshopId) { return Task.FromResult(20); } + #region Methods For Ajax + + /// + ///غیبت ها + /// public async Task GetAbsentRollCallWorkFlowsByDate(long workshopId, DateTime date) { @@ -135,7 +143,8 @@ public class WorkFlowApplication : IWorkFlowApplication var newItem = new DailyRollCallWorkFlowViewModel() { DateTime = date.Date, - DateTimeFa = date.ToFarsi() + DateTimeFa = date.ToFarsi(), + }; //dont count absences before the last checkout @@ -148,36 +157,40 @@ public class WorkFlowApplication : IWorkFlowApplication { newItem.RollCallWorkFlowPerDayViewModels = absencesWithoutCheckout .Where(x => confirmedAbssences.All(y => x.EmployeeId != y.EmployeeId)) - .Select(x => new RollCallWorkFlowViewModel() - { - EmployeeId = x.EmployeeId, - EmployeeName = x.EmployeeName, - Message = "", - RollCallDate = x.RollCallDate, - RollCallId = x.RollCallId, - WorkshopId = x.WorkshopId - }).ToList(); + .ToList(); } else { - newItem.RollCallWorkFlowPerDayViewModels = absencesWithoutCheckout.Select(x => new RollCallWorkFlowViewModel() - { - EmployeeId = x.EmployeeId, - EmployeeName = x.EmployeeName, - Message = "", - RollCallDate = x.RollCallDate, - RollCallId = x.RollCallId, - WorkshopId = x.WorkshopId - - }).ToList(); + newItem.RollCallWorkFlowPerDayViewModels = absencesWithoutCheckout.ToList(); } + + + FilterWithOffset(workshopId, date,ref newItem); + newItem.DayOfWeekFa = newItem.DateTime.DayOfWeek.DayOfWeeKToPersian(); return newItem; } + + private void FilterWithOffset(long workshopId, DateTime date,ref DailyRollCallWorkFlowViewModel dailyRollCall) + { + if(date.Date == DateTime.Now.Date.AddDays(-1)) + { + foreach (var item in dailyRollCall.RollCallWorkFlowPerDayViewModels.ToList()) + { + var employeeOffset = _rollCallDomainService.GetEmployeeOffSetForRegularSettings(item.EmployeeId, workshopId); + if (DateTime.Now < DateTime.Today + employeeOffset.ToTimeSpan()) + dailyRollCall.RollCallWorkFlowPerDayViewModels.Remove(item); + } + } + } + + /// + /// بدون ثبت استراحت + /// public async Task GetEmployeesWithoutLunchBreakByDate(long workshopId, DateTime date) { var startOfDay = date.Date; @@ -193,11 +206,12 @@ public class WorkFlowApplication : IWorkFlowApplication .Where(x => !lastCheckouts.Any(y => y.EmployeeId == x.EmployeeId && y.CheckoutStart.Date <= x.RollCallDate.Date && y.CheckoutEnd.Date >= x.RollCallDate.Date) && activeEmployees.Any(y => y.EmployeeId == x.EmployeeId)).ToList(); - var employeeWithoutBreakTimeAndNotSliced = notSlicedRollCalls.Join(employeesWithoutBreakTime, x => x.EmployeeId, y => y.EmployeeId, (x, y) => - new { y.EmployeeId, x.EmployeeName, x.RollCallId, x.RollCallDate }).ToList(); + var employeeWithoutBreakTimeAndNotSliced = notSlicedRollCalls + .Join(employeesWithoutBreakTime, x => x.EmployeeId, y => y.EmployeeId, (x, y) => + new { x.EmployeeId, x.EmployeeName, x.RollCallId, x.RollCallDate }).ToList(); - var entites = _rollCallConfirmedWithoutLunchBreakRepository.GetByWorkshopId(workshopId, startOfDay, endOfDay).ToList(); + var confirmed = _rollCallConfirmedWithoutLunchBreakRepository.GetByWorkshopId(workshopId, startOfDay, endOfDay).ToList(); return new DailyRollCallConfirmedWithoutLunchBreakViewModel() { @@ -205,15 +219,19 @@ public class WorkFlowApplication : IWorkFlowApplication DateGr = date.Date, DayOfWeekFa = date.DayOfWeek.DayOfWeeKToPersian(), RollCallConfirmedWithoutLunchList = employeeWithoutBreakTimeAndNotSliced - .Where(x => entites.All(y => y.RollCallId != x.RollCallId)).Select(y => new RollCallConfirmedWithoutLunchBreakViewModel - { - EmployeeId = y.EmployeeId, - EmployeeName = y.EmployeeName, - RollCallId = y.RollCallId - }).ToList() + .Where(x => confirmed.All(y => y.RollCallId != x.RollCallId)).Select(y => new RollCallConfirmedWithoutLunchBreakViewModel + { + EmployeeId = y.EmployeeId, + EmployeeName = y.EmployeeName, + RollCallId = y.RollCallId + }).ToList() }; } + + /// + /// قطع شده توسط سیستم + /// public async Task GetRollCallWorkFlowsCutByBgServiceByDate(long workshopId, DateTime date) { var startOfDay = date.Date; @@ -235,296 +253,300 @@ public class WorkFlowApplication : IWorkFlowApplication RollCallWorkFlowPerDayViewModels = rollCallsForDate.RollCallWorkFlowPerDayViewModels .Where(y => !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && z.CheckoutStart.Date <= rollCallsForDate.DateTime.Date && z.CheckoutEnd.Date >= rollCallsForDate.DateTime.Date) && activeEmployees.Any(z => y.EmployeeId == z.EmployeeId)) - .Select(e => new RollCallWorkFlowViewModel() - { - EmployeeId = e.EmployeeId, - EmployeeName = e.EmployeeName, - Message = e.Message, - RollCallId = e.RollCallId - }).ToList(), + .ToList(), DayOfWeekFa = date.DayOfWeek.DayOfWeeKToPersian() }; return result; } + + + /// + /// تعیین وضعیت تردد پرسنل + /// public async Task GetUndefinedRollCallsByDate(long workshopId, DateTime date) { - var startOfDay = date.Date; - var endOfDay = startOfDay.AddDays(1).Date.AddTicks(-1); + var startOfDay = date.Date; + var endOfDay = startOfDay.AddDays(1).Date.AddTicks(-1); - startOfDay.AddMonthsFa(-2, out var twoMonthsAgo); + startOfDay.AddMonthsFa(-2, out var twoMonthsAgo); - var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, DateTime.Now.Date); - var rollCalls = _rollCallACL.GetUndefinedRollCalls(workshopId, startOfDay, endOfDay); - var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, startOfDay, endOfDay); + var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, DateTime.Now.Date); + var rollCalls = _rollCallACL.GetUndefinedRollCalls(workshopId, startOfDay, endOfDay); + var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, startOfDay, endOfDay); - var rollCallsForDate = rollCalls.FirstOrDefault(); - if (rollCallsForDate == null) - return new(); - var result = new DailyRollCallWorkFlowViewModel() - { - DateTime = date.Date, - DateTimeFa = date.ToFarsi(), - RollCallWorkFlowPerDayViewModels = rollCallsForDate.RollCallWorkFlowPerDayViewModels - .Where(y => !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && z.CheckoutStart.Date <= rollCallsForDate.DateTime.Date && - z.CheckoutEnd.Date >= rollCallsForDate.DateTime.Date) && activeEmployees.Any(z => y.EmployeeId == z.EmployeeId)) - .Select(e => new RollCallWorkFlowViewModel() - { - EmployeeId = e.EmployeeId, - EmployeeName = e.EmployeeName, - Message = e.Message, - RollCallId = e.RollCallId - }).ToList(), - DayOfWeekFa = date.DayOfWeek.DayOfWeeKToPersian() - }; - return result; + var rollCallsForDate = rollCalls.FirstOrDefault(); + if (rollCallsForDate == null) + return new(); + var result = new DailyRollCallWorkFlowViewModel() + { + DateTime = date.Date, + DateTimeFa = date.ToFarsi(), + RollCallWorkFlowPerDayViewModels = rollCallsForDate.RollCallWorkFlowPerDayViewModels + .Where(y => !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && z.CheckoutStart.Date <= rollCallsForDate.DateTime.Date && + z.CheckoutEnd.Date >= rollCallsForDate.DateTime.Date) && activeEmployees.Any(z => y.EmployeeId == z.EmployeeId)) + .ToList(), + DayOfWeekFa = date.DayOfWeek.DayOfWeeKToPersian() + }; + return result; } - - public async Task GetRollCallsOverlappingLeaveByDate(long workshopId, - DateTime date) + /// + /// تداخل مرخصی و حضور + /// + public async Task GetRollCallsOverlappingLeaveByDate(long workshopId, DateTime date) { - var startOfDay = date.Date; - var endOfDay = startOfDay.AddDays(1).Date.AddTicks(-1); + var startOfDay = date.Date; + var endOfDay = startOfDay.AddDays(1).Date.AddTicks(-1); - startOfDay.AddMonthsFa(-2, out var twoMonthsAgo); + startOfDay.AddMonthsFa(-2, out var twoMonthsAgo); - var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, DateTime.Now.Date); - var rollCalls = _rollCallACL.GetRollCallsOverlappingLeaves(workshopId, startOfDay, endOfDay); - var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, startOfDay, endOfDay); + var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, DateTime.Now.Date); + var rollCalls = _rollCallACL.GetRollCallsOverlappingLeaves(workshopId, startOfDay, endOfDay); + var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, startOfDay, endOfDay); - var rollCallsForDate = rollCalls.FirstOrDefault(x => x.Date == date); - if (rollCallsForDate == null) - return new(); + var rollCallsForDate = rollCalls.FirstOrDefault(x => x.Date == date); + if (rollCallsForDate == null) + return new(); - var result = new DailyWorkFlowEmployeesWithRollCallOnLeaveViewModel() - { - Date = date.Date, - DateFa = date.ToFarsi(), - EmployeesList = rollCallsForDate. EmployeesList - .Where(y => !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && - z.CheckoutStart.Date <= rollCallsForDate.Date.Date && - z.CheckoutEnd.Date >= rollCallsForDate.Date.Date) && activeEmployees.Any(z => y.EmployeeId == z.EmployeeId)) - .Select(e => new WorkFlowEmployeeWithRollCallOnLeaveViewModel() - { - EmployeeId = e.EmployeeId, - EmployeeFullName = e.EmployeeFullName, - LeaveId = e.LeaveId, - EndOfOverlapTime = e.EndOfOverlapTime, - StartOfOverlapTime = e.StartOfOverlapTime, - RollCallId = e.RollCallId, - EndOfOverlapDateFa = e.EndOfOverlapDateFa, - EndOfOverlapDateTime = e.EndOfOverlapDateTime, - StartOfOverlapDateFa = e.StartOfOverlapDateFa, - StartOfOverlapDateTime = e.StartOfOverlapDateTime - }).ToList(), - DayOfWeek = date.DayOfWeek.DayOfWeeKToPersian() - }; - return result; - } - public async Task> GetRollCallsOverlappingLeaves(long workshopId) - { - var now = DateTime.Now; - DateTime.Now.Date.AddMonthsFa(-2, out var twoMonthsAgo); - var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, now); - var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, twoMonthsAgo, now); - var rollCalls = _rollCallACL.GetRollCallsOverlappingLeaves(workshopId, twoMonthsAgo, now); - return rollCalls - .Select(x => new DailyWorkFlowEmployeesWithRollCallOnLeaveViewModel() - { - Date = x.Date, - DateFa = x.DateFa, - EmployeesList = x.EmployeesList - .Where(y => !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && - z.CheckoutStart.Date <= x.Date.Date && - z.CheckoutEnd.Date >= x.Date.Date) && activeEmployees.Any(z => y.EmployeeId == z.EmployeeId)) - .Select(e => new WorkFlowEmployeeWithRollCallOnLeaveViewModel() - { - EmployeeId = e.EmployeeId, - EmployeeFullName = e.EmployeeFullName, - LeaveId = e.LeaveId, - EndOfOverlapTime = e.EndOfOverlapTime, - StartOfOverlapTime = e.StartOfOverlapTime, - RollCallId = e.RollCallId, - EndOfOverlapDateFa = e.EndOfOverlapDateFa, - EndOfOverlapDateTime = e.EndOfOverlapDateTime, - StartOfOverlapDateFa = e.StartOfOverlapDateFa, - StartOfOverlapDateTime = e.StartOfOverlapDateTime - }).ToList(), - DayOfWeek = x.DayOfWeek - }) - .Where(y => y.EmployeesList != null && y.EmployeesList.Any()) - .OrderBy(x => x.Date).ToList(); + var result = new DailyWorkFlowEmployeesWithRollCallOnLeaveViewModel() + { + Date = date.Date, + DateFa = date.ToFarsi(), + EmployeesList = rollCallsForDate.EmployeesList + .Where(y => !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && + z.CheckoutStart.Date <= rollCallsForDate.Date.Date && + z.CheckoutEnd.Date >= rollCallsForDate.Date.Date) && activeEmployees.Any(z => y.EmployeeId == z.EmployeeId)) + .Select(e => new WorkFlowEmployeeWithRollCallOnLeaveViewModel() + { + EmployeeId = e.EmployeeId, + EmployeeFullName = e.EmployeeFullName, + LeaveId = e.LeaveId, + EndOfOverlapTime = e.EndOfOverlapTime, + StartOfOverlapTime = e.StartOfOverlapTime, + RollCallId = e.RollCallId, + EndOfOverlapDateFa = e.EndOfOverlapDateFa, + EndOfOverlapDateTime = e.EndOfOverlapDateTime, + StartOfOverlapDateFa = e.StartOfOverlapDateFa, + StartOfOverlapDateTime = e.StartOfOverlapDateTime + }).ToList(), + DayOfWeek = date.DayOfWeek.DayOfWeeKToPersian() + }; + return result; + } + #endregion - } - - - public async Task> GetConfirmAbsencesBy(long workshopId, DateTime start, DateTime end) + public async Task> GetConfirmAbsencesBy(long workshopId, DateTime start, DateTime end) { return _absenceRepository.GetConfirmAbsencesBy(workshopId, start, end); } - public async Task> GetUndefinedRollCalls(long workshopId) - { - var now = DateTime.Now; - DateTime.Now.Date.AddMonthsFa(-2, out var twoMonthsAgo); - var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, now); - List rollCalls = _rollCallACL.GetUndefinedRollCalls(workshopId, twoMonthsAgo, now.AddDays(-1).Date); - var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, twoMonthsAgo, now); - return rollCalls.Select(x => new DailyRollCallWorkFlowViewModel() + + #region Methods For OnGet + + + /// + /// لیست تداخل مرخصی و حضور + /// + public async Task> GetRollCallsOverlappingLeaves(long workshopId) { - DateTime = x.DateTime, - DateTimeFa = x.DateTimeFa, - RollCallWorkFlowPerDayViewModels = x.RollCallWorkFlowPerDayViewModels - .Where(y => - !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && z.CheckoutStart.Date <= x.DateTime.Date && - z.CheckoutEnd.Date >= x.DateTime.Date) && - activeEmployees.Any(z => z.EmployeeId == y.EmployeeId && x.DateTime.Date >= z.startActive && - x.DateTime.Date <= z.endActive)) - .Select(e => new RollCallWorkFlowViewModel() - { - EmployeeId = e.EmployeeId, - EmployeeName = e.EmployeeName, - Message = e.Message, - RollCallId = e.RollCallId - }).ToList(), - DayOfWeekFa = x.DateTime.DayOfWeek.DayOfWeeKToPersian() - }).Where(y => y.RollCallWorkFlowPerDayViewModels != null && y.RollCallWorkFlowPerDayViewModels.Any()).OrderBy(x => x.DateTime).ToList(); - } - - public async Task> GetRollCallWorkFlowsCutByBgService(long workshopId) - { - var now = DateTime.Now; - - DateTime.Now.Date.AddMonthsFa(-2, out var twoMonthsAgo); - - var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, now); - var rollCalls = _rollCallACL.GetRollCallWorkFlowsCutByBgService(workshopId, twoMonthsAgo, now.AddDays(-1).Date); - var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, twoMonthsAgo, now); - return rollCalls.Select(x => new DailyRollCallWorkFlowViewModel() - { - DateTime = x.DateTime, - DateTimeFa = x.DateTimeFa, - RollCallWorkFlowPerDayViewModels = x.RollCallWorkFlowPerDayViewModels - .Where(y => !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && z.CheckoutStart.Date <= x.DateTime.Date && - z.CheckoutEnd.Date >= x.DateTime.Date) && activeEmployees.Any(z => z.EmployeeId == y.EmployeeId && x.DateTime.Date >= z.startActive && - x.DateTime.Date <= z.endActive)) - .Select(e => new RollCallWorkFlowViewModel() - { - EmployeeId = e.EmployeeId, - EmployeeName = e.EmployeeName, - Message = e.Message, - RollCallId = e.RollCallId - }).ToList(), - DayOfWeekFa = x.DateTime.DayOfWeek.DayOfWeeKToPersian() - }).Where(y => y.RollCallWorkFlowPerDayViewModels != null && y.RollCallWorkFlowPerDayViewModels.Any()) - .OrderBy(x => x.DateTime).ToList(); - } - public async Task> GetAbsentRollCallWorkFlows(long workshopId) - { - - var now = DateTime.Now; - - DateTime.Now.Date.AddMonthsFa(-2, out var twoMonthsAgo); - - - var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, now); - - var absences = _rollCallACL.GetAbsentRollCallWorkFlows(workshopId, twoMonthsAgo, now.AddDays(-1).Date); - var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, twoMonthsAgo, now); - - var confirmedAbssences = await GetConfirmAbsencesBy(workshopId, twoMonthsAgo, - now); - - - var groupedConfirmedAbssencesByDate = confirmedAbssences.GroupBy(x => x.AbsenceDate.Date).ToList(); - - List result = new(); - - //iterating day by day in absences - foreach (var item in absences) - { - - var allAbsencesInDate = item.RollCallWorkFlowPerDayViewModels; - var confirmedAbssencesInDate = groupedConfirmedAbssencesByDate.FirstOrDefault(x => x.Key == item.DateTime.Date); - //set the date of new item - var newItem = new DailyRollCallWorkFlowViewModel() - { - DateTime = item.DateTime, - DateTimeFa = item.DateTime.ToFarsi() - }; - - //dont count absences before the last checkout - allAbsencesInDate = allAbsencesInDate.Where(x => !lastCheckouts.Any(y => - x.EmployeeId == y.EmployeeId && y.CheckoutStart <= item.DateTime.Date && y.CheckoutEnd >= item.DateTime.Date) && activeEmployees.Any(y => - item.DateTime.Date >= y.startActive && item.DateTime.Date <= y.endActive)).ToList(); - - - if (confirmedAbssencesInDate != null) - { - newItem.RollCallWorkFlowPerDayViewModels = allAbsencesInDate - .Where(x => confirmedAbssencesInDate.All(y => x.EmployeeId != y.EmployeeId)) - .Select(x => new RollCallWorkFlowViewModel() - { - EmployeeId = x.EmployeeId, - EmployeeName = x.EmployeeName, - Message = "" - }).ToList(); - } - else - { - newItem.RollCallWorkFlowPerDayViewModels = allAbsencesInDate.Select(x => new RollCallWorkFlowViewModel() + var now = DateTime.Now; + DateTime.Now.Date.AddMonthsFa(-2, out var twoMonthsAgo); + var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, now); + var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, twoMonthsAgo, now); + var rollCalls = _rollCallACL.GetRollCallsOverlappingLeaves(workshopId, twoMonthsAgo, now); + return rollCalls + .Select(x => new DailyWorkFlowEmployeesWithRollCallOnLeaveViewModel() { - EmployeeId = x.EmployeeId, - EmployeeName = x.EmployeeName, - Message = "" - }).ToList(); + Date = x.Date, + DateFa = x.DateFa, + EmployeesList = x.EmployeesList + .Where(y => !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && + z.CheckoutStart.Date <= x.Date.Date && + z.CheckoutEnd.Date >= x.Date.Date) && activeEmployees.Any(z => y.EmployeeId == z.EmployeeId)) + .Select(e => new WorkFlowEmployeeWithRollCallOnLeaveViewModel() + { + EmployeeId = e.EmployeeId, + EmployeeFullName = e.EmployeeFullName, + LeaveId = e.LeaveId, + EndOfOverlapTime = e.EndOfOverlapTime, + StartOfOverlapTime = e.StartOfOverlapTime, + RollCallId = e.RollCallId, + EndOfOverlapDateFa = e.EndOfOverlapDateFa, + EndOfOverlapDateTime = e.EndOfOverlapDateTime, + StartOfOverlapDateFa = e.StartOfOverlapDateFa, + StartOfOverlapDateTime = e.StartOfOverlapDateTime + }).ToList(), + DayOfWeek = x.DayOfWeek + }) + .Where(y => y.EmployeesList != null && y.EmployeesList.Any()) + .OrderBy(x => x.Date).ToList(); - } - - newItem.DayOfWeekFa = newItem.DateTime.DayOfWeek.DayOfWeeKToPersian(); - if (newItem.RollCallWorkFlowPerDayViewModels.Count > 0) - result.Add(newItem); } - return result.OrderBy(x => x.DateTime).ToList(); - } - public async Task> GetEmployeesWithoutLunchBreak(long workshopId) - { - var now = DateTime.Now.Date; - now.AddMonthsFa(-2, out var twoMonthsAgo); + /// + /// لیست وضعیت تردد پرسنل + /// + public async Task> GetUndefinedRollCalls(long workshopId) + { + var now = DateTime.Now; - var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, now); - var notSlicedRollCalls = _rollCallACL.GetNotSlicedRollCallsByWorkshopId(workshopId, twoMonthsAgo, now.AddDays(-1).Date); - var employeesWithoutBreakTime = _customizedWorkshopSettingsACL.GetEmployeesWithoutBreakTime(workshopId); + DateTime.Now.Date.AddMonthsFa(-2, out var twoMonthsAgo); - notSlicedRollCalls = notSlicedRollCalls - .Where(x => !lastCheckouts.Any(y => y.EmployeeId == x.EmployeeId && y.CheckoutStart.Date <= x.RollCallDate.Date && y.CheckoutEnd.Date >= x.RollCallDate.Date)).ToList(); - - var employeeWithoutBreakTimeAndNotSliced = notSlicedRollCalls.Join(employeesWithoutBreakTime, x => x.EmployeeId, y => y.EmployeeId, (x, y) => - new { y.EmployeeId, x.EmployeeName, x.RollCallId, x.RollCallDate }).ToList(); - - - var entites = _rollCallConfirmedWithoutLunchBreakRepository.GetByWorkshopId(workshopId, twoMonthsAgo, now).ToList(); - - return employeeWithoutBreakTimeAndNotSliced.Where(x => !entites.Any(y => y.RollCallId == x.RollCallId)) - .GroupBy(x => x.RollCallDate.Date).OrderBy(x => x.Key).Select(x => new DailyRollCallConfirmedWithoutLunchBreakViewModel + var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, now); + List rollCalls = _rollCallACL.GetUndefinedRollCalls(workshopId, twoMonthsAgo, now.AddDays(-1).Date); + var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, twoMonthsAgo, now); + return rollCalls.Select(x => new DailyRollCallWorkFlowViewModel() { - DateGr = x.Key.Date, - DateFa = x.Key.Date.ToFarsi(), - DayOfWeekFa = x.Key.DayOfWeek.DayOfWeeKToPersian(), - RollCallConfirmedWithoutLunchList = x.Select(y => new RollCallConfirmedWithoutLunchBreakViewModel - { - EmployeeId = y.EmployeeId, - EmployeeName = y.EmployeeName, - RollCallId = y.RollCallId - }).ToList() - }).ToList(); + DateTime = x.DateTime, + DateTimeFa = x.DateTimeFa, + RollCallWorkFlowPerDayViewModels = x.RollCallWorkFlowPerDayViewModels + .Where(y => + !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && z.CheckoutStart.Date <= x.DateTime.Date && + z.CheckoutEnd.Date >= x.DateTime.Date) && + activeEmployees.Any(z => z.EmployeeId == y.EmployeeId && x.DateTime.Date >= z.startActive && + x.DateTime.Date <= z.endActive)) + .ToList(), + DayOfWeekFa = x.DateTime.DayOfWeek.DayOfWeeKToPersian() + }).Where(y => y.RollCallWorkFlowPerDayViewModels != null && y.RollCallWorkFlowPerDayViewModels.Any()).OrderBy(x => x.DateTime).ToList(); + } + + /// + /// لیست قطع شده توسط سیستم + /// + public async Task> GetRollCallWorkFlowsCutByBgService(long workshopId) + { + var now = DateTime.Now; + + DateTime.Now.Date.AddMonthsFa(-2, out var twoMonthsAgo); + + var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, now); + var rollCalls = _rollCallACL.GetRollCallWorkFlowsCutByBgService(workshopId, twoMonthsAgo, now.AddDays(-1).Date); + var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, twoMonthsAgo, now); + return rollCalls.Select(x => new DailyRollCallWorkFlowViewModel() + { + DateTime = x.DateTime, + DateTimeFa = x.DateTimeFa, + RollCallWorkFlowPerDayViewModels = x.RollCallWorkFlowPerDayViewModels + .Where(y => !lastCheckouts.Any(z => z.EmployeeId == y.EmployeeId && z.CheckoutStart.Date <= x.DateTime.Date && + z.CheckoutEnd.Date >= x.DateTime.Date) && activeEmployees.Any(z => z.EmployeeId == y.EmployeeId && x.DateTime.Date >= z.startActive && + x.DateTime.Date <= z.endActive)) + .ToList(), + DayOfWeekFa = x.DateTime.DayOfWeek.DayOfWeeKToPersian() + }).Where(y => y.RollCallWorkFlowPerDayViewModels != null && y.RollCallWorkFlowPerDayViewModels.Any()) + .OrderBy(x => x.DateTime).ToList(); + } + + /// + /// لیست غیبت ها + /// + public async Task> GetAbsentRollCallWorkFlows(long workshopId) + { + + var now = DateTime.Now; + + DateTime.Now.Date.AddMonthsFa(-2, out var twoMonthsAgo); + + + var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, now); + + var absences = _rollCallACL.GetAbsentRollCallWorkFlows(workshopId, twoMonthsAgo, now.AddDays(-1).Date); + var activeEmployees = _rollCallACL.GetActiveWorkshopRollCallEmployees(workshopId, twoMonthsAgo, now); + + var confirmedAbssences = await GetConfirmAbsencesBy(workshopId, twoMonthsAgo, + now); + + + var groupedConfirmedAbssencesByDate = confirmedAbssences.GroupBy(x => x.AbsenceDate.Date).ToList(); + + List result = new(); + + //iterating day by day in absences + foreach (var item in absences) + { + + var allAbsencesInDate = item.RollCallWorkFlowPerDayViewModels; + var confirmedAbssencesInDate = groupedConfirmedAbssencesByDate.FirstOrDefault(x => x.Key == item.DateTime.Date); + //set the date of new item + var newItem = new DailyRollCallWorkFlowViewModel() + { + DateTime = item.DateTime, + DateTimeFa = item.DateTime.ToFarsi() + }; + + //dont count absences before the last checkout + allAbsencesInDate = allAbsencesInDate.Where(x => !lastCheckouts.Any(y => + x.EmployeeId == y.EmployeeId && y.CheckoutStart <= item.DateTime.Date && y.CheckoutEnd >= item.DateTime.Date) && activeEmployees.Any(y => + item.DateTime.Date >= y.startActive && item.DateTime.Date <= y.endActive)).ToList(); + + + if (confirmedAbssencesInDate != null) + { + newItem.RollCallWorkFlowPerDayViewModels = allAbsencesInDate + .Where(x => confirmedAbssencesInDate.All(y => x.EmployeeId != y.EmployeeId)) + .ToList(); + } + else + { + newItem.RollCallWorkFlowPerDayViewModels = allAbsencesInDate.ToList(); + + } + + newItem.DayOfWeekFa = newItem.DateTime.DayOfWeek.DayOfWeeKToPersian(); + FilterWithOffset(workshopId,item.DateTime,ref newItem); + if (newItem.RollCallWorkFlowPerDayViewModels.Count > 0) + result.Add(newItem); + + } + return result.OrderBy(x => x.DateTime).ToList(); + } + + /// + /// لیست بدون ثبت استرحت + /// + public async Task> GetEmployeesWithoutLunchBreak(long workshopId) + { + var now = DateTime.Now.Date; + + now.AddMonthsFa(-2, out var twoMonthsAgo); + + var lastCheckouts = _checkoutACL.GetLastCheckoutsByWorkshopIdForWorkFlow(workshopId, twoMonthsAgo, now); + var notSlicedRollCalls = _rollCallACL.GetNotSlicedRollCallsByWorkshopId(workshopId, twoMonthsAgo, now.AddDays(-1).Date); + var employeesWithoutBreakTime = _customizedWorkshopSettingsACL.GetEmployeesWithoutBreakTime(workshopId); + + notSlicedRollCalls = notSlicedRollCalls + .Where(x => !lastCheckouts.Any(y => y.EmployeeId == x.EmployeeId && y.CheckoutStart.Date <= x.RollCallDate.Date && y.CheckoutEnd.Date >= x.RollCallDate.Date)).ToList(); + + var employeeWithoutBreakTimeAndNotSliced = notSlicedRollCalls + .Join(employeesWithoutBreakTime, x => x.EmployeeId, + y => y.EmployeeId, (x, y) => + new { y.EmployeeId, x.EmployeeName, x.RollCallId, x.RollCallDate }).ToList(); + + + var entites = _rollCallConfirmedWithoutLunchBreakRepository.GetByWorkshopId(workshopId, twoMonthsAgo, now).ToList(); + + return employeeWithoutBreakTimeAndNotSliced.Where(x => !entites.Any(y => y.RollCallId == x.RollCallId)) + .GroupBy(x => x.RollCallDate.Date).OrderBy(x => x.Key).Select(x => new DailyRollCallConfirmedWithoutLunchBreakViewModel + { + DateGr = x.Key.Date, + DateFa = x.Key.Date.ToFarsi(), + DayOfWeekFa = x.Key.DayOfWeek.DayOfWeeKToPersian(), + RollCallConfirmedWithoutLunchList = x.Select(y => new RollCallConfirmedWithoutLunchBreakViewModel + { + EmployeeId = y.EmployeeId, + EmployeeName = y.EmployeeName, + RollCallId = y.RollCallId, + }).ToList() + }).ToList(); + + } + + #endregion + - } public async Task> GetEmployeesWithoutGroup(long workshopId) { return _customizedWorkshopSettingsACL.GetEmployeesWithoutGroup(workshopId); diff --git a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/RollCall/IWorkFlowRollCallACL.cs b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/RollCall/IWorkFlowRollCallACL.cs index 0ad946e2..25673f3c 100644 --- a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/RollCall/IWorkFlowRollCallACL.cs +++ b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/RollCall/IWorkFlowRollCallACL.cs @@ -24,7 +24,8 @@ public interface IWorkFlowRollCallACL /// int GetCountCutRollCallByBgService(long workshopId); - List GetNotSlicedRollCallsByWorkshopId(long workshopId, DateTime durationStart, DateTime durationEnd); + List GetNotSlicedRollCallsByWorkshopId(long workshopId, DateTime durationStart, + DateTime durationEnd); int GetRollCallAbsentsWorkFlowsCount(long workshopId, DateTime durationEnd, DateTime durationStart); List<(long EmployeeId, string EmployeeName, DateTime startActive, DateTime endActive)> GetActiveWorkshopRollCallEmployees(long workshopId, DateTime start, DateTime end); List GetAbsentRollCallWorkFlows(long workshopId, DateTime durationStart, DateTime durationEnd); diff --git a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/RollCall/WorkFlowRollCallACL.cs b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/RollCall/WorkFlowRollCallACL.cs index acbe9282..f5293ec0 100644 --- a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/RollCall/WorkFlowRollCallACL.cs +++ b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/RollCall/WorkFlowRollCallACL.cs @@ -1,4 +1,5 @@ using _0_Framework.Application; +using _0_Framework.Domain.CustomizeCheckoutShared.Enums; using CompanyManagment.App.Contracts.RollCall; using CompanyManagment.App.Contracts.RollCallEmployeeStatus; using CompanyManagment.App.Contracts.RollCallService; @@ -19,57 +20,6 @@ public class WorkFlowRollCallACL : IWorkFlowRollCallACL } - - public List GetRollCallWorkFlowsCutByBgService(long workshopId, DateTime start, DateTime end) - { - var result = _rollCallApplication.GetRollCallWorkFlowsCutByBgService(workshopId, start, end).Select(x => - { - return new DailyRollCallWorkFlowViewModel() - { - DateTime = x.DateGr, - DateTimeFa = x.DateFa, - RollCallWorkFlowPerDayViewModels = x.ActiveEmployees.Select(e => new RollCallWorkFlowViewModel() - { - EmployeeId = e.EmployeeId, - EmployeeName = e.EmployeeFullName, - Message = $"{TimeOnly.FromDateTime(e.StartDate!.Value):HH:mm} الی {TimeOnly.FromDateTime(e.EndDate.Value):HH:mm}", - RollCallId = e.Id - }).ToList(), - DayOfWeekFa = x.DateGr.DayOfWeek.DayOfWeeKToPersian(), - }; - }).Where(x => x.RollCallWorkFlowPerDayViewModels.Count > 0).ToList(); - return result; - } - public List GetRollCallsOverlappingLeaves(long workshopId, DateTime start, DateTime end) - { - var rollCalls= _rollCallApplication.GetOverlappedRollCallsWithLeaveInDates(workshopId, start, end).Select(x => - new WorkFlowEmployeeWithRollCallOnLeaveViewModel() - { - EmployeeFullName = x.EmployeeFullName, - EmployeeId = x.EmployeeId, - RollCallId = x.RollCallId, - EndOfOverlapDateFa = x.EndOfOverlapDateFa, - EndOfOverlapTime = x.EndOfOverlapTime, - LeaveId = x.LeaveId, - StartOfOverlapDateFa = x.StartOfOverlapDateFa, - StartOfOverlapTime = x.StartOfOverlapTime, - EndOfOverlapDateTime = x.EndOfOverlapDateTime, - StartOfOverlapDateTime = x.StartOfOverlapDateTime - }).GroupBy(x=>x.StartOfOverlapDateTime.Date).Select(x=> new DailyWorkFlowEmployeesWithRollCallOnLeaveViewModel - { - DayOfWeek = x.Key.DayOfWeek.DayOfWeeKToPersian(), - DateFa = x.Key.ToFarsi(), - EmployeesList = x.ToList(), - Date = x.Key - }).ToList(); - - return rollCalls; - } - public List<(long EmployeeId, string EmployeeName, DateTime startActive, DateTime endActive)> GetActiveWorkshopRollCallEmployees(long workshopId, DateTime start, DateTime end) - { - return _rollCallEmployeeStatusApplication.GetActiveByWorkshopIdInDate(workshopId, start, end).Select(x => (x.EmployeeId, x.EmployeeName, x.StartDateGr, x.EndDateGr)) - .ToList(); - } public int GetCountCutRollCallByBgService(long workshopId) { var now = DateTime.Now; @@ -83,7 +33,59 @@ public class WorkFlowRollCallACL : IWorkFlowRollCallACL { return GetAbsentRollCallWorkFlows(workshopId, durationStart, durationEnd).Count; } + public List<(long EmployeeId, string EmployeeName, DateTime startActive, DateTime endActive)> GetActiveWorkshopRollCallEmployees(long workshopId, DateTime start, DateTime end) + { + return _rollCallEmployeeStatusApplication.GetActiveByWorkshopIdInDate(workshopId, start, end).Select(x => (x.EmployeeId, x.EmployeeName, x.StartDateGr, x.EndDateGr)) + .ToList(); + } + public List GetRollCallWorkFlowsCutByBgService(long workshopId, DateTime start, DateTime end) + { + return _rollCallApplication.GetRollCallWorkFlowsCutByBgService(workshopId, start, end).Select(x => + { + return new DailyRollCallWorkFlowViewModel() + { + DateTime = x.DateGr, + DateTimeFa = x.DateFa, + RollCallWorkFlowPerDayViewModels = x.ActiveEmployees.GroupBy(y=>y.EmployeeId).Select(e => new RollCallWorkFlowViewModel() + { + EmployeeId = e.Key, + EmployeeName = e.First().EmployeeFullName, + TimesList = e.Select(y=>new RollCallWorkFlowTimesViewModel() + { + RollCallId = y.Id, + StartTimeAndEndTimeAsMessage = $"{TimeOnly.FromDateTime(y.StartDate!.Value):HH:mm} الی {TimeOnly.FromDateTime(y.EndDate.Value):HH:mm}" + }).ToList(), + }).ToList(), + DayOfWeekFa = x.DateGr.DayOfWeek.DayOfWeeKToPersian(), + }; + }).Where(x => x.RollCallWorkFlowPerDayViewModels.Count > 0).ToList(); + } + public List GetRollCallsOverlappingLeaves(long workshopId, DateTime start, DateTime end) + { + var rollCalls = _rollCallApplication.GetOverlappedRollCallsWithLeaveInDates(workshopId, start, end).Select(x => + new WorkFlowEmployeeWithRollCallOnLeaveViewModel() + { + EmployeeFullName = x.EmployeeFullName, + EmployeeId = x.EmployeeId, + RollCallId = x.RollCallId, + EndOfOverlapDateFa = x.EndOfOverlapDateFa, + EndOfOverlapTime = x.EndOfOverlapTime, + LeaveId = x.LeaveId, + StartOfOverlapDateFa = x.StartOfOverlapDateFa, + StartOfOverlapTime = x.StartOfOverlapTime, + EndOfOverlapDateTime = x.EndOfOverlapDateTime, + StartOfOverlapDateTime = x.StartOfOverlapDateTime + }).GroupBy(x => x.StartOfOverlapDateTime.Date).Select(x => new DailyWorkFlowEmployeesWithRollCallOnLeaveViewModel + { + DayOfWeek = x.Key.DayOfWeek.DayOfWeeKToPersian(), + DateFa = x.Key.ToFarsi(), + EmployeesList = x.ToList(), + Date = x.Key + }).ToList(); + + return rollCalls; + } public List GetAbsentRollCallWorkFlows(long workshopId, DateTime durationStart, DateTime durationEnd) { return _rollCallApplication.GetWorkshopAbsentHistory(workshopId, durationStart, durationEnd).Select(x => new DailyRollCallWorkFlowViewModel() @@ -96,7 +98,6 @@ public class WorkFlowRollCallACL : IWorkFlowRollCallACL RollCallWorkFlowPerDayViewModels = x.ActiveEmployees.Select(a => new RollCallWorkFlowViewModel() { EmployeeId = a.EmployeeId, - Message = "", EmployeeName = a.EmployeeFullName, WorkshopId = a.WorkshopId }).ToList() @@ -104,11 +105,10 @@ public class WorkFlowRollCallACL : IWorkFlowRollCallACL } - - public List GetNotSlicedRollCallsByWorkshopId(long workshopId, DateTime durationStart, DateTime durationEnd) + public List GetNotSlicedRollCallsByWorkshopId(long workshopId, DateTime durationStart, DateTime durationEnd) { return _rollCallApplication.GetNotSlicedRollCallsByWorkshopId(workshopId, durationStart, durationEnd) - .Select(x => new RollCallWorkFlowViewModel + .Select(x => new NotSlicedRollCallWorkFlowViewModel() { EmployeeId = x.EmployeeId, EmployeeName = x.EmployeeFullName, @@ -117,6 +117,7 @@ public class WorkFlowRollCallACL : IWorkFlowRollCallACL }).ToList(); } + public RollCallWorkFlowViewModel GetDetails(long rollCallId) { var entity = _rollCallApplication.GetDetails(rollCallId); @@ -126,7 +127,13 @@ public class WorkFlowRollCallACL : IWorkFlowRollCallACL { EmployeeId = entity.EmployeeId, EmployeeName = entity.EmployeeFullName, - RollCallId = rollCallId, + TimesList = + [ + new RollCallWorkFlowTimesViewModel() + { + RollCallId =entity.Id + } + ], RollCallDate = entity.DateGr.Date, WorkshopId = entity.WorkshopId }; @@ -135,7 +142,6 @@ public class WorkFlowRollCallACL : IWorkFlowRollCallACL { return _rollCallServiceApplication.GetActiveServiceByWorkshopId(workshopId); } - public List GetUndefinedRollCalls(long workshopId, DateTime durationStart, DateTime durationEnd) { var result = _rollCallApplication.GetUndefinedRollCallWorkFlowsService(workshopId, durationStart, durationEnd).Select(x => @@ -149,7 +155,13 @@ public class WorkFlowRollCallACL : IWorkFlowRollCallACL EmployeeId = e.EmployeeId, EmployeeName = e.EmployeeFullName, //Message = $"{TimeOnly.FromDateTime(e.StartDate!.Value):HH:mm} الی {TimeOnly.FromDateTime(e.EndDate.Value):HH:mm}", - RollCallId = e.Id + TimesList = + [ + new RollCallWorkFlowTimesViewModel() + { + RollCallId =e.Id + } + ], }).ToList(), DayOfWeekFa = x.DayOfWeekFa, };