diff --git a/addons_extensions/consolidated_batch_payslip/models/batch_payslip.py b/addons_extensions/consolidated_batch_payslip/models/batch_payslip.py index 762af2245..a7f7bfb63 100644 --- a/addons_extensions/consolidated_batch_payslip/models/batch_payslip.py +++ b/addons_extensions/consolidated_batch_payslip/models/batch_payslip.py @@ -1,6 +1,9 @@ from odoo import models, fields, api, _ from odoo.exceptions import UserError, ValidationError -import datetime +from collections import defaultdict +from functools import reduce + + class HrPayslipRun(models.Model): _inherit = 'hr.payslip.run' @@ -287,6 +290,8 @@ class HrPayslipRun(models.Model): class HrPayslip(models.Model): _inherit = 'hr.payslip' + + def get_payslip_lines_data(self, payslip_id): payslip = self.browse(payslip_id) return [{ @@ -296,4 +301,12 @@ class HrPayslip(models.Model): 'amount': line.amount, 'quantity': line.quantity, 'rate': line.rate - } for line in payslip.line_ids] \ No newline at end of file + } for line in payslip.line_ids] + + def action_open_payslips(self): + self.ensure_one() + action = self.env["ir.actions.actions"]._for_xml_id("hr_payroll.action_view_hr_payslip_month_form") + action['views'] = [[False, "form"]] + action['res_id'] = self.id + action['target'] = 'new' + return action diff --git a/addons_extensions/consolidated_batch_payslip/static/src/components/pqgrid_batch_payslip/pqgrid_batch_payslip.js b/addons_extensions/consolidated_batch_payslip/static/src/components/pqgrid_batch_payslip/pqgrid_batch_payslip.js index 963eb098d..a33cbb545 100644 --- a/addons_extensions/consolidated_batch_payslip/static/src/components/pqgrid_batch_payslip/pqgrid_batch_payslip.js +++ b/addons_extensions/consolidated_batch_payslip/static/src/components/pqgrid_batch_payslip/pqgrid_batch_payslip.js @@ -4,6 +4,7 @@ import { Component, onMounted, useRef, useState, onWillStart } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { useService } from "@web/core/utils/hooks"; import { loadJS, loadCSS } from "@web/core/assets"; +import { rpc } from "@web/core/network/rpc"; export class ConsolidatedPayslipGrid extends Component { static props = { @@ -15,6 +16,7 @@ export class ConsolidatedPayslipGrid extends Component { setup() { this.orm = useService("orm"); this.gridRef = useRef("gridContainer"); + this.action = useService("action"); this.state = useState({ rows: [], payslipRunId: this.props.record.resId || this.props.record.evalContext.id || false @@ -36,16 +38,15 @@ export class ConsolidatedPayslipGrid extends Component { async loadDependencies() { try { - await Promise.all([ - loadJS("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"), - loadJS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"), - loadCSS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/themes/base/jquery-ui.min.css"), - loadJS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.js"), - loadJS("https://cdnjs.cloudflare.com/ajax/libs/jszip/2.6.1/jszip.min.js"), - loadJS("https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"), - loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.css"), - loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/themes/Office/pqgrid.min.css") - ]); + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"); + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"); + await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/themes/base/jquery-ui.min.css"); + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.js"); + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jszip/2.6.1/jszip.min.js"); + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"); + await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.css"); + await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/themes/Office/pqgrid.min.css"); + // Set global jQuery references window.$ = window.jQuery = window.$ || window.jQuery; @@ -145,24 +146,18 @@ export class ConsolidatedPayslipGrid extends Component { editable: true, stripeRows:false, editModel: { saveKey: $.ui.keyCode.ENTER }, - filterModel: { - on: true, - mode: "AND", - header: true, - autoSearch: true, - type: 'local', - minLength: 1 - }, - dataModel: { - data: this.state.rows, - location: "local", - sorting: "local", - paging: "local" - }, + filterModel: {on: true, mode: "AND", header: true, autoSearch: true, type: 'local', minLength: 1}, + dataModel: {data: this.state.rows, location: "local", sorting: "local", paging: "local"}, + cellSave: function (evt, ui) { + const payload = { + id: ui.rowData.id, + field: ui.dataIndx, + value: ui.newVal + }; + updateData(payload); + }, menuIcon: true, - menuUI:{ - tabs: ['hideCols'] - }, + menuUI:{tabs: ['hideCols']}, colModel: columns, postRenderInterval: -1, toolbar: { @@ -212,6 +207,21 @@ export class ConsolidatedPayslipGrid extends Component { ] }, }; + function updateData(data){ + $.ajax({ + url: "/slip/update", + type: "POST", + contentType: "application/json", + data: JSON.stringify(data), + success: function (response) { + console.log("Update successful:", response); + }, + error: function (xhr) { + console.error("Update failed:", xhr.responseText); + } + }); + }; + // Apply CSS and initialize grid $(this.gridRef.el) @@ -428,7 +438,47 @@ export class ConsolidatedPayslipGrid extends Component { return `${state}`; } }, - ...subCols + ...subCols, + { + title: "View", + width: 120, + editable: false, + summary:false, + render: function (ui) { + return "View" + }, + postRender: function (ui) { + var grid = this, + $cell = grid.getCell(ui); + $cell.find(".row-btn-view") + .button({ icons: { primary: 'ui-icon-extlink'} }) + .on("click", async function (evt) { + const res = await odoo.__WOWL_DEBUG__.root.orm.call('hr.payslip','action_open_payslips',[ui.rowData.id]) +// res.views = [[false, "form"]], + await odoo.__WOWL_DEBUG__.root.actionService.doAction(res) + }); + } + + }, + { + title: "Edit", + width: 120, + editable: false, + render: function (ui) { + return "Edit" + }, + postRender: function (ui) { + var grid = this, + $cell = grid.getCell(ui); + $cell.find(".row-btn-edit") + .button({ icons: { primary: 'ui-icon-pencil'} }) + .on("click", async function (evt) { + const res = await odoo.__WOWL_DEBUG__.root.orm.call('hr.payslip','action_edit_payslip_lines',[ui.rowData.id]) + res.views = [[false, "form"]], + await odoo.__WOWL_DEBUG__.root.actionService.doAction(res) + }); + } + } ]; } diff --git a/addons_extensions/ftp_feed/__init__.py b/addons_extensions/ftp_feed/__init__.py new file mode 100644 index 000000000..45fab17f9 --- /dev/null +++ b/addons_extensions/ftp_feed/__init__.py @@ -0,0 +1 @@ +from . import models, controllers \ No newline at end of file diff --git a/addons_extensions/ftp_feed/__manifest__.py b/addons_extensions/ftp_feed/__manifest__.py new file mode 100644 index 000000000..f2db3ed64 --- /dev/null +++ b/addons_extensions/ftp_feed/__manifest__.py @@ -0,0 +1,19 @@ +{ + 'name': 'FTP Feed', + 'summary': 'Feed Module', + 'category': 'Reporting', + 'version': '1.0.0', + 'author': 'Pranay', + 'website': 'https://ftprotech.in', + 'license': 'LGPL-3', + 'sequence': -100, + 'depends': [ + 'base', 'web', 'hr' + ], + 'data': [ + 'security/ir.model.access.csv', + 'security/security.xml', + 'views/feed.xml', + ], + 'images': ['static/description/banner.png'], +} diff --git a/addons_extensions/ftp_feed/controllers/__init__.py b/addons_extensions/ftp_feed/controllers/__init__.py new file mode 100644 index 000000000..72f4562d7 --- /dev/null +++ b/addons_extensions/ftp_feed/controllers/__init__.py @@ -0,0 +1 @@ +from . import controller \ No newline at end of file diff --git a/addons_extensions/ftp_feed/controllers/controller.py b/addons_extensions/ftp_feed/controllers/controller.py new file mode 100644 index 000000000..1a8d6eb2f --- /dev/null +++ b/addons_extensions/ftp_feed/controllers/controller.py @@ -0,0 +1,22 @@ +from odoo import http +from odoo.http import request + + +class FeedController(http.Controller): + @http.route('/feed/attachment/', auth='user') + def get_feed_attachment(self, attachment_id, **kwargs): + attachment = request.env['ir.attachment'].sudo().search([ + ('id', '=', attachment_id), + '|', + ('res_model', '=', 'ftp.feed'), + ('res_model', '=', 'ftp.feed.comments') + ]) + + if not attachment: + return request.not_found() + + return http.send_file( + attachment._full_path(attachment.store_fname), + filename=attachment.name, + as_attachment=True + ) \ No newline at end of file diff --git a/addons_extensions/ftp_feed/models/__init__.py b/addons_extensions/ftp_feed/models/__init__.py new file mode 100644 index 000000000..25e3f9d79 --- /dev/null +++ b/addons_extensions/ftp_feed/models/__init__.py @@ -0,0 +1 @@ +from . import feed \ No newline at end of file diff --git a/addons_extensions/ftp_feed/models/feed.py b/addons_extensions/ftp_feed/models/feed.py new file mode 100644 index 000000000..7cce75402 --- /dev/null +++ b/addons_extensions/ftp_feed/models/feed.py @@ -0,0 +1,147 @@ +from odoo import fields, api, _, models +from odoo.exceptions import UserError, ValidationError +from datetime import datetime + + +class FtpFeed(models.Model): + _name = 'ftp.feed' + _description = 'Social Feed Posts' + _order = 'create_date desc' + + description = fields.Text(string='Post Content') + images = fields.Many2many('ir.attachment', string='Post Images') + user_id = fields.Many2one('res.users', default=lambda self: self.env.user, string='Author') + employee_id = fields.Many2one('hr.employee', string='Employee', compute='_compute_employee', store=True) + feed_data = fields.One2many('ftp.feed.data', 'feed_id', string='Reactions') + feed_comments = fields.One2many('ftp.feed.comments', 'feed_id', string='Comments') + like_count = fields.Integer(compute='_compute_like_count', string='Likes') + comment_count = fields.Integer(compute='_compute_comment_count', string='Comments') + post_time = fields.Char(compute='_compute_post_time', string='Posted') + + @api.depends('user_id') + def _compute_employee(self): + for record in self: + employee = self.env['hr.employee'].search([('user_id', '=', record.user_id.id)], limit=1) + record.employee_id = employee.id if employee else False + + @api.depends('feed_data.feed_type') + def _compute_like_count(self): + for record in self: + record.like_count = len(record.feed_data.filtered(lambda x: x.feed_type == 'like')) + + @api.depends('feed_comments') + def _compute_comment_count(self): + for record in self: + record.comment_count = len(record.feed_comments) + + @api.depends('create_date') + def _compute_post_time(self): + for record in self: + if record.create_date: + delta = datetime.now() - record.create_date + if delta.days > 0: + record.post_time = f"{delta.days}d ago" + elif delta.seconds > 3600: + record.post_time = f"{delta.seconds // 3600}h ago" + elif delta.seconds > 60: + record.post_time = f"{delta.seconds // 60}m ago" + else: + record.post_time = "Just now" + else: + record.post_time = "" + + @api.model + def create(self, vals): + vals['user_id'] = self.env.uid + if not vals.get('images') and not vals.get('description'): + raise ValidationError(_("Can't create an empty post")) + # Handle images to ensure they are public + if vals.get('images'): + # images is a list of commands like [(6, 0, [id1, id2])] + image_ids = [] + for command in vals['images']: + if command[0] == 6: # REPLACE command + image_ids = command[2] + elif command[0] in (4, 1): # LINK or CREATE command + image_ids.append(command[1] if command[0] == 4 else command[0]) + + # Update all attachments to be public + if image_ids: + self.env['ir.attachment'].browse(image_ids).write({'public': True}) + + return super().create(vals) + + def write(self, vals): + for record in self: + if self.env.user != record.user_id: + if 'description' in vals or 'images' in vals: + raise UserError(_("Only the author can modify post content")) + if vals.get('images'): + # Get all new image IDs being added + new_image_ids = [] + for command in vals['images']: + if command[0] == 6: # REPLACE command + new_image_ids = command[2] + elif command[0] in (4, 1): # LINK or CREATE command + new_image_ids.append(command[1] if command[0] == 4 else command[0]) + + # Update all new attachments to be public + if new_image_ids: + self.env['ir.attachment'].browse(new_image_ids).write({'public': True}) + return super().write(vals) + + def unlink(self): + for record in self: + if self.env.user != record.user_id: + raise UserError(_("Only the author can delete this post")) + return super().unlink() + + +class FtpFeedData(models.Model): + _name = 'ftp.feed.data' + _description = 'Feed Reactions' + + feed_type = fields.Selection([ + ('like', 'Like'), + ('dislike', 'Dislike') + ], default='like', required=True) + user_id = fields.Many2one('res.users', default=lambda self: self.env.user, required=True) + feed_id = fields.Many2one('ftp.feed', required=True, ondelete='cascade') + + _sql_constraints = [ + ('unique_user_feed', 'unique(user_id, feed_id)', 'You can only react once per post!'), + ] + + +class FtpFeedComments(models.Model): + _name = 'ftp.feed.comments' + _description = 'Feed Comments' + _order = 'create_date desc' + + feed_comment = fields.Text(string='Comment', required=True) + user_id = fields.Many2one('res.users', default=lambda self: self.env.user, string='Author') + employee_id = fields.Many2one('hr.employee', string='Employee', compute='_compute_employee', store=True) + feed_id = fields.Many2one('ftp.feed', required=True, ondelete='cascade') + comment_time = fields.Char(compute='_compute_comment_time', string='Commented') + + @api.depends('user_id') + def _compute_employee(self): + for record in self: + employee = self.env['hr.employee'].search([('user_id', '=', record.user_id.id)], limit=1) + record.employee_id = employee.id if employee else False + + @api.depends('create_date') + def _compute_comment_time(self): + for record in self: + if record.create_date: + delta = datetime.now() - record.create_date + if delta.days > 0: + record.comment_time = f"{delta.days}d ago" + elif delta.seconds > 3600: + record.comment_time = f"{delta.seconds // 3600}h ago" + elif delta.seconds > 60: + record.comment_time = f"{delta.seconds // 60}m ago" + else: + record.comment_time = "Just now" + else: + record.comment_time = "" \ No newline at end of file diff --git a/addons_extensions/ftp_feed/security/ir.model.access.csv b/addons_extensions/ftp_feed/security/ir.model.access.csv new file mode 100644 index 000000000..d61fe4c24 --- /dev/null +++ b/addons_extensions/ftp_feed/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_ftp_feed,access_ftp_feed,model_ftp_feed,,1,1,1,1 +access_ftp_feed_data,access_ftp_feed_data,model_ftp_feed_data,,1,1,1,1 +access_ftp_feed_comments,access_ftp_feed_comments,model_ftp_feed_comments,,1,1,1,1 +access_ftp_feed_attachment,ftp.feed.attachment.access,base.model_ir_attachment,base.group_user,1,0,0,0 diff --git a/addons_extensions/ftp_feed/security/security.xml b/addons_extensions/ftp_feed/security/security.xml new file mode 100644 index 000000000..4b732fc0c --- /dev/null +++ b/addons_extensions/ftp_feed/security/security.xml @@ -0,0 +1,14 @@ + + + + + Feed - Read + + [(1, '=', 1)] + + + + + + + diff --git a/addons_extensions/ftp_feed/static/description/banner.png b/addons_extensions/ftp_feed/static/description/banner.png new file mode 100644 index 000000000..53845a42e Binary files /dev/null and b/addons_extensions/ftp_feed/static/description/banner.png differ diff --git a/addons_extensions/ftp_feed/static/description/banner_2.png b/addons_extensions/ftp_feed/static/description/banner_2.png new file mode 100644 index 000000000..e8a670f00 Binary files /dev/null and b/addons_extensions/ftp_feed/static/description/banner_2.png differ diff --git a/addons_extensions/ftp_feed/views/feed.xml b/addons_extensions/ftp_feed/views/feed.xml new file mode 100644 index 000000000..69f8514e4 --- /dev/null +++ b/addons_extensions/ftp_feed/views/feed.xml @@ -0,0 +1,156 @@ + + + + ftp.feed.form + ftp.feed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ftp.feed.list + ftp.feed + + + + + + + + + + + + + ftp.feed.kanban + ftp.feed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Social Feed + ftp.feed + kanban,list,form + {'default_user_id': uid} + + + Share updates with your team! + + + + + + + + \ No newline at end of file diff --git a/addons_extensions/hr_payroll/__manifest__.py b/addons_extensions/hr_payroll/__manifest__.py index ab74ceec4..839cd1ad0 100644 --- a/addons_extensions/hr_payroll/__manifest__.py +++ b/addons_extensions/hr_payroll/__manifest__.py @@ -66,6 +66,7 @@ 'web.assets_backend': [ 'hr_payroll/static/src/components/add_payslips/**', 'hr_payroll/static/src/views/add_payslips_hook.js', + 'hr_payroll/static/src/js/payslip_line_one2many.js' # 'hr_payroll/static/src/**/*', # ('remove', 'hr_payroll/static/src/js/hr_payroll_report_graph_view.js'), # ('remove', 'hr_payroll/static/src/js/hr_payroll_report_pivot_*'), diff --git a/addons_extensions/hr_payroll/models/wages_register.py b/addons_extensions/hr_payroll/models/wages_register.py new file mode 100644 index 000000000..40be490c1 --- /dev/null +++ b/addons_extensions/hr_payroll/models/wages_register.py @@ -0,0 +1,61 @@ +from datetime import timedelta, datetime, date +from dateutil.relativedelta import relativedelta +from odoo import api, fields, models, _ +from odoo.http import request +from odoo import http +import babel.dates + + + +class HrPayslip(models.Model): + _inherit = 'hr.payslip' + + @api.model + def get_wage_register_data(self, date): + if not date: + now = fields.Datetime.now() + date = babel.dates.format_datetime(now, "MMMM yyyy", locale='en') + sql = """ + SELECT + e.name AS employee, + job.name AS designation, + e.doj AS date_of_joining, + e.birthday AS date_of_birth, + to_char(p.date_from, 'Month YYYY') AS month_of_wages, + e.l10n_in_uan AS uan_no, + e.l10n_in_esic_number AS esic_no, + bank.acc_number AS bank_account_no, + + SUM(CASE WHEN pl.code = 'BASIC' THEN pl.total ELSE 0 END) AS basic, + SUM(CASE WHEN pl.code = 'HRA' THEN pl.total ELSE 0 END) AS hra, + SUM(CASE WHEN pl.code = 'SPA' THEN pl.total ELSE 0 END) AS other_allowance, + SUM(CASE WHEN pl.code = 'GROSS' THEN pl.total ELSE 0 END) AS gross_wages, + + SUM(CASE WHEN pl.code = 'ESICS' THEN pl.total ELSE 0 END) AS esi, + SUM(CASE WHEN pl.code = 'PF' THEN pl.total ELSE 0 END) AS pf, + SUM(CASE WHEN pl.code = 'PT' THEN pl.total ELSE 0 END) AS pt, + SUM(CASE WHEN pl.code = 'DED' THEN pl.total ELSE 0 END) AS total_deductions, + + SUM(CASE WHEN pl.code = 'LTA' THEN pl.total ELSE 0 END) AS lta, + p.net_wage AS net_amount_payable + +FROM hr_payslip p + JOIN hr_employee e ON p.employee_id = e.id + LEFT JOIN hr_job job ON e.job_id = job.id + LEFT JOIN hr_payslip_line pl ON pl.slip_id = p.id + LEFT JOIN hr_salary_rule_category cat_earn ON cat_earn.code = 'GROSS' + LEFT JOIN hr_salary_rule_category cat_deduct ON cat_deduct.code = 'DED' + LEFT JOIN res_partner_bank bank ON bank.id = e.bank_account_id + +GROUP BY + e.name, job.name, e.doj, e.birthday, + p.date_from, e.l10n_in_uan, e.l10n_in_esic_number, e.bank_account_id, p.net_wage, bank.acc_number +ORDER BY e.name; + """ + self.env.cr.execute(sql) + result = self.env.cr.dictfetchall() + data = [] + for i in result: + i['designation'] = i['designation']['en_US'] + data.append(i) + return data diff --git a/addons_extensions/hr_payroll/static/src/js/payslip_batch.js b/addons_extensions/hr_payroll/static/src/js/payslip_batch.js new file mode 100644 index 000000000..254516ca5 --- /dev/null +++ b/addons_extensions/hr_payroll/static/src/js/payslip_batch.js @@ -0,0 +1,215 @@ +/** @odoo-module **/ +import { standardWidgetProps } from "@web/views/widgets/standard_widget_props"; +import { Component, onMounted, useRef, useState, onWillStart } from "@odoo/owl"; +import { registry } from "@web/core/registry"; +import { useService } from "@web/core/utils/hooks"; +import { loadJS, loadCSS } from "@web/core/assets"; + +export class SaleTest extends Component { + static props = { + ...standardWidgetProps, + }; + static template = "SaleTest"; + setup() { + this.orm = useService("orm"); + this.gridRef = useRef("wageGrid"); + this.state = useState({ rows: [] }); + + onWillStart(async () => { + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"); + window.$ = window.jQuery = window.$ || window.jQuery; + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"); + await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/themes/base/jquery-ui.min.css"); + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.js"); + await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.css"); + await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/themes/steelblue/pqgrid.min.css"); + await this.loadData(); + }); + + onMounted(() => { + if (this.gridRef.el) { + this.renderGrid(); + setTimeout(() => this.initializeDatePicker(), 200); + } else { + console.error("Grid element not found"); + } + }); + } + + renderGrid() { + const data = this.state.rows.length ? this.state.rows : [ + { + employee: "John Doe", designation: "Software Engineer", date_of_joining: "2020-01-10", + date_of_birth: "1990-04-15", month_of_wages: "January 2024", days_worked: 22, + uan_no: "100100100", esic_no: "ESIC12345", bank_account_no: "1234567890", + basic: 35000, hra: 15000, lta: 5000, other_allowance: 5000, + gross_wages: 60000, esi: 500, pf: 1800, pt: 200, total_deductions: 2500, net_amount_payable: 57500 + } + ]; + + $(this.gridRef.el).pqGrid({ + width: "100%", + height: 600, + editable: false, + showSummary: true, + filterModel: { + on: true, + mode: "AND", + header: true + }, + toolbar: { + items: [ + { + type: "button", + label: "GET", + icon: "fa fa-check", + listener: () => this.onFilterClick() + }, + { + type: "button", + label: "Export to Excel", + icon: "ui-icon-document", + listener: () => this.exportExcel() + }, + { + type: "button", + label: "Export to PDF", + icon: "ui-icon-print", + listener: () => this.exportPDF() + } + ] + }, + colModel: [ + { title: "Name of the Employee", dataIndx: "employee", width: 220, filter: {type: 'textbox', condition: 'begin', listeners: ['keyup']} }, + { title: "Designation / Category", dataIndx: "designation", width: 150, filter: {type: 'textbox', condition: 'begin', listeners: ['keyup']} }, + { title: "Date of Joining", dataIndx: "date_of_joining", width: 90 }, + { title: "Date of Birth", dataIndx: "date_of_birth", width: 90 }, + { title: "Month of Wages", dataIndx: "month_of_wages", width: 150 }, + { title: "No. of Days Worked", dataIndx: "days_worked", width: 90 }, + { title: "UAN No.", dataIndx: "uan_no", width: 150 }, + { title: "ESIC No.", dataIndx: "esic_no", width: 150 }, + { title: "Bank Account No.", dataIndx: "bank_account_no", width: 150, filter: {type: 'textbox', condition: 'begin', listeners: ['keyup']} }, + { title: "Basic", dataIndx: "basic", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }, + { title: "HRA", dataIndx: "hra", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }, + { title: "LTA", dataIndx: "lta", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }, + { title: "Other Allowance", dataIndx: "other_allowance", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }, + { title: "Gross Wages", dataIndx: "gross_wages", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }, + { title: "ESI", dataIndx: "esi", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }, + { title: "PF", dataIndx: "pf", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }, + { title: "PT", dataIndx: "pt", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }, + { title: "Total Deductions", dataIndx: "total_deductions", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }, + { title: "Net Amount Payable", dataIndx: "net_amount_payable", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" } + ], + dataModel: { + data: data, + location: "local" + }, + groupModel: { + on: true, + dataIndx: ["month_of_wages"], + showSummary: true + } + }); + } + + initializeDatePicker() { + $("#fromDate").datepicker({ + changeMonth: true, + changeYear: true, + showButtonPanel: true, + dateFormat: 'MM yy', + onClose: function (dateText, inst) { + const month = $("#ui-datepicker-div .ui-datepicker-month :selected").val(); + const year = $("#ui-datepicker-div .ui-datepicker-year :selected").val(); + $(this).datepicker('setDate', new Date(year, month, 1)); + }, + beforeShow: function (input, inst) { + $(input).datepicker("widget").addClass("monthOnly"); + } + }); + + $("
+ Share updates with your team! +