forked from Mapan/odoo17e
150 lines
5.7 KiB
Python
150 lines
5.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from datetime import date
|
|
|
|
from odoo import _, api, fields, models
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.osv import expression
|
|
|
|
|
|
class L10nHkRental(models.Model):
|
|
_name = 'l10n_hk.rental'
|
|
_description = "Hong Kong: Rental"
|
|
|
|
name = fields.Char("Rental Reference", required=True)
|
|
active = fields.Boolean(default=True)
|
|
address = fields.Char("Address")
|
|
state = fields.Selection([
|
|
('draft', 'Draft'),
|
|
('open', 'Running'),
|
|
('close', 'Expired'),
|
|
('cancel', 'Cancelled'),
|
|
], default='draft', required=True, copy=False)
|
|
employee_id = fields.Many2one(
|
|
'hr.employee',
|
|
string='Employee',
|
|
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]",
|
|
required=True)
|
|
date_start = fields.Date(
|
|
'Start Date', required=True, default=fields.Date.today, index=True)
|
|
date_end = fields.Date('End Date')
|
|
amount = fields.Monetary(
|
|
"Rental Amount", required=True)
|
|
nature = fields.Selection(
|
|
selection=[
|
|
('flat', 'Flat'),
|
|
('hotel', 'Hotel')
|
|
], string='Rental Type', default='flat', required=True)
|
|
company_id = fields.Many2one(
|
|
'res.company',
|
|
store=True,
|
|
readonly=False,
|
|
compute='_compute_company_id',
|
|
default=lambda self: self.env.company,
|
|
required=True)
|
|
currency_id = fields.Many2one(
|
|
string="Currency",
|
|
related='company_id.currency_id',
|
|
readonly=True)
|
|
rentals_count = fields.Integer(related='employee_id.l10n_hk_rentals_count')
|
|
|
|
@api.depends('employee_id')
|
|
def _compute_company_id(self):
|
|
for rental in self:
|
|
if not rental.employee_id:
|
|
continue
|
|
rental.company_id = rental.employee_id.company_id
|
|
|
|
@api.constrains('employee_id', 'state', 'date_start', 'date_end')
|
|
def _check_current_rental(self):
|
|
for rental in self:
|
|
if rental.state in ['draft', 'cancel'] or not rental.employee_id:
|
|
continue
|
|
domain = [
|
|
('id', '!=', rental.id),
|
|
('employee_id', '=', rental.employee_id.id),
|
|
('company_id', '=', rental.company_id.id),
|
|
('state', 'in', ['open', 'close']),
|
|
]
|
|
if not rental.date_end:
|
|
start_domain = []
|
|
end_domain = ['|', ('date_end', '>=', rental.date_start), ('date_end', '=', False)]
|
|
else:
|
|
start_domain = [('date_start', '<=', rental.date_end)]
|
|
end_domain = ['|', ('date_end', '>', rental.date_start), ('date_end', '=', False)]
|
|
|
|
domain = expression.AND([domain, start_domain, end_domain])
|
|
if self.search_count(domain):
|
|
raise ValidationError(_(
|
|
'Rental %(rental)s: employee %(employee)s already has a rental running during this period.',
|
|
rental=rental.name, employee=rental.employee_id.name,
|
|
))
|
|
|
|
@api.constrains('date_start', 'date_end')
|
|
def _check_dates(self):
|
|
for rental in self:
|
|
if rental.date_end and rental.date_start > rental.date_end:
|
|
raise ValidationError(_(
|
|
'Rental %(rental)s: start date (%(start)s) must be earlier than rental end date (%(end)s).',
|
|
rental=rental.name, start=rental.date_start, end=rental.date_end,
|
|
))
|
|
|
|
@api.model
|
|
def update_state(self):
|
|
rentals_to_close = self.search([
|
|
('state', '=', 'open'),
|
|
('date_end', '<=', fields.Date.to_string(date.today())),
|
|
])
|
|
if rentals_to_close:
|
|
rentals_to_close.write({'state': 'close'})
|
|
|
|
rentals_to_open = self.search([
|
|
('state', '=', 'draft'),
|
|
('date_start', '<=', fields.Date.to_string(date.today())),
|
|
])
|
|
if rentals_to_open:
|
|
rentals_to_open.write({'state': 'open'})
|
|
return True
|
|
|
|
def _assign_open_rental(self):
|
|
for rental in self:
|
|
rental.employee_id.sudo().write({'l10n_hk_rental_id': rental.id})
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
rentals = super().create(vals_list)
|
|
rentals.filtered(lambda r: r.state == 'open')._assign_open_rental()
|
|
return rentals
|
|
|
|
def write(self, vals):
|
|
old_state = {c.id: c.state for c in self}
|
|
res = super().write(vals)
|
|
new_state = {c.id: c.state for c in self}
|
|
if vals.get('state') == 'open':
|
|
self._assign_open_rental()
|
|
for rental in self:
|
|
if rental == rental.sudo().employee_id.l10n_hk_rental_id \
|
|
and old_state[rental.id] == 'open' \
|
|
and new_state[rental.id] != 'open':
|
|
running_rental = self.env['l10n_hk.rental'].search([
|
|
('employee_id', '=', rental.employee_id.id),
|
|
('company_id', '=', rental.company_id.id),
|
|
('state', '=', 'open'),
|
|
])
|
|
if running_rental:
|
|
rental.employee_id.l10n_hk_rental_id = running_rental[0]
|
|
else:
|
|
rental.employee_id.l10n_hk_rental_id = False
|
|
return res
|
|
|
|
def action_open_rentals_list(self):
|
|
self.ensure_one()
|
|
action = self.env["ir.actions.actions"]._for_xml_id("l10n_hk_hr_payroll.action_l10n_hk_rental")
|
|
action.update({
|
|
'domain': [('employee_id', '=', self.employee_id.id)],
|
|
'views': [[False, 'list'], [False, 'form']],
|
|
'context': {'default_employee_id': self.employee_id.id},
|
|
})
|
|
return action
|