server-ux/date_range/wizard/date_range_generator.py
2021-03-23 20:38:33 +01:00

114 lines
4.5 KiB
Python

# Copyright 2016 ACSONE SA/NV (<https://acsone.eu>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from flectra import api, fields, models
from flectra.tools.translate import _
from flectra.exceptions import ValidationError
from dateutil.rrule import (rrule,
YEARLY,
MONTHLY,
WEEKLY,
DAILY)
from dateutil.relativedelta import relativedelta
class DateRangeGenerator(models.TransientModel):
_name = 'date.range.generator'
_description = 'Date Range Generator'
@api.model
def _default_company(self):
return self.env['res.company']._company_default_get('date.range')
name_prefix = fields.Char('Range name prefix', required=True)
date_start = fields.Date(strint='Start date', required=True)
type_id = fields.Many2one(
comodel_name='date.range.type', string='Type', required=True,
domain="['|', ('company_id', '=', company_id), "
"('company_id', '=', False)]", ondelete='cascade')
company_id = fields.Many2one(
comodel_name='res.company', string='Company',
default=_default_company)
unit_of_time = fields.Selection([
(YEARLY, 'years'),
(MONTHLY, 'months'),
(WEEKLY, 'weeks'),
(DAILY, 'days')], required=True)
duration_count = fields.Integer('Duration', required=True)
count = fields.Integer(
string="Number of ranges to generate", required=True)
parent_id = fields.Many2one(
comodel_name='date.range', string="Parent", index=1)
@api.multi
def _compute_date_ranges(self):
self.ensure_one()
vals = rrule(freq=self.unit_of_time, interval=self.duration_count,
dtstart=fields.Date.from_string(self.date_start),
count=self.count+1)
vals = list(vals)
date_ranges = []
count_digits = len(str(self.count))
for idx, dt_start in enumerate(vals[:-1]):
date_start = fields.Date.to_string(dt_start.date())
# always remove 1 day for the date_end since range limits are
# inclusive
dt_end = vals[idx+1].date() - relativedelta(days=1)
date_end = fields.Date.to_string(dt_end)
date_ranges.append({
'name': '%s%0*d' % (
self.name_prefix, count_digits, idx + 1),
'date_start': date_start,
'date_end': date_end,
'type_id': self.type_id.id,
'company_id': self.company_id.id,
'parent_id': self.parent_id.id})
return date_ranges
@api.onchange('company_id')
def _onchange_company_id(self):
if self.company_id and self.type_id.company_id and \
self.type_id.company_id != self.company_id:
self._cache.update(
self._convert_to_cache({'type_id': False}, update=True))
@api.multi
@api.constrains('company_id', 'type_id')
def _check_company_id_type_id(self):
for rec in self.sudo():
if rec.company_id and rec.type_id.company_id and\
rec.company_id != rec.type_id.company_id:
raise ValidationError(
_('The Company in the Date Range Generator and in '
'Date Range Type must be the same.'))
@api.multi
def action_apply(self):
date_ranges = self._compute_date_ranges()
if date_ranges:
for dr in date_ranges:
self.env['date.range'].create(dr)
return self.env['ir.actions.act_window'].for_xml_id(
module='date_range', xml_id='date_range_action')
@api.multi
@api.onchange('type_id', 'date_start')
def onchange_type_id(self):
self.ensure_one()
date_range = self.env['date.range']
domain = []
if self.type_id:
domain.append(('type_id', '=', self.type_id.parent_type_id.id))
if self.date_start:
domain.append('|')
domain.append(('date_start', '<=', self.date_start))
domain.append(('date_start', '=', False))
if domain:
# If user did not select a parent already, autoselect the last
# (ordered by date_start) or only parent that applies.
if self.type_id and self.date_start and not self.parent_id:
possible_parent = date_range.search(
domain, limit=1, order='date_start desc')
self.parent_id = possible_parent # can be empty!
return {'domain': {'parent_id': domain}}