Initial commit: OCA Technical packages (595 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:03 +02:00
commit 2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions

View file

@ -0,0 +1,94 @@
==============
Base Sub State
==============
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f61483bd82ccd6e03a71443c8950a9f3231656d3afa1a27a909024a8e27df7f0
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--ux-lightgray.png?logo=github
:target: https://github.com/OCA/server-ux/tree/16.0/base_substate
:alt: OCA/server-ux
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/server-ux-16-0/server-ux-16-0-base_substate
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/server-ux&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module provide abstract models to manage customizable
substates to be applied on different models (sale order, purchase, ...).
example:
--------
* for the quotation state of a sale order we can define 3 substates "In negotiation",
"Won" and "Lost".
* We can also send mail when the substate is reached.
It is not useful by itself. You can see an example of implementation
in the 'purchase_substate' module. (purchase-workflow repository).
**Table of contents**
.. contents::
:local:
Usage
=====
#. You must install an application module depending this one (for example purchase_substate)
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-ux/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/server-ux/issues/new?body=module:%20base_substate%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Akretion
Contributors
~~~~~~~~~~~~
* Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
* Kitti U. <kittiu@ecosoft.co.th>
* Alexei Rivera <arivera@archeti.com> (migration to 15.0)
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
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.
This module is part of the `OCA/server-ux <https://github.com/OCA/server-ux/tree/16.0/base_substate>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1 @@
from . import models

View file

@ -0,0 +1,20 @@
# Copyright 2020 Akretion (<http://www.akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Base Sub State",
"version": "16.0.1.0.1",
"category": "Tools",
"author": "Akretion, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/server-ux",
"license": "AGPL-3",
"depends": ["base", "mail"],
"data": [
"security/base_substate_security.xml",
"security/ir.model.access.csv",
"views/base_substate_type_views.xml",
"views/base_substate_value_views.xml",
"views/base_substate_views.xml",
],
"installable": True,
}

View file

@ -0,0 +1,228 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * base_substate
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__active
msgid "Active"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__model
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__model
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__model
msgid "Apply on"
msgstr ""
#. module: base_substate
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_form
msgid "Archived"
msgstr ""
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_base_substate_view
#: model:ir.model,name:base_substate.model_base_substate
#: model:ir.ui.menu,name:base_substate.menu_base_substate
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_search
msgid "Base Substate"
msgstr ""
#. module: base_substate
#: model:ir.model,name:base_substate.model_base_substate_type
msgid "Base Substate Type"
msgstr ""
#. module: base_substate
#: model:ir.model,name:base_substate.model_base_substate_mixin
msgid "BaseSubstate Mixin"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__create_uid
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__create_uid
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__create_uid
msgid "Created by"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__create_date
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__create_date
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__create_date
msgid "Created on"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__description
msgid "Description"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__display_name
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__display_name
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__display_name
msgid "Display Name"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__mail_template_id
msgid "Email Template"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__sequence
msgid "Gives the sequence order when applying the default substate"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__id
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__id
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__id
msgid "ID"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__mail_template_id
msgid ""
"If set, an email will be sent to the partner when the object reaches this "
"substate."
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate____last_update
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type____last_update
#: model:ir.model.fields,field_description:base_substate.field_target_state_value____last_update
msgid "Last Modified on"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__write_uid
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__write_uid
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__write_uid
msgid "Last Updated by"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__write_date
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__write_date
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__write_date
msgid "Last Updated on"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__model
#: model:ir.model.fields,help:base_substate.field_target_state_value__model
msgid "Model for technical use"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__name
msgid "Name"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__sequence
msgid "Sequence"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_mixin__substate_id
msgid "Sub State"
msgstr ""
#. module: base_substate
#: model:ir.ui.menu,name:base_substate.menu_substate_config
msgid "Sub State Configuration"
msgstr ""
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_base_substate_type_view
#: model:ir.ui.menu,name:base_substate.menu_base_substate_type
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_type_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_type_view_search
msgid "Sub State Type"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__name
msgid "Substate Name"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__base_substate_type_id
msgid "Substate Type"
msgstr ""
#. module: base_substate
#: model:res.groups,name:base_substate.group_substate_manager
msgid "Substate manager"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__target_state_field
msgid "Target State Field"
msgstr ""
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_target_state_value_view
#: model:ir.model,name:base_substate.model_target_state_value
#: model:ir.model.fields,field_description:base_substate.field_base_substate__target_state_value_id
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__target_state_value
#: model:ir.ui.menu,name:base_substate.menu_target_state_value
#: model_terms:ir.ui.view,arch_db:base_substate.target_state_value_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.target_state_value_view_search
msgid "Target State Value"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__name
msgid "Target state Name"
msgstr ""
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_target_state_value__name
msgid ""
"Target state translateble name.\n"
"Ex: for sale order \"Quotation\", \"Sale order\", \"Locked\"..."
msgstr ""
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate_type__target_state_field
msgid ""
"Technical target state field name. Ex for sale order \"state\" for other "
"\"status\" ... "
msgstr ""
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_target_state_value__target_state_value
msgid ""
"Technical target state value.\n"
"Ex: for sale order \"draft\", \"sale\", \"done\", ..."
msgstr ""
#. module: base_substate
#. odoo-python
#: code:addons/base_substate/models/base_substate_mixin.py:0
#, python-format
msgid ""
"The substate %(name)s is not defined for the state %(state)s but for "
"%(target_state)s "
msgstr ""
#. module: base_substate
#. odoo-python
#: code:addons/base_substate/models/base_substate_mixin.py:0
#, python-format
msgid "This substate is not define for this object but for %s"
msgstr ""

View file

@ -0,0 +1,228 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * base_substate
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__active
msgid "Active"
msgstr "Aktivan"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__model
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__model
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__model
msgid "Apply on"
msgstr "Primjeni na"
#. module: base_substate
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_form
msgid "Archived"
msgstr "Arhivirano"
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_base_substate_view
#: model:ir.model,name:base_substate.model_base_substate
#: model:ir.ui.menu,name:base_substate.menu_base_substate
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_search
msgid "Base Substate"
msgstr "Osnovno podstanje"
#. module: base_substate
#: model:ir.model,name:base_substate.model_base_substate_type
msgid "Base Substate Type"
msgstr "Tip osnovnog podstanja"
#. module: base_substate
#: model:ir.model,name:base_substate.model_base_substate_mixin
msgid "BaseSubstate Mixin"
msgstr "BaseSubstate Mixin"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__create_uid
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__create_uid
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__create_uid
msgid "Created by"
msgstr "Kreirao"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__create_date
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__create_date
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__create_date
msgid "Created on"
msgstr "Kreirano"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__description
msgid "Description"
msgstr "Opis"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__display_name
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__display_name
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__display_name
msgid "Display Name"
msgstr "Prikazani naziv"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__mail_template_id
msgid "Email Template"
msgstr "Predložak email-a"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__sequence
msgid "Gives the sequence order when applying the default substate"
msgstr "Daje redoslijed sekvence prilikom primjene defaultnog podstanja"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__id
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__id
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__id
msgid "ID"
msgstr "ID"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__mail_template_id
msgid ""
"If set, an email will be sent to the partner when the object reaches this "
"substate."
msgstr ""
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate____last_update
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type____last_update
#: model:ir.model.fields,field_description:base_substate.field_target_state_value____last_update
msgid "Last Modified on"
msgstr "Zadnje mijenjano"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__write_uid
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__write_uid
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__write_uid
msgid "Last Updated by"
msgstr "Zadnji ažurirao"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__write_date
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__write_date
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__write_date
msgid "Last Updated on"
msgstr "Zadnje ažurirano"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__model
#: model:ir.model.fields,help:base_substate.field_target_state_value__model
msgid "Model for technical use"
msgstr "Model za tehničku upotrebu"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__name
msgid "Name"
msgstr "Naziv:"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__sequence
msgid "Sequence"
msgstr "Sekvenca"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_mixin__substate_id
msgid "Sub State"
msgstr "Podstanje"
#. module: base_substate
#: model:ir.ui.menu,name:base_substate.menu_substate_config
msgid "Sub State Configuration"
msgstr "Konfiguracija podstanja"
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_base_substate_type_view
#: model:ir.ui.menu,name:base_substate.menu_base_substate_type
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_type_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_type_view_search
msgid "Sub State Type"
msgstr "Tip podstanja"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__name
msgid "Substate Name"
msgstr "Ime podstanja"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__base_substate_type_id
msgid "Substate Type"
msgstr "Tip podstanja"
#. module: base_substate
#: model:res.groups,name:base_substate.group_substate_manager
msgid "Substate manager"
msgstr "Upravljač podstanja"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__target_state_field
msgid "Target State Field"
msgstr "Polje ciljnog stanja"
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_target_state_value_view
#: model:ir.model,name:base_substate.model_target_state_value
#: model:ir.model.fields,field_description:base_substate.field_base_substate__target_state_value_id
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__target_state_value
#: model:ir.ui.menu,name:base_substate.menu_target_state_value
#: model_terms:ir.ui.view,arch_db:base_substate.target_state_value_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.target_state_value_view_search
msgid "Target State Value"
msgstr "Vrijednost ciljnog stanja"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__name
msgid "Target state Name"
msgstr "Ime ciljnog stanja"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_target_state_value__name
msgid ""
"Target state translateble name.\n"
"Ex: for sale order \"Quotation\", \"Sale order\", \"Locked\"..."
msgstr ""
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate_type__target_state_field
msgid ""
"Technical target state field name. Ex for sale order \"state\" for other "
"\"status\" ... "
msgstr ""
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_target_state_value__target_state_value
msgid ""
"Technical target state value.\n"
"Ex: for sale order \"draft\", \"sale\", \"done\", ..."
msgstr ""
#. module: base_substate
#. odoo-python
#: code:addons/base_substate/models/base_substate_mixin.py:0
#, python-format
msgid ""
"The substate %(name)s is not defined for the state %(state)s but for "
"%(target_state)s "
msgstr ""
#. module: base_substate
#. odoo-python
#: code:addons/base_substate/models/base_substate_mixin.py:0
#, python-format
msgid "This substate is not define for this object but for %s"
msgstr "Ovo podstanje nije definirano za ovaj objekat već za %s"

View file

@ -0,0 +1,241 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * base_substate
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-11-11 15:17+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: none\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__active
msgid "Active"
msgstr "Activo"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__model
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__model
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__model
msgid "Apply on"
msgstr "Aplicar sobre"
#. module: base_substate
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_form
msgid "Archived"
msgstr "Archivado"
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_base_substate_view
#: model:ir.model,name:base_substate.model_base_substate
#: model:ir.ui.menu,name:base_substate.menu_base_substate
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_search
msgid "Base Substate"
msgstr "Subestado Base"
#. module: base_substate
#: model:ir.model,name:base_substate.model_base_substate_type
msgid "Base Substate Type"
msgstr "Tipo de Subestado Base"
#. module: base_substate
#: model:ir.model,name:base_substate.model_base_substate_mixin
msgid "BaseSubstate Mixin"
msgstr "Mezcla de subestado base"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__create_uid
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__create_uid
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__create_date
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__create_date
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__create_date
msgid "Created on"
msgstr "Creado el"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__description
msgid "Description"
msgstr "Descripción"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__display_name
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__display_name
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__display_name
msgid "Display Name"
msgstr "Mostrar Nombre"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__mail_template_id
msgid "Email Template"
msgstr "Plantilla de Correo Electrónico"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__sequence
msgid "Gives the sequence order when applying the default substate"
msgstr "Indica el orden de secuencia al aplicar el subestado por defecto"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__id
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__id
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__id
msgid "ID"
msgstr "ID (identificación)"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__mail_template_id
msgid ""
"If set, an email will be sent to the partner when the object reaches this "
"substate."
msgstr ""
"Si se establece, se enviará un correo electrónico al socio cuando el objeto "
"alcance este subestado."
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate____last_update
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type____last_update
#: model:ir.model.fields,field_description:base_substate.field_target_state_value____last_update
msgid "Last Modified on"
msgstr "Última Modificación el"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__write_uid
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__write_uid
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__write_uid
msgid "Last Updated by"
msgstr "Actualizado por Última vez por"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__write_date
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__write_date
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__write_date
msgid "Last Updated on"
msgstr "Última Actualización el"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__model
#: model:ir.model.fields,help:base_substate.field_target_state_value__model
msgid "Model for technical use"
msgstr "Modelo para uso técnico"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__name
msgid "Name"
msgstr "Nombre"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__sequence
msgid "Sequence"
msgstr "Secuencia"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_mixin__substate_id
msgid "Sub State"
msgstr "Sub Estado"
#. module: base_substate
#: model:ir.ui.menu,name:base_substate.menu_substate_config
msgid "Sub State Configuration"
msgstr "Configuración del Sub Estado"
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_base_substate_type_view
#: model:ir.ui.menu,name:base_substate.menu_base_substate_type
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_type_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_type_view_search
msgid "Sub State Type"
msgstr "Tipo de Sub Estado"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__name
msgid "Substate Name"
msgstr "Nombre del Subestado"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__base_substate_type_id
msgid "Substate Type"
msgstr "Tipo de Subestado"
#. module: base_substate
#: model:res.groups,name:base_substate.group_substate_manager
msgid "Substate manager"
msgstr "Gerente del Subestado"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__target_state_field
msgid "Target State Field"
msgstr "Objetivo Campo del Estado"
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_target_state_value_view
#: model:ir.model,name:base_substate.model_target_state_value
#: model:ir.model.fields,field_description:base_substate.field_base_substate__target_state_value_id
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__target_state_value
#: model:ir.ui.menu,name:base_substate.menu_target_state_value
#: model_terms:ir.ui.view,arch_db:base_substate.target_state_value_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.target_state_value_view_search
msgid "Target State Value"
msgstr "Valor Objetivo del Estado"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__name
msgid "Target state Name"
msgstr "Nombre del Estado objetivo"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_target_state_value__name
msgid ""
"Target state translateble name.\n"
"Ex: for sale order \"Quotation\", \"Sale order\", \"Locked\"..."
msgstr ""
"Nombre traducible del estado de destino.\n"
"Ej: para orden de venta \"Quotation\", \"Sale order\", \"Locked\"..."
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate_type__target_state_field
msgid ""
"Technical target state field name. Ex for sale order \"state\" for other "
"\"status\" ... "
msgstr ""
"Nombre de campo de estado de destino técnico. Ej para pedido de venta \"state"
" \" para otro \"status \" ... "
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_target_state_value__target_state_value
msgid ""
"Technical target state value.\n"
"Ex: for sale order \"draft\", \"sale\", \"done\", ..."
msgstr ""
"Valor de estado del objetivo técnico.\n"
"Ej: para pedido de venta \"draft \", \"sale \", \"done \", ..."
#. module: base_substate
#. odoo-python
#: code:addons/base_substate/models/base_substate_mixin.py:0
#, python-format
msgid ""
"The substate %(name)s is not defined for the state %(state)s but for "
"%(target_state)s "
msgstr ""
"El subestado %(name)s no está definido para el estado %(state)s sino para "
"%(target_state)s "
#. module: base_substate
#. odoo-python
#: code:addons/base_substate/models/base_substate_mixin.py:0
#, python-format
msgid "This substate is not define for this object but for %s"
msgstr "Este subestado no está definido para este objeto sino para %s"

View file

@ -0,0 +1,242 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * base_substate
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-02-21 18:06+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.6.2\n"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__active
msgid "Active"
msgstr "Attivo"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__model
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__model
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__model
msgid "Apply on"
msgstr "Applica a"
#. module: base_substate
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_form
msgid "Archived"
msgstr "In archivio"
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_base_substate_view
#: model:ir.model,name:base_substate.model_base_substate
#: model:ir.ui.menu,name:base_substate.menu_base_substate
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_view_search
msgid "Base Substate"
msgstr "Substato base"
#. module: base_substate
#: model:ir.model,name:base_substate.model_base_substate_type
msgid "Base Substate Type"
msgstr "Tipo substato base"
#. module: base_substate
#: model:ir.model,name:base_substate.model_base_substate_mixin
msgid "BaseSubstate Mixin"
msgstr "Mixin substato base"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__create_uid
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__create_uid
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__create_uid
msgid "Created by"
msgstr "Creato da"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__create_date
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__create_date
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__create_date
msgid "Created on"
msgstr "Creato il"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__description
msgid "Description"
msgstr "Descrizione"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__display_name
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__display_name
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__display_name
msgid "Display Name"
msgstr "Nome visualizzato"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__mail_template_id
msgid "Email Template"
msgstr "Modello e-mail"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__sequence
msgid "Gives the sequence order when applying the default substate"
msgstr "Fornisce la sequenza quando si applica il substato predefinito"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__id
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__id
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__id
msgid "ID"
msgstr "ID"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__mail_template_id
msgid ""
"If set, an email will be sent to the partner when the object reaches this "
"substate."
msgstr ""
"Se impostato, verrà mandata una e-mail al partner quando l'oggetto raggiunge "
"questo substato."
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate____last_update
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type____last_update
#: model:ir.model.fields,field_description:base_substate.field_target_state_value____last_update
msgid "Last Modified on"
msgstr "Ultima modifica il"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__write_uid
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__write_uid
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__write_uid
msgid "Last Updated by"
msgstr "Ultimo aggiornamento di"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__write_date
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__write_date
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__write_date
msgid "Last Updated on"
msgstr "Ultimo aggiornamento il"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate__model
#: model:ir.model.fields,help:base_substate.field_target_state_value__model
msgid "Model for technical use"
msgstr "Modello per uso tecnico"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__name
msgid "Name"
msgstr "Nome"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__sequence
msgid "Sequence"
msgstr "Sequenza"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_mixin__substate_id
msgid "Sub State"
msgstr "Substato"
#. module: base_substate
#: model:ir.ui.menu,name:base_substate.menu_substate_config
msgid "Sub State Configuration"
msgstr "Configurazione substato"
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_base_substate_type_view
#: model:ir.ui.menu,name:base_substate.menu_base_substate_type
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_type_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.base_substate_type_view_search
msgid "Sub State Type"
msgstr "Tipo substato"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate__name
msgid "Substate Name"
msgstr "Nome substato"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__base_substate_type_id
msgid "Substate Type"
msgstr "Tipo substato"
#. module: base_substate
#: model:res.groups,name:base_substate.group_substate_manager
msgid "Substate manager"
msgstr "Responsabile substato"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_base_substate_type__target_state_field
msgid "Target State Field"
msgstr "Campo stato obiettivo"
#. module: base_substate
#: model:ir.actions.act_window,name:base_substate.act_open_target_state_value_view
#: model:ir.model,name:base_substate.model_target_state_value
#: model:ir.model.fields,field_description:base_substate.field_base_substate__target_state_value_id
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__target_state_value
#: model:ir.ui.menu,name:base_substate.menu_target_state_value
#: model_terms:ir.ui.view,arch_db:base_substate.target_state_value_view_form
#: model_terms:ir.ui.view,arch_db:base_substate.target_state_value_view_search
msgid "Target State Value"
msgstr "Valore stato obiettivo"
#. module: base_substate
#: model:ir.model.fields,field_description:base_substate.field_target_state_value__name
msgid "Target state Name"
msgstr "Nome stato obiettivo"
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_target_state_value__name
msgid ""
"Target state translateble name.\n"
"Ex: for sale order \"Quotation\", \"Sale order\", \"Locked\"..."
msgstr ""
"Nome traducibile dello stato obiettivo.\n"
"Es: per ordine di vendita \"Preventivo\", \"Ordine di vendita\", \"Bloccato\""
"..."
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_base_substate_type__target_state_field
msgid ""
"Technical target state field name. Ex for sale order \"state\" for other "
"\"status\" ... "
msgstr ""
"Nome tecnico del campo obiettivo dello stato. Es: per ordine di vendita "
"\"state\", per altri \"status\" ... "
#. module: base_substate
#: model:ir.model.fields,help:base_substate.field_target_state_value__target_state_value
msgid ""
"Technical target state value.\n"
"Ex: for sale order \"draft\", \"sale\", \"done\", ..."
msgstr ""
"Valore tecnico dello stato obiettivo.\n"
"Es: per ordine di vendita \"draft\", \"sale\", \"done\", ..."
#. module: base_substate
#. odoo-python
#: code:addons/base_substate/models/base_substate_mixin.py:0
#, python-format
msgid ""
"The substate %(name)s is not defined for the state %(state)s but for "
"%(target_state)s "
msgstr ""
"Il substato %(name)s non è definito per lo stato %(state)s ma per "
"%(target_state)s "
#. module: base_substate
#. odoo-python
#: code:addons/base_substate/models/base_substate_mixin.py:0
#, python-format
msgid "This substate is not define for this object but for %s"
msgstr "Questo sottostato non è definito per questo oggetto ma per %s"

View file

@ -0,0 +1,2 @@
from . import base_substate
from . import base_substate_mixin

View file

@ -0,0 +1,103 @@
# Copyright 2020 Akretion
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class BaseSubstateType(models.Model):
"""This model defines technical data which precises
for each target model concerned by substate,
the technical "state" field name.
Data in this model should be created by import as technical data
in the specific module. For example in sale_substate we can define:
base.substate.type:
- name: Sale order Substate
- model: sale.order
- target_state_field: state
"""
_name = "base.substate.type"
_description = "Base Substate Type"
_order = "name asc, model asc"
name = fields.Char(required=True, translate=True)
model = fields.Selection(selection=[], string="Apply on", required=True)
target_state_field = fields.Char(
required=True,
help="Technical target state field name."
' Ex for sale order "state" for other "status" ... ',
)
class TargetStateValue(models.Model):
"""This model define technical data that precise the translatable name
of the target model state (ex:Quotation for 'draft' State)
Data in this model should be created by import as technical data
in specific module ex : sale_subsatate
"""
_name = "target.state.value"
_description = "Target State Value"
_order = "name asc"
name = fields.Char(
"Target state Name",
required=True,
translate=True,
help="Target state translateble name.\n"
'Ex: for sale order "Quotation", "Sale order", "Locked"...',
)
base_substate_type_id = fields.Many2one(
"base.substate.type",
string="Substate Type",
ondelete="restrict",
)
target_state_value = fields.Char(
required=True,
help="Technical target state value.\n"
'Ex: for sale order "draft", "sale", "done", ...',
)
model = fields.Selection(
related="base_substate_type_id.model",
store=True,
readonly=True,
help="Model for technical use",
)
class BaseSubstate(models.Model):
"""This model define substates that will be applied on the target model.
for each state we can define one or more substate.
ex:
for the quotation state of a sale order we can define
3 substates "In negotiation",
"Won" and "Lost".
We can also send mail when the susbstate is reached.
"""
_name = "base.substate"
_description = "Base Substate"
_order = "active desc, sequence asc"
name = fields.Char("Substate Name", required=True, translate=True)
description = fields.Text(translate=True)
sequence = fields.Integer(
index=True,
help="Gives the sequence order when applying the default substate",
)
target_state_value_id = fields.Many2one(
"target.state.value", string="Target State Value", ondelete="restrict"
)
active = fields.Boolean(default=True)
mail_template_id = fields.Many2one(
"mail.template",
string="Email Template",
help="If set, an email will be sent to the partner "
"when the object reaches this substate.",
)
model = fields.Selection(
related="target_state_value_id.model",
store=True,
readonly=True,
help="Model for technical use",
)

View file

@ -0,0 +1,127 @@
# Copyright 2020 Akretion
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class BaseSubstateMixin(models.AbstractModel):
_name = "base.substate.mixin"
_description = "BaseSubstate Mixin"
_state_field = "state"
@api.constrains("substate_id", _state_field)
def check_substate_id_value(self):
rec_states = dict(self._fields[self._state_field].selection)
for rec in self:
target_state = rec.substate_id.target_state_value_id.target_state_value
if rec.substate_id and rec.state != target_state:
raise ValidationError(
_(
"The substate %(name)s is not defined for the state"
" %(state)s but for %(target_state)s "
)
% {
"name": rec.substate_id.name,
"state": _(rec_states[rec.state]),
"target_state": _(rec_states[target_state]),
}
)
def _get_default_substate_id(self, state_val=False):
"""Gives default substate_id"""
search_domain = self._get_default_substate_domain(state_val)
# perform search, return the first found
return (
self.env["base.substate"]
.search(search_domain, order="sequence", limit=1)
.id
)
def _get_default_substate_domain(self, state_val=False):
"""Override this method
to change domain values
"""
if not state_val:
state_val = self._get_default_state_value()
substate_type = self._get_substate_type()
state_field = substate_type.target_state_field
if self and not state_val and state_field in self._fields:
state_val = self[state_field]
domain = [("target_state_value_id.target_state_value", "=", state_val)]
domain += [
("target_state_value_id.base_substate_type_id", "=", substate_type.id)
]
return domain
def _get_default_state_value(
self,
):
"""Override this method
to change state_value
"""
return "draft"
def _get_substate_type(
self,
):
"""Override this method
to change substate_type (get by xml id for example)
"""
return self.env["base.substate.type"].search(
[("model", "=", self._name)], limit=1
)
substate_id = fields.Many2one(
"base.substate",
string="Sub State",
ondelete="restrict",
default=lambda self: self._get_default_substate_id(),
tracking=5,
index=True,
domain=lambda self: [("model", "=", self._name)],
copy=False,
)
@api.constrains("substate_id")
def check_substate_id_consistency(self):
for mixin_obj in self:
if mixin_obj.substate_id and mixin_obj.substate_id.model != self._name:
raise ValidationError(
_("This substate is not define for this object but for %s")
% mixin_obj.substate_id.model
)
def _update_before_write_create(self, values):
substate_type = self._get_substate_type()
state_field = substate_type.target_state_field
if values.get(state_field) and not values.get("substate_id"):
state_val = values.get(state_field)
values["substate_id"] = self._get_default_substate_id(state_val)
# Send mail if substate has mail template
if values.get("substate_id"):
substate = self.env["base.substate"].browse(values["substate_id"])
if (
hasattr(self, "message_post_with_template")
and substate.mail_template_id
):
self.message_post_with_template(
substate.mail_template_id.id,
subtype_id=self.env["ir.model.data"]._xmlid_to_res_id(
"mail.mt_note"
),
)
return values
def write(self, values):
values = self._update_before_write_create(values)
res = super().write(values)
return res
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
vals = self._update_before_write_create(vals)
res = super().create(vals_list)
return res

View file

@ -0,0 +1,3 @@
* Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
* Kitti U. <kittiu@ecosoft.co.th>
* Alexei Rivera <arivera@archeti.com> (migration to 15.0)

View file

@ -0,0 +1,12 @@
This module provide abstract models to manage customizable
substates to be applied on different models (sale order, purchase, ...).
example:
--------
* for the quotation state of a sale order we can define 3 substates "In negotiation",
"Won" and "Lost".
* We can also send mail when the substate is reached.
It is not useful by itself. You can see an example of implementation
in the 'purchase_substate' module. (purchase-workflow repository).

View file

@ -0,0 +1 @@
#. You must install an application module depending this one (for example purchase_substate)

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="group_substate_manager" model="res.groups">
<field name="name">Substate manager</field>
<field name="implied_ids" eval="[(4, ref('base.group_user'))]" />
</record>
</odoo>

View file

@ -0,0 +1,7 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_base_substate_type,base.substate.type user,model_base_substate_type,base.group_user,1,0,0,0
access_base_substate_type_manager,base.substate.type manager,model_base_substate_type,base_substate.group_substate_manager,1,1,1,1
access_target_state_value,base.substate.value user,model_target_state_value,base.group_user,1,0,0,0
access_target_state_value_manager,base.substate.value manager,model_target_state_value,base_substate.group_substate_manager,1,1,1,1
access_base_substate,base.substate user,model_base_substate,base.group_user,1,0,0,0
access_base_substate_manager,base.substate manager,model_base_substate,base_substate.group_substate_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_base_substate_type base.substate.type user model_base_substate_type base.group_user 1 0 0 0
3 access_base_substate_type_manager base.substate.type manager model_base_substate_type base_substate.group_substate_manager 1 1 1 1
4 access_target_state_value base.substate.value user model_target_state_value base.group_user 1 0 0 0
5 access_target_state_value_manager base.substate.value manager model_target_state_value base_substate.group_substate_manager 1 1 1 1
6 access_base_substate base.substate user model_base_substate base.group_user 1 0 0 0
7 access_base_substate_manager base.substate manager model_base_substate base_substate.group_substate_manager 1 1 1 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,443 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Base Sub State</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="base-sub-state">
<h1 class="title">Base Sub State</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f61483bd82ccd6e03a71443c8950a9f3231656d3afa1a27a909024a8e27df7f0
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/server-ux/tree/16.0/base_substate"><img alt="OCA/server-ux" src="https://img.shields.io/badge/github-OCA%2Fserver--ux-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/server-ux-16-0/server-ux-16-0-base_substate"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/server-ux&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module provide abstract models to manage customizable
substates to be applied on different models (sale order, purchase, …).</p>
<div class="section" id="example">
<h1>example:</h1>
<ul class="simple">
<li>for the quotation state of a sale order we can define 3 substates “In negotiation”,
“Won” and “Lost”.</li>
<li>We can also send mail when the substate is reached.</li>
</ul>
<p>It is not useful by itself. You can see an example of implementation
in the purchase_substate module. (purchase-workflow repository).</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h2><a class="toc-backref" href="#toc-entry-1">Usage</a></h2>
<ol class="arabic simple">
<li>You must install an application module depending this one (for example purchase_substate)</li>
</ol>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/server-ux/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 to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/server-ux/issues/new?body=module:%20base_substate%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-3">Credits</a></h2>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-4">Authors</a></h3>
<ul class="simple">
<li>Akretion</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-5">Contributors</a></h3>
<ul class="simple">
<li>Mourad EL HADJ MIMOUNE &lt;<a class="reference external" href="mailto:mourad.elhadj.mimoune&#64;akretion.com">mourad.elhadj.mimoune&#64;akretion.com</a>&gt;</li>
<li>Kitti U. &lt;<a class="reference external" href="mailto:kittiu&#64;ecosoft.co.th">kittiu&#64;ecosoft.co.th</a>&gt;</li>
<li>Alexei Rivera &lt;<a class="reference external" href="mailto:arivera&#64;archeti.com">arivera&#64;archeti.com</a>&gt; (migration to 15.0)</li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h3>
<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
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/server-ux/tree/16.0/base_substate">OCA/server-ux</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,3 @@
from . import models_mixin
from . import sale_test
from . import test_base_substate

View file

@ -0,0 +1,125 @@
# Copyright 2018 Simone Orsi - Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from operator import attrgetter
class TestMixin(object):
"""Mixin to setup fake models for tests.
Usage - the model:
class FakeModel(models.Model, TestMixin):
_name = 'fake.model'
name = fields.Char()
Usage - the test klass:
@classmethod
def setUpClass(cls):
super().setUpClass()
FakeModel._test_setup_model(cls.env)
@classmethod
def tearDownClass(cls):
FakeModel._test_teardown_model(cls.env)
super().tearDownClass()
"""
# Generate xmlids
# This is needed if you want to load data tied to a test model via xid.
_test_setup_gen_xid = False
# If you extend a real model (ie: res.partner) you must enable this
# to not delete the model on tear down.
_test_teardown_no_delete = False
# You can add custom fields to real models (eg: res.partner).
# In this case you must delete them to leave registry and model clean.
# This is mandatory for relational fields that link a fake model.
_test_purge_fields = []
@classmethod
def _test_setup_models(cls, env, model_clses):
"""
Setup models at the same time
if one fake model ref to another in relational
field.
ex : many2one fields
in this case we should don't use manual=True as an option in field.
"""
for model_cls in model_clses:
model_cls._build_model(env.registry, env.cr)
env.registry.setup_models(env.cr)
ctx = dict(env.context, update_custom_fields=True)
if cls._test_setup_gen_xid:
ctx["module"] = cls._module
env.registry.init_models(
env.cr, [model_cls._name for model_cls in model_clses], ctx
)
@classmethod
def _test_setup_model(cls, env):
"""Initialize it."""
cls._build_model(env.registry, env.cr)
env.registry.setup_models(env.cr)
ctx = dict(env.context, update_custom_fields=True)
if cls._test_setup_gen_xid:
ctx["module"] = cls._module
env.registry.init_models(env.cr, [cls._name], ctx)
@classmethod
def _test_teardown_model(cls, env):
"""Cleanup registry and real models."""
for fname in cls._test_purge_fields:
model = env[cls._name]
if fname in model:
model._pop_field(fname)
if not getattr(cls, "_test_teardown_no_delete", False):
del env.registry.models[cls._name]
# here we must remove the model from list of children of inherited
# models
parents = cls._inherit
parents = [parents] if isinstance(parents, str) else (parents or [])
# keep a copy to be sure to not modify the original _inherit
parents = list(parents)
parents.extend(cls._inherits.keys())
parents.append("base")
funcs = [
attrgetter(kind + "_children") for kind in ["_inherits", "_inherit"]
]
for parent in parents:
for func in funcs:
children = func(env.registry[parent])
if cls._name in children:
# at this stage our cls is referenced as children of
# parent -> must un reference it
children.remove(cls._name)
def _test_get_model_id(self):
self.env.cr.execute("SELECT id FROM ir_model WHERE model = %s", (self._name,))
res = self.env.cr.fetchone()
return res[0] if res else None
def _test_create_ACL(self, **kw):
model_id = self._test_get_model_id()
if not model_id:
self._reflect()
model_id = self._test_get_model_id()
if model_id:
vals = self._test_ACL_values(model_id)
vals.update(kw)
self.env["ir.model.access"].create(vals)
def _test_ACL_values(self, model_id):
values = {
"name": "Fake ACL for %s" % self._name,
"model_id": model_id,
"perm_read": 1,
"perm_create": 1,
"perm_write": 1,
"perm_unlink": 1,
"active": True,
}
return values

View file

@ -0,0 +1,55 @@
# Copyright 2020 Akretion Mourad EL HADJ MIMOUNE
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models
from .models_mixin import TestMixin
class SaleTest(models.Model, TestMixin):
_name = "base.substate.test.sale"
_inherit = ["base.substate.mixin", "mail.thread"]
_description = "Base substate Test Model"
name = fields.Char(required=True)
user_id = fields.Many2one("res.users", string="Responsible")
state = fields.Selection(
[("draft", "New"), ("cancel", "Cancelled"), ("sale", "Sale"), ("done", "Done")],
string="Status",
readonly=True,
default="draft",
)
active = fields.Boolean(default=True)
partner_id = fields.Many2one("res.partner", string="Partner")
line_ids = fields.One2many(
comodel_name="base.substate.test.sale.line",
inverse_name="sale_id",
context={"active_test": False},
)
amount_total = fields.Float(compute="_compute_amount_total", store=True)
@api.depends("line_ids")
def _compute_amount_total(self):
for record in self:
for line in record.line_ids:
record.amount_total += line.amount * line.qty
def button_confirm(self):
self.write({"state": "sale"})
return True
def button_cancel(self):
self.write({"state": "cancel"})
class LineTest(models.Model, TestMixin):
_name = "base.substate.test.sale.line"
_description = "Base substate Test Model Line"
name = fields.Char()
sale_id = fields.Many2one(
comodel_name="base.substate.test.sale",
ondelete="cascade",
context={"active_test": False},
)
qty = fields.Float()
amount = fields.Float()

View file

@ -0,0 +1,133 @@
# Copyright 2020 Akretion Mourad EL HADJ MIMOUNE
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.tests import common
from .sale_test import LineTest, SaleTest
@common.tagged("post_install", "-at_install")
class TestBaseSubstate(common.TransactionCase):
@classmethod
def setUpClass(cls):
super(TestBaseSubstate, cls).setUpClass()
SaleTest._test_setup_models(cls.env, [SaleTest, LineTest])
LineTest._test_setup_model(cls.env)
cls.substate_test_sale = cls.env["base.substate.test.sale"]
cls.substate_test_sale_line = cls.env["base.substate.test.sale.line"]
cls.mail_template = cls.env["mail.template"].create(
{
"name": "Waiting for legal documents",
"model_id": cls.substate_test_sale.id,
"subject": "Test Email Substate",
}
)
cls.base_substate = cls.env["base.substate.mixin"]
cls.substate_type = cls.env["base.substate.type"]
cls.substate_type._fields["model"].selection.append(
("base.substate.test.sale", "Sale Order")
)
cls.substate_type = cls.env["base.substate.type"].create(
{
"name": "Sale",
"model": "base.substate.test.sale",
"target_state_field": "state",
}
)
cls.substate_val_quotation = cls.env["target.state.value"].create(
{
"name": "Quotation",
"base_substate_type_id": cls.substate_type.id,
"target_state_value": "draft",
}
)
cls.substate_val_sale = cls.env["target.state.value"].create(
{
"name": "Sale order",
"base_substate_type_id": cls.substate_type.id,
"target_state_value": "sale",
}
)
cls.substate_under_negotiation = cls.env["base.substate"].create(
{
"name": "Under negotiation",
"sequence": 1,
"target_state_value_id": cls.substate_val_quotation.id,
}
)
cls.substate_won = cls.env["base.substate"].create(
{
"name": "Won",
"sequence": 1,
"target_state_value_id": cls.substate_val_quotation.id,
}
)
cls.substate_wait_docs = cls.env["base.substate"].create(
{
"name": "Waiting for legal documents",
"sequence": 2,
"target_state_value_id": cls.substate_val_sale.id,
"mail_template_id": cls.mail_template.id,
}
)
cls.substate_valid_docs = cls.env["base.substate"].create(
{
"name": "To validate legal documents",
"sequence": 3,
"target_state_value_id": cls.substate_val_sale.id,
}
)
cls.substate_in_delivering = cls.env["base.substate"].create(
{
"name": "In delivering",
"sequence": 4,
"target_state_value_id": cls.substate_val_sale.id,
}
)
@classmethod
def tearDownClass(cls):
SaleTest._test_teardown_model(cls.env)
LineTest._test_teardown_model(cls.env)
return super().tearDownClass()
def test_sale_order_substate(self):
partner = self.env.ref("base.res_partner_1")
so_test1 = self.substate_test_sale.create(
{
"name": "Test base substate to basic sale",
"partner_id": partner.id,
"line_ids": [
(0, 0, {"name": "line test", "amount": 120.0, "qty": 1.5})
],
}
)
self.assertTrue(so_test1.state == "draft")
self.assertTrue(so_test1.substate_id == self.substate_under_negotiation)
self.assertNotIn(
self.mail_template.subject, so_test1.message_ids.mapped("subject")
)
# Test that validation of sale order change substate_id
so_test1.button_confirm()
self.assertTrue(so_test1.state == "sale")
self.assertTrue(so_test1.substate_id == self.substate_wait_docs)
# Check some message_ids are created and sent email
self.assertIn(
self.mail_template.subject, so_test1.message_ids.mapped("subject")
)
# Test that substate_id is set to false if
# there is not substate corresponding to state
so_test1.button_cancel()
self.assertTrue(so_test1.state == "cancel")
self.assertTrue(not so_test1.substate_id)

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Akretion
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="base_substate_type_view_tree" model="ir.ui.view">
<field name="model">base.substate.type</field>
<field name="arch" type="xml">
<tree>
<field name="name" />
<field name="model" />
<field name="target_state_field" />
</tree>
</field>
</record>
<record id="base_substate_type_view_form" model="ir.ui.view">
<field name="model">base.substate.type</field>
<field name="arch" type="xml">
<form string="Sub State Type" name="base_substate_type">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" />
<h1>
<field name="name" />
</h1>
</div>
<group>
<group name="model_def" colspan="4" groups="base.group_system">
<field name="model" />
<field name="target_state_field" />
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="base_substate_type_view_search" model="ir.ui.view">
<field name="model">base.substate.type</field>
<field name="arch" type="xml">
<search string="Sub State Type">
<field name="name" />
<field name="model" />
<field name="target_state_field" />
</search>
</field>
</record>
<record model="ir.actions.act_window" id="act_open_base_substate_type_view">
<field name="name">Sub State Type</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">base.substate.type</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="base_substate_type_view_search" />
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record
model="ir.actions.act_window.view"
id="act_open_base_substate_type_view_form"
>
<field name="act_window_id" ref="act_open_base_substate_type_view" />
<field name="sequence" eval="20" />
<field name="view_mode">form</field>
<field name="view_id" ref="base_substate_type_view_form" />
</record>
<record
model="ir.actions.act_window.view"
id="act_open_base_substate_type_view_tree"
>
<field name="act_window_id" ref="act_open_base_substate_type_view" />
<field name="sequence" eval="10" />
<field name="view_mode">tree</field>
<field name="view_id" ref="base_substate_type_view_tree" />
</record>
<menuitem
id="menu_substate_config"
parent="base.menu_custom"
sequence="10"
name="Sub State Configuration"
/>
<menuitem
id="menu_base_substate_type"
parent="menu_substate_config"
sequence="20"
action="act_open_base_substate_type_view"
/>
</odoo>

View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Akretion
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="target_state_value_view_tree" model="ir.ui.view">
<field name="model">target.state.value</field>
<field name="arch" type="xml">
<tree>
<field name="name" />
<field name="base_substate_type_id" />
<field name="target_state_value" />
</tree>
</field>
</record>
<record id="target_state_value_view_form" model="ir.ui.view">
<field name="model">target.state.value</field>
<field name="arch" type="xml">
<form string="Target State Value">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" />
<h1>
<field name="name" />
</h1>
</div>
<group>
<group
name="state_value"
colspan="4"
groups="base.group_system"
>
<field name="base_substate_type_id" />
<field name="target_state_value" />
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="target_state_value_view_search" model="ir.ui.view">
<field name="model">target.state.value</field>
<field name="arch" type="xml">
<search string="Target State Value">
<field name="name" />
<field name="base_substate_type_id" />
<field name="target_state_value" />
</search>
</field>
</record>
<record model="ir.actions.act_window" id="act_open_target_state_value_view">
<field name="name">Target State Value</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">target.state.value</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="target_state_value_view_search" />
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record
model="ir.actions.act_window.view"
id="act_open_target_state_value_view_form"
>
<field name="act_window_id" ref="act_open_target_state_value_view" />
<field name="sequence" eval="20" />
<field name="view_mode">form</field>
<field name="view_id" ref="target_state_value_view_form" />
</record>
<record
model="ir.actions.act_window.view"
id="act_open_target_state_value_view_tree"
>
<field name="act_window_id" ref="act_open_target_state_value_view" />
<field name="sequence" eval="10" />
<field name="view_mode">tree</field>
<field name="view_id" ref="target_state_value_view_tree" />
</record>
<menuitem
id="menu_target_state_value"
parent="menu_substate_config"
sequence="20"
action="act_open_target_state_value_view"
/>
</odoo>

View file

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Akretion
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="base_substate_view_tree" model="ir.ui.view">
<field name="model">base.substate</field>
<field name="arch" type="xml">
<tree>
<field name="name" />
<field name="description" />
<field name="sequence" widget="handle" />
<field name="target_state_value_id" />
<field name="active" widget="boolean_toggle" />
</tree>
</field>
</record>
<record id="base_substate_view_form" model="ir.ui.view">
<field name="model">base.substate</field>
<field name="arch" type="xml">
<form string="Base Substate" name="base_substate">
<sheet>
<div class="oe_button_box" name="button_box">
<widget
name="web_ribbon"
title="Archived"
bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}"
/>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only" />
<h1>
<field name="name" />
</h1>
</div>
<group>
<group name="substate_definition">
<field name="active" invisible="1" />
<field name="description" />
<field name="sequence" />
<field name="target_state_value_id" />
<field name="model" />
<field
name="mail_template_id"
domain="[('model', '=', model)]"
/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="base_substate_view_search" model="ir.ui.view">
<field name="model">base.substate</field>
<field name="arch" type="xml">
<search string="Base Substate">
<field name="name" />
</search>
</field>
</record>
<record model="ir.actions.act_window" id="act_open_base_substate_view">
<field name="name">Base Substate</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">base.substate</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="base_substate_view_search" />
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record model="ir.actions.act_window.view" id="act_open_base_substate_view_form">
<field name="act_window_id" ref="act_open_base_substate_view" />
<field name="sequence" eval="20" />
<field name="view_mode">form</field>
<field name="view_id" ref="base_substate_view_form" />
</record>
<record model="ir.actions.act_window.view" id="act_open_base_substate_view_tree">
<field name="act_window_id" ref="act_open_base_substate_view" />
<field name="sequence" eval="10" />
<field name="view_mode">tree</field>
<field name="view_id" ref="base_substate_view_tree" />
</record>
<menuitem
id="menu_base_substate"
parent="menu_substate_config"
sequence="20"
action="act_open_base_substate_view"
/>
</odoo>