mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-18 22:32:01 +02:00
Initial commit: OCA Technical packages (595 packages)
This commit is contained in:
commit
2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions
|
|
@ -0,0 +1,4 @@
|
|||
from . import test_date_range_type
|
||||
from . import test_date_range
|
||||
from . import test_date_range_generator
|
||||
from . import test_date_range_search_mixin
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
from odoo import fields, models
|
||||
|
||||
|
||||
class TestDateRangeSearchMixin(models.Model):
|
||||
_name = "test.date.range.search.mixin"
|
||||
_inherit = ["date.range.search.mixin"]
|
||||
_date_range_search_field = "test_date"
|
||||
|
||||
name = fields.Char()
|
||||
test_date = fields.Date()
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>)
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)
|
||||
|
||||
import datetime
|
||||
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
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):
|
||||
dr = self.date_range.create(
|
||||
{
|
||||
"name": "FS2016",
|
||||
"date_start": "2015-01-01",
|
||||
"date_end": "2016-12-31",
|
||||
"type_id": self.type.id,
|
||||
}
|
||||
)
|
||||
self.assertTrue(dr.company_id)
|
||||
# you can specify company_id to False
|
||||
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(dr.company_id)
|
||||
|
||||
def test_empty_company(self):
|
||||
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(dr.name, "FS2016")
|
||||
|
||||
def test_invalid(self):
|
||||
with self.assertRaises(ValidationError) as cm:
|
||||
self.date_range.create(
|
||||
{
|
||||
"name": "FS2016",
|
||||
"date_end": "2015-01-01",
|
||||
"date_start": "2016-12-31",
|
||||
"type_id": self.type.id,
|
||||
}
|
||||
)
|
||||
message = str(cm.exception.args[0])
|
||||
self.assertEqual(
|
||||
message, "FS2016 is not a valid range (2016-12-31 > 2015-01-01)"
|
||||
)
|
||||
|
||||
def test_overlap(self):
|
||||
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():
|
||||
self.date_range.create(
|
||||
{
|
||||
"name": "FS2016",
|
||||
"date_start": "2015-01-01",
|
||||
"date_end": "2016-12-31",
|
||||
"type_id": self.type.id,
|
||||
}
|
||||
)
|
||||
message = str(cm.exception.args[0])
|
||||
self.assertEqual(message, "FS2016 overlaps FS2015")
|
||||
# check it's possible to overlap if it's allowed by the date range type
|
||||
self.type.allow_overlap = True
|
||||
dr = self.date_range.create(
|
||||
{
|
||||
"name": "FS2016",
|
||||
"date_start": "2015-01-01",
|
||||
"date_end": "2016-12-31",
|
||||
"type_id": self.type.id,
|
||||
}
|
||||
)
|
||||
self.assertEqual(dr.name, "FS2016")
|
||||
|
||||
def test_domain(self):
|
||||
dr = self.date_range.create(
|
||||
{
|
||||
"name": "FS2015",
|
||||
"date_start": "2015-01-01",
|
||||
"date_end": "2015-12-31",
|
||||
"type_id": self.type.id,
|
||||
}
|
||||
)
|
||||
domain = dr.get_domain("my_field")
|
||||
# By default the domain include limits
|
||||
self.assertEqual(
|
||||
domain,
|
||||
[
|
||||
("my_field", ">=", datetime.date(2015, 1, 1)),
|
||||
("my_field", "<=", datetime.date(2015, 12, 31)),
|
||||
],
|
||||
)
|
||||
|
||||
def test_date_range_multicompany_1(self):
|
||||
with self.assertRaises(UserError):
|
||||
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,
|
||||
}
|
||||
)
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>)
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
import datetime
|
||||
|
||||
from dateutil.rrule import MONTHLY
|
||||
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tests.common import Form, TransactionCase
|
||||
|
||||
|
||||
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.generator.create(
|
||||
{
|
||||
"date_start": "1943-01-01",
|
||||
"name_prefix": "1943-",
|
||||
"type_id": self.type.id,
|
||||
"duration_count": 3,
|
||||
"unit_of_time": str(MONTHLY),
|
||||
"count": 4,
|
||||
}
|
||||
)
|
||||
generator.action_apply()
|
||||
ranges = self.env["date.range"].search([("type_id", "=", self.type.id)])
|
||||
self.assertEqual(len(ranges), 4)
|
||||
range4 = ranges[3]
|
||||
self.assertEqual(range4.date_start, datetime.date(1943, 10, 1))
|
||||
self.assertEqual(range4.date_end, datetime.date(1943, 12, 31))
|
||||
self.assertEqual(range4.type_id, self.type)
|
||||
|
||||
def test_generator_multicompany_1(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": str(MONTHLY),
|
||||
"count": 4,
|
||||
"company_id": self.company_2.id,
|
||||
}
|
||||
)
|
||||
|
||||
def test_generator_form(self):
|
||||
"""Test validation and onchange functionality"""
|
||||
form = Form(self.env["date.range.generator"])
|
||||
form.type_id = self.type
|
||||
form.unit_of_time = str(MONTHLY)
|
||||
form.duration_count = 10
|
||||
form.date_end = "2021-01-01"
|
||||
# Setting count clears date_end
|
||||
form.count = 10
|
||||
self.assertFalse(form.date_end)
|
||||
# Setting date_end clears count
|
||||
form.date_end = "2021-01-01"
|
||||
self.assertFalse(form.count)
|
||||
form.count = 10
|
||||
form.name_prefix = "PREFIX"
|
||||
# Cannot generate ranges with an invalid name_expr
|
||||
with self.assertRaisesRegex(ValidationError, "Invalid name expression"):
|
||||
form.name_expr = "'not valid"
|
||||
# Setting name_expr clears name_prefix
|
||||
form.name_expr = "'PREFIX%s' % index"
|
||||
self.assertFalse(form.name_prefix)
|
||||
self.assertEqual(form.range_name_preview, "PREFIX01")
|
||||
wizard = form.save()
|
||||
|
||||
# Cannot generate ranges without count and without date_end
|
||||
wizard.date_end = False
|
||||
wizard.count = False
|
||||
with self.assertRaisesRegex(ValidationError, "end date.*number of ranges"):
|
||||
wizard.action_apply()
|
||||
|
||||
wizard.count = 10
|
||||
# Cannot generate ranges without a prefix and without an expression
|
||||
wizard.name_expr = False
|
||||
wizard.name_prefix = False
|
||||
with self.assertRaisesRegex(ValidationError, "prefix.*expression"):
|
||||
wizard.action_apply()
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>)
|
||||
# Copyright 2021 Opener B.V. <stefan@opener.amsterdam>
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
from dateutil.rrule import MONTHLY
|
||||
from odoo_test_helper import FakeModelLoader
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestDateRangeearchMixin(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
# Load a test model using odoo_test_helper
|
||||
cls.loader = FakeModelLoader(cls.env, cls.__module__)
|
||||
cls.loader.backup_registry()
|
||||
from .models import TestDateRangeSearchMixin
|
||||
|
||||
cls.loader.update_registry((TestDateRangeSearchMixin,))
|
||||
|
||||
cls.env.user.lang = "en_US"
|
||||
rtype = cls.env["date.range.type"].create(
|
||||
{"name": __name__, "company_id": False, "allow_overlap": False}
|
||||
)
|
||||
cls.env["date.range.generator"].create(
|
||||
{
|
||||
"date_start": "1943-01-01",
|
||||
"name_prefix": "1943-",
|
||||
"type_id": rtype.id,
|
||||
"duration_count": 3,
|
||||
"unit_of_time": str(MONTHLY),
|
||||
"count": 4,
|
||||
}
|
||||
).action_apply()
|
||||
cls.ranges = cls.env["date.range"].search([("type_id", "=", rtype.id)])
|
||||
cls.model = cls.env[TestDateRangeSearchMixin._name]
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.loader.restore_registry()
|
||||
return super().tearDownClass()
|
||||
|
||||
def test_01_search_view(self):
|
||||
"""The search field is injected in the model's search view"""
|
||||
self.assertIn(
|
||||
'<separator/><field name="date_range_search_id" string="Period"/>',
|
||||
self.model.get_view(view_type="search")["arch"],
|
||||
)
|
||||
self.assertNotIn(
|
||||
'<separator/><field name="date_range_search_id" string="Period"/>',
|
||||
self.model.get_view(view_type="form")["arch"],
|
||||
)
|
||||
# Having a view with a group element in it
|
||||
view = self.env["ir.ui.view"].create(
|
||||
{
|
||||
"name": __name__,
|
||||
"model": self.model._name,
|
||||
"arch": """
|
||||
<search>
|
||||
<field name="name"/>
|
||||
<group string="Group by">
|
||||
<filter name="name" context="{'group_by': 'name'}"/>
|
||||
</group>
|
||||
</search>
|
||||
""",
|
||||
}
|
||||
)
|
||||
self.assertIn(
|
||||
'<separator/><field name="date_range_search_id" string="Period"/>',
|
||||
self.model.get_view(view_type="search")["arch"],
|
||||
)
|
||||
# Having a view in which the field is added explicitely
|
||||
view.arch = """
|
||||
<search>
|
||||
<field name="name"/>
|
||||
<field name="date_range_search_id"/>
|
||||
<group string="Group by">
|
||||
<filter name="name" context="{'group_by': 'name'}"/>
|
||||
</group>
|
||||
</search>
|
||||
"""
|
||||
self.assertNotIn(
|
||||
'<separator/><field name="date_range_search_id" string="Period"/>',
|
||||
self.model.get_view(view_type="search")["arch"],
|
||||
)
|
||||
|
||||
def test_02_search_result(self):
|
||||
"""Using the search field leads to expected results"""
|
||||
record = self.model.create({"test_date": "1943-04-05"})
|
||||
self.assertFalse(record.date_range_search_id)
|
||||
self.assertIn(
|
||||
record,
|
||||
self.model.search([("date_range_search_id", "=", self.ranges[1].id)]),
|
||||
)
|
||||
self.assertNotIn(
|
||||
record,
|
||||
self.model.search([("date_range_search_id", "!=", self.ranges[1].id)]),
|
||||
)
|
||||
self.assertIn(
|
||||
record,
|
||||
self.model.search([("date_range_search_id", "!=", self.ranges[0].id)]),
|
||||
)
|
||||
self.assertNotIn(
|
||||
record,
|
||||
self.model.search([("date_range_search_id", "=", self.ranges[0].id)]),
|
||||
)
|
||||
self.assertIn(
|
||||
record, self.model.search([("date_range_search_id", "in", self.ranges.ids)])
|
||||
)
|
||||
self.assertNotIn(
|
||||
record,
|
||||
self.model.search([("date_range_search_id", "not in", self.ranges.ids)]),
|
||||
)
|
||||
self.assertIn(
|
||||
record,
|
||||
self.model.search([("date_range_search_id", "not in", self.ranges[3].ids)]),
|
||||
)
|
||||
self.assertNotIn(
|
||||
record,
|
||||
self.model.search([("date_range_search_id", "in", self.ranges[3].ids)]),
|
||||
)
|
||||
self.assertIn(
|
||||
record, self.model.search([("date_range_search_id", "ilike", "1943")])
|
||||
)
|
||||
self.assertNotIn(
|
||||
record, self.model.search([("date_range_search_id", "not ilike", "1943")])
|
||||
)
|
||||
self.assertIn(
|
||||
record, self.model.search([("date_range_search_id", "not ilike", "2021")])
|
||||
)
|
||||
self.assertNotIn(
|
||||
record, self.model.search([("date_range_search_id", "ilike", "2021")])
|
||||
)
|
||||
self.assertIn(record, self.model.search([("date_range_search_id", "=", True)]))
|
||||
self.assertNotIn(
|
||||
record, self.model.search([("date_range_search_id", "=", False)])
|
||||
)
|
||||
self.assertIn(
|
||||
record, self.model.search([("date_range_search_id", "!=", False)])
|
||||
)
|
||||
self.assertNotIn(
|
||||
record, self.model.search([("date_range_search_id", "!=", True)])
|
||||
)
|
||||
|
||||
def test_03_read(self):
|
||||
"""Read returns a falsy value"""
|
||||
record = self.model.create({"test_date": "1943-04-05"})
|
||||
self.assertFalse(record.date_range_search_id)
|
||||
|
||||
def test_04_load_views(self):
|
||||
"""Technical field label is replaced in `load_views`"""
|
||||
field = self.model.get_views([(None, "form")])["models"][self.model._name][
|
||||
"date_range_search_id"
|
||||
]
|
||||
self.assertNotIn("technical", field["string"])
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>)
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from dateutil.rrule import MONTHLY, YEARLY
|
||||
from psycopg2 import IntegrityError
|
||||
|
||||
from odoo import fields
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests.common import TransactionCase
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
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.type.create({"name": "Fiscal year", "allow_overlap": False})
|
||||
self.assertTrue(drt.company_id)
|
||||
# you can specify company_id to False
|
||||
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}
|
||||
)
|
||||
dr = 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,
|
||||
}
|
||||
)
|
||||
drt.company_id = self.company.id
|
||||
with self.assertRaises(UserError):
|
||||
dr.company_id = self.company_2
|
||||
|
||||
def test_autogeneration(self):
|
||||
"""Ranges are autogenerated for types configured for that"""
|
||||
today = fields.Date.context_today(self.env.user)
|
||||
year_start = today.replace(day=1, month=1)
|
||||
dr_type = self.env["date.range.type"].create(
|
||||
{
|
||||
"name": __name__,
|
||||
"name_expr": "'>%s<' % date_start.strftime('%d%m%Y')",
|
||||
"unit_of_time": str(MONTHLY),
|
||||
"duration_count": 1,
|
||||
"autogeneration_count": 1,
|
||||
"autogeneration_unit": str(YEARLY),
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
dr_type.range_name_preview, ">%s<" % year_start.strftime("%d%m%Y")
|
||||
)
|
||||
|
||||
self.env["date.range.type"].autogenerate_ranges()
|
||||
ranges = self.env["date.range"].search(
|
||||
[("type_id", "=", dr_type.id)], order="date_start asc"
|
||||
)
|
||||
# For new types, ranges are autogenerated from the start of the year
|
||||
year_start = today.replace(day=1, month=1)
|
||||
self.assertEqual(ranges[0].date_start, year_start)
|
||||
# Ranges are autogenerated upto the range in which the computed end
|
||||
# date falls, c.q. the first of the month a year from now.
|
||||
next_year_month_start = today.replace(day=1) + relativedelta(years=1)
|
||||
self.assertEqual(ranges[-1].date_start, next_year_month_start)
|
||||
self.assertEqual(
|
||||
ranges[-1].name, ">%s<" % next_year_month_start.strftime("%d%m%Y")
|
||||
)
|
||||
|
||||
# No new ranges get generated anymore this month
|
||||
self.env["date.range.type"].autogenerate_ranges()
|
||||
self.assertEqual(
|
||||
len(ranges),
|
||||
len(
|
||||
self.env["date.range"].search(
|
||||
[("type_id", "=", dr_type.id)], order="date_start asc"
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
def test_autogeneration_with_start_date(self):
|
||||
today = fields.Date.context_today(self.env.user)
|
||||
start_date = today.replace(year=2019, day=6, month=1)
|
||||
dr_type = self.env["date.range.type"].create(
|
||||
{
|
||||
"name": __name__,
|
||||
"name_expr": "'>%s<' % date_start.strftime('%d%m%Y')",
|
||||
"unit_of_time": str(MONTHLY),
|
||||
"duration_count": 1,
|
||||
"autogeneration_date_start": start_date,
|
||||
"autogeneration_count": 1,
|
||||
"autogeneration_unit": str(YEARLY),
|
||||
}
|
||||
)
|
||||
self.assertFalse(dr_type.date_ranges_exist)
|
||||
self.env["date.range.type"].autogenerate_ranges()
|
||||
self.assertTrue(dr_type.date_ranges_exist)
|
||||
ranges = self.env["date.range"].search(
|
||||
[("type_id", "=", dr_type.id)], order="date_start asc"
|
||||
)
|
||||
self.assertEqual(ranges[0].date_start, start_date)
|
||||
# No new ranges get generated anymore this month
|
||||
self.env["date.range.type"].autogenerate_ranges()
|
||||
self.assertEqual(
|
||||
len(ranges),
|
||||
len(
|
||||
self.env["date.range"].search(
|
||||
[("type_id", "=", dr_type.id)], order="date_start asc"
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
def test_autogeneration_invalid_config(self):
|
||||
"""The cron method does not raise when an invalid config exists"""
|
||||
today = fields.Date.context_today(self.env.user)
|
||||
start_date = today.replace(year=2019, day=6, month=1)
|
||||
dr_type = self.env["date.range.type"].create(
|
||||
{
|
||||
"name": __name__,
|
||||
"name_expr": "index",
|
||||
"unit_of_time": str(MONTHLY),
|
||||
"duration_count": 1,
|
||||
"autogeneration_date_start": start_date,
|
||||
"autogeneration_count": 1,
|
||||
"autogeneration_unit": str(YEARLY),
|
||||
}
|
||||
)
|
||||
# Inject invalid value
|
||||
self.env.cr.execute("UPDATE date_range_type SET name_expr = 'invalid'")
|
||||
dr_type.invalidate_model()
|
||||
with mute_logger("odoo.addons.date_range.models.date_range_type"):
|
||||
self.env["date.range.type"].autogenerate_ranges()
|
||||
self.assertFalse(dr_type.date_ranges_exist)
|
||||
Loading…
Add table
Add a link
Reference in a new issue