Initial Commit

This commit is contained in:
2023-12-21 12:02:04 +01:00
parent 141ad6bfcd
commit edc8cffc69
49 changed files with 0 additions and 1732 deletions

View File

@@ -1,5 +0,0 @@
from . import calendar_event_type
from . import hr_employee
from . import hr_lv_allocation
from . import res_company
from . import res_config_settings

View File

@@ -1,17 +0,0 @@
from odoo import fields, models
class MeetingType(models.Model):
_inherit = "calendar.event.type"
ref = fields.Char(
string="Reference",
copy=False,
store=True,
)
remove_luncheon_voucher = fields.Boolean(
string="Remove luncheon voucher",
copy=True,
store=True,
)

View File

@@ -1,83 +0,0 @@
from xml.dom.minicompat import EmptyNodeList
from odoo import fields, models, api
class HrEmployeeBase(models.AbstractModel):
_inherit = "hr.employee.base"
lv_allocations_ids = fields.One2many("hr.lv.allocation", "employee_id")
total_acquired_lv = fields.Integer(
string="Total allocated luncheon vouchers", store=True, copy=False
)
distributed_lv = fields.Integer(
string="Distributed luncheon vouchers", store=True, copy=False
)
dued_lv = fields.Integer(
string="Remaining luncheon vouchers", store=True, copy=False
)
default_monthly_lv = fields.Integer(
string="Default monthly distribution", store=True, copy=True
)
def refresh_lv_values(self):
for record in self:
record._compute_total_acquired_lv()
record._compute_distributed_lv()
record._compute_dued_lv()
def _compute_total_acquired_lv(self):
for record in self:
allocations = self.env["hr.lv.allocation"].search(
[("employee_id", "=", record.id), ("state", "=", ["confirmed", "distributed"])]
)
record.total_acquired_lv = sum(allocations.mapped("number_acquired_lv"))
def _compute_distributed_lv(self):
for record in self:
allocations = self.env["hr.lv.allocation"].search(
[("employee_id", "=", record.id), ("state", "=", "distributed")]
)
record.distributed_lv = sum(allocations.mapped("number_distributed_lv"))
def _compute_dued_lv(self):
for record in self:
record.dued_lv = record.total_acquired_lv - record.distributed_lv
def generate_mass_lv_allocation(self, values):
for record in self:
record.generate_lv_allocation(values)
def generate_lv_allocation(self, values):
self.ensure_one()
values["employee_id"] = self.id
values["name"] = values["distrib_campaign_name"] + " - " + self.name
self.env["hr.lv.allocation"].create(values)
def action_lv_allocations(self):
action = self.env["ir.actions.act_window"]._for_xml_id("hr_luncheon_voucher.act_lv_allocations")
action['context'] = {
'search_default_employee_id': self.id,
'default_employee_id': self.id,
}
action['domain'] = [('employee_id', '=', self.id)]
return action
def action_lv_allocations_requests_wizard(self):
action = self.env["ir.actions.act_window"]._for_xml_id(
"hr_luncheon_voucher.lv_allocations_requests_wizard_action"
)
ctx = dict(self.env.context)
ctx["active_ids"] = self.ids
action["context"] = ctx
return action
@api.model
def _name_search(self, name='', args=None, operator='ilike', limit=100, name_get_uid=None):
"""
On lv allocation, allow employee search on all companies
"""
if self.env.context.get('search_all_campanies'):
return super(HrEmployeeBase, self.sudo())._name_search(name, args, operator, limit, name_get_uid)
return super(HrEmployeeBase, self)._name_search(name, args, operator, limit, name_get_uid)

View File

@@ -1,186 +0,0 @@
from datetime import datetime, timedelta, time
from dateutil.rrule import rrule, DAILY
from pytz import UTC
from odoo import fields, models, api
class LuncheonVouchersAllocation(models.Model):
_name = "hr.lv.allocation"
_description = "Luncheon Vouchers Allocation"
name = fields.Char('Name')
distrib_campaign_name = fields.Char('Distribution campaign')
state = fields.Selection(
[
("draft", "Draft"),
("confirmed", "Confirmed"),
("distributed", "Distributed"),
],
string="Status",
readonly=True,
copy=False,
default="draft",
help="The status is set to 'Draft', when an allocation request is created. The status is 'Confirmed', when an allocation request is confirmed by HR manager. The status is 'Distributed', when the luncheon vouchers have been distributed.",
)
date_from = fields.Datetime(
string="Start Date",
store=True,
readonly=False,
copy=False,
states={
"confirmed": [("readonly", True)],
"distributed": [("readonly", True)],
},
)
date_to = fields.Datetime(
string="End Date",
store=True,
readonly=False,
copy=False,
states={
"confirmed": [("readonly", True)],
"distributed": [("readonly", True)],
},
)
employee_id = fields.Many2one(
"hr.employee",
store=True,
string="Employee",
index=True,
readonly=False,
ondelete="restrict",
states={
"confirmed": [("readonly", True)],
"distributed": [("readonly", True)],
},
)
number_acquired_lv = fields.Integer(
string="Acquired Vouchers",
store=True,
readonly=False,
states={
"confirmed": [("readonly", True)],
"distributed": [("readonly", True)],
},
)
number_dued_lv = fields.Integer(
string="Dued Vouchers",
store=True,
readonly=False,
states={
"confirmed": [("readonly", True)],
"distributed": [("readonly", True)],
},
)
number_distributed_lv = fields.Integer(
string="Distributed Vouchers",
store=True,
readonly=False,
states={
"confirmed": [("readonly", False)],
"distributed": [("readonly", True)],
},
)
lv_balance = fields.Integer('Vouchers balance', compute="_get_lv_balance", help="Vouchers available after distribution. Dued vouchers - Distributed vouchers")
@api.depends("number_dued_lv", "number_distributed_lv")
def _get_lv_balance(self):
for allocation in self:
allocation.lv_balance = allocation.number_dued_lv - allocation.number_distributed_lv
@api.model_create_multi
def create(self, values):
res = super(LuncheonVouchersAllocation, self).create(values)
res._calculate_number_acquired_lv()
res._calculate_number_dued_lv()
res._default_number_distributed_lv()
return res
@api.depends("employee_id")
def _default_number_distributed_lv(self):
for record in self:
record.number_distributed_lv = record.employee_id.default_monthly_lv
def _has_cancelling_voucher_event(self, day):
category_no_voucher_ids = self.env["calendar.event.type"].search([("remove_luncheon_voucher", "=", True)])
events = self.env["calendar.event"].search(
[
("categ_ids", "in", category_no_voucher_ids.ids),
("partner_ids", "in", self.employee_id.user_id.partner_id.id)
]
)
day_start = fields.Datetime.to_datetime(day.date())
day_end = fields.Datetime.to_datetime(day.date()) + timedelta(hours=24)
cancelling_events = events.filtered(lambda x: not((x.start < day_start) and (x.stop <= day_start)) and not((x.start >= day_end) and (x.stop > day_end)) )
if len(cancelling_events) > 0:
return True
else:
return False
def _calculate_number_acquired_lv(self):
nb_eligible_days = 0
dfrom = datetime.combine(fields.Date.from_string(self.date_from), time.min).replace(tzinfo=UTC)
dto = datetime.combine(fields.Date.from_string(self.date_to), time.max).replace(tzinfo=UTC)
period_days = rrule(DAILY, dfrom, until=dto)
calendar_resource = self.employee_id.resource_calendar_id
for day in period_days:
# Check if this days is a working day
if not calendar_resource.is_working_day(day):
continue
# The employee should work this day but...
if self.env.company.hr_half_day_cancels_voucher and not calendar_resource.is_full_working_day(day):
# The luncheon voucher is acquired only if the employee has worked the entire day
continue
# Check leaves
if not calendar_resource.is_worked_day(self.employee_id, day):
continue
# The employee has worked this day but...
if self.env.company.hr_half_day_cancels_voucher and not calendar_resource.all_attendances_worked(self.employee_id.resource_id, day):
# The luncheon voucher is acquired only if the employee has worked the entire day
continue
# Check there is no event cancelling the voucher
if self._has_cancelling_voucher_event(day):
continue
# All checks passed, the days is eligible for a voucher
nb_eligible_days += 1
self.number_acquired_lv = nb_eligible_days
def _calculate_number_dued_lv(self):
for record in self:
if record.state == "distributed":
record.number_dued_lv = record.employee_id.dued_lv
else:
record.number_dued_lv = (
record.employee_id.dued_lv + record.number_acquired_lv
)
def confirm_allocation(self):
for record in self:
if record.state == "draft":
record.state = "confirmed"
record.employee_id._compute_total_acquired_lv()
record.employee_id._compute_dued_lv()
def back_to_draft(self):
for record in self:
if record.state in ["confirmed","distributed"]:
record.state = "draft"
record.employee_id._compute_total_acquired_lv()
record.employee_id._compute_distributed_lv()
record.employee_id._compute_dued_lv()
def distribute_allocation(self):
for record in self:
if record.state == "confirmed":
record.state = "distributed"
record.employee_id._compute_distributed_lv()
record.employee_id._compute_dued_lv()
def adjust_distribution(self):
for record in self:
for record in self:
if record.state == "draft":
record.number_distributed_lv = record.employee_id.dued_lv + record.number_acquired_lv

View File

@@ -1,7 +0,0 @@
from odoo import fields, models
class Company(models.Model):
_inherit = 'res.company'
hr_half_day_cancels_voucher = fields.Boolean(string="Half working days cancel luncheon vouchers")

View File

@@ -1,8 +0,0 @@
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
hr_half_day_cancels_voucher = fields.Boolean(string="Half working days cancel luncheon vouchers", related="company_id.hr_half_day_cancels_voucher", readonly=False)