VaKeR CYBER ARMY
Logo of a company Server : Apache/2.4.41 (Ubuntu)
System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64
User : www-data ( 33)
PHP Version : 7.4.33
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Directory :  /var/www/html/keeview_app/html/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /var/www/html/keeview_app/html/pay_sheet.js

hr.pay_sheet.denyPay_sheet = function(host, id, comment){
    ModalElement.show_loading();
    FormClass.api_call({
        url: "pay_sheet_deny.php",
        params: [
            {name: "pay_sheetid", value: id},
            {name: "employeeid", value: host.employeeOfMe[0]},
            {name: "employee_peopleid", value: host.peopleOfMe},
            {name: "comment", value: comment}
        ],
        func: function(success, message){
            ModalElement.close(-1);
            if (success){
                if (message.substr(0, 2) == "ok"){
                    var st = EncodingClass.string.toVariable(message.substr(2));
                    host.dataPay_sheetEdit = st.data;
                    delete st.data;
                    contentModule.makeDatabaseContent(host, st);
                    hr.pay_sheet.makePrivApproval(host, id);
                    host.redrawTableFunc();
                    host.redrawHeaderViewFunc();
                    var index = host.database.pay_sheet.getIndex(id);
                    host.database.pay_sheet.items[index] = host.dataPay_sheetEdit;
                    hr.pay_sheet.redraw(host);
                }
                else if (message == "failed_id"){
                    ModalElement.alert({message: LanguageModule.text("war_txt_failed_data")});
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
            else {
                ModalElement.alert({message: message});
            }
        }
    });
};

hr.pay_sheet.denyPay_sheetConfirm = function(host, id){
    var comment_input = DOMElement.textarea({
        attrs: {
            className: "cardSimpleTextarea",
            style: {
                minWidth: "250px",
                width: "100%",
                height: "100px"
            }
        }
    });
    ModalElement.showWindow({
        title: LanguageModule.text("war_title_deny_pay_sheet"),
        bodycontent: DOMElement.div({
            children: [
                DOMElement.div({
                    attrs: {
                        style: {
                            height: "var(--control-height)",
                            lineHeight: "var(--control-height)",
                            width: "300px"
                        }
                    },
                    text: LanguageModule.text("txt_reason_deny")
                }),
                comment_input
            ]
        }),
        buttonlist: [
            {
                text: LanguageModule.text("txt_save"),
                onclick: function(){
                    ModalElement.close();
                    var comment = comment_input.value.trim();
                    hr.pay_sheet.denyPay_sheet(host, id, comment);
                }
            },
            {
                text: LanguageModule.text("txt_cancel"),
                onclick: function(){
                    ModalElement.close();
                }
            }
        ]
    });
    comment_input.focus();
};

hr.pay_sheet.approvalPay_sheet = function(host, id){
    ModalElement.show_loading();
    FormClass.api_call({
        url: "pay_sheet_approval.php",
        params: [
            {name: "pay_sheetid", value: id},
            {name: "employeeid", value: host.employeeOfMe[0]},
            {name: "employee_peopleid", value: host.peopleOfMe}
        ],
        func: function(success, message){
            ModalElement.close(-1);
            if (success){
                if (message.substr(0, 2) == "ok"){
                    var st = EncodingClass.string.toVariable(message.substr(2));
                    host.dataPay_sheetEdit = st.data;
                    delete st.data;
                    contentModule.makeDatabaseContent(host, st);
                    hr.pay_sheet.makePrivApproval(host, id);
                    host.redrawHeaderViewFunc();
                    var index = host.database.pay_sheet.getIndex(id);
                    host.database.pay_sheet.items[index] = host.dataPay_sheetEdit;
                    hr.pay_sheet.redraw(host);
                }
                else if (message == "failed_id"){
                    ModalElement.alert({message: LanguageModule.text("war_txt_failed_data")});
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
            else {
                ModalElement.alert({message: message});
            }
        }
    });
};

hr.pay_sheet.getDataFormPolicy = function(host, peopleIdList, list_type){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_list_by_employeeid_list_and_cycle"},
                {name: "data", value: EncodingClass.string.fromVariable({
                    list_type: list_type,
                    peopleIdList: peopleIdList,
                    cycleid: host.dataPay_sheetEdit.cycleid,
                    payroll_date: contentModule.getDateFrom1970(host.dataPay_sheetEdit.payroll_date)
                })}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0,2) == "ok"){
                        var content = EncodingClass.string.toVariable(message.substr(2));
                        var host1 = {database: {}};
                        contentModule.makeDatabaseContent(host1, content);
                        var policyDic = contentModule.makeDictionaryIndex(host1.database.policies.items);
                        var listDic = {};
                        host1.database.list.items.forEach(function(item){
                            listDic[item.id] = item.policyid;
                        });
                        var data = {};
                        host1.database.list_details.items.forEach(function(item){
                            var policyid = listDic[item.listid];
                            if (policyid === undefined) return;
                            if (!data[policyid]){
                                var pIndex = policyDic[policyid];
                                if (pIndex === undefined) return;
                                data[policyid] = EncodingClass.string.duplicate(host1.database.policies.items[pIndex]);
                                data[policyid].employees = {};
                            }
                            if (!data[policyid].employees[item.employee_peopleid]){
                                data[policyid].employees[item.employee_peopleid] = 0;
                            }
                            data[policyid].employees[item.employee_peopleid] += item.amount;
                        });
                        host.dataPay_sheetPolicy[list_type] = data;
                        host.updateProcessBar();
                        resolve();
                    }
                    else if (message == "no_list"){
                        resolve();
                        return;
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.getDataFormPay_percentage = function(host, pay_percentageid){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_pay_percentage_by_cycle"},
                {name: "data", value: EncodingClass.string.fromVariable({
                    pay_percentageid: pay_percentageid,
                    cycleid: host.dataPay_sheetEdit.cycleid,
                    payroll_date: contentModule.getDateFrom1970(host.dataPay_sheetEdit.payroll_date)
                })}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0,2) == "ok"){
                        var content = EncodingClass.string.toVariable(message.substr(2));
                        console.log(content);
                        var host1 = {database: {}};
                        contentModule.makeDatabaseContent(host1, content);
                        var data = {};
                        host1.database.timesheet_employee_workday_details_2.items.forEach(function(item){
                            if (!data[item.employee_peopleid]){
                                data[item.employee_peopleid] = 0;
                            }
                            data[item.employee_peopleid] += item.working_hours;
                        });
                        host.dataPay_sheetPay_percentage[pay_percentageid] = data;
                        host.updateProcessBar();
                        resolve();
                    }
                    else if (message == "no_pay_percentage"){
                        resolve();
                        return;
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.loadTaxPolicyApplyToEmployee = function(host, peopleIdList){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_tax_policy_apply_to_employee_by_peopleIdList"},
                {name: "peopleIdList", value: EncodingClass.string.fromVariable(peopleIdList)}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0,2) == "ok"){
                        var content = EncodingClass.string.toVariable(message.substr(2));
                        var host1 = {database: {}};
                        contentModule.makeDatabaseContent(host1, content);
                        host1.database.tax_policies.items.forEach(function(item){
                            if (item.tax_type == "progressive_tax"){
                                item.tax_rate_progressive_tax = EncodingClass.string.toVariable(item.tax_rate_progressive_tax);
                                item.tax_rate_progressive_tax.sort(function(a, b){
                                    return a.tax_rate_lines_amount - b.tax_rate_lines_amount;
                                });
                            }
                        });
                        var policyDic = contentModule.makeDictionaryIndex(host1.database.tax_policies.items);
                        systemconfig.paysheetConfig.tax = {};
                        host1.database.employee_policies.items.forEach(function(item){
                            var k = policyDic[item.policyid];
                            var eData = host.employee_peopleDic[item.employee_peopleid];
                            if (k >= 0) systemconfig.paysheetConfig.tax[eData.code] = host1.database.tax_policies.items[k];
                        });
                        host.updateProcessBar();
                        resolve();
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.deletePay_sheet = function(host, id){
    return new Promise(function(resolve,reject){
        ModalElement.show_loading();
        FormClass.api_call({
            url: "pay_sheet_delete.php",
            params: [{name: "id", value: id}],
            func: function(success, message){
                ModalElement.close(-1);
                if (success){
                    if (message.substr(0, 2) == "ok"){
                        var index = host.database.pay_sheet.getIndex(id);
                        host.database.pay_sheet.items.splice(index, 1);
                        resolve();
                    }
                    else if (message == "lock_system"){
                        ModalElement.alert({message: LanguageModule.text("war_txt_system_lock")});
                    }
                    else if (message == "failed_used"){
                        ModalElement.alert({
                            message: LanguageModule.text("war_txt_can_not_delete")
                        });
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.deletePay_sheetConfirm = function(host, id){
    return new Promise(function(resolve,reject){
        var index = host.database.pay_sheet.getIndex(id);
        ModalElement.question({
            title: LanguageModule.text("war_title_delete_pay_sheet"),
            message: LanguageModule.text2("war_txt_detele", [host.database.pay_sheet.items[index].name]),
            onclick: function(sel){
                if (sel == 0){
                    hr.pay_sheet.deletePay_sheet(host, id).then(function(value){
                        resolve(value);
                    });
                }
            }
        });
    });
};

hr.pay_sheet.addPay_sheetSubmit = function(host, data){
    return new Promise(function(resolve,reject){
        var saveFunc = function(){
            ModalElement.show_loading();
            FormClass.api_call({
                url: "pay_sheet_save.php",
                params: [{name: "data", value: EncodingClass.string.fromVariable(data)}],
                func: function(success, message){
                    ModalElement.close(-1);
                    if (success){
                        if (message.substr(0, 2) == "ok"){
                            var st = EncodingClass.string.toVariable(message.substr(2));
                            if (data.id != 0){
                                var index = host.database.pay_sheet.getIndex(data.id);
                                host.database.pay_sheet.items[index] = st;
                                host.dataPay_sheetEdit = host.database.pay_sheet.items[index];
                            }
                            else {
                                var id = st.id;
                                data.id = id;
                                host.id = id;
                                host.database.pay_sheet.items.push(st);
                                host.dataPay_sheetEdit = st;
                            }
                            hr.pay_sheet.redraw(host);
                            resolve();
                        }
                        else if (message == "failed_no_timekeeping_start_date") {
                            ModalElement.alert({message: "Chưa thiết lập ngày bắt đầu tính lương"});
                        }
                        else if (message == "lock_system"){
                            ModalElement.alert({message: LanguageModule.text("war_txt_system_lock")});
                        }
                        else if (message == "deleted" || message == "edited"){
                            ModalElement.alert({
                                message: LanguageModule.text("war_txt_failed_ver_reload_data")
                            });
                        }
                        else {
                            ModalElement.alert({message: message});
                        }
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
            });
        };
        if (data.id != 0){
            var ischange = contentModule.isChanged(host.dataPay_sheetEdit, data, ["name", "cycleid"]);
            if (!ischange){
                resolve();
                return;
            }
            data.ver = host.dataPay_sheetEdit.ver;
        }
        else {
            var orgDic = contentModule.makeDictionaryIndex(host.database.orgs.items);
            var employeeDic = contentModule.makeDictionaryIndex(host.database.employees.items);
            var peopleIdList = [], oIndex, empIndex;
            for (var i = 0; i < host.database.payroll_cycle_orgs.items.length; i++){
                if (host.database.payroll_cycle_orgs.items[i].cycleid != data.cycleid) continue;
                if (host.database.payroll_cycle_orgs.items[i].orgid < 0){
                    empIndex = employeeDic[-host.database.payroll_cycle_orgs.items[i].orgid];
                    if (empIndex >= 0 && host.database.employees.items[empIndex].available) peopleIdList.push(host.database.employees.items[empIndex].peopleid);
                }
                else {
                    oIndex = orgDic[host.database.payroll_cycle_orgs.items[i].orgid];
                    var orgIDList = contentModule.getDepartmentIDList(host, oIndex);
                    for (var i = 0; i < orgIDList.length; i++){
                        oIndex = orgDic[orgIDList[i]];
                        host.database.orgs.items[oIndex].employeeIndexList.forEach(function(empIndex){
                            if (!host.database.employees.items[empIndex].available) return;
                            peopleIdList.push(host.database.employees.items[empIndex].peopleid);
                        });
                    }
                }
            }
            peopleIdList.sort(function(a, b){
                return a - b;
            });
            data.peopleIdList = peopleIdList;
        }
        saveFunc();
    });
};

hr.pay_sheet.addPay_sheetClose = function(host, data){
    return new Promise(function(resolve, reject){
        if (data.id != 0){
            var oldData = host.dataPay_sheetEdit;
            var ischange = contentModule.isChanged(oldData, data, ["name", "cycleid"]);
            if (!ischange){
                resolve();
                return;
            }
        }
        contentModule.questionChange({
            onclick: function(sel){
                if (sel == 0){
                    hr.pay_sheet.addPay_sheetSubmit(host, data);
                }
                else if (sel == 1){
                    resolve();
                }
            }
        });
    });
};

hr.pay_sheet.redrawDetails = function(host, id){
    host.id = id;
    var payroll_cycleItems = [];
    for (var i = 0; i < host.database.payroll_cycle.items.length; i++){
        payroll_cycleItems.push({
            value: host.database.payroll_cycle.items[i].id,
            text: contentModule.getPayRollCycleView(host, host.database.payroll_cycle.items[i].id),
            noSelect: host.database.payroll_cycle.items[i].expired
        });
    }
    theme.formPay_sheetEdit({
        id: id,
        data: id > 0? host.dataPay_sheetEdit : "",
        payroll_cycleItems: payroll_cycleItems,
        func: {
            get_cycle_data_by_cycleid: function(cycleid){
                if (cycleid == 0) return {};
                var cIndex = host.database.payroll_cycle.getIndex(cycleid);
                return host.database.payroll_cycle.items[cIndex];
            },
            save: function(data){
                return hr.pay_sheet.addPay_sheetSubmit(host, data);
            },
            cancel: function(data){
                return hr.pay_sheet.addPay_sheetClose(host, data);
            }
        }
    });
};

hr.pay_sheet.loadPay_sheetData = function(host, id){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_by_id"},
                {name: "id", value: id}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0, 2) == "ok"){
                        var st = EncodingClass.string.toVariable(message.substr(2));
                        host.dataPay_sheetEdit = st;
                        resolve();
                    }
                    else if (message == "war_txt_failed_data"){
                        ModalElement.alert({
                            message: LanguageModule.text("war_txt_failed_data"),
                            func: function(){
                                hr.pay_sheet.init(host);
                            }
                        });
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.makePrivApproval = function(host, id){
    host.privApproval = false;
    if (host.dataPay_sheetEdit.status == -1){
        var ex = -1;
        host.database.payroll_cycle_approvers.items.forEach(function(item, index){
            if (item.employee_peopleid == host.peopleOfMe){
                ex = index;
            }
        });
        if (ex >= 0){
            var dic = {};
            host.database.pay_sheet_approvers1.items.forEach(function(item){
                if (item.old || item.status == -1) return;
                dic[item.employee_peopleid] = item.status;
            });
            var cIndex = host.database.payroll_cycle.getIndex(host.dataPay_sheetEdit.cycleid);
            switch (host.database.payroll_cycle.items[cIndex].approval_method) {
                case "sequence":
                    if (!dic[host.peopleOfMe]){
                        var prevDone = true;
                        for (var i = 0; i < ex; i++){
                            if (!dic[host.database.payroll_cycle_approvers.items[i].employee_peopleid]){
                                prevDone = false;
                                break;
                            }
                        }
                        if (prevDone) host.privApproval = true;
                    }
                    break;
                case "parallel":
                    if (!dic[host.peopleOfMe]) host.privApproval = true;
                    break;
                case "one_approver":
                    host.privApproval = true;
                    break;
                default:

            }
        }
    }
};

hr.pay_sheet.loadPay_sheetDataView = function(host, id){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_view_by_id"},
                {name: "id", value: id}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0, 2) == "ok"){
                        var st = EncodingClass.string.toVariable(message.substr(2));
                        host.dataPay_sheetEdit = st.data;
                        delete st.data;
                        contentModule.makeDatabaseContent(host, st);
                        hr.pay_sheet.makePrivApproval(host, id);
                        resolve();
                    }
                    else if (message == "war_txt_failed_data"){
                        ModalElement.alert({
                            message: LanguageModule.text("war_txt_failed_data"),
                            func: function(){
                                hr.pay_sheet.init(host);
                            }
                        });
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.addPay_sheet = function(host, id){
    if (host.database.payroll_cycle.items.length == 0){
        ModalElement.alert({message: "Chưa có chu kỳ tính lương"});
        return;
    }
    if (id == 0){
        hr.pay_sheet.redrawDetails(host, id);
    }
    else {
        if (host.database.pay_sheet.getIndex(id) < 0) return;
        ModalElement.show_loading();
        hr.pay_sheet.loadPay_sheetData(host, id).then(function(){
            ModalElement.close(-1);
            hr.pay_sheet.redrawDetails(host, id);
        });
    }
};

hr.pay_sheet.loadPay_sheet_employeesList = function(host, id){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_employees"},
                {name: "id", value: id}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0, 2) == "ok"){
                        var st = EncodingClass.string.toVariable(message.substr(2));
                        contentModule.makeDatabaseContent(host, st);
                        resolve();
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.loadSalaryDecisionsByEmployeePeopleIdList = function(host, peopleIdList){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_salary_decisions"},
                {name: "peopleIdList", value: EncodingClass.string.fromVariable(peopleIdList)}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0, 2) == "ok"){
                        for (var i = 0; i < host.database.employees.items.length; i++){
                            host.database.employees.items[i].basic_salary_amount = 0;
                            host.database.employees.items[i].gross_salary_amount = 0;
                            host.database.employees.items[i].salary_grade = "";
                            host.database.employees.items[i].salary_coefficient = "";
                        }
                        var st = EncodingClass.string.toVariable(message.substr(2));
                        var eData;
                        for (var i = 0; i < st.length; i++){
                            eData = host.employee_peopleDic[st[i].employee_peopleid];
                            if (eData){
                                eData.basic_salary_amount = st[i].basic_salary_amount;
                                eData.gross_salary_amount = st[i].gross_salary_amount;
                                eData.salary_grade = st[i].salary_grade;
                                eData.salary_coefficient = st[i].salary_coefficient;
                            }
                        }
                        host.updateProcessBar();
                        resolve();
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.loadStandard_workdaysConfig = function(host, peopleIdList){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "load_standard_workday_by_peopleIdList"},
                {name: "peopleIdList", value: EncodingClass.string.fromVariable(peopleIdList)}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0, 2) == "ok"){
                        var host1 = {database: {}};
                        var st = EncodingClass.string.toVariable(message.substr(2));
                        contentModule.makeDatabaseContent(host1, st);
                        var dic = contentModule.makeDictionaryIndex(host1.database.standard_workday_policies.items);
                        var peopleNeedLoadAssign = [];
                        host1.database.employee_policies.items.forEach(function(item){
                            var k = dic[item.policyid];
                            if (k >= 0){
                                if (host1.database.standard_workday_policies.items[k].calculation == "total_shifts_assigned"){
                                    peopleNeedLoadAssign.push(item.employee_peopleid);
                                }
                            }
                        });
                        var cIndex = host.database.payroll_cycle.getIndex(host.dataPay_sheetEdit.cycleid);
                        var cycle = host.database.payroll_cycle.items[cIndex].cycle;
                        var payroll_date = EncodingClass.string.duplicate(host.dataPay_sheetEdit.payroll_date);
                        var enddate = contentModule.getDateFrom1970(host.dataPay_sheetEdit.payroll_date);
                        var startdate;
                        if (cycle == "month"){
                            if (host.database.payroll_cycle.items[cIndex].payroll_date == 0){
                                startdate = new Date(payroll_date.setDate(0));
                            }
                            else {
                                startdate = absol.datetime.prevMonth(payroll_date);
                                startdate = new Date(startdate.setDate(cycleData.payroll_date));
                            }
                        }
                        else {
                            startdate = new Date(payroll_date.getTime() - 7*24*60*60*1000);
                        }
                        startdate = contentModule.getDateFrom1970(startdate) + 1;
                        var f = function(){
                            var standard_workdayDic = {};
                            host1.database.standard_workday_policies.items.forEach(function(item){
                                if (item.calculation == "total_shifts_assigned") return;
                                standard_workdayDic[item.calculation] = contentModule.getStandardWorkdayByCalculation(item, startdate, enddate);
                            });
                            var policyDic = contentModule.makeDictionaryIndex(host1.database.standard_workday_policies.items);
                            if (peopleNeedLoadAssign.length > 0){
                                contentModule.makeShiftsData(host1);
                                host1.database.shifts.items.sort(function(a, b){
                                    return b.fromdate - a.fromdate;
                                });
                                var emp_assignDic = {};
                                host1.database.assign_employee_shifts.items.forEach(function(item){
                                    if (!emp_assignDic[item.employee_peopleid]) emp_assignDic[item.employee_peopleid] = 0;
                                    var shiftContent = contentModule.getContentShiftFollowDateById(host1, item.shiftid, item.date);
                                    if (!shiftContent) return;
                                    var duration_h = contentModule.getOverTimeHoursHasShiftContent(
                                        host1,
                                        new Date(item.date*86400000),
                                        new Date(item.date*86400000),
                                        {
                                            dayOffset: item.time_in,
                                            duration: item.time_out - item.time_in
                                        },
                                        shiftContent,
                                        item.ot_in_breaktime,
                                    );
                                    var workdays = (duration_h/shiftContent.number_of_standard_working_hours)*shiftContent.number_of_work_days;
                                    emp_assignDic[item.employee_peopleid] += workdays;
                                });
                            }
                            host.standard_workdays = {};
                            host1.database.employee_policies.items.forEach(function(item){
                                var pIndex = policyDic[item.policyid];
                                if (pIndex >= 0){
                                    if (host1.database.standard_workday_policies.items[pIndex].calculation == "total_shifts_assigned"){
                                        host.standard_workdays[item.employee_peopleid] = emp_assignDic[item.employee_peopleid];
                                    }
                                    else {
                                        host.standard_workdays[item.employee_peopleid] = standard_workdayDic[host1.database.standard_workday_policies.items[pIndex].calculation];
                                    }
                                }
                            });
                            host.updateProcessBar();
                            resolve();
                        };
                        if (peopleNeedLoadAssign.length > 0){
                            FormClass.api_call({
                                url: "database_load.php",
                                params: [
                                    {name: "task", value: "load_assign_by_peopleIdList_in_time"},
                                    {name: "peopleIdList", value: EncodingClass.string.fromVariable(peopleNeedLoadAssign)},
                                    {name: "startdate", value: startdate},
                                    {name: "enddate", value: enddate}
                                ],
                                func: function(success, message){
                                    if (success){
                                        if (message.substr(0, 2) == "ok"){
                                            var content = EncodingClass.string.toVariable(message.substr(2));
                                            contentModule.makeDatabaseContent(host1, content);
                                            f();
                                        }
                                        else {
                                            ModalElement.alert({message: message});
                                        }
                                    }
                                    else {
                                        ModalElement.alert({message: message});
                                    }
                                }
                            })
                        }
                        else {
                            f();
                        }
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.loadActualWorkdays = function(host){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_timesheet"},
                {name: "data", value: EncodingClass.string.fromVariable({
                    cycleid: host.dataPay_sheetEdit.cycleid,
                    payroll_date: contentModule.getDateFrom1970(host.dataPay_sheetEdit.payroll_date)
                })}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0,2) == "ok"){
                        var content = EncodingClass.string.toVariable(message.substr(2));
                        contentModule.makeDatabaseContent(host, content);
                        host.actual_workdays = {};
                        host.database.timesheet_employees.items.forEach(function(item){
                            host.actual_workdays[item.employee_peopleid] = item.workdays;
                        });
                        host.updateProcessBar();
                        resolve();
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.loadDependentPersons = function(host, peopleIdList){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "load_dependent_persons_by_peopleIdList"},
                {name: "peopleIdList", value: EncodingClass.string.fromVariable(peopleIdList)}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0,2) == "ok"){
                        var content = EncodingClass.string.toVariable(message.substr(2));
                        contentModule.makeDatabaseContent(host, content);
                        host.dependent_persons = {};
                        host.database.employee_dependent_persons.items.forEach(function(item){
                            if (!host.dependent_persons[item.employee_peopleid]) host.dependent_persons[item.employee_peopleid] = 0;
                            host.dependent_persons[item.employee_peopleid] += 1;
                        });
                        host.updateProcessBar();
                        resolve();
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.loadPieceWageData = function(host, peopleIdList){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_piece_wage"},
                {name: "data", value: EncodingClass.string.fromVariable({
                    cycleid: host.dataPay_sheetEdit.cycleid,
                    payroll_date: contentModule.getDateFrom1970(host.dataPay_sheetEdit.payroll_date),
                    peopleIdList: peopleIdList
                })}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0,2) == "ok"){
                        var content = EncodingClass.string.toVariable(message.substr(2));
                        contentModule.makeDatabaseContent(host, content);
                        systemconfig.paysheetConfig.piece_wage = {};
                        var dic = contentModule.makeDictionaryIndex(host.database.piece_wage.items);
                        host.database.piece_wage_table.items.forEach(function(item){
                            var k = dic[item.piece_wage_id];
                            if (k >= 0){
                                var eData = host.employee_peopleDic[host.database.piece_wage.items[k].employee_peopleid];
                                if (!systemconfig.paysheetConfig.piece_wage[eData.code]){
                                    systemconfig.paysheetConfig.piece_wage[eData.code] = 0;
                                }
                                systemconfig.paysheetConfig.piece_wage[eData.code] += item.money;
                            }
                        });
                        host.updateProcessBar();
                        resolve();
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.reCalculatedPayByChange = function(host, peopleIdDic){
    return new Promise(function(resolve, reject){
        var f = function(){
            var data = EncodingClass.string.duplicate(host.dataPay_sheetDetails);
            var listSetting = EncodingClass.string.duplicate(host.database.pay_sheet_column_configs.items);
            for (var i = 0; i < listSetting.length; i++){
                if (listSetting[i].setting && (listSetting[i].setting.data == "formula")){
                    if (listSetting[i].setting.formula == "") listSetting[i].setting.formula = "0";
                    listSetting[i].setting.formula = contentModule.convertPaysheetFormula(listSetting[i].setting.formula);
                    listSetting[i].setting.formula = MathClass.Expression.parse(listSetting[i].setting.formula);
                    if (!listSetting[i].setting.formula){
                        ModalElement.alert({message: LanguageModule.text("war_txt_formula_is_invalid")});
                        return;
                    }
                }
            }
            var pList = [];
            var variablesSystemList = contentModule.getPaySheetVariableSystem();
            var t = contentModule.getCalOrderList(listSetting, variablesSystemList);
            if (!t.status){
                ModalElement.close(-1);
                return;
            }
            var res = t.content;
            var dataInsert = [], dataUpdate = [];
            host.database.pay_sheet_employees.items.forEach(function(item){
                if (!peopleIdDic[item.employee_peopleid]) return;
                var eData = host.employee_peopleDic[item.employee_peopleid];
                if (!eData) return;
                var employee_code = eData.code;
                res.forEach(function(columnIndex){
                    var column_code = host.database.pay_sheet_column_configs.items[columnIndex].code;
                    var setting = listSetting[columnIndex].setting;
                    if (setting){
                        switch (setting.data) {
                            case "formula":
                                pList.push({
                                    employee_code: employee_code,
                                    func: function(){
                                        return new Promise(function(rs, rj){
                                            data[item.employee_peopleid][column_code.toLowerCase()] = setting.formula.calc(function (varname) {
                                                switch (varname) {
                                                    case "v_employeename":
                                                        return eData.fullname;
                                                    case "v_employeecode":
                                                        return eData.code;
                                                    case "v_startpropotionworkingdate":
                                                        return eData.start_date;
                                                    case "v_startofficialworkingdate":
                                                        return eData.official_date;
                                                    case "v_employeedepartment":
                                                        return host.database.orgs.items[eData.orgIndex].name;
                                                    case "v_employeeposition":
                                                        return eData.positionName;
                                                    case "v_basicsalary":
                                                        return eData.basic_salary_amount;
                                                    case "v_grosssalary":
                                                        return eData.gross_salary_amount;
                                                    case "v_salarycoefficient":
                                                        return eData.salary_coefficient;
                                                    case "v_salarygrade":
                                                        return eData.salary_grade;
                                                    case "v_standardworkdays":
                                                        return host.standard_workdays[item.employee_peopleid]? host.standard_workdays[item.employee_peopleid] : 0;
                                                    case "v_actualworkdays":
                                                        return host.actual_workdays[item.employee_peopleid]? host.actual_workdays[item.employee_peopleid] : 0;
                                                    case "v_dependentpersons":
                                                        return host.dependent_persons[item.employee_peopleid]? host.dependent_persons[item.employee_peopleid] : 0;
                                                    default:
                                                        if (data[item.employee_peopleid][varname] !== undefined){
                                                            if (EncodingClass.type.isNumber(data[item.employee_peopleid][varname]) || !absol.int.isNumber(data[item.employee_peopleid][varname])){
                                                                return data[item.employee_peopleid][varname];
                                                            }
                                                            else {
                                                                return contentModule.getValueFromMoneyFormat(data[item.employee_peopleid][varname]);
                                                            }
                                                        }
                                                        return null;
                                                    }
                                            });
                                            if (host.dataPay_sheetDetailsIdDic && host.dataPay_sheetDetailsIdDic[item.employee_peopleid] && host.dataPay_sheetDetailsIdDic[item.employee_peopleid][column_code.toLowerCase()]){
                                                dataUpdate.push({
                                                    id: host.dataPay_sheetDetailsIdDic[item.employee_peopleid][column_code.toLowerCase()],
                                                    employee_peopleid: item.employee_peopleid,
                                                    code: column_code,
                                                    content: EncodingClass.string.fromVariable(data[item.employee_peopleid][column_code.toLowerCase()])
                                                });
                                            }
                                            else {
                                                dataInsert.push({
                                                    id: 0,
                                                    pay_sheetid: host.dataPay_sheetEdit.id,
                                                    employee_peopleid: item.employee_peopleid,
                                                    code: column_code,
                                                    content: EncodingClass.string.fromVariable(data[item.employee_peopleid][column_code.toLowerCase()])
                                                });
                                            }
                                            rs();
                                        });
                                    }
                                });
                                break;
                            case "function":
                                pList.push({
                                    employee_code: employee_code,
                                    func: function(){
                                        return new Promise(function(rs, rj){
                                            var args = [];
                                            setting.function.args.forEach(function(arg){
                                                switch (arg.type) {
                                                    case "number":
                                                    case "string":
                                                        args.push(arg.value);
                                                        break;
                                                    case "employee_code":
                                                        args.push(employee_code);
                                                        break;
                                                    case "code_of_column":
                                                        args.push(data[item.employee_peopleid][arg.value]);
                                                        break;
                                                    default:

                                                }
                                            });
                                            contentModule.sclangCall(setting.function.functionid, {args: args}).then(function(value){
                                                data[item.employee_peopleid][column_code.toLowerCase()] = value;
                                                if (host.dataPay_sheetDetailsIdDic && host.dataPay_sheetDetailsIdDic[item.employee_peopleid] && host.dataPay_sheetDetailsIdDic[item.employee_peopleid][column_code.toLowerCase()]){
                                                    dataUpdate.push({
                                                        id: host.dataPay_sheetDetailsIdDic[item.employee_peopleid][column_code.toLowerCase()],
                                                        employee_peopleid: item.employee_peopleid,
                                                        code: column_code,
                                                        content: EncodingClass.string.fromVariable(data[item.employee_peopleid][column_code.toLowerCase()])
                                                    });
                                                }
                                                else {
                                                    dataInsert.push({
                                                        id: 0,
                                                        pay_sheetid: host.dataPay_sheetEdit.id,
                                                        employee_peopleid: item.employee_peopleid,
                                                        code: column_code,
                                                        content: EncodingClass.string.fromVariable(data[item.employee_peopleid][column_code.toLowerCase()])
                                                    });
                                                }
                                                rs();
                                            });
                                        });
                                    }
                                });
                                break;
                            default:

                        }
                    }
                });
            });
            var finishedCal = pList.reduce(function(ac, item){
                return ac.then(function(){
                    systemconfig.paysheetConfig.employee_code = item.employee_code;
                    return item.func();
                });
            }, Promise.resolve());
            finishedCal.then(function(){
                console.log(dataInsert, dataUpdate);
                if (dataInsert.length == 0 && dataUpdate.length == 0){
                    resolve();
                    return;
                }
                hr.pay_sheet.saveDataInsertUpdate(host, dataInsert, dataUpdate).then(function(){
                    resolve();
                });
            });
        };
        var peopleIdList = [];
        host.database.pay_sheet_employees.items.forEach(function(item){
            if (!peopleIdDic[item.employee_peopleid]) return;
            peopleIdList.push(item.employee_peopleid);
        });
        var peopleIdList = [];
        for (var i = 0; i < host.database.pay_sheet_employees.items.length; i++){
            peopleIdList.push(host.database.pay_sheet_employees.items[i].employee_peopleid);
        }
        host.taskDone = 0;
        var promiseList = [hr.pay_sheet.loadSalaryDecisionsByEmployeePeopleIdList(host, peopleIdList)];
        promiseList.push(hr.pay_sheet.loadPieceWageData(host, peopleIdList));
        promiseList.push(hr.pay_sheet.loadStandard_workdaysConfig(host, peopleIdList));
        promiseList.push(hr.pay_sheet.loadActualWorkdays(host));
        promiseList.push(hr.pay_sheet.loadDependentPersons(host, peopleIdList));
        promiseList.push(hr.pay_sheet.loadTaxPolicyApplyToEmployee(host, peopleIdList));
        host.totalTask = 6;
        Promise.all(promiseList).then(function(){
            f();
        });
    });
};

hr.pay_sheet.saveDataInsertUpdate = function(host, dataInsert, dataUpdate){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "pay_sheet_save_employee_data_change.php",
            params: [
                {name: "dataInsert", value: EncodingClass.string.fromVariable(dataInsert)},
                {name: "dataUpdate", value: EncodingClass.string.fromVariable(dataUpdate)}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0, 2) == "ok"){
                        var st = EncodingClass.string.toVariable(message.substr(2));
                        for (var i = 0; i < dataUpdate.length; i++){
                            host.dataPay_sheetDetails[dataUpdate[i].employee_peopleid][dataUpdate[i].code.toLowerCase()] = EncodingClass.string.toVariable(dataUpdate[i].content);
                        }
                        for (var i = 0; i < st.length; i++){
                            if (!host.dataPay_sheetDetails[st[i].employee_peopleid]) host.dataPay_sheetDetails[st[i].employee_peopleid] = {};
                            host.dataPay_sheetDetails[st[i].employee_peopleid][st[i].code.toLowerCase()] = EncodingClass.string.toVariable(st[i].content);
                            if (!host.dataPay_sheetDetailsIdDic[st[i].employee_peopleid]) host.dataPay_sheetDetailsIdDic[st[i].employee_peopleid] = {};
                            host.dataPay_sheetDetailsIdDic[st[i].employee_peopleid][st[i].code.toLowerCase()] = st[i].id
                        }
                        resolve();
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.calculatedPay = function(host){
    return new Promise(function(resolve, reject){
        host.dataPay_sheetPolicy = {};
        host.dataPay_sheetPay_percentage = {};
        var peopleIdList = [];
        for (var i = 0; i < host.database.pay_sheet_employees.items.length; i++){
            peopleIdList.push(host.database.pay_sheet_employees.items[i].employee_peopleid);
        }
        host.taskDone = 0;
        var promiseList = [hr.pay_sheet.loadSalaryDecisionsByEmployeePeopleIdList(host, peopleIdList)];
        promiseList.push(hr.pay_sheet.loadPieceWageData(host, peopleIdList));
        promiseList.push(hr.pay_sheet.loadStandard_workdaysConfig(host, peopleIdList));
        promiseList.push(hr.pay_sheet.loadActualWorkdays(host));
        promiseList.push(hr.pay_sheet.loadDependentPersons(host, peopleIdList));
        promiseList.push(hr.pay_sheet.loadTaxPolicyApplyToEmployee(host, peopleIdList));
        host.totalTask = 6;
        host.database.pay_sheet_column_configs.items.forEach(function(item){
            if (item.setting){
                if (item.setting.data == "policy"){
                    var policys = item.setting.policy.split("_");
                    var list_type = policys[0];
                    if (!host.dataPay_sheetPolicy[list_type]){
                        host.dataPay_sheetPolicy[list_type] = {};
                        promiseList.push(hr.pay_sheet.getDataFormPolicy(host, peopleIdList, list_type));
                        host.totalTask++;
                    }
                }
                else if (item.setting.data == "pay_percentage"){
                    host.dataPay_sheetPay_percentage[item.setting.pay_percentage] = {};
                    promiseList.push(hr.pay_sheet.getDataFormPay_percentage(host, item.setting.pay_percentage));
                    host.totalTask++;
                }
            }
        });
        Promise.all(promiseList).then(function(values){
            var listSetting = EncodingClass.string.duplicate(host.database.pay_sheet_column_configs.items);
            for (var i = 0; i < listSetting.length; i++){
                if (listSetting[i].setting && (listSetting[i].setting.data == "formula")){
                    if (listSetting[i].setting.formula == "") listSetting[i].setting.formula = "0";
                    listSetting[i].setting.formula = contentModule.convertPaysheetFormula(listSetting[i].setting.formula);
                    listSetting[i].setting.formula = MathClass.Expression.parse(listSetting[i].setting.formula);
                    if (!listSetting[i].setting.formula){
                        ModalElement.alert({message: LanguageModule.text("war_txt_formula_is_invalid")});
                        return;
                    }
                }
            }
            var pList = [];
            var variablesSystemList = contentModule.getPaySheetVariableSystem();
            var t = contentModule.getCalOrderList(listSetting, variablesSystemList);
            if (!t.status){
                ModalElement.close(-1);
                return;
            }
            var res = t.content;
            var data = {};
            host.database.pay_sheet_employees.items.forEach(function(item){
                var eData = host.employee_peopleDic[item.employee_peopleid];
                if (!eData) return;
                var employee_code = eData.code;
                data[item.employee_peopleid] = {};
                res.forEach(function(columnIndex){
                    var column_code = listSetting[columnIndex].code;
                    var setting = listSetting[columnIndex].setting;
                    if (setting){
                        switch (setting.data) {
                            case "direct_input":
                                if (host.dataPay_sheetDetails && host.dataPay_sheetDetails[item.employee_peopleid] && host.dataPay_sheetDetails[item.employee_peopleid][column_code] !== undefined){
                                    data[item.employee_peopleid][column_code] = host.dataPay_sheetDetails[item.employee_peopleid][column_code];
                                }
                                else {
                                    data[item.employee_peopleid][column_code] = "";
                                }
                                break;
                            case "formula":
                                pList.push({
                                    employee_code: employee_code,
                                    func: function(){
                                        return new Promise(function(rs, rj){
                                            data[item.employee_peopleid][column_code] = setting.formula.calc(function (varname) {
                                                switch (varname) {
                                                    case "v_employeename":
                                                        return eData.fullname;
                                                    case "v_employeecode":
                                                        return eData.code;
                                                    case "v_startpropotionworkingdate":
                                                        return eData.start_date;
                                                    case "v_startofficialworkingdate":
                                                        return eData.official_date;
                                                    case "v_employeedepartment":
                                                        return host.database.orgs.items[eData.orgIndex].name;
                                                    case "v_employeeposition":
                                                        return eData.positionName;
                                                    case "v_basicsalary":
                                                        return eData.basic_salary_amount;
                                                    case "v_grosssalary":
                                                        return eData.gross_salary_amount;
                                                    case "v_salarycoefficient":
                                                        return eData.salary_coefficient;
                                                    case "v_salarygrade":
                                                        return eData.salary_grade;
                                                    case "v_standardworkdays":
                                                        return host.standard_workdays[item.employee_peopleid]? host.standard_workdays[item.employee_peopleid] : 0;
                                                    case "v_actualworkdays":
                                                        return host.actual_workdays[item.employee_peopleid]? host.actual_workdays[item.employee_peopleid] : 0;
                                                    case "v_dependentpersons":
                                                        return host.dependent_persons[item.employee_peopleid]? host.dependent_persons[item.employee_peopleid] : 0;
                                                    default:
                                                        if (data[item.employee_peopleid][varname] !== undefined){
                                                            if (EncodingClass.type.isNumber(data[item.employee_peopleid][varname]) || !absol.int.isNumber(data[item.employee_peopleid][varname])){
                                                                return data[item.employee_peopleid][varname];
                                                            }
                                                            else {
                                                                return contentModule.getValueFromMoneyFormat(data[item.employee_peopleid][varname]);
                                                            }
                                                        }
                                                        return null;
                                                }
                                            });
                                            rs();
                                        });
                                    }
                                });
                                break;
                            case "function":
                                pList.push({
                                    employee_code: employee_code,
                                    func: function(){
                                        return new Promise(function(rs, rj){
                                            var args = [];
                                            setting.function.args.forEach(function(arg){
                                                switch (arg.type) {
                                                    case "number":
                                                    case "string":
                                                        args.push(arg.value);
                                                        break;
                                                    case "employee_code":
                                                        args.push(employee_code);
                                                        break;
                                                    case "code_of_column":
                                                        args.push(data[item.employee_peopleid][arg.value]);
                                                        break;
                                                    default:

                                                }
                                            });
                                            contentModule.sclangCall(setting.function.functionid, {args: args}).then(function(value){
                                                data[item.employee_peopleid][column_code] = value;
                                                rs();
                                            });
                                        });
                                    }
                                });
                                break;
                            case "policy":
                                policys = setting.policy.split("_");
                                var list_type = policys[0];
                                var policyid = parseInt(policys[1]);
                                if (host.dataPay_sheetPolicy[list_type][policyid] && host.dataPay_sheetPolicy[list_type][policyid].employees[item.employee_peopleid]){
                                    data[item.employee_peopleid][column_code] = host.dataPay_sheetPolicy[list_type][policyid].employees[item.employee_peopleid];
                                }
                                else {
                                    data[item.employee_peopleid][column_code] = 0;
                                }
                                break;
                            case "pay_percentage":
                                var pay_percentageid = parseInt(setting.pay_percentage);
                                if (host.dataPay_sheetPay_percentage[pay_percentageid] && host.dataPay_sheetPay_percentage[pay_percentageid][item.employee_peopleid]){
                                    data[item.employee_peopleid][column_code] = host.dataPay_sheetPay_percentage[pay_percentageid][item.employee_peopleid];
                                }
                                else {
                                    data[item.employee_peopleid][column_code] = 0;
                                }
                                break;
                            default:

                        }
                    }
                });
            });
            var finishedCal = pList.reduce(function(ac, item){
                return ac.then(function(){
                    systemconfig.paysheetConfig.employee_code = item.employee_code;
                    return item.func();
                });
            }, Promise.resolve());
            finishedCal.then(function(){
                host.progressBarCalculated.value = 0.6;
                var dataSave = [], sIndex;
                host.database.pay_sheet_employees.items.forEach(function(item, index){
                    if (index%50 == 0){
                        dataSave.push([]);
                        sIndex = dataSave.length - 1;
                    }
                    var employee_peopleid = item.employee_peopleid;
                    host.database.pay_sheet_column_configs.items.forEach(function(itemSetting){
                        var column_code = itemSetting.code;
                        dataSave[sIndex].push({
                            pay_sheetid: host.dataPay_sheetEdit.id,
                            employee_peopleid: employee_peopleid,
                            code: column_code,
                            content: EncodingClass.string.fromVariable(data[employee_peopleid][column_code.toLowerCase()])
                        });
                    });
                });
                var finishedSave = dataSave.reduce(function(ac, item, index) {
                    return ac.then(function(){
                        return new Promise(function(rs) {
                            var params = [
                                {name: "data", value: EncodingClass.string.fromVariable(item)},
                                {name: "pay_sheetid", value: host.dataPay_sheetEdit.id}
                            ];
                            if (index == 0) params.push({name: "del", value: 1});
                            if (index == dataSave.length - 1) params.push({name: "done", value: 1});
                            FormClass.api_call({
                                url: "pay_sheet_save_employee_data.php",
                                params: params,
                                func: function(success, message){
                                    if (success){
                                        if (message.substr(0, 2) == "ok"){
                                            host.dataPay_sheetEdit.calculated = 1;
                                            host.progressBarCalculated.value = 0.6 + ((index + 1)/dataSave.length)*0.3;
                                            rs();
                                        }
                                        else {
                                            ModalElement.alert({message: message});
                                        }
                                    }
                                    else {
                                        ModalElement.alert({message: message});
                                    }
                                }
                            });
                        });
                    });
                }, Promise.resolve());
                finishedSave.then(function(){
                    resolve();
                });
            });
        });
    });
};

hr.pay_sheet.loadPay_sheetDataDetails = function(host, id){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_employee_data"},
                {name: "pay_sheetid", value: id}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0, 2) == "ok"){
                        var st = EncodingClass.string.toVariable(message.substr(2));
                        contentModule.makeDatabaseContent(host, st);
                        var data = {};
                        host.dataPay_sheetDetailsIdDic = {};
                        host.database.pay_sheet_employee_data.items.forEach(function(item){
                            item.content = EncodingClass.string.toVariable(item.content);
                            if (!data[item.employee_peopleid]){
                                data[item.employee_peopleid] = {};
                                host.dataPay_sheetDetailsIdDic[item.employee_peopleid] = {};
                            }
                            data[item.employee_peopleid][item.code.toLowerCase()] = item.content;
                            host.dataPay_sheetDetailsIdDic[item.employee_peopleid][item.code.toLowerCase()] = item.id;
                        });
                        resolve(data);
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.saveChangeDirectInput = function(host){
    return new Promise(function(resolve, reject){
        ModalElement.show_loading();
        var peopleIdDic = {};
        var dataInsert = [], dataUpdate = [];
        var peopleid, value;
        for (var i = 0; i < host.database.pay_sheet_employees.items.length; i++){
            peopleid = host.database.pay_sheet_employees.items[i].employee_peopleid;
            if (!host.inputidboxesDirectInput[peopleid]) continue;
            host.database.pay_sheet_column_configs.items.forEach(function(item){
                if (!host.inputidboxesDirectInput[peopleid][item.code.toLowerCase()]) return;
                value = host.inputidboxesDirectInput[peopleid][item.code.toLowerCase()].value.trim();
                if (absol.int.isNumber(value)) value = contentModule.getValueFromMoneyFormat(value);
                if (host.dataPay_sheetDetailsIdDic[peopleid] && host.dataPay_sheetDetailsIdDic[peopleid][item.code.toLowerCase()]){
                    if (value != host.dataPay_sheetDetails[peopleid][item.code.toLowerCase()]){
                        dataUpdate.push({
                            id: host.dataPay_sheetDetailsIdDic[peopleid][item.code.toLowerCase()],
                            employee_peopleid: peopleid,
                            code: item.code,
                            content: EncodingClass.string.fromVariable(value)
                        });
                        peopleIdDic[peopleid] = true;
                    }
                }
                else {
                    if (value != ""){
                        dataInsert.push({
                            id: 0,
                            pay_sheetid: host.dataPay_sheetEdit.id,
                            employee_peopleid: peopleid,
                            code: item.code,
                            content: EncodingClass.string.fromVariable(value)
                        });
                        peopleIdDic[peopleid] = true;
                    }
                }
            });
        }
        if (dataInsert.length == 0 && dataUpdate.length == 0){
            ModalElement.close(-1);
            return;
        }
        hr.pay_sheet.saveDataInsertUpdate(host, dataInsert, dataUpdate).then(function(){
            hr.pay_sheet.reCalculatedPayByChange(host, peopleIdDic).then(function(){
                resolve();
                ModalElement.close(-1);
            });
        });
    });
};

hr.pay_sheet.showApproval = function(host, id){
    var approval_methodName = "";
    var cIndex = host.database.payroll_cycle.getIndex(host.dataPay_sheetEdit.cycleid);
    switch (host.database.payroll_cycle.items[cIndex].approval_method){
        case "sequence":
            approval_methodName = LanguageModule.text("txt_sequence");
            break;
        case "parallel":
            approval_methodName = LanguageModule.text("txt_parallel");
            break;
        case "one_approver":
            approval_methodName = LanguageModule.text("txt_one_approver");
            break;
        default:

    }
    var data = [];
    host.database.pay_sheet_approvers1.items.forEach(function(item){
        if (!item.old && item.status != -1) return;
        var eData = host.employee_peopleDic[item.employee_peopleid];
        if (!eData) return;
        var statusElt;
        switch (item.status){
            case -1:
                statusElt = DOMElement.div({
                    attrs: {
                        className: "table-view-status request"
                    },
                    text: LanguageModule.text("txt_request")
                });
                break;
            case 1:
                statusElt = DOMElement.div({
                    attrs: {
                        className: "table-view-status approved"
                    },
                    text: LanguageModule.text("txt_approved")
                });
                break;
            case 2:
                statusElt = DOMElement.div({
                    attrs: {
                        className: "table-view-status deny"
                    },
                    text: LanguageModule.text("txt_deny")
                });
                break;
            default:
                statusElt = DOMElement.div({});
        }
        data.push([
            {attrs: {style: {whiteSpace: "nowrap"}}, text: contentModule.getDateTimeView(item.time)},
            {attrs: {style: {whiteSpace: "nowrap"}}, text: eData.fullname},
            {attrs: {style: {whiteSpace: "nowrap"}}, children: [statusElt]},
            {text: item.comment}
        ]);
    });
    var dic = {};
    var request_time;
    host.database.pay_sheet_approvers1.items.forEach(function(item){
        if (item.old) return;
        if (item.status == -1){
            request_time = item.time;
            return;
        }
        dic[item.employee_peopleid] = item;
    });
    host.database.payroll_cycle_approvers.items.forEach(function(item, index){
        var eData = host.employee_peopleDic[item.employee_peopleid];
        if (!eData) return;
        var time = "", comment = "";
        var aItem = dic[item.employee_peopleid];
        var status;
        if (aItem){
            time = contentModule.getDateTimeView(aItem.time);
            comment = aItem.comment;
            status = aItem.status;
        }
        else {
            switch (host.database.payroll_cycle.items[cIndex].approval_method){
                case "sequence":
                    var prevDone = true;
                    for (var i = 0; i < index; i++){
                        if (!dic[host.database.payroll_cycle_approvers.items[i].employee_peopleid]){
                            prevDone = false;
                            break;
                        }
                        else {
                            if (dic[host.database.payroll_cycle_approvers.items[i].employee_peopleid].status == 2){
                                prevDone = false;
                                break;
                            }
                        }
                    }
                    if (prevDone) status = 0;
                    break;
                case "parallel":
                case "one_approver":
                    status = 0;
                    break;
                default:

            }
        }
        var statusElt;
        switch (status){
            case 0:
                var over_due = false;
                if (request_time){
                    var remain_time = (new Date()).getTime() - (request_time.getTime() + host.database.payroll_cycle.items[cIndex].time_hours_needed_for_approval*60*60*1000);
                    if (remain_time > 0) over_due = true;
                }
                if (!over_due){
                    statusElt = DOMElement.div({
                        attrs: {
                            className: "table-view-status waiting-approval"
                        },
                        text: LanguageModule.text("txt_waiting_approval")
                    });
                }
                else {
                    statusElt = DOMElement.div({
                        attrs: {
                            className: "table-view-status over-due"
                        },
                        text: LanguageModule.text("txt_over_due")
                    });
                }
                break;
            case 1:
                statusElt = DOMElement.div({
                    attrs: {
                        className: "table-view-status approved"
                    },
                    text: LanguageModule.text("txt_approved")
                });
                break;
            case 2:
                statusElt = DOMElement.div({
                    attrs: {
                        className: "table-view-status deny"
                    },
                    text: LanguageModule.text("txt_deny")
                });
                break;
            default:
                statusElt = DOMElement.div({});
        }
        data.push([
            {attrs: {style: {whiteSpace: "nowrap"}}, text: time},
            {attrs: {style: {whiteSpace: "nowrap"}}, text: eData.fullname},
            {attrs: {style: {whiteSpace: "nowrap"}}, children: [statusElt]},
            {text: comment}
        ]);
    });
    var tableView = DOMElement.table({
        header: [
            {text: LanguageModule.text("txt_checkintime")},
            {text: LanguageModule.text("txt_employee")},
            {text: LanguageModule.text("txt_status")},
            {text: LanguageModule.text("txt_reason")}
        ],
        data: data
    });
    ModalElement.showWindow({
        title: LanguageModule.text("txt_approval_history"),
        bodycontent: DOMElement.div({
            children: [
                DOMElement.table({
                    data: [
                        [
                            {
                                attrs: {style: {lineHeight: "var(--control-height)"}},
                                text: LanguageModule.text("txt_time_hours_needed_for_approval")
                            },
                            {attrs: {style: {width: "var(--distance-between-title-value)"}}},
                            {text: host.database.payroll_cycle.items[cIndex].time_hours_needed_for_approval}
                        ],
                        [{attrs: {style: {height: "var(--control-verticle-distance-2)"}}}],
                        [
                            {
                                attrs: {style: {lineHeight: "var(--control-height)"}},
                                text: LanguageModule.text("txt_approval_method")
                            },
                            {attrs: {style: {width: "var(--distance-between-title-value)"}}},
                            approval_methodName
                        ]
                    ]
                }),
                DOMElement.div({attrs: {style: {height: "var(--control-verticle-distance-2)"}}}),
                DOMElement.div({
                    attrs: {className: "cardsimpletableclass"},
                    children: [tableView]
                })
            ]
        }),
        buttonlist: [
            {
                text: LanguageModule.text("txt_close"),
                onclick: function(){
                    ModalElement.close();
                }
            }
        ]
    });
};

hr.pay_sheet.requestPay_sheet = function(host, id){
    ModalElement.show_loading();
    FormClass.api_call({
        url: "pay_sheet_request.php",
        params: [
            {name: "pay_sheetid", value: id},
            {name: "employeeid", value: host.employeeOfMe[0]},
            {name: "employee_peopleid", value: host.peopleOfMe}
        ],
        func: function(success, message){
            ModalElement.close(-1);
            if (success){
                if (message.substr(0, 2) == "ok"){
                    var st = EncodingClass.string.toVariable(message.substr(2));
                    host.dataPay_sheetEdit = st.data;
                    delete st.data;
                    contentModule.makeDatabaseContent(host, st);
                    hr.pay_sheet.makePrivApproval(host, id);
                    host.redrawTableFunc();
                    host.redrawHeaderViewFunc();
                    var index = host.database.pay_sheet.getIndex(id);
                    host.database.pay_sheet.items[index] = host.dataPay_sheetEdit;
                    hr.pay_sheet.redraw(host);
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
            else {
                ModalElement.alert({message: message})
            }
        }
    });
};

hr.pay_sheet.requestPay_sheetConfirm = function(host, id){
    ModalElement.question({
        title: LanguageModule.text("war_title_request_pay_sheet"),
        message: LanguageModule.text2("war_txt_request_pay_sheet", [host.dataPay_sheetEdit.name]),
        onclick: function(sel){
            if (sel == 0){
                hr.pay_sheet.requestPay_sheet(host, id);
            }
        }
    });
};

hr.pay_sheet.exportPaysheet = function(host, id){
    ModalElement.alert({message: LanguageModule.text("txt_export_notification")});
    var exportContent = {
        row: 0,
        col: 0,
        data: [
            {
                row: 0,
                col: 0,
                colSpan: 5,
                value: host.dataPay_sheetEdit.name,
                bold: true,
                horizontal: "center",
                vertical: "middle"
            }
        ]
    };
    exportContent.row = 2;
    exportContent.data.push({
        row: exportContent.row,
        col: exportContent.col++,
        value: LanguageModule.text("txt_index"),
        bold: true,
        backgroundcolor: "FFEBEBEB",
        horizontal: "center",
        vertical: "middle"
    });
    for (var i = 0; i < host.database.pay_sheet_column_configs.items.length; i++){
        exportContent.data.push({
            row: exportContent.row,
            col: exportContent.col++,
            value: host.database.pay_sheet_column_configs.items[i].name,
            bold: true,
            backgroundcolor: "FFEBEBEB",
            horizontal: "center",
            vertical: "middle"
        });
    }
    var data = host.dataPay_sheetDetails;
    var index = 0, peopleid, eData;
    for (var i = 0; i < host.database.pay_sheet_employees.items.length; i++){
        peopleid = host.database.pay_sheet_employees.items[i].employee_peopleid;
        eData = host.employee_peopleDic[peopleid];
        exportContent.row++;
        index++;
        exportContent.col = 0;
        exportContent.data.push({
            row: exportContent.row,
            col: exportContent.col++,
            value: index
        });
        host.database.pay_sheet_column_configs.items.forEach(function(item){
            var value = "";
            if (data[peopleid] && data[peopleid][item.code] !== undefined) value = data[peopleid][item.code];
            if (absol.int.isNumber(value)){
                value = parseFloat(value);
            }
            var celldata = {
                row: exportContent.row,
                col: exportContent.col++,
                value: value
            };
            if (absol.int.isNumber(value)){
                celldata.numFmt = "#,##0.0";
            }
            exportContent.data.push(celldata);
        });
    }
    var excelData = {
        sheets: [
            {
                name: "Pay_sheet",
                data: exportContent.data
            }
        ]
    };
    var x = contentModule.getDateTimeExcelExport(new Date());
    var startWorker = function(result, fileName = host.dataPay_sheetEdit.name + "_" +x+".xlsx") {
        var w;
        if(typeof(Worker) !== "undefined") {
            if(typeof(w) == "undefined") {
                w = new Worker(window.domain + "exceljs.js");
                w.postMessage(result);
            }
            w.onmessage = function(event) {
                var data = event.data;
                if(data.name == "end")
                {
                    var link = document.createElement('a');
                    link.href = window.URL.createObjectURL(data.data);
                    link.download = fileName;
                    link.click();
                }
            }
        } else {
            console.log("Sorry, your browser does not support Web Workers...");
        }
    }
    startWorker(excelData);
};

hr.pay_sheet.exportDirectInputColumn = function(host, id){
    ModalElement.alert({message: LanguageModule.text("txt_export_notification")});
    var hasExportDic = {
        EmployeeCode: true,
        EmployeeName: true,
        EmployeeDepartment: true,
        EmployeePosition: true
    };
    var exportContent = {
        row: 0,
        col: 0,
        data: [
            {
                row: 0,
                col: 0,
                colSpan: 5,
                value: host.dataPay_sheetEdit.name,
                bold: true,
                horizontal: "center",
                vertical: "middle"
            }
        ]
    };
    exportContent.row = 2;
    exportContent.data.push({
        row: exportContent.row,
        col: exportContent.col,
        value: LanguageModule.text("txt_index"),
        bold: true,
        backgroundcolor: "FFEBEBEB",
        horizontal: "center",
        vertical: "middle"
    });
    exportContent.data.push({
        row: exportContent.row + 1,
        col: exportContent.col++,
        value: "",
        bold: true,
        backgroundcolor: "FFEBEBEB",
        horizontal: "center",
        vertical: "middle"
    });
    host.database.pay_sheet_column_configs.items.forEach(function(item){
        var isExport = false;
        if (hasExportDic[item.code]) isExport = true;
        else if (item.setting && item.setting.data == "direct_input") isExport = true;
        if (!isExport) return;
        exportContent.data.push({
            row: exportContent.row,
            col: exportContent.col,
            value: item.name,
            bold: true,
            backgroundcolor: "FFEBEBEB",
            horizontal: "center",
            vertical: "middle"
        });
        exportContent.data.push({
            row: exportContent.row + 1,
            col: exportContent.col++,
            value: item.code,
            backgroundcolor: "FFEBEBEB",
            horizontal: "center",
            vertical: "middle"
        });
    });
    exportContent.row++;
    var data = host.dataPay_sheetDetails;
    var index = 0, peopleid, eData;
    for (var i = 0; i < host.database.pay_sheet_employees.items.length; i++){
        peopleid = host.database.pay_sheet_employees.items[i].employee_peopleid;
        eData = host.employee_peopleDic[peopleid];
        exportContent.row++;
        index++;
        exportContent.col = 0;
        exportContent.data.push({
            row: exportContent.row,
            col: exportContent.col++,
            value: index
        });
        host.database.pay_sheet_column_configs.items.forEach(function(item){
            var isExport = false;
            if (hasExportDic[item.code]) isExport = true;
            else if (item.setting && item.setting.data == "direct_input") isExport = true;
            if (!isExport) return;
            var value = "";
            if (data[peopleid] && data[peopleid][item.code] !== undefined) value = data[peopleid][item.code];
            if (absol.int.isNumber(value)){
                value = parseFloat(value);
            }
            var celldata = {
                row: exportContent.row,
                col: exportContent.col++,
                value: value
            };
            if (absol.int.isNumber(value)){
                celldata.numFmt = "#,##0.0";
            }
            exportContent.data.push(celldata);
        });
    }
    var excelData = {
        sheets: [
            {
                name: "Pay_sheet_direct_input",
                data: exportContent.data
            }
        ]
    };
    var x = contentModule.getDateTimeExcelExport(new Date());
    var startWorker = function(result, fileName = host.dataPay_sheetEdit.name + "_" +x+".xlsx") {
        var w;
        if(typeof(Worker) !== "undefined") {
            if(typeof(w) == "undefined") {
                w = new Worker(window.domain + "exceljs.js");
                w.postMessage(result);
            }
            w.onmessage = function(event) {
                var data = event.data;
                if(data.name == "end")
                {
                    var link = document.createElement('a');
                    link.href = window.URL.createObjectURL(data.data);
                    link.download = fileName;
                    link.click();
                }
            }
        } else {
            console.log("Sorry, your browser does not support Web Workers...");
        }
    }
    startWorker(excelData);
};

hr.pay_sheet.importDirectInputColumn = function(host, id, fi){
    var f = new FileReader();
    f.onload = (function (fname) {
        return function (e) {
            var peopleIdList = [];
            for (var i = 0; i < host.database.pay_sheet_employees.items.length; i++){
                peopleIdList.push(host.database.pay_sheet_employees.items[i].employee_peopleid);
            }
            peopleIdList.sort(function(a, b){
                return a - b;
            });
            var column_configs_direct_input = {};
            host.database.pay_sheet_column_configs.items.forEach(function(item){
                if (item.setting && item.setting.data == "direct_input"){
                    column_configs_direct_input[item.code] = 1;
                }
            });
            ModalElement.show_loading();
            excel_module.load(f.result).then(function(rs){
                FormClass.api_call({
                    url: "pay_sheet_import_direct_input.php",
                    params: [
                        {
                            name: "exc_data",
                            value: EncodingClass.string.fromVariable(rs)
                        },
                        {
                            name: "peopleIdList",
                            value: EncodingClass.string.fromVariable(peopleIdList)
                        },
                        {
                            name: "column_configs_direct_input",
                            value: EncodingClass.string.fromVariable(column_configs_direct_input)
                        },
                        {
                            name: "pay_sheetid",
                            value: id
                        }
                    ],
                    func: function (success, message) {
                        if (success) {
                            if (message.substr(0, 2) == "ok"){
                                var st = EncodingClass.string.toVariable(message.substr(2));
                                var peopleIdDic = {};
                                for (var i = 0; i < st.length; i++){
                                    st[i].content = EncodingClass.string.toVariable(st[i].content);
                                    peopleIdDic[st[i].employee_peopleid] = true;
                                    if (!host.dataPay_sheetDetails[st[i].employee_peopleid]){
                                        host.dataPay_sheetDetails[st[i].employee_peopleid] = {};
                                        host.dataPay_sheetDetailsIdDic[st[i].employee_peopleid] = {};
                                    }
                                    host.dataPay_sheetDetails[st[i].employee_peopleid][st[i].code] = st[i].content;
                                    host.dataPay_sheetDetailsIdDic[st[i].employee_peopleid][st[i].code] = st[i].id;
                                }
                                hr.pay_sheet.reCalculatedPayByChange(host, peopleIdDic).then(function(values){
                                    ModalElement.close(-1);
                                    host.redrawTableFunc();
                                });
                            }
                            else if (message == "no_employee_code_column"){
                                ModalElement.alert({message: "Không tìm thấy cột mã nhân viên"});
                            }
                            else if (message.startsWith("employee_code_invalid_")){
                                var row = message.substr("employee_code_invalid_".length);
                                ModalElement.alert({message: "Mã nhân viên ở dòng " + row + " không tồn tại"});
                            }
                            else if (message == "no_sheet") {
                                ModalElement.alert({message: "Không tìm thấy sheet: Pay_sheet_direct_input"});
                            }
                            else if (message.startsWith("duplicate_employee_code_")){
                                var code = message.substr("duplicate_employee_code_".length);
                                ModalElement.alert({message: "Mã nhân viên " + code + " bị trùng lặp"});
                            }
                            else if (message.startsWith("duplicate_column_code_")){
                                var code = message.substr("duplicate_column_code_".length);
                                ModalElement.alert({message: "Mã cột " + code + " bị trùng lặp"});
                            }
                            else if (message == "no_data"){
                                ModalElement.close(-1);
                            }
                            else {
                                ModalElement.alert({
                                    message: message
                                });
                                return;
                            }
                        }
                        else {
                            ModalElement.alert({
                                message: message
                            });
                            return;
                        }
                    }
                });
            });
        }
    }(fi.value));
    f.readAsArrayBuffer(fi.files[0]);
    setTimeout(function(){
        fi.value = "";
    }, 1000);
};

hr.pay_sheet.getPayslipElt = function(host, peopleid){
    return new Promise(function(resolve, reject){
        var f = function(){
            var eData = host.employee_peopleDic[peopleid];
            var dataDic = host.dataPay_sheetDetails;
            var notDetailsDic = {
                EmployeeCode: true,
                EmployeeName: true,
                EmployeePosition: true,
                EmployeeDepartment: true,
                BasicSalary: true,
                GrossSalary: true,
                StandardWorkdays: true,
                ActualWorkdays: true
            };
            var details = [];
            if (dataDic[peopleid]){
                host.database.pay_sheet_column_configs.items.forEach(function(item){
                    if (notDetailsDic[item.code]) return;
                    var amount = 0;
                    if (dataDic[peopleid][item.code]) amount = dataDic[peopleid][item.code];
                    details.push({
                        name: item.name,
                        description: item.description,
                        amount: amount
                    });
                });
            }
            var data = {
                company_name: host.config_company.name,
                company_address: host.config_company.address,
                company_logo: host.config_company.logoSrc,
                paysheet_name: host.dataPay_sheetEdit.name,
                employee_code: (dataDic[peopleid] && dataDic[peopleid].EmployeeCode)? dataDic[peopleid].EmployeeCode : "",
                employee_name: (dataDic[peopleid] && dataDic[peopleid].EmployeeName)? dataDic[peopleid].EmployeeName : "",
                position: (dataDic[peopleid] && dataDic[peopleid].EmployeePosition)? dataDic[peopleid].EmployeePosition : "",
                department: (dataDic[peopleid] && dataDic[peopleid].EmployeeDepartment)? dataDic[peopleid].EmployeeDepartment : "",
                bank_account: eData.bank_account_number,
                bank_name: eData.bank_name,
                account_holder_name: eData.bank_account_holder_name,
                basic_salary: (dataDic[peopleid] && dataDic[peopleid].BasicSalary)? dataDic[peopleid].BasicSalary : 0,
                gross_salary: (dataDic[peopleid] && dataDic[peopleid].GrossSalary)? dataDic[peopleid].GrossSalary : 0,
                actual_workdays: (dataDic[peopleid] && dataDic[peopleid].StandardWorkdays)? dataDic[peopleid].StandardWorkdays : 0,
                standard_workdays: (dataDic[peopleid] && dataDic[peopleid].ActualWorkdays)? dataDic[peopleid].ActualWorkdays : 0,
                details: details,
                employee_signature: (dataDic[peopleid] && dataDic[peopleid].EmployeeName)? dataDic[peopleid].EmployeeName : "",
            };
            var bodycontent = DOMElement.div({});
            contentModule.makeOutputFormData({
                typeid: host.form_config.payslip.typeid,
                formid: host.form_config.payslip.output_form,
                initialValue: data,
                formContainer: bodycontent,
                typelists: host.database.typelists.items,
                variableType: "system"
            }).then(function(getValue){
                var employee_name = (dataDic[peopleid] && dataDic[peopleid].EmployeeName)? dataDic[peopleid].EmployeeName : "";
                resolve({
                    elt: bodycontent,
                    filename: "Payslip_" + absol.string.normalizeIdent(employee_name) + ".pdf",
                    footer: employee_name
                });
            });
        };
        if (!host.config_company){
            ModalElement.show_loading();
            hr.options.loadDataCompany().then(function(value){
                host.config_company = value;
                f();
            });
        }
        else {
            f();
        }
    });
};

hr.pay_sheet.viewPayslip = function(host, peopleid){
    hr.pay_sheet.getPayslipElt(host, peopleid).then(function(res){
        ModalElement.showWindow({
            title: LanguageModule.text("txt_payslip"),
            bodycontent: res.elt,
            buttonlist: [
                {
                    text: LanguageModule.text("txt_close"),
                    onclick: function(){
                        ModalElement.close();
                    }
                },
                {
                    text: LanguageModule.text("txt_export"),
                    onclick: function(){
                        var fragElt = absol.$('.as-fm-fragment', res.elt);//get form element safely
                        if (fragElt) absol.printer.downloadAsPDF(fragElt, res.filename);
                    }
                }
            ]
        });
    });
};

hr.pay_sheet.exportPayslip = function(host, peopleid){
    ModalElement.show_loading();
    hr.pay_sheet.getPayslipElt(host, peopleid).then(function(res){
        DOMElement.removeAllChildren(DOMElement.hiddendiv);
        DOMElement.hiddendiv.appendChild(res.elt);
        setTimeout(function(){
            ModalElement.close(-1);
            absol.printer.downloadAsPDF(res.elt, res.filename);
        }, 500);
    });
};

hr.pay_sheet.exportPayslipList = function(host){
    var f = function(){
        var peopleIdList = [];
        var employeeIdView = host.employee_select.values;
        var employeeIdViewDic = {};
        employeeIdView.forEach(function(employeeid){
            employeeIdViewDic[employeeid] = true;
        });
        var dataTable = [];
        var row, eData;
        for (var i = 0; i < host.database.pay_sheet_employees.items.length; i++){
            eData = host.employee_peopleDic[host.database.pay_sheet_employees.items[i].employee_peopleid];
            if (!employeeIdViewDic[eData.id]) continue;
            peopleIdList.push(host.database.pay_sheet_employees.items[i].employee_peopleid);
        }
        var docs = [];
        peopleIdList.forEach(function(peopleid, index){
            docs.push({
                index: index,
                peopleid: peopleid,
                opt: {
                    // footer: "Form thứ "+ index
                },
                render: function (holderDiv, data){
                    return hr.pay_sheet.getPayslipElt(host, peopleid).then(function(res){
                        var fragElt = absol.$('.as-fm-fragment', res.elt);
                        // data.opt.footer = res.footer;
                        if (fragElt) holderDiv.addChild(fragElt);
                    });
                }
            });
        });
        absol.printer.silentDownloadAsPdf({
            parallel: 64,
            fileName: "Payslip_" + contentModule.getDateTimeExcelExport(new Date()) + ".pdf",
            docs: docs
        });
    };
    if (!host.config_company){
        ModalElement.show_loading();
        hr.options.loadDataCompany().then(function(value){
            host.config_company = value;
            f();
        });
    }
    else {
        f();
    }
};

hr.pay_sheet.showPay_sheet = function(host, id){
    systemconfig.paysheetConfig = {};
    hr.sclang.global.declareVar('paysheetConfig', systemconfig.paysheetConfig, true);
    host.updateProcessBar = function(){
        if (!host.progressBarCalculated) return;
        host.taskDone++;
        host.progressBarCalculated.value = (host.taskDone/host.totalTask)*0.5;
    };
    host.pay_sheetid = id;
    ModalElement.show_loading();
    Promise.all([hr.pay_sheet.loadColumConfigs(host, id), hr.pay_sheet.loadPay_sheetDataView(host, id), hr.pay_sheet.loadPay_sheet_employeesList(host, id)]).then(function(values){
        var saveBtnCtn;
        host.redrawHeaderViewFunc = function(){
            DOMElement.removeAllChildren(button_header_ctn);
            button_header_ctn.appendChild(DOMElement.div({
                attrs: {className: "single-button-header"},
                children: [theme.backButton({
                    onclick: function(){
                        host.frameList.removeLast();
                    }
                })]
            }));
            if (systemconfig.privSystem >= 2 || data_module.admin_rights_of_me.pay_sheet){
                if (host.dataPay_sheetEdit.status == 0 || host.dataPay_sheetEdit.status == 2){
                    saveBtnCtn = DOMElement.div({
                        attrs: {className: "single-button-header hidden"},
                        children: [theme.saveButton({
                            onclick: function(){
                                hr.pay_sheet.saveChangeDirectInput(host).then(function(value){
                                    host.redrawTableFunc();
                                });
                            }
                        })]
                    });
                    button_header_ctn.appendChild(saveBtnCtn);
                    button_header_ctn.appendChild(
                        DOMElement.div({
                            attrs: {className: "single-button-header"},
                            children: [theme.addButton({
                                text: LanguageModule.text("txt_payroll"),
                                onclick: function(){
                                    host.progressBarCalculated = absol.buildDom({
                                        tag: 'progressbar',
                                        style: {
                                            width: "600px",
                                            maxWidth: "80vw",
                                            fontSize: "2em"
                                        },
                                        props: {
                                            variant: "success",
                                            value: 0,
                                            animated: true
                                        }
                                    });
                                    ModalElement.show({
                                        bodycontent: host.progressBarCalculated
                                    });
                                    hr.pay_sheet.calculatedPay(host).then(function(value){
                                        hr.pay_sheet.loadPay_sheetDataDetails(host, id).then(function(value){
                                            saveBtnCtn.classList.remove("hidden");
                                            host.dataPay_sheetDetails = value;
                                            host.progressBarCalculated.value = 1;
                                            ModalElement.close();
                                            host.redrawTableFunc();
                                        });
                                    });
                                }
                            })]
                        })
                    );
                    if (host.dataPay_sheetEdit.calculated){
                        button_header_ctn.appendChild(
                            DOMElement.div({
                                attrs: {className: "single-button-header"},
                                children: [theme.addButton({
                                    text: LanguageModule.text("txt_proposal"),
                                    onclick: function(){
                                        hr.pay_sheet.requestPay_sheetConfirm(host, id);
                                    }
                                })]
                            })
                        );
                    }
                }
            }
            if (host.privApproval){
                button_header_ctn.appendChild(DOMElement.div({
                    attrs: {className: "single-button-header"},
                    children: [theme.approvalButton({
                        onclick: function(){
                            hr.pay_sheet.approvalPay_sheet(host, id);
                        }
                    })]
                }));
                button_header_ctn.appendChild(DOMElement.div({
                    attrs: {className: "single-button-header"},
                    children: [theme.denyButton({
                        onclick: function(){
                            hr.pay_sheet.denyPay_sheetConfirm(host, id);
                        }
                    })]
                }));
            }
            if (host.dataPay_sheetEdit.calculated){
                var qmenuButton = DOMElement.div({
                    attrs: {
                        className: "card-icon-cover"
                    },
                    children: [DOMElement.i({
                        attrs: {
                            className: "material-icons bsc-icon-hover-black"
                        },
                        text: "more_vert"
                    })]
                });
                absol.QuickMenu.toggleWhenClick(qmenuButton, {
                    getMenuProps: function(){
                        var quickMenuItems = [
                            {
                                text: LanguageModule.text("txt_export_pay_sheet"),
                                extendClasses: "bsc-quickmenu",
                                icon: DOMElement.i({
                                    attrs: {
                                        className: "mdi mdi-export"
                                    }
                                }),
                                cmd: function(){
                                    hr.pay_sheet.exportPaysheet(host, id);
                                }
                            },
                            {
                                text: LanguageModule.text("txt_export_direct_input_column"),
                                extendClasses: "bsc-quickmenu",
                                icon: DOMElement.i({
                                    attrs: {
                                        className: "mdi mdi-export"
                                    }
                                }),
                                cmd: function(){
                                    hr.pay_sheet.exportDirectInputColumn(host, id);
                                }
                            }
                        ];
                        if (systemconfig.privSystem >= 2 || data_module.admin_rights_of_me.pay_sheet){
                            if (host.dataPay_sheetEdit.status == 0 || host.dataPay_sheetEdit.status == 2){
                                quickMenuItems.push({
                                    text: LanguageModule.text("txt_import_direct_input_column"),
                                    extendClasses: "bsc-quickmenu",
                                    icon: DOMElement.i({
                                        attrs: {
                                            className: "mdi mdi-import"
                                        }
                                    }),
                                    cmd: function(){
                                        uploadwindow.click();
                                    }
                                });
                            }
                            var uploadwindow = DOMElement.input({
                            	attrs: {
                                    type: "file",
                                    style: {display: "none"}
                                }
                            });
                            uploadwindow.onchange = function(){
                                hr.pay_sheet.importDirectInputColumn(host, id, this);
                            };
                        }
                        if (host.dataPay_sheetEdit.status != 0){
                            quickMenuItems.push({
                                text: LanguageModule.text("txt_approval_history"),
                                extendClasses: "bsc-quickmenu",
                                icon: DOMElement.i({
                                    attrs: {
                                        className: "mdi mdi-account-clock"
                                    }
                                }),
                                cmd: function(){
                                    hr.pay_sheet.showApproval(host, id);
                                }
                            });
                        }
                        quickMenuItems.push({
                            text: LanguageModule.text("txt_export_payslip"),
                            extendClasses: "bsc-quickmenu",
                            icon: DOMElement.i({
                                attrs: {
                                    className: "mdi mdi-export"
                                }
                            }),
                            cmd: function(){
                                hr.pay_sheet.exportPayslipList(host);
                            }
                        });
                        return {items: quickMenuItems};
                    },
                    onSelect: function (item){
                        item.cmd();
                    }
                });
                button_header_ctn.appendChild(DOMElement.div({
                    attrs: {className: "single-button-header"},
                    children: [qmenuButton]
                }));
                button_header_ctn.appendChild(DOMElement.div({
                    attrs: {className: "single-button-header"},
                    children: [host.employee_select]
                }));
                button_header_ctn.appendChild(DOMElement.div({
                    attrs: {className: "single-button-header"},
                    children: [inputsearchbox]
                }));
                var statusElt;
                var cIndex = host.database.payroll_cycle.getIndex(host.dataPay_sheetEdit.cycleid);
                var request_time;
                host.database.pay_sheet_approvers1.items.forEach(function(item){
                    if (item.status == -1){
                        request_time = item.time;
                    }
                });
                switch (host.dataPay_sheetEdit.status) {
                    case -1:
                        var over_due = false;
                        if (request_time){
                            var remain_time = (new Date()).getTime() - (request_time.getTime() + host.database.payroll_cycle.items[cIndex].time_hours_needed_for_approval*60*60*1000);
                            if (remain_time > 0) over_due = true;
                        }
                        if (!over_due){
                            statusElt = DOMElement.div({
                                attrs: {
                                    className: "hr-status-view-btn waiting-approval"
                                },
                                text: LanguageModule.text("txt_waiting_approval")
                            });
                        }
                        else {
                            statusElt = DOMElement.div({
                                attrs: {
                                    className: "hr-status-view-btn over-due"
                                },
                                text: LanguageModule.text("txt_over_due")
                            });
                        }
                        break;
                    case 0:
                        statusElt = DOMElement.div({
                            attrs: {
                                className: "hr-status-view-btn new"
                            },
                            text: LanguageModule.text("txt_new")
                        });
                        break;
                    case 1:
                        statusElt = DOMElement.div({
                            attrs: {
                                className: "hr-status-view-btn approved"
                            },
                            text: LanguageModule.text("txt_approved")
                        });
                        break;
                    case 2:
                        statusElt = DOMElement.div({
                            attrs: {
                                className: "hr-status-view-btn deny"
                            },
                            text: LanguageModule.text("txt_deny")
                        });
                        break;

                }
                button_header_ctn.appendChild(DOMElement.div({
                    attrs: {style: {marginTop: "10px"}},
                    children: [DOMElement.div({
                        attrs: {
                            className: "hr-intro-view-form"
                        },
                        children: [
                            DOMElement.table({
                                data: [[
                                    DOMElement.span({
                                        attrs: {
                                            style: {
                                                marginRight: "var(--control-horizontal-distance-1)",
                                                fontWeight: "bold"
                                            }
                                        },
                                        text: LanguageModule.text("txt_pay_sheet")
                                    }),
                                    DOMElement.span({text: host.dataPay_sheetEdit.name}),
                                    {attrs: {style: {width: "20px"}}},
                                    statusElt
                                ]]
                            })
                        ]
                    })]
                }));
            }
        };
        host.redrawTableFunc = function(){
            var fontValue = getComputedStyle(document.body).getPropertyValue('--font');
            host.inputidboxesDirectInput = {};
            var data = host.dataPay_sheetDetails;
            var getRow = function(peopleid){
                host.inputidboxesDirectInput[peopleid] = {};
                function applyParam(elt){
                    return elt;
                };
                var cells = [
                    {
                        style: {textAlign: "center"},
                        render: function(tdElt){
                            tdElt.addChild(DOMElement.span({attrs: {className: "as-dt-row-index"}}));
                        }
                    }
                ];
                host.database.pay_sheet_column_configs.items.forEach(function(item){
                    if (item.hidden) return;
                    var value = "";
                    if (data[peopleid] && data[peopleid][item.code.toLowerCase()] !== undefined) value = data[peopleid][item.code.toLowerCase()];
                    var isNumber = 0;
                    if (absol.int.isNumber(value)){
                        switch (item.format) {
                            case "1,234":
                                value = contentModule.moneyFormat2(value, 0, 0);
                                break;
                            case "1,234.1":
                                value = contentModule.moneyFormat2(value, 0, 1);
                                break;
                            case "1,234.21":
                                value = contentModule.moneyFormat2(value, 0, 2);
                                break;
                            case "1,234.321":
                                value = contentModule.moneyFormat2(value, 0, 3);
                                break;
                            default:
                                value = contentModule.moneyFormat2(value, 0, 0);
                        }
                        isNumber = 1;
                    }
                    else if (EncodingClass.type.isDate(value)){
                        switch (item.format) {
                            case "dd/mm/yyyy":
                                value = contentModule.getDateView(value);
                                break;
                            case "dd/mm/yyyy hh:ss":
                                value = contentModule.getDateTimeView(value);
                                break;
                            case "hh:ss":
                                value = contentModule.getTimeView(value);
                                break;
                            default:

                        }
                    }
                    celldata = {
                        innerText: value,
                        render: function(tdElt){
                            if (item.setting && item.setting.data == "direct_input"){
                                host.inputidboxesDirectInput[peopleid][item.code.toLowerCase()] = theme.input({
                                    value: value
                                });
                                if (systemconfig.privSystem < 2 && !data_module.admin_rights_of_me.pay_sheet) host.inputidboxesDirectInput[peopleid][item.code.toLowerCase()].disabled = true;
                                if (host.dataPay_sheetEdit.status != 0 && host.dataPay_sheetEdit.status != 2) host.inputidboxesDirectInput[peopleid][item.code.toLowerCase()].disabled = true;
                                if (isNumber) host.inputidboxesDirectInput[peopleid][item.code.toLowerCase()].style.textAlign = "right";
                                tdElt.addChild(host.inputidboxesDirectInput[peopleid][item.code.toLowerCase()]);
                            }
                            else {
                                tdElt.addChild(DOMElement.div({text: value}));
                            }
                        }
                    };
                    if (isNumber) celldata.style = {textAlign: "right"};
                    cells.push(celldata);
                });
                cells.push({
                    style: {width: "40px", textAlign: "center"},
                    render: function(tdElt){
                        var qmenuButton = DOMElement.div({
                            attrs: {
                                className: "card-icon-cover"
                            },
                            children: [DOMElement.i({
                                attrs: {
                                    className: "material-icons bsc-icon-hover-black"
                                },
                                text: "more_vert"
                            })]
                        });
                        absol.QuickMenu.toggleWhenClick(qmenuButton, {
                            getMenuProps: function(){
                                var quickMenuItems = [];
                                quickMenuItems.push({
                                    text: LanguageModule.text("txt_view_payslip"),
                                    extendClasses: "bsc-quickmenu",
                                    icon: DOMElement.i({
                                        attrs: {
                                            className: "material-icons"
                                        },
                                        text: "visibility"
                                    }),
                                    cmd: function(){
                                        hr.pay_sheet.viewPayslip(host, peopleid);
                                    }
                                });
                                quickMenuItems.push({
                                    text: LanguageModule.text("txt_export_payslip"),
                                    extendClasses: "bsc-quickmenu",
                                    icon: DOMElement.i({
                                        attrs: {
                                            className: "mdi mdi-export"
                                        }
                                    }),
                                    cmd: function(){
                                        hr.pay_sheet.exportPayslip(host, peopleid);
                                    }
                                });
                                return {items: quickMenuItems};
                            },
                            onSelect: function (item){
                               item.cmd();
                            },
                            anchor: [3, 4]
                        });
                        tdElt.addChild(qmenuButton);
                    }
                });
                var row = {
                    cells: cells
                };
                return row;
            };
            DOMElement.removeAllChildren(data_ctn);
            var header = [
                {
                    id: "index",
                    child: DOMElement.span({text: LanguageModule.text("txt_index")})
                }
            ];
            for (var i = 0; i < host.database.pay_sheet_column_configs.items.length; i++){
                if (host.database.pay_sheet_column_configs.items[i].hidden) continue;
                header.push({
                    id: host.database.pay_sheet_column_configs.items[i].code,
                    child: DOMElement.span({text: host.database.pay_sheet_column_configs.items[i].name})
                });
            }
            header.push({});
            var employeeIdView = host.employee_select.values;
            var employeeIdViewDic = {};
            var eData;
            host.database.pay_sheet_employees.items.forEach(function(item){
                eData = host.employee_peopleDic[item.employee_peopleid];
                employeeIdViewDic[eData.id] = true;
            });
            var dataTable = [];
            if (host.dataPay_sheetEdit.calculated){
                var row, k;
                for (var i = 0; i < employeeIdView.length; i++){
                    if (!employeeIdViewDic[employeeIdView[i]]) continue;
                    k = host.employeesDic[employeeIdView[i]];
                    if (k >= 0){
                        row = getRow(host.database.employees.items[k].peopleid);
                        if (row) dataTable.push(row);
                    }
                }
            }
            var tableView = absol.buildDom({
                tag: "dynamictable",
                props: {
                    id: "pay_sheet_details",
                    adapter: {
                       fixedCol: 3,
                       data: {
                           head: {
                               rows: [
                                   {
                                       cells: header
                                   }
                               ]
                           },
                           body: {
                               rows: dataTable
                           }
                       }
                   }
               },
               on: {
                   orderchange: function(event){
                       changeIndexFunc(event.from, event.to);
                   }
               }
            });
            tableView.attachSearchInput(inputsearchbox);
            data_ctn.appendChild(tableView);
        };
        var orgEmpItems = contentModule.getOrgsAndEmployeesListSelectTreeMenuLeaf(host);
        var values = [];
        host.database.employees.items.forEach(function(item){
            values.push(item.id);
        });
        host.employee_select = absol.buildDom({
            tag: "multichecktreemenu",
            props: {
                items: orgEmpItems,
                values: values,
                leafOnly: true,
                enableSearch: true
            },
            on: {
                change: function(){
                    if (host.dataPay_sheetEdit.calculated){
                        host.redrawTableFunc();
                    }
                }
            }
        });
        var inputsearchbox = absol.buildDom({
            tag:'searchcrosstextinput',
            style: {
                width: "var(--searchbox-width)"
            },
            props:{
                placeholder: LanguageModule.text("txt_search")
            }
        });
        var button_header_ctn = DOMElement.div({
            attrs: {className: 'button-panel-header absol-single-page-header'}
        });
        var data_ctn = DOMElement.div({attrs: {style: {paddingTop: "var(--control-verticle-distance-2)"}}});
        var singlePage = absol.buildDom({
            tag: "singlepage",
            child: [
                button_header_ctn,
                data_ctn
            ]
        });
        host.frameList.addChild(singlePage);
        singlePage.requestActive();
        host.redrawHeaderViewFunc();
        if (host.dataPay_sheetEdit.calculated){
            hr.pay_sheet.loadPay_sheetDataDetails(host, id).then(function(value){
                host.dataPay_sheetDetails = value;
                ModalElement.close(-1);
                if (saveBtnCtn) saveBtnCtn.classList.remove("hidden");
                host.redrawTableFunc();
            });
        }
        else {
            ModalElement.close(-1);
            host.redrawTableFunc();
        }
    });
};

hr.pay_sheet.loadColumConfigs = function(host, id){
    return new Promise(function(resolve, reject){
        FormClass.api_call({
            url: "database_load.php",
            params: [
                {name: "task", value: "pay_sheet_load_column_configs"},
                {name: "id", value: id}
            ],
            func: function(success, message){
                if (success){
                    if (message.substr(0, 2) == "ok"){
                        var st = EncodingClass.string.toVariable(message.substr(2));
                        contentModule.makeDatabaseContent(host, st);
                        host.database.pay_sheet_column_configs.items.forEach(function(item){
                            if (item.setting){
                                item.setting = EncodingClass.string.toVariable(item.setting);
                            }
                        });
                        resolve();
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
                else {
                    ModalElement.alert({message: message});
                }
            }
        });
    });
};

hr.pay_sheet.getFormatItems = function(){
    return [
        {value: "Text", text: "Text"},
        {value: "1,234", text: "1,234"},
        {value: "1,234.1", text: "1,234.1"},
        {value: "1,234.21", text: "1,234.21"},
        {value: "1,234.321", text: "1,234.321"},
        {value: "dd/mm/yyyy", text: "dd/mm/yyyy"},
        {value: "dd/mm/yyyy hh:ss", text: "dd/mm/yyyy hh:ss"},
        {value: "hh:ss", text: "hh:ss"}
    ];
};

hr.pay_sheet.columnConfigs = function(host, id){
    host.pay_sheetid = id;
    ModalElement.show_loading();
    hr.pay_sheet.loadColumConfigs(host, id).then(function(){
        var index = host.database.pay_sheet.getIndex(id);
        var status = host.database.pay_sheet.items[index].status;
        ModalElement.close(-1);
        var changeIndexFunc = function(from, to){
            var data = host.database.pay_sheet_column_configs.items[from];
            host.database.pay_sheet_column_configs.items.splice(from, 1);
            host.database.pay_sheet_column_configs.items.splice(to, 0, data);
            var listUpdateIndex = [], item;
            for (var i = 0; i < host.database.pay_sheet_column_configs.items.length; i++){
                if (i != host.database.pay_sheet_column_configs.items[i].cindex){
                    item = {
                        id: host.database.pay_sheet_column_configs.items[i].id,
                        cindex: i
                    };
                    if (host.database.pay_sheet_column_configs.items[i].id < 0){
                        item.id = 0;
                        item.name = host.database.pay_sheet_column_configs.items[i].name;
                        item.width = host.database.pay_sheet_column_configs.items[i].width;
                        item.code = host.database.pay_sheet_column_configs.items[i].code;
                        item.setting = EncodingClass.string.fromVariable(host.database.pay_sheet_column_configs.items[i].setting);
                        item.pay_sheetid = host.pay_sheetid;
                        item.type = "system";
                    }
                    listUpdateIndex.push(item);
                }
            }
            FormClass.api_call({
                url: "pay_sheet_change_index_column_config.php",
                params: [
                    {name: "listUpdateIndex", value: EncodingClass.string.fromVariable(listUpdateIndex)},
                    {name: "pay_sheetid", value: host.pay_sheetid}
                ],
                func: function(success, message){
                    if (success){
                        if (message.substr(0,2) == "ok"){
                            var st = EncodingClass.string.toVariable(message.substr(2));
                            contentModule.makeDatabaseContent(host, st);
                            host.database.pay_sheet_column_configs.items.forEach(function(item){
                                if (item.setting){
                                    item.setting = EncodingClass.string.toVariable(item.setting);
                                }
                            });
                        }
                        else {
                            ModalElement.alert({message: message});
                        }
                    }
                    else {
                        ModalElement.alert({message: message});
                    }
                }
            });
        };
        var deleteRow = function(id){
            return new Promise(function(rs, rj){
                var listSetting = EncodingClass.string.duplicate(host.database.pay_sheet_column_configs.items);
                var k = host.database.pay_sheet_column_configs.getIndex(id);
                listSetting.splice(k, 1);
                for (var i = 0; i < listSetting.length; i++){
                    if (listSetting[i].setting && (listSetting[i].setting.data == "formula")){
                        if (listSetting[i].setting.formula == "") listSetting[i].setting.formula = "0";
                        listSetting[i].setting.formula = contentModule.convertPaysheetFormula(listSetting[i].setting.formula);
                        listSetting[i].setting.formula = MathClass.Expression.parse(listSetting[i].setting.formula);
                        if (!listSetting[i].setting.formula){
                            ModalElement.alert({message: LanguageModule.text("war_txt_formula_is_invalid")});
                            return;
                        }
                    }
                }
                var variablesSystemList = contentModule.getPaySheetVariableSystem();
                var res = contentModule.getCalOrderList(listSetting, variablesSystemList);
                if (!res.status){
                    ModalElement.alert({message: LanguageModule.text("war_failed_used_column")});
                    return;
                }
                ModalElement.show_loading();
                FormClass.api_call({
                    url: "pay_sheet_delete_column_configs.php",
                    params: [
                        {name: "id", value: id}
                    ],
                    func: function(success, message){
                        ModalElement.close(-1);
                        if (success){
                            if (message.substr(0, 2) == "ok"){
                                var index = host.database.pay_sheet_column_configs.getIndex(id);
                                host.database.pay_sheet_column_configs.items.splice(index, 1);
                                rs();
                            }
                            else {
                                ModalElement.alert({message: message});
                            }
                        }
                        else {
                            ModalElement.alert({message: message});
                        }
                    }
                });
            });
        };
        var deleteRowConfirm = function(id){
            return new Promise(function(rs, rj){
                ModalElement.question({
                    title: LanguageModule.text("war_title_delete_pay_sheet_colum_config"),
                    message: LanguageModule.text2("war_txt_detele", [""]),
                    onclick: function(sel){
                        if (sel == 0){
                            deleteRow(id).then(function(value){
                                rs(value);
                            });
                        }
                    }
                });
            });
        };
        var saveRow = function(data){
            return new Promise(function(rs, rj){
                data.pay_sheetid = host.pay_sheetid;
                var listSetting = EncodingClass.string.duplicate(host.database.pay_sheet_column_configs.items);
                var data1 = EncodingClass.string.duplicate(data);
                data1.setting = EncodingClass.string.toVariable(data1.setting);
                var listUpdate = [];
                if (data.id == 0){
                    listSetting.push(data1);
                }
                else {
                    var index = host.database.pay_sheet_column_configs.getIndex(data.id);
                    listSetting[index] = data1;
                    var old_code = host.database.pay_sheet_column_configs.items[index].code.toLowerCase();
                    var new_code = data1.code;
                    if (old_code != new_code){
                        var change, s2;
                        for (var i = 0; i < listSetting.length; i++){
                            change = false;
                            if (listSetting[i].setting){
                                if (listSetting[i].setting.data == "formula"){
                                    s2 = listSetting[i].setting.formula.replace(/[A-Za-z_0-9]+/g, function(all){
                                        if (all.toLowerCase() === old_code) {
                                            change = true;
                                            return new_code;
                                        }
                                        return all;
                                    });
                                    listSetting[i].setting.formula = s2;
                                }
                                else if (listSetting[i].setting.data == "function"){
                                    for (var j = 0; j < listSetting[i].setting.function.args.length; j++){
                                        if (listSetting[i].setting.function.args[j].type == "code_of_column" && listSetting[i].setting.function.args[j].value.toLowerCase() === old_code){
                                            change = true;
                                            listSetting[i].setting.function.args[j].value = new_code;
                                        }
                                    }
                                }
                            }
                            if (change) listUpdate.push(EncodingClass.string.duplicate(listSetting[i]));
                        }
                    }
                }
                console.log(listSetting, listUpdate);
                for (var i = 0; i < listSetting.length; i++){
                    if (listSetting[i].setting && (listSetting[i].setting.data == "formula")){
                        if (listSetting[i].setting.formula == "") listSetting[i].setting.formula = "0";
                        listSetting[i].setting.formula = contentModule.convertPaysheetFormula(listSetting[i].setting.formula);
                        listSetting[i].setting.formula = MathClass.Expression.parse(listSetting[i].setting.formula);
                        if (!listSetting[i].setting.formula){
                            ModalElement.alert({message: LanguageModule.text("war_txt_formula_is_invalid")});
                            return;
                        }
                    }
                }
                var variablesSystemList = contentModule.getPaySheetVariableSystem();
                var res = contentModule.getCalOrderList(listSetting, variablesSystemList);
                if (!res.status){
                    if (res.content.type == "variable_not_found" || res.content.type == "code_of_column_not_found"){
                        var ex = false;
                        if (data.id > 0){
                            var index = host.database.pay_sheet_column_configs.getIndex(data.id);
                            if (host.database.pay_sheet_column_configs.items[index].code.toLowerCase() == res.content.value.toLowerCase()) ex = true;
                        }
                        if (ex){
                            ModalElement.alert({message: LanguageModule.text("war_txt_code_is_used")});
                        }
                        else {
                            ModalElement.alert({message: LanguageModule.text2("war_txt_variable_is_null", [res.content.value])});
                        }
                    }
                    else {
                        ModalElement.alert({message: LanguageModule.text("war_txt_formula_loop")});
                    }
                    return;
                }
                if (data.id == 0) data.cindex = host.database.pay_sheet_column_configs.items.length;
                ModalElement.show_loading();
                FormClass.api_call({
                    url: "pay_sheet_save_column_configs.php",
                    params: [
                        {name: "data", value: EncodingClass.string.fromVariable(data)},
                        {name: "listUpdate", value: EncodingClass.string.fromVariable(listUpdate)}
                    ],
                    func: function(success, message){
                        ModalElement.close(-1);
                        if (success){
                            if (message.substr(0, 2) == "ok"){
                                var st = EncodingClass.string.toVariable(message.substr(2));
                                if (st.data.setting) st.data.setting = EncodingClass.string.toVariable(st.data.setting);
                                if (data.id == 0){
                                    host.database.pay_sheet_column_configs.items.push(st.data);
                                }
                                else {
                                    var index = host.database.pay_sheet_column_configs.getIndex(data.id);
                                    host.database.pay_sheet_column_configs.items[index] = st.data;
                                }
                                for (var i = 0; i < listUpdate.length; i++){
                                    var index = host.database.pay_sheet_column_configs.getIndex(listUpdate[i].id);
                                    st.listUpdate[i].setting = EncodingClass.string.toVariable(st.listUpdate[i].setting);
                                    host.database.pay_sheet_column_configs.items[index] = st.listUpdate[i];
                                }
                                ModalElement.close();
                                redrawFunc();
                            }
                            else {
                                ModalElement.alert({message: message});
                            }
                        }
                        else {
                            ModalElement.alert({message: message});
                        }
                    }
                });
            });
        };
        var addRow = function(id){
            return new Promise(function(rs, rj){
                var content;
                if (id != 0){
                    var index = host.database.pay_sheet_column_configs.getIndex(id);
                    content = host.database.pay_sheet_column_configs.items[index];
                }
                var name_user_input = theme.input({
                    style: {
                        minWidth: "400px",
                        width: "100%"
                    },
                    value: (id != 0)? content.name : ""
                });
                var code_input = theme.input({
                    style: {
                        minWidth: "400px",
                        width: "100%"
                    },
                    value: (id != 0)? content.code : ""
                });
                if (id != 0 && content.type == "system") code_input.disabled = true;
                var data_select = absol.buildDom({
                    tag: "selectmenu",
                    style: {
                        display: "block",
                        width: "100%"
                    },
                    props: {
                        items: [
                            {value: 0, text: LanguageModule.text("txt_select_value")},
                            {value: "direct_input", text: LanguageModule.text("txt_direct_input")},
                            {value: "formula", text: LanguageModule.text("txt_use_formula")},
                            {value: "function", text: LanguageModule.text("txt_use_function")},
                            {value: "policy", text: "Lấy từ chính sách"},
                            {value: "pay_percentage", text: LanguageModule.text("txt_pay_percentage")},
                            // {value: "employee_profile", text: LanguageModule.text("txt_employee_profile")}
                        ]
                    },
                    on: {
                        change: function(){
                            switch (this.value) {
                                case 0:
                                case "direct_input":
                                    var listElt = absol.$$('.paysheet-setting-formula', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-function', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-policy', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-pay-percentage', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-employee-profile', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    break;
                                case "formula":
                                    var listElt = absol.$$('.paysheet-setting-formula', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "";
                                    });
                                    listElt = absol.$$('.paysheet-setting-function', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-policy', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-pay-percentage', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-employee-profile', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    break;
                                case "function":
                                    var listElt = absol.$$('.paysheet-setting-formula', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-function', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "";
                                    });
                                    listElt = absol.$$('.paysheet-setting-policy', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-pay-percentage', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-employee-profile', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    break;
                                case "policy":
                                    var listElt = absol.$$('.paysheet-setting-formula', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-function', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-policy', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "";
                                    });
                                    listElt = absol.$$('.paysheet-setting-pay-percentage', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-employee-profile', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    break;
                                case "pay_percentage":
                                    var listElt = absol.$$('.paysheet-setting-formula', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-function', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-policy', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-pay-percentage', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "";
                                    });
                                    listElt = absol.$$('.paysheet-setting-employee-profile', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    break;
                                case "employee_profile":
                                    var listElt = absol.$$('.paysheet-setting-formula', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-function', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-policy', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-pay-percentage', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "none";
                                    });
                                    listElt = absol.$$('.paysheet-setting-employee-profile', bodycontent);
                                    listElt.forEach(function(elt){
                                        elt.style.display = "";
                                    });
                                    break;
                                default:

                            }
                        }
                    }
                });
                var formula_input = DOMElement.textarea({
                    attrs: {
                        className: "cardSimpleTextarea",
                        style: {
                            minWidth: "400px",
                            width: "100%",
                            height: "100px"
                        }
                    }
                });
                var function_select = absol.buildDom({
                    tag: "selecttreeleafmenu",
                    style: {
                        display: "block",
                        width: "100%"
                    },
                    style: {
                        display: "block",
                        width: "100%"
                    },
                    props: {
                        enableSearch: true,
                        items: host.functionItems
                    },
                    on: {
                        change: function(){
                            DOMElement.removeAllChildren(function_params_ctn);
                            if (this.value == 0) return;
                            hr.sclang.getNodeInfoById(this.value).then(function(result){
                                if (!result) return;
                                if (!result.params) return;
                                var data = [];
                                var inputidBoxes = {};
                                for (var i = 0; i < result.params.length; i++){
                                    inputidBoxes[i] = {
                                        0: absol.buildDom({
                                            tag: "selectmenu",
                                            props: {
                                                items: host.functionArgsItems
                                            },
                                            on: {
                                                change: function(i){
                                                    return function(){
                                                        inputidBoxes[i][1].value = "";
                                                        if (this.value == "employee_code"){
                                                            inputidBoxes[i][1].disabled = true;
                                                        }
                                                        else {
                                                            inputidBoxes[i][1].disabled = false;
                                                        }
                                                        if (this.value == "number") inputidBoxes[i][1].type = "number";
                                                        else {
                                                            inputidBoxes[i][1].type = "";
                                                        }
                                                    }
                                                }(i)
                                            }
                                        }),
                                        1: theme.input({
                                            style: {
                                                minWidth: "200px",
                                                width: "100%"
                                            }
                                        })
                                    };
                                    if ((id != 0) && content.setting && content.setting.data == "function" && content.setting.function.functionid == function_select.value){
                                        if (content.setting.function.args[i].type == "number"){
                                            inputidBoxes[i][1].type = "number";
                                        }
                                        else if (content.setting.function.args[i].type == "employee_code"){
                                            inputidBoxes[i][1].disabled = true;
                                        }
                                        inputidBoxes[i][0].value = content.setting.function.args[i].type;
                                        inputidBoxes[i][1].value = content.setting.function.args[i].value;
                                    }
                                    if (i > 0) data.push([{attrs: {className: "paysheet-setting-function", style: {height: "var(--control-verticle-distance-2)"}}}]);
                                    data.push(
                                        [
                                            {attrs: {className: "paysheet-setting-function"}, text: result.params[i].name},
                                            {attrs: {className: "paysheet-setting-function", style: {width: "var(--control-horizontal-distance-2)"}}},
                                            {
                                                attrs: {className: "paysheet-setting-function"},
                                                children: inputidBoxes[i][0]
                                            },
                                            {attrs: {className: "paysheet-setting-function", style: {width: "var(--control-horizontal-distance-2)"}}},
                                            {
                                                attrs: {className: "paysheet-setting-function"},
                                                children: inputidBoxes[i][1]
                                            }
                                        ]
                                    )
                                }
                                function_params_ctn.appendChild(DOMElement.table({
                                    data: data
                                }));
                                function_params_ctn.getValue = function(){
                                    var args = [], type, value;
                                    for (var i = 0; i < result.params.length; i++){
                                        type = inputidBoxes[i][0].value;
                                        value = inputidBoxes[i][1].value;
                                        if (type == "number"){
                                            if (value == "") value = "0";
                                            value = parseFloat(value);
                                        }
                                        args.push({
                                            type: type,
                                            value: value
                                        });
                                    }
                                    return args;
                                };
                            });
                        }
                    }
                });
                var policy_select = absol.buildDom({
                    tag: "selecttreemenu",
                    style: {
                        display: "block",
                        width: "100%"
                    },
                    props: {
                        items: host.policyHasListItems,
                        enableSearch: true
                    }
                });
                var pay_percentage_select = absol.buildDom({
                    tag: "selectmenu",
                    style: {
                        display: "block",
                        width: "100%"
                    },
                    props: {
                        items: host.payPercentageListItems,
                        enableSearch: true
                    }
                });
                var employee_profile_select = absol.buildDom({
                    tag: "selectmenu",
                    style: {
                        display: "block",
                        width: "100%"
                    },
                    props: {
                        items: host.employeeProfileListItems,
                        enableSearch: true
                    }
                });
                if (id != 0){
                    if (content.setting && content.setting.data){
                        data_select.value = content.setting.data;
                        if (content.setting.data == "formula") formula_input.value = content.setting.formula;
                        if (content.setting.data == "function") function_select.value = content.setting.function.functionid;
                        if (content.setting.data == "policy") policy_select.value = content.setting.policy;
                        if (content.setting.data == "pay_percentage") pay_percentage_select.value = content.setting.pay_percentage;
                        if (content.setting.data == "employee_profile") employee_profile_select.value = content.setting.employee_profile;
                    }
                }
                var function_params_ctn = DOMElement.div({});
                var dataView = [
                    [{attrs: {style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {text: LanguageModule.text("txt_column_name")},
                        {attrs: {style: {width: "var(--control-horizontal-distance-2)"}}},
                        name_user_input
                    ],
                    [{attrs: {style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {text: LanguageModule.text("txt_code")},
                        {attrs: {style: {width: "var(--control-horizontal-distance-2)"}}},
                        code_input
                    ]
                ];
                dataView.push(
                    [{attrs: {style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {text: LanguageModule.text("txt_data")},
                        {attrs: {style: {width: "var(--control-horizontal-distance-2)"}}},
                        data_select
                    ],
                    [{attrs: {className: "paysheet-setting-formula", style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {attrs: {className: "paysheet-setting-formula"}, text: LanguageModule.text("txt_formula")},
                        {attrs: {className: "paysheet-setting-formula", style: {width: "var(--control-horizontal-distance-2)"}}},
                        {
                            attrs: {className: "paysheet-setting-formula"},
                            children: [formula_input]
                        }
                    ],
                    [{attrs: {className: "paysheet-setting-function", style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {attrs: {className: "paysheet-setting-function"}, text: "Hàm"},
                        {attrs: {className: "paysheet-setting-function", style: {width: "var(--control-horizontal-distance-2)"}}},
                        {
                            attrs: {className: "paysheet-setting-function"},
                            children: [function_select]
                        }
                    ],
                    [{attrs: {className: "paysheet-setting-function", style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {attrs: {className: "paysheet-setting-function"}, text: LanguageModule.text("txt_params")},
                        {attrs: {className: "paysheet-setting-function", style: {width: "var(--control-horizontal-distance-2)"}}},
                        {
                            attrs: {className: "paysheet-setting-function"},
                            children: [function_params_ctn]
                        }
                    ],
                    [{attrs: {className: "paysheet-setting-policy", style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {attrs: {className: "paysheet-setting-policy"}, text: LanguageModule.text("txt_policy")},
                        {attrs: {className: "paysheet-setting-policy", style: {width: "var(--control-horizontal-distance-2)"}}},
                        {
                            attrs: {className: "paysheet-setting-policy"},
                            children: [policy_select]
                        }
                    ],
                    [{attrs: {className: "paysheet-setting-pay-percentage", style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {attrs: {className: "paysheet-setting-pay-percentage"}, text: LanguageModule.text("txt_pay_percentage")},
                        {attrs: {className: "paysheet-setting-pay-percentage", style: {width: "var(--control-horizontal-distance-2)"}}},
                        {
                            attrs: {className: "paysheet-setting-pay-percentage"},
                            children: [pay_percentage_select]
                        }
                    ],
                    [{attrs: {className: "paysheet-setting-employee-profile", style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {attrs: {className: "paysheet-setting-employee-profile"}, text: LanguageModule.text("txt_field")},
                        {attrs: {className: "paysheet-setting-employee-profile", style: {width: "var(--control-horizontal-distance-2)"}}},
                        {
                            attrs: {className: "paysheet-setting-employee-profile"},
                            children: [employee_profile_select]
                        }
                    ]
                );
                var description_input = theme.input({
                    style: {
                        minWidth: "400px",
                        width: "100%"
                    }
                });
                var format_select = absol.buildDom({
                    tag: "selectmenu",
                    style: {
                        display: "block",
                        width: "100%"
                    },
                    props: {
                        items: hr.pay_sheet.getFormatItems()
                    }
                });
                var display_checkbox = absol.buildDom({
                    tag: "switch",
                    style: {
                        font: "var(--switch-fontsize)"
                    }
                });
                if (id != 0){
                    description_input.value = content.description;
                    format_select.value = (content.format != "")? content.format : "1,234.1";
                    display_checkbox.checked = !content.hidden;
                }
                else {
                    format_select.value = "1,234.1";
                    display_checkbox.checked = true;
                }
                dataView.push(
                    [{attrs: {style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {text: LanguageModule.text("txt_description")},
                        {attrs: {style: {width: "var(--control-horizontal-distance-2)"}}},
                        description_input
                    ],
                    [{attrs: {style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {text: LanguageModule.text("txt_format")},
                        {attrs: {style: {width: "var(--control-horizontal-distance-2)"}}},
                        format_select
                    ],
                    [{attrs: {style: {height: "var(--control-verticle-distance-2)"}}}],
                    [
                        {text: LanguageModule.text("txt_display")},
                        {attrs: {style: {width: "var(--control-horizontal-distance-2)"}}},
                        display_checkbox
                    ]
                );
                var column_width_input = theme.input({
                    style: {
                        minWidth: "400px",
                        width: "100%"
                    },
                    type: "number",
                    value: (id != 0)? content.width : 100
                });
                var drawColumnCode = function(){
                    DOMElement.removeAllChildren(column_code_ctn);
                    var data = [];
                    host.database.pay_sheet_column_configs.items.forEach(function(item){
                        if (item.id == id) return;
                        data.push([
                            {text: item.name},
                            {
                                attrs: {
                                    className: "hr-table-cell-link",
                                    onclick: function(){
                                        contentModule.copyToClipboard(item.code);
                                        absol.require('snackbar').show("Copied: " + item.code);
                                    }
                                },
                                text: item.code
                            }
                        ]);
                    });
                    var variables = contentModule.getPaySheetVariableSystem();
                    variables.forEach(function(item){
                        data.push([
                            {text: item.text},
                            {
                                attrs: {
                                    className: "hr-table-cell-link",
                                    onclick: function(){
                                        contentModule.copyToClipboard(item.name);
                                        absol.require('snackbar').show("Copied: " + item.name);
                                    }
                                },
                                text: item.name
                            }
                        ]);
                    });
                    var table = DOMElement.table({
                        // header: [
                        //     {text: LanguageModule.text("txt_column_name")},
                        //     {text: LanguageModule.text("txt_code")}
                        // ],
                        data: data
                    });
                    table.addSearchBox(inputsearchbox1);
                    column_code_ctn.appendChild(table);
                    table.style.width = table.getBoundingClientRect().width + "px";
                    column_code_ctn.style.width = table.getBoundingClientRect().width + 17 + "px";
                };
                var inputsearchbox1 = absol.buildDom({
                    tag:'searchcrosstextinput',
                    style: {
                        width: "100%"
                    },
                    props:{
                        placeholder: LanguageModule.text("txt_search")
                    }
                });
                var column_code_ctn = DOMElement.div({
                    attrs: {
                        className: "cardsimpletableclass",
                        style: {
                            maxHeight: "calc(90vh - 260px)",
                            overflowY: "auto"
                        }
                    }
                });
                var bodycontent = DOMElement.div({
                    attrs: {style: {whiteSpace: "nowrap"}},
                    children: [
                        DOMElement.div({
                            attrs: {style: {display: "inline-block", paddingRight: "var(--control-horizontal-distance-2)", verticalAlign: "top"}},
                            children: [DOMElement.table({
                                data: dataView
                            })]
                        }),
                        DOMElement.div({
                            attrs: {style: {display: "inline-block", verticalAlign: "top"}},
                            children: [
                                inputsearchbox1,
                                DOMElement.div({attrs: {style: {height: "var(--control-verticle-distance-2)"}}}),
                                column_code_ctn
                            ]
                        })
                    ]
                });
                ModalElement.showWindow({
                    title: "Thiết lập cột",
                    bodycontent: bodycontent,
                    buttonlist: [
                        {
                            text: LanguageModule.text("txt_save"),
                            onclick: function(){
                                if (id != 0){
                                    var cIndex = host.database.pay_sheet_column_configs.getIndex(id);
                                }
                                var code = code_input.value;
                                var name = name_user_input.value.trim();
                                if (name == ""){
                                    ModalElement.alert({
                                        message: LanguageModule.text("war_txt_no_name"),
                                        func: function(){
                                            name_user_input.focus();
                                        }
                                    });
                                    return;
                                }
                                for (var i = 0; i < host.database.pay_sheet_column_configs.items.length; i++){
                                    if (host.database.pay_sheet_column_configs.items[i].id == id) continue;
                                    if (host.database.pay_sheet_column_configs.items[i].name.toLowerCase() == name.toLowerCase()){
                                        ModalElement.alert({
                                            message: LanguageModule.text("war_txt_name_was_used"),
                                            func: function(){
                                                name_user_input.focus();
                                            }
                                        });
                                        return;
                                    }
                                }
                                if (code == ""){
                                    ModalElement.alert({
                                        message: LanguageModule.text("war_txt_no_code"),
                                        func: function(){
                                            code_input.focus();
                                        }
                                    });
                                    return;
                                }
                                var regexText = /^[0-9A-Za-z_]*$/;
                                if (!regexText.test(code)){
                                    ModalElement.alert({
                                        message: LanguageModule.text("war_txt_column_code_invalid"),
                                        func: function(){
                                            code_input.focus();
                                        }
                                    });
                                    return;
                                }
                                var variablesSystemList = contentModule.getPaySheetVariableSystem();
                                for (var i = 0; i < variablesSystemList.length; i++){
                                    if (variablesSystemList[i].name.toLowerCase() == code.toLowerCase()){
                                        ModalElement.alert({
                                            message: LanguageModule.text("war_txt_duplicated_column_code_and_var"),
                                            func: function(){
                                                code_input.focus();
                                            }
                                        });
                                        return;
                                    }
                                }
                                for (var i = 0; i < host.database.pay_sheet_column_configs.items.length; i++){
                                    if (host.database.pay_sheet_column_configs.items[i].id == id) continue;
                                    if (host.database.pay_sheet_column_configs.items[i].code.toLowerCase() == code.toLowerCase()){
                                        ModalElement.alert({
                                            message: LanguageModule.text("war_txt_code_was_used"),
                                            func: function(){
                                                code_input.focus();
                                            }
                                        });
                                        return;
                                    }
                                }
                                var setting_data = data_select.value;
                                if (setting_data == 0){
                                    ModalElement.alert({message: "Chưa chọn dữ liệu"});
                                    return;
                                }
                                var setting = {
                                    data: setting_data
                                };
                                switch (setting_data) {
                                    case "policy":
                                        var policy = policy_select.value;
                                        if (policy == 0){
                                            ModalElement.alert({message: LanguageModule.text("war_txt_no_policy")});
                                            return;
                                        }
                                        setting.policy = policy;
                                        break;
                                    case "pay_percentage":
                                        var pay_percentage = pay_percentage_select.value;
                                        if (pay_percentage == 0){
                                            ModalElement.alert({message: LanguageModule.text("war_txt_no_pay_percentage")});
                                            return;
                                        }
                                        setting.pay_percentage = pay_percentage;
                                        break;
                                    case "employee_profile":
                                        var employee_profile = employee_profile_select.value;
                                        if (employee_profile == 0){
                                            ModalElement.alert({message: LanguageModule.text("war_txt_no_employee_profile_field")});
                                            return;
                                        }
                                        setting.employee_profile = employee_profile;
                                        break;
                                    case "formula":
                                        var formula = formula_input.value;
                                        setting.formula = formula;
                                        break;
                                    case "function":
                                        var functionid = function_select.value;
                                        if (functionid == 0){
                                            ModalElement.alert({message: LanguageModule.text("war_txt_no_function")});
                                            return;
                                        }
                                        setting.function = {
                                            functionid: functionid,
                                            args: function_params_ctn.getValue()
                                        };
                                        break;
                                    default:

                                }
                                var data = {
                                    id: id,
                                    code: code,
                                    name: name,
                                    setting: EncodingClass.string.fromVariable(setting),
                                    format: format_select.value,
                                    hidden: display_checkbox.checked? 0 : 1
                                };
                                if (id == 0) data.type == "user";
                                else {
                                    data.type = host.database.pay_sheet_column_configs.items[cIndex].type;
                                }
                                if (id != 0) data.cindex = host.database.pay_sheet_column_configs.items[cIndex].cindex;
                                data.description = description_input.value;
                                saveRow(data);
                            }
                        },
                        {
                            text: LanguageModule.text("txt_cancel"),
                            onclick: function(){
                                ModalElement.close();
                            }
                        }
                    ]
                });
                name_user_input.focus();
                function_select.emit("change");
                data_select.emit("change");
                drawColumnCode();
            });
        };
        var getRow = function(content){
            function applyParam(elt){
                elt.classList.add("hr-table-cell-link");
                elt.onclick = function(){
                    addRow(content.id);
                };
                return elt;
            };
            var cells = [];
            if (status == 0 || status == 2) cells.push({
                style: {
                    width: '30px',
                    textAlign: 'center',
                    fontSize: '25px'
                },
                class: 'as-drag-zone',
                child: 'span.mdi.mdi-drag'
            });
            cells.push({
                innerText: content.name,
                child: applyParam(DOMElement.span({text: content.name}))
            });
            cells.push({
                innerText: content.code,
                child: applyParam(DOMElement.span({text: content.code}))
            });
            var settingName = "";
            if (content.setting){
                switch (content.setting.data) {
                    case "direct_input":
                        settingName = LanguageModule.text("txt_direct_input");
                        break;
                    case "formula":
                        settingName = LanguageModule.text("txt_use_formula") + ": " + content.setting.formula;
                        break;
                    case "policy":
                        var policyName = "";
                        var item = host.policyHasListItemsDic.getItemByValue(content.setting.policy);
                        if (item){
                            policyName = item.text;
                        }
                        settingName = "Lấy từ chính sách " + policyName;
                        break;
                    case "pay_percentage":
                        var pay_percentageName = "";
                        var item = host.payPercentageListItemsDic.getItemByValue(content.setting.pay_percentage);
                        if (item){
                            pay_percentageName = item.text;
                        }
                        settingName = LanguageModule.text("txt_pay_percentage") + ": " + pay_percentageName;
                        break;
                    case "function":
                        var functionName;
                        var item = host.functionItemsDic.getItemByValue(content.setting.function.functionid);
                        if (item){
                            functionName = item.text + " (";
                            for (var i = 0; i < content.setting.function.args.length; i++){
                                if (i > 0) functionName += "; ";
                                var item2 = host.functionArgsItemsDic.getItemByValue(content.setting.function.args[i].type);
                                if (item2){
                                    functionName += item2.text;
                                    if (content.setting.function.args[i].type != "employee_code"){
                                        functionName += ": " + content.setting.function.args[i].value;
                                    }
                                }
                            }
                            functionName += ")";
                        }
                        settingName = LanguageModule.text("txt_use_function") + ": " + functionName
                        break;
                    default:

                }
            }
            cells.push({
                innerText: settingName,
                child: applyParam(DOMElement.span({text: settingName}))
            });
            cells.push({
                innerText: content.description,
                child: applyParam(DOMElement.span({text: content.description}))
            });
            cells.push({
                innerText: content.format,
                child: applyParam(DOMElement.span({text: content.format}))
            });
            cells.push({
                child: applyParam(absol.buildDom({
                    tag: "switch",
                    style: {
                        font: "var(--switch-fontsize)"
                    },
                    props: {
                        checked: !content.hidden,
                        disabled: true
                    }
                }))
            });
            if (content.type == "system"){
                cells.push({
                    style: {whiteSpace: "nowrap"},
                    innerText: LanguageModule.text("txt_system"),
                    child: applyParam(DOMElement.span({text: LanguageModule.text("txt_system")}))
                });
            }
            else {
                cells.push({
                    style: {whiteSpace: "nowrap"},
                    innerText: LanguageModule.text("txt_user"),
                    child: applyParam(DOMElement.span({text: LanguageModule.text("txt_user")}))
                });
            }
            if (status == 0 || status == 2){
                var qmenuButton = DOMElement.div({
                    attrs: {
                        className: "card-icon-cover"
                    },
                    children: [DOMElement.i({
                        attrs: {
                            className: "material-icons bsc-icon-hover-black"
                        },
                        text: "more_vert"
                    })]
                });
                absol.QuickMenu.toggleWhenClick(qmenuButton, {
                    getMenuProps: function(){
                        var quickMenuItems = [];
                        quickMenuItems.push({
                            text: LanguageModule.text("txt_edit"),
                            extendClasses: "bsc-quickmenu",
                            icon: DOMElement.i({
                                attrs: {
                                    className: "material-icons"
                                },
                                text: "create"
                            }),
                            cmd: function(){
                                addRow(content.id);
                            }
                        });
                        if (content.type != "system"){
                            quickMenuItems.push({
                                text: LanguageModule.text("txt_delete"),
                                extendClasses: ["bsc-quickmenu", "red"],
                                icon: DOMElement.i({
                                    attrs: {
                                        className: "material-icons"
                                    },
                                    text: "delete"
                                }),
                                cmd: function(){
                                    deleteRowConfirm(content.id).then(function(value){
                                        var x = tableView.rowOf(row)
                                        x.remove();
                                    });
                                }
                            });
                        }
                        return {items: quickMenuItems};
                    },
                    onSelect: function (item){
                        item.cmd();
                    },
                    anchor: [3, 4]
                });
                cells.push({
                    style: {width: "40px"},
                    child: qmenuButton
                });
            }
            var row = {
                cells: cells
            };
            return row;
        };
        var tableView;
        var redrawFunc = function(){
            var data = [];
            for (var i = 0; i < host.database.pay_sheet_column_configs.items.length; i++){
                data.push(getRow(host.database.pay_sheet_column_configs.items[i]));
            }
            var header = [
                {
                    id: "column_name",
                    child:  absol.buildDom({text: LanguageModule.text("txt_column_name")})
                },
                {
                    id: "code",
                    child:  absol.buildDom({text: LanguageModule.text("txt_code")})
                },
                {
                    id: "settings",
                    child:  absol.buildDom({text: LanguageModule.text("txt_settings")})
                },
                {
                    id: "description",
                    style: {
                        width: "30%"
                    },
                    child:  absol.buildDom({text: LanguageModule.text("txt_description")})
                },
                {
                    id: "format",
                    child:  absol.buildDom({text: LanguageModule.text("txt_format")})
                },
                {
                    id: "display",
                    child:  absol.buildDom({text: LanguageModule.text("txt_display")})
                },
                {
                    id: "type",
                    child:  absol.buildDom({text: LanguageModule.text("txt_type")})
                }
            ];
            if (status == 0 || status == 2){
                header.unshift({});
                header.push({});
            }
            tableView = absol.buildDom({
                tag: "dynamictable",
                props: {
                    id: "pay_sheet_column_configs",
                    adapter: {
                       data: {
                           head: {
                               rows: [
                                   {
                                       cells: header
                                   }
                               ]
                           },
                           body: {
                               rows: data
                           }
                       }
                   }
               },
               on: {
                   orderchange: function(event){
                       changeIndexFunc(event.from, event.to);
                   }
               }
            });
            tableView.attachSearchInput(inputsearchboxSetting);
            DOMElement.removeAllChildren(data_ctn);
            data_ctn.appendChild(tableView);
        };
        var data_ctn = DOMElement.div({});
        var inputsearchboxSetting = absol.buildDom({
            tag:'searchcrosstextinput',
            style: {
                width: "var(--searchbox-width)"
            },
            props:{
                placeholder: LanguageModule.text("txt_search")
            }
        });
        redrawFunc();
        var buttonlist = [
            DOMElement.div({
                attrs: {className: "single-button-header"},
                children: [theme.backButton({
                    onclick: function(){
                        host.frameList.removeLast();
                    }
                })]
            })
        ];
        if (status == 0 || status == 2) buttonlist.push(DOMElement.div({
            attrs: {className: "single-button-header"},
            children: [theme.addButton({
                onclick: function(){
                    addRow(0);
                }
            })]
        }));
        buttonlist.push(DOMElement.div({
            attrs: {className: "single-button-header"},
            children: [inputsearchboxSetting]
        }));
        var singlePage = absol.buildDom({
            tag: "singlepage",
            child: [
                DOMElement.div({
                    attrs: {className: 'button-panel-header absol-single-page-header'},
                    children: buttonlist
                }),
                data_ctn
            ]
        });
        host.frameList.addChild(singlePage);
        singlePage.requestActive();
    });
};

hr.pay_sheet.getCellPay_sheet = function(host, id){
    var index = host.database.pay_sheet.getIndex(id);
    var func = {
        view: function(){
            hr.pay_sheet.showPay_sheet(host, id);
        }
    };
    var res = host.database.pay_sheet.items[index];
    switch (res.status) {
        case 0:
            res.statusType = "new";
            break;
        case -1:
            var request_time;
            host.database.pay_sheet_approvers.items.forEach(function(item){
                if (item.paysheetid != id) return;
                if (item.old) return;
                if (item.status == -1){
                    request_time = item.time;
                    return;
                }
                dic[item.employee_peopleid] = item;
            });
            var cIndex = host.database.payroll_cycle.getIndex(res.cycleid);
            var over_due = false;
            if (request_time){
                var remain_time = (new Date()).getTime() - (request_time.getTime() + host.database.payroll_cycle.items[cIndex].time_hours_needed_for_approval*60*60*1000);
                if (remain_time > 0) over_due = true;
            }
            if (over_due) res.statusType = "over_due";
            else res.statusType = "waiting_approval";
            break;
        case 1:
            res.statusType = "approved";
            break;
        case 2:
            res.statusType = "deny";
            break;
        default:

    }
    if (systemconfig.privSystem >= 2 || data_module.admin_rights_of_me.pay_sheet){
        func.setting = function(){
            hr.pay_sheet.columnConfigs(host, id);
        };
        if (res.status == 0 || res.status == 2){
            func.edit = function(){
                hr.pay_sheet.addPay_sheet(host, id);
            };
            func.delete = function(){
                return new Promise(function(resolve,reject){
                    hr.pay_sheet.deletePay_sheetConfirm(host, id).then(function(value){
                        resolve(value);
                    });
                });
            };
        }
    }
    res.cycle_name = contentModule.getPayRollCycleView(host, res.cycleid);
    res.func = func;
    return res;
};

hr.pay_sheet.redraw = function(host){
    var columnList = [
        {value: "name", text: LanguageModule.text("txt_name"), display: true, type: -1, main: true},
        {value: "cycle_name", text: LanguageModule.text("txt_payroll_cycle"), display: true, type: -1, main: true},
        {value: "status", text: LanguageModule.text("txt_status"), display: true, type: -1, main: true}
    ];
    var redrawTableFunc = function(){
        var data = [];
        for (var i = 0; i < host.database.pay_sheet.items.length; i++) {
            data.push(hr.pay_sheet.getCellPay_sheet(host, host.database.pay_sheet.items[i].id));
        }
        contentModule.getColumnListConfig(host, host.user_column_configsDic, columnList, "pay_sheet_list").then(function(value){
            host.configColumnPay_sheet = value;
            DOMElement.removeAllChildren(host.data_container);
            var dataView = theme.formPay_sheetContentData({
                data: data,
                inputsearchbox: host.inputsearchbox,
                configColumnPay_sheet: host.configColumnPay_sheet,
                configColumnFunc: function(){
                    contentModule.userColumnConfigForm({
                        type: "pay_sheet_list",
                        columnList: columnList
                    }).then(function(value){
                        host.user_column_configsDic["pay_sheet_list"] = value;
                        redrawTableFunc();
                    });
                }
            });
            host.data_container.appendChild(dataView);
        });
    };
    redrawTableFunc();
};

hr.pay_sheet.init = function(host){
    return new Promise(function(resolveMn, rejectMn){
        hr.menu.changeCurrentUrlTab(host, "pay_sheet");
        var loadData = function(){
            return new Promise(function(rs, rj){
                FormClass.api_call({
                    url: "database_load.php",
                    params: [
                        {name: "task", value: "pay_sheet_load_init"}
                    ],
                    func: function(success, message){
                        if (success){
                            if (message.substr(0, 2) == "ok"){
                                var content = EncodingClass.string.toVariable(message.substr(2));
                                host.employeeOfMe = content.employeeOfMe;
                                if (host.employeeOfMe.length == 0){
                                    ModalElement.alert({message: LanguageModule.text("war_txt_you_need_to_link_with_an_employee_in_organization_chart_to_use_app_functions")});
                                    return;
                                }
                                delete content.employeeOfMe;
                                rs(content);
                            }
                            else {
                                ModalElement.alert({message: message});
                            }
                        }
                        else {
                            ModalElement.alert({message: message});
                        }
                    }
                });
            });
        };
        ModalElement.show_loading();
        var loadFunctionSelection = new Promise(function(rs, rj){
            hr.sclang.loadFunctionSelection().then(function(result){
                host.functionItems = result;
                host.functionItemsDic = new absol.ListDictionary(result);
                host.functionItems.unshift({value: 0, text: LanguageModule.text("txt_select_value"), isLeaf: true});
                rs();
            });
        });
        Promise.all([loadData(), loadFunctionSelection]).then(function(values){
            ModalElement.close(-1);
            host.database = {};
            contentModule.makeDatabaseContent(host, values[0]);
            contentModule.makeTypelistsIndex(host);
            host.form_config = contentModule.configVariable(host);
            contentModule.makeOrgsIndex(host);
            contentModule.makeEmployeeAllData(host);
            contentModule.makeEmployeesIndex(host);
            contentModule.makeEmployeePositionData(host);
            host.employeeProfileListItems = [{value: 0, text: LanguageModule.text("txt_select_value")}];
            var eIndex = host.database.employees.getIndex(host.employeeOfMe[0]);
            host.peopleOfMe = host.database.employees.items[eIndex].peopleid;
            host.employee_peopleDic = {};
            host.database.employees.items.forEach(function(item){
                host.employee_peopleDic[item.peopleid] = item;
            });
            host.employeesDic = contentModule.makeDictionaryIndex(host.database.employees.items);
            host.policyHasListItems = contentModule.getAllPolicyHasListItems(host);
            host.policyHasListItemsDic = new absol.ListDictionary(host.policyHasListItems);
            host.payPercentageListItems = [{value: 0, text: LanguageModule.text("txt_select_value")}];
            host.database.pay_percentage.items.forEach(function(item){
                host.payPercentageListItems.push({value: item.id, text: item.name + " - " + item.percentage + "%"});
            });
            host.payPercentageListItemsDic = new absol.ListDictionary(host.payPercentageListItems);
            host.functionArgsItems = [
                {value: "number", text: LanguageModule.text("txt_number_2")},
                {value: "string", text: LanguageModule.text("txt_string")},
                {value: "employee_code", text: LanguageModule.text("txt_employee_code")},
                {value: "code_of_column", text: LanguageModule.text("txt_code_of_column")}
            ];
            host.functionArgsItemsDic = new absol.ListDictionary(host.functionArgsItems);
            host.user_column_configsDic = contentModule.getUser_column_configsDic(host);
            host.inputsearchbox = absol.buildDom({
                tag:'searchcrosstextinput',
                style: {
                    width: "var(--searchbox-width)"
                },
                props:{
                    placeholder: LanguageModule.text("txt_search")
                }
            });
            var cmdbutton = {
                close: function () {
                    if (hr.isMobile){
                        host.holder.selfRemove();
                        hr.menu.loadPage(1000);
                    }
                    else {
                        hr.menu.tabPanel.removeTab(host.holder.id);
                    }
                }
            };
            if (systemconfig.privSystem >= 2 || data_module.admin_rights_of_me.pay_sheet){
                cmdbutton.add = function (event, me) {
                    hr.pay_sheet.addPay_sheet(host, 0);
                };
            }
            host.data_container = DOMElement.div({attrs: {style: {paddingBottom: "var(--footer-margin)"}}});
            host.holder.addChild(host.frameList);
            var singlePage = theme.formPay_sheetInit({
                cmdbutton: cmdbutton,
                data_container: host.data_container,
                inputsearchbox: host.inputsearchbox
            });
            host.frameList.addChild(singlePage);
            singlePage.requestActive();
            hr.pay_sheet.redraw(host);
            resolveMn(host);
        });
    });
};

VaKeR 2022