diff --git a/sequence_reset_period/README.rst b/sequence_reset_period/README.rst new file mode 100644 index 0000000..ef1ba94 --- /dev/null +++ b/sequence_reset_period/README.rst @@ -0,0 +1,38 @@ +.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :alt: License: LGPL-3 + +===================== +Sequence Reset period +===================== + +This module was written to reset the sequences on the specified times, because +by default they are reset yearly. + +Usage +===== + +* Access sequences and configurate the model to use. +* When sequence is computed, date_range will follow the specified rules + +Credits +======= + +Contributors +------------ + +* Enric Tobella + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/sequence_reset_period/__init__.py b/sequence_reset_period/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/sequence_reset_period/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/sequence_reset_period/__manifest__.py b/sequence_reset_period/__manifest__.py new file mode 100644 index 0000000..d8402ce --- /dev/null +++ b/sequence_reset_period/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright (C) 2017 Creu Blanca +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +{ + "name": "Reset Sequences on selected period ranges", + "version": "11.0.1.0.0", + "category": "Reporting", + "website": "https://github.com/OCA/server-tools", + "author": "Creu Blanca, " + "Odoo Community Association (OCA)", + "license": "LGPL-3", + "installable": True, + "application": False, + "summary": "Adds a check digit on sequences", + "depends": [ + "base", + ], + "data": [ + "views/sequence_views.xml", + ], +} diff --git a/sequence_reset_period/models/__init__.py b/sequence_reset_period/models/__init__.py new file mode 100644 index 0000000..5b01577 --- /dev/null +++ b/sequence_reset_period/models/__init__.py @@ -0,0 +1 @@ +from . import ir_sequence diff --git a/sequence_reset_period/models/ir_sequence.py b/sequence_reset_period/models/ir_sequence.py new file mode 100644 index 0000000..2e2aca7 --- /dev/null +++ b/sequence_reset_period/models/ir_sequence.py @@ -0,0 +1,58 @@ +# Copyright (C) 2017 Creu Blanca +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import fields, models +from datetime import datetime, timedelta, date as datetime_date +from dateutil.relativedelta import relativedelta + + +class IrSequence(models.Model): + _inherit = "ir.sequence" + + range_reset = fields.Selection([ + ('daily', 'Daily'), + ('weekly', 'Weekly'), + ('monthly', 'Monthly'), + ('yearly', 'Yearly') + ]) + + def _compute_date_from_to(self, date): + self.ensure_one() + date_from = date_to = fields.Date.from_string(date) + if self.range_reset == 'weekly': + date_from = date_from - timedelta(days=date_from.weekday()) + date_to = date_from + timedelta(days=6) + elif self.range_reset == 'monthly': + date_from = datetime_date(date_from.year, date_from.month, 1) + date_to = date_from + relativedelta(months=1) + date_to += relativedelta(days=-1) + elif self.range_reset == 'yearly': + date_from = datetime_date(date_from.year, 1, 1) + date_to = datetime_date(date_from.year, 12, 31) + return date_from.strftime('%Y-%m-%d'), date_to.strftime('%Y-%m-%d') + + def _create_date_range_seq(self, date): + self.ensure_one() + if not self.range_reset: + return super()._create_date_range_seq(date) + date_from, date_to = self._compute_date_from_to(date) + date_range = self.env['ir.sequence.date_range'].search( + [('sequence_id', '=', self.id), ('date_from', '>=', date), + ('date_from', '<=', date_to)], order='date_from desc', limit=1) + if date_range: + date_to = datetime.strptime(date_range.date_from, + '%Y-%m-%d') + timedelta(days=-1) + date_to = date_to.strftime('%Y-%m-%d') + date_range = self.env['ir.sequence.date_range'].search( + [('sequence_id', '=', self.id), ('date_to', '>=', date_from), + ('date_to', '<=', date)], order='date_to desc', limit=1) + if date_range: + date_from = datetime.strptime(date_range.date_to, + '%Y-%m-%d') + timedelta(days=1) + date_from = date_from.strftime('%Y-%m-%d') + seq_date_range = self.env['ir.sequence.date_range'].sudo().create({ + 'date_from': date_from, + 'date_to': date_to, + 'sequence_id': self.id, + }) + return seq_date_range diff --git a/sequence_reset_period/static/description/icon.png b/sequence_reset_period/static/description/icon.png new file mode 100644 index 0000000..3a0328b Binary files /dev/null and b/sequence_reset_period/static/description/icon.png differ diff --git a/sequence_reset_period/tests/__init__.py b/sequence_reset_period/tests/__init__.py new file mode 100644 index 0000000..6021908 --- /dev/null +++ b/sequence_reset_period/tests/__init__.py @@ -0,0 +1 @@ +from . import test_period diff --git a/sequence_reset_period/tests/test_period.py b/sequence_reset_period/tests/test_period.py new file mode 100644 index 0000000..07cbce6 --- /dev/null +++ b/sequence_reset_period/tests/test_period.py @@ -0,0 +1,71 @@ +# Copyright 2017 Creu Blanca +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + + +from odoo.tests import common +from datetime import datetime + + +class TestSequence(common.TransactionCase): + def setUp(self): + super().setUp() + self.date = datetime(2018, 3, 14).strftime('%Y-%m-%d') + + def get_sequence(self, method): + return self.env['ir.sequence'].create({ + 'name': 'Test sequence', + 'implementation': 'standard', + 'use_date_range': True, + 'range_reset': method, + 'padding': '5' + }) + + def test_none(self): + sequence = self.get_sequence(False) + self.assertFalse(sequence.date_range_ids) + self.assertEqual('00001', sequence.with_context( + ir_sequence_date=self.date).next_by_id()) + range = sequence.date_range_ids + self.assertTrue(range) + self.assertEqual('2018-01-01', range.date_from) + self.assertEqual('2018-12-31', range.date_to) + + def test_daily(self): + sequence = self.get_sequence('daily') + self.assertFalse(sequence.date_range_ids) + self.assertEqual('00001', sequence.with_context( + ir_sequence_date=self.date).next_by_id()) + range = sequence.date_range_ids + self.assertTrue(range) + self.assertEqual(self.date, range.date_from) + self.assertEqual(self.date, range.date_to) + + def test_weekly(self): + sequence = self.get_sequence('weekly') + self.assertFalse(sequence.date_range_ids) + self.assertEqual('00001', sequence.with_context( + ir_sequence_date=self.date).next_by_id()) + range = sequence.date_range_ids + self.assertTrue(range) + self.assertEqual('2018-03-12', range.date_from) + self.assertEqual('2018-03-18', range.date_to) + + def test_monthly(self): + sequence = self.get_sequence('monthly') + self.assertFalse(sequence.date_range_ids) + self.assertEqual('00001', sequence.with_context( + ir_sequence_date=self.date).next_by_id()) + range = sequence.date_range_ids + self.assertTrue(range) + self.assertEqual('2018-03-01', range.date_from) + self.assertEqual('2018-03-31', range.date_to) + + def test_yearly(self): + sequence = self.get_sequence('yearly') + self.assertFalse(sequence.date_range_ids) + self.assertEqual('00001', sequence.with_context( + ir_sequence_date=self.date).next_by_id()) + range = sequence.date_range_ids + self.assertTrue(range) + self.assertEqual('2018-01-01', range.date_from) + self.assertEqual('2018-12-31', range.date_to) diff --git a/sequence_reset_period/views/sequence_views.xml b/sequence_reset_period/views/sequence_views.xml new file mode 100644 index 0000000..e631357 --- /dev/null +++ b/sequence_reset_period/views/sequence_views.xml @@ -0,0 +1,12 @@ + + + + ir.sequence + + + + + + + +