123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- # -*- coding: utf-8 -*-
- # Part of Odoo. See LICENSE file for full copyright and licensing details.
- from dateutil.relativedelta import relativedelta
- from odoo import api, fields, models
- class FleetVehicleLogContract(models.Model):
- _inherit = ['mail.thread', 'mail.activity.mixin']
- _name = 'fleet.vehicle.log.contract'
- _description = 'Vehicle Contract'
- _order = 'state desc,expiration_date'
- def compute_next_year_date(self, strdate):
- oneyear = relativedelta(years=1)
- start_date = fields.Date.from_string(strdate)
- return fields.Date.to_string(start_date + oneyear)
- vehicle_id = fields.Many2one('fleet.vehicle', 'Vehicle', required=True, check_company=True)
- cost_subtype_id = fields.Many2one('fleet.service.type', 'Type', help='Cost type purchased with this cost', domain=[('category', '=', 'contract')])
- amount = fields.Monetary('Cost', tracking=True)
- date = fields.Date(help='Date when the cost has been executed')
- company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.company)
- currency_id = fields.Many2one('res.currency', related='company_id.currency_id')
- name = fields.Char(string='Name', compute='_compute_contract_name', store=True, readonly=False)
- active = fields.Boolean(default=True)
- user_id = fields.Many2one('res.users', 'Responsible', default=lambda self: self.env.user, index=True)
- start_date = fields.Date(
- 'Contract Start Date', default=fields.Date.context_today,
- help='Date when the coverage of the contract begins')
- expiration_date = fields.Date(
- 'Contract Expiration Date', default=lambda self:
- self.compute_next_year_date(fields.Date.context_today(self)),
- help='Date when the coverage of the contract expirates (by default, one year after begin date)')
- days_left = fields.Integer(compute='_compute_days_left', string='Warning Date')
- expires_today = fields.Boolean(compute='_compute_days_left')
- insurer_id = fields.Many2one('res.partner', 'Vendor')
- purchaser_id = fields.Many2one(related='vehicle_id.driver_id', string='Driver')
- ins_ref = fields.Char('Reference', size=64, copy=False)
- state = fields.Selection(
- [('futur', 'Incoming'),
- ('open', 'In Progress'),
- ('expired', 'Expired'),
- ('closed', 'Closed')
- ], 'Status', default='open', readonly=True,
- help='Choose whether the contract is still valid or not',
- tracking=True,
- copy=False)
- notes = fields.Html('Terms and Conditions', copy=False)
- cost_generated = fields.Monetary('Recurring Cost', tracking=True)
- cost_frequency = fields.Selection([
- ('no', 'No'),
- ('daily', 'Daily'),
- ('weekly', 'Weekly'),
- ('monthly', 'Monthly'),
- ('yearly', 'Yearly')
- ], 'Recurring Cost Frequency', default='monthly', required=True)
- service_ids = fields.Many2many('fleet.service.type', string="Included Services")
- @api.depends('vehicle_id.name', 'cost_subtype_id')
- def _compute_contract_name(self):
- for record in self:
- name = record.vehicle_id.name
- if name and record.cost_subtype_id.name:
- name = record.cost_subtype_id.name + ' ' + name
- record.name = name
- @api.depends('expiration_date', 'state')
- def _compute_days_left(self):
- """return a dict with as value for each contract an integer
- if contract is in an open state and is overdue, return 0
- if contract is in a closed state, return -1
- otherwise return the number of days before the contract expires
- """
- today = fields.Date.from_string(fields.Date.today())
- for record in self:
- if record.expiration_date and record.state in ['open', 'expired']:
- renew_date = fields.Date.from_string(record.expiration_date)
- diff_time = (renew_date - today).days
- record.days_left = diff_time if diff_time > 0 else 0
- record.expires_today = diff_time == 0
- else:
- record.days_left = -1
- record.expires_today = False
- def write(self, vals):
- res = super(FleetVehicleLogContract, self).write(vals)
- if 'start_date' in vals or 'expiration_date' in vals:
- date_today = fields.Date.today()
- future_contracts, running_contracts, expired_contracts = self.env[self._name], self.env[self._name], self.env[self._name]
- for contract in self.filtered(lambda c: c.start_date and c.state != 'closed'):
- if date_today < contract.start_date:
- future_contracts |= contract
- elif not contract.expiration_date or contract.start_date <= date_today <= contract.expiration_date:
- running_contracts |= contract
- else:
- expired_contracts |= contract
- future_contracts.action_draft()
- running_contracts.action_open()
- expired_contracts.action_expire()
- if vals.get('expiration_date') or vals.get('user_id'):
- self.activity_reschedule(['fleet.mail_act_fleet_contract_to_renew'], date_deadline=vals.get('expiration_date'), new_user_id=vals.get('user_id'))
- return res
- def action_close(self):
- self.write({'state': 'closed'})
- def action_draft(self):
- self.write({'state': 'futur'})
- def action_open(self):
- self.write({'state': 'open'})
- def action_expire(self):
- self.write({'state': 'expired'})
- @api.model
- def scheduler_manage_contract_expiration(self):
- # This method is called by a cron task
- # It manages the state of a contract, possibly by posting a message on the vehicle concerned and updating its status
- params = self.env['ir.config_parameter'].sudo()
- delay_alert_contract = int(params.get_param('hr_fleet.delay_alert_contract', default=30))
- date_today = fields.Date.from_string(fields.Date.today())
- outdated_days = fields.Date.to_string(date_today + relativedelta(days=+delay_alert_contract))
- reminder_activity_type = self.env.ref('fleet.mail_act_fleet_contract_to_renew', raise_if_not_found=False) or self.env['mail.activity.type']
- nearly_expired_contracts = self.search([
- ('state', '=', 'open'),
- ('expiration_date', '<', outdated_days),
- ('user_id', '!=', False)
- ]
- ).filtered(
- lambda nec: reminder_activity_type not in nec.activity_ids.activity_type_id
- )
- for contract in nearly_expired_contracts:
- contract.activity_schedule(
- 'fleet.mail_act_fleet_contract_to_renew', contract.expiration_date,
- user_id=contract.user_id.id)
- expired_contracts = self.search([('state', 'not in', ['expired', 'closed']), ('expiration_date', '<',fields.Date.today() )])
- expired_contracts.write({'state': 'expired'})
- futur_contracts = self.search([('state', 'not in', ['futur', 'closed']), ('start_date', '>', fields.Date.today())])
- futur_contracts.write({'state': 'futur'})
- now_running_contracts = self.search([('state', '=', 'futur'), ('start_date', '<=', fields.Date.today())])
- now_running_contracts.write({'state': 'open'})
- def run_scheduler(self):
- self.scheduler_manage_contract_expiration()
|