/*
Legacy dashboard controller preserved for rollback.
The active controller now lives in: app/components/dashboard/dashboard_taskify.js

//blank line is required
app.controller('dashboard',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	rootUrl=$rootScope.site_url;
	module="dashboard/";
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');}});
	
//	$scope.type='';
	$scope.expanse=0;
	$scope.followup=0;
	
	$scope.type=localStorage.getItem("type");
	
	if(localStorage.getItem("type")=='User')
	{
		$('#user_privileges1').remove();
	}
//	$("#l_username1").html(localStorage.getItem("staff_name"));
//	$("#l_usertype").html(localStorage.getItem("type"));
//	$("#l_username2").html(localStorage.getItem("username"));
	
	$scope.filldata=function()
	{
		$scope.type=localStorage.getItem("type");
		
		if(localStorage.getItem("type")=='Administrator')
		{
//			console.log("hide");
		}
	}
	if(!localStorage.getItem("username"))
	{
		$http.get(rootUrl+"dashboard/fetch_userdata").success(function(data)
		{
			if(data.type=='A') data.type='Administrator';
			if(data.type=='U') data.type='User';
			if(data.type=='D') data.type='Developer';
			
			if(data.staff_name) localStorage.setItem("staff_name",data.staff_name);
			if(data.username) localStorage.setItem("username",data.username);
			if(data.grade) localStorage.setItem("grade",data.grade);
			if(data.image) localStorage.setItem("image",data.image);
			if(data.emp_id) localStorage.setItem("emp_id",data.emp_id);
			if(data.type) localStorage.setItem("type",data.type);
			if(data.login) localStorage.setItem("login",data.login);
			$scope.filldata();
		})	
	}
	else
	{
		$scope.filldata();
	}
	
	$('.input-daterange').datepicker({});
	$scope.cs={};
	$scope.qs={};
	$http.get(rootUrl+"dashboard/fetch_emp_bday").success(function(data){
		if(data.length>0)
			$scope.ebd=data;
	})
	$http.get(rootUrl+"dashboard/attendance").success(function(data)
	{
		$scope.$total_strength=data['total'];
		$scope.$today_absent=data['absent'];
		$scope.$today_present=data['present'];
	})
	$http.get(rootUrl+"dashboard/get_task").success(function(data)
	{
		$scope.$month_task=data['total_month_task'];
		$scope.$month_run_task=data['total_month_run'];
	})
	// checking for Members
	$http.get(rootUrl+"dashboard/fetch_admin").success(function(data)
	{
		$scope.$admin_rows=data;
	})
	$http.get(rootUrl+"dashboard/fetch_user").success(function(data)
	{
		$scope.$users_rows=data;
	})
	$http.get(rootUrl+"dashboard/fetch_emp").success(function(data)
	{
		$scope.$employee_rows=data;
	})
	// checking for Members End here
	
	$http.get(rootUrl+"dashboard/fetch_journals_data").success(function(data)
	{
		if(data['debit']>0||data['credit']>0)
		{
			$scope.expanse=1;
			$scope.debit=data['debit'];
			$scope.credit=data['credit'];
			$scope.total_trans=data['total_trans'];
		}
	})
	// checking privilege for each user
	$http.get(rootUrl+"dashboard/check_privilege").success(function(data)
	{
		if(data==1)
			$scope.followup=1;
	})
	
		
	$scope.filter_today=function()//Today's Follow Up
	{
		$scope.cs={};
		$scope.qs={};
		$scope.isLoading=true;
		var today=new Date();
		var date=today.getDate();
		if(date.toString().length==1) date='0'+date;
		var month=today.getMonth()+1;
		if(month.toString().length==1) month='0'+month;
		var year=today.getFullYear();
		tdate=date+"/"+month+"/"+year;
		
		$http.get(rootUrl+"hr_follow_up/dash_data?date="+tdate).success(function(data)
		{
			$scope.foldatas=data;
			$scope.isLoading=false;
		})
	}
	$scope.filter_today();
	
	$scope.filter_date=function()// Reminder Follow
	{
		$scope.isLoading=true;
		$scope.cs={};
		if($scope.qs.esdate && $scope.qs.eedate)
		{
			url=rootUrl+"hr_follow_up/dash_data?join=1&esdate="+$scope.qs.esdate+"&eedate="+$scope.qs.eedate;
			$http.get(url).success(function(data)
			{
				$scope.foldatas=data;
				$scope.rows=data.length;
				$scope.isLoading=false;
			})
		}
	}
			
	$scope.filter_date2=function(x)//Contact Follow
	{
		$scope.isLoading=true;
		$scope.qs={};
		if($scope.cs.csdate && $scope.cs.cedate)
		{
			url=rootUrl+"hr_follow_up/dash_data?csdate="+$scope.cs.csdate+"&cedate="+$scope.cs.cedate;
			$http.get(url).success(function(data)
			{
				$scope.foldatas=data;
				$scope.rows=data.length;
				$scope.isLoading=false;
			})
		}
	}
	
		
}]);
*/
// Taskify-style dashboard controller.
// This is intentionally kept in a separate file so legacy dashboard logic remains preserved.
app.directive('taskifyTodoDragSource', [function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.attr('draggable', 'true');
            element.on('dragstart', function () {
                var bucket = attrs.taskifyTodoBucket || 'warm';
                var index = parseInt(attrs.taskifyTodoDragSource, 10);
                scope.$applyAsync(function () {
                    scope.todoDragStart(bucket, index);
                });
            });
        }
    };
}]);

app.directive('taskifyTodoDropTarget', [function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('dragover', function (event) {
                event.preventDefault();
            });
            element.on('drop', function (event) {
                event.preventDefault();
                var bucket = attrs.taskifyTodoBucket || 'warm';
                var index = parseInt(attrs.taskifyTodoDropTarget, 10);
                scope.$applyAsync(function () {
                    scope.todoDrop(bucket, index, event);
                });
            });
        }
    };
}]);

app.controller('dashboard', ['$scope', '$rootScope', '$http', '$q', '$timeout', function ($scope, $rootScope, $http, $q, $timeout) {
    var rootUrl = $rootScope.site_url;
    var todoWidgetResizeBound = false;
    function initRatingSelect2() {
        if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
            return;
        }
        $timeout(function () {
            $('.rating-select2').each(function () {
                var $el = $(this);
                if (!$el.is('select')) return;
                if ($el.data('select2')) {
                    $el.select2('destroy');
                }
                $el.select2({
                    width: '100%',
                    minimumResultsForSearch: 0
                });
            });
        }, 0, false);
    }

    function ensureTodoPrioritySelectNative() {
        if (typeof $ === 'undefined' || !$.fn) {
            return;
        }
        $timeout(function () {
            var $select = $('.taskify-todo-widget__composer-select');
            if (!$select.length) {
                return;
            }
            if ($select.data('select2')) {
                $select.select2('destroy');
            }
            $select.removeClass('select2-hidden-accessible');
            $select.removeAttr('data-select2-id');
            $select.removeAttr('tabindex');
            $select.next('.select2, .select2-container').remove();
        }, 0, false);
    }

    $scope.identity = {
        name: localStorage.getItem('staff_name') || 'Team Member',
        type: localStorage.getItem('type') || 'User',
        grade: localStorage.getItem('grade') || '',
        emp_id: localStorage.getItem('emp_id') || '',
        com_id: localStorage.getItem('com_id') || '',
        branch_id: localStorage.getItem('branch_id') || ''
    };

    $scope.dashboardMeta = {
        today: '',
        loading: true,
        error: ''
    };

    $scope.summary = {
        adminCount: 0,
        userCount: 0,
        employeeCount: 0
    };

    $scope.roleAccess = {
        isAdmin: false,
        canAttendance: false,
        canTask: false,
        canFollowup: false,
        canStaff: false,
        canPayslip: false,
        canFinance: false,
        canTodo: true,
        canRating: false,
        canCharts: false,
        allowedModules: []
    };

    $scope.filterOptions = [
        { id: 'today', label: 'Today' },
        { id: 'yesterday', label: 'Yesterday' },
        { id: 'weekly', label: 'Weekly' },
        { id: 'monthly', label: 'Monthly' },
        { id: 'quarterly', label: 'Quarterly' },
        { id: 'half_yearly', label: 'Half Yearly' },
        { id: 'yearly', label: 'Yearly' },
        { id: 'date_range', label: 'Date Range' },
        { id: 'all', label: 'All Data' }
    ];

    $scope.filters = {
        preset: 'monthly',
        from: '',
        to: ''
    };

    $scope.filterWindow = {
        label: 'Current Month'
    };

    var rawData = {
        followupsToday: [],
        followupsAll: [],
        tasksAll: [],
        staffAll: [],
        payslipsAll: [],
        birthdaysAll: [],
        ratingsAll: []
    };

    $scope.stats = {
        attendance: { present: 0, absent: 0, total: 0 },
        tasks: { monthly: 0, running: 0, completed: 0 },
        journals: { debit: 0, credit: 0, total: 0 }
    };

    $scope.progress = {
        attendance: 0,
        runningTasks: 0,
        todayRunningTasks: 0,
        taskCompletion: 0,
        debitShare: 0,
        payslipApproval: 0,
        reminderCoverage: 0
    };

    $scope.quickStats = {
        activeStaff: 0,
        inactiveStaff: 0,
        approvedPayslips: 0,
        pendingPayslips: 0,
        dueReminders: 0,
        todayRunningTasks: 0,
        todayTotalTasks: 0,
        todayBirthdays: 0,
        todayBirthdayNames: [],
        todayBirthdayNamesText: 'No active birthdays today',
        todayBirthdayWishText: ''
    };

    $scope.todoWidget = {
        tasks: [],
        visibleTasks: [],
        groups: { hot: [], warm: [], cold: [] },
        visibleGroups: { hot: [], warm: [], cold: [] },
        stats: { total: 0, completed: 0, pending: 0 },
        form: { title: '', priority_type: 'warm' },
        loading: false,
        drag: { bucket: '', index: -1 },
        visibleLimit: 6,
        listMaxHeight: 320,
        hiddenCount: 0
    };

    $scope.followups = [];
    $scope.reminderFeed = [];
    $scope.taskFeed = [];
    $scope.staffFeed = [];
    $scope.payslips = [];
    $scope.birthdays = [];
    $scope.ratingPanel = {
        loading: false,
        error: '',
        isGradeA: false,
        employees: [],
        customers: [],
        filters: {
            emp_id: '',
            c_id: '',
            period: 'all'
        },
        periodOptions: [
            { id: 'all', label: 'All' },
            { id: 'this_month', label: 'This Month' },
            { id: 'last_month', label: 'Last Month' },
            { id: 'months_12', label: '12 Months (Till Last Month)' }
        ],
        summary: {
            average: 0,
            count: 0,
            high: 0,
            mid: 0,
            low: 0,
            windowLabel: 'All Time',
            employeeName: '',
            customerName: 'All Customers'
        }
    };

    $scope.visuals = {
        donuts: {
            attendance: {},
            tasks: {},
            journals: {},
            payslips: {}
        },
        bars: [],
        gradeMix: [],
        activityMix: []
    };

    function toNumber(value) {
        var parsed = parseFloat(value);
        return isNaN(parsed) ? 0 : parsed;
    }

    function toCount(value) {
        if (angular.isArray(value)) {
            return value.length;
        }
        if (value && typeof value === 'object') {
            if (value.total !== undefined) return toNumber(value.total);
            if (value.count !== undefined) return toNumber(value.count);
            if (value.rows !== undefined) return toNumber(value.rows);
        }
        return toNumber(value);
    }

    function percent(part, whole) {
        if (!whole || whole <= 0) {
            return 0;
        }
        var pct = Math.round((toNumber(part) / toNumber(whole)) * 100);
        if (pct < 0) return 0;
        if (pct > 100) return 100;
        return pct;
    }

    function asArray(value) {
        return angular.isArray(value) ? value : [];
    }

    function sameDay(dateA, dateB) {
        if (!dateA || !dateB) return false;
        return dateA.getFullYear() === dateB.getFullYear() &&
            dateA.getMonth() === dateB.getMonth() &&
            dateA.getDate() === dateB.getDate();
    }

    function parseDMY(value) {
        if (!value || typeof value !== 'string') {
            return null;
        }
        var parts = value.split('/');
        if (parts.length !== 3) {
            return null;
        }
        var day = parseInt(parts[0], 10);
        var month = parseInt(parts[1], 10);
        var year = parseInt(parts[2], 10);
        if (!day || !month || !year) {
            return null;
        }
        return new Date(year, month - 1, day);
    }

    function parseISODate(value) {
        if (!value || typeof value !== 'string') {
            return null;
        }
        var parts = value.split('-');
        if (parts.length !== 3) {
            return null;
        }
        var year = parseInt(parts[0], 10);
        var month = parseInt(parts[1], 10);
        var day = parseInt(parts[2], 10);
        if (!year || !month || !day) {
            return null;
        }
        return new Date(year, month - 1, day);
    }

    function parseDashDMY(value) {
        if (!value || typeof value !== 'string') {
            return null;
        }
        var parts = value.split('-');
        if (parts.length !== 3) {
            return null;
        }
        var day = parseInt(parts[0], 10);
        var month = parseInt(parts[1], 10);
        var year = parseInt(parts[2], 10);
        if (!day || !month || !year) {
            return null;
        }
        return new Date(year, month - 1, day);
    }

    function parseFlexibleDate(value) {
        if (!value && value !== 0) {
            return null;
        }
        if (value instanceof Date) {
            return normalizeDate(value);
        }
        var text = String(value).trim();
        if (!text) {
            return null;
        }

        if (text.indexOf('/') !== -1) {
            return parseDMY(text);
        }

        if (text.indexOf('-') !== -1) {
            if (/^\d{4}-\d{2}-\d{2}$/.test(text)) {
                return parseISODate(text);
            }
            return parseDashDMY(text);
        }

        return normalizeDate(text);
    }

    function normalizeDate(dateValue) {
        if (!dateValue) return null;
        var d = new Date(dateValue);
        if (isNaN(d.getTime())) return null;
        return new Date(d.getFullYear(), d.getMonth(), d.getDate());
    }

    function formatISO(dateValue) {
        var d = normalizeDate(dateValue);
        if (!d) return '';
        var month = d.getMonth() + 1;
        var day = d.getDate();
        var m = month < 10 ? '0' + month : '' + month;
        var dd = day < 10 ? '0' + day : '' + day;
        return d.getFullYear() + '-' + m + '-' + dd;
    }

    function formatDMY(dateValue) {
        var d = normalizeDate(dateValue);
        if (!d) return '';
        var month = d.getMonth() + 1;
        var day = d.getDate();
        var m = month < 10 ? '0' + month : '' + month;
        var dd = day < 10 ? '0' + day : '' + day;
        return dd + '/' + m + '/' + d.getFullYear();
    }

    function inRange(dateValue, range) {
        var d = normalizeDate(dateValue);
        if (!d) return false;
        if (!range || (!range.start && !range.end)) {
            return true;
        }
        if (range.start && d < range.start) {
            return false;
        }
        if (range.end && d > range.end) {
            return false;
        }
        return true;
    }

    function sameMonthDay(dateA, dateB) {
        if (!dateA || !dateB) return false;
        return dateA.getMonth() === dateB.getMonth() && dateA.getDate() === dateB.getDate();
    }

    function readGenderValue(item) {
        if (!item) return '';
        var raw = '';
        if (item.gender !== undefined && item.gender !== null && String(item.gender).trim() !== '') {
            raw = item.gender;
        } else if (item.gen !== undefined && item.gen !== null && String(item.gen).trim() !== '') {
            raw = item.gen;
        } else if (item.sex !== undefined && item.sex !== null && String(item.sex).trim() !== '') {
            raw = item.sex;
        } else if (item.gndr !== undefined && item.gndr !== null && String(item.gndr).trim() !== '') {
            raw = item.gndr;
        }
        return raw === undefined || raw === null ? '' : String(raw).trim();
    }

    function normalizeGender(value) {
        var v = value === undefined || value === null ? '' : String(value).trim().toLowerCase();
        if (!v) return 'unknown';
        if (v === 'm' || v === 'male') return 'male';
        if (v === 'f' || v === 'female') return 'female';
        if (v.indexOf('female') === 0) return 'female';
        if (v.indexOf('male') === 0) return 'male';
        return 'unknown';
    }

    function getPresetRange(preset) {
        var today = normalizeDate(new Date());
        if (!today) {
            return { start: null, end: null, label: 'All Data' };
        }

        var start = null;
        var end = normalizeDate(today);
        var month = today.getMonth();
        var year = today.getFullYear();

        if (preset === 'today') {
            start = normalizeDate(today);
        } else if (preset === 'yesterday') {
            start = new Date(year, month, today.getDate() - 1);
            end = normalizeDate(start);
        } else if (preset === 'weekly') {
            start = new Date(year, month, today.getDate() - 6);
        } else if (preset === 'monthly') {
            start = new Date(year, month, 1);
        } else if (preset === 'quarterly') {
            var quarterStart = Math.floor(month / 3) * 3;
            start = new Date(year, quarterStart, 1);
        } else if (preset === 'half_yearly') {
            start = new Date(year, month < 6 ? 0 : 6, 1);
        } else if (preset === 'yearly') {
            start = new Date(year, 0, 1);
        } else if (preset === 'date_range') {
            start = parseISODate($scope.filters.from);
            end = parseISODate($scope.filters.to);
            if (!start || !end) {
                return { start: null, end: null, label: 'Invalid Date Range', invalid: true };
            }
            if (start > end) {
                var temp = start;
                start = end;
                end = temp;
            }
        } else if (preset === 'all') {
            start = null;
            end = null;
        }

        if (start && end) {
            return {
                start: normalizeDate(start),
                end: normalizeDate(end),
                label: formatDMY(start) + ' to ' + formatDMY(end)
            };
        }

        return { start: null, end: null, label: 'All Data' };
    }

    function getToday() {
        var now = new Date();
        var dd = now.getDate();
        var mm = now.getMonth() + 1;
        var yyyy = now.getFullYear();
        if (dd < 10) dd = '0' + dd;
        if (mm < 10) mm = '0' + mm;
        return dd + '/' + mm + '/' + yyyy;
    }

    function refreshIdentity(userData) {
        if (!userData) return;
        if (userData.type === 'A') userData.type = 'Administrator';
        if (userData.type === 'U') userData.type = 'User';
        if (userData.type === 'D') userData.type = 'Developer';

        if (userData.staff_name) {
            localStorage.setItem('staff_name', userData.staff_name);
            $scope.identity.name = userData.staff_name;
        }
        if (userData.type) {
            localStorage.setItem('type', userData.type);
            $scope.identity.type = userData.type;
        }
        if (userData.grade !== undefined && userData.grade !== null && userData.grade !== '') {
            localStorage.setItem('grade', userData.grade);
            $scope.identity.grade = userData.grade;
        }
        if (userData.emp_id !== undefined && userData.emp_id !== null && userData.emp_id !== '') {
            localStorage.setItem('emp_id', userData.emp_id);
            $scope.identity.emp_id = userData.emp_id;
        }
        if (userData.com_id !== undefined && userData.com_id !== null && userData.com_id !== '') {
            localStorage.setItem('com_id', userData.com_id);
            $scope.identity.com_id = userData.com_id;
        }
        if (userData.branch_id !== undefined && userData.branch_id !== null && userData.branch_id !== '') {
            localStorage.setItem('branch_id', userData.branch_id);
            $scope.identity.branch_id = userData.branch_id;
        }
    }

    function setRoleAccess(otherPrivilegesData, moduleData, followupPrivilegeFlag) {
        var moduleList = [];
        angular.forEach(asArray(moduleData), function (item) {
            if (item && item.module) {
                moduleList.push(item.module);
            }
        });

        var other = {};
        if (asArray(otherPrivilegesData).length > 0) {
            other = asArray(otherPrivilegesData)[0] || {};
        }

        var type = ($scope.identity.type || '').toLowerCase();
        var isAdmin = type === 'administrator' || type === 'developer';
        var followupAllowed = String(followupPrivilegeFlag) === '1';

        function hasModule(moduleName) {
            return moduleList.indexOf(moduleName) !== -1;
        }

        $scope.roleAccess.isAdmin = isAdmin;
        $scope.roleAccess.allowedModules = moduleList;
        $scope.roleAccess.canAttendance = isAdmin || hasModule('hr_attendance') || String(other.attendance) === '1';
        $scope.roleAccess.canTask = isAdmin || hasModule('task') || hasModule('task_assigner') || String(other.task) === '1';
        $scope.roleAccess.canFollowup = isAdmin || hasModule('hr_follow_up') || followupAllowed;
        $scope.roleAccess.canStaff = isAdmin || hasModule('hr_staff_details') || String(other.hr_staff_details) === '1';
        $scope.roleAccess.canPayslip = isAdmin || hasModule('hr_payslip');
        $scope.roleAccess.canFinance = isAdmin || hasModule('hr_journals') || hasModule('payments');
        $scope.roleAccess.canTodo = true;
        $scope.roleAccess.canRating = true;
        $scope.roleAccess.canCharts = $scope.roleAccess.canTask || $scope.roleAccess.canFollowup || $scope.roleAccess.canPayslip || $scope.roleAccess.canFinance;
    }

    function taskDate(row) {
        return parseDMY((row && (row.start_date || row.end_date)) || null);
    }

    function followupDate(row) {
        return parseDMY((row && row.date) || null);
    }

    function payslipDate(row) {
        return parseDMY((row && row.pay_date) || null);
    }

    function ratingDate(row) {
        if (!row) {
            return null;
        }
        var raw = row.created_at || row.rating_date || row.date || row.timestamp || '';
        if (!raw) {
            return null;
        }
        var asText = String(raw).trim();
        if (!asText) {
            return null;
        }
        if (asText.indexOf(' ') !== -1 && /^\d{4}-\d{2}-\d{2}/.test(asText)) {
            asText = asText.split(' ')[0];
        }
        var parsed = parseFlexibleDate(asText);
        if (parsed) {
            return parsed;
        }
        var fallback = new Date(raw);
        if (isNaN(fallback.getTime())) {
            return null;
        }
        return new Date(fallback.getFullYear(), fallback.getMonth(), fallback.getDate());
    }

    function getEmployeeId(row) {
        if (!row) return '';
        var id = row.emp_id;
        if (id === undefined || id === null || String(id).trim() === '') {
            id = row.eid;
        }
        return (id === undefined || id === null) ? '' : String(id).trim();
    }

    function getEmployeeName(row) {
        if (!row) return '-';
        var name = row.staff_name;
        if (name === undefined || name === null || String(name).trim() === '') {
            name = row.snam;
        }
        if (name === undefined || name === null || String(name).trim() === '') {
            name = row.name;
        }
        var text = (name === undefined || name === null) ? '' : String(name).trim();
        return text || '-';
    }

    function getCustomerId(row) {
        if (!row) return '';
        var id = row.c_id;
        if (id === undefined || id === null || String(id).trim() === '') {
            id = row.id;
        }
        return (id === undefined || id === null) ? '' : String(id).trim();
    }

    function getCustomerName(row) {
        if (!row) return '-';
        var name = row.customer_name;
        if (name === undefined || name === null || String(name).trim() === '') {
            name = row.company_name;
        }
        if (name === undefined || name === null || String(name).trim() === '') {
            name = row.name;
        }
        if (name === undefined || name === null || String(name).trim() === '') {
            name = row.cname;
        }
        var text = (name === undefined || name === null) ? '' : String(name).trim();
        return text || '-';
    }

    function employeeIsActive(row) {
        if (!row) return false;
        var status = row.st;
        if (status === undefined || status === null || String(status).trim() === '') {
            status = row.status;
        }
        if (status === undefined || status === null || String(status).trim() === '') {
            status = 1;
        }
        return String(status) === '1';
    }

    function isGradeAUser() {
        return String($scope.identity.grade || '').toUpperCase() === 'A';
    }

    function getRatingPeriodRange(periodId) {
        var today = normalizeDate(new Date());
        var y = today.getFullYear();
        var m = today.getMonth();
        if (periodId === 'this_month') {
            return {
                start: new Date(y, m, 1),
                end: today,
                label: 'This Month'
            };
        }
        if (periodId === 'last_month') {
            return {
                start: new Date(y, m - 1, 1),
                end: new Date(y, m, 0),
                label: 'Last Month'
            };
        }
        if (periodId === 'months_12') {
            return {
                start: new Date(y, m - 12, 1),
                end: new Date(y, m, 0),
                label: 'Last 12 Months (Excluding Current Month)'
            };
        }
        return {
            start: null,
            end: null,
            label: 'All Time'
        };
    }

    function inSimpleRange(dateObj, rangeObj) {
        if (!dateObj) return false;
        if (!rangeObj) return true;
        if (rangeObj.start && dateObj < rangeObj.start) return false;
        if (rangeObj.end && dateObj > rangeObj.end) return false;
        return true;
    }

    function loadRatingFiltersAndData() {
        $scope.ratingPanel.loading = true;
        $scope.ratingPanel.error = '';
        $scope.ratingPanel.isGradeA = isGradeAUser();
        $scope.ratingPanel.filters.period = 'all';
        $scope.ratingPanel.filters.c_id = '';

        var comId = $scope.identity.com_id || localStorage.getItem('com_id') || '';
        var branchId = $scope.identity.branch_id || localStorage.getItem('branch_id') || '';
        var employeeUrl = rootUrl + 'hr_staff_details/view_employee?st=1&status=1';
        var customerUrl = rootUrl + 'customer/view_cust_project?status=1&st=1';

        if (comId) {
            employeeUrl += '&com_id=' + encodeURIComponent(comId);
            customerUrl += '&com_id=' + encodeURIComponent(comId);
        }
        if (branchId) {
            employeeUrl += '&branch_id=' + encodeURIComponent(branchId);
            customerUrl += '&branch_id=' + encodeURIComponent(branchId);
        }

        var requests = [
            $http.get(rootUrl + 'employee_rating/rating_data').then(function (response) {
                return response;
            }, function () {
                return { data: [] };
            })
        ];

        if ($scope.ratingPanel.isGradeA) {
            requests.push($http.get(employeeUrl).then(function (response) {
                return response;
            }, function () {
                return { data: [] };
            }));
        } else {
            requests.push($q.when({ data: [] }));
        }

        $q.all(requests).then(function (responses) {
            rawData.ratingsAll = asArray(responses[0].data);

            $scope.ratingPanel.employees = [];
            if ($scope.ratingPanel.isGradeA) {
                var empMap = {};
                angular.forEach(asArray(responses[1].data), function (row) {
                    if (!employeeIsActive(row)) return;
                    var id = getEmployeeId(row);
                    if (!id || empMap[id]) return;
                    empMap[id] = true;
                    $scope.ratingPanel.employees.push({
                        emp_id: id,
                        staff_name: getEmployeeName(row)
                    });
                });
                $scope.ratingPanel.employees.sort(function (a, b) {
                    return String(a.staff_name).localeCompare(String(b.staff_name));
                });
                var hasSelected = false;
                angular.forEach($scope.ratingPanel.employees, function (item) {
                    if (String(item.emp_id) === String($scope.ratingPanel.filters.emp_id || '')) {
                        hasSelected = true;
                    }
                });
                if ((!$scope.ratingPanel.filters.emp_id || !hasSelected) && $scope.ratingPanel.employees.length > 0) {
                    $scope.ratingPanel.filters.emp_id = $scope.ratingPanel.employees[0].emp_id;
                }
            } else {
                $scope.ratingPanel.filters.emp_id = String($scope.identity.emp_id || localStorage.getItem('emp_id') || '');
            }

            loadRatingCustomersByEmployee($scope.ratingPanel.filters.emp_id, customerUrl).then(function () {
                applyRatingFilter();
                initRatingSelect2();
                $scope.ratingPanel.loading = false;
            }, function () {
                applyRatingFilter();
                initRatingSelect2();
                $scope.ratingPanel.loading = false;
            });
        }, function () {
            $scope.ratingPanel.loading = false;
            $scope.ratingPanel.error = 'Unable to load rating filter data.';
            rawData.ratingsAll = [];
            applyRatingFilter();
        });
    }

    function loadRatingCustomersByEmployee(empId, baseCustomerUrl) {
        var customerApiUrl = baseCustomerUrl || (rootUrl + 'customer/view_cust_project?status=1&st=1');
        var employeeId = String(empId || '');
        if (employeeId) {
            customerApiUrl += '&emp_id=' + encodeURIComponent(employeeId);
        }

        return $http.get(customerApiUrl).then(function (response) {
            var customerMap = {};
            var nextCustomers = [];
            angular.forEach(asArray(response.data), function (row) {
                var id = getCustomerId(row);
                if (!id || customerMap[id]) return;
                customerMap[id] = true;
                nextCustomers.push({
                    c_id: id,
                    name: getCustomerName(row)
                });
            });
            nextCustomers.sort(function (a, b) {
                return String(a.name).localeCompare(String(b.name));
            });
            $scope.ratingPanel.customers = nextCustomers;

            var hasSelectedCustomer = false;
            angular.forEach(nextCustomers, function (item) {
                if (String(item.c_id) === String($scope.ratingPanel.filters.c_id || '')) {
                    hasSelectedCustomer = true;
                }
            });
            if (!hasSelectedCustomer) {
                $scope.ratingPanel.filters.c_id = '';
            }
        }, function () {
            $scope.ratingPanel.customers = [];
            $scope.ratingPanel.filters.c_id = '';
            $scope.ratingPanel.error = 'Unable to load customers for selected employee.';
        });
    }

    function applyRatingFilter() {
        var ratings = asArray(rawData.ratingsAll);
        var employeeId = String($scope.ratingPanel.filters.emp_id || '');
        var customerId = String($scope.ratingPanel.filters.c_id || '');
        var periodId = String($scope.ratingPanel.filters.period || 'all');
        var range = getRatingPeriodRange(periodId);
        var selectedEmployeeName = '';
        var selectedCustomerName = 'All Customers';

        if ($scope.ratingPanel.isGradeA) {
            angular.forEach($scope.ratingPanel.employees, function (item) {
                if (String(item.emp_id) === employeeId) {
                    selectedEmployeeName = item.staff_name;
                }
            });
        } else {
            selectedEmployeeName = $scope.identity.name || 'My Rating';
            if (!employeeId) {
                employeeId = String($scope.identity.emp_id || localStorage.getItem('emp_id') || '');
                $scope.ratingPanel.filters.emp_id = employeeId;
            }
        }

        angular.forEach($scope.ratingPanel.customers, function (item) {
            if (String(item.c_id) === customerId) {
                selectedCustomerName = item.name;
            }
        });

        var total = 0;
        var count = 0;
        var high = 0;
        var mid = 0;
        var low = 0;

        if (!employeeId) {
            $scope.ratingPanel.summary = {
                average: 0,
                count: 0,
                high: 0,
                mid: 0,
                low: 0,
                windowLabel: range.label,
                employeeName: selectedEmployeeName,
                customerName: selectedCustomerName
            };
            return;
        }

        angular.forEach(ratings, function (row) {
            var rowEmpId = getEmployeeId(row);
            if (String(rowEmpId) !== String(employeeId)) return;

            var rowCustomerId = getCustomerId(row);
            if (customerId && String(rowCustomerId) !== String(customerId)) return;

            var rowDate = ratingDate(row);
            if ((range.start || range.end) && !inSimpleRange(rowDate, range)) return;

            var score = parseInt(row.rating, 10);
            if (isNaN(score) || score < 1 || score > 10) return;

            total += score;
            count += 1;
            if (score >= 8) high += 1;
            else if (score >= 5) mid += 1;
            else low += 1;
        });

        $scope.ratingPanel.summary = {
            average: count > 0 ? (total / count) : 0,
            count: count,
            high: high,
            mid: mid,
            low: low,
            windowLabel: range.label,
            employeeName: selectedEmployeeName,
            customerName: selectedCustomerName
        };
    }

    $scope.onRatingFilterChange = function () {
        applyRatingFilter();
    };

    $scope.onRatingEmployeeChange = function () {
        $scope.ratingPanel.loading = true;
        $scope.ratingPanel.error = '';

        var comId = $scope.identity.com_id || localStorage.getItem('com_id') || '';
        var branchId = $scope.identity.branch_id || localStorage.getItem('branch_id') || '';
        var customerUrl = rootUrl + 'customer/view_cust_project?status=1&st=1';
        if (comId) {
            customerUrl += '&com_id=' + encodeURIComponent(comId);
        }
        if (branchId) {
            customerUrl += '&branch_id=' + encodeURIComponent(branchId);
        }

        loadRatingCustomersByEmployee($scope.ratingPanel.filters.emp_id, customerUrl).then(function () {
            applyRatingFilter();
            initRatingSelect2();
            $scope.ratingPanel.loading = false;
        }, function () {
            applyRatingFilter();
            initRatingSelect2();
            $scope.ratingPanel.loading = false;
        });
    };

    function sortByDateDesc(rows, extractor) {
        return asArray(rows).slice(0).sort(function (a, b) {
            var da = extractor(a);
            var db = extractor(b);
            if (!da && !db) return 0;
            if (!da) return 1;
            if (!db) return -1;
            return db - da;
        });
    }

    function countByStatus(rows, statusValue) {
        var count = 0;
        angular.forEach(asArray(rows), function (row) {
            var value = (row && row.status !== undefined && row.status !== null) ? row.status : row.st;
            if (String(value) === String(statusValue)) {
                count += 1;
            }
        });
        return count;
    }

    function buildTrendSeries(followupRows, taskRows, payslipRows) {
        var followupMap = {};
        var taskMap = {};
        var payslipMap = {};
        var keyMap = {};

        function pushDate(map, key) {
            if (!key) return;
            if (!map[key]) map[key] = 0;
            map[key] += 1;
            keyMap[key] = true;
        }

        angular.forEach(asArray(followupRows), function (row) {
            var d = followupDate(row);
            pushDate(followupMap, d ? formatISO(d) : null);
        });
        angular.forEach(asArray(taskRows), function (row) {
            var d = taskDate(row);
            pushDate(taskMap, d ? formatISO(d) : null);
        });
        angular.forEach(asArray(payslipRows), function (row) {
            var d = payslipDate(row);
            pushDate(payslipMap, d ? formatISO(d) : null);
        });

        var keys = Object.keys(keyMap).sort();
        if (keys.length > 40) {
            var fm = {};
            var tm = {};
            var pm = {};
            var monthKeysMap = {};
            angular.forEach(keys, function (key) {
                var mKey = key.substring(0, 7);
                monthKeysMap[mKey] = true;
                fm[mKey] = (fm[mKey] || 0) + (followupMap[key] || 0);
                tm[mKey] = (tm[mKey] || 0) + (taskMap[key] || 0);
                pm[mKey] = (pm[mKey] || 0) + (payslipMap[key] || 0);
            });
            keys = Object.keys(monthKeysMap).sort();
            followupMap = fm;
            taskMap = tm;
            payslipMap = pm;
        }

        if (keys.length > 24) {
            keys = keys.slice(keys.length - 24);
        }

        var categories = [];
        var fSeries = [];
        var tSeries = [];
        var pSeries = [];

        angular.forEach(keys, function (key) {
            if (key.length === 7) {
                var mk = key.split('-');
                categories.push(mk[1] + '/' + mk[0]);
            } else {
                var d = parseISODate(key);
                categories.push(d ? formatDMY(d).substring(0, 5) : key);
            }
            fSeries.push(toNumber(followupMap[key] || 0));
            tSeries.push(toNumber(taskMap[key] || 0));
            pSeries.push(toNumber(payslipMap[key] || 0));
        });

        return {
            categories: categories,
            followups: fSeries,
            tasks: tSeries,
            payslips: pSeries
        };
    }

    function getDonutStyle(pct, colorA, colorB) {
        var cleaned = pct;
        if (cleaned < 0) cleaned = 0;
        if (cleaned > 100) cleaned = 100;
        return {
            'background': 'conic-gradient(' + colorA + ' 0% ' + cleaned + '%, ' + colorB + ' ' + cleaned + '% 100%)'
        };
    }

    function buildMix(data, keyName, fallbackLabel, maxItems) {
        var mapped = {};
        var rows = asArray(data);
        angular.forEach(rows, function (row) {
            var label = row[keyName] || fallbackLabel;
            if (!mapped[label]) {
                mapped[label] = 0;
            }
            mapped[label] += 1;
        });

        var total = rows.length;
        var result = [];
        angular.forEach(mapped, function (count, label) {
            result.push({
                label: label,
                count: count,
                percent: percent(count, total)
            });
        });

        result.sort(function (a, b) {
            return b.count - a.count;
        });

        return result.slice(0, maxItems || 6);
    }

    function buildReminderFeed(followupRows, today) {
        var rows = [];
        angular.forEach(asArray(followupRows), function (item) {
            if (!item.rem_date || item.rem_date === ':') {
                return;
            }
            var remDate = parseDMY(item.rem_date);
            if (!remDate) {
                return;
            }
            var state = 'Upcoming';
            if (sameDay(remDate, today)) {
                state = 'Today';
            } else if (remDate < today) {
                state = 'Overdue';
            }
            rows.push({
                f_id: item.f_id,
                title: item.title,
                staff_name: item.staff_name,
                rem_date: item.rem_date,
                rem_time: item.rem_time,
                cname: item.cname,
                reminderDateObj: remDate,
                reminderState: state
            });
        });

        rows.sort(function (a, b) {
            return a.reminderDateObj - b.reminderDateObj;
        });

        return rows.slice(0, 10);
    }

    function buildVisualBars() {
        $scope.visuals.bars = [
            {
                label: 'Attendance Health',
                percent: $scope.progress.attendance,
                value: $scope.stats.attendance.present + ' / ' + $scope.stats.attendance.total,
                tone: 'blue'
            },
            {
                label: 'Task Completion',
                percent: $scope.progress.taskCompletion,
                value: $scope.stats.tasks.completed + ' / ' + $scope.stats.tasks.monthly,
                tone: 'teal'
            },
            {
                label: 'Payslip Approval',
                percent: $scope.progress.payslipApproval,
                value: $scope.quickStats.approvedPayslips + ' / ' + ($scope.quickStats.approvedPayslips + $scope.quickStats.pendingPayslips),
                tone: 'green'
            },
            {
                label: 'Reminder Coverage',
                percent: $scope.progress.reminderCoverage,
                value: $scope.quickStats.dueReminders + ' / ' + ($scope.reminderFeed.length || 0),
                tone: 'orange'
            }
        ];
    }

    function renderCharts(filteredFollowups, filteredTasks, filteredPayslips) {
        if (!window.Highcharts) {
            return;
        }

        $timeout(function () {
            var trendData = buildTrendSeries(filteredFollowups, filteredTasks, filteredPayslips);

            if ($scope.roleAccess.canCharts && document.getElementById('taskifyChartTrend')) {
                var trendSeries = [];
                if ($scope.roleAccess.canFollowup) {
                    trendSeries.push({
                        name: 'Follow-ups',
                        data: trendData.followups,
                        color: '#2f7afe'
                    });
                }
                if ($scope.roleAccess.canTask) {
                    trendSeries.push({
                        name: 'Tasks',
                        data: trendData.tasks,
                        color: '#1cbf9f'
                    });
                }
                if ($scope.roleAccess.canPayslip) {
                    trendSeries.push({
                        name: 'Payslips',
                        data: trendData.payslips,
                        color: '#f08b2e'
                    });
                }

                Highcharts.chart('taskifyChartTrend', {
                    chart: {
                        type: 'areaspline',
                        backgroundColor: 'transparent',
                        height: 320
                    },
                    title: { text: null },
                    credits: { enabled: false },
                    legend: { enabled: true },
                    xAxis: {
                        categories: trendData.categories,
                        tickLength: 0
                    },
                    yAxis: {
                        title: { text: null },
                        allowDecimals: false
                    },
                    tooltip: { shared: true },
                    series: trendSeries
                });
            }

            if ($scope.roleAccess.canTask && document.getElementById('taskifyChartTaskStatus')) {
                Highcharts.chart('taskifyChartTaskStatus', {
                    chart: {
                        type: 'pie',
                        backgroundColor: 'transparent',
                        height: 280
                    },
                    title: { text: null },
                    credits: { enabled: false },
                    tooltip: {
                        pointFormat: '<b>{point.y}</b> ({point.percentage:.1f}%)'
                    },
                    plotOptions: {
                        pie: {
                            innerSize: '55%',
                            dataLabels: { enabled: true }
                        }
                    },
                    series: [{
                        name: 'Tasks',
                        data: [
                            { name: 'Running', y: toNumber($scope.stats.tasks.running), color: '#f08b2e' },
                            { name: 'Completed', y: toNumber($scope.stats.tasks.completed), color: '#1cbf9f' }
                        ]
                    }]
                });
            }

            if ($scope.roleAccess.canFollowup && document.getElementById('taskifyChartActivity')) {
                var categories = [];
                var data = [];
                angular.forEach($scope.visuals.activityMix, function (item) {
                    categories.push(item.label);
                    data.push(item.count);
                });

                Highcharts.chart('taskifyChartActivity', {
                    chart: {
                        type: 'bar',
                        backgroundColor: 'transparent',
                        height: 280
                    },
                    title: { text: null },
                    credits: { enabled: false },
                    xAxis: {
                        categories: categories
                    },
                    yAxis: {
                        title: { text: null },
                        allowDecimals: false
                    },
                    legend: { enabled: false },
                    series: [{
                        name: 'Follow-ups',
                        data: data,
                        color: '#2f7afe'
                    }]
                });
            }

            if ($scope.roleAccess.canPayslip && document.getElementById('taskifyChartPayslip')) {
                Highcharts.chart('taskifyChartPayslip', {
                    chart: {
                        type: 'column',
                        backgroundColor: 'transparent',
                        height: 280
                    },
                    title: { text: null },
                    credits: { enabled: false },
                    xAxis: {
                        categories: ['Approved', 'Pending']
                    },
                    yAxis: {
                        title: { text: null },
                        allowDecimals: false
                    },
                    legend: { enabled: false },
                    series: [{
                        name: 'Payslips',
                        data: [toNumber($scope.quickStats.approvedPayslips), toNumber($scope.quickStats.pendingPayslips)],
                        colorByPoint: true,
                        colors: ['#1c9d5d', '#f08b2e']
                    }]
                });
            }
        }, 60, false);
    }

    function applyDerivedVisuals() {
        $scope.visuals.donuts.attendance = getDonutStyle($scope.progress.attendance, '#2f7afe', '#e2ecfa');
        $scope.visuals.donuts.tasks = getDonutStyle($scope.progress.taskCompletion, '#1cbf9f', '#e0f5ef');
        $scope.visuals.donuts.journals = getDonutStyle($scope.progress.debitShare, '#f08b2e', '#faead8');
        $scope.visuals.donuts.payslips = getDonutStyle($scope.progress.payslipApproval, '#1c9d5d', '#deefe6');
        buildVisualBars();
    }

    function rebuildDataForFilter() {
        var range = getPresetRange($scope.filters.preset);
        if (range.invalid) {
            return;
        }
        $scope.filterWindow.label = range.label;

        var filteredFollowups = asArray(rawData.followupsAll).filter(function (row) {
            if (!range.start && !range.end) return true;
            return inRange(followupDate(row), range);
        });

        var filteredTasks = asArray(rawData.tasksAll).filter(function (row) {
            if (!range.start && !range.end) return true;
            return inRange(taskDate(row), range);
        });

        var filteredPayslips = asArray(rawData.payslipsAll).filter(function (row) {
            if (!range.start && !range.end) return true;
            return inRange(payslipDate(row), range);
        });

        $scope.followups = sortByDateDesc(filteredFollowups, followupDate).slice(0, 8);
        $scope.taskFeed = sortByDateDesc(filteredTasks, taskDate).slice(0, 10);
        $scope.payslips = sortByDateDesc(filteredPayslips, payslipDate).slice(0, 10);

        var activeCount = 0;
        var activeEmpMap = {};
        var activeEmpDetails = {};
        angular.forEach(asArray(rawData.staffAll), function (emp) {
            var empStatus = (emp && emp.status !== undefined && emp.status !== null) ? emp.status : emp.st;
            if (String(empStatus) !== '1') {
                return;
            }
            activeCount += 1;

            var activeEmpId = '';
            if (emp && emp.emp_id !== undefined && emp.emp_id !== null && String(emp.emp_id).trim() !== '') {
                activeEmpId = String(emp.emp_id).trim();
            } else if (emp && emp.eid !== undefined && emp.eid !== null && String(emp.eid).trim() !== '') {
                activeEmpId = String(emp.eid).trim();
            }
            if (activeEmpId) {
                activeEmpMap[activeEmpId] = true;
                activeEmpDetails[activeEmpId] = {
                    gender: readGenderValue(emp)
                };
            }
        });
        $scope.quickStats.activeStaff = activeCount;
        $scope.quickStats.inactiveStaff = asArray(rawData.staffAll).length - activeCount;
        if ($scope.quickStats.inactiveStaff < 0) $scope.quickStats.inactiveStaff = 0;

        $scope.stats.tasks.monthly = filteredTasks.length;
        $scope.stats.tasks.running = countByStatus(filteredTasks, 0);
        $scope.stats.tasks.completed = $scope.stats.tasks.monthly - $scope.stats.tasks.running;
        if ($scope.stats.tasks.completed < 0) $scope.stats.tasks.completed = 0;

        $scope.progress.runningTasks = percent($scope.stats.tasks.running, $scope.stats.tasks.monthly);
        $scope.progress.taskCompletion = percent($scope.stats.tasks.completed, $scope.stats.tasks.monthly);

        $scope.quickStats.approvedPayslips = countByStatus(filteredPayslips, 1);
        $scope.quickStats.pendingPayslips = filteredPayslips.length - $scope.quickStats.approvedPayslips;
        if ($scope.quickStats.pendingPayslips < 0) $scope.quickStats.pendingPayslips = 0;
        $scope.progress.payslipApproval = percent($scope.quickStats.approvedPayslips, filteredPayslips.length);

        var reminderConfigured = 0;
        angular.forEach(filteredFollowups, function (item) {
            if (item.rem_date && item.rem_date !== ':') reminderConfigured += 1;
        });
        $scope.progress.reminderCoverage = percent(reminderConfigured, filteredFollowups.length);

        var todayDate = parseDMY($scope.dashboardMeta.today) || normalizeDate(new Date());
        $scope.quickStats.todayRunningTasks = 0;
        $scope.quickStats.todayTotalTasks = 0;
        angular.forEach(asArray(rawData.tasksAll), function (task) {
            var taskDay = taskDate(task);
            if (!sameDay(taskDay, todayDate)) {
                return;
            }

            $scope.quickStats.todayTotalTasks += 1;

            var taskStatus = (task && task.status !== undefined && task.status !== null) ? task.status : task.st;
            if (String(taskStatus) !== '0') {
                return;
            }
            $scope.quickStats.todayRunningTasks += 1;
        });
        $scope.progress.todayRunningTasks = percent($scope.quickStats.todayRunningTasks, $scope.quickStats.todayTotalTasks);

        $scope.reminderFeed = buildReminderFeed(filteredFollowups, todayDate || normalizeDate(new Date()));
        $scope.quickStats.dueReminders = 0;
        angular.forEach($scope.reminderFeed, function (item) {
            if (item.reminderState === 'Today' || item.reminderState === 'Overdue') {
                $scope.quickStats.dueReminders += 1;
            }
        });

        $scope.visuals.gradeMix = buildMix(rawData.staffAll, 'gr', 'NA', 6);
        $scope.visuals.activityMix = buildMix(filteredFollowups, 'cname', 'Uncategorized', 6);
        var activeBirthdays = [];
        var birthdayNames = [];
        var birthdayNameMap = {};
        var birthdayKeyMap = {};
        function getEmpId(item) {
            if (item && item.emp_id !== undefined && item.emp_id !== null && String(item.emp_id).trim() !== '') {
                return String(item.emp_id).trim();
            }
            if (item && item.eid !== undefined && item.eid !== null && String(item.eid).trim() !== '') {
                return String(item.eid).trim();
            }
            return '';
        }
        function getEmpName(item) {
            var name = (item && item.name !== undefined && item.name !== null) ? item.name :
                ((item && item.staff_name !== undefined && item.staff_name !== null) ? item.staff_name : item.snam);
            return name === undefined || name === null ? '' : String(name).trim();
        }
        function addBirthday(item) {
            var empId = getEmpId(item);
            var name = getEmpName(item);
            var dob = (item && item.dob !== undefined && item.dob !== null) ? String(item.dob).trim() : '';
            var gender = readGenderValue(item);
            if (!gender && empId && activeEmpDetails[empId]) {
                gender = activeEmpDetails[empId].gender || '';
            }
            var key = empId ? ('ID:' + empId) : ('ROW:' + name + '|' + dob);
            if (birthdayKeyMap[key]) {
                return;
            }
            birthdayKeyMap[key] = true;

            var safeItem = angular.extend({}, item || {});
            if (empId && (!safeItem.emp_id || String(safeItem.emp_id).trim() === '')) {
                safeItem.emp_id = empId;
            }
            if (name && (!safeItem.name || String(safeItem.name).trim() === '')) {
                safeItem.name = name;
            }
            if (gender && (!safeItem.gender || String(safeItem.gender).trim() === '')) {
                safeItem.gender = gender;
            }
            activeBirthdays.push(safeItem);

            if (name && !birthdayNameMap[name]) {
                birthdayNameMap[name] = true;
                birthdayNames.push(name);
            }
        }

        angular.forEach(asArray(rawData.birthdaysAll), function (item) {
            var itemStatus = (item && item.status !== undefined && item.status !== null) ? item.status : item.st;
            var empId = getEmpId(item);
            var isActiveBirthday = (String(itemStatus) === '1');
            if (!isActiveBirthday && empId && activeEmpMap[empId]) {
                isActiveBirthday = true;
            }
            if (!isActiveBirthday) {
                return;
            }
            addBirthday(item);
        });

        angular.forEach(asArray(rawData.staffAll), function (emp) {
            var empStatus = (emp && emp.status !== undefined && emp.status !== null) ? emp.status : emp.st;
            if (String(empStatus) !== '1') {
                return;
            }
            var dobValue = (emp && emp.dob !== undefined && emp.dob !== null) ? emp.dob : '';
            var dobDate = parseFlexibleDate(dobValue);
            if (!sameMonthDay(dobDate, todayDate)) {
                return;
            }

            addBirthday({
                emp_id: getEmpId(emp),
                name: getEmpName(emp),
                dob: typeof dobValue === 'string' ? dobValue : formatDMY(dobDate),
                st: 1
            });
        });

        $scope.birthdays = activeBirthdays.slice(0, 8);
        $scope.quickStats.todayBirthdays = activeBirthdays.length;
        $scope.quickStats.todayBirthdayNames = birthdayNames;
        $scope.quickStats.todayBirthdayNamesText = birthdayNames.length ? birthdayNames.join(', ') : 'No active birthdays today';
        if ($scope.quickStats.todayBirthdays > 1) {
            $scope.quickStats.todayBirthdayWishText = 'Celebrate and Wish Them Today';
        } else if ($scope.quickStats.todayBirthdays === 1) {
            var onlyBirthdayGender = normalizeGender(readGenderValue(activeBirthdays[0]));
            if (onlyBirthdayGender === 'male') {
                $scope.quickStats.todayBirthdayWishText = 'Celebrate and Wish Him Birthday';
            } else if (onlyBirthdayGender === 'female') {
                $scope.quickStats.todayBirthdayWishText = 'Celebrate and Wish Her Birthday';
            } else {
                $scope.quickStats.todayBirthdayWishText = 'Celebrate and Wish Them Birthday';
            }
        } else {
            $scope.quickStats.todayBirthdayWishText = '';
        }

        $scope.staffFeed = asArray(rawData.staffAll).slice(0, 10);

        applyDerivedVisuals();
        renderCharts(filteredFollowups, filteredTasks, filteredPayslips);
    }

    $scope.onPresetChange = function () {
        if ($scope.filters.preset !== 'date_range') {
            var range = getPresetRange($scope.filters.preset);
            $scope.filters.from = range.start ? formatISO(range.start) : '';
            $scope.filters.to = range.end ? formatISO(range.end) : '';
            rebuildDataForFilter();
        }
    };

    $scope.applyDateRange = function () {
        if (!$scope.filters.from || !$scope.filters.to) {
            return;
        }
        $scope.filters.preset = 'date_range';
        rebuildDataForFilter();
    };

    function parseJsonResponse(data) {
        if (angular.isObject(data)) return data;
        if (!data) return {};
        try {
            return JSON.parse(data);
        } catch (e) {
            return { error: 1, msg: String(data) };
        }
    }

    function normalizeTodoPriorityType(row) {
        var raw = '';
        if (row && row.priority_type !== undefined && row.priority_type !== null) raw = row.priority_type;
        else if (row && row.priority_level !== undefined && row.priority_level !== null) raw = row.priority_level;
        else if (row && row.task_priority !== undefined && row.task_priority !== null) raw = row.task_priority;
        raw = String(raw || '').trim().toLowerCase();
        if (raw === 'hot' || raw === 'high' || raw === '1') return 'hot';
        if (raw === 'cold' || raw === 'low' || raw === '3') return 'cold';
        return 'warm';
    }

    function todoPriorityRank(type) {
        if (type === 'hot') return 3;
        if (type === 'warm') return 2;
        return 1;
    }

    function sortTodoByPriority(tasks) {
        return asArray(tasks).slice().sort(function (a, b) {
            var pa = todoPriorityRank(normalizeTodoPriorityType(a));
            var pb = todoPriorityRank(normalizeTodoPriorityType(b));
            if (pb !== pa) return pb - pa;
            var ra = parseInt(a && a.priority, 10);
            var rb = parseInt(b && b.priority, 10);
            ra = isNaN(ra) ? 0 : ra;
            rb = isNaN(rb) ? 0 : rb;
            if (rb !== ra) return rb - ra;
            var ia = parseInt(a && a.todo_id, 10);
            var ib = parseInt(b && b.todo_id, 10);
            ia = isNaN(ia) ? 0 : ia;
            ib = isNaN(ib) ? 0 : ib;
            return ib - ia;
        });
    }

    function getTodoRowDate(row, fields) {
        if (!row || !fields || !fields.length) return null;
        var raw = '';
        angular.forEach(fields, function (key) {
            if (!raw && row[key] !== undefined && row[key] !== null && String(row[key]).trim() !== '') {
                raw = String(row[key]).trim();
            }
        });
        if (!raw) return null;
        if (/^\d{4}-\d{2}-\d{2}[ T]/.test(raw)) {
            raw = raw.split(/[ T]/)[0];
        }
        var parsed = parseFlexibleDate(raw);
        return parsed ? normalizeDate(parsed) : null;
    }

    function includeTodoWidgetTask(row, today) {
        if (!today) return true;
        var createdDate = getTodoRowDate(row, ['todo_date', 'task_date', 'created_at', 'date']);
        var updatedDate = getTodoRowDate(row, ['updated_at', 'modified_at', 'updated_date', 'completed_at']);
        var isCompleted = String(row && row.is_completed) === '1';

        if (isCompleted) {
            if (sameDay(updatedDate, today) || sameDay(createdDate, today)) return true;
            return false;
        }

        if (!createdDate) return true;
        return createdDate <= today;
    }

    function groupTodoByPriority(tasks) {
        var groups = { hot: [], warm: [], cold: [] };
        angular.forEach(asArray(tasks), function (task) {
            task.priority_type = normalizeTodoPriorityType(task);
            if (task.priority_type === 'hot') groups.hot.push(task);
            else if (task.priority_type === 'cold') groups.cold.push(task);
            else groups.warm.push(task);
        });
        return groups;
    }

    function buildTodoWidgetStats(tasks) {
        var list = asArray(tasks);
        var completed = 0;
        angular.forEach(list, function (item) {
            if (String(item && item.is_completed) === '1') completed += 1;
        });
        return { total: list.length, completed: completed, pending: list.length - completed };
    }

    function computeTodoVisibleLimit() {
        var ratingHeight = $('.taskify-rating-panel:visible').first().outerHeight();
        if (!ratingHeight || ratingHeight < 260) ratingHeight = 420;
        var reserved = 205; // header + composer + stats + paddings
        var usable = ratingHeight - reserved;
        if (usable < 180) usable = 180;
        var itemHeight = 56;
        var limit = Math.floor(usable / itemHeight);
        if (limit < 3) limit = 3;
        if (limit > 24) limit = 24;
        $scope.todoWidget.visibleLimit = limit;
        $scope.todoWidget.listMaxHeight = usable;
    }

    function applyVisibleTodoSegments() {
        var sorted = sortTodoByPriority($scope.todoWidget.tasks);
        var grouped = groupTodoByPriority(sorted);
        $scope.todoWidget.groups = grouped;
        $scope.todoWidget.visibleTasks = sorted;
        $scope.todoWidget.visibleGroups = grouped;
        $scope.todoWidget.hiddenCount = 0;
    }

    function refreshTodoVisibleWindow() {
        $timeout(function () {
            computeTodoVisibleLimit();
            applyVisibleTodoSegments();
        }, 0, false);
    }

    function getOrderedTodoFromGroups(groups) {
        var ordered = [];
        angular.forEach(['hot', 'warm', 'cold'], function (bucket) {
            angular.forEach(asArray(groups[bucket]), function (task) {
                task.priority_type = bucket;
                ordered.push(task);
            });
        });
        return ordered;
    }

    function persistTodoPriorityType(task, bucket, done) {
        if (!task || !task.todo_id) {
            if (done) done(false);
            return;
        }
        $.ajax({
            type: 'POST',
            url: rootUrl + 'to_do_list/save_data',
            data: {
                todo_id: task.todo_id,
                title: task.title || '',
                priority_type: bucket,
                priority_level: bucket,
                task_priority: bucket
            },
            success: function (data) {
                var response = parseJsonResponse(data);
                if (done) done(response && String(response.error) === '0');
            },
            error: function () {
                if (done) done(false);
            }
        });
    }

    function persistTodoOrder(done) {
        var ordered = getOrderedTodoFromGroups($scope.todoWidget.groups);
        var orderedIds = [];
        var orderedTypes = [];
        var orderedMap = [];
        var rank = ordered.length;
        angular.forEach(ordered, function (task) {
            orderedIds.push(task.todo_id);
            orderedTypes.push(task.priority_type || 'warm');
            orderedMap.push({
                todo_id: task.todo_id,
                priority_type: task.priority_type || 'warm',
                priority_rank: rank
            });
            rank -= 1;
        });

        $.ajax({
            type: 'POST',
            url: rootUrl + 'to_do_list/reorder',
            data: {
                'ordered_ids[]': orderedIds,
                'ordered_priority_types[]': orderedTypes,
                ordered_priority_map: JSON.stringify(orderedMap)
            },
            success: function (data) {
                var response = parseJsonResponse(data);
                if (done) done(response && String(response.error) === '0');
            },
            error: function () {
                if (done) done(false);
            }
        });
    }

    $scope.todoPriorityClass = function (task) {
        return 'taskify-priority--' + normalizeTodoPriorityType(task);
    };

    $scope.loadTodoWidget = function () {
        $scope.todoWidget.loading = true;
        var empId = $scope.identity.emp_id || localStorage.getItem('emp_id') || '';
        var endpoint = rootUrl + 'to_do_list/view/500/1?status=1';
        if (empId) endpoint += '&emp_id=' + encodeURIComponent(empId);

        $http.get(endpoint).success(function (response) {
            response = response || {};
            var today = normalizeDate(new Date());
            var tasks = sortTodoByPriority(asArray(response.data).filter(function (row) {
                return includeTodoWidgetTask(row, today);
            }));
            $scope.todoWidget.tasks = tasks;
            $scope.todoWidget.stats = buildTodoWidgetStats(tasks);
            refreshTodoVisibleWindow();
            ensureTodoPrioritySelectNative();

            if (!todoWidgetResizeBound && typeof $ !== 'undefined') {
                todoWidgetResizeBound = true;
                $(window).on('resize.taskifyTodoWidget', function () {
                    $scope.$applyAsync(function () {
                        refreshTodoVisibleWindow();
                    });
                });
            }
        }).finally(function () {
            $scope.todoWidget.loading = false;
        });
    };

    $scope.addTodoFromWidget = function () {
        var title = (($scope.todoWidget.form && $scope.todoWidget.form.title) || '').trim();
        if (!title) return;

        $.ajax({
            type: 'POST',
            url: rootUrl + 'to_do_list/save_data',
            data: { title: title, priority_type: ($scope.todoWidget.form.priority_type || 'warm') },
            success: function (data) {
                var response = parseJsonResponse(data);
                if (response && String(response.error) === '0') {
                    $scope.$applyAsync(function () {
                        $scope.todoWidget.form.title = '';
                        $scope.todoWidget.form.priority_type = 'warm';
                        $scope.loadTodoWidget();
                    });
                    messages('success', 'Success!', 'Task added successfully.', 2200);
                } else {
                    messages('warning', 'Warning!', response.msg || 'Unable to add task.', 4500);
                }
            }
        });
    };

    $scope.toggleTodoFromWidget = function (task) {
        if (!task || !task.todo_id) return;
        var nextValue = String(task.is_completed) === '1' ? 0 : 1;
        $.ajax({
            type: 'POST',
            url: rootUrl + 'to_do_list/toggle_status',
            data: { todo_id: task.todo_id, is_completed: nextValue },
            success: function (data) {
                var response = parseJsonResponse(data);
                if (response && String(response.error) === '0') {
                    $scope.$applyAsync(function () {
                        $scope.loadTodoWidget();
                    });
                } else {
                    messages('warning', 'Warning!', response.msg || 'Unable to update task.', 4500);
                }
            }
        });
    };

    $scope.deleteTodoFromWidget = function (task) {
        if (!task || !task.todo_id) return;
        if (!confirm('Archive this task?')) return;
        $http.get(rootUrl + 'to_do_list/delete_data?id=' + task.todo_id).success(function (data) {
            if (String(data) === '1') {
                messages('success', 'Success!', 'Task archived.', 2000);
                $scope.loadTodoWidget();
            } else {
                messages('warning', 'Warning!', 'Unable to archive task.', 4500);
            }
        });
    };

    $scope.todoDragStart = function (bucket, index) {
        $scope.todoWidget.drag.bucket = bucket;
        $scope.todoWidget.drag.index = index;
    };

    $scope.todoDragOver = function ($event) {
        if ($event && $event.preventDefault) $event.preventDefault();
    };

    $scope.todoDrop = function (targetBucket, targetIndex, $event) {
        if ($event && $event.preventDefault) $event.preventDefault();
        var fromBucket = $scope.todoWidget.drag.bucket;
        var fromIndex = $scope.todoWidget.drag.index;
        if (!fromBucket || fromIndex < 0) return;

        if (!targetBucket) targetBucket = fromBucket;
        if (['hot', 'warm', 'cold'].indexOf(targetBucket) === -1) return;

        var groups = $scope.todoWidget.groups || { hot: [], warm: [], cold: [] };
        var source = groups[fromBucket] || [];
        if (!source.length || fromIndex >= source.length) return;

        var moved = source.splice(fromIndex, 1)[0];
        var target = groups[targetBucket] || [];
        var insertAt = parseInt(targetIndex, 10);
        if (isNaN(insertAt) || insertAt < 0 || insertAt > target.length) insertAt = target.length;
        target.splice(insertAt, 0, moved);
        moved.priority_type = targetBucket;

        $scope.todoWidget.drag.bucket = '';
        $scope.todoWidget.drag.index = -1;

        $scope.todoWidget.tasks = getOrderedTodoFromGroups(groups);
        applyVisibleTodoSegments();

        persistTodoOrder(function (orderedOk) {
            if (!orderedOk) {
                messages('warning', 'Warning!', 'Unable to save task order.', 4500);
                return;
            }
            persistTodoPriorityType(moved, targetBucket, function (typeOk) {
                if (!typeOk) {
                    messages('warning', 'Warning!', 'Priority updated in UI but API did not confirm priority type save.', 4500);
                }
            });
        });
    };

    $scope.openTodoActiveModal = function () {
        ensureTodoPrioritySelectNative();
        $('#todoActiveTaskModal').modal('show');
        refreshTodoVisibleWindow();
    };

    $scope.refreshDashboard = function () {
        $scope.dashboardMeta.loading = true;
        $scope.dashboardMeta.error = '';
        $scope.dashboardMeta.today = getToday();

        $q.all([
            $http.get(rootUrl + 'dashboard/index'),
            $http.get(rootUrl + 'dashboard/fetch_userdata'),
            $http.get(rootUrl + 'dashboard/check_other_privilge').then(function (response) {
                return response;
            }, function () {
                return { data: [] };
            }),
            $http.get(rootUrl + 'dashboard/check_emp_privilge').then(function (response) {
                return response;
            }, function () {
                return { data: [] };
            }),
            $http.get(rootUrl + 'dashboard/check_privilege').then(function (response) {
                return response;
            }, function () {
                return { data: 2 };
            }),
            $http.get(rootUrl + 'dashboard/fetch_admin'),
            $http.get(rootUrl + 'dashboard/fetch_user'),
            $http.get(rootUrl + 'dashboard/attendance'),
            $http.get(rootUrl + 'dashboard/get_task'),
            $http.get(rootUrl + 'dashboard/fetch_journals_data'),
            $http.get(rootUrl + 'hr_follow_up/dash_data?date=' + $scope.dashboardMeta.today),
            $http.get(rootUrl + 'hr_follow_up/dash_data'),
            $http.get(rootUrl + 'task/view/2000/1?join=1'),
            $http.get(rootUrl + 'hr_staff_details/view'),
            $http.get(rootUrl + 'hr_payslip/view'),
            $http.get(rootUrl + 'employee/fetch_emp_bday').then(function (response) {
                return response;
            }, function () {
                return { data: [] };
            })
        ]).then(function (responses) {
            var auth = responses[0].data;
            if (auth === 0 || auth === '0') {
                window.location.assign('login.html');
                return;
            }

            refreshIdentity(responses[1].data);
            setRoleAccess(responses[2].data, responses[3].data, responses[4].data);
            $scope.summary.adminCount = toCount(responses[5].data);
            $scope.summary.userCount = toCount(responses[6].data);
            $scope.summary.employeeCount = $scope.summary.adminCount + $scope.summary.userCount;

            var attendance = responses[7].data || {};
            $scope.stats.attendance.present = toNumber(attendance.present);
            $scope.stats.attendance.absent = toNumber(attendance.absent);
            $scope.stats.attendance.total = toNumber(attendance.total);
            $scope.progress.attendance = percent($scope.stats.attendance.present, $scope.stats.attendance.total);

            var tasks = responses[8].data || {};
            $scope.stats.tasks.monthly = toNumber(tasks.total_month_task);
            $scope.stats.tasks.running = toNumber(tasks.total_month_run);
            $scope.stats.tasks.completed = $scope.stats.tasks.monthly - $scope.stats.tasks.running;
            if ($scope.stats.tasks.completed < 0) {
                $scope.stats.tasks.completed = 0;
            }
            $scope.progress.runningTasks = percent($scope.stats.tasks.running, $scope.stats.tasks.monthly);
            $scope.progress.taskCompletion = percent($scope.stats.tasks.completed, $scope.stats.tasks.monthly);

            var journals = responses[9].data || {};
            $scope.stats.journals.debit = toNumber(journals.debit);
            $scope.stats.journals.credit = toNumber(journals.credit);
            $scope.stats.journals.total = toNumber(journals.total_trans);
            $scope.progress.debitShare = percent($scope.stats.journals.debit, $scope.stats.journals.total);

            rawData.followupsToday = asArray(responses[10].data);
            rawData.followupsAll = asArray(responses[11].data);

            var taskPayload = responses[12].data || {};
            rawData.tasksAll = asArray(taskPayload.data || taskPayload);

            rawData.staffAll = asArray(responses[13].data);

            rawData.payslipsAll = asArray(responses[14].data);
            rawData.birthdaysAll = asArray(responses[15].data);

            $scope.onPresetChange();
            $scope.loadTodoWidget();
            if ($scope.roleAccess.canRating) {
                loadRatingFiltersAndData();
            } else {
                rawData.ratingsAll = [];
            }
            $scope.dashboardMeta.loading = false;
            refreshTodoVisibleWindow();
        }, function () {
            $scope.dashboardMeta.loading = false;
            $scope.dashboardMeta.error = 'Unable to load dashboard data. Please verify API/session and retry.';
        });
    };

    $scope.refreshDashboard();
}]);
//blank line is required
app.controller('change_password',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	rootUrl=$rootScope.site_url;
	ch_module="change_password";
//	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$scope.x={};
	$scope.filter_new=function()
	{
		$scope.x={};
	}
	$scope.save_data=function(x)
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+"login/change_password_submit",
			data: $("#changeform1").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					$scope.filter_new();
					messages("success", "Success!","Password Changed Successfully", 3000);
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	
}]);//blank line is required
app.controller('grade',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	rootUrl=$rootScope.site_url;
	module="hr_grades/";
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});

	$scope.loader=function()
	{
		$http.get(rootUrl+module+"view").success(function(data){
			$scope.datadb=data;
		})
	}
	$scope.loader();
	$scope.update_call=function(y){
		$scope.x=y;
	}
	
	$scope.filter_new=function(){
		$scope.x={};
	}
	
	$scope.save_data=function(y){
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"save",
			data: $("#catform").serialize(),
//			xhrFields: { withCredentials: true },
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data){
				if(data=="1")
				{
					$scope.x={};                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
					messages("success", "Success!","Grade Saved Successfully", 3000);
					$scope.loader();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", .3000);
				}
				else
				{
					messages("danger", "Warning!",data, 8000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
		
	}
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Grade may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"delete?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Grade Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!",data+", Grade not Deleted", 4000);
					}
					$scope.loader();
				})
			}
		}
	}
	
}]);app.controller('hr_designation',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	module='hr_designation';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$http.get(rootUrl+"hr_departments/view").success(function(data)
	{
		$scope.departments=data;
	})
	$http.get(rootUrl+"hr_grades/view?st=1").success(function(data)
	{
		$scope.grades=data;
	})
	
	$scope.init=function()
	{
		$http.get(rootUrl+module+"/view?join=1").success(function(data)
		{
			$scope.datadb=data;
		})
	}
	$scope.init();
	
	$scope.update_call=function(y)
	{
		$scope.x=y;
	}
	$scope.fetch_salary=function(g)
	{
		if(g)
		{
			$scope.salary="loading......";
			$http.get(rootUrl+"hr_grades/view?grade="+g).success(function(data)
			{
				$scope.salary=data[0].min_sal+" - "+ data[0].max_sal;
			})
		}
		else $scope.salary="";
	}
	
	$scope.filter_new=function()
	{
		$scope.x={};
		$scope.salary="";
	}
	
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"/save",
			data: $("#desform").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				console.log(data);
				if(data=="1")
				{
					messages("success", "Success!","Designation Saved Successfully", 3000);
					$scope.init();
					$scope.filter_new();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Designation may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"/delete?dg_id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Designation Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Designation not Deleted", 4000);
					}
					$scope.init();
				})
			}
		}
	}
}]);app.controller('pay_setting',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	module='hr_pay_setting';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$http.get(rootUrl+"hr_paytype/view?st=1").success(function(data)
	{
		$scope.paytypes_data=data;
	})
	$http.get(rootUrl+"hr_grades/view?st=1").success(function(data)
	{
		$scope.grades=data;
	})
	$scope.ftype=function(t){
		if(t=='1') return "-"; else return "+";
	}
	$scope.init=function()
	{
		$http.get(rootUrl+module+"/view?join=1").success(function(data)
		{
			$scope.datadb=data;
		})
	}
	$scope.init();
	
	$scope.update_call=function(y)
	{
		$scope.x=y;
	}
	
	
	$scope.filter_new=function()
	{
		$scope.x={};
		$scope.salary="";
	}
	
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"/save",
			data: $("#desform").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","PaySetting Saved Successfully", 3000);
					$scope.init();
					$scope.filter_new();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Pay Setting  may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"/delete?ps_id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Pay Setting Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Pay Setting  not Deleted", 4000);
					}
					$scope.init();
				})
			}
		}
	}
}]);app.controller('hr_leaves',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	lmodule='hr_leaves/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+lmodule+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});

	$scope.login_check=localStorage.getItem('type');
	$scope.emp_id=localStorage.getItem('emp_id');
	$scope.pageno = 1;
	$scope.total_count = 0;
	$scope.itemsPerPage = '12';
	$scope.qx = {};
	$scope.datadb = [];
	$scope.session_list = [];
	$scope.x = {sess:1};
	$scope.leave_modal_title = "Add Leave";

	$scope.init_datepicker = function()
	{
		setTimeout(function(){
			$("#DOB2").datepicker();
			$("#DOB3").datepicker();
		},100);
	};

	function initHrLeavesSelect2() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		setTimeout(function () {
			var $modal = $('#hrLeavesModal');
			var isSelect2V4 = !!($.fn.select2 && $.fn.select2.amd);

			if (!$modal.length) {
				return;
			}

			$modal.find('select').each(function () {
				var $el = $(this);
				if (!$el.is('select')) {
					return;
				}

				if ($el.data('select2')) {
					$el.select2('destroy');
				}

				var options = {
					width: '100%',
					allowClear: false,
					minimumResultsForSearch: 0
				};

				if (isSelect2V4) {
					options.dropdownParent = $modal;
				}

				$el.select2(options);
			});
		}, 0);
	}

	function initFilterSelect2() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		setTimeout(function () {
			var $filterBar = $('.hr-leaves-filterbar');

			if (!$filterBar.length) {
				return;
			}

			$filterBar.find('select').each(function () {
				var $el = $(this);
				if (!$el.is('select')) {
					return;
				}

				if ($el.data('select2')) {
					$el.select2('destroy');
				}

				var options = {
					width: '100%',
					allowClear: true,
					minimumResultsForSearch: 0
				};

				$el.select2(options);
			});
		}, 0);
	}

	function allowSelect2TypingInsideHrLeavesModal() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.modal || !$.fn.modal.Constructor) {
			return;
		}

		var ModalConstructor = $.fn.modal.Constructor;
		if (ModalConstructor.prototype._hrLeavesSelect2FocusPatched) {
			return;
		}

		ModalConstructor.prototype.enforceFocus = function () {
			var modalThis = this;
			$(document)
				.off('focusin.bs.modal')
				.on('focusin.bs.modal', function (e) {
					var $target = $(e.target);
					var isInsideModal = modalThis.$element[0] === e.target || modalThis.$element.has(e.target).length;
					var isSelect2Input =
						$target.closest('.select2-container, .select2-dropdown, .select2-drop, .select2-search').length > 0 ||
						$target.is('.select2-input, .select2-search__field');

					if (!isInsideModal && !isSelect2Input) {
						modalThis.$element.trigger('focus');
					}
				});
		};

		ModalConstructor.prototype._hrLeavesSelect2FocusPatched = true;

		$(document).off('select2:open.hrLeaves select2-open.hrLeaves');
		$(document).on('select2:open.hrLeaves select2-open.hrLeaves', function () {
			setTimeout(function () {
				var $search = $('.select2-container-active .select2-input, .select2-drop-active .select2-input, .select2-container--open .select2-search__field');
				if ($search.length) {
					$search.focus();
				}
			}, 0);
		});
	}

	$scope.loader = function(pageno)
	{
		if(!pageno)
			pageno = 1;
		$scope.pageno = pageno;

		var params = ["join=1"];
		if($scope.qx.emp_id)
			params.push("emp_id=" + encodeURIComponent($scope.qx.emp_id));
		if($scope.qx.sess_id)
			params.push("sess_id=" + encodeURIComponent($scope.qx.sess_id));
		if($scope.qx.status!==undefined && $scope.qx.status!=="")
			params.push("status=" + encodeURIComponent($scope.qx.status));

		var url = rootUrl + lmodule + "view/" + $scope.itemsPerPage + "/" + pageno;
		if(params.length)
			url += "?" + params.join("&");

		$http.get(url).success(function(response)
		{
			if(response && response.data !== undefined)
			{
				$scope.datadb = response.data || [];
				$scope.total_count = response.total_count || 0;
			}
			else
			{
				$scope.datadb = response || [];
				$scope.total_count = ($scope.datadb || []).length;
			}
		});
	};

	$scope.apply_filters = function()
	{
		$scope.loader(1);
	};

	$scope.clear_filters = function()
	{
		$scope.qx = {};
		$scope.itemsPerPage = '12';
		$scope.loader(1);
	};

	$scope.on_items_per_page_change = function()
	{
		$scope.loader(1);
	};

	$scope.initalValue=function()
	{
		$scope.x.cl=0;
		$scope.x.sl=0;
		$scope.x.pl=0;
		$scope.x.ml=0;
		$scope.x.lwp=0;
		$scope.x.days=0;
	};

	$scope.get_days=function()
	{
		if(!$scope.x.to || !$scope.x.from)
			return;

		$scope.initalValue();
		$scope.disable=0;
		$scope.x.reason="";

		$scope.color2 = {
		        "background-color" : "white",
		   };

		$scope.dateError=0;
		$scope.compare = $scope.x.to.split("/");
		$scope.compare =parseInt($scope.compare[1]);

		$scope.x.fDate = $scope.x.from.split("/");
		$scope.x.fDate =parseInt($scope.x.fDate[1]);

		if($scope.compare==$scope.x.fDate)
		{
			if($scope.x.from && $scope.x.to)
			{
				$http.get(rootUrl+"hr_leaves/number_of_working_days?sdate="+$scope.x.from+"&edate="+$scope.x.to).success(function(data){
		    		$scope.x.days=parseInt(data);
		    	});
			}
		}
		else
		{
			$scope.disable=1;
			$scope.dateError=1;
			$scope.color2 = {
			        "background-color" : "#f17d7d6b",
			   };
			$scope.initalValue();
			$scope.x.reason="";

			$scope.x.casual="";
			$scope.x.sick="";
			$scope.x.paid="";
			$scope.x.maternity="";

			$scope.cl=0;
			$scope.sl=0;
			$scope.pl=0;
			$scope.ml=0;
			$scope.lwp=0;
		}

		$http.get(rootUrl+"hr_leaves/leaveRecord?from="+$scope.x.from+"&to="+$scope.x.to+"&emp_id="+$scope.x.emp_id).success(function(data)
		{
    		$scope.leaveshow=0;
    		if(data.show=='1')
    		{
    			$scope.leaveshow=1;
    			$scope.from=data.from;
    			$scope.to=data.to;
    		}
    	});
	};


	$scope.clear_leave_to=function()
	{
		$("#DOB3").val("");
		$scope.leaveshow=0;
	};

	$scope.fetch_employee=function(y)
	{
		$http.get(rootUrl+"hr_staff_details/view?data=emp_id,staff_name&status=1").success(function(data)
		{
			$scope.employees=data;
			initHrLeavesSelect2();
			initFilterSelect2();
		});
	};
	$scope.fetch_employee();

	$scope.load_session_filter = function()
	{
		$http.get(rootUrl+"hr_leaves/employee_session").success(function(data)
		{
			$scope.session_list = data || [];
			initFilterSelect2();
		});
	};

	$scope.fetch_total_leave=function(ses_id,id)
	{
		$scope.initalValue();
		$scope.cl=0;
		$scope.sl=0;
		$scope.pl=0;
		$scope.ml=0;

		$http.get(rootUrl+"hr_leave_setting/view?grade="+$scope.grade).success(function(data)
		{
			if(data.length>0)
			{
				$scope.x.casual=data[0].cl;
				$scope.x.sick=data[0].sl;
				$scope.x.paid=data[0].pl;
				$scope.x.maternity=data[0].ml;
			}

			$http.get(rootUrl+"hr_leaves/employe_session_leave?join=1&emp_id="+id+"&sess_id="+ses_id).success(function(data)
			{
				angular.forEach(data, function(val, key)
				{
					if(val.cl)
						$scope.cl=$scope.cl+parseFloat(val.cl);
					if(val.sl)
						$scope.sl=$scope.sl+parseFloat(val.sl);
					if(val.pl)
						$scope.pl=$scope.pl+parseFloat(val.pl);
					if(val.ml)
						$scope.ml=$scope.ml+parseFloat(val.ml);
				});
			});
    	});
	};


	$scope.fetch_leave=function(id,skipListRefresh,preserveFormData)
	{
		if(preserveFormData!==true)
		{
			$scope.cl=0;
			$scope.sl=0;
			$scope.pl=0;
			$scope.ml=0;
			$scope.initalValue();
			$scope.x.reason="";
			$scope.x.from="";
			$scope.x.to="";

			$scope.x.casual="";
			$scope.x.sick="";
			$scope.x.paid="";
			$scope.x.maternity="";

			$scope.x.sess=1;
		}
		if(!id)
			return;

		if(skipListRefresh!==true)
		{
			$scope.qx.emp_id = id;
			$scope.loader(1);
		}

		$http.get(rootUrl+"hr_staff_details/view?emp_id="+id).success(function(data)
		{
			$scope.grade=data[0].grade;
			$http.get(rootUrl+"hr_leaves/employe_session_leave?emp_id="+id).success(function(data)
			{
				if(data.length>1)
				{
					$scope.x.sess=2;
					 $scope.required = true;
					 $scope.session=data;
					 if(preserveFormData!==true || !$scope.x.sess_id)
					 	$scope.x.sess_id=data[0].sess_id;
					 $scope.fetch_total_leave($scope.x.sess_id,id);
				}
				else
				{
					$http.get(rootUrl+"hr_leave_setting/view?grade="+$scope.grade).success(function(data)
					{
						if(data.length>0)
						{
							$scope.x.casual=data[0].cl;
							$scope.x.sick=data[0].sl;
							$scope.x.paid=data[0].pl;
							$scope.x.maternity=data[0].ml;
						}

		    			});
					$http.get(rootUrl+"hr_leaves/view?emp_id="+id).success(function(data)
					{
						angular.forEach(data, function(val, key)
						{
							if(val.cl)
								$scope.cl=$scope.cl+parseFloat(val.cl);
							if(val.sl)
								$scope.sl=$scope.sl+parseFloat(val.sl);
							if(val.pl)
								$scope.pl=$scope.pl+parseFloat(val.pl);
							if(val.ml)
								$scope.ml=$scope.ml+parseFloat(val.ml);
						});
		    			});
				}
	    	});

			initHrLeavesSelect2();
		});
	};

	$scope.calc_lwp=function()
	{
		$scope.disable=0;
		$scope.x.lwp=parseFloat($scope.x.days)-(parseFloat($scope.x.cl)+parseFloat($scope.x.sl)+parseFloat($scope.x.ml)+parseFloat($scope.x.pl));
		if($scope.x.lwp<0)
		{
			$scope.disable=1;
			$scope.color = {
			        "color" : "white",
			        "background-color" : "red",
			   };
		}else{
			$scope.color = {
			        "background-color" : "white",
			   };
		}
	};
	$scope.update_call=function(y)
	{
		$scope.cl=0;
		$scope.sl=0;
		$scope.pl=0;
		$scope.ml=0;
		$scope.x=angular.copy(y);
		if(y.sess_id&&y.sess_id>0)
		{
			$http.get(rootUrl+"hr_leaves/employee_session?sess_id="+y.sess_id).success(function(data)
			{
				$scope.x.sess=2;
				 $scope.required = true;
				 $scope.session=data;
				 $scope.x.sess_id=data[0].sess_id;
			});
		}
		$scope.fetch_leave($scope.x.emp_id,true,true);
	};

	$scope.open_leave_modal=function(mode,y)
	{
		if(mode=="edit" && y)
		{
			$scope.leave_modal_title = "Edit Leave";
			$scope.update_call(y);
		}
		else
		{
			$scope.leave_modal_title = "Apply For Leave";
			$scope.filter_new(false);
		}
		$('#hrLeavesModal').modal('show');
		allowSelect2TypingInsideHrLeavesModal();
		initHrLeavesSelect2();
		$scope.init_datepicker();
	};

	$scope.filter_new=function(refreshList)
	{
		$scope.x={sess:1};
		$scope.salary="";
		$scope.required = false;
		$scope.session = [];
		$scope.disable = 0;
		$scope.leaveshow = 0;
		$scope.dateError = 0;
		$scope.color = {"background-color" : "white"};
		$scope.color2 = {"background-color" : "white"};
		$scope.cl=0;
		$scope.sl=0;
		$scope.pl=0;
		$scope.ml=0;
		$scope.lwp=0;
		if(refreshList!==false)
			$scope.loader($scope.pageno || 1);
	};

	$scope.save_data=function(x)
	{
		$('#submitbtn11').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+lmodule+"/save",
			data: $("#hr_leaves_form2").serialize(),
			beforeSend: function()
			{
				$('#loader121').css('display','inline');
			},
			success: function(data)
			{
				console.log(data);
				if(data=="1")
				{
					messages("success", "Success!","Leave Saved Successfully", 3000);
					$scope.loader($scope.pageno || 1);
					$scope.filter_new(false);
					$scope.cl=0;
					$scope.sl=0;
					$scope.pl=0;
					$scope.ml=0;
					$scope.lwp=0;
					$('#hrLeavesModal').modal('hide');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader121').css('display','none');
				$('#submitbtn11').attr('disabled',false);
			}
		});
	};

	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Data may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+lmodule+"/delete?el_id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Data Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Data not Deleted", 4000);
					}
					$scope.loader($scope.pageno || 1);
				});
			}
		}
	};

	$scope.load_session_filter();
	$scope.filter_new(false);
	$scope.loader(1);
	$scope.init_datepicker();
	initFilterSelect2();
	allowSelect2TypingInsideHrLeavesModal();
	$(document).off('shown.bs.modal.hrLeavesSelect2', '#hrLeavesModal').on('shown.bs.modal.hrLeavesSelect2', '#hrLeavesModal', function () {
		initHrLeavesSelect2();
	});
}]);
app.controller('medical',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	mmodule='hr_medical_details';
	rootUrl=$rootScope.site_url;
	//login auth not required here..
	
	$scope.save_data1=function(x)
	{
		$('#submitbtn3').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+mmodule+"/save",
			data: $("#medicalform").serialize(),
			beforeSend: function()
			{
				$('#loader3').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$("#dc_id").trigger('click');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader3').css('display','none');
				$('#submitbtn3').attr('disabled',false);
			}
		});
	}
}]);app.controller('staffs',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+"hr_staff_details/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){window.location.assign('index.html');}});

	$scope.login_check=localStorage.getItem('login');
	$scope.type_check=localStorage.getItem('type');
	console.log('login_check:', $scope.login_check, 'type_check:', $scope.type_check);
	$scope.default_status="1";
	$scope.qs={status:$scope.default_status};
	$scope.staff_form_tab="staff_details1";
	$scope.select_staff_form_tab=function(tab_key)
	{
		var tab_map={
			"staff_details1":"#cus_tab",
			"medical_details":"#m_id",
			"documents_details":"#dc_id",
			"work_details":"#we_id",
			"guard_details":"#gd_id",
			"academic_details":"#acd_id",
			"payroll_monthly":"#ps_id"
		};
		var safe_tab=tab_key || "staff_details1";
		$scope.staff_form_tab=safe_tab;
		if(tab_map[safe_tab]){
			$(tab_map[safe_tab]).trigger('click');
		}
	}
	$http.get(rootUrl+"hr_grades/view?data=grade").success(function(data)
	{
		$scope.grades=data;
	})
	$scope.fetch_destinations=function(grade)
	{
		if(grade)
		{
			$http.get(rootUrl+"hr_designation/view?join=1&data=d_id,name&grade="+grade).success(function(data)
			{
				$scope.designations=data;
			})
			 
			$scope.salaryss="loading...";
			$http.get(rootUrl+"hr_grades/view?grade="+grade).success(function(data){
				if(data.length>0){
					$scope.min_sal=data[0].min_sal;
					$scope.max_sal=data[0].max_sal;
				}
			})
		}
		else
		{
			$scope.min_sal=0;
			$scope.max_sal=0;
		}
	}
	$scope.init=function()
	{
		var safe_status=$scope.qs.status || $scope.default_status;
		$http.get(rootUrl+"hr_staff_details/view?status="+encodeURIComponent(safe_status)+"&st="+encodeURIComponent(safe_status)).success(function(data)
		{
			$scope.datadb=data;
			$scope.qs.status=safe_status;
		})
	}
	$scope.init();
	$scope.filter_new=function()
	{
		$scope.qs={status:$scope.default_status};
		$scope.init();
	}

	$scope.open_add_staff=function()
	{
		$scope.filter_new1();
		$scope.staff_modal_title="Add Staff";
		$("#staffFormModal").modal("show");
		$scope.select_staff_form_tab("staff_details1");
	}

	$scope.open_view_staff=function()
	{
		$("#staffFormModal").modal("hide");
	}

	$scope.webcam=function(id)
	{
		window.open("./app/components/staffs/camera.html?emp_id="+id);
	}
	
	$scope.filter_data=function(name,grade,d_id,status)
	{
		var safe_name=name || "";
		var safe_grade=grade || "";
		var safe_d_id=d_id || "";
		var safe_status=(status===undefined || status===null || status==="") ? $scope.default_status : status;
		$http.get(rootUrl+"hr_staff_details/view?name="+encodeURIComponent(safe_name)+"&grade="+encodeURIComponent(safe_grade)+"&d_id="+encodeURIComponent(safe_d_id)+"&status="+encodeURIComponent(safe_status)+"&st="+encodeURIComponent(safe_status)).success(function(data){
			$scope.datadb=data;
			$scope.qs.status=safe_status;
		})
	}
	$scope.x={};
	$scope.docdb="";
	$scope.workdb="";
	$scope.m="";
	$scope.d="";
	$scope.w="";
	$scope.g="";
	$scope.eye_check="";
	$scope.supdate_call=function(id,gr)
	{
		$scope.fetch_destinations(gr);
		$scope.emp_id=id;
		$http.get(rootUrl+"hr_staff_details/view?emp_id="+id).success(function(data)
		{
			$scope.x=data[0];
			$scope.emp_staff_name=data[0].staff_name;
//			$scope.type=data[0].type;
			$scope.login=data[0].login;
			console.log('staff data:',data);
		})
		$http.get(rootUrl+"hr_medical_details/view?emp_id="+id).success(function(data)
		{
			$scope.m=data[0];
			if(data.length>0)
			{
				if(data[0].eye_problem)
				{
					$scope.eye_check=1;
					$("#eye_check").prop('checked',true);
				}
				if(data[0].disability)
				{
					$scope.disab_check=1;
					$("#disab_check").prop('checked',true);
				}
			}
		})
		$http.get(rootUrl+"hr_document_details/view?emp_id="+id).success(function(data)
		{
			$scope.docdb=data;
		})
		
		$http.get(rootUrl+"hr_work_experience/view?emp_id="+id).success(function(data)
		{
			$scope.workdb=data;
		})
		
		$http.get(rootUrl+"guardian_details/view?emp_id="+id).success(function(data)
		{
			$scope.gaurdiandb=data;
		})
		$http.get(rootUrl+"hr_academic/view?emp_id="+id).success(function(data)
		{
			$scope.accdata=data;
		})
		$scope.staff_modal_title="Edit Staff";
		$("#staffFormModal").modal("show");
		$scope.select_staff_form_tab("staff_details1");
	}
	
	$scope.filter_new1=function()
	{
		$scope.x={};
		$scope.emp_id="";
		$scope.docdb="";
		$scope.workdb="";
		$scope.m="";
		$scope.d="";
		$scope.w="";
		$scope.emp_staff_name="";
	}
	$scope.save_data1=function(x)
	{
		$('#staffform').ajaxForm({
			type: "POST",
			url: rootUrl+"hr_staff_details/save",
			beforeSend: function()
			{
				$('#loader1').css('display','inline');
			},
			success: function(data)
			{
				console.log(data);
				if(data.error=="0")
				{
					if(data.emp_id)
					{
						$scope.x.emp_id=data.emp_id;
						$scope.emp_id=data.emp_id;
						$http.get(rootUrl+"hr_staff_details/view?emp_id="+$scope.emp_id).success(function(data)
						{
							$scope.emp_staff_name=data[0].staff_name;
						})
					}
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.init();
					$scope.select_staff_form_tab("medical_details");
				}
				else if (data.error == '1')
				{
					messages("danger", "Warning!",data.msg, 6000);
				} else {
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader1').css('display','none');
				$('#submitbtn1').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Staff Details may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+"hr_staff_details/delete?emp_id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Staff Details Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Staff Details not Deleted. "+data, 4000);
					}
					$scope.init();
				})
			}
		}
	}
}]);
app.controller('documents',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	dmodule='hr_document_details';
	rootUrl=$rootScope.site_url;
	$scope.imgUrl=$rootScope.img_url;
	$scope.d={};
	$scope.initd=function()
	{
		$http.get(rootUrl+"hr_document_details/view?emp_id="+$scope.emp_id).success(function(data)
		{
			$scope.docdb=data;
		})
	}
	
//	$scope.init();
	
	$scope.update_call=function(y)
	{
		$scope.d=y;
	}
	$scope.filter_new_doc=function()
	{
		$scope.d={};
	}
	
	$scope.save_data=function()
	{
		$('#documents').ajaxForm({
			type: "POST",
			url: rootUrl+dmodule+"/save",
			beforeSend: function()
			{
				$('#submitbtn2').attr('disabled',true);
				$('#loader2').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.initd();
					$scope.filter_new_doc();
					$("#we_id").trigger('click');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader2').css('display','none');
				$('#submitbtn2').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting documents may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+dmodule+"/delete?dc_id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","documents Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","documents not Deleted", 4000);
					}
					$scope.initd();
				})
			}
		}
	}
}]);app.controller('work',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	wmodule='hr_work_experience';
	rootUrl=$rootScope.site_url;
//	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 3000);window.location.assign('index.html');}}); NOT Required in Child Module	
	
	$scope.w={};
	$scope.init=function()
	{
		$http.get(rootUrl+wmodule+"/view?emp_id="+$scope.emp_id).success(function(data)
		{
			$scope.workdb=data;
		})
	}
	
	$scope.update_call=function(y)
	{
		$scope.w=y;
	}
	$scope.filter_new=function()
	{
		$scope.w={};
	}
	
	$scope.save_data=function(x)
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+wmodule+"/save",
			data: $("#workform").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.init();
					$scope.filter_new();
					$("#gd_id").trigger("click");
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}

	$scope.delete_data=function(id)
	{
		if(confirm("Are you Sure to DELETE ??"))
		{
			$http.get(rootUrl+wmodule+"/delete?we_id="+id).success(function(data){
				if(data=="1")
				{
					messages("success", "Success!","Work Experience Deleted Successfully", 3000);
				}
				else
				{
					messages("danger", "Warning!","Work Experience not Deleted", 4000);
				}
				$scope.init();
			})
		}
	}
}]);app.controller('guardian_details',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	gua_module='guardian_details';
	rootUrl=$rootScope.site_url;
	
	$scope.g={};
	$scope.initg=function()
	{
		$http.get(rootUrl+"guardian_details/view?emp_id="+$scope.emp_id).success(function(data)
		{
			$scope.gaurdiandb=data;
		})
	}
//	$scope.initg();
	$scope.change=true;
	$scope.update_call=function(y)
	{
		if(y.stch==1)
		{
			$scope.change=true;
		}	
		else
		{
			$scope.change=false;
			$scope.change2=true;
		}
		
		$scope.g=y;
	}
	$scope.filter_new_guardian=function()
	{
		$scope.change=true;
		$scope.change2=false;
		$scope.g={};
	}
	
	$scope.save_data=function()
	{
		$('#guardianform').ajaxForm({
			type: "POST",
			url: rootUrl+gua_module+"/save",
			beforeSend: function()
			{
				$('#submitbtn5').attr('disabled',true);
				$('#loader5').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.initg();
					$scope.filter_new_guardian();
					$scope.change=true;
					$scope.change2=false;
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader5').css('display','none');
				$('#submitbtn5').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting documents may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+gua_module+"/delete?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Guardian Details Deleted Successfully", 3000);
						$scope.initg();
					}
					else
					{
						messages("danger", "Warning!","Guardian Details not Deleted", 4000);
					}
					$scope.initg();
				})
			}
		}
	}
}]);app.controller('academic',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	accmodule='hr_academic';
	rootUrl=$rootScope.site_url;
//	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 3000);window.location.assign('index.html');}}); NOT Required in Child Module	
	
	$scope.acc={};
	$scope.init=function()
	{
		$http.get(rootUrl+accmodule+"/view?emp_id="+$scope.emp_id).success(function(data)
		{
			$scope.accdata=data;
		})
	}
	
	$scope.update_call=function(y)
	{
		$scope.acc=y;
	}
	$scope.filter_new=function()
	{
		$scope.acc={};
	}
	
	$scope.save_data=function(x)
	{
		$('#submitbtnacc').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+accmodule+"/save",
			data: $("#academicform").serialize(),
			beforeSend: function()
			{
				$('#loaderacc').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.init();
					$scope.filter_new();
					$("#gd_id").trigger("click");
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loaderacc').css('display','none');
				$('#submitbtnacc').attr('disabled',false);
			}
		});
	}

	$scope.delete_data=function(id)
	{
		if(confirm("Are you Sure to DELETE ??"))
		{
			$http.get(rootUrl+accmodule+"/delete?acc_id="+id).success(function(data){
				if(data=="1")
				{
					messages("success", "Success!","Academic Details Deleted Successfully", 3000);
				}
				else
				{
					messages("danger", "Warning!","Academic Details not Deleted", 4000);
				}
				$scope.init();
			})
		}
	}
}]);//blank line is required
app.controller('hr_id_card',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	module='hr_id_card/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$http.get(rootUrl+"hr_grades/view?st=1").success(function(data)
	{
		$scope.grades=data;
	})
	$scope.x={};
	$scope.fetch_desig=function(grade)
	{
		$http.get(rootUrl+"hr_designation/view?grade="+grade+"&join="+1).success(function(data)
		{
			$scope.designation=data;
		})
	}
	$scope.print=function()
	{
		url=rootUrl+"hr_id_card/view?grade="+$scope.x.grade+"&d_id="+$scope.x.d_id+"&emp_id="+$scope.x.emp_id;
		window.open(url,"_blank", "toolbar=yes,scrollbars=yes,resizable=yes,top=10,left=10,width=1000;");
	}
	$scope.filter_new_id=function()
	{
		$scope.x={};
		$('#result').html("");
	}
	
	$scope.view_data = function(x)
	{
		$scope.myVar = true;
		$('#loader').css('display', 'inline');
		
		$http.get(rootUrl+"hr_id_card/view?grade="+$scope.x.grade+"&d_id="+$scope.x.d_id+"&emp_id="+$scope.x.emp_id).success(function(data)
		{
			$('#loader').css('display', 'none');
			$('#result').html(data);
		})
	}
	
}]);app.controller('leave_setting',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	module='hr_leave_setting';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	$scope.x={};
	
	$scope.init=function()
	{
		$http.get(rootUrl+module+"/view").success(function(data)
		{
			$scope.datadb=data;
		})
	}
	$http.get(rootUrl+"hr_grades/view?st=1").success(function(data)
	{
		$scope.grades=data;
	})
	$scope.init();
	
	$scope.update_call=function(y)
	{
		$scope.x=y;
	}
	$scope.filter_new=function()
	{
		$scope.x={};
	}
	
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"/save",
			data: $("#ptform").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.init();
					$scope.filter_new();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Leave Setting may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"/delete?id="+id).success(function(data)
				{
					if(data=="1")
					{
						messages("success", "Success!","Leave Setting Deleted Successfully", 3000);
						$scope.init();
					}
					else
					{
						messages("danger", "Warning!","Leave Setting not Deleted", 4000);
					}
				})
			}
		}
	}
}]);//blank line is required
app.controller('hr_category',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	module='category/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	$scope.x={};
	
	$scope.init=function()
	{
		$http.get(rootUrl+module+"view_data").success(function(data)
		{
			$scope.datadb=data;
		})
	}
	$scope.init();
	
	$scope.filter_new_cat=function()
	{
		$scope.x={};
	}
	$scope.update_call=function(y)
	{
		$scope.x=y;
		$("#addform").trigger('click');
		$("html, body").animate({ scrollTop: 0 }, 200);
	}
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"save_data",
			data: $("#catform").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.filter_new_cat();
					$scope.init();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Category may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"delete_data?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Category Details Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Category Details not Deleted", 4000);
					}
					$scope.init();
				})
			}
		}
	}
	
}]);
app.controller('client_login', ['$scope', '$rootScope', '$http', '$timeout', function ($scope, $rootScope, $http, $timeout) {
	rootUrl = $rootScope.site_url;
	$scope.page = {
		loading: false,
		saving: false,
		message: '',
		messageType: 'info'
	};
	$scope.customers = [];
	$scope.selectedCustomerId = '';

	function refreshSelect2() {
		$timeout(function () {
			if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
				return;
			}

			var $select = $('#client-login-customer');
			if (!$select.length) {
				return;
			}

			try {
				if ($select.data('select2')) {
					$select.select2('destroy');
				}
			} catch (e) {}

			$select.select2({
				width: '100%',
				placeholder: 'Select an active customer'
			});
		}, 0, false);
	}

	function setMessage(type, message) {
		$scope.page.messageType = type || 'info';
		$scope.page.message = message || '';
	}

	$scope.init = function () {
		$scope.page.loading = true;
		setMessage('info', 'Loading active customers...');

		$http.get(rootUrl + 'client_login/index').success(function (data) {
			if (data == 0) {
				window.location.assign('login.html');
				return;
			}
			if (data == 2) {
				window.location.assign('index.html');
				return;
			}
		});

		$http.get(rootUrl + 'client_login/active_customers').success(function (data) {
			$scope.customers = angular.isArray(data) ? data : [];
			$scope.page.loading = false;
			if (!$scope.customers.length) {
				setMessage('warning', 'No active customers were found.');
			} else {
				setMessage('success', 'Select a customer and click Login.');
			}
			refreshSelect2();
		}).error(function () {
			$scope.page.loading = false;
			setMessage('danger', 'Unable to load active customers.');
		});
	};

	$scope.login = function () {
		if (!$scope.selectedCustomerId) {
			setMessage('warning', 'Please select a customer first.');
			return;
		}

		$scope.page.saving = true;
		setMessage('info', 'Creating client session...');

		$http({
			method: 'POST',
			url: rootUrl + 'client_login/create_session',
			data: $.param({
				c_id: $scope.selectedCustomerId
			}),
			headers: {
				'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
			}
		}).then(function (response) {
			var res = (response && response.data) ? response.data : {};
			if (String(res.error) === '0' && res.redirect_url) {
				window.location.assign(res.redirect_url);
				return;
			}

			$scope.page.saving = false;
			setMessage('danger', res.msg || 'Unable to start client login.');
		}, function () {
			$scope.page.saving = false;
			setMessage('danger', 'Unable to start client login.');
		});
	};

	$scope.$watch('customers.length', function () {
		refreshSelect2();
	});

	$scope.init();
}]);
app.controller('user_privileges',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	rootUrl=$rootScope.site_url;
	module="user_privileges/";
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$('#progress').hide();
	$http.get(rootUrl+'hr_staff_details/view?data=username as name,emp_id&status=1').success (function(data) {
			$scope.users=data;
	});
	$http.get(rootUrl+'user_privileges/view_privileges_json').success (function(data) {
			$scope.modules=data;
	});

	$scope.reset_all=function()
	{
		$scope.user="";
		$scope.user_name="";
		$scope.o="";
	};
	$scope.fetch_data=function(id)
	{
		$scope.reset_all();
		$('#progress').toggle();
		$http.get(rootUrl+'user_privileges/view_data?id='+ id).success (function(data)
		{
			if(data.length<1)
			{
				$http.get(rootUrl+'user_privileges/user_default_privileges/'+ id).success (function(data)//insert default privileges
				{
					$scope.fetch_data(id);
				});
			}else{
				$scope.user=data;
				$('#progress').hide();	
			}
			$http.get(rootUrl+'user_privileges/otherPrivlg_view_data?id='+ id).success (function(data)//insert default privileges
			{
				if(data.length>0)
				{
					$scope.o=data;
					if(data[0].hr_staff_details=='1')
						$('#employee').prop('checked',true); 
					else
						$('#employee').prop('checked',false);
					if(data[0].hr_id_card=='1')
						$('#id_card').prop('checked',true);
					else
						$('#id_card').prop('checked',false);
					if(data[0].hr_report=='1')
						$('#report').prop('checked',true); 
					else
						$('#report').prop('checked',false);
					if(data[0].sms=='1')
						$('#sms').prop('checked',true); 
					else
						$('#sms').prop('checked',false);
					if(data[0].attendance=='1')
						$('#attendance').prop('checked',true); 
					else
						$('#attendance').prop('checked',false);
					if(data[0].task=='1')
						$('#taskss').prop('checked',true); 
					else
						$('#taskss').prop('checked',false);
				}
				else
				{
					$('#employee').prop('checked',false);
					$('#id_card').prop('checked',false);
					$('#report').prop('checked',false);
					$('#sms').prop('checked',false);
					$('#attendance').prop('checked',false);
					$('#taskss').prop('checked',false);
//					$('#user_privilege').prop('checked',false);
//					$('#payslip').prop('checked',false);
				}
			});
		});
		$("#btnsubmit").prop('disabled',false);
	};
	
	$scope.update_data=function(x)
	{
		$("#btnsubmit").text('Please Wait...');
		$("#btnsubmit").prop('disabled',true);
		$("#uprogress").css( 'display' , 'inline');
		$.ajax({
			type: "POST",
			url: rootUrl+"user_privileges/update_data",
			data: $("#form2").serialize(),
			beforeSend: function()
			{
				$('#progress').toggle();
			},
			success: function(data)
			{
				$("#btnsubmit").text('Save');
				$("#btnsubmit").prop('disabled',false);
				$('#progress').toggle();
				var data = $.parseJSON(data);
				if (data.type == "1") {
					messages("danger", "Warning!",data.error, 8000);
				} else {
					setTimeout($scope.unlockwindow, 2000);
					messages("success", "Success!",data.error, 4000);
				}
			}
		});
	};
	$scope.other_save=function(x)
	{
		$("#btnsubmito").text('Please Wait...');
		$("#btnsubmito").prop('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+"user_privileges/other_privilege",
			data: $("#form3").serialize(),
			beforeSend: function()
			{
				$('#progress').toggle();
			},
			success: function(data)
			{
				$("#btnsubmito").text('Save');
				$("#btnsubmito").prop('disabled',false);
				$('#progress').toggle();
				var data = $.parseJSON(data);
				if (data.type == "1") {
					messages("danger", "Warning!",data.error, 8000);
				} else {
					setTimeout($scope.unlockwindow, 2000);
					messages("success", "Success!",data.error, 4000);
				}
			}
		});
	};
	$scope.unlockwindow=function(){
		window.location.reload();
	}
	
	$scope.update_data_other=function(x){
		$.ajax({
			type: "POST",
			url: "other_privileges/update_data",
			data: $("#form3").serialize(),
			beforeSend: function()
			{
				$('#webprogress').css('display','inline');
			},
			success: function(data)
			{
				var arr = $.parseJSON(data);
				if(arr.type=="1")
				{
					$('#error_msg').html(arr.error);
					$('#error_modal').trigger("click");
				}
				else
				{
					setTimeout($scope.unlockwindow, 3000);
					$('#success_msg').html(arr.error);
					$('#alert_modal').trigger("click");
				}
				$('#webprogress').css('display','none');
			}
		});
	};
	
}]);app.controller('pay_head',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	module='hr_payslip';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$scope.type_check=localStorage.getItem('type');
	$scope.e={};
	$scope.init=function()
	{
		$http.get(rootUrl+module+"/view").success(function(data){
			$scope.datadb=data;
		})
	}
	
	$scope.update_call=function(y)
	{
		$scope.x=y;
		$scope.fetch_details(y.emp_id);
		$scope.calc_total();
		$("#pay_slip_form1").trigger('click');
	}
	
	$scope.filter_new=function()
	{
		$scope.x={};
		$scope.e={};
		$scope.qs={};
		$scope.x.value1=0;
		$scope.x.value2=0;
		$scope.x.net_deduction=0;
		$scope.init();
		$scope.show=0;
		
	}
	$scope.filter_new();
	
	$http.get(rootUrl+"hr_staff_details/view?st=1&data=staff_name,emp_id").success(function(data)
	{
		$scope.employees=data;
	})
	$http.get(rootUrl+"hr_grades/view?data=grade&st=1").success(function(data)
	{
		$scope.grades=data;
	})
	$scope.fetch_designations=function(grade)
	{
		$http.get(rootUrl+"hr_designation/view?join=1&data=d_id,name&grade="+grade).success(function(data)
		{
			$scope.designations=data;
		}) 
	}
	
	$scope.filter_data=function($name)
	{
		$http.get(rootUrl+"hr_payslip/view?name="+$name).success(function(data)
		{
				$scope.datadb=data;
		})
	}
	
	
	//testing
	$scope.print=function(y)
	{
		url=rootUrl+"printer/generate_payslip/"+y.pay_id;
		$.ajax(url).done(function(data)
		{ 
			var w = window.open();
			$(w.document.body).html(data);
		});
	}
	
	$scope.fetch_pay=function(pay_id)
	{
		if(pay_id)
		{
			$("#pay_id").val(pay_id);
			$http.get(rootUrl+"printer/generate_payslip/"+pay_id).success(function(data)
			{
				$("#modalBody").html(data);
			})
		}
	}
	
	$scope.initalize=function()
	{
		$scope.x={};
		$scope.check=0;
		$scope.show=0;
		
		$scope.halfMinTime=0;
		$scope.halfAmtPcnt=0;
		$scope.halfAbsnt=0;
		$scope.work_hour="";
		
		$scope.pf_comPcent="";
		$scope.pf_empPcent="";
		$scope.pf_max="";
		$scope.pf_min="";
		
		$scope.gminustotal=0;
		$scope.gplustotal=0;
		$scope.gtotal=0;
		$scope.total=0;
		$scope.x.value1=0;
		$scope.x.value2=0;
		
		$scope.minustotal=0;
		$scope.plustotal=0;
	}
	
	$scope.fetch_details=function(empid)
	{
		$scope.loading=1;
		$scope.initalize();
		
		$http.get(rootUrl+"hr_staff_details/view?emp_id="+empid).success(function(data)
		{
			$scope.emp_details=data;
			$scope.b_sal=parseFloat(data[0].b_salary);
			$scope.e.grade=data[0].grade;
			$http.get(rootUrl+"hr_grades/view?data=gpay&grade="+data[0].grade).success(function(data){
				if(data.length>0)
					$scope.x.gpay=data[0].gpay;
				else
					$scope.x.gpay=data[0].gpay;
				
				$scope.get_pay_names();
				$scope.loading=0;
				$scope.calc_pf($scope.b_sal);
			})
		})
	}
	
	$scope.GetHalfDaySettings=function(mnth,yr)
	{
		year=20+yr; // changing year into format of 20XX
		var date= new Date(year, mnth, 0).getDate();
		
		$http.get(rootUrl+"hr_master_settings/view?data=work_hour,wrk_days").success(function(data)
		{
			if(data.length>0)
			{
				$scope.work_hour=data[0].work_hour;
				if(data[0].wrk_days!=0)
					$scope.x.work_days=data[0].wrk_days;
				else
					$scope.x.work_days=date;
			}
			$http.get(rootUrl+"half_day_settings/view?data=m_time,pay_amt,absent").success(function(data)
			{
				if(data.length>0)
				{
					$scope.halfMinTime=data[0].m_time;
					$scope.halfAmtPcnt=parseFloat(data[0].pay_amt).toFixed(2);
					$scope.halfAbsnt=parseInt(data[0].absent);
				}
				else
				{
					$scope.halfMinTime=0;
					$scope.halfAmtPcnt=0;
					$scope.halfAbsnt=0;
				}
			})
		})
	}
	
	$scope.calc_pf=function(b_sal)
	{
		$http.get(rootUrl+"pf_settings/view").success(function(data)
		{
			if(data.length<1){
				$scope.x.pf_amt=0;
			}
			else
			{
				$scope.pf_empPcent=data[0].emp_pcnt;
				$scope.pf_comPcent=data[0].com_pcnt;
				$scope.pf_max=parseFloat(data[0].max_amt);
				$scope.pf_min=parseFloat(data[0].min_amt);
				
				
				$scope.x.pf_amt=parseFloat(parseFloat(b_sal)*(parseFloat($scope.pf_empPcent)/100)).toFixed(2);
				$scope.x.compf_amt=parseFloat(parseFloat(b_sal)*(parseFloat($scope.pf_comPcent)/100)).toFixed(2);
				if($scope.x.pf_amt>$scope.pf_max)
				{
					$scope.x.pf_amt=$scope.pf_max;
				}
				if($scope.x.pf_amt<$scope.pf_min)
				{
					$scope.x.pf_amt=$scope.pf_min;
				}
				if($scope.x.compf_amt>$scope.pf_max)
				{
					$scope.x.compf_amt=$scope.pf_max;
				}
				if($scope.x.compf_amt<$scope.pf_min)
				{
					$scope.x.compf_amt=$scope.pf_min;
				}
				$scope.show_value();
			}
		});
	}
	
	$scope.halfshow=0;
	$scope.calc_days=function()
	{
		$scope.GetHalfDaySettings($scope.x.month,$scope.x.year);
		
		$scope.x.cl=0;
		$scope.x.sl=0;
		$scope.x.pl=0;
		$scope.x.ml=0;
		$scope.x.lwp=0;
		$scope.check=0;
		$scope.leave_total=0;
		
		if($scope.x.month && $scope.x.year)
		{
			$http.get(rootUrl+"hr_attendance/get_half_day?emp_id="+$scope.e.emp_id+"&month="+$scope.x.month+"&year=20"+$scope.x.year+"&minTime="+$scope.halfMinTime+"&type=P"+"&wrking_hr="+$scope.work_hour).success(function(data)
			{
				$scope.x.AbsentHalfDay=0;
				$scope.x.AbsentHalfDayAmt=0;
				$scope.x.totalHalfDeduct=0;
				if(data.err=="0")
				{
					$scope.halfshow=1;
					$scope.x.HalfDay=parseFloat(data.half);
					$scope.x.AbsentHalfDay=parseFloat(data.absent);
					$scope.x.TotalHalfDay=parseFloat(data.half)+parseFloat(data.absent);
					
					$scope.get_attendance_data();
				}
				else
				{
					$scope.x.totalHalfDeduct=0;
					$scope.x.HalfDay=0;
					
					$scope.get_attendance_data();
				}
			})
		}
	}
	
	$scope.get_attendance_data=function()
	{
		$http.get(rootUrl+"hr_attendance/get_day/"+$scope.e.emp_id+"/"+$scope.x.month+"/20"+$scope.x.year+"/P").success(function(dat)
		{
			$scope.x.present=dat;
			$http.get(rootUrl+"hr_attendance/get_day/"+$scope.e.emp_id+"/"+$scope.x.month+"/20"+$scope.x.year+"/A").success(function(datas)
			{
				$scope.x.absent=parseFloat(datas);
//				$scope.x.absent+=parseFloat($scope.x.AbsentHalfDay);
				$http.get(rootUrl+"hr_payslip/get_session?month="+$scope.x.month+"&year=20"+$scope.x.year+"&emp_id="+$scope.e.emp_id).success(function(data)
				{
					$scope.check=1;
					if(data.length>0)
					{ 
						angular.forEach(data, function(val, key)
						{
							if(val.cl)
								$scope.x.cl+=parseFloat(val.cl);
							if(val.sl)
								$scope.x.sl+=parseFloat(val.sl);
							if(val.pl)
								$scope.x.pl+=parseFloat(val.pl);
							if(val.ml)
								$scope.x.ml+=parseFloat(val.ml);
							if(val.lwp)
								$scope.x.lwp+=parseFloat(val.lwp);
						});
						$scope.leave_total=$scope.x.cl+$scope.x.sl+$scope.x.pl+$scope.x.ml;
					}
					$scope.calc_total();
				})
			})
		})
	}
	
	$scope.show_value=function()
	{
		$scope.show=1;
	}
	
	$scope.get_pay_names=function()
	{
		$http.get(rootUrl+"hr_pay_setting/view?join=1&grade="+$scope.e.grade).success(function(data2)
		{
			$scope.pay_names=[];
			$scope.paysettings=data2;
			setTimeout(function()
			{
				$(data2).each(function(k,v)
				{
					var per=parseFloat(v.per);
					var val=$scope.b_sal*per/100;
					$scope.pay_names.push(v);
					if(val<v.min_amt)
					{
						$("#pay"+v.pt_id).val(v.min_amt);
					}	
					else if(val>v.max_amt)
					{
						$("#pay"+v.pt_id).val(v.max_amt);
					}
					else
					{
						$("#pay"+v.pt_id).val(val);
					}
					if(k==data2.length-1)
					{
						$scope.loading=0;
					}
				});
			}, 1000);
	    });
	}
	
	$scope.calc_total=function()
	{
		if($scope.x.value1=='') $scope.x.value1=0;
		if($scope.x.value2=='') $scope.x.value2=0;
		if($scope.x.net_deduction=='') $scope.x.net_deduction=0;
		if($scope.x.absent_deduction=='') $scope.x.absent_deduction=0;
		$scope.minustotal=0;
		$scope.plustotal=0;
		$scope.x.totalAbsentHalfDeduct=0;
		
		var perday_sal=(parseFloat($scope.b_sal)/parseFloat($scope.x.work_days)).toFixed(2);
		
		if($scope.halfAbsnt==1)
		{
			$scope.x.absent+=parseFloat($scope.x.AbsentHalfDay);
			$scope.x.AbsentHalfDayAmt=parseFloat(parseFloat($scope.x.AbsentHalfDay)*parseFloat(perday_sal)).toFixed(2);
		}
		else
		{
			$scope.x.totalAbsentHalfDeduct=parseFloat((parseFloat(perday_sal)*(parseFloat($scope.halfAmtPcnt)/100))*parseFloat($scope.x.AbsentHalfDay)).toFixed(2);
			$scope.x.AbsentHalfDayAmt=parseFloat((parseFloat(perday_sal)*(parseFloat($scope.halfAmtPcnt)/100))*parseFloat($scope.x.AbsentHalfDay)).toFixed(2);
		}
		$scope.x.totalHalfDeduct=parseFloat((parseFloat(perday_sal)*(parseFloat($scope.halfAmtPcnt)/100))*parseFloat($scope.x.HalfDay)).toFixed(2);
		
		$scope.totalAbsent=parseFloat($scope.x.absent)-parseFloat($scope.leave_total);
		
		$scope.x.absent_deduction=parseFloat((parseFloat(perday_sal)*parseFloat($scope.totalAbsent))+parseFloat($scope.x.totalAbsentHalfDeduct)).toFixed(2);

		if($scope.pay_names!='' && $scope.x.absent_deduction)
		{
			$($scope.pay_names).each(function(k,v)
			{
				if($("#pay"+v.pt_id).val()==' ') $("#pay"+v.pt_id).val(0);
				if(v.type==1) //minus
				{
					$scope.minustotal=$scope.minustotal+parseFloat($("#pay"+v.pt_id).val());
				}
				else  //plus
				{
					$scope.plustotal=$scope.plustotal+parseFloat($("#pay"+v.pt_id).val());
				}
				
				if(k==$scope.pay_names.length-1)//last row of loop
				{
					$scope.gminustotal=parseFloat(parseFloat($scope.minustotal)+parseFloat($scope.x.absent_deduction)+parseFloat($scope.x.value2)+parseFloat($scope.x.totalHalfDeduct)+parseFloat($scope.x.pf_amt)).toFixed(2);
					$scope.gplustotal=parseFloat(parseFloat($scope.plustotal)+parseFloat($scope.x.value1)).toFixed(2);
					$scope.gtotal=parseFloat(parseFloat($scope.plustotal)+parseFloat($scope.x.value1)+parseFloat($scope.b_sal)+parseFloat($scope.x.gpay)).toFixed(2);
					$scope.total=parseFloat(parseFloat($scope.gtotal)-parseFloat($scope.gminustotal)).toFixed(2);
					
					//loading checking error
					$scope.loading=0;
				}
			});
		}
		else
		{
			
			$scope.gminustotal=parseFloat(parseFloat($scope.minustotal)+parseFloat($scope.x.absent_deduction)+parseFloat($scope.x.value2)+parseFloat($scope.x.totalHalfDeduct)+parseFloat($scope.x.pf_amt)).toFixed(2);
			$scope.gplustotal=parseFloat(parseFloat($scope.plustotal)+parseFloat($scope.x.value1)).toFixed(2);
			$scope.gtotal=parseFloat(parseFloat($scope.plustotal)+parseFloat($scope.x.value1)+parseFloat($scope.b_sal)+parseFloat($scope.x.gpay)).toFixed(2);
			$scope.total=parseFloat(parseFloat($scope.gtotal)-parseFloat($scope.gminustotal)).toFixed(2);
		}
	}
	
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"/save",
			data: $("#pay_slip").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				console.log(data);
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.init();
					$scope.filter_new();
					$scope.total=0;
					$("#pay_slip_view1").trigger('click');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	$scope.PayNowSave=function()
	{
		$('#submitbtn312').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"/PayNowSave",
			data: $("#pay_slip").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				console.log(data);
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.init();
					$scope.filter_new();
					$scope.total=0;
					$("#pay_slip_view1").trigger('click');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn312').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Pay Slip Data may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"/delete?id="+id).success(function(data)
				{
					console.log(data)
					if(data=="0")
					{
						messages("danger", "Warning!","Pay Slip not Deleted", 4000);
					}
					else
					{
						messages("success", "Success!","Pay Slip Deleted Successfully", 3000);
						$scope.init();
						$scope.filter_new();
					}
				})
			}
		}
	}
	
	
	
}]);app.controller('attendance',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	module='hr_attendance';
	rootUrl=$rootScope.site_url;
	//rootUrl="http://localhost/HrMaster/index.php/";
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	$scope.x={};
	$("#DOB1").datepicker();

	function initAttendanceSelect2() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		var runInit = function () {
			$('.attendance-root select').each(function () {
				var $el = $(this);
				if (!$el.is('select')) {
					return;
				}
				if ($el.hasClass('no-select2') || $el.is('[data-no-select2]')) {
					return;
				}

				if ($el.data('select2')) {
					$el.select2('destroy');
				}

				$el.select2({
					width: '100%',
					minimumResultsForSearch: 0
				});
			});
		};

		setTimeout(runInit, 0);
		setTimeout(runInit, 180);
	}

	$scope.filter_attend=function()
	{
		$scope.x.date="";
		$scope.x.grade="";
		$scope.employees="";
		$scope.show=0;
		$scope.shw=0;
		$scope.time="";
		$scope.name="";
		initAttendanceSelect2();
	}
	
//	$scope.filter_attend();
	
	$http.get(rootUrl+"hr_grades/view?st=1").success(function(data)
	{
		$scope.grades=data;
		initAttendanceSelect2();
	})
	
	$scope.filter_data=function(g)
	{
		$scope.shw=0;
		$scope.show=0;
		$scope.time="";
		$scope.name="";
		
		if(g)
			grade="&grade="+g;
		else
			grade="";
		
		$http.get(rootUrl+"hr_staff_details/view?data=emp_id,staff_name,grade&grade="+grade+"&st=1").success(function(data)
		{
			$scope.employees=data;
			$http.get(rootUrl+module+"/get_attendance?date="+$scope.x.date+grade).success(function(data)
			{
				if(data.type==1)
				{
					messages("warning", "Warning!",data.error, 3000);
					$scope.employees="";
				}
				if(data.list!="")
				{
					$.each(data.list, function(i, val) 
					{
						if(val.status==1){
							$("#ch"+val.emp_id).prop('checked',true);
						}
						if(val.status==3){
							$("#ch"+val.emp_id).prop('disabled',true);
							$("#time"+val.emp_id).prop('disabled',true);
							$("#time_out"+val.emp_id).prop('disabled',true);
							$("#row"+val.emp_id).addClass('warning');
						}
						$scope.show=1;
						$("#time"+val.emp_id).val(val.time_in);
						$("#id"+val.emp_id).val(val.id);
						$("#comment"+val.emp_id).val(val.comment);
						$("#time_out"+val.emp_id).val(val.time_out);
						$("#duration"+val.emp_id).val(val.duration);
				    });
					$http.get(rootUrl+module+"/GetLastUpdate?date="+$scope.x.date).success(function(data)
					{
						if(data.show=='1')
						{
							$scope.shw=1;
							$scope.time=data.time;
							$scope.name=data.name;
						}
					})
				}
				
			})
		})
	}
	
	
	$scope.save_data=function()
	{
		$.ajax({
			type: "POST",
			url: rootUrl+module+"/save",
			data: $("#attendanceform1").serialize(),
			beforeSend: function()
			{
				$('#submitbtn1').attr('disabled',true);
				$('#loader1').css('display','inline');
			},
			success: function(data)
			{
				console.log(data)
				if(data=="1")
				{
					$("#clearbtn").trigger('click');
					messages("success", "Success!","Attendance Saved Successfully", 3000);
				}
				else if(data=="0")
				{
					messages("warning", "Info!","Failed to save the attendance", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader1').css('display','none');
				$('#submitbtn1').attr('disabled',false);
				$scope.filter_attend();
			}
		});
	}

	initAttendanceSelect2();
	
}]);
//blank line is required
app.controller('follow_up',['$scope','$rootScope','$http', 'sharedService',function($scope,$rootScope,$http, sharedService)
{
	module='hr_follow_up/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){window.location.assign('index.html');}});
	$scope.follow_up_modal_title = "Add Follow Up";

	function initFollowUpSelect2() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		setTimeout(function () {
			var $modal = $('#followUpModal');
			var isSelect2V4 = !!($.fn.select2 && $.fn.select2.amd);

			$('#followUpModal .follow-up-select2').each(function () {
				var $el = $(this);
				if (!$el.is('select')) {
					return;
				}

				if ($el.data('select2')) {
					$el.select2('destroy');
				}

				var options = {
					width: '100%',
					minimumResultsForSearch: 0
				};

				if (isSelect2V4) {
					options.dropdownParent = $modal;
				}

				$el.select2(options);
			});
		}, 0);
	}

	function allowSelect2TypingInsideFollowUpModal() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.modal || !$.fn.modal.Constructor) {
			return;
		}

		var ModalConstructor = $.fn.modal.Constructor;
		if (ModalConstructor.prototype._followUpSelect2FocusPatched) {
			return;
		}

		ModalConstructor.prototype.enforceFocus = function () {
			var modalThis = this;
			$(document)
				.off('focusin.bs.modal')
				.on('focusin.bs.modal', function (e) {
					var $target = $(e.target);
					var isInsideModal = modalThis.$element[0] === e.target || modalThis.$element.has(e.target).length;
					var isSelect2Input =
						$target.closest('.select2-container, .select2-dropdown, .select2-drop, .select2-search').length > 0 ||
						$target.is('.select2-input, .select2-search__field');

					if (!isInsideModal && !isSelect2Input) {
						modalThis.$element.trigger('focus');
					}
				});
		};

		ModalConstructor.prototype._followUpSelect2FocusPatched = true;

		$(document).off('select2:open.followUp select2-open.followUp');
		$(document).on('select2:open.followUp select2-open.followUp', function () {
			setTimeout(function () {
				var $search = $('.select2-container-active .select2-input, .select2-drop-active .select2-input, .select2-container--open .select2-search__field');
				if ($search.length) {
					$search.focus();
				}
			}, 0);
		});
	}

	$scope.init=function()
	{
		var data_select = encodeURIComponent("f_id,c_id,hr_follow_up.cat_id,date,title,notes,rem_date,rem_time,hr_staff_details.staff_name as staff_name,category.name as cname,hr_follow_up.timestamp");
		$http.get(rootUrl+module+"view_data?data="+data_select).success(function(data){
			$scope.datadb=data;
		})
	}
	$scope.init();
	$scope.x={};
	
	$http.get(rootUrl+"category/view_data?data=cat_id,name&status=1&follow_up=1").success(function(data)
	{
		$scope.category=data;
		initFollowUpSelect2();
	})
	
	// Listen for update event
	$scope.$on('follow_up', function () {

		var sharedData = sharedService.getData();

		if (sharedData && sharedData.c_id) {
			$scope.c_id = sharedData.c_id;
			$http.get(rootUrl + "customer/view?c_id=" + $scope.c_id + "data=c_id,name").success(function (data) {
				$scope.customers = data;
				$scope.x.c_id = data[0].c_id;
				initFollowUpSelect2();
			});
			// 🔥 Call your API here
			// $scope.loadFollowUpData($scope.c_id);
		}
	});

	$http.get(rootUrl + "customer/view?data=c_id,name").success(function (data) {
		$scope.customers = data;
		initFollowUpSelect2();
	});
	
	$scope.typehead_load=function()
	{
		$('.typeahead').typeahead('destroy');
		$http.get(rootUrl+module+"view_typehead").success(function(data)
		{
			$(".typeahead").typeahead({
			  source: data,
			  autoSelect: true
			});
		})
	}
	$scope.typehead_load();
	$scope.filter_new=function(refreshList)
	{
		$scope.x={};
		if(refreshList!==false)
			$scope.init();
		setTimeout(function(){
			if($('#date').length)
				$('#date').datepicker('setDate','now');
		},120);
	}

	$scope.update_call=function(y)
	{
		$scope.x = angular.copy(y || {});
		if($scope.x.rem_time==':')
			$scope.x.rem_time="";
	}

	$scope.open_follow_up_modal=function(mode,y)
	{
		if(mode=="edit" && y)
		{
			$scope.follow_up_modal_title = "Edit Follow Up";
			$scope.update_call(y);
		}
		else
		{
			$scope.follow_up_modal_title = "Add Follow Up";
			$scope.filter_new(false);
		}
		$('#followUpModal').modal('show');
		setTimeout(function(){ $scope.typehead_load(); },120);
		allowSelect2TypingInsideFollowUpModal();
		initFollowUpSelect2();
	}
	
	$scope.save_data=function()
	{
		if(confirm("Save the followup"))
		{
			$('#submitbtn').attr('disabled',true);
			$.ajax({
				type: "POST",
				url: rootUrl+module+"save_data",
				data: $("#folform1").serialize(),
				beforeSend: function()
				{
					$('#loader').css('display','inline');
				},
				success: function(data)
				{
					console.log(data)
					if(data=="1")
					{
						messages("success", "Success!","Saved Successfully", 3000);
						$scope.filter_new(false);
						$scope.typehead_load();
						$scope.init();
						$('#followUpModal').modal('hide');
					}
					else if(data=="0")
					{
						messages("warning", "Info!","No Data Affected", 3000);
					}
					else
					{
						messages("danger", "Warning!",data, 6000);
					}
					$('#loader').css('display','none');
					$('#submitbtn').attr('disabled',false);
				}
			});
		}
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Staff Details may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"delete_data?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Category Details Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Category Details not Deleted", 4000);
					}
					$scope.init();
				})
			}
		}
	}

	allowSelect2TypingInsideFollowUpModal();
	$(document).off('shown.bs.modal.followUpSelect2', '#followUpModal').on('shown.bs.modal.followUpSelect2', '#followUpModal', function () {
		initFollowUpSelect2();
	});
	
}]);
//blank line is required
app.controller('task_assigner',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	
	rootUrl=$rootScope.site_url;
	module="task_assigner/";
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});

	function initTaskAssignerSelect2() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		setTimeout(function () {
			var $modal = $('#taskAssignerModal');
			var isSelect2V4 = !!($.fn.select2 && $.fn.select2.amd);

			$('.task-assigner-select2').each(function () {
				var $el = $(this);
				var inModal = $el.closest('#taskAssignerModal').length > 0;

				if (!$el.is('select')) {
					return;
				}

				if ($el.data('select2')) {
					$el.select2('destroy');
				}

				var options = {
					width: '100%',
					allowClear: false,
					minimumResultsForSearch: 0
				};

				if (isSelect2V4) {
					options.dropdownParent = inModal ? $modal : $(document.body);
				}

				$el.select2(options);
			});
		}, 0);
	}

	function allowSelect2TypingInsideModal() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.modal || !$.fn.modal.Constructor) {
			return;
		}

		var ModalConstructor = $.fn.modal.Constructor;
		if (ModalConstructor.prototype._taskAssignerSelect2FocusPatched) {
			return;
		}

		ModalConstructor.prototype.enforceFocus = function () {
			var modalThis = this;
			$(document)
				.off('focusin.bs.modal')
				.on('focusin.bs.modal', function (e) {
					var $target = $(e.target);
					var isInsideModal = modalThis.$element[0] === e.target || modalThis.$element.has(e.target).length;
					var isSelect2Input =
						$target.closest('.select2-container, .select2-dropdown, .select2-drop, .select2-search').length > 0 ||
						$target.is('.select2-input, .select2-search__field');

					if (!isInsideModal && !isSelect2Input) {
						modalThis.$element.trigger('focus');
					}
				});
		};

		ModalConstructor.prototype._taskAssignerSelect2FocusPatched = true;

		$(document).off('select2:open.taskAssigner select2-open.taskAssigner');
		$(document).on('select2:open.taskAssigner select2-open.taskAssigner', function () {
			setTimeout(function () {
				var $search = $('.select2-container-active .select2-input, .select2-drop-active .select2-input, .select2-container--open .select2-search__field');
				if ($search.length) {
					$search.focus();
				}
			}, 0);
		});
	}
	
	$scope.pageno = 1;
	$scope.total_count = 0;
	$scope.itemsPerPage = '15';
	$scope.qx = {};
	$scope.x = {type:'employ'};
	$scope.datadb = [];
	$scope.task_title_filter = [];
	$scope.task_assigner_modal_title = "Add Task Assigner";

	$scope.typehead_load=function()
	{
		$('.typeahead').typeahead('destroy');
		$http.get(rootUrl+module+"/view_typehead").success(function(data)
		{
			$(".typeahead").typeahead({
			  source: data,
			  autoSelect: true
			});
		})
	}

	$scope.load_task_title_filter = function()
	{
		$http.get(rootUrl+"task_assigner/view_data?distinct=title").success(function(data)
		{
			$scope.task_title_filter = data || [];
		});
	};

	$scope.loader = function(pageno)
	{
		if(!pageno)
			pageno = 1;
		$scope.pageno = pageno;

		var params = [];

		if($scope.qx.emp_id)
			params.push("emp_id=" + encodeURIComponent($scope.qx.emp_id));
		if($scope.qx.title)
			params.push("title=" + encodeURIComponent($scope.qx.title));
		if($scope.qx.status!==undefined && $scope.qx.status!=="")
			params.push("status=" + encodeURIComponent($scope.qx.status));

		var url = rootUrl + "task_assigner/view/" + $scope.itemsPerPage + "/" + pageno;
		if(params.length)
			url += "?" + params.join("&");

		$http.get(url).success(function(response){
			if(response && response.data !== undefined)
			{
				$scope.datadb = response.data;
				$scope.total_count = response.total_count || 0;
			}
			else
			{
				$scope.datadb = response || [];
				$scope.total_count = ($scope.datadb || []).length;
			}
			initTaskAssignerSelect2();
		});
	};

	$scope.apply_filters = function()
	{
		$scope.loader(1);
	};

	$scope.clear_filters = function()
	{
		$scope.qx = {};
		$scope.itemsPerPage = '15';
		$scope.loader(1);
	};

	$scope.on_items_per_page_change = function()
	{
		$scope.loader(1);
	};
	
	$http.get(rootUrl+"hr_staff_details/view?data=emp_id,staff_name&st=1").success(function(data)
	{
		$scope.employees=data;
		initTaskAssignerSelect2();
	});

	$http.get(rootUrl+"hr_departments/view_active").success(function(data)
	{
		$scope.designations=data;
		initTaskAssignerSelect2();
	});

	$scope.update_call=function(y)
	{
		$scope.x = angular.copy(y);
		$scope.x.type = 'employ';
	}

	$scope.open_task_assigner_modal=function(mode,y)
	{
		if(mode=="edit" && y)
		{
			$scope.task_assigner_modal_title = "Edit Task Assigner";
			$scope.update_call(y);
		}
		else
		{
			$scope.task_assigner_modal_title = "Add Task Assigner";
			$scope.filter_new(false);
		}
		$('#taskAssignerModal').modal('show');
		initTaskAssignerSelect2();
		setTimeout(function(){ $scope.typehead_load(); },200);
	}
	
	$scope.filter_new=function(refreshList)
	{
		$scope.x={type:'employ'};
		$scope.typehead_load();
		initTaskAssignerSelect2();
		if(refreshList!==false)
			$scope.loader($scope.pageno || 1);
	}

	$scope.$watch('x.type', function () {
		initTaskAssignerSelect2();
	});

	$scope.save_data=function(x)
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+"task_assigner/save_data",
			data: $("#form1").serialize(),
			beforeSend: function()
			{
				$('#webprogress').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Task Assiged Successfully", 4000);
					$scope.loader($scope.pageno || 1);
					$scope.load_task_title_filter();
					$scope.filter_new(false);
					$('#taskAssignerModal').modal('hide');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 10000);
				} else if(data=="4")
				{
					messages("warning", "Info!","Employee is already assigned with this task title.", 10000);
				}
				else
				{
					messages("warning", "Warning!",data, 10000);
				}
				$('#webprogress').css('display','none');
			}
		});
		$('#submitbtn').attr('disabled',false);
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting task_assigners may hamper your data associated with it. You will loose the data related with this task_assigner."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+"task_assigner/delete_data?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Assigned task Deleted Successfully", 4000);
						$scope.loader($scope.pageno || 1);
						$scope.load_task_title_filter();
					}
					else
					{
						messages("danger", "Warning!","Assigned task not Deleted", 10000);
					}
				})
			}
		}
	}

	$scope.typehead_load();
	$scope.load_task_title_filter();
	$scope.loader(1);
	allowSelect2TypingInsideModal();

	$('#taskAssignerModal').on('shown.bs.modal', function () {
		// Select2 v3 appends search input outside modal; disable Bootstrap focus trap for this modal.
		$(document).off('focusin.bs.modal');
		initTaskAssignerSelect2();
	});
	initTaskAssignerSelect2();
	
}]);
app.controller('task', ['$scope', '$rootScope', '$http', '$timeout', '$interval', "$sce", function ($scope, $rootScope, $http, $timeout, $interval, $sce) {
	rootUrl = $rootScope.site_url;
	tmodule = "task/";
	$http.get(rootUrl + tmodule + "/index").success(function (data) { if (data == 0) { window.location.assign('login.html'); } else if (data == 2) { messages("success", "Privilege not assigned.", 1000); window.location.assign('index.html'); } });

	$scope.x = {};
	$scope.showLocationPopup = true;
	$scope.locationModal = {
		title: "Task Location",
		lat: "",
		lng: "",
		url: null
	};

	$scope.getMapUrl = function (lat, lng) {
		var url = 'https://maps.google.com/maps?q=' + lat + ',' + lng + '&z=15&output=embed';
		return $sce.trustAsResourceUrl(url);
	};

	function parseCoordinate(value) {
		var parsed = parseFloat(value);
		return isNaN(parsed) ? null : parsed;
	}

	function isValidCoordinatePair(lat, lng) {
		return lat !== null && lng !== null && lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180;
	}

	function formatFilterDate(value) {
		if (!value) return "";
		if (angular.isDate(value)) {
			var yyyy = value.getFullYear();
			var mm = ('0' + (value.getMonth() + 1)).slice(-2);
			var dd = ('0' + value.getDate()).slice(-2);
			return yyyy + '-' + mm + '-' + dd;
		}
		return value;
	}

	// function initTaskSelect2() {
	// 	if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
	// 		return;
	// 	}

	// 	$timeout(function () {
	// 		var $modal = $('#taskFormModal');
	// 		$('.task-select2').each(function () {
	// 			var $el = $(this);
	// 			var inModal = $el.closest('#taskFormModal').length > 0;

	// 			if ($el.hasClass('select2-hidden-accessible')) {
	// 				$el.select2('destroy');
	// 			}

	// 			$el.select2({
	// 				width: '100%',
	// 				dropdownParent: inModal ? $modal : $(document.body)
	// 			});
	// 		});
	// 	}, 0);
	// }
	function initTaskSelect2() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		$timeout(function () {
			var $modal = $('#taskFormModal');
			var isSelect2V4 = !!($.fn.select2 && $.fn.select2.amd);
			$('.task-select2').each(function () {
				var $el = $(this);
				var inModal = $el.closest('#taskFormModal').length > 0;

				// Guard against accidental initialization on non-select nodes (legacy Select2 v3 throws query errors).
				if (!$el.is('select')) {
					return;
				}

				// Works for both Select2 v3 and v4.
				if ($el.data('select2')) {
					$el.select2('destroy');
				}

				var options = {
					width: '100%',
					allowClear: false,
					minimumResultsForSearch: 0
				};

				// v4-only option; do not pass to v3.
				if (isSelect2V4) {
					options.dropdownParent = inModal ? $modal : $(document.body);
				}

				$el.select2(options);
			});
		}, 0);
	}

	function allowSelect2TypingInsideModal() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.modal || !$.fn.modal.Constructor) {
			return;
		}

		var ModalConstructor = $.fn.modal.Constructor;
		if (ModalConstructor.prototype._taskSelect2FocusPatched) {
			return;
		}

		ModalConstructor.prototype.enforceFocus = function () {
			var modalThis = this;
			$(document)
				.off('focusin.bs.modal')
				.on('focusin.bs.modal', function (e) {
					var $target = $(e.target);
					var isInsideModal = modalThis.$element[0] === e.target || modalThis.$element.has(e.target).length;
					var isSelect2Input =
						$target.closest('.select2-container, .select2-dropdown, .select2-drop, .select2-search').length > 0 ||
						$target.is('.select2-input, .select2-search__field');

					if (!isInsideModal && !isSelect2Input) {
						modalThis.$element.trigger('focus');
					}
				});
		};

		ModalConstructor.prototype._taskSelect2FocusPatched = true;

		$(document).off('select2:open.task select2-open.task');
		$(document).on('select2:open.task select2-open.task', function () {
			$timeout(function () {
				var $search = $('.select2-container--open .select2-search__field, .select2-drop-active .select2-input');
				if ($search.length) {
					$search.trigger('focus');
				}
			}, 0);
		});
	}

	function refreshTaskSelect2Values() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		$timeout(function () {
			// Refresh select2 values for modal form inputs
			if ($scope.x.emp_id) {
				$('select[name="emp_id"]').val($scope.x.emp_id).trigger('change');
			}
			if ($scope.x.project_id) {
				$('select[name="project_id"]').val($scope.x.project_id).trigger('change');
			}
			if ($scope.x.assign_id) {
				$('select[name="assign_id"]').val($scope.x.assign_id).trigger('change');
			}
		}, 100);
	}

	$scope.openLocationMap = function (type, row) {
		var isStart = type === 'start';
		var lat = parseCoordinate(isStart ? row.start_latitude : row.end_latitude);
		var lng = parseCoordinate(isStart ? row.start_longitude : row.end_longitude);
		var locationLabel = isStart ? "Start Location" : "End Location";

		if (!isValidCoordinatePair(lat, lng)) {
			messages("warning", "Location Missing", locationLabel + " is not available for this task.", 3000);
			return;
		}

		$scope.locationModal.title = locationLabel + (row.staff_name ? " - " + row.staff_name : "");
		$scope.locationModal.lat = lat.toFixed(6);
		$scope.locationModal.lng = lng.toFixed(6);
		$scope.locationModal.url = $scope.getMapUrl(lat, lng);
		$('#taskLocationModal').modal('show');
	};

	$scope.hasCoordinates = function (type, row) {
		if (!row) return false;
		var isStart = type === 'start';
		var lat = parseCoordinate(isStart ? row.start_latitude : row.end_latitude);
		var lng = parseCoordinate(isStart ? row.start_longitude : row.end_longitude);
		return isValidCoordinatePair(lat, lng);
	};

	$scope.compactCoordinate = function (value) {
		var parsed = parseCoordinate(value);
		if (parsed === null) return "";
		return parsed.toFixed(3) + "...";
	};
	$scope.requestLocation = function () {
		navigator.geolocation.getCurrentPosition(
			function (pos) {
				$scope.$apply(function () {
					$scope.showLocationPopup = false;
				});
			},
			function () {
				$scope.$apply(function () {
					$scope.showLocationPopup = false;
				});
			}
		);
	};
	$scope.isStartDisabled = false;

	$scope.requestLocation();
	allowSelect2TypingInsideModal();
	$('#taskFormModal').on('shown.bs.modal', function () {
		// Legacy Select2 (v3) often appends dropdown/search outside modal;
		// removing Bootstrap's focus trap here prevents blocked typing.
		$(document).off('focusin.bs.modal');
		initTaskSelect2();
	});
	// Get location automatically
	$scope.getLocation = function (time) {
		if (navigator.geolocation) {
			navigator.geolocation.getCurrentPosition(function (position) {
				$scope.$apply(function () {
					if (time === 'start') {
						$scope.x.start_latitude = position.coords.latitude;
						$scope.x.start_longitude = position.coords.longitude;
					} else if (time === 'stop') {
						$scope.x.end_latitude = position.coords.latitude;
						$scope.x.end_longitude = position.coords.longitude;
					}

				});
			}, function (error) {
				alert("Location permission denied");
			});
		} else {
			// alert("Geolocation not supported by browser");
		}
	};
	
	$scope.on_employee_change = function (emp_id){
		$http.get(rootUrl + 'project_assign/get_cust?emp_id=' + emp_id).success(function (data) {	
			$scope.project_filter_list = data || [];
			initTaskSelect2();
		});
	}

	$scope.getDurationClass = function (totalSeconds) {
		if (!totalSeconds) totalSeconds = 0;
		
		var fourHours = 4 * 3600;      // 14400 seconds
		var eightHours = 8 * 3600;     // 28800 seconds
		
		if (totalSeconds < fourHours) {
			return 'red';
		} else if (totalSeconds < eightHours) {
			return 'orange';
		} else {
			return 'green';
		}
	};

	$scope.getProgressPercentage = function (totalSeconds) {
		if (!totalSeconds) totalSeconds = 0;
		
		var eightHours = 8 * 3600;     // 28800 seconds
		var percentage = (totalSeconds / eightHours) * 100;
		
		// Cap at 100%
		return Math.min(percentage, 100);
	};


	$('#DOB1').datepicker('now');
	$('#DOB2').datepicker('now');

	$scope.local = localStorage.getItem('type');
	$scope.emp_id = localStorage.getItem('emp_id');
	$scope.grade = localStorage.getItem('grade');
	$scope.dailySummary = {
		date: "",
		can_view_all: false,
		overall_duration: "00:00:00",
		totals: [],
		self: null
	};
	$scope.lastSummaryParams = [];
	$scope.isDailySummaryRefreshing = false;

	$scope.load_daily_summary = function (filterParams) {
		var qs = [];
		if (angular.isArray(filterParams) && filterParams.length) {
			qs = filterParams.slice(0);
		}
		$scope.lastSummaryParams = qs.slice(0);
		var url = rootUrl + "task/daily_duration_summary" + (qs.length ? ("?" + qs.join("&")) : "");
		$scope.isDailySummaryRefreshing = true;
		$http.get(url).success(function (data) {
			data = data || {};
			$scope.dailySummary.date = data.date || "";
			$scope.dailySummary.can_view_all = String(data.can_view_all) === '1' || data.can_view_all === 1 || data.can_view_all === true;
			$scope.dailySummary.overall_duration = data.overall_duration || "00:00:00";
			$scope.dailySummary.totals = angular.isArray(data.totals) ? data.totals : [];
			$scope.dailySummary.self = (!$scope.dailySummary.can_view_all && $scope.dailySummary.totals.length) ? $scope.dailySummary.totals[0] : null;
		}).finally(function () {
			$scope.isDailySummaryRefreshing = false;
		});
	};

	$scope.refresh_daily_summary = function () {
		$scope.load_daily_summary($scope.lastSummaryParams || []);
	};

	$http.get(rootUrl + "hr_staff_details/view?data=emp_id,staff_name&st=1").success(function (data) {
		$scope.employees = data;
		initTaskSelect2();
	});
	$http.get(rootUrl + "task_assigner/view_data?emp_id=" + $scope.emp_id).success(function (data) {
		$scope.tasks = data;
		initTaskSelect2();
	});
	$http.get(rootUrl + "task_assigner/view_data?data=assign_id,title&distinct=assign_id,title").success(function (data) {
		$scope.task_filter_list = data || [];
		initTaskSelect2();
	});
	$http.get(rootUrl + "customer/view?data=c_id,company_name&status=1").success(function (data) {
		$scope.project_filter_list = data || [];
		initTaskSelect2();
	});
	//	$http.get(rootUrl + "projects_assign/view_data").success(function (data) {
	//		$scope.projects = data;
	//	});

	$scope.pageno = 1; // initialize page no to 1
	$scope.total_count = 0;
	$scope.itemsPerPage = '15';
	$scope.qx = {};
	$scope.task_filter_list = [];
	$scope.project_filter_list = [];
	$scope.x = {};
	$scope.isLoading = false;
	$scope.loader = function (pageno = 1) {
		if (!pageno)
			pageno = 1;
		$scope.pageno = pageno;
		$scope.isLoading = true;
		var params = ['join=1'];
		var summaryParams = [];
		if ($scope.qx.emp_id) {
			var empParam = "emp_id=" + encodeURIComponent($scope.qx.emp_id);
			params.push(empParam);
			summaryParams.push(empParam);
		}
		if ($scope.qx.project_id) {
			var projectParam = "project_id=" + encodeURIComponent($scope.qx.project_id);
			params.push(projectParam);
			summaryParams.push(projectParam);
		}
		if ($scope.qx.status !== undefined && $scope.qx.status !== "") {
			var statusParam = "status=" + encodeURIComponent($scope.qx.status);
			params.push(statusParam);
			summaryParams.push(statusParam);
		}
		if ($scope.qx.date_type) {
			var dateTypeParam = "date_type=" + encodeURIComponent($scope.qx.date_type);
			params.push(dateTypeParam);
			summaryParams.push(dateTypeParam);
		}
		if ($scope.qx.date_type === 'range') {
			var fromDate = formatFilterDate($scope.qx.date_from);
			var toDate = formatFilterDate($scope.qx.date_to);
			if (fromDate) {
				var dateFromParam = "date_from=" + encodeURIComponent(fromDate);
				params.push(dateFromParam);
				summaryParams.push(dateFromParam);
			}
			if (toDate) {
				var dateToParam = "date_to=" + encodeURIComponent(toDate);
				params.push(dateToParam);
				summaryParams.push(dateToParam);
			}
		}

		var url = rootUrl + "task/view/" + $scope.itemsPerPage + "/" + pageno + "?" + params.join("&");
		$http.get(url).success(function (response) {
			$scope.datadb = (response && response.data) ? response.data : [];  // data to be displayed on current page.
			$scope.total_count = (response && response.total_count) ? response.total_count : 0; // total data count.
			$scope.load_daily_summary(summaryParams);
			//        	console.log(data);
			$scope.isLoading = false;
			$scope.datadb.forEach(function (item) {
				if (!item.end_time) {
					// convert start date+time to timestamp
					var parts = item.start_date.split('/');
					var t = item.start_time.split(':');

					// d/m/Y H:i:s → JS Date
					var start = new Date(
						parts[2],               // year
						parts[1] - 1,           // month
						parts[0],               // day
						t[0], t[1], t[2] || 0
					);

					item.startTimestamp = start.getTime();
					item.duration = '00:00:00';
				}
			});
			startGlobalTimer();
			if ($scope.employees.length == "1") {
				$scope.x.emp_id = $scope.employees[0]['emp_id'];
			}
			initTaskSelect2();
		});
		/*
		$http.get(rootUrl + "task/view_data").success(function (data) {
			$scope.datadb = data;
			$scope.datadb.forEach(function (item) {
				if (!item.end_time) {
					// convert start date+time to timestamp
					var parts = item.start_date.split('/');
					var t = item.start_time.split(':');

					// d/m/Y H:i:s → JS Date
					var start = new Date(
						parts[2],               // year
						parts[1] - 1,           // month
						parts[0],               // day
						t[0], t[1], t[2] || 0
					);

					item.startTimestamp = start.getTime();
					item.duration = '00:00:00';
				}
			});
			startGlobalTimer();
		});
		*/
		$http.get(rootUrl + "project_assign/get_cust").success(function (data) {
			$scope.companies = data;
			if (data.length == 1) {
				$scope.x.project_id = data[0].c_id;
			}
			initTaskSelect2();
		});

		$http.get(rootUrl + tmodule + 'get_sess').success(function (data) {
			$scope.sess = data['type'];
			// console.log('sess:',$scope.sess);
		});
	}

	$scope.apply_filters = function () {
		if ($scope.qx.date_type === 'range') {
			var fromDate = formatFilterDate($scope.qx.date_from);
			var toDate = formatFilterDate($scope.qx.date_to);
			if (!fromDate || !toDate) {
				messages("warning", "Info!", "Please select both From Date and To Date for Date Range.", 3500);
				return;
			}
			if (fromDate > toDate) {
				messages("warning", "Info!", "From Date should be less than or equal to To Date.", 3500);
				return;
			}
		}
		$scope.loader(1);
	};

	$scope.clear_filters = function () {
		$scope.qx = {};
		$scope.itemsPerPage = '15';
		$scope.loader(1);
	};

	$scope.on_date_type_change = function () {
		if ($scope.qx.date_type !== 'range') {
			$scope.qx.date_from = "";
			$scope.qx.date_to = "";
		}
	};

	$scope.on_items_per_page_change = function () {
		$scope.loader(1);
	};
	$scope.loader();

	// $scope.page_refresh = function ()//to get value after page refresshing the stop watch
	// {
	// 	$http.get(rootUrl + "task/view_data?status=0").success(function (data) {
	// 		if (data.length > 0) {
	// 			if (data[0].status == '0') {
	// 				$scope.x.tstatus = data[0].status;
	// 				$scope.x.task_id = data[0].task_id;
	// 				$scope.x.start_date = data[0].start_date;
	// 				$scope.x.start_time = data[0].start_time;
	// 				$scope.x.emp_id = data[0].emp_id;
	// 				$scope.x.assign_id = data[0].assign_id;
	// 				$scope.x.comment = data[0].comment;
	// 				$scope.timer(data[0].start_date, data[0].start_time, "0");
	// 			}
	// 		}
	// 	})
	// }
	// if ($scope.local != "Administrator")
	// 	$scope.page_refresh();

	$scope.fetch_task = function (emp_id) {
		$http.get(rootUrl + "task_assigner/view_data?emp_id=" + emp_id).success(function (data) {
			$scope.tasks = data;
			initTaskSelect2();
		});
		$http.get(rootUrl + 'project_assign/get_cust?emp_id=' + emp_id).success(function (data) {
			$scope.companies = data;
			initTaskSelect2();
		});
	}
	$http.get(rootUrl + "task/check_timer_on").success(function (data) {
		//		console.log(data);
		if (data != '0') {
			$scope.x = data[0];
			$scope.timer(data[0].start_date, data[0].start_time, 0);
		}
	})

	$scope.timer = function (sdate, stime, b) {
		$scope.mytimer = setInterval(function () { doCountDown() }, 1000);
		function doCountDown() {
			$http.get(rootUrl + "task/timer?sdate=" + sdate + "&stime=" + stime).success(function (data) {
				$("#txt").html(data);
			})
		}
	}

	$scope.update_call = function (y) {
		clearInterval($scope.mytimer);
		$http.get(rootUrl + "task_assigner/view_data?emp_id=" + y.emp_id).success(function (data) {
			$scope.tasks = data;//to fill empdata in select box
			// Find the task in datadb by task_id to ensure we have the live reference
			var liveTask = $scope.datadb.find(function (item) {
				return item.task_id === y.task_id;
			});
			// Use the live reference if found, otherwise use the passed task
			$scope.x = liveTask || y;
			//			console.log($scope.x);
			$scope.value = "on";
			// The global timer is already updating x.duration via ng-bind
			// No need to call $scope.timer() which conflicts with ng-bind
			$timeout(function () {
				$('#taskFormModal').modal('show');
				initTaskSelect2();
				refreshTaskSelect2Values();
			}, 80);
		});
		$timeout(function () {
			$scope.getLocation('stop');
		}, 500);
		//		$timeout(function () {
		//			$('#addform').tab('show');
		//		}, 1000);
	}

	$scope.filter_new = function () {
		$scope.x = {};
		$scope.value = "";
		// clearInterval($scope.mytimer);
		$("#txt").html("");
	}

	$scope.openTaskModal = function (mode, row) {
		if (mode === 'edit' && row) {
			$scope.update_call(row);
			return;
		}

		$scope.filter_new();

		if ($scope.local != "Administrator" && $scope.emp_id) {
			$scope.x.emp_id = $scope.emp_id;
			$scope.fetch_task($scope.emp_id);
		}

		if ($scope.employees && $scope.employees.length == 1) {
			$scope.x.emp_id = $scope.employees[0]['emp_id'];
			$scope.fetch_task($scope.x.emp_id);
		}

		$timeout(function () {
			$('#taskFormModal').modal('show');
			initTaskSelect2();
		}, 80);
	}

	$scope.save_data = function (y, time) {
		$('#submitbtn').attr('disabled', true);
		if (time === 'start') {
			$scope.getLocation('start');
		}
		//		$timeout(function () {
		$.ajax({
			type: "POST",
			url: rootUrl + "task/save_data",
			data: $("#form1").serialize(),
			beforeSend: function () {
				$('#loader').css('display', 'inline');
			},
			success: function (data1) {
				$('#loader').css('display', 'none');
				$('#submitbtn').attr('disabled', false);
				if (data1.error == "0") {
					if (data1.task_id) {
						messages("success", "Success!", "Task Saved Successfully", 3000);
						$('#taskFormModal').modal('hide');
						/*
						$http.get(rootUrl + "task/view_data").success(function (data) {
							$scope.datadb = data;
							$scope.datadb.forEach(function (item) {
								if (!item.end_time) {
									// convert start date+time to timestamp
									var parts = item.start_date.split('/');
									var t = item.start_time.split(':');

									// d/m/Y H:i:s → JS Date
									var start = new Date(
										parts[2],               // year
										parts[1] - 1,           // month
										parts[0],               // day
										t[0], t[1], t[2] || 0
									);

									item.startTimestamp = start.getTime();
									item.duration = '00:00:00';
								}
							});

							startGlobalTimer();

						});
						if (data1.multiple != 'true') {
							// disable button
							$scope.isStartDisabled = true;
						}
						$scope.x = {}; */

					}
					else {
						messages("success", "Success!", "Task Updated Successfully", 3000);
						$('#taskFormModal').modal('hide');
					}

					$scope.$applyAsync(function () {
						$scope.filter_new();
						$scope.loader($scope.pageno || 1);
						checkStartButton();
					});
				}
				else {
					messages("danger", "Warning!", data1.msg, 6000);
					$('#submitbtn').attr('disabled', false);
				}

			}
		});
		//		}, 4000);
	}

	$scope.stop_data = function (y, time) {
		$('#stopbtn').attr('disabled', true);
		if (time === 'stop') {
			$scope.fetch_task(y.emp_id);
			$scope.x = y;
			$timeout(function () {
				$scope.getLocation('stop');
			}, 500);
			console.log($scope.x);
		}
	}

	// $scope.save_stop_data = function () {
	// 	$timeout(function () {
	// 		$http.post(rootUrl + tmodule + 'stop_data?task_id=' + y.task_id + '&duration=' + y.duration + '&end_longitude=' + $scope.end_longitude + '&end_latitude=' + $scope.end_latitude).success(function (data) {
	// 			console.log(data);
	// 			if (data.status === 'success') {
	// 				messages('success', 'Success!', data.msg, 3000);
	// 				$http.get(rootUrl + "hr_staff_details/view?data=emp_id,staff_name&st=1").success(function (data) {
	// 					if (data.length === 1) {
	// 						$scope.x.emp_id = data[0]['emp_id'];
	// 					}
	// 					$scope.employees = data;

	// 				});
	// 				$scope.isStartDisabled = false;
	// 				$http.get(rootUrl + "task/view_data").success(function (data) {
	// 					$scope.datadb = data;
	// 					$scope.datadb.forEach(function (item) {
	// 						if (!item.end_time) {
	// 							// convert start date+time to timestamp
	// 							var parts = item.start_date.split('/');
	// 							var t = item.start_time.split(':');

	// 							// d/m/Y H:i:s → JS Date
	// 							var start = new Date(
	// 								parts[2],               // year
	// 								parts[1] - 1,           // month
	// 								parts[0],               // day
	// 								t[0], t[1], t[2] || 0
	// 							);

	// 							item.startTimestamp = start.getTime();
	// 							item.duration = '00:00:00';
	// 						}
	// 					});

	// 					startGlobalTimer();

	// 				});
	// 			} else {
	// 				messages('danger', 'Warning!', data.msg, 3000);
	// 			}
	// 		});
	// 	}, 5000);
	// }

	$scope.delete_data = function (id) {
		if (confirm("Deleting Task may hamper your data associated with it.")) {
			if (confirm("Are you Sure to DELETE ??")) {
				$http.get(rootUrl + "task/delete_data?id=" + id).success(function (data) {
					if (data == "1") {
						messages("success", "Success!", "Task Deleted Successfully", 3000);
					}
					else {
						messages("danger", "Warning!", "Task not Deleted You cannot delete the task. Please contact admin", 4000);
					}
					$scope.loader();
					initTaskSelect2();
				})
			}
		}
	}

	$scope.checkDuration = function (duration) {
		if (!duration) return false;

		var parts = duration.split(':');   // ["26", "2", "11"]

		var totalSeconds = (+parts[0]) * 3600 + (+parts[1]) * 60 + (+parts[2]);

		var eightHours = 8 * 3600;  // 8 hours in seconds

		return totalSeconds < eightHours;
	};

	app.directive('bsTooltip', function () {
		return {
			restrict: 'A',
			link: function (scope, element, attrs) {
				$(element).tooltip();
			}
		};
	});

	$timeout(function () {
		$('[data-toggle="tooltip"]').tooltip();
	}, 100);


	var timerPromise;
	var dailySummaryTimer = $interval(function () {
		$scope.load_daily_summary($scope.lastSummaryParams || []);
	}, 60000);

	function startGlobalTimer() {
		if (timerPromise) return;

		timerPromise = $interval(function () {
			var now = Date.now();

			$scope.datadb.forEach(function (item) {

				// only for running tasks
				if (!item.end_time && item.startTimestamp) {

					var diff = now - item.startTimestamp;

					var h = Math.floor(diff / 3600000);
					var m = Math.floor((diff % 3600000) / 60000);
					var s = Math.floor((diff % 60000) / 1000);

					item.duration =
						(h < 10 ? '0' : '') + h + ':' +
						(m < 10 ? '0' : '') + m + ':' +
						(s < 10 ? '0' : '') + s;
				}
			});

		}, 1000);
	}


	function checkStartButton() {

		$http.get(rootUrl + tmodule + 'get_ongoing').success(function (data) {
			if (data.length > 0 && data[0]['end_time'] == null) {
				$timeout(function () {
					$scope.getLocation('stop');
				}, 500);
				//				if (data.grade != 'A') {
				$scope.isStartDisabled = true;
				$scope.x = data[0];

				timerPromise = $interval(function () {
					var now = Date.now();
					if (!data[0].end_time) {
						// convert start date+time to timestamp
						var parts = data[0].start_date.split('/');
						var t = data[0].start_time.split(':');

						// d/m/Y H:i:s → JS Date
						var start = new Date(
							parts[2],               // year
							parts[1] - 1,           // month
							parts[0],               // day
							t[0], t[1], t[2] || 0
						);

						data[0].startTimestamp = start.getTime();
						data[0].duration = '00:00:00';
					}
					if (!data[0].end_time && data[0].startTimestamp) {
						var diff = now - data[0].startTimestamp;
						var h = Math.floor(diff / 3600000);
						var m = Math.floor((diff % 3600000) / 60000);
						var s = Math.floor((diff % 60000) / 1000);
						$scope.x.duration =
							(h < 10 ? '0' : '') + h + ':' +
							(m < 10 ? '0' : '') + m + ':' +
							(s < 10 ? '0' : '') + s;
					}
				}, 1000);
				//				}
			} else {
				$timeout(function () {
					$scope.getLocation('start');
				}, 500);
			}
		});
	}

	checkStartButton();

}]);




//blank line is required
app.controller('task_details',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	
	rootUrl=$rootScope.site_url;
	module="task_details/";
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$scope.pageno = 1;
	$scope.total_count = 0;
	$scope.itemsPerPage = '15';
	$scope.qx = {};
	$scope.x = {};
	$scope.tasks = [];
	$scope.task_filter_list = [];
	$scope.task_details_modal_title="Add Task Details";

	$http.get(rootUrl+"hr_staff_details/view?data=emp_id as eid,staff_name as snam&st=1").success(function(data)
	{
		$scope.employees=data;
	});

	$http.get(rootUrl+"task_assigner/view_data?data=assign_id,title").success(function(data)
	{
		$scope.task_filter_list = data;
	});

	$scope.loader = function(pageno)
	{
		if(!pageno)
			pageno = 1;
		$scope.pageno = pageno;

		var url = "task_details/view/" + $scope.itemsPerPage + "/" + pageno + "?join=1";
		var params = "";

		if($scope.qx.emp_id)
			params += "&emp_id=" + encodeURIComponent($scope.qx.emp_id);
		if($scope.qx.assign_id)
			params += "&assign_id=" + encodeURIComponent($scope.qx.assign_id);
		if($scope.qx.status!==undefined && $scope.qx.status!=="")
			params += "&status=" + encodeURIComponent($scope.qx.status);
		if($scope.qx.edit!==undefined && $scope.qx.edit!=="")
			params += "&edit=" + encodeURIComponent($scope.qx.edit);

		$http.get(rootUrl + url + params).success(function(response){
			if(response && response.data !== undefined)
			{
				$scope.datadb = response.data;
				$scope.total_count = response.total_count || 0;
			}
			else
			{
				$scope.datadb = response || [];
				$scope.total_count = ($scope.datadb || []).length;
			}
		});
	};

	$scope.apply_filters = function()
	{
		$scope.loader(1);
	};

	$scope.clear_filters = function()
	{
		$scope.qx = {};
		$scope.itemsPerPage = '15';
		$scope.loader(1);
	};

	$scope.on_items_per_page_change = function()
	{
		$scope.loader(1);
	};

	$scope.filter_new=function(refreshList)
	{
		$scope.x={};
		if(refreshList!==false)
			$scope.loader($scope.pageno || 1);
	};

	$scope.loader(1);

	$scope.filter_employee=function(eid)
	{
		$http.get(rootUrl+"task_assigner/view_data?emp_id="+eid).success(function(data)
		{
			$scope.tasks=data;
		})
	}
	$scope.update_call=function(y)
	{
		$scope.x=y;
		$scope.filter_employee(y.emp_id);
	}
	$scope.open_task_details_modal=function(mode,y)
	{
		if(mode=="edit" && y)
		{
			$scope.task_details_modal_title="Edit Task Details";
			$scope.update_call(y);
		}
		else
		{
			$scope.task_details_modal_title="Add Task Details";
			$scope.x={};
			$scope.tasks=[];
		}
		$('#taskDetailsModal').modal('show');
	}
	
	$scope.options = { height: 150 };
	$scope.save_data=function(x)
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+"task_details/save_data",
			data: $("#form1").serialize(),
			beforeSend: function()
			{
				$('#webprogress').css('display','inline');
			},
			success: function(data)
			{
//				console.log(data);
				if(data=="1")
				{
					messages("success", "Success!","Task Assiged Successfully", 4000);
					$scope.filter_new();
					$('#taskDetailsModal').modal('hide');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 10000);
				}
				else
				{
					messages("warning", "Warning!",data, 10000);
				}
				$('#webprogress').css('display','none');
			}
		});
		$('#submitbtn').attr('disabled',false);
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting task_assigners may hamper your data associated with it. You will loose the data related with this task_assigner."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+"task_details/delete_data?id="+id).success(function(data){
//					console.log(data);
					if(data=="1")
					{
						messages("success", "Success!","Assigned task Deleted Successfully", 4000);
						$scope.filter_new(true);
					}
					else
					{
						messages("danger", "Warning!","Assigned task not Deleted", 10000);
					}
//					$http.get("task_assigner/view_data").success(function(data){
//						$scope.datadb=data;
//					})
				})
			}
		}
	}
	
}]);
app.controller('email_admin',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	module='email_admin/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$scope.init=function()
	{
		$http.get(rootUrl+"email_admin/view").success(function(data)
		{
			$scope.datadb=data;
		});
	}
	$scope.init();
	
	$http.get(rootUrl+"category/view_data").success(function(data)
	{
		$scope.categories=data;
	});
	
	$scope.update_call=function(y)
	{
		$scope.x=y;
	}
	$scope.filter_new=function()
	{
		$scope.x={};
	}
	
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"save",
			data: $("#admin_email_form").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.filter_new();
					$scope.init();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Data may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"delete?id="+id).success(function(data)
				{
					if(data=="1")
					{
						messages("success", "Success!","Details Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Details not Deleted", 4000);
					}
				})
				$scope.init();
			}
		}
	}
	
}]);app.controller('email_contact',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	module='email_contact/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$scope.init=function()
	{
		$http.get(rootUrl+"email_contact/view").success(function(data)
		{
			$scope.datadb=data;
		});
	}
	$scope.init();
	
	$http.get(rootUrl+"category/view_data").success(function(data)
	{
		$scope.categories=data;
	});
	
	$scope.update_call=function(y)
	{
		$scope.x=y;
	}
	$scope.filter_new=function()
	{
		$scope.x={};
	}
	
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"save",
			data: $("#mailform").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.filter_new();
					$scope.init();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Staff Details may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"delete?id="+id).success(function(data)
				{
					if(data=="1")
					{
						messages("success", "Success!","Details Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Details not Deleted", 4000);
					}
				})
				$scope.init();
			}
		}
	}
	
}]);app.controller('email_headerFooter',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	module='email_headerFooter/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$scope.init=function()
	{
		$http.get(rootUrl+"email_headerFooter/view").success(function(data)
		{
			$scope.datadb=data;
		});
	}
	$scope.init();
	$scope.x={};
	
	$scope.update_call=function(y)
	{
		$("#addform").trigger('click');
		$scope.x=y;
	}
	
	$scope.options = {
		    height: 150,
		    toolbar: [
		               ['style', ["undo","redo",'style','bold', 'italic', 'underline']],
      		           ['fontname', ['fontname']],
      		           ['fontsize', ['fontsize']],
      		           ['color', ['color']],
      		           [ 'para', [ 'ol', 'ul', 'paragraph', 'height' ] ],
      		           ['font', ['strikethrough', 'superscript', 'subscript']],
      		           ['table',['table']],
      		           [ 'insert', [ 'link','video','hr','picture'] ],
      	               ["view", ["fullscreen", "codeview", "help",]]
		        ]
		  };
	
	$scope.filter_new=function()
	{
		$scope.x={};
	}
	
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"save",
			data: $("#head_foot_form").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$("#viewform").trigger('click');
					$scope.filter_new();
					$scope.init();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Data may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"delete?id="+id).success(function(data)
				{
					if(data=="1")
					{
						messages("success", "Success!","Details Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Details not Deleted", 4000);
					}
				})
				$scope.init();
			}
		}
	}
	
}]);app.controller('email_main',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	module='email_main/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$scope.init=function()
	{
		$http.get(rootUrl+"email_main/view").success(function(data)
		{
			$scope.datadb=data;
		});
	}
	$scope.init();
	$scope.x={};
	
	$http.get(rootUrl+"email_contact/view").success(function(data)
	{
		$scope.contacts=data;
	});
	$http.get(rootUrl+"email_template/view?data=et_id,name").success(function(data)
	{
		$scope.templates=data;
	});
	
	$("#checkedAll").change(function() 
	{
        if (this.checked) {
            $(".checkSingle").each(function() {
                this.checked=true;
            });
        } else {
            $(".checkSingle").each(function() {
                this.checked=false;
            });
        }
    });
	
	$scope.update_call=function(y)
	{
		$("#addform").trigger('click');
		$scope.x=y;
	}
	
	$scope.options = 
	{
	    height: 150,
	    toolbar: [
	               ['style', ["undo","redo",'style','bold', 'italic', 'underline']],
  		           ['fontname', ['fontname']],
  		           ['fontsize', ['fontsize']],
  		           ['color', ['color']],
  		           [ 'para', [ 'ol', 'ul', 'paragraph', 'height' ] ],
  		           ['font', ['strikethrough', 'superscript', 'subscript']],
  		           ['table',['table']],
  		           [ 'insert', [ 'link','video','hr','picture'] ],
  	               ["view", ["fullscreen", "codeview", "help",]]
	        ]
	  };
	
	$scope.filter_new=function()
	{
		$scope.x={};
	}
	
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"save",
			data: $("#head_foot_form").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$("#viewform").trigger('click');
					$scope.filter_new();
					$scope.init();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Data may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"delete?id="+id).success(function(data)
				{
					if(data=="1")
					{
						messages("success", "Success!","Email Details Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Email Details not Deleted", 4000);
					}
				})
				$scope.init();
			}
		}
	}
	
}]);app.controller('email_template',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	module='email_template/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$scope.init=function()
	{
		$http.get(rootUrl+"email_template/view").success(function(data)
		{
			$scope.datadb=data;
		});
	}
	$scope.init();
	$scope.x={};
	
	$http.get(rootUrl+"category/view_data").success(function(data)
	{
		$scope.categories=data;
	});
	
	$http.get(rootUrl+"email_headerFooter/view?type=H").success(function(data)
	{
		$scope.headers=data;
	});
		
	$http.get(rootUrl+"email_headerFooter/view?type=F").success(function(data)
	{
		$scope.footers=data;
	});
	
	$scope.update_call=function(y)
	{
		$("#addform").trigger("click");
		$scope.x=y;
	}
	$scope.filter_new=function()
	{
		$scope.x={};
	}
	
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"save",
			data: $("#et_form").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.filter_new();
					$scope.init();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Data may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"delete?id="+id).success(function(data)
				{
					if(data=="1")
					{
						messages("success", "Success!","Details Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Details not Deleted", 4000);
					}
				})
				$scope.init();
			}
		}
	}
	
}]);//blank line is required
app.controller('journals',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	jmodule='hr_journals/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+jmodule+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	$scope.d={};
	$scope.init=function()
	{
		$http.get(rootUrl+jmodule+"view_data").success(function(data)
		{
			$scope.datadb=data;
		})
	}
	$scope.init();
	$http.get(rootUrl+"category/view_data?data=cat_id,name&status=1&journal=1").success(function(data)
	{
		$scope.category=data;
	})
	
	$scope.filter_new_jour=function()
	{
		$scope.d={};
	}
	
	$scope.update_call=function(y)
	{
		$scope.d=y;
		if($scope.d.debit==0)
			$scope.d.debit="";
		if($scope.d.credit==0)
			$scope.d.credit="";
		$("#addform").trigger('click');
	}
	
	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+jmodule+"save",
			data: $("#form1").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.init();
					$scope.filter_new_jour();
					$("#viewform").trigger('click');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Journals Records may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+jmodule+"delete_data?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Journals Records Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Journals Records not Deleted", 4000);
					}
					$scope.init();
				})
			}
		}
	}
	
}]);//blank line is required
app.controller('company_master', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) {
	com_module = 'company_master/';
	rootUrl = $rootScope.site_url;
	$http.get(rootUrl + com_module + "/index").success(function (data) { if (data == 0) { window.location.assign('login.html'); } else if (data == 2) { messages("success", "Privilege not assigned.", 1000); window.location.assign('index.html'); } });
	$scope.y = {};

	$scope.init_com = function () {
		$http.get(rootUrl + com_module + "view").success(function (data) {
			$scope.datadb = data;
		});
		$http.get(rootUrl + com_module + "view?data=com_name,com_id").success(function (data) {
			$scope.parent = data;
		});
		$http.get(rootUrl + com_module + "view_state?data=iso2,name").success(function (data) {
			$scope.state_list = data;
		});
	}
	$scope.init_com();

	$scope.filter_new_com = function () {
		$scope.y = {};
	}

	$scope.update_call = function (y) {
		$scope.y = y;
		$("#addform").trigger('click');
	}

	$scope.save_data_com = function () {
		$('#comform1').ajaxForm({
			type: "POST",
			url: rootUrl + com_module + "/save",
			beforeSend: function () {
				$('#submitbtn1com').attr('disabled', true);
				$('#loader1com').css('display', 'inline');
			},
			success: function (data) {
				if (data.error == "0") {
					messages("success", "Success!", data.msg, 3000);
					$scope.filter_new_com();
					$scope.init_com();
				}
				else {
					messages("danger", "Warning!", data.msg, 6000);
				}
				$('#loader1com').css('display', 'none');
				$('#submitbtn1com').attr('disabled', false);
			}
		});
	}

	$scope.delete_data = function (id) {
		if (confirm("Deleting Company Details may hamper your data associated with it.")) {
			if (confirm("Are you Sure to DELETE ??")) {
				$http.get(rootUrl + com_module + "delete?id=" + id).success(function (data) {
					if (data == "1") {
						messages("success", "Success!", "Company Details Deleted Successfully", 3000);
					}
					else {
						messages("danger", "Warning!", "Company Details not Deleted", 4000);
					}
					$scope.init_com();
				})
			}
		}
	}

	$scope.add_company_serials = function (y) {
		$scope.company = y;
		console.log($scope.company);
		$('#addModal').modal('show');
	};

	$scope.save_serials = function(company, $event) {
		if ($event) $event.preventDefault(); // stop reload
	  
		console.log('test: ', company)
		$('#serialForm').ajaxForm({
		  type: "POST",
		  url: rootUrl + com_module + "/save_serial",
		  beforeSend: function() {
			$('#serialbtn').attr('disabled', true);
		  },
		  success: function(data) {
			console.log(data);
			if(data.status == 'success'){
				messages("success", "Success!", 'Data Updated Successfully.', 3000);
				$('#serialbtn').attr('disabled', false);
				$('#addModal').modal('hide');
			} else if (data.status == 'error'){
				messages("danger", "Warning!", 'Error in updating data.', 3000);
			}
			
		  },
		  error: function() {
			$('#serialbtn').attr('disabled', false);
		  }
		}).submit();
	  };
	  


}]);//blank line is required
app.controller('hr_session',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	rootUrl=$rootScope.site_url;
	sess_module="hr_session/";
	$http.get(rootUrl+sess_module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$scope.s={};
	$scope.com_id=[];
	$scope.branch_id=[];
	
	$("#DOB12").datepicker();
	$("#DOB13").datepicker();
	
	$scope.init_sess=function()
	{
		$http.get(rootUrl+sess_module+"view").success(function(data)
		{
			$scope.datadb=data;
		})
	}
	$scope.init_sess();
	
	$http.get(rootUrl+"company_master/view?data=com_id,com_name,branch_id").success(function(data)
	{
		$scope.company=data;
	})
	
	$scope.filter_new_sess=function()
	{
		$scope.s={};
	}
	$scope.update_call_sess=function(y)
	{
		$scope.s=y;
		$('#addformsess').trigger('click');
	}
	$scope.save_data_sess=function(x)
	{
		$.ajax({
			type: "POST",
			url: rootUrl+sess_module+"save",
			data: $("#sessionform").serialize(),
			beforeSend: function()
			{
				$('#loader1ses').css('display','inline');
				$('#submitbtn1ses').attr('disabled',true);
			},
			success: function(data)
			{
				console.log(data);
				if(data=="1")
				{
					messages("success", "Success!","Session Set Successfully", 3000);
					$scope.filter_new_sess();
					$scope.init_sess();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
					$scope.filter_new_sess();
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader1ses').css('display','none');
				$('#submitbtn1ses').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data_sess=function(id)
	{
		if(confirm("Deleting Session Details may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+sess_module+"delete?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Sesssion Details Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Session Details not Deleted", 4000);
					}
					$scope.init_sess();
				})
			}
		}
	}
	
	
	
}]);//blank line is required
app.controller('help',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	module='help/';
	rootUrl=$rootScope.site_url;
	//$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	
}]);app.controller('logs',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+'login/auth').success (function(data) 
	{
		if(data!=1){window.location.assign('login.html');}
	});
	
	$http.get(rootUrl+"logs/view_data").success(function(data)
	{
//		console.log(data);
		$scope.datadb=data;
	})
	$scope.fetch_log=function(id)
	{
	 	$(".modal-body").html('');
	 	$("#modalbtn").trigger('click');
	 	$("#myModalLabel").html("Log Details");
	 	$.get(rootUrl+"logs/get_object?id="+id, function(data, status)
	 	{
	 		$(".modal-body").html(data);
	     });
	 }
}]);//blank line is required
app.controller('marketing_management',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	marketing='marketing_management/';
	rootUrl=$rootScope.site_url;
	$scope.x={};
	$scope.y={};
	
	$http.get(rootUrl+"hr_staff_details/view?data=emp_id,staff_name&st=1").success(function(data)
	{
		$scope.employees=data;
	})
	$http.get(rootUrl+"category/view_data?data=name,cat_id&marketing=1&status=1").success(function(data)
	{
		$scope.activities=data;
	})
	
	$scope.x.arv_cst=0;
	$scope.x.dept_cst=0;
	$scope.x.other_cst=0;
	$scope.x.total_exp=0;
	$scope.x.food=0;
	$scope.x.lodging=0;
	$scope.get_followUp=function()
	{
		$http.get(rootUrl+marketing+"follow_temp_view").success(function(data)
		{
			$scope.mar_follows=data;
		})
	}
	$scope.get_followUp();
	
	$scope.get_marketingfollowUp=function()
	{
		$http.get(rootUrl+marketing+"view_data").success(function(data)
		{
			$scope.datadb=data;
		})
	}
	$scope.get_marketingfollowUp();
	
	$scope.total_km=function()
	{
		$scope.x.tot_km=parseFloat($scope.x.km_strt)+parseFloat($scope.x.km_end);
	}
	$scope.total_arr_dep=function()
	{
		$scope.x.total_exp=parseFloat($scope.x.arv_cst)+parseFloat($scope.x.dept_cst)+parseFloat($scope.x.other_cst);
	}
	
	$scope.main_clear=function()
	{
		$http.get(rootUrl+marketing+"ClearPreviousMarketingTemp").success(function(data)
		{
			$scope.x={};
			$scope.mar_follows="";
		})
		
	}
	$scope.follow_clear=function()
	{
		$scope.y={};
	}
	
	$scope.follow_update_call=function(y)
	{
		$scope.y=y;
	}
	
	$scope.update_call=function(y)
	{
		$scope.x=y;
		$http.get(rootUrl+marketing+"fetch_marketing_list?mar_head_id="+y.mar_head_id).success(function(data)
		{
			if(data==1)
			{
				$scope.get_followUp();
				$scope.mar_follows=data;
			}
		})
		$("#addform").trigger('click');
	}
	
	
	$scope.follow_temp=function(y)
	{
		if(y.mar_temp_id)
		{
			$('#loader1add').css('display','inline');
			$('#submitbtn1add').attr('disabled',true);
			$http.get(rootUrl+marketing+"follow_temp?cat_id="+y.cat_id+"&place="+y.place+"&rem_date="+y.rem_date+"&visit_place="+y.visit_place+"&remarks="+y.remarks+"&id="+y.mar_temp_id+"&mar_list_id="+y.mar_list_id).success(function(data)
			{
				$('#submitbtn1add').attr('disabled',false);
				if(data=="1")
				{
					$scope.y={};
					messages("success", "Success!","Data Assigned Successfully", 3000);
					$scope.get_followUp();
				}
				else
				{
					messages("danger", "Warning!",data, 4000);
				}
				$('#loader1add').css('display','none');
			})
		}
		else
		{
			$('#loader1add').css('display','inline');
			$('#submitbtn1add').attr('disabled',true);
			$http.get(rootUrl+marketing+"follow_temp?cat_id="+y.cat_id+"&place="+y.place+"&rem_date="+y.rem_date+"&visit_place="+y.visit_place+"&remarks="+y.remarks).success(function(data)
			{
				if(data=="1")
				{
					$scope.y={};
					messages("success", "Success!","Data Assigned Successfully", 3000);
					$scope.get_followUp();
				}
				else
				{
					messages("danger", "Warning!",data, 4000);
				}
				$('#submitbtn1add').attr('disabled',false);
				$('#loader1add').css('display','none');
			})
		}
	}
	
	
	$scope.save_data=function()
	{
		$('#markform1').ajaxForm({
			type: "POST",
			url: rootUrl+marketing+"/save",
			beforeSend: function()
			{
				$('#submitbtn1mar').attr('disabled',true);
				$('#loader1mar').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					$scope.main_clear();
					$scope.follow_clear();
					messages("success", "Success!","Data Saved Successfully", 3000);
					$scope.get_marketingfollowUp();
					$scope.get_followUp();
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader1mar').css('display','none');
				$('#submitbtn1mar').attr('disabled',false);
			}
		});
	}
	
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Staff Details may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+marketing+"delete?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Category Details Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Category Details not Deleted", 4000);
					}
					$scope.get_marketingfollowUp();
				})
			}
		}
	}
	
	$scope.folow_temp_delete_data=function(id)
	{
		if(confirm("Deleting Data may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+marketing+"folow_temp_delete?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Data Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Data not Deleted", 4000);
					}
					$scope.get_followUp();
				})
			}
		}
	}
	
}]);//blank line is required
app.controller('hr_master_settings',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	
	rootUrl=$rootScope.site_url;
	module="hr_master_settings/";
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	$scope.show=0;
	$scope.x={};
	$scope.y={};
	$scope.s={};
	$scope.s1={};
	$scope.exit=function(){
		$scope.show=0;
	}
	$scope.exit();
	
	//Getting Modules View Data
	$scope.loader=function()
	{
		$http.get(rootUrl+"shift_settings/view").success(function(data)
		{
			$scope.s=data[0];
			if(data[1])
			{
				$scope.s1=data[1];
				if($scope.s1.name)
					$scope.show=1;
			}
		})
	}
	$scope.loader();
	$scope.loader_half=function()
	{
		$http.get(rootUrl+"half_day_settings/view").success(function(data){
			console.log("Half day");
			console.log(data);
			if(data.length>0){
				$scope.y=data[0];
				var halftim=data[0].m_time.split(':');
				$('#HalfTimeHour').val(halftim[0]);
				$('#HalfTimeMin').val(halftim[1]);
			}
		})
	}
	$scope.loader_half();
	$scope.loader_com=function()
	{
		$http.get(rootUrl+"com_config/view").success(function(data){
			console.log(data);
			$scope.c=data[0];
		})
	}
	$scope.loader_com();
	$scope.loader2=function()
	{
		$http.get(rootUrl+"hr_master_settings/view_data").success(function(data)
		{
			console.log(data);
			$scope.m=data[0];
			var tim=data[0].work_hour.split(':');
			$('#hour').val(tim[0]);
			$('#min').val(tim[1]);
		})
	}
	$scope.loader2();
	
	$scope.loader3=function()
	{
		$http.get(rootUrl+"pf_settings/view").success(function(data){
			console.log(data);
			$scope.p=data[0];
		})
	}
	$scope.loader3();
	//Getting Modules View Data END
	
	
	// Each Module Data
	$scope.shift_new=function()
	{
		$("#form1").trigger('reset');
		$scope.s={};
	}
	$scope.changeForm=function()
	{
		console.log("asdfhj");
		$scope.show=1;
	}
	
	$scope.master_new=function()
	{
		$("#master_form").trigger('reset');
		$scope.x={};
	}
	$scope.half_new=function()
	{
		$("#half_form").trigger('reset');
		$scope.h={};
	}
	//end here//
	
	
	
	// Save 
	$scope.master_save_data=function(x)
	{
		$('#master_submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+"hr_master_settings/master_save_data",
			data: $("#master_form").serialize(),
			beforeSend: function()
			{
				$('#webprogress').css('display','inline');
			},
			success: function(data)
			{
				console.log(data)
				if(data=="1")
				{
					$scope.loader2();
					$scope.loader3();
					$scope.loader_half();
					$scope.loader();
					messages("success", "Success!","Master Settings Set Successfully", 4000);
					
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 10000);
				}
				else
				{
					messages("danger", "Warning!",data, 10000);
				}
				$('#webprogress').css('display','none');
			}
		});
		$('#master_submitbtn').attr('disabled',false);
	}
}]);//blank line is required
app.controller('hr_docs_design',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	
	rootUrl=$rootScope.site_url;
	module="hr_docs_design/";
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});
	
	
	$scope.loader=function()
	{
		$http.get(rootUrl+"hr_docs_design/view").success(function(data)
		{
			$scope.datadb=data;
		})
	}
	$scope.loader();
	$scope.filter_new=function()
	{
		$scope.x={};
	}
	$scope.update_call=function(y)
	{
		$scope.x=y;
		$http.get(rootUrl+"hr_docs_design/view?data=content&id="+y.dd_id).success(function(data)
		{
			$scope.x.content=data[0].content;
		})
	}
	$scope.save_data=function(x)
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+"hr_docs_design/save_data",
			data: $("#dd_form").serialize(),
			beforeSend: function()
			{
				$('#webprogress').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					$scope.loader();
					$scope.filter_new();
					messages("success", "Success!","Master Settings Set Successfully", 4000);
					
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 10000);
				}
				else
				{
					messages("warning", "Warning!",data, 10000);
				}
				$('#webprogress').css('display','none');
			}
		});
		$('#submitbtn').attr('disabled',false);
	}
	
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting data may hamper your data associated with it. You will loose the data related with this."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+"hr_docs_design/delete_data?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Document Deleted Successfully", 4000);
					}
					else
					{
						messages("danger", "Warning!","Document not Deleted", 10000);
					}
					$scope.loader();
				})
			}
		}
	}
	
}]);//blank line is required
app.controller('hr_issue_certificate',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	
	rootUrl=$rootScope.site_url;
	module="hr_issue_certificate/";
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});

	$scope.x = {};
	$scope.show = 0;
	$scope.employee = [];
	$scope.datadb = [];
	$scope.pageno = 1;
	$scope.total_count = 0;
	$scope.pager = {itemsPerPage:'15'};
	$scope.qx = {};
	$scope.issue_certificate_modal_title = "Add Issue Certificate";

	function initIssueCertificateSelect2() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		setTimeout(function () {
			var $modal = $('#issueCertificateModal');
			var isSelect2V4 = !!($.fn.select2 && $.fn.select2.amd);

			$('.issue-certificate-root select, #issueCertificateModal select').each(function () {
				var $el = $(this);
				if (!$el.is('select')) {
					return;
				}
				if ($el.hasClass('no-select2') || $el.is('[data-no-select2]')) {
					return;
				}

				if ($el.data('select2')) {
					$el.select2('destroy');
				}

				var options = {
					width: '100%',
					minimumResultsForSearch: 0
				};

				if (isSelect2V4 && $el.closest('#issueCertificateModal').length) {
					options.dropdownParent = $modal;
				}

				$el.select2(options);
			});
		}, 0);
	}

	function allowSelect2TypingInsideIssueCertificateModal() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.modal || !$.fn.modal.Constructor) {
			return;
		}

		var ModalConstructor = $.fn.modal.Constructor;
		if (ModalConstructor.prototype._issueCertificateSelect2FocusPatched) {
			return;
		}

		ModalConstructor.prototype.enforceFocus = function () {
			var modalThis = this;
			$(document)
				.off('focusin.bs.modal')
				.on('focusin.bs.modal', function (e) {
					var $target = $(e.target);
					var isInsideModal = modalThis.$element[0] === e.target || modalThis.$element.has(e.target).length;
					var isSelect2Input =
						$target.closest('.select2-container, .select2-dropdown, .select2-drop, .select2-search').length > 0 ||
						$target.is('.select2-input, .select2-search__field');

					if (!isInsideModal && !isSelect2Input) {
						modalThis.$element.trigger('focus');
					}
				});
		};

		ModalConstructor.prototype._issueCertificateSelect2FocusPatched = true;

		$(document).off('select2:open.issueCertificate select2-open.issueCertificate');
		$(document).on('select2:open.issueCertificate select2-open.issueCertificate', function () {
			setTimeout(function () {
				var $search = $('.select2-container-active .select2-input, .select2-drop-active .select2-input, .select2-container--open .select2-search__field');
				if ($search.length) {
					$search.focus();
				}
			}, 0);
		});
	}

	$scope.loader=function(pageno)
	{
		if(!pageno)
			pageno = 1;
		$scope.pageno = pageno;

		var params = [];
		if($scope.qx.emp_code)
			params.push("emp_code=" + encodeURIComponent($scope.qx.emp_code));
		if($scope.qx.dd_id)
			params.push("dd_id=" + encodeURIComponent($scope.qx.dd_id));
		if($scope.qx.issue_date)
			params.push("issue_date=" + encodeURIComponent($scope.qx.issue_date));
		if($scope.qx.q)
			params.push("q=" + encodeURIComponent($scope.qx.q));

		var url = rootUrl + "hr_issue_certificate/view/" + $scope.pager.itemsPerPage + "/" + pageno;
		if(params.length)
			url += "?" + params.join("&");

		$http.get(url).success(function(response)
		{
			if(response && response.data !== undefined)
			{
				$scope.datadb = response.data || [];
				$scope.total_count = response.total_count || 0;
				initIssueCertificateSelect2();
			}
			else
			{
				$scope.datadb = response || [];
				$scope.total_count = ($scope.datadb || []).length;
				initIssueCertificateSelect2();
			}
		});
	};
	$scope.loader(1);

	$scope.get_page_count = function()
	{
		var per = parseInt($scope.pager.itemsPerPage, 10) || 0;
		var total = parseInt($scope.total_count, 10) || 0;
		var page = parseInt($scope.pageno, 10) || 1;

		if(per <= 0 || total <= 0)
			return 0;

		var shown = total - ((page - 1) * per);
		if(shown <= 0)
			return 0;
		return shown > per ? per : shown;
	};

	$scope.apply_filters=function()
	{
		$scope.loader(1);
	};

	$scope.clear_filters=function()
	{
		$scope.qx = {};
		$scope.pager.itemsPerPage = '15';
		$scope.loader(1);
	};

	$scope.on_items_per_page_change=function()
	{
		$scope.loader(1);
	};

	function initIssueDatePicker(){
		setTimeout(function(){
			if($('#dateissue').length && !$('#dateissue').data('datepicker'))
				$('#dateissue').datepicker();
			if($('#dateissue').length && !$('#dateissue').val())
				$('#dateissue').datepicker('setDate','now');
		},120);
	}
	
	$http.get(rootUrl+"hr_docs_design/view?data=dd_id,title").success(function(data){
		$scope.docs=data;
		initIssueCertificateSelect2();
	});
	
	$scope.filter_form=function(refreshList)
	{
		$scope.show=0;
		$scope.x={};
		$scope.employee=[];
		$("#response").html("");
		if(refreshList!==false)
			$scope.loader(1);
		initIssueDatePicker();
	};

	$scope.update_call=function(y)
	{
		$scope.x = angular.copy(y || {});
		$scope.x.date = y.issue_date;
	};

	$scope.open_issue_certificate_modal=function(mode,y)
	{
		if(mode=="edit" && y)
		{
			$scope.issue_certificate_modal_title = "Edit Issue Certificate";
			$scope.update_call(y);
		}
		else
		{
			$scope.issue_certificate_modal_title = "Add Issue Certificate";
			$scope.filter_form(false);
		}
		$('#issueCertificateModal').modal('show');
		allowSelect2TypingInsideIssueCertificateModal();
		initIssueCertificateSelect2();
		initIssueDatePicker();
		if(mode=="edit" && y && y.emp_code)
			$scope.fetchEmployee(y.emp_code);
	};
	
	$scope.fetchEmployee=function(emp_code)
	{
		$scope.show=0;
		$("#response").html("");
		$http.get(rootUrl+"hr_staff_details/view?data=emp_id,staff_name as ename,grade as gr,hr_departments.name as dname,gender,emp_type&emp_code="+emp_code).success(function(data)
		{
			if(data.length>0)
			{
				$scope.show=1;
				$scope.x.emp_id=data[0].emp_id;
				$scope.employee=data;
			}	
			else
			{
				$msg="<div class='alert alert-danger'><h4 style='text-align:center;color:red;'>Invalid Employee Code!! Check Employee Code</h4><div>";
				$("#response").html($msg);
			}
		});
	};
	
	$scope.print=function(isc_id)
	{
		$http.get(rootUrl+"hr_issue_certificate/view?data=layout&id="+isc_id).success(function(data)
		{
			if(data.length>0)
			{
				var wnd = window.open("about:blank", "", "_blank");
				wnd.document.write(data[0].layout);
			}
		});
	};
	
	$scope.save_data=function(x)
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+"hr_issue_certificate/save_data",
			data: $("#isc_form").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				console.log(data);
				if(data=="1")
				{
					messages("success", "Success!","Certificate Issued Successfully", 4000);
					$scope.loader($scope.pageno || 1);
					$scope.filter_form(false);
					$('#issueCertificateModal').modal('hide');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 10000);
				}
				else
				{
					messages("warning", "Warning!",data, 10000);
				}
				$('#loader').css('display','none');
			}
		});
		$('#submitbtn').attr('disabled',false);
	};
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting data may hamper your data associated with it. You will loose the data related with this."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+"hr_issue_certificate/delete_data?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Issued Certificate Deleted Successfully", 4000);
						$scope.loader($scope.pageno || 1);
					}
					else
					{
						messages("danger", "Warning!","Issued Certificate Not Deleted", 10000);
					}
				});
			}
		}
	};

	allowSelect2TypingInsideIssueCertificateModal();
	$(document).off('shown.bs.modal.issueCertificateSelect2', '#issueCertificateModal').on('shown.bs.modal.issueCertificateSelect2', '#issueCertificateModal', function () {
		initIssueCertificateSelect2();
	});
	initIssueCertificateSelect2();
	
}]);
//blank line is required
app.controller('master_follow_up',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	module='Hr_master_follow_up/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){window.location.assign('index.html');}});
	$scope.init=function()
	{
		$http.get(rootUrl+module+"view_data").success(function(data){
			$scope.datadb=data;
		})
	}
	$scope.init();
	$scope.x={};
	$scope.update_call=function(y)
	{
		$scope.x=y;
	}
	$scope.filter_new=function()
	{
		$scope.x={};
		$scope.init();
	}
	
	$scope.save_data=function()
	{
			$('#submitbtn').attr('disabled',true);
			$.ajax({
				type: "POST",
				url: rootUrl+module+"save_data",
				data: $("#master_folform1").serialize(),
				beforeSend: function()
				{
					$('#loader').css('display','inline');
				},
				success: function(data)
				{
					if(data=="1")
					{
						messages("success", "Success!","Master Follow Up Saved Successfully", 3000);
						$scope.filter_new();
						$scope.init();
					}
					else if(data=="0")
					{
						messages("warning", "Info!","No Data Affected", 3000);
					}
					else
					{
						messages("danger", "Warning!",data, 6000);
					}
					$('#loader').css('display','none');
					$('#submitbtn').attr('disabled',false);
				}
			});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Staff Details may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"delete_data?fm_id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Master Follow Up Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Master Follow Up not Deleted", 4000);
					}
					$scope.init();
				})
			}
		}
	}
	
}]);//blank line is required
app.controller('payments',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	jmodule='payments/';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+jmodule+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});

	$scope.d = {};
	$scope.x = {};
	$scope.datadb = [];
	$scope.show = 0;
	$scope.pageno = 1;
	$scope.total_count = 0;
	$scope.pager = { itemsPerPage: '15' };
	$scope.qx = {};
	$scope.payments_modal_title = "Add Payment";

	function initPaymentsSelect2() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		setTimeout(function () {
			var $modal = $('#paymentsModal');
			var isSelect2V4 = !!($.fn.select2 && $.fn.select2.amd);

			$('.payments-root .payments-select2, #paymentsModal .payments-select2').each(function () {
				var $el = $(this);
				if (!$el.is('select')) {
					return;
				}

				if ($el.data('select2')) {
					$el.select2('destroy');
				}

				var options = {
					width: '100%',
					minimumResultsForSearch: 0
				};

				if (isSelect2V4 && $el.closest('#paymentsModal').length) {
					options.dropdownParent = $modal;
				}

				$el.select2(options);
			});
		}, 0);
	}

	function allowSelect2TypingInsidePaymentsModal() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.modal || !$.fn.modal.Constructor) {
			return;
		}

		var ModalConstructor = $.fn.modal.Constructor;
		if (ModalConstructor.prototype._paymentsSelect2FocusPatched) {
			return;
		}

		ModalConstructor.prototype.enforceFocus = function () {
			var modalThis = this;
			$(document)
				.off('focusin.bs.modal')
				.on('focusin.bs.modal', function (e) {
					var $target = $(e.target);
					var isInsideModal = modalThis.$element[0] === e.target || modalThis.$element.has(e.target).length;
					var isSelect2Input =
						$target.closest('.select2-container, .select2-dropdown, .select2-drop, .select2-search').length > 0 ||
						$target.is('.select2-input, .select2-search__field');

					if (!isInsideModal && !isSelect2Input) {
						modalThis.$element.trigger('focus');
					}
				});
		};

		ModalConstructor.prototype._paymentsSelect2FocusPatched = true;

		$(document).off('select2:open.payments select2-open.payments');
		$(document).on('select2:open.payments select2-open.payments', function () {
			setTimeout(function () {
				var $search = $('.select2-container-active .select2-input, .select2-drop-active .select2-input, .select2-container--open .select2-search__field');
				if ($search.length) {
					$search.focus();
				}
			}, 0);
		});
	}

	$scope.loader = function(pageno)
	{
		if(!pageno)
			pageno = 1;
		$scope.pageno = pageno;

		var params = [];
		if($scope.qx.emp_id)
			params.push("emp_id=" + encodeURIComponent($scope.qx.emp_id));
		if($scope.qx.mode)
			params.push("mode=" + encodeURIComponent($scope.qx.mode));
		if($scope.qx.date)
			params.push("date=" + encodeURIComponent($scope.qx.date));
		if($scope.qx.q)
			params.push("q=" + encodeURIComponent($scope.qx.q));

		var url = rootUrl + jmodule + "view/" + $scope.pager.itemsPerPage + "/" + pageno;
		if(params.length)
			url += "?" + params.join("&");

		$http.get(url).success(function(response)
		{
			if(response && response.data !== undefined)
			{
				$scope.datadb = response.data || [];
				$scope.total_count = response.total_count || 0;
				initPaymentsSelect2();
			}
			else
			{
				// Backward-compatible fallback if paginated endpoint is unavailable.
				$http.get(rootUrl+jmodule+"view_data").success(function(data)
				{
					$scope.datadb = data || [];
					$scope.total_count = ($scope.datadb || []).length;
					initPaymentsSelect2();
				});
			}
		});
	};

	$scope.apply_filters = function()
	{
		$scope.loader(1);
	};

	$scope.clear_filters = function()
	{
		$scope.qx = {};
		$scope.pager.itemsPerPage = '15';
		$scope.loader(1);
	};

	$scope.on_items_per_page_change = function()
	{
		$scope.loader(1);
	};

	$scope.get_page_count = function()
	{
		var per = parseInt($scope.pager.itemsPerPage, 10) || 0;
		var total = parseInt($scope.total_count, 10) || 0;
		var page = parseInt($scope.pageno, 10) || 1;

		if(per <= 0 || total <= 0)
			return 0;

		var shown = total - ((page - 1) * per);
		if(shown <= 0)
			return 0;
		return shown > per ? per : shown;
	};

	$http.get(rootUrl+"hr_staff_details/view?data=staff_name as name,emp_id&st=1").success(function(data)
	{
		$scope.employees=data;
		initPaymentsSelect2();
	});

	$scope.filter_new_jour=function()
	{
		$scope.d={};
		$scope.show=0;
		setTimeout(function(){
			if($('#DOB1').length && !$('#DOB1').val())
				$('#DOB1').datepicker('setDate','now');
		},120);
	};

	$scope.update_call=function(y)
	{
		$scope.show=0;
		$scope.d=angular.copy(y);
		if($scope.d.dr==0)
			$scope.d.dr="";
		if($scope.d.cr==0)
			$scope.d.cr="";
		if($scope.d.emp_id)
			$scope.calcDue($scope.d.emp_id);
	};

	$scope.open_payment_modal = function(mode,y)
	{
		if(mode=="edit" && y)
		{
			$scope.payments_modal_title = "Edit Payment";
			$scope.update_call(y);
		}
		else
		{
			$scope.payments_modal_title = "Add Payment";
			$scope.filter_new_jour();
		}
		$('#paymentsModal').modal('show');
		allowSelect2TypingInsidePaymentsModal();
		initPaymentsSelect2();
	};

	$scope.calcDue=function(emp_id)
	{
		$scope.show=1;
		$scope.due=0;
		$scope.lastCrDate="";
		$scope.lastDrDate="";
		$http.get(rootUrl+jmodule+"calcDue?emp_id="+emp_id).success(function(data)
		{
			if(data)
			{
				$scope.due=data.due;
				$scope.lastCrDate=data.lastCrDate;
				$scope.lastDrDate=data.lastDrDate;
				$scope.lastCredit=data.lastCredit;
				$scope.lastDebit=data.lastDebit;
			}
		});
	};

	$scope.save_data=function()
	{
		$('#submitbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+jmodule+"save",
			data: $("#form1").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$scope.loader($scope.pageno || 1);
					$scope.filter_new_jour();
					$('#paymentsModal').modal('hide');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#submitbtn').attr('disabled',false);
			}
		});
	};

	$scope.delete_data=function(id)
	{
		if(confirm("Deleting payments Records may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+jmodule+"delete_data?id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","payments Records Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","payments Records not Deleted", 4000);
					}
					$scope.loader($scope.pageno || 1);
				});
			}
		}
	};

	$scope.loader(1);
	allowSelect2TypingInsidePaymentsModal();
	$(document).off('shown.bs.modal.paymentsSelect2', '#paymentsModal').on('shown.bs.modal.paymentsSelect2', '#paymentsModal', function () {
		initPaymentsSelect2();
	});
	initPaymentsSelect2();
}]);
//blank line is required
app.controller('sms',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	rootUrl=$rootScope.site_url;
	module="sms/";
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});

	function initSmsSelect2() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		setTimeout(function () {
			$('.sms-page .select-two').each(function () {
				var $el = $(this);
				if (!$el.is('select')) {
					return;
				}

				if ($el.data('select2')) {
					$el.select2('destroy');
				}

				$el.select2({
					width: '100%',
					minimumResultsForSearch: 0
				});
			});
		}, 0);
	}

	$scope.x={};
	$scope.isLoading=true;
	$('#progress').hide();
	
	$scope.url=rootUrl+'hr_staff_details/view?data=staff_name as nm,hr_departments.name as desig,type as tp,grade as gd,contact_no as phn,emp_id as id&status=1';
    $http.get($scope.url)
		.success (function(data) {$scope.staff_data=data;
		$scope.rows=Object.keys(data).length;
		$scope.isLoading=false;
		initSmsSelect2();
	});
    
    $http.get(rootUrl+"hr_grades/view?data=grade").success(function(data){
		$scope.grades=data;
		initSmsSelect2();
	})
    
	$scope.fetch_design=function(x){
    	$scope.x.design='';
		$scope.isLoading=true;
		if(x && x.grade)
		{
			$http.get(rootUrl+"hr_designation/view?join=1&data=d_id,name&grade="+x.grade).success(function(data)
			{
				$scope.designations=data;
				initSmsSelect2();
			})
		}
		$http.get($scope.url+'&grade='+x.grade)
			.success (function(data) {$scope.staff_data=data;
			$scope.rows=Object.keys(data).length;
			$scope.isLoading=false;
			initSmsSelect2();
		});
		$("#selecctall").checked= false;
	};
	
	$scope.design_filter=function(x){
		$scope.isLoading=true;
		$http.get($scope.url+'&grade='+x.grade+"&d_id="+x.design)
			.success (function(data) {$scope.staff_data=data;
			$scope.rows=Object.keys(data).length;
			$scope.isLoading=false;
			initSmsSelect2();
		});
	};

	$scope.select_all=function(){
		 if(this.checked) { // check select status
	            $('.checkbox1').each(function() { //loop through each checkbox
	                this.checked = true;  //select all checkboxes with class "checkbox1"               
	            });
	        }else{
	            $('.checkbox1').each(function() { //loop through each checkbox
	                this.checked = false; //deselect all checkboxes with class "checkbox1"                       
	            });         
	        }
	}
 	$scope.send=function(){
 		$("#btnsubmit").text('Please Wait...');
		$("#btnsubmit").prop('disabled',true);
 		$.ajax({
 			type: "POST",
 			url: rootUrl+"psms/send_sms",
 			data: $("#form").serialize(),
 			beforeSend: function()
 			{
 				$('#progress').toggle();
 			},
 			success: function(data){
 				$('#progress').hide();
 				var arr = $.parseJSON(data);
				if(arr.type=="1")
 				{
					messages("danger", "Warning!",arr.error, 4000);
 				}
 				else
 				{
 					$("#form").trigger('reset');
 					messages("success", "Success!",arr.error, 5000);
 				}
				$("#btnsubmit").text('Send');
				$("#btnsubmit").prop('disabled',false);
 			}
 		});
 	};

	initSmsSelect2();
}]);
app.controller('payroll_monthly',['$scope','$rootScope','$http',function($scope,$rootScope,$http)
{
	mmodule='payroll_monthly';
	rootUrl=$rootScope.site_url;
	//login auth not required here..
	
	$http.get(rootUrl+"hr_paytype/view?st=1").success(function(data){
		$scope.paytypes_data=data;
	})
	$scope.ftype=function(t){
		if(t=='1') return "-"; else return "+";
	}
	
	$scope.save_data1=function(x)
	{
		$('#submitbtn3').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+mmodule+"/save",
			data: $("#medicalform").serialize(),
			beforeSend: function()
			{
				$('#loader3').css('display','inline');
			},
			success: function(data)
			{
				if(data=="1")
				{
					messages("success", "Success!","Saved Successfully", 3000);
					$("#dc_id").trigger('click');
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader3').css('display','none');
				$('#submitbtn3').attr('disabled',false);
			}
		});
	}
}]);app.controller('plan_master',['$scope','$rootScope','$http',function($scope,$rootScope,$http){
	module='plan_master';
	rootUrl=$rootScope.site_url;
	$http.get(rootUrl+module+"/index").success (function(data) {if(data==0){window.location.assign('login.html');} else if(data==2){messages("success", "Privilege not assigned.", 1000);window.location.assign('index.html');}});

	
	$scope.init=function()
	{
		$http.get(rootUrl+module+"/view").success(function(data)
		{
			$scope.datadb=data;
		});
		$http.get(rootUrl + "service_master/view").success(function(data){
			$scope.service_list = data;
		});
	}
	$scope.init();
	
	$scope.update_call=function(y)
	{
		$scope.x=y;
	}
	
	$scope.filter_new=function()
	{
		$scope.x={};
		$scope.salary="";
	}
	
	$scope.save_data=function()
	{
		$('#planbtn').attr('disabled',true);
		$.ajax({
			type: "POST",
			url: rootUrl+module+"/save",
			data: $("#planform").serialize(),
			beforeSend: function()
			{
				$('#loader').css('display','inline');
			},
			success: function(data)
			{
				console.log(data);
				if(data=="1")
				{
					messages("success", "Success!","Plan Saved Successfully", 3000);
					$scope.init();
					$scope.filter_new();
				}
				else if(data=="0")
				{
					messages("warning", "Info!","No Data Affected", 3000);
				}
				else
				{
					messages("danger", "Warning!",data, 6000);
				}
				$('#loader').css('display','none');
				$('#planbtn').attr('disabled',false);
			}
		});
	}
	
	$scope.delete_data=function(id)
	{
		if(confirm("Deleting Designation may hamper your data associated with it."))
		{
			if(confirm("Are you Sure to DELETE ??"))
			{
				$http.get(rootUrl+module+"/delete?dg_id="+id).success(function(data){
					if(data=="1")
					{
						messages("success", "Success!","Designation Deleted Successfully", 3000);
					}
					else
					{
						messages("danger", "Warning!","Designation not Deleted", 4000);
					}
					$scope.init();
				})
			}
		}
	}

	$scope.options = {
		height: 200,
		toolbar: [
		  // Remove 'style' button group completely
		  ['font', ['bold', 'italic', 'underline']],
		  ['para', ['ol', 'paragraph']],
		  ['insert', ['link']],
		  ['view', ['codeview']]
		]
	  };
}]);app.controller('customer', ['$scope', '$rootScope', '$http', '$timeout', 'sharedService', function ($scope, $rootScope, $http, $timeout, sharedService) {
	rootUrl = $rootScope.site_url;
	$http.get(rootUrl + "customer/index").success(function (data) { if (data == 0) { window.location.assign('login.html'); } else if (data == 2) { window.location.assign('index.html'); } });

	$scope.login_check = localStorage.getItem('login');
	$scope.type_check = localStorage.getItem('type');
	$scope.pageno = 1;
	$scope.total_count = 0;
	$scope.itemsPerPage = '15';
	$scope.qx = {};
	$scope.x = {};
	$scope.qs = {};
	$scope.datadb = [];
	$scope.customer_modal_title = "Add Customer";
	$scope.numbers = Array.from({ length: 12 }, (_, i) => i + 1);
	$scope.reviewStatusUpdating = {};

	$scope.options =
	{
		height: 150,
		toolbar: [
			['style', ["undo", "redo", 'style', 'bold', 'italic', 'underline']],
			['fontname', ['fontname']],
			['fontsize', ['fontsize']],
			['color', ['color']],
			['para', ['ol', 'ul', 'paragraph', 'height']],
			['font', ['strikethrough', 'superscript', 'subscript']],
			['table', ['table']],
			['insert', ['link', 'video', 'hr', 'picture']],
			["view", ["fullscreen", "codeview", "help",]]
		]
	};

	$scope.loader = function (pageno) {
		if (!pageno)
			pageno = 1;
		$scope.pageno = pageno;

		var params = [];
		if ($scope.qx.com_name)
			params.push("com_name=" + encodeURIComponent($scope.qx.com_name));
		if ($scope.qx.grade)
			params.push("grade=" + encodeURIComponent($scope.qx.grade));
		if ($scope.qx.phone)
			params.push("phone=" + encodeURIComponent($scope.qx.phone));

		var url = rootUrl + "customer/view_paginated/" + $scope.itemsPerPage + "/" + pageno;
		if (params.length)
			url += "?" + params.join("&");

		$http.get(url).success(function (response) {
			if (response && response.data !== undefined) {
				$scope.datadb = response.data || [];
				$scope.total_count = response.total_count || 0;
			} else {
				$scope.datadb = response || [];
				$scope.total_count = ($scope.datadb || []).length;
			}
		});
	};

	$scope.init = function () {
		$scope.loader(1);
		$http.get(rootUrl + "company_master/view_state?data=iso2,name").success(function (data) {
			$scope.state_list = data;
		});
	};
	$scope.init();

	$scope.filter_data = function (com_name, grade, phone) {
		$scope.qx.com_name = com_name;
		$scope.qx.grade = grade;
		$scope.qx.phone = phone;
		$scope.loader(1);
	};

	$scope.apply_filters = function () {
		$scope.loader(1);
	};

	$scope.clear_filters = function () {
		$scope.qx = {};
		$scope.itemsPerPage = '15';
		$scope.loader(1);
	};

	$scope.on_items_per_page_change = function () {
		$scope.loader(1);
	};

	$scope.filter_new = function () {
		$scope.clear_filters();
	};

	$scope.selectedPlans = [];
	$scope.$watchCollection('selectedPlans', function () {
		$timeout(function () {
			var totalPlans = $scope.selectedPlans.length;
			for (var i = 1; i <= totalPlans; i++) {
				$("#DOB" + i + "_start").datepicker({
					format: "yyyy-mm-dd",
					autoclose: true,
					todayHighlight: true
				}).on('changeDate', function (e) {
					var index = $(this).attr("id").match(/\d+/)[0] - 1;
					$scope.$apply(function () {
						$scope.selectedPlans[index].start_date = e.format(0, "yyyy-mm-dd");
					});
				});

				$("#DOB" + i + "_end").datepicker({
					format: "yyyy-mm-dd",
					autoclose: true,
					todayHighlight: true
				}).on('changeDate', function (e) {
					var index = $(this).attr("id").match(/\d+/)[0] - 1;
					$scope.$apply(function () {
						$scope.selectedPlans[index].end_date = e.format(0, "yyyy-mm-dd");
					});
				});
			}
		});
	});

	$scope.plan_change = function (selectedPlanNames) {
		$scope.x.plan_cost = 0;
		$scope.selectedPlans = [];

		if (!selectedPlanNames || selectedPlanNames.length === 0) {
			$scope.x.plan_cost = "";
			return;
		}

		angular.forEach(selectedPlanNames, function (planName) {
			var plan = $scope.plan_data.find(function (p) { return p.name === planName; });
			if (plan) {
				$scope.selectedPlans.push({
					name: plan.name,
					sp: parseFloat(plan.sp) || 0,
					start_date: null,
					end_date: null
				});
				$scope.x.plan_cost += parseFloat(plan.sp) || 0;
			}
		});
	};

	$scope.supdate_call = function (c_id) {
		sharedService.setData({ c_id: c_id });
		$rootScope.$broadcast('follow_up');
		$http.get(rootUrl + "customer/view?c_id=" + c_id).success(function (data) {
			$scope.x = data[0] || {};
			$scope.name = ($scope.x && $scope.x.name) ? $scope.x.name : '';
			$scope.login = ($scope.x && $scope.x.login) ? $scope.x.login : '';
			$('#customerFormModal').modal('show');
		});
	};

	$scope.open_customer_modal = function (mode, y) {
		if (mode == 'edit' && y) {
			$scope.customer_modal_title = "Edit Customer";
			$scope.supdate_call(y.c_id);
			return;
		}

		$scope.customer_modal_title = "Add Customer";
		$scope.filter_new1();
		$scope.x.status = '1';
		$scope.x.review_status = '0';
		$('#customerFormModal').modal('show');
	};

	$scope.filter_new1 = function () {
		$scope.x = {};
	};

	$scope.save_data1 = function (x) {
		$('#customerform').ajaxForm({
			type: "POST",
			url: rootUrl + "customer/save",
			beforeSend: function () {
				$('#loader1').css('display', 'inline');
			},
			success: function (data) {
				if (data.error == "0") {
					messages("success", data.msg);
					$scope.loader($scope.pageno || 1);
					$scope.filter_new1();
					$('#customerFormModal').modal('hide');
				}
				else {
					messages("danger", "Warning!", data.msg, 6000);
				}
				$('#loader1').css('display', 'none');
				$('#submitbtn1').attr('disabled', false);
			}
		});
	};

	$scope.update_review_status = function (row) {
		if (!row || !row.c_id) {
			return;
		}

		var c_id = row.c_id;
		var nextStatus = (row.review_status == '1' || row.review_status === 1 || row.review_status === true) ? '1' : '0';
		var previous = nextStatus === '1' ? '0' : '1';

		if ($scope.reviewStatusUpdating[c_id]) {
			row.review_status = previous;
			return;
		}

		$scope.reviewStatusUpdating[c_id] = true;

		$http({
			method: 'POST',
			url: rootUrl + "customer/update_review_status",
			data: $.param({
				c_id: c_id,
				review_status: nextStatus
			}),
			headers: {
				'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
			}
		}).then(function (response) {
			var res = (response && response.data) ? response.data : {};
			if (String(res.error) === "0") {
				row.review_status = nextStatus;
				messages("success", "Success!", res.msg || "Review status updated successfully.", 2500);
			} else {
				row.review_status = previous;
				messages("warning", "Warning!", (res.msg || "Review status update failed."), 4000);
			}
		}, function () {
			row.review_status = previous;
			messages("danger", "Warning!", "Unable to update review status.", 4000);
		}).finally(function () {
			$scope.reviewStatusUpdating[c_id] = false;
		});
	};

	$scope.delete_data = function (id) {
		if (confirm("Deleting Customer Details may hamper your data associated with it.")) {
			if (confirm("Are you Sure to DELETE ??")) {
				$http.get(rootUrl + "customer/delete?c_id=" + id).success(function (data) {
					if (data == "1") {
						messages("success", "Success!", "Customer Details Deleted Successfully", 3000);
					}
					else {
						messages("danger", "Warning!", "Customer Details not Deleted. " + data, 4000);
					}
					$scope.loader($scope.pageno || 1);
				});
			}
		}
	};
}]);
app.controller('quotation', ['$scope', '$rootScope', '$http', '$timeout', '$state', '$stateParams', function ($scope, $rootScope, $http, $timeout, $state, $stateParams) {
	let module = 'quotation';
	let rootUrl = $rootScope.site_url;
	$http.get(rootUrl + module + "/index").success(function (data) { if (data == 0) { window.location.assign('login.html'); } else if (data == 2) { messages("success", "Privilege not assigned.", 1000); window.location.assign('index.html'); } });


	$scope.init = function () {
		$http.get(rootUrl + module + "/view").success(function (data) {
			$scope.datadb = data;
			console.log('datadb:', $scope.datadb);
		})
		$http.get(rootUrl + "customer/view?data=name,c_id").success(function (data) {
			if (data.length == 1) {
				$scope.x.c_id = data[0]['c_id'];
				$scope.customers = data;
			} else {
				$scope.customers = data;
			}
		});
		$http.get(rootUrl + "company_master/view?data=name,com_id").success(function (data) {
			if (data.length == 1) {
				$scope.x.com_id = data[0]['com_id'];
				$scope.companies = data;
			} else {
				$scope.companies = data;
			}
		});
		$http.get(rootUrl + module + "/get_staff_list?quotation_generator=1").success(function (data) {
			if (data.length == 1) {
				$scope.x.emp_id = data[0]['emp_id'];
				$scope.employies = data;
			} else {
				$scope.employies = data;
			}
		});
		$http.get(rootUrl + module + "/get_template_list").then(function (response) {
			$scope.template_list = response.data;
		});
		$http.get(rootUrl + "plan_master/view").success(function (data) {
			$scope.plan_data = data;
		});
	}
	$scope.today_date = function () {
		// setting the current date as default
		$scope.x = $scope.x || {};
		let d = new Date();
		let day = ("0" + d.getDate()).slice(-2);
		let month = ("0" + (d.getMonth() + 1)).slice(-2);
		let year = d.getFullYear();
		$scope.x.date = day + "/" + month + "/" + year;
		// end of setting current date
	}
	$scope.init();
	$scope.today_date();
	$('#DOB1').datepicker({
		format: 'dd/mm/yyyy',
		autoclose: true
	});
	$('.date').datepicker({
		format: 'dd/mm/yyyy',
		autoclose: true
	});
	$scope.q_id = '';
	$scope.update_call = function (y) {
		$scope.x = y;
		$scope.q_id = y.q_id;
		$scope.copy_plans_to_temp($scope.q_id);
	}

	$scope.$watch('x.t_save', function (newVal) {
		let t_save = newVal;
		if (t_save == '0') {
			$scope.x.template_name = '';
			$('#template_name').hide();
		} else if (t_save == 1) {
			$('#template_name').show();
		}
	});

	$scope.$watch('x.template_id', function (newVal) {
		let t_id = newVal;
		if (t_id) {
			$http.get(rootUrl + module + '/get_template_details?id=' + t_id).then(function (response) {
				console.log('template details:', response.data);
				if (response.data.status == '1') {
					// $scope.x = response.data.val;
					$scope.get_plan_temp_data(); // get temporary table data
				}
			});
		}
	});

	$scope.copy_plans_to_temp = function (q_id) {
		q_id = q_id || 0;
		$http.get(rootUrl + module + "/copy_plans_to_temp_table?q_id=" + q_id).success(function (data) {
			// if (!$scope.quotation_plans) {
			// 	$scope.quotation_plans = [];
			// }
			// if (!$scope.x) {
			// 	$scope.x = [];
			// }
			// let total = 0;
			// angular.forEach(data, function(plan,index){
			// 	total += parseFloat(plan.sp) || 0; 
			// });

			// $scope.x.plan_cost = total;
			// $scope.quotation_plans = data;

			$scope.get_plan_temp_data();

		});
	}

	// $scope.copy_plans_to_temp_details = function(q_id){
	// 	$http.get(rootUrl + module + "/get_quotation_details?q_id=" + q_id).success(function (data) {
	// 		if (!$scope.quotation_plans_data) {
	// 			$scope.quotation_plans_data = [];
	// 		}
	// 		$scope.quotation_plans_data = data;
	// 	});
	// }

	$scope.filter_new = function () {
		$scope.x = {};
		$scope.today_date();
		$http.get(rootUrl + module + '/delete_temp').success(function (data) {
			if (data === '1') {
				$scope.temp_data = {};
			}
		});
		// $scope.quotation_plans = {};
	}

	$scope.filter_plans = function () {
		$scope.selected = {};
	}

	$scope.save_data = function (x) {
		$('#quotationbtn').attr('disabled', true);
		$.ajax({
			type: "POST",
			url: rootUrl + module + "/save",
			data: $('#quotation_details').serialize(),
			beforeSend: function () {
				$('#loader').css('display', 'inline');
			},
			success: function (data) {
				if (data == "1") {
					messages("success", "Success!", "Quotation Saved Successfully", 3000);
					$scope.init();
					$scope.filter_new();
					$scope.temp_data = {};
					// $scope.quotation_plans = {};
					$scope.today_date();
				}
				else if (data == "0") {
					messages("warning", "Info!", "No Data Affected", 3000);
				}
				else {
					messages("danger", "Warning!", data, 6000);
				}
				$('#loader').css('display', 'none');
				$('#quotationbtn').attr('disabled', false);
			}
		});
	}

	$scope.add_plans = function (y) {
		// console.log('pl:',y);
		$.ajax({
			type: 'POST',
			url: rootUrl + module + '/add_plan',
			data: y,
			dataType: 'json',
			success: function (data) {
				if (data.status == 'success') {
					messages('success', 'Success', data.msg, 4000);
					$scope.filter_plans();
					$scope.get_plan_temp_data();
				} else {
					messages('warning', 'Warning', data.msg, 4000);
				}
			}
		})
	}

	$scope.get_plan_temp_data = function () {
		$http.get(rootUrl + 'quotation/get_temp_data').success(function (data) {
			if (!$scope.x) {
				$scope.x = {};
			}
			let total = 0;
			angular.forEach(data, function (plan, index) {
				total += parseFloat(plan.sp) || 0;
			});
			$scope.x.plan_cost = total;
			$scope.temp_data = data;
			console.log('temp', $scope.temp_data);
		});
	}
	$scope.generate_proforma_invoice = function (y) {
		$state.go('proforma_invoice', { q_id: y });
	}


	$scope.plan_selected = function (y) {
		$http.get(rootUrl + 'plan_master/view?plan_id=' + y).success(function (data) {
			if (!$scope.selected) {
				$scope.selected = {}; // initialize if empty
			}
			angular.extend($scope.selected, data[0]); // merge new keys/values
			$scope.selected.unit = 1;

			// ✅ Calculate discount only if both values exist
			$scope.calculateDiscount();
			$http.get(rootUrl + 'service_master/view?service_id=' + data[0].service_id + '&data=term_condition').success(function (response) {
				$scope.selected.term_condition = response[0].term_condition;
			});
		});

	}

	$scope.calculateDiscount = function (unitForm = false) {
		if ($scope.selected && $scope.selected.mrp && $scope.selected.unit && $scope.selected.sp) {
			const mrp = parseFloat($scope.selected.mrp);
			const unit = parseFloat($scope.selected.unit);
			const sp = parseFloat($scope.selected.sp);

			if (!isNaN(mrp) && !isNaN(sp) && !isNaN(unit)) {
				let price = mrp * unit;
				if (price > sp) {
					if (unitForm === true) {
						$scope.selected.sp = price;
						$scope.selected.discount = 0;
					} else {
						$scope.selected.discount = price - sp;
					}
				} else {
					$scope.selected.discount = 0;
				}

			} else {
				$scope.selected.discount = '';
			}
		} else {
			$scope.selected.discount = '';
		}
	};

	$scope.unit_change = function () {
		if ($scope.selected && $scope.selected.unit && $scope.selected.mrp) {
			$scope.calculateDiscount(true);

		}
	}

	$scope.delete_temp = function (y) {
		// console.log(y);
		if (y.temp_id) {
			$http.get(rootUrl + module + '/delete_temp?temp_id=' + y.temp_id).success(function (data) {
				if (data.status == 'success') {
					$scope.x.plan_cost = 0;
					messages('success', 'Success', data.msg, 4000);
					$scope.get_plan_temp_data();
				} else {
					messages('warning', 'Warning', data.msg, 4000);
				}
			});
		}
	}

	$scope.$watch('x.project_id', function (newVal) {
		let new_com_id = newVal;

		if (new_com_id !== undefined && new_com_id !== null && new_com_id !== '') {
			$http.get(rootUrl + "company_master/view?id=" + new_com_id + "&data=quotation_unique_no,quotation_prefix").success(function (data) {
				if (data.length === 1) {
					// console.log('data:',data);
					$scope.unique_no = data[0]['quotation_unique_no'];
					$scope.prefix = data[0]['quotation_prefix'];
					// console.log('unique:',$scope.unique_no);
					// console.log('prefix:',$scope.prefix);
					$http.get(rootUrl + module + "/view?com_id=" + new_com_id).success(function (data1) {
						// console.log('data1:', data1);
						if (data1.length === 1) {

							if ($scope.prefix) {
								$scope.recent_quotation_no = data1[0]['quotation_number'];

								let numberPart = 0;
								if ($scope.recent_quotation_no.indexOf($scope.prefix) === 0) {
									let suffix = $scope.recent_quotation_no.slice($scope.prefix.length);
									numberPart = parseInt(suffix, 10) || 0;
								}

								$scope.x.quotation_number = $scope.prefix + (numberPart + 1);
								// console.log('recent ', $scope.recent_quotation_no);
							} else {
								$scope.recent_quotation_no = data1[0]['quotation_number'];
								$scope.x.quotation_number = parseInt($scope.recent_quotation_no) + 1;
							}

						} else if (data1.length === 0) {
							// console.log()
							if ($scope.prefix) {
								if ($scope.unique_no) {
									$scope.x.quotation_number = $scope.prefix + $scope.unique_no;
								} else {
									$scope.x.quotation_number = $scope.prefix + '1';
								}

							} else {
								if ($scope.unique_no) {
									$scope.x.quotation_number = ($scope.unique_no == '0') ? 1 : $scope.unique_no;
								} else {
									$scope.x.quotation_number = 1;
								}
							}

						} else {
							if ($scope.prefix) {
								$scope.recent_quotation_no = data1[0]['quotation_number'];

								let numberPart = 0;
								if ($scope.recent_quotation_no.indexOf($scope.prefix) === 0) {
									let suffix = $scope.recent_quotation_no.slice($scope.prefix.length);
									numberPart = parseInt(suffix, 10) || 0;
								}

								$scope.x.quotation_number = $scope.prefix + (numberPart + 1);
							} else {
								$scope.recent_quotation_no = data1[0]['quotation_number'];
								$scope.x.quotation_number = parseInt($scope.recent_quotation_no) + 1;
							}

						}
					})
				}
			});
		}
	});

	$scope.generate_pdf = function (id) {
		$scope.ID = id;
		if ($scope.ID) {
			const url = rootUrl + module + `/generate_pdf?&id=${$scope.ID}`;
			window.open(url, "_blank");
		}
	}

	$scope.options = {
		height: 200,
		toolbar: [
			// Remove 'style' button group completely
			['font', ['bold', 'italic', 'underline']],
			['font', ['fontsize']],
			['para', ['ol']],
			['insert', ['link']],
			['view', ['codeview']],
			['para', ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull']]
		]
	};

	$scope.cleanHTML = function (html) {
		return html ? html.replace(/<[^>]+>/g, '') : '';
	};

}]);app.controller('invoice', ['$scope', '$rootScope', '$http', '$timeout', '$state', '$stateParams', function ($scope, $rootScope, $http, $timeout, $state, $stateParams) {
	let module = 'invoice';
	let rootUrl = $rootScope.site_url;
	$http.get(rootUrl + module + "/index").success(function (data) { if (data == 0) { window.location.assign('login.html'); } else if (data == 2) { messages("success", "Privilege not assigned.", 1000); window.location.assign('index.html'); } });

	$scope.proforma_id = $stateParams.proforma_id;
	// console.log('proforma_id:',$scope.proforma_id);
	$scope.init = function () {
		$http.get(rootUrl + "customer/view?data=name,c_id").success(function (data) {
			if (data.length === 1) {
				$scope.x.c_id = data[0]['c_id'];
				$scope.customers = data;
			} else {
				$scope.customers = data;
			}
		});
		$http.get(rootUrl + "company_master/view?data=name,com_id").success(function (data) {
			if (data.length == 1) {
				$scope.x.project_id = data[0]['com_id'];
				$scope.companies = data;
			} else {
				$scope.companies = data;
			}
			$scope.companies = data;
		});
		$http.get(rootUrl + "plan_master/view").success(function (data) {
			$scope.plan_data = data;
			// console.log('plans', data);
		});
		$http.get(rootUrl + module + "/view").success(function (data) {
			$scope.datadb = data;
			// console.log('datadb:', $scope.datadb);
		});
		// Fetching Quotation Data if invoice is generated from quotation
		if ($scope.proforma_id) {
			$http.get(rootUrl + 'proforma_invoice/view?proforma_id=' + $scope.proforma_id).success(function (data) {
				// console.log(data);
				$scope.x = data[0];
				$scope.today_date();

			});
			$http.get(rootUrl + 'proforma_invoice/get_proforma_invoice_details?proforma_id=' + $scope.proforma_id).success(function (data) {

				$http.post(rootUrl + module + '/save_temp_plans', { plans: data }).success(function (data) {
					if (data == 1) {
						$http.get(rootUrl + module + "/get_temp_plans").success(function (data) {
							$scope.invoice_plans = data;
							let total = 0;
							angular.forEach($scope.invoice_plans, function (plan, index) {
								console.log('plan: ', plan);
								total += parseFloat(plan.sp);
							});
							$scope.x.plan_cost = total;
						});
					}
				});
			});

		}
	}

	$scope.today_date = function () {
		// setting the current date as default
		$scope.x = $scope.x || {};
		let d = new Date();
		let day = ("0" + d.getDate()).slice(-2);
		let month = ("0" + (d.getMonth() + 1)).slice(-2);
		let year = d.getFullYear();
		$scope.x.inv_date = day + "/" + month + "/" + year;
		// end of setting current date
	}
	$scope.init();
	$scope.generatedRows = [];

	$('.date').datepicker({
		format: 'dd/mm/yyyy',
		autoclose: true
	});
	$scope.today_date();

	$scope.update_call = function (y) {
		$scope.x = y;
		$scope.q_id = y.q_id;
		$scope.get_plans_to_temp(y.invoice_id);
	}

	$scope.get_plans_to_temp = function (invoice_id) {
		$http.get(rootUrl + module + '/copy_plans_to_temp?invoice_id=' + invoice_id).success(function (data) {
			console.log(data);
			if (data == 1) {
				$http.get(rootUrl + module + "/get_temp_plans").success(function (data) {
					$scope.invoice_plans = data;
					let total = 0;
					angular.forEach($scope.invoice_plans, function (plan, index) {
						// console.log('plan: ', plan);
						total += parseFloat(plan.sp);
					});
					$scope.x.plan_cost = total;
				});


			}
		});
	}

	$scope.get_proforma_plans_details = function (invoice_id) {
		$http.get(rootUrl + module + '/get_invoice_details?invoice_id=' + invoice_id).success(function (data) {
			if (!$scope.invoice_plans_data) {
				$scope.invoice_plans_data = [];
			}
			$scope.invoice_plans_data = data;
			console.log(data);
		});
	}

	$scope.plan_selected = function (y) {
		$http.get(rootUrl + 'plan_master/view?plan_id=' + y).success(function (data) {
			if (!$scope.selected) {
				$scope.selected = {}; // initialize if empty
			}
			angular.extend($scope.selected, data[0]); // merge new keys/values
			$scope.selected.unit = 1;

			// ✅ Calculate discount only if both values exist
			$scope.calculateDiscount();
		});

	}

	$scope.filter_new = function () {
		$scope.x = {};
		$scope.temp_data = {};
		$scope.invoice_plans = {};
		$state.go('invoice_view');
		$http.get(rootUrl + module + '/delete_temp_plans').success(function (data) {
			if (data == 1) {
				messages('success', 'Success', 'Plan Deleted Successfully.', 3000);
			} else {
				messages('danger', 'Danger', 'Plan Could Not Be Deleted.', 3000);
			}
		});

	}

	$scope.filter_plans = function () {
		$scope.selected = {};
		$scope.generatedRows = {};
	}

	$scope.$watchGroup(['x.c_id', 'x.project_id'], function (value) {
		let c_id = value[0];
		let com_id = value[1];
		if (c_id) {
			$http.get(rootUrl + 'customer/view?c_id=' + c_id).success(function (data) {
				$scope.cust_state = data[0]['state'];
				if ($scope.com_gst) {
					if ($scope.com_state && $scope.cust_state) {
						$scope.x.gst = ($scope.com_state === $scope.cust_state)
							? "cgst_sgst"
							: "igst";
					}
				} else {
					$scope.x.gst = "";
				}

			});
		}
		if (com_id) {
			$http.get(rootUrl + 'company_master/view?id=' + com_id + '&data=gst_no,state').success(function (data) {
				$scope.com_gst = data[0]['gst_no'];
				$scope.com_state = data[0]['state'];
				console.log('gst', $scope.com_gst);
				if ($scope.com_gst) {
					if ($scope.com_state && $scope.cust_state) {
						$scope.x.gst = ($scope.com_state === $scope.cust_state)
							? "cgst_sgst"
							: "igst";
					}
				} else {
					$scope.x.gst = "";
				}
			});
		}
	});

	$scope.save_data = function (x) {
		$('#proformainvoicebtn').attr('disabled', true);
		$.ajax({
			type: "POST",
			url: rootUrl + module + "/save",
			data: $('#invoice_form').serialize(),
			beforeSend: function () {
				$('#loader').css('display', 'inline');
			},
			success: function (data) {
				if (data == "1") {
					messages("success", "Success!", "invoice Saved Successfully", 3000);
					$scope.filter_new();
					$scope.temp_data = {};
					$scope.invoice_plans = {};
					$scope.today_date();
				} else if (data == '2') {
					messages('success', 'Success!', "Data Updated Successfully", 4000);
					$scope.filter_new();
					$scope.temp_data = {};
					$scope.invoice_plans = {};
					$scope.today_date();
				}
				else if (data == "0") {
					messages("warning", "Info!", "No Data Affected", 3000);
				}
				else {
					messages("danger", "Warning!", data, 6000);
				}
				$('#loader').css('display', 'none');
				$('#proformainvoicebtn').attr('disabled', false);
			}
		});
	}

	// /temp data
	$scope.get_temp_plans = function () {
		$http.get(rootUrl + module + "/get_temp_plans").success(function (data) {
			$scope.invoice_plans = data;
			$timeout(function () {
				let total = 0;
				angular.forEach($scope.invoice_plans, function (plan, index) {
					console.log('plan: ', plan);
					total += parseFloat(plan.sp);
				});
				$scope.x.plan_cost = total;
			}, 500);
		});
	}

	$scope.add_plans = function (a, row) {
		if (a) {
			// Updating plan to existing proforma
			$http.post(rootUrl + module + "/add_plans", { plans: a, invoice_id: $scope.x.invoice_id, installments: $scope.generatedRows }).success(function (data) {
				if (data == '1') {
					messages('success', 'Success!', 'Plans Added Successfully', 3000);
					$scope.filter_plans();
					$scope.get_temp_plans();
				} else if (data == '2') {
					messages('success', 'Success!', 'Plans Updated Successfully', 3000);
					$scope.filter_plans();
					$scope.get_temp_plans();

				} else {
					messages('warning', 'Warning!', 'No Data Affected', 3000);
				}
			});
		} else {
			messages('warning', 'Warning!', 'Please Fill Out The Details', 3000);
		}
	};

	$scope.edit_plan = function (p) {
		console.log('p', p.plan_id);
		$scope.selected = p;
		$scope.selected.plan = p.plan_id;
		$scope.generatedRows = p.installments;

	}
	$scope.delete_plan = function (p) {
		console.log(p);
		if (confirm("Are you sure you want to delete this plan?")) {
			$http.get(rootUrl + module + '/delete_temp_plans?id=' + p.temp_ip_id).success(function (data) {
				if (data == 1) {
					messages('success', 'Success', 'Plan Deleted Successfully.', 3000);
					$scope.get_temp_plans();
				} else {
					messages('danger', 'Danger', 'Plan Could Not Be Deleted.', 3000);
				}
			});
		}
	};

	$scope.calculateDiscount = function (unitForm = false) {
		if ($scope.selected && $scope.selected.mrp && $scope.selected.unit && $scope.selected.sp) {
			const mrp = parseFloat($scope.selected.mrp);
			const unit = parseFloat($scope.selected.unit);
			const sp = parseFloat($scope.selected.sp);

			if (!isNaN(mrp) && !isNaN(sp) && !isNaN(unit)) {
				let price = mrp * unit;
				if (price > sp) {
					if (unitForm === true) {
						$scope.selected.sp = price;
						$scope.selected.discount = 0;
					} else {
						$scope.selected.discount = price - sp;
					}
				} else {
					$scope.selected.discount = 0;
				}

			} else {
				$scope.selected.discount = '';
			}
		} else {
			$scope.selected.discount = '';
		}
	};

	$scope.unit_change = function () {
		if ($scope.selected && $scope.selected.type && $scope.selected.type == 'One TIme') {
			let num = parseFloat($scope.selected.unit) || 0;
			if (!$scope.generatedRows) {
				$scope.generatedRows = [];
			}
			// console.log('generated:', $scope.generatedRows);
			if ($scope.generatedRows.length === 0) {
				for (i = 1; i <= num; i++) {
					let row = {
						title: "",
						percent: "",
						amount: "",
						due_date: ""
					};
					$('.datepicker').datepicker();

					if (i === 1) {
						let today = new Date();
						let dd = String(today.getDate()).padStart(2, '0');
						let mm = String(today.getMonth() + 1).padStart(2, '0');
						let yyyy = today.getFullYear();

						row.due_date = dd + '/' + mm + '/' + yyyy;
					}

					$scope.generatedRows.push(row);
				}
			} else {
				actualNum = num - $scope.generatedRows.length;
				for (i = 1; i <= actualNum; i++) {
					$scope.generatedRows.push({
						title: "",
						percent: "",
						amount: "",
						due_date: ""
					});
				}
			}

		} else if ($scope.selected && $scope.selected.unit && $scope.selected.mrp) {
			$scope.calculateDiscount(true);
		}
	}

	// $scope.calculate_total = function (plans) {
	// 	if (!$scope.x) {
	// 		$scope.x = {};
	// 	}
	// 	let total = 0;
	// 	angular.forEach(plans, function (plan, index) {
	// 		total += parseFloat(plan.sp) || 0;
	// 	});
	// 	$scope.x.plan_cost = total;
	// 	$scope.x.pay_amount = total;
	// }


	$scope.$watch('x.project_id', function (newVal) {
		let new_com_id = newVal;
		// console.log('sdfedf:',new_com_id);
		if (new_com_id !== undefined && new_com_id !== null && new_com_id !== '') {
			// $http.get(rootUrl + "company_master/view?id="+new_com_id+"&data=invoice_unique_no,invoice_prefix").success(function (data) {
			// 	if (data.length === 1) {
			// 		$scope.unique_no = data[0]['invoice_unique_no'];
			// 		$scope.prefix = data[0]['invoice_prefix'];
			// 		$http.get(rootUrl + module + "/view?project_id="+new_com_id).success(function(data1){
			// 			if (data1.length === 1){
			// 				// $scope.recent_invoice_no = data1[0]['invoice_number'];
			// 				// let numberPart = parseInt($scope.recent_invoice_no.replace(/\D/g, ''));  
			// 				// $scope.x.invoice_number = $scope.prefix + (numberPart+1);
			// 				// console.log($scope.recent_invoice_no);
			// 				if ($scope.prefix){
			// 					$scope.recent_invoice_no = data1[0]['invoice_number'];
			// 					let numberPart = parseInt($scope.recent_invoice_no.replace(/\D/g, ''));  
			// 					$scope.x.invoice_number = $scope.prefix + (numberPart+1);
			// 					console.log($scope.recent_quotation_no);
			// 				} else {
			// 					$scope.recent_invoice_no = data1[0]['invoice_number']; 
			// 					$scope.x.invoice_number = parseInt($scope.recent_invoice_no) + 1;
			// 				}
			// 			} else if (data1.length === 0){
			// 				// $scope.x.invoice_number = $scope.prefix + $scope.unique_no;
			// 				if ($scope.prefix){
			// 					if($scope.unique_no){
			// 						$scope.x.invoice_number = $scope.prefix + $scope.unique_no;
			// 					} else {
			// 						$scope.x.invoice_number = $scope.prefix + '1';
			// 					}

			// 				} else {
			// 					if ($scope.unique_no){
			// 						$scope.x.invoice_number = ($scope.unique_no == '0') ? 1 : $scope.unique_no;
			// 					} else {
			// 						$scope.x.invoice_number = 1;
			// 					}
			// 				}
			// 			} else {
			// 				// $scope.recent_invoice_no = data1[0]['invoice_number'];
			// 				// let numberPart = parseInt($scope.recent_invoice_no.replace(/\D/g, ''));  
			// 				// $scope.x.invoice_number = $scope.prefix + (numberPart + 1);
			// 				if ($scope.prefix){
			// 					$scope.recent_invoice_no = data1[0]['invoice_number'];
			// 					let numberPart = parseInt($scope.recent_invoice_no.replace(/\D/g, ''));  
			// 					$scope.x.invoice_number = $scope.prefix + (numberPart + 1);
			// 				} else {
			// 					$scope.recent_invoice_no = data1[0]['invoice_number']; 
			// 					$scope.x.invoice_number = parseInt($scope.recent_invoice_no) + 1;
			// 				}
			// 			}
			// 		})
			// 	}
			// });
			$http.get(rootUrl + "company_master/view?id=" + new_com_id + "&data=invoice_unique_no,invoice_prefix")
				.success(function (data) {

					if (data.length === 1) {
						$scope.unique_no = data[0]['invoice_unique_no'] || 1;
						$scope.prefix = data[0]['invoice_prefix'] || '';

						// function to pad number → 0001 format
						function padNumber(num) {
							return String(num).padStart(4, '0');
						}

						$http.get(rootUrl + module + "/view?project_id=" + new_com_id)
							.success(function (data1) {

								let newNumber;

								// 👉 CASE 1: No previous invoice
								if (data1.length === 0) {

									newNumber = padNumber($scope.unique_no);

								} else {

									let lastInvoice = data1[0]['invoice_number'] || '';

									if ($scope.prefix) {

										// 👉 Check if prefix matches
										if (lastInvoice.startsWith($scope.prefix)) {

											// remove prefix → get number
											let numberPart = lastInvoice.replace($scope.prefix, '');
											numberPart = parseInt(numberPart) || 0;

											newNumber = padNumber(numberPart + 1);

										} else {

											// prefix changed → reset
											newNumber = padNumber($scope.unique_no);

										}

									} else {

										// 👉 No prefix case
										let numberPart = parseInt(lastInvoice) || 0;
										newNumber = numberPart + 1;

									}
								}

								// 👉 Final invoice number
								$scope.x.invoice_number = $scope.prefix
									? $scope.prefix + newNumber
									: newNumber;

							});
					}
				});
		}
	});

	$scope.$watch('x.plan_cost', function (newVal) {
		let new_cost = newVal;

		if (new_cost !== undefined && new_cost !== null && new_cost !== '') {
			let cost = parseFloat(new_cost) || 0;

			if ($scope.x.gst === 'cgst_sgst') {

				let cgstPer = 9, sgstPer = 9;

				$scope.x.cgst = $scope.percent(cost, cgstPer);
				$scope.x.sgst = $scope.percent(cost, sgstPer);

				$scope.x.pay_amount = cost + $scope.x.cgst + $scope.x.sgst;

			} else if ($scope.x.gst === 'igst') {

				let igstPer = 18;

				$scope.x.igst = $scope.percent(cost, igstPer);
				$scope.x.pay_amount = cost + $scope.x.igst;
			} else {
				$scope.x.pay_amount = cost
			}

			return; // Stop here, do not run next block
		}
	});


	$scope.$watch('x.pay_amount', function (newVal, oldVal) {
		if (!newVal) return;

		let pay = parseFloat(newVal);

		// Reverse calculate amount excluding tax
		$scope.x.amt_extax = pay / 1.18;
		$scope.x.due = $scope.x.plan_cost - $scope.x.amt_extax

		if ($scope.x.gst === 'cgst_sgst') {
			let diff = pay - $scope.x.amt_extax;
			$scope.x.cgst = diff / 2;
			$scope.x.sgst = diff / 2;
		}

		else if ($scope.x.gst === 'igst') {
			$scope.x.igst = pay - $scope.x.amt_extax;
		}
	});


	$scope.percent = function (value, rate) {
		return parseFloat((value * rate) / 100);
	};

	$scope.generate_pdf = function (id, download) {
		$scope.ID = id;
		$scope.isDownload = download;
		if ($scope.ID) {
			const url = rootUrl + module + `/generate_pdf?download=${$scope.isDownload}&id=${$scope.ID}`;
			window.open(url, "_blank");
		}
	}

	$scope.options = {
		height: 200,
		toolbar: [
			// Remove 'style' button group completely
			['font', ['bold', 'italic', 'underline']],
			['para', ['ol']],
			['insert', ['link']],
			['view', ['codeview']],
			['para', ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull']]
		]
	};

	$scope.cleanHTML = function (html) {
		return html ? html.replace(/<[^>]+>/g, '') : '';
	};

}]);app.controller('proforma_invoice', ['$scope', '$rootScope', '$http', '$timeout', '$state', '$stateParams', function ($scope, $rootScope, $http, $timeout, $state, $stateParams) {
	let module = 'proforma_invoice';
	let rootUrl = $rootScope.site_url;
	let select2Selectors = '#proforma_company_select, #proforma_customer_select, #proforma_plan_select';
	$http.get(rootUrl + module + "/index").success(function (data) { if (data == 0) { window.location.assign('login.html'); } else if (data == 2) { messages("success", "Privilege not assigned.", 1000); window.location.assign('index.html'); } });

	$scope.initSelect2 = function () {
		$timeout(function () {
			if (!$.fn.select2) {
				return;
			}

			$(select2Selectors).each(function () {
				let $select = $(this);
				if ($select.data('select2')) {
					$select.select2('destroy');
				}
				$select.select2({
					width: '100%'
				});
			});
		}, 0);
	};
	$scope.q_id = $stateParams.q_id;
	$scope.init = function () {
		$http.get(rootUrl + "customer/view?data=name,c_id").success(function (data) {
			if (data.length === 1) {
				$scope.x.c_id = data[0]['c_id'];
				$scope.customers = data;
			} else {
				$scope.customers = data;
			}
			$scope.initSelect2();
		});
		$http.get(rootUrl + "company_master/view?data=name,com_id").success(function (data) {
			if (data.length == 1) {
				$scope.x.project_id = data[0]['com_id'];
				$scope.companies = data;
			} else {
				$scope.companies = data;
			}
			$scope.companies = data;
			$scope.initSelect2();
		});
		$http.get(rootUrl + "plan_master/view").success(function (data) {
			$scope.plan_data = data;
			// console.log('plans', data);
			$scope.initSelect2();
		});
		$http.get(rootUrl + module + "/view").success(function (data) {
			$scope.datadb = data;
			// console.log('datadb:', $scope.datadb);
		});
		// Fetching Quotation Data if proforma_invoice is generated from quotation
		if ($scope.q_id) {
			$http.get(rootUrl + 'quotation/view?q_id=' + $scope.q_id).success(function (data) {
				// console.log(data);
				$scope.x = data[0];
				$scope.today_date();

			});
			$http.get(rootUrl + 'quotation/get_quotation_details?q_id=' + $scope.q_id + '&data=discount,mrp,plan_id as plan,plan_id,sp,subscription,type,unit').success(function (data) {
				
				$http.post(rootUrl + module + '/save_temp_plans', { plans: data }).success(function (data) {
					if (data == 1) {
						$http.get(rootUrl + module + "/get_temp_plans").success(function (data) {
							$scope.proforma_invoice_plans = data;
							let total = 0;
							angular.forEach($scope.proforma_invoice_plans, function (plan, index) {
								console.log('plan: ', plan);
								total += parseFloat(plan.sp);
							});
							$scope.x.plan_cost = total;
						});
					}
				});
			});

		}
	}

	$scope.today_date = function () {
		// setting the current date as default
		$scope.x = $scope.x || {};
		let d = new Date();
		let day = ("0" + d.getDate()).slice(-2);
		let month = ("0" + (d.getMonth() + 1)).slice(-2);
		let year = d.getFullYear();
		$scope.x.invoice_date = day + "/" + month + "/" + year;
		// end of setting current date
	}
	$scope.init();
	$scope.generatedRows = [];

	$('.date').datepicker({
		format: 'dd/mm/yyyy',
		autoclose: true
	});
	$scope.today_date();

	$scope.update_call = function (y) {
		$scope.x = y;
		$scope.q_id = y.q_id;
		$scope.get_plans_to_temp(y.proforma_id);
	}

	$scope.get_plans_to_temp = function (proforma_id) {
		$http.get(rootUrl + module + '/copy_plans_to_temp?proforma_id=' + proforma_id).success(function (data) {
			console.log(data);
			if (data == 1) {
				$http.get(rootUrl + module + "/get_temp_plans").success(function (data) {
					$scope.proforma_invoice_plans = data;
					let total = 0;
					angular.forEach($scope.proforma_invoice_plans, function (plan, index) {
						// console.log('plan: ', plan);
						total += parseFloat(plan.sp);
					});
					$scope.x.plan_cost = total;
				});


			}
		});
	}

	$scope.get_proforma_plans_details = function (proforma_id) {
		$http.get(rootUrl + module + '/get_proforma_invoice_details?proforma_id=' + proforma_id).success(function (data) {
			if (!$scope.proforma_invoice_plans_data) {
				$scope.proforma_invoice_plans_data = [];
			}
			$scope.proforma_invoice_plans_data = data;
			// console.log(data);
		});
	}

	$scope.plan_selected = function (y) {
		$http.get(rootUrl + 'plan_master/view?plan_id=' + y).success(function (data) {
			if (!$scope.selected) {
				$scope.selected = {}; // initialize if empty
			}
			angular.extend($scope.selected, data[0]); // merge new keys/values
			$scope.selected.unit = 1;

			// ✅ Calculate discount only if both values exist
			$scope.calculateDiscount();
		});

	}

	$scope.filter_new = function () {
		$scope.x = {};
		$scope.temp_data = {};
		$scope.proforma_invoice_plans = {};
		$state.go('proforma_invoice_view');
		$scope.initSelect2();
		$http.get(rootUrl + module + '/delete_temp_plans').success(function (data) {
			if (data == 1) {
				messages('success', 'Success', 'Plan Deleted Successfully.', 3000);
			} else {
				messages('danger', 'Danger', 'Plan Could Not Be Deleted.', 3000);
			}
		});

	}

	$scope.filter_plans = function () {
		$scope.selected = {};
		$scope.generatedRows = {};
		$scope.initSelect2();
	}

	$scope.$watchGroup(['x.c_id', 'x.project_id'], function (value) {
		let c_id = value[0];
		let com_id = value[1];
		if (c_id) {
			$http.get(rootUrl + 'customer/view?c_id=' + c_id).success(function (data) {
				$scope.cust_state = data[0]['state'];
				if ($scope.com_gst) {
					if ($scope.com_state && $scope.cust_state) {
						$scope.x.gst = ($scope.com_state === $scope.cust_state)
							? "cgst_sgst"
							: "igst";
					}
				} else {
					$scope.x.gst = "";
				}

			});
		}
		if (com_id) {
			$http.get(rootUrl + 'company_master/view?id=' + com_id + '&data=gst_no,state').success(function (data) {
				$scope.com_gst = data[0]['gst_no'];
				$scope.com_state = data[0]['state'];
				console.log('gst',$scope.com_gst);
				if ($scope.com_gst) {
					if ($scope.com_state && $scope.cust_state) {
						$scope.x.gst = ($scope.com_state === $scope.cust_state)
							? "cgst_sgst"
							: "igst";
					}
				} else {
					$scope.x.gst = "";
				}
			});
		}
	});

	$scope.save_data = function (x) {
		$('#proformainvoicebtn').attr('disabled', true);
		$.ajax({
			type: "POST",
			url: rootUrl + module + "/save",
			data: $('#proforma_invoice_form').serialize(),
			beforeSend: function () {
				$('#loader').css('display', 'inline');
			},
			success: function (data) {
				if (data == "1") {
					messages("success", "Success!", "proforma_invoice Saved Successfully", 3000);
					$scope.filter_new();
					$scope.temp_data = {};
					$scope.proforma_invoice_plans = {};
					$scope.today_date();
					$scope.init();
				} else if (data == '2') {
					messages('success', 'Success!', "Data Updated Successfully", 4000);
					$scope.filter_new();
					$scope.temp_data = {};
					$scope.proforma_invoice_plans = {};
					$scope.today_date();
					$scope.init();
				}
				else if (data == "0") {
					messages("warning", "Info!", "No Data Affected", 3000);
				}
				else {
					messages("danger", "Warning!", data, 6000);
				}
				$('#loader').css('display', 'none');
				$('#proformainvoicebtn').attr('disabled', false);
			}
		});
	}

	// /temp data
	$scope.get_temp_plans = function () {
		$http.get(rootUrl + module + "/get_temp_plans").success(function (data) {
			$scope.proforma_invoice_plans = data;
			$timeout(function () {
				let total = 0;
				angular.forEach($scope.proforma_invoice_plans, function (plan, index) {
					console.log('plan: ', plan);
					total += parseFloat(plan.sp);
				});
				$scope.x.plan_cost = total;
			}, 500);
		});
	}

	$scope.add_plans = function (a, row) {
		if (a) {
			// Updating plan to existing proforma
			$http.post(rootUrl + module + "/add_plans", { plans: a, proforma_id: $scope.x.proforma_id, installments: $scope.generatedRows }).success(function (data) {
				if (data == '1') {
					messages('success', 'Success!', 'Plans Added Successfully', 3000);
					$scope.filter_plans();
					$scope.get_temp_plans();
				} else if (data == '2') {
					messages('success', 'Success!', 'Plans Updated Successfully', 3000);
					$scope.filter_plans();
					$scope.get_temp_plans();

				} else {
					messages('warning', 'Warning!', 'No Data Affected', 3000);
				}
			});
		} else {
			messages('warning', 'Warning!', 'Please Fill Out The Details', 3000);
		}
	};

	$scope.edit_plan = function (p) {
		console.log('p', p.plan_id);
		$scope.selected = p;
		$scope.selected.plan = p.plan_id;
		$scope.generatedRows = p.installments;
		$scope.initSelect2();
	}
	$scope.delete_plan = function (p) {
		console.log(p.temp_p_id);
		if (confirm("Are you sure you want to delete this plan?")) {
			$http.get(rootUrl + module + '/delete_temp_plans?id=' + p.temp_p_id).success(function (data) {
				if (data == 1) {
					messages('success', 'Success', 'Plan Deleted Successfully.', 3000);
					$scope.get_temp_plans();
				} else {
					messages('danger', 'Danger', 'Plan Could Not Be Deleted.', 3000);
				}
			});
		}
	};

	$scope.calculateDiscount = function (unitForm = false) {
		if ($scope.selected && $scope.selected.mrp && $scope.selected.unit && $scope.selected.sp) {
			const mrp = parseFloat($scope.selected.mrp);
			const unit = parseFloat($scope.selected.unit);
			const sp = parseFloat($scope.selected.sp);

			if (!isNaN(mrp) && !isNaN(sp) && !isNaN(unit)) {
				let price = mrp * unit;
				if (price > sp) {
					if (unitForm === true) {
						$scope.selected.sp = price;
						$scope.selected.discount = 0;
					} else {
						$scope.selected.discount = price - sp;
					}
				} else {
					$scope.selected.discount = 0;
				}

			} else {
				$scope.selected.discount = '';
			}
		} else {
			$scope.selected.discount = '';
		}
	};

	$scope.unit_change = function () {
		if ($scope.selected && $scope.selected.type && $scope.selected.type == 'One TIme') {
			let num = parseFloat($scope.selected.unit) || 0;
			if (!$scope.generatedRows) {
				$scope.generatedRows = [];
			}
			// console.log('generated:', $scope.generatedRows);
			if ($scope.generatedRows.length === 0) {
				for (i = 1; i <= num; i++) {
					let row = {
						title: "",
						percent: "",
						amount: "",
						due_date: ""
					};
					$('.datepicker').datepicker();

					if (i === 1) {
						let today = new Date();
						let dd = String(today.getDate()).padStart(2, '0');
						let mm = String(today.getMonth() + 1).padStart(2, '0');
						let yyyy = today.getFullYear();

						row.due_date = dd + '/' + mm + '/' + yyyy;
					}

					$scope.generatedRows.push(row);
				}
			} else {
				actualNum = num - $scope.generatedRows.length;
				for (i = 1; i <= actualNum; i++) {
					$scope.generatedRows.push({
						title: "",
						percent: "",
						amount: "",
						due_date: ""
					});
				}
			}

		} else if ($scope.selected && $scope.selected.unit && $scope.selected.mrp) {
			$scope.calculateDiscount(true);
		}
	}

	// $scope.calculate_total = function (plans) {
	// 	if (!$scope.x) {
	// 		$scope.x = {};
	// 	}
	// 	let total = 0;
	// 	angular.forEach(plans, function (plan, index) {
	// 		total += parseFloat(plan.sp) || 0;
	// 	});
	// 	$scope.x.plan_cost = total;
	// 	$scope.x.pay_amount = total;
	// }



	$scope.$watch('x.plan_cost', function (newVal) {
		let new_cost = newVal;

		if (new_cost !== undefined && new_cost !== null && new_cost !== '') {
			let cost = parseFloat(new_cost) || 0;

			if ($scope.x.gst === 'cgst_sgst') {

				let cgstPer = 9, sgstPer = 9;

				$scope.x.cgst = $scope.percent(cost, cgstPer);
				$scope.x.sgst = $scope.percent(cost, sgstPer);

				$scope.x.pay_amount = cost + $scope.x.cgst + $scope.x.sgst;

			} else if ($scope.x.gst === 'igst') {

				let igstPer = 18;

				$scope.x.igst = $scope.percent(cost, igstPer);
				$scope.x.pay_amount = cost + $scope.x.igst;
			} else {
				$scope.x.pay_amount = cost
			}

			return; // Stop here, do not run next block
		}
	});


	$scope.$watch('x.pay_amount', function (newVal, oldVal) {
		if (!newVal) return;

		let pay = parseFloat(newVal);

		// Reverse calculate amount excluding tax
		$scope.x.amt_extax = pay / 1.18;
		$scope.x.due = $scope.x.plan_cost - $scope.x.amt_extax

		if ($scope.x.gst === 'cgst_sgst') {
			let diff = pay - $scope.x.amt_extax;
			$scope.x.cgst = diff / 2;
			$scope.x.sgst = diff / 2;
		}

		else if ($scope.x.gst === 'igst') {
			$scope.x.igst = pay - $scope.x.amt_extax;
		}
	});


	$scope.percent = function (value, rate) {
		return parseFloat((value * rate) / 100);
	};

	$scope.generate_pdf = function (id, download) {
		$scope.ID = id;
		$scope.isDownload = download;
		if ($scope.ID) {
			const url = rootUrl + module + `/generate_pdf?download=${$scope.isDownload}&id=${$scope.ID}`;
			window.open(url, "_blank");
		}
	}

	$scope.generate_invoice = function(id){
		$state.go('invoice',{proforma_id: id});
	}

	$scope.options = {
		height: 200,
		toolbar: [
			// Remove 'style' button group completely
			['font', ['bold', 'italic', 'underline']],
			['para', ['ol']],
			['insert', ['link']],
			['view', ['codeview']],
			['para', ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull']]
		]
	};

	$scope.cleanHTML = function (html) {
		return html ? html.replace(/<[^>]+>/g, '') : '';
	};

	$scope.$watchCollection('companies', function () {
		$scope.initSelect2();
	});

	$scope.$watchCollection('customers', function () {
		$scope.initSelect2();
	});

	$scope.$watchCollection('plan_data', function () {
		$scope.initSelect2();
	});

	$scope.$watchGroup(['x.project_id', 'x.c_id', 'selected.plan'], function () {
		$scope.initSelect2();
	});

	$scope.$on('$destroy', function () {
		if ($.fn.select2) {
			$(select2Selectors).each(function () {
				let $select = $(this);
				if ($select.data('select2')) {
					$select.select2('destroy');
				}
			});
		}
	});

}]);app.controller('service_master', ['$scope', '$rootScope', '$http', '$timeout', '$stateParams', '$state', function ($scope, $rootScope, $http, $timeout, $stateParams, $state) {
	module = 'service_master';
	rootUrl = $rootScope.site_url;
	$http.get(rootUrl + module + "/index").success(function (data) { if (data == 0) { window.location.assign('login.html'); } else if (data == 2) { messages("success", "Privilege not assigned.", 1000); window.location.assign('index.html'); } });
	
	$scope.init = function () {
		$http.get(rootUrl + module + "/view?data=name,service_id").success(function (data) {
			$scope.datadb = data;
		})
	}
	$scope.init();

	$scope.save_data = function (x) {
		$('#servicebtn').attr('disabled', true);
		$.ajax({
			type: "POST",
			url: rootUrl + module + "/save",
			data: $("#service_details").serialize(),
			dataType: "json",
			beforeSend: function () {
				$('#loader').css('display', 'inline');
			},
			success: function (data) {
				console.log(data.status);
				if (data.status == "success") {
					messages("success", "Success!", data.msg, 3000);
					$scope.init();
					$scope.filter_new();
				}
				else if (data.status == "warning") {
					messages("warning", "Info!", data.msg, 3000);
				}
				else {
					messages("danger", "Warning!", data.msg, 6000);
				}
				$('#loader').css('display', 'none');
				$('#planbtn').attr('disabled', false);
			}
		});
	} 

	$scope.update_call = function(y){
		$scope.x = y;
		$http.get(rootUrl + module + "/view?service_id="+y.service_id).success(function (data) {
			$scope.x = data[0];
		})
	}

	$scope.filter_new = function(){
		$scope.x = {};
	}

	$scope.options = {
		height: 200,
		toolbar: [
		  // Remove 'style' button group completely
		  ['font', ['bold', 'italic', 'underline']],
		  ['para', ['ol', 'paragraph']],
		  ['insert', ['link']],
		  ['view', ['codeview']]
		]
	  };
	  
}]);//blank line is required
app.controller('project_assign', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) {

	rootUrl = $rootScope.site_url;
	module = "project_assign/";
	$http.get(rootUrl + module + "/index").success(function (data) { if (data == 0) { window.location.assign('login.html'); } else if (data == 2) { messages("success", "Privilege not assigned.", 1000); window.location.assign('index.html'); } });

	function initProjectAssignSelect2() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
			return;
		}

		setTimeout(function () {
			var $modal = $('#projectAssignModal');
			var isSelect2V4 = !!($.fn.select2 && $.fn.select2.amd);

			$('.project-assign-select2').each(function () {
				var $el = $(this);
				var inModal = $el.closest('#projectAssignModal').length > 0;

				if (!$el.is('select')) {
					return;
				}

				if ($el.data('select2')) {
					$el.select2('destroy');
				}

				var options = {
					width: '100%',
					allowClear: false,
					minimumResultsForSearch: 0
				};

				if ($el.prop('multiple')) {
					options.closeOnSelect = false;
				}

				if (isSelect2V4) {
					options.dropdownParent = inModal ? $modal : $(document.body);
				}

				$el.select2(options);
			});
		}, 0);
	}

	function allowSelect2TypingInsideModal() {
		if (typeof $ === 'undefined' || !$.fn || !$.fn.modal || !$.fn.modal.Constructor) {
			return;
		}

		var ModalConstructor = $.fn.modal.Constructor;
		if (ModalConstructor.prototype._projectAssignSelect2FocusPatched) {
			return;
		}

		ModalConstructor.prototype.enforceFocus = function () {
			var modalThis = this;
			$(document)
				.off('focusin.bs.modal')
				.on('focusin.bs.modal', function (e) {
					var $target = $(e.target);
					var isInsideModal = modalThis.$element[0] === e.target || modalThis.$element.has(e.target).length;
					var isSelect2Input =
						$target.closest('.select2-container, .select2-dropdown, .select2-drop, .select2-search').length > 0 ||
						$target.is('.select2-input, .select2-search__field');

					if (!isInsideModal && !isSelect2Input) {
						modalThis.$element.trigger('focus');
					}
				});
		};

		ModalConstructor.prototype._projectAssignSelect2FocusPatched = true;

		$(document).off('select2:open.projectAssign select2-open.projectAssign');
		$(document).on('select2:open.projectAssign select2-open.projectAssign', function () {
			setTimeout(function () {
				var $search = $('.select2-container-active .select2-input, .select2-drop-active .select2-input, .select2-container--open .select2-search__field');
				if ($search.length) {
					$search.focus();
				}
			}, 0);
		});
	}

	$scope.on_employee_change = function (emp_id) {
		$http.get(rootUrl + 'project_assign/get_cust?emp_id=' + emp_id).success(function (data) {
			$scope.projects = data || [];
			initProjectAssignSelect2();
		});
	}

	$scope.pageno = 1;
	$scope.total_count = 0;
	$scope.itemsPerPage = '15';
	$scope.qx = {};
	$scope.x = { emp_id: [] };
	$scope.datadb = [];
	$scope.project_assign_modal_title = "Add Project Assign";

	$scope.loader = function (pageno) {
		if (!pageno)
			pageno = 1;
		$scope.pageno = pageno;

		var params = [];

		if ($scope.qx.emp_id)
			params.push("emp_id=" + encodeURIComponent($scope.qx.emp_id));
		if ($scope.qx.project_id)
			params.push("project_id=" + encodeURIComponent($scope.qx.project_id));
		if ($scope.qx.status !== undefined && $scope.qx.status !== '')
			params.push("status=" + encodeURIComponent($scope.qx.status));

		var url = rootUrl + "project_assign/view/" + $scope.itemsPerPage + "/" + pageno;
		if (params.length)
			url += "?" + params.join("&");

		$http.get(url).success(function (response) {
			if (response && response.data !== undefined) {
				$scope.datadb = response.data;
				$scope.total_count = response.total_count || 0;
			}
			else {
				$scope.datadb = response || [];
				$scope.total_count = ($scope.datadb || []).length;
			}
			initProjectAssignSelect2();
		});
	};

	$scope.apply_filters = function () {
		$scope.loader(1);
	};

	$scope.clear_filters = function () {
		$scope.qx = {};
		$scope.itemsPerPage = '15';
		$scope.loader(1);
	};

	$scope.on_items_per_page_change = function () {
		$scope.loader(1);
	};

	$http.get(rootUrl + "hr_staff_details/view?data=emp_id,staff_name&st=1").success(function (data) {
		$scope.employees = data;
		initProjectAssignSelect2();
	});

	$http.get(rootUrl + "customer/view?data=c_id,company_name&status=1").success(function (data) {
		$scope.customers = data;
		$scope.projects = data || [];
		initProjectAssignSelect2();
	});

	// $http.get(rootUrl + 'customer/view').success(function (data) {
	// 	$scope.projects = data || [];
	// 	initProjectAssignSelect2();
	// });

	function normalizeEmpIds(value) {
		if (angular.isArray(value)) {
			return value.map(function (v) { return String(v); });
		}
		if (value === undefined || value === null || value === '') {
			return [];
		}
		return [String(value)];
	}

	$scope.update_call = function (y) {
		$scope.x = angular.copy(y);
		$scope.x.emp_id = normalizeEmpIds($scope.x.emp_id);
	}

	$scope.open_project_assign_modal = function (mode, y) {
		if (mode == "edit" && y) {
			$scope.project_assign_modal_title = "Edit Project Assign";
			$scope.update_call(y);
		}
		else {
			$scope.project_assign_modal_title = "Add Project Assign";
			$scope.filter_new(false);
		}
		$('#projectAssignModal').modal('show');
		initProjectAssignSelect2();
	}

	$scope.filter_new = function (refreshList) {
		$scope.x = { emp_id: [] };
		initProjectAssignSelect2();
		if (refreshList !== false)
			$scope.loader($scope.pageno || 1);
	}

	$scope.save_data = function (x) {
		function normalizeResponse(data) {
			if (data === undefined || data === null) {
				return '';
			}
			return String(data).trim();
		}

		function isAssignedSuccessMessage(msg) {
			var lower = (msg || '').toLowerCase();
			return lower.indexOf('successfully assigned') !== -1 || lower.indexOf('remaining employees are assigned') !== -1;
		}

		$('#submitbtn').attr('disabled', true);
		$.ajax({
			type: "POST",
			url: rootUrl + "project_assign/save_data",
			data: $("#form1").serialize(),
			beforeSend: function () {
				$('#webprogress').css('display', 'inline');
			},
			success: function (data) {
				var response = normalizeResponse(data);

				if (response == "1") {
					messages("success", "Success!", "Project Assigned Successfully", 4000);
					$scope.loader($scope.pageno || 1);
					$scope.filter_new(false);
					$('#projectAssignModal').modal('hide');
				}
				else if (isAssignedSuccessMessage(response)) {
					messages("success", "Success!", response, 6000);
					$scope.loader($scope.pageno || 1);
					$scope.filter_new(false);
					$('#projectAssignModal').modal('hide');
				}
				else if (response == "0") {
					messages("warning", "Info!", "No Data Affected", 10000);
				}
				else {
					messages("warning", "Warning!", response, 10000);
				}
			},
			complete: function () {
				$('#webprogress').css('display', 'none');
				$('#submitbtn').attr('disabled', false);
			}
		});
	}

	$scope.delete_data = function (id) {
		if (confirm("Deleting Project may hamper your data associated with it. You will loose the data related with this Project.")) {
			if (confirm("Are you Sure to DELETE ??")) {
				$http.get(rootUrl + "project_assign/delete_data?id=" + id).success(function (data) {
					if (data == "1") {
						messages("success", "Success!", "Assigned Project Deleted Successfully", 4000);
						$scope.loader($scope.pageno || 1);
					}
					else {
						messages("danger", "Warning!", "Assigned Project not Deleted", 10000);
					}
				})
			}
		}
	}

	$scope.loader(1);
	allowSelect2TypingInsideModal();

	$('#projectAssignModal').on('shown.bs.modal', function () {
		// Select2 v3 appends search input outside modal; disable Bootstrap focus trap for this modal.
		$(document).off('focusin.bs.modal');
		initProjectAssignSelect2();
	});
	initProjectAssignSelect2();

}]);
app.controller('ftp_credentials', ['$scope', '$rootScope', '$http', '$timeout', function ($scope, $rootScope, $http, $timeout) {
    rootUrl = $rootScope.site_url;
    module = 'ftp_credentials/';

    $http.get(rootUrl + module + 'index').success(function (data) {
        if (data == 0) {
            window.location.assign('login.html');
        }
    });

    $scope.pageno = 1;
    $scope.total_count = 0;
    $scope.itemsPerPage = '15';
    $scope.qx = {};
    $scope.x = {
        server_type: 'our_server',
        status: '1'
    };
    $scope.assign = {
        fc_id: '',
        title: '',
        emp_ids: []
    };
    $scope.assignPrompt = {
        row: null
    };
    $scope.datadb = [];
    $scope.customers = [];
    $scope.employees = [];
    $scope.ftp_credentials_modal_title = 'Add FTP Credentials';

    $scope.showFtpPassword = false;
    $scope.showDbPassword = false;
    $scope.showServerLoginPassword = false;
    $scope.showWebmailPassword = false;
    $scope.showDomainPassword = false;
    $scope.visibleFtp = {};
    $scope.visibleDb = {};
    $scope.visibleWebmail = {};
    $scope.visibleDomain = {};

    function resetVisibleStates() {
        $scope.visibleFtp = {};
        $scope.visibleDb = {};
        $scope.visibleWebmail = {};
        $scope.visibleDomain = {};
    }

    function initFtpCredentialsSelect2() {
        if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
            return;
        }

        $timeout(function () {
            var $mainModal = $('#ftpCredentialsModal');
            var $assignModal = $('#assignEmployeesModal');
            var isSelect2V4 = !!($.fn.select2 && $.fn.select2.amd);

            $('.ftp-credentials-select2').each(function () {
                var $el = $(this);
                var inMainModal = $el.closest('#ftpCredentialsModal').length > 0;
                var inAssignModal = $el.closest('#assignEmployeesModal').length > 0;

                if (!$el.is('select')) {
                    return;
                }

                if ($el.data('select2')) {
                    $el.select2('destroy');
                }

                var options = {
                    width: '100%',
                    allowClear: false,
                    minimumResultsForSearch: 0
                };

                if ($el.prop('multiple')) {
                    options.closeOnSelect = false;
                }

                if (isSelect2V4) {
                    if (inAssignModal) {
                        options.dropdownParent = $assignModal;
                    } else if (inMainModal) {
                        options.dropdownParent = $mainModal;
                    } else {
                        options.dropdownParent = $(document.body);
                    }
                }

                $el.select2(options);
            });
        }, 0);
    }

    function allowSelect2TypingInsideModal() {
        if (typeof $ === 'undefined' || !$.fn || !$.fn.modal || !$.fn.modal.Constructor) {
            return;
        }

        var ModalConstructor = $.fn.modal.Constructor;
        if (ModalConstructor.prototype._ftpCredentialsSelect2FocusPatched) {
            return;
        }

        ModalConstructor.prototype.enforceFocus = function () {
            var modalThis = this;
            $(document)
                .off('focusin.bs.modal')
                .on('focusin.bs.modal', function (e) {
                    var $target = $(e.target);
                    var isInsideModal = modalThis.$element[0] === e.target || modalThis.$element.has(e.target).length;
                    var isSelect2Input =
                        $target.closest('.select2-container, .select2-dropdown, .select2-drop, .select2-search').length > 0 ||
                        $target.is('.select2-input, .select2-search__field');

                    if (!isInsideModal && !isSelect2Input) {
                        modalThis.$element.trigger('focus');
                    }
                });
        };

        ModalConstructor.prototype._ftpCredentialsSelect2FocusPatched = true;
    }

    function refreshSelect2Values() {
        if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
            return;
        }

        $timeout(function () {
            if ($scope.x.customer_id) {
                $('select[name="customer_id"]').val(String($scope.x.customer_id)).trigger('change');
            }
            if ($scope.assign.emp_ids && $scope.assign.emp_ids.length) {
                $('select[name="emp_ids[]"]').val($scope.assign.emp_ids).trigger('change');
            }
        }, 100);
    }
    function getCustomerNameById(customerId) {
        var id = String(customerId || '');
        if (!id || !$scope.customers || !$scope.customers.length) {
            return '';
        }

        for (var i = 0; i < $scope.customers.length; i++) {
            if (String($scope.customers[i].c_id) === id) {
                return $scope.customers[i].company_name || '';
            }
        }

        return '';
    }

    $scope.loader = function (pageno) {
        if (!pageno)
            pageno = 1;

        $scope.pageno = pageno;

        var params = [];
        if ($scope.qx.customer_id)
            params.push('customer_id=' + encodeURIComponent($scope.qx.customer_id));
        if ($scope.qx.server_type)
            params.push('server_type=' + encodeURIComponent($scope.qx.server_type));
        if ($scope.qx.status !== undefined && $scope.qx.status !== '')
            params.push('status=' + encodeURIComponent($scope.qx.status));

        var url = rootUrl + module + 'view/' + $scope.itemsPerPage + '/' + pageno;
        if (params.length)
            url += '?' + params.join('&');

        $http.get(url).success(function (response) {
            if (response && response.data !== undefined) {
                $scope.datadb = response.data || [];
                $scope.total_count = response.total_count || 0;
            } else {
                $scope.datadb = response || [];
                $scope.total_count = ($scope.datadb || []).length;
            }
            resetVisibleStates();
        });
    };

    $scope.load_customers = function () {
        $http.get(rootUrl + 'customer/view?data=c_id,company_name&status=1').success(function (data) {
            $scope.customers = data || [];
            initFtpCredentialsSelect2();
        });
    };

    $scope.load_employees = function () {
        $http.get(rootUrl + 'hr_staff_details/view?data=emp_id,staff_name&st=1').success(function (data) {
            $scope.employees = data || [];
            initFtpCredentialsSelect2();
        });
    };

    $scope.apply_filters = function () {
        $scope.loader(1);
    };

    $scope.clear_filters = function () {
        $scope.qx = {};
        $scope.itemsPerPage = '15';
        $scope.loader(1);
        initFtpCredentialsSelect2();
    };

    $scope.on_items_per_page_change = function () {
        $scope.loader(1);
    };

    $scope.toggleFtpPassword = function (id) {
        $scope.visibleFtp[id] = !$scope.visibleFtp[id];
    };

    $scope.toggleDbPassword = function (id) {
        $scope.visibleDb[id] = !$scope.visibleDb[id];
    };

    $scope.toggleWebmailPassword = function (id) {
        $scope.visibleWebmail[id] = !$scope.visibleWebmail[id];
    };

    $scope.toggleDomainPassword = function (id) {
        $scope.visibleDomain[id] = !$scope.visibleDomain[id];
    };

    $scope.filter_new = function () {
        $scope.x = {
            server_type: 'our_server',
            status: '1'
        };
        $scope.showFtpPassword = false;
        $scope.showDbPassword = false;
        $scope.showServerLoginPassword = false;
        $scope.showWebmailPassword = false;
        $scope.showDomainPassword = false;
        refreshSelect2Values();
    };

    $scope.update_call = function (row) {
        $scope.x = angular.copy(row || {});
        $scope.x.customer_id = $scope.x.customer_id ? String($scope.x.customer_id) : '';
        $scope.x.status = ($scope.x.status == '0') ? '0' : '1';
        if (!$scope.x.server_type) {
            $scope.x.server_type = 'our_server';
        }
        $scope.showFtpPassword = false;
        $scope.showDbPassword = false;
        $scope.showServerLoginPassword = false;
        $scope.showWebmailPassword = false;
        $scope.showDomainPassword = false;
        refreshSelect2Values();
    };

    $scope.ask_assign_after_save = function (row) {
        $scope.assignPrompt.row = row || null;
        $('#assignAfterSaveModal').modal('show');
    };

    $scope.confirm_assign_after_save = function () {
        var row = $scope.assignPrompt.row;
        $scope.assignPrompt.row = null;
        $('#assignAfterSaveModal').modal('hide');

        if (row && row.fc_id) {
            $scope.open_assign_modal(row);
        }
    };

    $scope.cancel_assign_after_save = function () {
        $scope.assignPrompt.row = null;
        $('#assignAfterSaveModal').modal('hide');
    };

    $scope.open_ftp_credentials_modal = function (mode, row) {
        if (mode === 'edit' && row) {
            $scope.ftp_credentials_modal_title = 'Edit FTP Credentials';
            $scope.update_call(row);
        } else {
            $scope.ftp_credentials_modal_title = 'Add FTP Credentials';
            $scope.filter_new();
        }

        $('#ftpCredentialsModal').modal('show');
        initFtpCredentialsSelect2();
    };

    $scope.open_assign_modal = function (row) {
        $scope.assign.fc_id = row.fc_id;
        $scope.assign.title = (row.company_name || '') + ' - ' + (row.server_type === 'our_server' ? 'Our Server' : 'Customer Server');
        $scope.assign.emp_ids = [];

        $http.get(rootUrl + module + 'assigned_employees?fc_id=' + row.fc_id).success(function (res) {
            var ids = (res && res.data) ? res.data : [];
            $scope.assign.emp_ids = ids.map(function (id) { return String(id); });
            $('#assignEmployeesModal').modal('show');
            initFtpCredentialsSelect2();
            refreshSelect2Values();
        });
    };

    $scope.save_assigned_employees = function () {
        $('#submitbtnAssign').attr('disabled', true);

        $.ajax({
            type: 'POST',
            url: rootUrl + module + 'save_assigned_employees',
            data: $('#assignEmployeesForm').serialize(),
            beforeSend: function () {
                $('#assignLoader').css('display', 'inline');
            },
            success: function (res) {
                if (String(res.error) === '0') {
                    messages('success', 'Success!', res.msg || 'Access updated successfully.', 3000);
                    $scope.$applyAsync(function () {
                        $('#assignEmployeesModal').modal('hide');
                        $scope.loader($scope.pageno || 1);
                    });
                } else {
                    messages('danger', 'Warning!', res.msg || 'Unable to update employee access.', 6000);
                }
                $('#assignLoader').css('display', 'none');
                $('#submitbtnAssign').attr('disabled', false);
            },
            error: function () {
                messages('danger', 'Warning!', 'Unable to update employee access.', 6000);
                $('#assignLoader').css('display', 'none');
                $('#submitbtnAssign').attr('disabled', false);
            }
        });
    };

    $scope.save_data = function () {
        $('#submitbtnFtp').attr('disabled', true);

        $.ajax({
            type: 'POST',
            url: rootUrl + module + 'save_data',
            data: $('#ftpCredentialsForm').serialize(),
            beforeSend: function () {
                $('#ftpLoader').css('display', 'inline');
            },
            success: function (data) {
                if (String(data.error) === '0') {
                    var savedFcId = parseInt(data.fc_id, 10) || 0;
                    var assignRow = {
                        fc_id: savedFcId,
                        company_name: getCustomerNameById($scope.x.customer_id),
                        server_type: $scope.x.server_type || 'our_server'
                    };

                    messages('success', 'Success!', data.msg || 'Saved Successfully', 3000);
                    $scope.$applyAsync(function () {
                        $('#ftpCredentialsModal').modal('hide');
                        $scope.loader($scope.pageno || 1);
                        $scope.filter_new();

                        if (savedFcId > 0) {
                            $scope.ask_assign_after_save(assignRow);
                        }
                    });
                } else {
                    messages('danger', 'Warning!', data.msg || 'Unable to save FTP credentials.', 6000);
                }

                $('#ftpLoader').css('display', 'none');
                $('#submitbtnFtp').attr('disabled', false);
            },
            error: function () {
                messages('danger', 'Warning!', 'Unable to save FTP credentials.', 6000);
                $('#ftpLoader').css('display', 'none');
                $('#submitbtnFtp').attr('disabled', false);
            }
        });
    };

    $scope.delete_data = function (id) {
        if (confirm('Deleting FTP Credentials may affect related operations.')) {
            if (confirm('Are you Sure to DELETE ??')) {
                $http.get(rootUrl + module + 'delete_data?id=' + id).success(function (data) {
                    if (String(data) === '1') {
                        messages('success', 'Success!', 'FTP Credentials Deleted Successfully', 3000);
                    } else {
                        messages('danger', 'Warning!', 'FTP Credentials not Deleted', 4000);
                    }
                    $scope.loader($scope.pageno || 1);
                });
            }
        }
    };

    $scope.copyPassword = function (value, label) {
        if (!value) {
            return;
        }

        if (navigator.clipboard && navigator.clipboard.writeText) {
            navigator.clipboard.writeText(value).then(function () {
                messages('success', 'Copied!', label + ' copied to clipboard.', 2000);
            }, function () {
                messages('warning', 'Warning!', 'Could not copy to clipboard.', 3000);
            });
            return;
        }

        var $temp = $('<input>');
        $('body').append($temp);
        $temp.val(value).select();
        document.execCommand('copy');
        $temp.remove();
        messages('success', 'Copied!', label + ' copied to clipboard.', 2000);
    };

    $scope.loader(1);
    $scope.load_customers();
    $scope.load_employees();
    allowSelect2TypingInsideModal();

    $('#ftpCredentialsModal, #assignEmployeesModal, #assignAfterSaveModal').on('shown.bs.modal', function () {
        $(document).off('focusin.bs.modal');
        initFtpCredentialsSelect2();
        refreshSelect2Values();
    });

    initFtpCredentialsSelect2();
}]);













app.controller('server_credentials', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) {
    rootUrl = $rootScope.site_url;
    module = 'server_credentials/';

    $http.get(rootUrl + module + 'index').success(function (data) {
        if (data == 0) {
            window.location.assign('login.html');
        }
    });

    $scope.pageno = 1;
    $scope.total_count = 0;
    $scope.itemsPerPage = '15';
    $scope.qx = {};
    $scope.datadb = [];
    $scope.customers = [];
    $scope.visibleFtp = {};
    $scope.visibleDb = {};
    $scope.visibleWebmail = {};
    $scope.visibleDomain = {};

    function initSelect2() {
        if (typeof $ === 'undefined' || !$.fn || !$.fn.select2) {
            return;
        }
        setTimeout(function () {
            $('.server-credentials-select2').each(function () {
                var $el = $(this);
                if (!$el.is('select')) {
                    return;
                }
                if ($el.data('select2')) {
                    $el.select2('destroy');
                }
                $el.select2({
                    width: '100%',
                    allowClear: false,
                    minimumResultsForSearch: 0
                });
            });
        }, 0);
    }

    $scope.loader = function (pageno) {
        if (!pageno)
            pageno = 1;

        $scope.pageno = pageno;

        var params = [];
        if ($scope.qx.customer_id)
            params.push('customer_id=' + encodeURIComponent($scope.qx.customer_id));
        if ($scope.qx.server_type)
            params.push('server_type=' + encodeURIComponent($scope.qx.server_type));

        var url = rootUrl + module + 'view/' + $scope.itemsPerPage + '/' + pageno;
        if (params.length)
            url += '?' + params.join('&');

        $http.get(url).success(function (response) {
            if (response && response.data !== undefined) {
                $scope.datadb = response.data || [];
                $scope.total_count = response.total_count || 0;
            } else {
                $scope.datadb = response || [];
                $scope.total_count = ($scope.datadb || []).length;
            }
        });
    };

    $scope.load_customers = function () {
        $http.get(rootUrl + 'customer/view?data=c_id,company_name&status=1').success(function (data) {
            $scope.customers = data || [];
            initSelect2();
        });
    };

    $scope.apply_filters = function () {
        $scope.loader(1);
    };

    $scope.clear_filters = function () {
        $scope.qx = {};
        $scope.itemsPerPage = '15';
        $scope.loader(1);
        initSelect2();
    };

    $scope.on_items_per_page_change = function () {
        $scope.loader(1);
    };

    $scope.toggleFtpPassword = function (id) {
        $scope.visibleFtp[id] = !$scope.visibleFtp[id];
    };

    $scope.toggleDbPassword = function (id) {
        $scope.visibleDb[id] = !$scope.visibleDb[id];
    };

    $scope.toggleWebmailPassword = function (id) {
        $scope.visibleWebmail[id] = !$scope.visibleWebmail[id];
    };

    $scope.toggleDomainPassword = function (id) {
        $scope.visibleDomain[id] = !$scope.visibleDomain[id];
    };

    $scope.copyValue = function (value, label) {
        if (!value) {
            return;
        }

        if (navigator.clipboard && navigator.clipboard.writeText) {
            navigator.clipboard.writeText(value).then(function () {
                messages('success', 'Copied!', label + ' copied to clipboard.', 2000);
            }, function () {
                messages('warning', 'Warning!', 'Could not copy to clipboard.', 3000);
            });
            return;
        }

        var $temp = $('<input>');
        $('body').append($temp);
        $temp.val(value).select();
        document.execCommand('copy');
        $temp.remove();
        messages('success', 'Copied!', label + ' copied to clipboard.', 2000);
    };

    $scope.loader(1);
    $scope.load_customers();
    initSelect2();
}]);
app.controller('employee_rating', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) {
	rootUrl = $rootScope.site_url;
	module = "employee_rating/";

	$scope.x = {};
	$scope.projects = [];
	$scope.employee_rows = [];
	$scope.saved_ratings = [];
	$scope.isSaving = false;
	$scope.isEditMode = false;
	$scope.editing_rating_id = null;
	$scope.isHrRatingUser = false;
	$scope.showSavedRatingsTable = false;
	$scope.ratingAnalytics = {
		totalRatings: 0,
		avgRating: 0,
		lowCount: 0,
		midCount: 0,
		highCount: 0,
		bucketDistribution: [],
		scoreDistribution: [],
		topEmployees: [],
		allEmployees: [],
		projectAverages: []
	};

	$scope.init_distribution = function () {
		var dist = [];
		for (var i = 10; i >= 1; i--) {
			dist.push({
				score: i,
				count: 0,
				percent: 0
			});
		}
		$scope.ratingAnalytics.scoreDistribution = dist;
	}

	$scope.init_distribution();

	$http.get(rootUrl + module + "index").success(function (data) {
		if (data == 0) {
			window.location.assign('login.html');
		} else if (data == 2) {
			messages("success", "Privilege not assigned.", 1000);
			window.location.assign('index.html');
		}
	});

	$scope.init = function () {
		$http.get(rootUrl + module + "rating_context").success(function (ctx) {
			$scope.isHrRatingUser = !!(ctx && (ctx.is_hr_rating_user == 1 || ctx.is_hr_rating_user == '1'));
			if ($scope.isHrRatingUser) {
				$scope.load_active_employees();
			} else {
				$scope.load_project_customers();
			}
		}).error(function () {
			$scope.isHrRatingUser = false;
			$scope.load_project_customers();
		});
		$scope.load_rating_data();
	}

	$scope.prepare_employee_rows = function (rows) {
		$scope.employee_rows = rows || [];
		angular.forEach($scope.employee_rows, function (row) {
			var parsedRating = parseInt(row.rating, 10);
			row.rating = (parsedRating >= 1 && parsedRating <= 10) ? parsedRating : 1;
			row.rating_comment = row.rating_comment ? row.rating_comment : "";
			row.not_required = '0';
		});
	}

	$scope.load_project_customers = function () {
		$http.get(rootUrl + module + "project_customers").success(function (data) {
			$scope.projects = data || [];
		});
	}

	$scope.load_active_employees = function () {
		$http.get(rootUrl + module + "active_employees").success(function (data) {
			$scope.prepare_employee_rows(data || []);
		});
	}

	$scope.load_rating_data = function () {
		$http.get(rootUrl + module + "rating_data").success(function (data) {
			$scope.saved_ratings = data || [];
			$scope.build_rating_analytics();
		});
	}

	$scope.build_rating_analytics = function () {
		var rows = $scope.saved_ratings || [];
		var total = 0;
		var sum = 0;
		var low = 0;
		var mid = 0;
		var high = 0;
		var scoreMap = {};
		var scoreEmployeeMap = {};
		var scoreCustomerMap = {};
		var employeeMap = {};
		var projectMap = {};
		var i;

		for (i = 1; i <= 10; i++) {
			scoreMap[i] = 0;
			scoreEmployeeMap[i] = {};
			scoreCustomerMap[i] = {};
		}

		var map_keys = function (obj) {
			var out = [];
			angular.forEach(obj, function (val, key) {
				if (val) {
					out.push(key);
				}
			});
			out.sort();
			return out;
		};

		var compact_names = function (arr, maxCount) {
			if (!arr || !arr.length) {
				return "-";
			}
			if (arr.length <= maxCount) {
				return arr.join(", ");
			}
			return arr.slice(0, maxCount).join(", ") + " +" + (arr.length - maxCount) + " more";
		};

		angular.forEach(rows, function (r) {
			var rating = parseInt(r.rating, 10);
			if (isNaN(rating) || rating < 1 || rating > 10) {
				return;
			}

			total += 1;
			sum += rating;
			scoreMap[rating] += 1;
			var rowStaffName = (r.staff_name && String(r.staff_name).trim() !== "") ? r.staff_name : "-";
			var rowCustomerName = (r.customer_name && String(r.customer_name).trim() !== "") ? r.customer_name : "General";
			scoreEmployeeMap[rating][rowStaffName] = true;
			scoreCustomerMap[rating][rowCustomerName] = true;

			if (rating <= 4) {
				low += 1;
			} else if (rating <= 7) {
				mid += 1;
			} else {
				high += 1;
			}

			var empKey = String(r.emp_id || '');
			if (!employeeMap[empKey]) {
				employeeMap[empKey] = {
					emp_id: r.emp_id,
					staff_name: rowStaffName,
					sum: 0,
					count: 0,
					customers: {}
				};
			}
			employeeMap[empKey].sum += rating;
			employeeMap[empKey].count += 1;
			employeeMap[empKey].customers[rowCustomerName] = true;

			var projectId = (r.c_id !== undefined && r.c_id !== null) ? r.c_id : 'general';
			var projectKey = String(projectId);
			if (!projectMap[projectKey]) {
				projectMap[projectKey] = {
					c_id: projectId,
					project_name: rowCustomerName,
					sum: 0,
					count: 0,
					employees: {}
				};
			}
			projectMap[projectKey].sum += rating;
			projectMap[projectKey].count += 1;
			projectMap[projectKey].employees[rowStaffName] = true;
		});

		var avg = total > 0 ? (sum / total) : 0;
		$scope.ratingAnalytics.totalRatings = total;
		$scope.ratingAnalytics.avgRating = avg;
		$scope.ratingAnalytics.lowCount = low;
		$scope.ratingAnalytics.midCount = mid;
		$scope.ratingAnalytics.highCount = high;
		$scope.ratingAnalytics.bucketDistribution = [
			{
				key: 'high',
				label: 'High (8-10)',
				count: high,
				percent: total > 0 ? Math.round((high / total) * 100) : 0
			},
			{
				key: 'mid',
				label: 'Mid (5-7)',
				count: mid,
				percent: total > 0 ? Math.round((mid / total) * 100) : 0
			},
			{
				key: 'low',
				label: 'Low (1-4)',
				count: low,
				percent: total > 0 ? Math.round((low / total) * 100) : 0
			}
		];

		var distribution = [];
		for (i = 10; i >= 1; i--) {
			var count = scoreMap[i] || 0;
			var scoreEmployeeList = map_keys(scoreEmployeeMap[i]);
			var scoreCustomerList = map_keys(scoreCustomerMap[i]);
			distribution.push({
				score: i,
				count: count,
				percent: total > 0 ? Math.round((count / total) * 100) : 0,
				employeeNamesText: compact_names(scoreEmployeeList, 5),
				customerNamesText: compact_names(scoreCustomerList, 5)
			});
		}
		$scope.ratingAnalytics.scoreDistribution = distribution;

		var empList = [];
		angular.forEach(employeeMap, function (e) {
			var avgEmp = e.count > 0 ? (e.sum / e.count) : 0;
			var employeeCustomerList = map_keys(e.customers);
			empList.push({
				emp_id: e.emp_id,
				staff_name: e.staff_name,
				avg: avgEmp,
				count: e.count,
				avgPercent: Math.round((avgEmp / 10) * 100),
				customerNamesText: compact_names(employeeCustomerList, 4)
			});
		});
		empList.sort(function (a, b) {
			if (b.avg === a.avg) {
				return b.count - a.count;
			}
			return b.avg - a.avg;
		});
		$scope.ratingAnalytics.allEmployees = empList;
		$scope.ratingAnalytics.topEmployees = empList.slice(0, 10);

		var projectList = [];
		angular.forEach(projectMap, function (p) {
			var avgProj = p.count > 0 ? (p.sum / p.count) : 0;
			var projectEmployeeList = map_keys(p.employees);
			projectList.push({
				c_id: p.c_id,
				project_name: p.project_name,
				avg: avgProj,
				count: p.count,
				avgPercent: Math.round((avgProj / 10) * 100),
				employeeNamesText: compact_names(projectEmployeeList, 4)
			});
		});
		projectList.sort(function (a, b) {
			if (b.avg === a.avg) {
				return b.count - a.count;
			}
			return b.avg - a.avg;
		});
		$scope.ratingAnalytics.projectAverages = projectList.slice(0, 6);
	}

	$scope.open_employee_avg_modal = function () {
		$('#employeeAverageModal').modal('show');
	}

	$scope.close_employee_avg_modal = function () {
		$('#employeeAverageModal').modal('hide');
	}

	$scope.score_distribution_tooltip = function (s) {
		if (!s) {
			return "";
		}
		return "Score: " + s.score +
			"\nCount: " + s.count +
			"\nEmployees: " + (s.employeeNamesText || "-") +
			"\nCustomers: " + (s.customerNamesText || "-");
	}

	$scope.employee_chart_tooltip = function (e) {
		if (!e) {
			return "";
		}
		return "Employee: " + (e.staff_name || "-") +
			"\nAvg Rating: " + (Math.round((e.avg || 0) * 100) / 100) + " / 10" +
			"\nRatings Count: " + (e.count || 0) +
			"\nCustomers: " + (e.customerNamesText || "-");
	}

	$scope.project_chart_tooltip = function (p) {
		if (!p) {
			return "";
		}
		return "Customer/Project: " + (p.project_name || "General") +
			"\nAvg Rating: " + (Math.round((p.avg || 0) * 100) / 100) + " / 10" +
			"\nRatings Count: " + (p.count || 0) +
			"\nEmployees: " + (p.employeeNamesText || "-");
	}

	$scope.open_add_rating_modal = function (mode, row) {
		if (mode === 'edit' && row) {
			$scope.edit_rating(row);
			return;
		}
		$scope.reset_form();
		$('#employeeRatingModal').modal('show');
	}

	$scope.close_add_rating_modal = function () {
		$('#employeeRatingModal').modal('hide');
	}

	$scope.toggle_saved_ratings = function () {
		$scope.showSavedRatingsTable = !$scope.showSavedRatingsTable;
	}

	$scope.rating_row_class = function (row) {
		var rating = parseInt((row && row.rating) ? row.rating : 0, 10);
		if (rating >= 8) return 'employee-rating-row-high';
		if (rating >= 5) return 'employee-rating-row-mid';
		return 'employee-rating-row-low';
	}

	$scope.project_change = function (c_id) {
		if ($scope.isHrRatingUser) {
			return;
		}

		$scope.employee_rows = [];
		if (!c_id) {
			return;
		}
		$http.get(rootUrl + module + "project_employees?c_id=" + c_id).success(function (data) {
			$scope.prepare_employee_rows(data || []);
		});
	}

	$scope.toggle_not_required = function (row) {
		if (row.not_required == '1') {
			row.rating = "";
		} else if (!row.rating) {
			row.rating = 1;
		}
	}

	$scope.ensure_project_option = function (c_id, customer_name) {
		var exists = false;
		angular.forEach($scope.projects, function (p) {
			if (String(p.c_id) === String(c_id)) {
				exists = true;
			}
		});
		if (!exists) {
			$scope.projects.push({
				c_id: String(c_id),
				company_name: customer_name || "Customer",
				name: ""
			});
		}
	}

	$scope.edit_rating = function (row) {
		if (!row || !row.rating_id) {
			return;
		}
		$scope.showSavedRatingsTable = false;
		$('#employeeRatingModal').modal('show');
		if (row.c_id) {
			$scope.ensure_project_option(row.c_id, row.customer_name);
			$scope.x.project_id = String(row.c_id);
		} else {
			$scope.x.project_id = "";
		}
		$scope.isEditMode = true;
		$scope.editing_rating_id = row.rating_id;

		$http.get(rootUrl + module + "rating_row?rating_id=" + row.rating_id).success(function (res) {
			if (!res || !res.rating_id) {
				$scope.employee_rows = [];
				messages("danger", "Warning!", "Selected rating row not found.", 4000);
				return;
			}
			var parsedRating = parseInt(res.rating, 10);
			$scope.employee_rows = [{
				rating_id: res.rating_id,
				emp_id: res.emp_id,
				staff_name: res.staff_name,
				rating: (parsedRating >= 1 && parsedRating <= 10) ? parsedRating : 1,
				rating_comment: res.rating_comment ? res.rating_comment : "",
				not_required: '0'
			}];
		});
	}

	$scope.reset_form = function () {
		$scope.x.project_id = "";
		if ($scope.isHrRatingUser) {
			$scope.load_active_employees();
		} else {
			$scope.employee_rows = [];
		}
		$scope.isEditMode = false;
		$scope.editing_rating_id = null;
	}

	$scope.cancel_edit = function () {
		$scope.reset_form();
	}

	$scope.save_ratings = function () {
		if (!$scope.isHrRatingUser && !$scope.isEditMode && !$scope.x.project_id) {
			messages("warning", "Warning!", "Please select project first.", 3000);
			return;
		}
		$scope.isSaving = true;
		if ($scope.isEditMode) {
			var row = $scope.employee_rows.length ? $scope.employee_rows[0] : null;
			if (!row || !$scope.editing_rating_id) {
				$scope.isSaving = false;
				messages("warning", "Warning!", "No selected row found for update.", 3000);
				return;
			}

			$http({
				method: "POST",
				url: rootUrl + module + "update_rating",
				data: $.param({
					rating_id: $scope.editing_rating_id,
					rating: row.rating,
					rating_comment: row.rating_comment ? row.rating_comment : "",
					not_required: row.not_required
				}),
				headers: {
					'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
				}
			}).success(function (res) {
				if (res && res.error == 0) {
					messages("success", "Success!", "Employee rating updated successfully.", 3000);
					$scope.reset_form();
					$scope.load_rating_data();
					$scope.close_add_rating_modal();
				} else {
					messages("danger", "Warning!", (res && res.msg) ? res.msg : "Employee rating could not be updated.", 4000);
				}
			}).error(function () {
				messages("danger", "Warning!", "Employee rating could not be updated.", 4000);
			}).finally(function () {
				$scope.isSaving = false;
			});
			return;
		}

		var payload = {
			rows: angular.toJson($scope.employee_rows)
		};
		if (!$scope.isHrRatingUser) {
			payload.c_id = $scope.x.project_id;
		}

		$http({
			method: "POST",
			url: rootUrl + module + "save_ratings",
			data: $.param(payload),
			headers: {
				'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
			}
		}).success(function (res) {
			if (res && res.error == 0) {
				messages("success", "Success!", "Employee ratings saved successfully.", 3000);
				$scope.reset_form();
				$scope.load_rating_data();
				$scope.close_add_rating_modal();
			} else {
				messages("danger", "Warning!", (res && res.msg) ? res.msg : "Employee ratings could not be saved.", 4000);
			}
		}).error(function () {
			messages("danger", "Warning!", "Employee ratings could not be saved.", 4000);
		}).finally(function () {
			$scope.isSaving = false;
		});
	}

	$scope.init();
}]);
app.directive('todoPriorityDragSource', [function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.attr('draggable', 'true');
            element.on('dragstart', function (event) {
                var bucket = attrs.todoPriorityBucket || '';
                var index = parseInt(attrs.todoPriorityDragSource, 10);
                scope.$applyAsync(function () {
                    scope.todoPriorityDragStart(bucket, index, event);
                });
            });
        }
    };
}]);

app.directive('todoPriorityDropTarget', [function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('dragover', function (event) {
                event.preventDefault();
            });
            element.on('drop', function (event) {
                event.preventDefault();
                var bucket = attrs.todoPriorityBucket || '';
                var index = parseInt(attrs.todoPriorityDropTarget, 10);
                scope.$applyAsync(function () {
                    scope.todoPriorityDrop(bucket, index, event);
                });
            });
        }
    };
}]);

app.controller('to_do_list', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) {
    var rootUrl = $rootScope.site_url;
    var module = 'to_do_list/';
    var priorityBuckets = ['hot', 'warm', 'cold'];

    $scope.pageno = 1;
    $scope.total_count = 0;
    $scope.itemsPerPage = '20';
    $scope.datadb = [];
    $scope.qx = {
        q: '',
        emp_id: '',
        is_completed: '',
        status: '1'
    };
    $scope.x = {};
    $scope.employees = [];
    $scope.is_admin = false;
    $scope.current_emp_id = '';

    $scope.todoBoard = {
        hot: [],
        warm: [],
        cold: [],
        drag: {
            bucket: '',
            index: -1
        }
    };

    $http.get(rootUrl + module + 'index').success(function (data) {
        if (data == 0) {
            window.location.assign('login.html');
        } else if (data == 2) {
            messages('warning', 'Warning!', 'Privilege not assigned.', 2000);
            window.location.assign('index.html');
        }
    });

    function setAdminFlag() {
        var type = (localStorage.getItem('type') || '').toUpperCase();
        $scope.is_admin = (type === 'A' || type === 'ADMINISTRATOR');
        $scope.current_emp_id = String(localStorage.getItem('emp_id') || '');
    }

    function parseJsonResponse(data) {
        if (angular.isObject(data)) return data;
        if (!data) return {};
        try {
            return JSON.parse(data);
        } catch (e) {
            return { error: 1, msg: String(data) };
        }
    }

    function normalizePriorityType(row) {
        var raw = '';
        if (row && row.priority_type !== undefined && row.priority_type !== null) raw = row.priority_type;
        else if (row && row.priority_level !== undefined && row.priority_level !== null) raw = row.priority_level;
        else if (row && row.task_priority !== undefined && row.task_priority !== null) raw = row.task_priority;
        else if (row && row.priority_tag !== undefined && row.priority_tag !== null) raw = row.priority_tag;

        raw = String(raw || '').trim().toLowerCase();
        if (raw === 'hot' || raw === 'high' || raw === '1') return 'hot';
        if (raw === 'warm' || raw === 'medium' || raw === '2') return 'warm';
        if (raw === 'cold' || raw === 'low' || raw === '3') return 'cold';
        return 'warm';
    }

    function labelOfPriority(priorityType) {
        if (priorityType === 'hot') return 'Hot';
        if (priorityType === 'cold') return 'Cold';
        return 'Warm';
    }

    function boardCount(bucket) {
        return ($scope.todoBoard[bucket] || []).length;
    }

    function rebuildBoard(rows) {
        $scope.todoBoard.hot = [];
        $scope.todoBoard.warm = [];
        $scope.todoBoard.cold = [];

        angular.forEach(rows || [], function (row) {
            var p = normalizePriorityType(row);
            row._priority_type = p;
            row._priority_label = labelOfPriority(p);

            if (p === 'hot') $scope.todoBoard.hot.push(row);
            else if (p === 'cold') $scope.todoBoard.cold.push(row);
            else $scope.todoBoard.warm.push(row);
        });
    }

    function getFlattenedBoardState() {
        var orderedIds = [];
        var orderedTypes = [];
        var orderedRows = [];
        var rank = 0;

        angular.forEach(priorityBuckets, function (bucket) {
            angular.forEach($scope.todoBoard[bucket] || [], function (task) {
                rank += 1;
                orderedIds.push(task.todo_id);
                orderedTypes.push(bucket);
                orderedRows.push({
                    todo_id: task.todo_id,
                    priority_type: bucket,
                    priority_rank: rank
                });
            });
        });

        return {
            ordered_ids: orderedIds,
            ordered_types: orderedTypes,
            ordered_rows: orderedRows
        };
    }

    function syncDatadbFromBoard() {
        var flattened = [];
        var total = 0;

        angular.forEach(priorityBuckets, function (bucket) {
            total += ($scope.todoBoard[bucket] || []).length;
        });

        var rank = total;
        angular.forEach(priorityBuckets, function (bucket) {
            angular.forEach($scope.todoBoard[bucket] || [], function (task) {
                task._priority_type = bucket;
                task._priority_label = labelOfPriority(bucket);
                task.priority = rank;
                rank -= 1;
                flattened.push(task);
            });
        });

        $scope.datadb = flattened;
        $scope.total_count = flattened.length;
    }

    function persistPriorityType(task, targetBucket, done) {
        if (!task || !task.todo_id) {
            if (done) done(false);
            return;
        }

        $.ajax({
            type: 'POST',
            url: rootUrl + module + 'save_data',
            data: {
                todo_id: task.todo_id,
                title: task.title || '',
                priority_type: targetBucket,
                priority_level: targetBucket,
                task_priority: targetBucket
            },
            success: function (data) {
                var response = parseJsonResponse(data);
                if (response && String(response.error) === '0') {
                    if (done) done(true);
                    return;
                }
                if (done) done(false);
            },
            error: function () {
                if (done) done(false);
            }
        });
    }

    function persistBoardOrder(done) {
        var boardState = getFlattenedBoardState();
        $.ajax({
            type: 'POST',
            url: rootUrl + module + 'reorder',
            data: {
                'ordered_ids[]': boardState.ordered_ids,
                'ordered_priority_types[]': boardState.ordered_types,
                ordered_priority_map: JSON.stringify(boardState.ordered_rows)
            },
            success: function (data) {
                var response = parseJsonResponse(data);
                if (response && String(response.error) === '0') {
                    if (done) done(true);
                    return;
                }
                if (done) done(false);
            },
            error: function () {
                if (done) done(false);
            }
        });
    }

    function canDragTask(task) {
        if (!task) return false;
        if ($scope.is_admin) return true;
        var owner = String(task.emp_id || '');
        if (!owner) return true;
        return owner === String($scope.current_emp_id || '');
    }

    function readFilters() {
        var params = [];
        if ($scope.qx.q) params.push('q=' + encodeURIComponent($scope.qx.q));
        if ($scope.qx.emp_id) params.push('emp_id=' + encodeURIComponent($scope.qx.emp_id));
        if ($scope.qx.is_completed !== '') params.push('is_completed=' + encodeURIComponent($scope.qx.is_completed));
        if ($scope.qx.status !== '') params.push('status=' + encodeURIComponent($scope.qx.status));
        return params;
    }

    $scope.getPriorityType = function (row) {
        return normalizePriorityType(row);
    };

    $scope.getPriorityLabel = function (row) {
        return labelOfPriority(normalizePriorityType(row));
    };

    $scope.getPriorityClass = function (row) {
        return 'todo-priority--' + normalizePriorityType(row);
    };

    $scope.getBoardCount = function (bucket) {
        return boardCount(bucket);
    };

    $scope.todoPriorityDragStart = function (bucket, index, event) {
        var list = $scope.todoBoard[bucket] || [];
        var task = list[index];
        if (!task || !canDragTask(task)) {
            $scope.todoBoard.drag.bucket = '';
            $scope.todoBoard.drag.index = -1;
            if (event && event.preventDefault) event.preventDefault();
            return;
        }
        $scope.todoBoard.drag.bucket = bucket;
        $scope.todoBoard.drag.index = index;
    };

    $scope.todoPriorityDrop = function (targetBucket, targetIndex, event) {
        if (event && event.preventDefault) event.preventDefault();
        if (priorityBuckets.indexOf(targetBucket) === -1) return;

        var fromBucket = $scope.todoBoard.drag.bucket;
        var fromIndex = $scope.todoBoard.drag.index;
        if (!fromBucket || fromIndex < 0) return;

        var fromList = $scope.todoBoard[fromBucket] || [];
        if (!fromList.length || fromIndex >= fromList.length) return;

        var movedTask = fromList[fromIndex];
        if (!canDragTask(movedTask)) {
            messages('warning', 'Warning!', 'You can drag only tasks created by you.', 3000);
            return;
        }

        fromList.splice(fromIndex, 1);

        var toList = $scope.todoBoard[targetBucket] || [];
        var insertAt = targetIndex;
        if (isNaN(insertAt) || insertAt < 0 || insertAt > toList.length) {
            insertAt = toList.length;
        }
        toList.splice(insertAt, 0, movedTask);

        movedTask._priority_type = targetBucket;
        movedTask._priority_label = labelOfPriority(targetBucket);

        $scope.todoBoard.drag.bucket = '';
        $scope.todoBoard.drag.index = -1;

        // Keep UI responsive even if backend priority_type support is partial.
        syncDatadbFromBoard();

        persistBoardOrder(function (ordered) {
            if (!ordered) {
                messages('warning', 'Warning!', 'Unable to save task order.', 4000);
                return;
            }

            persistPriorityType(movedTask, targetBucket, function (ok) {
                if (!ok) {
                    messages('warning', 'Warning!', 'Priority type save not supported by API yet. UI moved, but refresh may restore old bucket.', 5000);
                    return;
                }
                $scope.$applyAsync(function () {
                    $scope.loader($scope.pageno || 1);
                });
            });
        });
    };

    $scope.loader = function (pageno) {
        if (!pageno) pageno = 1;
        $scope.pageno = pageno;

        var params = readFilters();
        var url = rootUrl + module + 'view/' + $scope.itemsPerPage + '/' + pageno;
        if (params.length) url += '?' + params.join('&');

        $http.get(url).success(function (response) {
            $scope.datadb = (response && response.data) ? response.data : [];
            $scope.total_count = (response && response.total_count) ? response.total_count : 0;
            if (response && response.is_admin !== undefined) {
                $scope.is_admin = String(response.is_admin) === '1';
            }
            rebuildBoard($scope.datadb);
        });
    };

    $scope.apply_filters = function () {
        $scope.loader(1);
    };

    $scope.clear_filters = function () {
        $scope.qx = {
            q: '',
            emp_id: '',
            is_completed: '',
            status: '1'
        };
        $scope.loader(1);
    };

    $scope.on_items_per_page_change = function () {
        $scope.loader(1);
    };

    $scope.open_modal = function (mode, row) {
        if (mode === 'edit' && row) {
            $scope.x = {
                todo_id: row.todo_id,
                title: row.title,
                priority_type: normalizePriorityType(row)
            };
        } else {
            $scope.x = {
                priority_type: 'warm'
            };
        }
        $('#toDoModal').modal('show');
    };

    $scope.save_data = function () {
        if (!$scope.x.priority_type) {
            $scope.x.priority_type = 'warm';
        }
        $('#todoSubmitBtn').attr('disabled', true);

        $.ajax({
            type: 'POST',
            url: rootUrl + module + 'save_data',
            data: $('#toDoForm').serialize(),
            beforeSend: function () {
                $('#todoProgress').css('display', 'inline');
            },
            success: function (data) {
                var response = parseJsonResponse(data);

                if (response && String(response.error) === '0') {
                    messages('success', 'Success!', response.msg || 'Saved successfully.', 3000);
                    $('#toDoModal').modal('hide');
                    $scope.$applyAsync(function () {
                        $scope.loader($scope.pageno || 1);
                    });
                } else {
                    messages('warning', 'Warning!', (response && response.msg) ? response.msg : 'Unable to save task.', 6000);
                }
            },
            complete: function () {
                $('#todoProgress').css('display', 'none');
                $('#todoSubmitBtn').attr('disabled', false);
            }
        });
    };

    $scope.toggle_completed = function (row) {
        var nextValue = row.is_completed == '1' ? 0 : 1;
        $.ajax({
            type: 'POST',
            url: rootUrl + module + 'toggle_status',
            data: {
                todo_id: row.todo_id,
                is_completed: nextValue
            },
            success: function (data) {
                var response = parseJsonResponse(data);

                if (response && String(response.error) === '0') {
                    messages('success', 'Success!', 'Task updated.', 2000);
                    $scope.$applyAsync(function () {
                        $scope.loader($scope.pageno || 1);
                    });
                } else {
                    messages('warning', 'Warning!', (response && response.msg) ? response.msg : 'Unable to update task.', 5000);
                }
            }
        });
    };

    $scope.delete_data = function (todo_id) {
        if (confirm('Archive this task from active list?')) {
            $http.get(rootUrl + module + 'delete_data?id=' + todo_id).success(function (data) {
                if (data == '1') {
                    messages('success', 'Success!', 'Task archived successfully.', 3000);
                    $scope.loader($scope.pageno || 1);
                } else {
                    messages('warning', 'Warning!', 'Task could not be archived.', 5000);
                }
            });
        }
    };

    $http.get(rootUrl + 'hr_staff_details/view?data=emp_id,staff_name&st=1').success(function (data) {
        $scope.employees = data || [];
    });

    setAdminFlag();
    $scope.loader(1);
}]);
 
