-
-
Notifications
You must be signed in to change notification settings - Fork 799
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by rafaelbn
- Loading branch information
Showing
20 changed files
with
426 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
**This file is going to be generated by oca-gen-addon-readme.** | ||
|
||
*Manual changes will be overwritten.* | ||
|
||
Please provide content in the ``readme`` directory: | ||
|
||
* **DESCRIPTION.rst** (required) | ||
* INSTALL.rst (optional) | ||
* CONFIGURE.rst (optional) | ||
* **USAGE.rst** (optional, highly recommended) | ||
* DEVELOP.rst (optional) | ||
* ROADMAP.rst (optional) | ||
* HISTORY.rst (optional, recommended) | ||
* **CONTRIBUTORS.rst** (optional, highly recommended) | ||
* CREDITS.rst (optional) | ||
|
||
Content of this README will also be drawn from the addon manifest, | ||
from keys such as name, authors, maintainers, development_status, | ||
and license. | ||
|
||
A good, one sentence summary in the manifest is also highly recommended. | ||
|
||
|
||
Automatic changelog generation | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
`HISTORY.rst` can be auto generated using `towncrier <https://pypi.org/project/towncrier>`_. | ||
|
||
Just put towncrier compatible changelog fragments into `readme/newsfragments` | ||
and the changelog file will be automatically generated and updated when a new fragment is added. | ||
|
||
Please refer to `towncrier` documentation to know more. | ||
|
||
NOTE: the changelog will be automatically generated when using `/ocabot merge $option`. | ||
If you need to run it manually, refer to `OCA/maintainer-tools README <https://github.com/OCA/maintainer-tools>`_. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Copyright 2023 Moduon Team S.L. | ||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) | ||
|
||
{ | ||
"name": "Project Sequence", | ||
"summary": "Add a sequence field to projects, filled automatically", | ||
"version": "14.0.0.1.0", | ||
"development_status": "Alpha", | ||
"category": "Services/Project", | ||
"website": "https://github.com/OCA/project", | ||
"author": "Moduon, Odoo Community Association (OCA)", | ||
"maintainers": ["yajo", "anddago78"], | ||
"license": "LGPL-3", | ||
"application": False, | ||
"installable": True, | ||
"depends": ["project"], | ||
"data": [ | ||
"data/ir_sequence.xml", | ||
"views/project_project.xml", | ||
], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<!-- Copyright 2023 Moduon Team S.L. | ||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) --> | ||
<data noupdate="1"> | ||
<record id="seq_project_sequence" model="ir.sequence"> | ||
<field name="name">Project sequence</field> | ||
<field name="code">project.sequence</field> | ||
<field name="prefix">%(range_y)s-</field> | ||
<field name="use_date_range">True</field> | ||
<field name="padding">5</field> | ||
<field name="company_id" eval="False" /> | ||
</record> | ||
</data> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# Translation of Odoo Server. | ||
# This file contains the translation of the following modules: | ||
# * project_sequence | ||
# | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: Odoo Server 14.0+e\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"POT-Creation-Date: 2023-04-10 10:29+0000\n" | ||
"PO-Revision-Date: 2023-04-19 11:22+0200\n" | ||
"Last-Translator: Andrea Cattalani <[email protected]>\n" | ||
"Language-Team: \n" | ||
"Language: es_ES\n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: 8bit\n" | ||
"Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||
"X-Generator: Poedit 3.1.1\n" | ||
|
||
#. module: project_sequence | ||
#: model:ir.model.fields,field_description:project_sequence.field_project_project__code | ||
msgid "Code" | ||
msgstr "Código" | ||
|
||
#. module: project_sequence | ||
#: model:ir.model.fields,field_description:project_sequence.field_project_project__display_name | ||
msgid "Display Name" | ||
msgstr "Nombre" | ||
|
||
#. module: project_sequence | ||
#: model:ir.model.fields,field_description:project_sequence.field_project_project__id | ||
msgid "ID" | ||
msgstr "ID" | ||
|
||
#. module: project_sequence | ||
#: model:ir.model.fields,field_description:project_sequence.field_project_project____last_update | ||
msgid "Last Modified on" | ||
msgstr "Última modificación el" | ||
|
||
#. module: project_sequence | ||
#: model:ir.model.fields,field_description:project_sequence.field_project_project__name | ||
msgid "Name" | ||
msgstr "Nombre" | ||
|
||
#. module: project_sequence | ||
#: model:ir.model,name:project_sequence.model_project_project | ||
msgid "Project" | ||
msgstr "Proyecto" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import project_project |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# Copyright 2023 Moduon Team S.L. | ||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) | ||
|
||
|
||
from odoo import api, fields, models | ||
|
||
|
||
class ProjectProject(models.Model): | ||
_inherit = "project.project" | ||
_sql_constraints = [ | ||
# Ensure compatibility with other modules that always expect a value in name | ||
("name_required", "CHECK(name IS NOT NULL)", "Project name is required"), | ||
( | ||
"sequence_code_unique", | ||
"UNIQUE(sequence_code)", | ||
"Sequence code must be unique", | ||
), | ||
] | ||
|
||
sequence_code = fields.Char( | ||
copy=False, | ||
readonly=True, | ||
) | ||
name = fields.Char( | ||
# We actually require it with the SQL constraint, but it is disabled | ||
# here to let users create/write projects without name, and let this module | ||
# add a default name if needed | ||
required=False, | ||
) | ||
|
||
def _sync_analytic_account_name(self): | ||
"""Set analytic account name equal to project's display name.""" | ||
for rec in self: | ||
if not rec.analytic_account_id: | ||
continue | ||
rec.analytic_account_id.name = rec.display_name | ||
|
||
def name_get(self): | ||
"""Prefix name with sequence code if they are different.""" | ||
old_result = super().name_get() | ||
result = [] | ||
for id_, name in old_result: | ||
project = self.browse(id_) | ||
if project.sequence_code and project.sequence_code != name: | ||
name = "{} - {}".format(project.sequence_code, name) | ||
result.append((id_, name)) | ||
return result | ||
|
||
@api.model | ||
def name_search(self, name="", args=None, operator="ilike", limit=100): | ||
"""Allow searching by sequence code by default.""" | ||
# Do not add any domain when user just clicked on search widget | ||
if not (name == "" and operator == "ilike"): | ||
# The dangling | is needed to combine with the domain added by super() | ||
args = (args or []) + ["|", ("sequence_code", operator, name)] | ||
return super().name_search(name, args, operator, limit) | ||
|
||
@api.model_create_multi | ||
def create(self, vals_list): | ||
"""Apply sequence code and a default name if not set.""" | ||
# It is important to set sequence_code before calling super() because | ||
# other modules such as hr_timesheet expect the name to always have a value | ||
for vals in vals_list: | ||
if "sequence_code" not in vals: | ||
vals["sequence_code"] = self.env["ir.sequence"].next_by_code( | ||
"project.sequence" | ||
) | ||
if not vals.get("name"): | ||
vals["name"] = vals["sequence_code"] | ||
res = super().create(vals_list) | ||
# The analytic account is created with just the project name, but | ||
# it is more useful to let it contain the project sequence too | ||
res._sync_analytic_account_name() | ||
return res | ||
|
||
def write(self, vals): | ||
"""Sync name and analytic account name when name is changed.""" | ||
# If name isn't changing, nothing special to do | ||
if "name" not in vals and "sequence_name" not in vals: | ||
return super().write(vals) | ||
# When changing name, we need to update the analytic account name too | ||
for one in self: | ||
sequence_code = vals.get("sequence_code", one.sequence_code) | ||
name = vals.get("name") or sequence_code | ||
super().write(dict(vals, name=name)) | ||
self._sync_analytic_account_name() | ||
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
* Andrea Cattalani (`Moduon <https://www.moduon.team/>`__) | ||
* Jairo Llopis (`Moduon <https://www.moduon.team/>`__) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
.. This file is optional and contains additional credits, other than | ||
authors, contributors, and maintainers. | ||
The development of this module has been financially supported by: | ||
|
||
* Moduon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.. This file must be max 2-3 paragraphs, and is required. | ||
It should explain *why* this module exists. | ||
Add a sequence field to projects, filled automatically and add a code sequence filter in tree view project. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
.. This file must be present. It contains the usage instructions | ||
for end-users. As all other rst files included in the README, | ||
it MUST NOT contain reStructuredText sections | ||
only body text (paragraphs, lists, tables, etc). Should you need | ||
a more elaborate structure to explain the addon, please create a | ||
Sphinx documentation (which may include this file as a "quick start" | ||
section). | ||
To use this module, you need to: | ||
|
||
#. Go to the project icon. | ||
#. Click the button "create" to create a new project | ||
#. Fill in the field Project name and click the "create" button | ||
#. Now in the Kanban view see the project name when you are created | ||
#. Repeat this operation creating another project without the name. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import test_project_sequence |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Copyright 2023 Moduon Team S.L. | ||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) | ||
from freezegun import freeze_time | ||
from psycopg2 import IntegrityError | ||
|
||
from odoo.tests.common import Form, SavepointCase, new_test_user, users | ||
from odoo.tools import mute_logger | ||
|
||
|
||
@freeze_time("2023-01-01 12:00:00") | ||
class TestProjectSequence(SavepointCase): | ||
@classmethod | ||
def setUpClass(cls): | ||
super().setUpClass() | ||
new_test_user( | ||
cls.env, | ||
"manager", | ||
"project.group_project_manager,analytic.group_analytic_accounting", | ||
) | ||
cls.pjr_seq = cls.env.ref("project_sequence.seq_project_sequence") | ||
cls.pjr_seq.date_range_ids.unlink() | ||
cls.analytic_account = cls.env["account.analytic.account"].create( | ||
{"name": "aaa"} | ||
) | ||
|
||
def setUp(self): | ||
super().setUp() | ||
self.pjr_seq._get_current_sequence().number_next = 11 | ||
|
||
@users("manager") | ||
def test_sequence_after_creation(self): | ||
"""Sequence is applied only after project creation.""" | ||
prj_f = Form(self.env["project.project"]) | ||
self.assertFalse(prj_f.name) | ||
self.assertFalse(prj_f.sequence_code) | ||
proj = prj_f.save() | ||
self.assertTrue(proj.sequence_code) | ||
self.assertEqual(proj.name, proj.sequence_code) | ||
self.assertEqual(proj.sequence_code, "23-00011") | ||
self.assertEqual(proj.display_name, "23-00011") | ||
|
||
def test_analytic_account_after_creation_no_name(self): | ||
"""Project's analytic account is named like project's default name.""" | ||
proj = self.env["project.project"].create( | ||
{"analytic_account_id": self.analytic_account.id} | ||
) | ||
self.assertEqual(proj.sequence_code, "23-00011") | ||
self.assertEqual(proj.name, "23-00011") | ||
self.assertEqual(proj.display_name, "23-00011") | ||
self.assertEqual(proj.analytic_account_id.name, "23-00011") | ||
|
||
def test_analytic_account_after_creation_named(self): | ||
"""Project's analytic account is named like project's display name.""" | ||
proj = self.env["project.project"].create( | ||
{"name": "whatever", "analytic_account_id": self.analytic_account.id} | ||
) | ||
self.assertEqual(proj.sequence_code, "23-00011") | ||
self.assertEqual(proj.name, "whatever") | ||
self.assertEqual(proj.display_name, "23-00011 - whatever") | ||
self.assertEqual(proj.analytic_account_id.name, "23-00011 - whatever") | ||
|
||
@users("manager") | ||
def test_sequence_copied_to_name_if_emptied(self): | ||
"""Sequence is copied to project name if user removes it.""" | ||
proj = self.env["project.project"].create( | ||
{"name": "whatever", "analytic_account_id": self.analytic_account.id} | ||
) | ||
self.assertEqual(proj.name, "whatever") | ||
self.assertEqual(proj.sequence_code, "23-00011") | ||
self.assertEqual(proj.display_name, "23-00011 - whatever") | ||
self.assertEqual(proj.analytic_account_id.name, "23-00011 - whatever") | ||
with Form(proj) as prj_f: | ||
prj_f.name = False | ||
self.assertEqual(proj.name, "23-00011") | ||
self.assertEqual(proj.sequence_code, "23-00011") | ||
self.assertEqual(proj.display_name, "23-00011") | ||
self.assertEqual(proj.analytic_account_id.name, "23-00011") | ||
|
||
@users("manager") | ||
def test_sequence_not_copied_to_another_project(self): | ||
"""Sequence is not duplicated to another project.""" | ||
proj1 = self.env["project.project"].create({"name": "whatever"}) | ||
proj2 = proj1.copy() | ||
self.assertEqual(proj1.sequence_code, "23-00011") | ||
self.assertEqual(proj2.sequence_code, "23-00012") | ||
|
||
@users("manager") | ||
@mute_logger("odoo.sql_db") | ||
def test_sequence_unique(self): | ||
"""Sequence cannot have duplicates.""" | ||
proj1 = self.env["project.project"].create({"name": "one"}) | ||
self.assertEqual(proj1.sequence_code, "23-00011") | ||
self.pjr_seq._get_current_sequence().number_next = 11 | ||
with self.assertRaises(IntegrityError), self.env.cr.savepoint(): | ||
proj1 = self.env["project.project"].create({"name": "two"}) | ||
|
||
@users("manager") | ||
def test_project_without_sequence(self): | ||
"""Preexisting projects had no sequence, and they should display fine.""" | ||
proj1 = self.env["project.project"].create( | ||
{"name": "one", "sequence_code": False} | ||
) | ||
self.assertEqual(proj1.display_name, "one") | ||
self.assertFalse(proj1.sequence_code) | ||
# Make sure that the sequence is not increased | ||
proj2 = self.env["project.project"].create({"name": "two"}) | ||
self.assertEqual(proj2.sequence_code, "23-00011") | ||
self.assertEqual(proj2.display_name, "23-00011 - two") |
Oops, something went wrong.