Browse Source

Merge pull request #1430 from acsone/10.0-date_range-backport-11.0

[10.0] date_range: backport from 11.0
pull/1222/head
Laurent Mignon (ACSONE) 6 years ago
committed by GitHub
parent
commit
b432303471
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      date_range/README.rst
  2. 2
      date_range/__manifest__.py
  3. 22
      date_range/models/date_range.py
  4. 18
      date_range/models/date_range_type.py
  5. 1
      date_range/readme/CONTRIBUTORS.rst
  6. 12
      date_range/readme/HISTORY.rst
  7. 2
      date_range/readme/INSTALL.rst
  8. 4
      date_range/security/date_range_security.xml
  9. 2
      date_range/security/ir.model.access.csv
  10. 50
      date_range/static/description/index.html
  11. 63
      date_range/tests/test_date_range.py
  12. 44
      date_range/tests/test_date_range_generator.py
  13. 47
      date_range/tests/test_date_range_type.py
  14. 23
      date_range/wizard/date_range_generator.py

19
date_range/README.rst

@ -38,8 +38,6 @@ Installation
The addon use the daterange method from postgres. This method is supported as of postgresql 9.2
Usage
=====
@ -91,6 +89,22 @@ To configure this module, you need to:
:scale: 80 %
:alt: Date range as filter result
Changelog
=========
10.0.2.0.1 (2018-11-19)
~~~~~~~~~~~~~~~~~~~~~~~
* [FIX] Fix bug in DateRange._onchange_company_id not called
when type_id is changed
* [FIX] Fix bug in DateRangeType._check_company_id when called
with more than one record.
(`#26 <https://github.com/OCA/server-ux/pull/26>`_)
* [IMP] Adapt module to work in multi company.
(`#10 <https://github.com/OCA/server-ux/pull/10>`_)
* [FIX] Fix unlink date range type.
(`#9 <https://github.com/OCA/server-ux/pull/9>`_)
Bug Tracker
===========
@ -115,6 +129,7 @@ Contributors
* Laurent Mignon <laurent.mignon@acsone.eu>
* Alexis de Lattre <alexis.delattre@akretion.com>
* Miquel Raïch <miquel.raich@eficent.com>
* Andrea Stirpe <a.stirpe@onestein.nl>
Maintainers
~~~~~~~~~~~

2
date_range/__manifest__.py

@ -4,7 +4,7 @@
{
"name": "Date Range",
"summary": "Manage all kind of date range",
"version": "10.0.1.0.2",
"version": "10.0.2.0.1",
"category": "Uncategorized",
"website": "https://odoo-community.org/",
"author": "ACSONE SA/NV, Odoo Community Association (OCA)",

22
date_range/models/date_range.py

@ -9,6 +9,7 @@ from odoo.exceptions import ValidationError
class DateRange(models.Model):
_name = "date.range"
_description = "Date Range"
_order = "type_name,date_start"
@api.model
@ -19,7 +20,9 @@ class DateRange(models.Model):
date_start = fields.Date(string='Start date', required=True)
date_end = fields.Date(string='End date', required=True)
type_id = fields.Many2one(
comodel_name='date.range.type', string='Type', index=1, required=True)
comodel_name='date.range.type', string='Type', index=1, required=True,
ondelete='restrict', domain="['|', ('company_id', '=', company_id), "
"('company_id', '=', False)]")
type_name = fields.Char(
string='Type', related='type_id.name', readonly=True, store=True)
company_id = fields.Many2one(
@ -33,6 +36,23 @@ class DateRange(models.Model):
('date_range_uniq', 'unique (name,type_id, company_id)',
'A date range must be unique per company !')]
@api.onchange('company_id', 'type_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 and in '
'Date Range Type must be the same.'))
@api.constrains('type_id', 'date_start', 'date_end', 'company_id')
def _validate_range(self):
for this in self:

18
date_range/models/date_range_type.py

@ -3,10 +3,13 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
from odoo.tools.translate import _
from odoo.exceptions import ValidationError
class DateRangeType(models.Model):
_name = "date.range.type"
_description = "Date Range Type"
@api.model
def _default_company(self):
@ -22,7 +25,22 @@ class DateRangeType(models.Model):
company_id = fields.Many2one(
comodel_name='res.company', string='Company', index=1,
default=_default_company)
date_range_ids = fields.One2many('date.range', 'type_id', string='Ranges')
_sql_constraints = [
('date_range_type_uniq', 'unique (name,company_id)',
'A date range type must be unique per company !')]
@api.constrains('company_id')
def _check_company_id(self):
if not self.env.context.get('bypass_company_validation', False):
for rec in self.sudo():
if not rec.company_id:
continue
if bool(rec.date_range_ids.filtered(
lambda r: r.company_id and
r.company_id != rec.company_id)):
raise ValidationError(
_('You cannot change the company, as this '
'Date Range Type is assigned to Date Range '
'(%s).') % (rec.date_range_ids.name_get()[0][1]))

1
date_range/readme/CONTRIBUTORS.rst

@ -1,3 +1,4 @@
* Laurent Mignon <laurent.mignon@acsone.eu>
* Alexis de Lattre <alexis.delattre@akretion.com>
* Miquel Raïch <miquel.raich@eficent.com>
* Andrea Stirpe <a.stirpe@onestein.nl>

12
date_range/readme/HISTORY.rst

@ -0,0 +1,12 @@
10.0.2.0.1 (2018-11-19)
~~~~~~~~~~~~~~~~~~~~~~~
* [FIX] Fix bug in DateRange._onchange_company_id not called
when type_id is changed
* [FIX] Fix bug in DateRangeType._check_company_id when called
with more than one record.
(`#26 <https://github.com/OCA/server-ux/pull/26>`_)
* [IMP] Adapt module to work in multi company.
(`#10 <https://github.com/OCA/server-ux/pull/10>`_)
* [FIX] Fix unlink date range type.
(`#9 <https://github.com/OCA/server-ux/pull/9>`_)

2
date_range/readme/INSTALL.rst

@ -1,3 +1 @@
The addon use the daterange method from postgres. This method is supported as of postgresql 9.2

4
date_range/security/date_range_security.xml

@ -3,11 +3,11 @@
<record id="date_range_type_comp_rule" model="ir.rule">
<field name="name">Date Range Type multi-company</field>
<field name="model_id" ref="model_date_range_type"/>
<field name="domain_force"> ['|',('company_id','=',user.company_id.id),('company_id','=',False)]</field>
<field name="domain_force"> ['|',('company_id','child_of',[user.company_id.id]),('company_id','=',False)]</field>
</record>
<record id="date_range_comp_rule" model="ir.rule">
<field name="name">Date Range multi-company</field>
<field name="model_id" ref="model_date_range"/>
<field name="domain_force"> ['|',('company_id','=',user.company_id.id),('company_id','=',False)]</field>
<field name="domain_force"> ['|',('company_id','child_of',[user.company_id.id]),('company_id','=',False)]</field>
</record>
</odoo>

2
date_range/security/ir.model.access.csv

@ -2,4 +2,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_date_range_date_range,date_range.date_range,model_date_range,base.group_user,1,0,0,0
access_date_range_date_range_type,date_range.date_range_type,model_date_range_type,base.group_user,1,0,0,0
access_date_range_date_range_config,date_range.date_range.config,model_date_range,base.group_system,1,1,1,1
access_date_range_date_range_type_config,date_range.date_range_type.config,model_date_range_type,base.group_system,1,1,1,1
access_date_range_date_range_type_config,date_range.date_range_type.config,model_date_range_type,base.group_system,1,1,1,1

50
date_range/static/description/index.html

@ -373,23 +373,27 @@ your values in tree views.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#installation" id="id1">Installation</a></li>
<li><a class="reference internal" href="#usage" id="id2">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id7">Maintainers</a></li>
<li><a class="reference internal" href="#installation" id="id5">Installation</a></li>
<li><a class="reference internal" href="#usage" id="id6">Usage</a></li>
<li><a class="reference internal" href="#changelog" id="id7">Changelog</a><ul>
<li><a class="reference internal" href="#id1" id="id8">10.0.2.0.1 (2018-11-19)</a></li>
</ul>
</li>
<li><a class="reference internal" href="#bug-tracker" id="id9">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id10">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id11">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id12">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id13">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="installation">
<h1><a class="toc-backref" href="#id1">Installation</a></h1>
<h1><a class="toc-backref" href="#id5">Installation</a></h1>
<p>The addon use the daterange method from postgres. This method is supported as of postgresql 9.2</p>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#id2">Usage</a></h1>
<h1><a class="toc-backref" href="#id6">Usage</a></h1>
<p>To configure this module, you need to:</p>
<ul>
<li><p class="first">Go to Settings &gt; Technical &gt; Date ranges &gt; Date Range Types where
@ -428,8 +432,25 @@ you can create date ranges.</p>
</li>
</ul>
</div>
<div class="section" id="changelog">
<h1><a class="toc-backref" href="#id7">Changelog</a></h1>
<div class="section" id="id1">
<h2><a class="toc-backref" href="#id8">10.0.2.0.1 (2018-11-19)</a></h2>
<ul class="simple">
<li>[FIX] Fix bug in DateRange._onchange_company_id not called
when type_id is changed</li>
<li>[FIX] Fix bug in DateRangeType._check_company_id when called
with more than one record.
(<a class="reference external" href="https://github.com/OCA/server-ux/pull/26">#26</a>)</li>
<li>[IMP] Adapt module to work in multi company.
(<a class="reference external" href="https://github.com/OCA/server-ux/pull/10">#10</a>)</li>
<li>[FIX] Fix unlink date range type.
(<a class="reference external" href="https://github.com/OCA/server-ux/pull/9">#9</a>)</li>
</ul>
</div>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id3">Bug Tracker</a></h1>
<h1><a class="toc-backref" href="#id9">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/server-tools/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
@ -437,23 +458,24 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id4">Credits</a></h1>
<h1><a class="toc-backref" href="#id10">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id5">Authors</a></h2>
<h2><a class="toc-backref" href="#id11">Authors</a></h2>
<ul class="simple">
<li>ACSONE SA/NV</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id6">Contributors</a></h2>
<h2><a class="toc-backref" href="#id12">Contributors</a></h2>
<ul class="simple">
<li>Laurent Mignon &lt;<a class="reference external" href="mailto:laurent.mignon&#64;acsone.eu">laurent.mignon&#64;acsone.eu</a>&gt;</li>
<li>Alexis de Lattre &lt;<a class="reference external" href="mailto:alexis.delattre&#64;akretion.com">alexis.delattre&#64;akretion.com</a>&gt;</li>
<li>Miquel Raïch &lt;<a class="reference external" href="mailto:miquel.raich&#64;eficent.com">miquel.raich&#64;eficent.com</a>&gt;</li>
<li>Andrea Stirpe &lt;<a class="reference external" href="mailto:a.stirpe&#64;onestein.nl">a.stirpe&#64;onestein.nl</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id7">Maintainers</a></h2>
<h2><a class="toc-backref" href="#id13">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose

63
date_range/tests/test_date_range.py

@ -10,45 +10,55 @@ class DateRangeTest(TransactionCase):
def setUp(self):
super(DateRangeTest, self).setUp()
self.date_range = self.env['date.range']
self.type = self.env['date.range.type'].create(
{'name': 'Fiscal year',
'company_id': False,
'allow_overlap': False})
self.company = self.env['res.company'].create({
'name': 'Test company',
})
self.company_2 = self.env['res.company'].create({
'name': 'Test company 2',
'parent_id': self.company.id,
})
self.typeB = self.env['date.range.type'].create(
{'name': 'Fiscal year B',
'company_id': self.company.id,
'allow_overlap': False})
def test_default_company(self):
date_range = self.env['date.range']
dt = date_range.create({
dr = self.date_range.create({
'name': 'FS2016',
'date_start': '2015-01-01',
'date_end': '2016-12-31',
'type_id': self.type.id,
})
self.assertTrue(dt.company_id)
self.assertTrue(dr.company_id)
# you can specify company_id to False
dt = date_range.create({
dr = self.date_range.create({
'name': 'FS2016_NO_COMPANY',
'date_start': '2015-01-01',
'date_end': '2016-12-31',
'type_id': self.type.id,
'company_id': False
})
self.assertFalse(dt.company_id)
self.assertFalse(dr.company_id)
def test_empty_company(self):
date_range = self.env['date.range']
dt = date_range.create({
dr = self.date_range.create({
'name': 'FS2016',
'date_start': '2015-01-01',
'date_end': '2016-12-31',
'type_id': self.type.id,
'company_id': None,
})
self.assertEqual(dt.name, 'FS2016')
self.assertEqual(dr.name, 'FS2016')
def test_invalid(self):
date_range = self.env['date.range']
with self.assertRaises(ValidationError) as cm:
date_range.create({
self.date_range.create({
'name': 'FS2016',
'date_end': '2015-01-01',
'date_start': '2016-12-31',
@ -59,15 +69,14 @@ class DateRangeTest(TransactionCase):
'FS2016 is not a valid range (2016-12-31 > 2015-01-01)')
def test_overlap(self):
date_range = self.env['date.range']
date_range.create({
self.date_range.create({
'name': 'FS2015',
'date_start': '2015-01-01',
'date_end': '2015-12-31',
'type_id': self.type.id,
})
with self.assertRaises(ValidationError) as cm, self.env.cr.savepoint():
date_range.create({
self.date_range.create({
'name': 'FS2016',
'date_start': '2015-01-01',
'date_end': '2016-12-31',
@ -76,7 +85,7 @@ class DateRangeTest(TransactionCase):
self.assertEqual(cm.exception.name, 'FS2016 overlaps FS2015')
# check it's possible to overlap if it's allowed by the date range type
self.type.allow_overlap = True
dr = date_range.create({
dr = self.date_range.create({
'name': 'FS2016',
'date_start': '2015-01-01',
'date_end': '2016-12-31',
@ -85,8 +94,7 @@ class DateRangeTest(TransactionCase):
self.assertEquals(dr.name, 'FS2016')
def test_domain(self):
date_range = self.env['date.range']
dr = date_range.create({
dr = self.date_range.create({
'name': 'FS2015',
'date_start': '2015-01-01',
'date_end': '2015-12-31',
@ -98,3 +106,26 @@ class DateRangeTest(TransactionCase):
domain,
[('my_field', '>=', '2015-01-01'),
('my_field', '<=', '2015-12-31')])
def test_date_range_multicompany_1(self):
dr = self.date_range.new({
'name': 'FS2016',
'date_start': '2015-01-01',
'date_end': '2016-12-31',
'type_id': self.typeB.id,
'company_id': self.company.id,
})
dr._cache.update(dr._convert_to_cache(
{'company_id': self.company_2.id}, update=True))
dr._onchange_company_id()
self.assertFalse(dr.type_id)
def test_date_range_multicompany_2(self):
with self.assertRaises(ValidationError):
self.date_range.create({
'name': 'FS2016',
'date_start': '2015-01-01',
'date_end': '2016-12-31',
'type_id': self.typeB.id,
'company_id': self.company_2.id,
})

44
date_range/tests/test_date_range_generator.py

@ -3,6 +3,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)nses/agpl).
from odoo.tests.common import TransactionCase
from odoo.exceptions import ValidationError
from dateutil.rrule import MONTHLY
@ -10,14 +11,26 @@ class DateRangeGeneratorTest(TransactionCase):
def setUp(self):
super(DateRangeGeneratorTest, self).setUp()
self.generator = self.env['date.range.generator']
self.type = self.env['date.range.type'].create(
{'name': 'Fiscal year',
'company_id': False,
'allow_overlap': False})
self.company = self.env['res.company'].create({
'name': 'Test company',
})
self.company_2 = self.env['res.company'].create({
'name': 'Test company 2',
'parent_id': self.company.id,
})
self.typeB = self.env['date.range.type'].create(
{'name': 'Fiscal year B',
'company_id': self.company.id,
'allow_overlap': False})
def test_generate(self):
generator = self.env['date.range.generator']
generator = generator.create({
generator = self.generator.create({
'date_start': '1943-01-01',
'name_prefix': '1943-',
'type_id': self.type.id,
@ -32,3 +45,30 @@ class DateRangeGeneratorTest(TransactionCase):
self.assertEqual(range4.date_start, '1943-10-01')
self.assertEqual(range4.date_end, '1943-12-31')
self.assertEqual(range4.type_id, self.type)
def test_generator_multicompany_1(self):
generator = self.generator.new({
'date_start': '1943-01-01',
'name_prefix': '1943-',
'type_id': self.typeB.id,
'duration_count': 3,
'unit_of_time': MONTHLY,
'count': 4,
'company_id': self.company.id,
})
generator._cache.update(generator._convert_to_cache(
{'company_id': self.company_2.id}, update=True))
generator._onchange_company_id()
self.assertFalse(generator.type_id)
def test_generator_multicompany_2(self):
with self.assertRaises(ValidationError):
self.generator.create({
'date_start': '1943-01-01',
'name_prefix': '1943-',
'type_id': self.typeB.id,
'duration_count': 3,
'unit_of_time': MONTHLY,
'count': 4,
'company_id': self.company_2.id,
})

47
date_range/tests/test_date_range_type.py

@ -3,18 +3,61 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from odoo.tests.common import TransactionCase
from odoo.tools import mute_logger
from psycopg2 import IntegrityError
from odoo.exceptions import ValidationError
class DateRangeTypeTest(TransactionCase):
def setUp(self):
super(DateRangeTypeTest, self).setUp()
self.type = self.env['date.range.type']
self.company = self.env['res.company'].create({
'name': 'Test company',
})
self.company_2 = self.env['res.company'].create({
'name': 'Test company 2',
'parent_id': self.company.id,
})
def test_default_company(self):
drt = self.env['date.range.type'].create(
drt = self.type.create(
{'name': 'Fiscal year',
'allow_overlap': False})
self.assertTrue(drt.company_id)
# you can specify company_id to False
drt = self.env['date.range.type'].create(
drt = self.type.create(
{'name': 'Fiscal year',
'company_id': False,
'allow_overlap': False})
self.assertFalse(drt.company_id)
def test_unlink(self):
date_range = self.env['date.range']
drt = self.env['date.range.type'].create(
{'name': 'Fiscal year',
'allow_overlap': False})
date_range.create({
'name': 'FS2016',
'date_start': '2015-01-01',
'date_end': '2016-12-31',
'type_id': drt.id,
})
with self.assertRaises(IntegrityError), mute_logger('odoo.sql_db'):
drt.unlink()
def test_type_multicompany(self):
drt = self.type.create(
{'name': 'Fiscal year',
'company_id': False,
'allow_overlap': False})
self.env['date.range'].create({
'name': 'FS2016',
'date_start': '2015-01-01',
'date_end': '2016-12-31',
'type_id': drt.id,
'company_id': self.company.id,
})
with self.assertRaises(ValidationError):
drt.company_id = self.company_2

23
date_range/wizard/date_range_generator.py

@ -3,6 +3,8 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
from odoo.tools.translate import _
from odoo.exceptions import ValidationError
from dateutil.rrule import (rrule,
YEARLY,
MONTHLY,
@ -13,6 +15,7 @@ from dateutil.relativedelta import relativedelta
class DateRangeGenerator(models.TransientModel):
_name = 'date.range.generator'
_description = 'Date Range Generator'
@api.model
def _default_company(self):
@ -22,7 +25,8 @@ class DateRangeGenerator(models.TransientModel):
date_start = fields.Date(strint='Start date', required=True)
type_id = fields.Many2one(
comodel_name='date.range.type', string='Type', required=True,
ondelete='cascade')
domain="['|', ('company_id', '=', company_id), "
"('company_id', '=', False)]", ondelete='cascade')
company_id = fields.Many2one(
comodel_name='res.company', string='Company',
default=_default_company)
@ -59,6 +63,23 @@ class DateRangeGenerator(models.TransientModel):
'company_id': self.company_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()

Loading…
Cancel
Save