///<summary>
        /// Method Invocation of wrapper classes
        ///<summary>
        protected static FR_L5S_SUSfP_1708 Invoke(DbConnection Connection, DbTransaction Transaction, string ConnectionString, P_L5S_SUSfP_1708 Parameter, CSV2Core.SessionSecurity.SessionSecurityTicket securityTicket = null)
        {
            bool cleanupConnection  = Connection == null;
            bool cleanupTransaction = Transaction == null;

            FR_L5S_SUSfP_1708 functionReturn = new FR_L5S_SUSfP_1708();

            try
            {
                if (cleanupConnection == true)
                {
                    Connection = CSV2Core_MySQL.Support.DBSQLSupport.CreateConnection(ConnectionString);
                    Connection.Open();
                }
                if (cleanupTransaction == true)
                {
                    Transaction = Connection.BeginTransaction();
                }

                functionReturn = Execute(Connection, Transaction, Parameter, securityTicket);

                #region Cleanup Connection/Transaction
                //Commit the transaction
                if (cleanupTransaction == true)
                {
                    Transaction.Commit();
                }
                //Close the connection
                if (cleanupConnection == true)
                {
                    Connection.Close();
                }
                #endregion
            }
            catch (Exception ex)
            {
                try
                {
                    if (cleanupTransaction == true && Transaction != null)
                    {
                        Transaction.Rollback();
                    }
                }
                catch { }

                try
                {
                    if (cleanupConnection == true && Connection != null)
                    {
                        Connection.Close();
                    }
                }
                catch { }

                throw new Exception("Exception occured in method cls_CreateUpdate_Slots_for_Practice", ex);
            }
            return(functionReturn);
        }
        protected static FR_L5S_SUSfP_1708 Execute(DbConnection Connection, DbTransaction Transaction, P_L5S_SUSfP_1708 Parameter, CSV2Core.SessionSecurity.SessionSecurityTicket securityTicket = null)
        {
            //Leave UserCode region to enable user code saving
            #region UserCode
            var returnValue = new FR_L5S_SUSfP_1708();

            //ucitati sve potrebne podatke
            L5ATW_ANfTID_1855[]  appointmnetTypesDB    = null;
            L5TE_GNWTfOID_1506[] officeNonWorkingTimes = null;
            L5TE_GSHfOID_1540[]  officeStandardHours   = null;
            L5TE_GSAfT_1645[]    allEmployeesDB        = null;
            L5TE_GTEFAS_1440[]   allStaffExceptions    = null;
            L5TE_GDAfT_1844[]    devices      = null;
            ORM_HEC_Doctor[]     hecDoctorsDB = null;
            ORM_HEC_Doctor_AssignableAppointmentType[] hecDoctor2ATDB = null;
            ORM_PPS_TSK_Task_Template_OrganizationalUnitAvailability[] ppsTaskTemplate2Office = null;
            L5BTS_GBSfPID_1141[] slotsAndCombinationForPractice = null;
            L3P_GPfT_1537[]      professionsForTenant           = null;

            //Parallel.Invoke(

            //    () =>
            //    {
            //        appointmnetTypesDB = cls_Get_AppointmentTypeWeb_Name_for_TenantID.Invoke(Transaction.Connection.ConnectionString, securityTicket).Result;
            //    },

            //    () =>
            //    {
            //        officeNonWorkingTimes = cls_Get_NonWorkingTimesforOfficeID.Invoke(Transaction.Connection.ConnectionString, new P_L5TE_GNWTfOID_1506() { OfficeID = Parameter.PracticeID }, securityTicket).Result;
            //    },

            //    () =>
            //    {
            //        officeStandardHours = cls_Get_StandardHours_for_OfficeID.Invoke(Transaction.Connection.ConnectionString, new P_L5TE_GSHfOID_1540() { OfficeID = Parameter.PracticeID }, securityTicket).Result;
            //    }
            //    ,

            //    () =>
            //    {
            //        allEmployeesDB = cls_Get_Staff_with_Availability_for_TenantID.Invoke(Transaction.Connection.ConnectionString, securityTicket).Result;
            //    },

            //    () =>
            //    {
            //        allStaffExceptions = cls_Get_TimeExceptionsForAllStaff.Invoke(Transaction.Connection.ConnectionString, securityTicket).Result;
            //    },

            //    () =>
            //    {
            //        devices = cls_Get_Devices_Availability_for_TenantID.Invoke(Transaction.Connection.ConnectionString, securityTicket).Result;
            //    },

            //    () =>
            //    {
            //        hecDoctorsDB = ORM_HEC_Doctor.Query.Search(Transaction.Connection.ConnectionString, new ORM_HEC_Doctor.Query() { Tenant_RefID = securityTicket.TenantID, IsDeleted = false }).ToArray();
            //    },

            //    () =>
            //    {
            //        hecDoctor2ATDB = ORM_HEC_Doctor_AssignableAppointmentType.Query.Search(Transaction.Connection.ConnectionString, new ORM_HEC_Doctor_AssignableAppointmentType.Query() { Tenant_RefID = securityTicket.TenantID, IsDeleted = false }).ToArray();
            //    },

            //    () =>
            //    {
            //        ppsTaskTemplate2Office = ORM_PPS_TSK_Task_Template_OrganizationalUnitAvailability.Query.Search(Transaction.Connection.ConnectionString, new ORM_PPS_TSK_Task_Template_OrganizationalUnitAvailability.Query() { Tenant_RefID = securityTicket.TenantID, IsDeleted = false, CMN_STR_Office_RefID = Parameter.PracticeID }).ToArray();
            //    },

            //    () =>
            //    {
            //        slotsAndCombinationForPractice = cls_Get_BookableSlots_for_PracticeID.Invoke(Transaction.Connection.ConnectionString, new P_L5BTS_GBSfPID_1141() { OfficeID = Parameter.PracticeID, AvaTypeMatchingID = EnumUtils.GetEnumDescription(AvailabilityType.WebBooking) }, securityTicket).Result;
            //    },

            //    () =>
            //    {
            //        professionsForTenant = cls_Get_Professions_for_TenantID.Invoke(Transaction.Connection.ConnectionString, securityTicket).Result;
            //    }
            //);

            appointmnetTypesDB    = cls_Get_AllAppointmentTypes_Name_for_TenantID.Invoke(Connection, Transaction, securityTicket).Result;
            officeNonWorkingTimes = cls_Get_NonWorkingTimesforOfficeID.Invoke(Connection, Transaction, new P_L5TE_GNWTfOID_1506()
            {
                OfficeID = Parameter.PracticeID
            }, securityTicket).Result;
            officeStandardHours = cls_Get_StandardHours_for_OfficeID.Invoke(Connection, Transaction, new P_L5TE_GSHfOID_1540()
            {
                OfficeID = Parameter.PracticeID
            }, securityTicket).Result;
            allEmployeesDB     = cls_Get_Staff_with_Availability_for_TenantID.Invoke(Connection, Transaction, securityTicket).Result;
            allStaffExceptions = cls_Get_TimeExceptionsForAllStaff.Invoke(Connection, Transaction, securityTicket).Result;
            devices            = cls_Get_Devices_Availability_for_TenantID.Invoke(Connection, Transaction, securityTicket).Result;
            hecDoctorsDB       = ORM_HEC_Doctor.Query.Search(Connection, Transaction, new ORM_HEC_Doctor.Query()
            {
                Tenant_RefID = securityTicket.TenantID, IsDeleted = false
            }).ToArray();
            hecDoctor2ATDB = ORM_HEC_Doctor_AssignableAppointmentType.Query.Search(Connection, Transaction, new ORM_HEC_Doctor_AssignableAppointmentType.Query()
            {
                Tenant_RefID = securityTicket.TenantID, IsDeleted = false
            }).ToArray();
            ppsTaskTemplate2Office = ORM_PPS_TSK_Task_Template_OrganizationalUnitAvailability.Query.Search(Connection, Transaction, new ORM_PPS_TSK_Task_Template_OrganizationalUnitAvailability.Query()
            {
                Tenant_RefID = securityTicket.TenantID, IsDeleted = false, CMN_STR_Office_RefID = Parameter.PracticeID
            }).ToArray();
            slotsAndCombinationForPractice = cls_Get_BookableSlots_for_PracticeID.Invoke(Connection, Transaction, new P_L5BTS_GBSfPID_1141()
            {
                OfficeID = Parameter.PracticeID
            }, securityTicket).Result;
            professionsForTenant = cls_Get_Professions_for_TenantID.Invoke(Connection, Transaction, securityTicket).Result;
            L5TE_GSAfT_1645[] employeesFromPracticeDB = allEmployeesDB.Where(e => e.Offices != null && e.Offices.FirstOrDefault(o => o.OfficeID == Parameter.PracticeID) != null).ToArray();


            //prepakuj podatke u zeljeni model
            var practice = ModelConvertor.ConvertPracticeDBData(Parameter.PracticeID, officeNonWorkingTimes, officeStandardHours, appointmnetTypesDB.Where(w => ppsTaskTemplate2Office.Select(s => s.PPS_TSK_Task_Template_RefID).Contains(w.PPS_TSK_Task_TemplateID)).ToArray());
            practice.Staff   = ModelConvertor.ConvertStaffDBData(Parameter.PracticeID, employeesFromPracticeDB, hecDoctorsDB, hecDoctor2ATDB, allStaffExceptions, professionsForTenant);
            practice.Devices = ModelConvertor.ConvertDevice(devices.Where(d => d.CMN_STR_Office_RefID == Parameter.PracticeID).ToArray());

            foreach (var appointmentType in practice.AppointmentTypes)
            {
                List <Staff> staffForThisAppointmentType = new List <Staff>(practice.Staff.Where(s => s.AvailableAppointmentTypeIds.Contains(appointmentType.ID)));

                var  persistedSlotsForAT = slotsAndCombinationForPractice.Where(w => w.TaskTemplate_RefID == appointmentType.ID).ToArray();
                bool needDevices         = appointmentType.RequiredDeviceTypes != null && appointmentType.RequiredDeviceTypes.Count > 0;

                //ucititati sve appointmente tog tipa u praksi
                var scheduledAppParam = new P_L5A_GAABDfObTfD_1915()
                {
                    FromDate       = DateTime.Now.AddDays(-1),
                    OfficeID       = Parameter.PracticeID,
                    TaskTemplateID = appointmentType.ID
                };
                var scheduledAppointmentsDB = cls_Get_AllAppointment_BaseData_for_Office_by_Type_from_Date.Invoke(Connection, Transaction, scheduledAppParam, securityTicket).Result;

                //ucitane appointmente prebaciti u zeljeni model
                var scheduledAppointments = ModelConvertor.ConvertAppointments(scheduledAppointmentsDB);

                var posibleResourceCombinations = new List <ResourceCombination>();

                //iskalkulisati sve moguce kombinacije osoblja za zelejni tip appointmenta
                var staffCombinations             = StaffAvailabiltyCalculations.GetFilteredStaffForAppointmentTypeBySkills(staffForThisAppointmentType, appointmentType);
                var weekFramesPerStaffCombination = new Dictionary <Guid, List <RangeIntersection> >();
                foreach (var comb in staffCombinations)
                {
                    weekFramesPerStaffCombination.Add(comb.ID, StaffAvailabiltyCalculations.CalculateWeekAvailableFramesForStaffCombination(comb.Data, practice.Availabilities));
                }


                //iskalkulisati sve moguce kombinacije osoblja za zelejni tip appointmenta
                if (needDevices)
                {
                    var deviceInstanceCombinations     = DeviceAvailabilityCalculations.GetFilteredDeviceForAppointmentType(practice.Devices, appointmentType);
                    var weekFramesPerDeviceCombination = new Dictionary <Guid, List <RangeIntersection> >();
                    foreach (var comb in deviceInstanceCombinations)
                    {
                        var allAbilities = comb.Data.Select(s => s.Availabilities).ToList();
                        allAbilities.Add(practice.Availabilities);
                        weekFramesPerDeviceCombination.Add(comb.ID, StaffAvailabiltyCalculations.FindAllIntersections(allAbilities));
                    }

                    foreach (var deviceCombination in weekFramesPerDeviceCombination)
                    {
                        foreach (var staffCombination in weekFramesPerStaffCombination)
                        {
                            var allIntersects = new List <List <RangeIntersection> >();
                            allIntersects.Add(staffCombination.Value);
                            allIntersects.Add(deviceCombination.Value);
                            var resourceCombinationIntersections = StaffAvailabiltyCalculations.FindAllIntersections(allIntersects);
                            if (resourceCombinationIntersections.Count > 0)
                            {
                                posibleResourceCombinations.Add(new ResourceCombination()
                                {
                                    AppointmentTypeID          = appointmentType.ID,
                                    OfficeID                   = Parameter.PracticeID,
                                    StaffCombination           = staffCombinations.Single(s => s.ID == staffCombination.Key),
                                    DeviceInstancesCombination = deviceInstanceCombinations.Single(s => s.ID == deviceCombination.Key),
                                    TimeIntersections          = resourceCombinationIntersections,
                                    IsDeviceNeeded             = true
                                });
                            }
                        }
                    }
                }
                else
                {
                    foreach (var staffCombination in weekFramesPerStaffCombination)
                    {
                        posibleResourceCombinations.Add(new ResourceCombination()
                        {
                            AppointmentTypeID = appointmentType.ID,
                            OfficeID          = Parameter.PracticeID,
                            StaffCombination  = staffCombinations.Single(s => s.ID == staffCombination.Key),
                            TimeIntersections = staffCombination.Value
                        });
                    }
                }

                //pranaci validne slotove od postojecih
                List <TimeSlot> calculatedSlots = new List <TimeSlot>();

                foreach (var combination in posibleResourceCombinations)
                {
                    //slotovi za narednih 6 meseci u odnosu na nedeljne slotove - izuzeci

                    var combinationSlots = TimeRangeUtils.CalculateTimeFramesFromRanges(combination.TimeIntersections, appointmentType.DurationInSec);
                    var exceptions       = new List <ExceptionTime>(practice.Exceptions);
                    exceptions.AddRange(combination.StaffCombination.Data.Select(select => select.Staff).SelectMany(c => c.Exceptions).ToList());
                    if (combination.IsDeviceNeeded)
                    {
                        exceptions.AddRange(combination.DeviceInstancesCombination.Data.SelectMany(s => s.Exceptions).ToList());
                    }
                    var makeSlotsForNext3Months = StaffAvailabiltyCalculations.MakeSlotsForPeriod(combinationSlots, exceptions, DateTime.Now, DateTime.Now.AddMonths(3));

                    var thisCombinationAppointments = scheduledAppointments.Where(w => w.StaffIDs.Intersect(combination.StaffCombination.Data.Select(s => s.Staff.ID)).Any()).ToList();
                    if (needDevices)
                    {
                        thisCombinationAppointments = thisCombinationAppointments.Where(w => w.DeviceInstanceIDs.Intersect(combination.DeviceInstancesCombination.Data.Select(s => s.ID)).Any()).ToList();
                    }

                    foreach (var slot in makeSlotsForNext3Months)
                    {
                        if (!TimeRangeUtils.SlotOverlapingWithAppontmentArray(slot, thisCombinationAppointments))
                        {
                            var slotMatch = calculatedSlots.FirstOrDefault(s => s.PeriodStart == slot.PeriodStart && s.PeriodEnd == slot.PeriodEnd);

                            if (!TimeRangeUtils.SlotOverlapingWithSlotArray(slot, calculatedSlots))
                            {
                                if (slotMatch == null)
                                {
                                    slot.ResourceCombination.Add(combination);
                                    calculatedSlots.Add(slot);
                                }
                                else
                                {
                                    slotMatch.ResourceCombination.Add(combination);
                                }
                            }
                            else
                            {
                                if (slotMatch != null)
                                {
                                    slotMatch.ResourceCombination.Add(combination);
                                }
                            }
                        }
                    }
                }

                var updatedSlotIDs = new List <Guid>();
                var slotParam      = new List <P_L5BTS_CSwRC_1156_Slot>();
                foreach (var slot in calculatedSlots)
                {
                    var persistedSlot = persistedSlotsForAT.FirstOrDefault(f => f.FreeInterval_Start == slot.PeriodStart && f.FreeInterval_End == slot.PeriodEnd);
                    if (persistedSlot != null) // postoji takav slot u bazi
                    {
                        updatedSlotIDs.Add(persistedSlot.PPS_TSK_BOK_BookableTimeSlotID);
                        var keepCombinationsIDs = new List <Guid>();

                        bool isSlotWebBookable = false;
                        var  combinationList   = new List <P_L5BTS_CSwRC_1156_Slot_Combination>();


                        foreach (var slotCombination in slot.ResourceCombination)
                        {
                            bool isCombinaitonWebBookable = true;

                            // da li je vidljiv za web bookovanje
                            foreach (var staff in slotCombination.StaffCombination.Data)
                            {
                                if (isCombinaitonWebBookable)
                                {
                                    if (!StaffAvailabiltyCalculations.IsStaffWebBookableInThisTameRange(staff.Staff, slot))
                                    {
                                        isCombinaitonWebBookable = false;
                                    }
                                }
                            }


                            if (!isSlotWebBookable && isCombinaitonWebBookable)
                            {
                                isSlotWebBookable = true;
                            }

                            // proveri da li vec postoji takva kobinacija u bazi
                            bool thisCombinationMatchedWithSomePersisted = false;
                            foreach (var persistedCombination in persistedSlot.Combinations)
                            {
                                if (CombinationUtils.CompareCombinations(slotCombination, persistedCombination))
                                {
                                    thisCombinationMatchedWithSomePersisted = true;
                                    keepCombinationsIDs.Add(persistedCombination.PPS_TSK_BOK_AvailableResourceCombinationID);
                                    break;
                                }
                            }


                            if (thisCombinationMatchedWithSomePersisted)                                                                                                                                  // ako postoji preskoci je
                            {
                                if ((persistedSlot.SlotType.GlobalPropertyMatchingID == EnumUtils.GetEnumDescription(AvailabilityType.WebBooking)) != isSlotWebBookable && appointmentType.IsWebBookable) // ako nije isti tip slota
                                {
                                    slotParam.Add(new P_L5BTS_CSwRC_1156_Slot()
                                    {
                                        Combinations  = combinationList.ToArray(),
                                        End           = slot.PeriodEnd,
                                        Start         = slot.PeriodStart,
                                        SlotID        = persistedSlot.PPS_TSK_BOK_BookableTimeSlotID,
                                        IsWebBookable = isSlotWebBookable && appointmentType.IsWebBookable
                                    });
                                }
                                continue;
                            }



                            var staffList          = new List <P_L5BTS_CSwRC_1156_Slot_Combination_Staff>();
                            var deviceInstanceList = new List <P_L5BTS_CSwRC_1156_Slot_Combination_DeviceInstance>();
                            foreach (var staff in slotCombination.StaffCombination.Data)
                            {
                                staffList.Add(new P_L5BTS_CSwRC_1156_Slot_Combination_Staff()
                                {
                                    CreatedFor_TaskTemplateRequiredStaff_RefID = staff.ID,
                                    StaffID = staff.Staff.ID
                                });
                                //if (isWebBookable)
                                //    if (!StaffAvailabiltyCalculations.IsStaffWebBookableInThisTameRange(staff.Staff, slot))
                                //        isWebBookable = false;
                            }
                            if (slotCombination.IsDeviceNeeded)
                            {
                                foreach (var deviceInstance in slotCombination.DeviceInstancesCombination.Data)
                                {
                                    deviceInstanceList.Add(new P_L5BTS_CSwRC_1156_Slot_Combination_DeviceInstance()
                                    {
                                        DeviceInstanceID = deviceInstance.ID
                                    });
                                }
                            }

                            combinationList.Add(new P_L5BTS_CSwRC_1156_Slot_Combination()
                            {
                                DeviceInstance = deviceInstanceList.ToArray(),
                                Staff          = staffList.ToArray()
                            });
                        }

                        if (combinationList.Count > 0 ||
                            ((persistedSlot.SlotType.GlobalPropertyMatchingID == EnumUtils.GetEnumDescription(AvailabilityType.WebBooking)) != isSlotWebBookable && appointmentType.IsWebBookable) ||
                            keepCombinationsIDs.Count != persistedSlot.Combinations.Count())
                        {
                            slotParam.Add(new P_L5BTS_CSwRC_1156_Slot()
                            {
                                Combinations         = combinationList.ToArray(),
                                End                  = slot.PeriodEnd,
                                Start                = slot.PeriodStart,
                                SlotID               = persistedSlot.PPS_TSK_BOK_BookableTimeSlotID,
                                IsWebBookable        = isSlotWebBookable && appointmentType.IsWebBookable,
                                CombinationForDelete = new P_L5BTS_CSwRC_1156_Slot_CombinationsForDelete()
                                {
                                    CombinationIDs = persistedSlot.Combinations.Select(s => s.PPS_TSK_BOK_AvailableResourceCombinationID).Except(keepCombinationsIDs).ToArray()
                                }
                            });
                        }
                    }
                    else // slot ne postoji, napravi novi
                    {
                        bool isSlotWebBookable = false;
                        var  combinationList   = new List <P_L5BTS_CSwRC_1156_Slot_Combination>();
                        foreach (var slotCombination in slot.ResourceCombination)
                        {
                            bool isCombinaitonWebBookable = true;
                            var  staffList          = new List <P_L5BTS_CSwRC_1156_Slot_Combination_Staff>();
                            var  deviceInstanceList = new List <P_L5BTS_CSwRC_1156_Slot_Combination_DeviceInstance>();
                            foreach (var staff in slotCombination.StaffCombination.Data)
                            {
                                staffList.Add(new P_L5BTS_CSwRC_1156_Slot_Combination_Staff()
                                {
                                    CreatedFor_TaskTemplateRequiredStaff_RefID = staff.ID,
                                    StaffID = staff.Staff.ID
                                });
                                if (isCombinaitonWebBookable)
                                {
                                    if (!StaffAvailabiltyCalculations.IsStaffWebBookableInThisTameRange(staff.Staff, slot))
                                    {
                                        isCombinaitonWebBookable = false;
                                    }
                                }
                            }
                            if (slotCombination.IsDeviceNeeded)
                            {
                                foreach (var deviceInstance in slotCombination.DeviceInstancesCombination.Data)
                                {
                                    deviceInstanceList.Add(new P_L5BTS_CSwRC_1156_Slot_Combination_DeviceInstance()
                                    {
                                        DeviceInstanceID = deviceInstance.ID
                                    });
                                }
                            }

                            combinationList.Add(new P_L5BTS_CSwRC_1156_Slot_Combination()
                            {
                                DeviceInstance = deviceInstanceList.ToArray(),
                                Staff          = staffList.ToArray()
                            });

                            if (!isSlotWebBookable && isCombinaitonWebBookable)
                            {
                                isSlotWebBookable = true;
                            }
                        }

                        slotParam.Add(new P_L5BTS_CSwRC_1156_Slot()
                        {
                            Combinations  = combinationList.ToArray(),
                            End           = slot.PeriodEnd,
                            Start         = slot.PeriodStart,
                            SlotID        = Guid.NewGuid(),
                            IsWebBookable = isSlotWebBookable && appointmentType.IsWebBookable
                        });
                    }
                }

                var createSlotBulkParam = new P_L5BTS_CSwRC_1156()
                {
                    AppointmentTypeID = appointmentType.ID,
                    OfficeID          = Parameter.PracticeID,
                    Slots             = slotParam.ToArray()
                };

                var persistedSlotForDeleteIDs = persistedSlotsForAT.Where(s => !updatedSlotIDs.Contains(s.PPS_TSK_BOK_BookableTimeSlotID)).Select(s => s.PPS_TSK_BOK_BookableTimeSlotID).ToArray();
                cls_Delete_Slots.Invoke(Connection, Transaction, new P_L5BTS_DS_1510()
                {
                    SlotIDs = persistedSlotForDeleteIDs
                }, securityTicket);
                cls_Create_Slots_with_ResourceCombinations.Invoke(Connection, Transaction, createSlotBulkParam, securityTicket);
            }

            return(returnValue);

            #endregion UserCode
        }