From 87028c063a48b8695db82c4e941c51f535955955 Mon Sep 17 00:00:00 2001 From: raman Date: Tue, 25 Mar 2025 10:51:50 +0530 Subject: [PATCH] cwf time sheets --- addons_extensions/cwf_timesheet/__init__.py | 1 + .../cwf_timesheet/__manifest__.py | 20 ++++ .../cwf_timesheet/controllers/controller.py | 9 ++ .../cwf_timesheet/data/email_template.xml | 109 ++++++++++++++++++ .../cwf_timesheet/models/__init__.py | 1 + .../cwf_timesheet/models/timesheet.py | 85 ++++++++++++++ .../security/ir.model.access.csv | 4 + .../static/src/js/timesheet_form.js | 48 ++++++++ .../cwf_timesheet/views/timesheet_form.xml | 27 +++++ .../cwf_timesheet/views/timesheet_view.xml | 83 +++++++++++++ 10 files changed, 387 insertions(+) create mode 100644 addons_extensions/cwf_timesheet/__init__.py create mode 100644 addons_extensions/cwf_timesheet/__manifest__.py create mode 100644 addons_extensions/cwf_timesheet/controllers/controller.py create mode 100644 addons_extensions/cwf_timesheet/data/email_template.xml create mode 100644 addons_extensions/cwf_timesheet/models/__init__.py create mode 100644 addons_extensions/cwf_timesheet/models/timesheet.py create mode 100644 addons_extensions/cwf_timesheet/security/ir.model.access.csv create mode 100644 addons_extensions/cwf_timesheet/static/src/js/timesheet_form.js create mode 100644 addons_extensions/cwf_timesheet/views/timesheet_form.xml create mode 100644 addons_extensions/cwf_timesheet/views/timesheet_view.xml diff --git a/addons_extensions/cwf_timesheet/__init__.py b/addons_extensions/cwf_timesheet/__init__.py new file mode 100644 index 000000000..43559cd9a --- /dev/null +++ b/addons_extensions/cwf_timesheet/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/addons_extensions/cwf_timesheet/__manifest__.py b/addons_extensions/cwf_timesheet/__manifest__.py new file mode 100644 index 000000000..6b23ded8f --- /dev/null +++ b/addons_extensions/cwf_timesheet/__manifest__.py @@ -0,0 +1,20 @@ +{ + 'name': 'CWF Timesheet Update', + 'version': '1.0', + 'category': 'Human Resources', + 'summary': 'Manage and update weekly timesheets for CWF department', + 'author': 'Your Name or Company', + 'depends': ['hr_attendance_extended','web', 'mail', 'base','hr_emp_dashboard'], + 'data': [ + # 'views/timesheet_form.xml', + 'security/ir.model.access.csv', + 'views/timesheet_view.xml', + 'data/email_template.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'cwf_timesheet/static/src/js/timesheet_form.js', + ], + }, + 'application': True, +} diff --git a/addons_extensions/cwf_timesheet/controllers/controller.py b/addons_extensions/cwf_timesheet/controllers/controller.py new file mode 100644 index 000000000..65377f44e --- /dev/null +++ b/addons_extensions/cwf_timesheet/controllers/controller.py @@ -0,0 +1,9 @@ +from odoo import http +from odoo.http import request + +class TimesheetController(http.Controller): + + @http.route('/timesheet/form', auth='user', website=True) + def timesheet_form(self, **kw): + # This will render the template for the timesheet form + return request.render('timesheet_form', {}) diff --git a/addons_extensions/cwf_timesheet/data/email_template.xml b/addons_extensions/cwf_timesheet/data/email_template.xml new file mode 100644 index 000000000..57410b9e2 --- /dev/null +++ b/addons_extensions/cwf_timesheet/data/email_template.xml @@ -0,0 +1,109 @@ + + + + Timesheet Update Reminder + ${(user.email or '')} + Reminder: Update Your Weekly Timesheet + + + + + + + + + diff --git a/addons_extensions/cwf_timesheet/models/__init__.py b/addons_extensions/cwf_timesheet/models/__init__.py new file mode 100644 index 000000000..63ae5f202 --- /dev/null +++ b/addons_extensions/cwf_timesheet/models/__init__.py @@ -0,0 +1 @@ +from . import timesheet \ No newline at end of file diff --git a/addons_extensions/cwf_timesheet/models/timesheet.py b/addons_extensions/cwf_timesheet/models/timesheet.py new file mode 100644 index 000000000..7688a8301 --- /dev/null +++ b/addons_extensions/cwf_timesheet/models/timesheet.py @@ -0,0 +1,85 @@ +from odoo import models, fields, api +from odoo.exceptions import ValidationError, UserError +from datetime import timedelta + +from odoo import _ + +class CwfTimesheet(models.Model): + _name = 'cwf.timesheet' + _description = 'CWF Weekly Timesheet' + + name = fields.Char(string='Week Name', required=True) + department_id = fields.Many2one('hr.department', string='Department') + week_start_date = fields.Date(string='Week Start Date', required=True) + week_end_date = fields.Date(string='Week End Date', required=True) + total_hours = fields.Float(string='Total Hours', required=True) + status = fields.Selection([ + ('draft', 'Draft'), + ('submitted', 'Submitted') + ], default='draft', string='Status') + lines = fields.One2many('cwf.timesheet.line','week_id') + + + + def send_timesheet_update_email(self): + template = self.env.ref('cwf_timesheet.email_template_timesheet_update') + # Ensure that we have a valid employee email + current_date = fields.Date.from_string(self.week_start_date) + end_date = fields.Date.from_string(self.week_end_date) + + if current_date > end_date: + raise UserError('The start date cannot be after the end date.') + + # Get all employees in the department + employees = self.env['hr.employee'].search([('department_id', '=', self.department_id.id)]) + + # Loop through each day of the week and create timesheet lines for each employee + while current_date <= end_date: + for employee in employees: + self.env['cwf.timesheet.line'].create({ + 'week_id': self.id, + 'employee_id': employee.id, + 'week_day':current_date, + }) + current_date += timedelta(days=1) + self.status = 'submitted' + for employee in employees: + if employee.work_email: + email_values = { + 'email_to': employee.work_email, + 'body_html': template.body_html, # Email body from template + 'subject': 'Timesheet Update Notification', + } + + template.send_mail(self.id, email_values=email_values, force_send=True) + + +class CwfTimesheetLine(models.Model): + _name = 'cwf.timesheet.line' + _description = 'CWF Weekly Timesheet Lines' + + employee_id = fields.Many2one('hr.employee', string='Employee') + week_id = fields.Many2one('cwf.timesheet', 'Week') + week_day = fields.Date(string='Date') + check_in_date = fields.Datetime(string='Checkin') + check_out_date = fields.Datetime(string='Checkout ') + is_updated = fields.Boolean('Attendance Updated') + state_type = fields.Selection([('draft','Draft'),('holiday', 'Holiday'),('time_off','Time Off'),('present','Present')], default='draft') + + def action_submit(self): + if self.state_type == 'draft' or not self.state_type: + raise ValidationError(_('State type should not Draft or Empty')) + if self.state_type not in ['holiday','time_off'] and not (self.check_in_date or self.check_out_date): + raise ValidationError(_('Please enter Check details')) + self._update_attendance() + + + def _update_attendance(self): + attendance_obj = self.env['hr.attendance'] + for record in self: + attendance_obj.sudo().create({ + 'employee_id': record.employee_id.id, + 'check_in': record.check_in_date, + 'check_out': record.check_out_date, + }) + record.is_updated = True diff --git a/addons_extensions/cwf_timesheet/security/ir.model.access.csv b/addons_extensions/cwf_timesheet/security/ir.model.access.csv new file mode 100644 index 000000000..6623ea460 --- /dev/null +++ b/addons_extensions/cwf_timesheet/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_cwf_timesheet_user,access.cwf.timesheet,model_cwf_timesheet,,1,1,1,1 +access_cwf_timesheet_line_user,access.cwf.timesheet.line,model_cwf_timesheet_line,,1,1,1,1 + diff --git a/addons_extensions/cwf_timesheet/static/src/js/timesheet_form.js b/addons_extensions/cwf_timesheet/static/src/js/timesheet_form.js new file mode 100644 index 000000000..52e4a134a --- /dev/null +++ b/addons_extensions/cwf_timesheet/static/src/js/timesheet_form.js @@ -0,0 +1,48 @@ +/** @odoo-module **/ + +import { patch } from "@web/core/utils/patch"; +import { NetflixProfileContainer } from "@hr_emp_dashboard/js/profile_component"; + +// Apply patch to NetflixProfileContainer prototype +patch(NetflixProfileContainer.prototype, { + /** + * @override + */ + setup() { + // Call parent setup method + + super.setup(...arguments); + + // Log the department of the logged-in employee (check if data is available) +// if (this.state && this.state.login_employee) { +// console.log(this.state.login_employee['department_id']); +// } else { +// console.error('Employee or department data is unavailable.'); +// } + }, + + /** + * Override the hr_timesheets method + */ + hr_timesheets() { + // Check the department of the logged-in employee + if (this.state.login_employee.department_id == 'CWF') { + // If the department is 'CWF', perform the action to open the timesheets + this.action.doAction({ + name: "Timesheets", + type: 'ir.actions.act_window', + res_model: 'cwf.timesheet.line', // Ensure this model exists + view_mode: 'list,form', + views: [[false, 'list'], [false, 'form']], + context: { + 'search_default_week_id': true, + }, + domain: [['employee_id.user_id','=', this.props.action.context.user_id]], + target: 'current', + }); + } else { + // If not 'CWF', call the base functionality + return super.hr_timesheets(); + } + }, +}); diff --git a/addons_extensions/cwf_timesheet/views/timesheet_form.xml b/addons_extensions/cwf_timesheet/views/timesheet_form.xml new file mode 100644 index 000000000..03a3b1d4f --- /dev/null +++ b/addons_extensions/cwf_timesheet/views/timesheet_form.xml @@ -0,0 +1,27 @@ + + + +
+

Weekly Timesheet

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
diff --git a/addons_extensions/cwf_timesheet/views/timesheet_view.xml b/addons_extensions/cwf_timesheet/views/timesheet_view.xml new file mode 100644 index 000000000..57f80f01e --- /dev/null +++ b/addons_extensions/cwf_timesheet/views/timesheet_view.xml @@ -0,0 +1,83 @@ + + + + CWF Timesheet + cwf.timesheet + list,form + + + cwf.timesheet.form + cwf.timesheet + +
+
+
+ +
+
+ + + + + + + + + + + + +
+
+
+
+ + + + + CWF Timesheet Lines + cwf.timesheet.line + list + {'search_default_group_by_employee_id':1} + + + cwf.timesheet.line.list + cwf.timesheet.line + + + + + + + +