Carlos Dauden
8 years ago
committed by
Pedro M. Baeza
18 changed files with 901 additions and 0 deletions
-
74partner_financial_risk/README.rst
-
4partner_financial_risk/__init__.py
-
22partner_financial_risk/__openerp__.py
-
15partner_financial_risk/data/partner_financial_risk_data.xml
-
321partner_financial_risk/i18n/es.po
-
6partner_financial_risk/models/__init__.py
-
38partner_financial_risk/models/account_invoice.py
-
13partner_financial_risk/models/res_company.py
-
12partner_financial_risk/models/res_config.py
-
150partner_financial_risk/models/res_partner.py
-
3partner_financial_risk/tests/__init__.py
-
79partner_financial_risk/tests/test_partner_financial_risk.py
-
15partner_financial_risk/views/account_invoice_view.xml
-
21partner_financial_risk/views/res_config_view.xml
-
58partner_financial_risk/views/res_partner_view.xml
-
3partner_financial_risk/wizard/__init__.py
-
37partner_financial_risk/wizard/parner_risk_exceeded.py
-
30partner_financial_risk/wizard/partner_risk_exceeded_view.xml
@ -0,0 +1,74 @@ |
|||||
|
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
||||
|
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
|
||||
|
====================== |
||||
|
Partner Financial Risk |
||||
|
====================== |
||||
|
|
||||
|
Adds a new page in partner to manage its *Financial Risk*. |
||||
|
|
||||
|
If any limit is exceeded, you won't be able to confirm any of its invoices |
||||
|
unless you are authorized (Account Adviser group). |
||||
|
|
||||
|
Configuration |
||||
|
============= |
||||
|
|
||||
|
To configure this module, you need to: |
||||
|
|
||||
|
#. Go to *Invoicing/Accounting > Configuration > Settings > Invoicing & Payments* |
||||
|
#. In the *Financial Risk* section, fill *Unpaid Margin* for setting the number |
||||
|
of days to last after the due date to consider an invoice as unpaid. |
||||
|
|
||||
|
Usage |
||||
|
===== |
||||
|
|
||||
|
To use this module, you need to: |
||||
|
|
||||
|
#. Go to *Invoicing/Accounting > Sales > Customers*. |
||||
|
#. Select an existing customer or create a new one. |
||||
|
#. Open the *Financial Risk* tab. |
||||
|
#. Set limits and choose options to compute in credit limit. |
||||
|
#. Go to *Invoicing/Accounting > Sales > Customer invoices* and create new |
||||
|
customer invoices. |
||||
|
#. Test the restriction trying to create an invoice for the partner for an |
||||
|
amount higher of the limit you have set. |
||||
|
|
||||
|
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
||||
|
:alt: Try me on Runbot |
||||
|
:target: https://runbot.odoo-community.org/runbot/134/9.0 |
||||
|
|
||||
|
|
||||
|
Bug Tracker |
||||
|
=========== |
||||
|
|
||||
|
Bugs are tracked on `GitHub Issues |
||||
|
<https://github.com/OCA/partner-contact/issues>`_. In case of trouble, please |
||||
|
check there if your issue has already been reported. If you spotted it first, |
||||
|
help us smashing it by providing a detailed and welcomed feedback. |
||||
|
|
||||
|
|
||||
|
Credits |
||||
|
======= |
||||
|
|
||||
|
Contributors |
||||
|
------------ |
||||
|
|
||||
|
* Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
* Pedro M. Baeza <pedro.baeza@tecnativa.com> |
||||
|
|
||||
|
|
||||
|
Maintainer |
||||
|
---------- |
||||
|
|
||||
|
.. image:: https://odoo-community.org/logo.png |
||||
|
:alt: Odoo Community Association |
||||
|
:target: https://odoo-community.org |
||||
|
|
||||
|
This module is maintained by the OCA. |
||||
|
|
||||
|
OCA, or the Odoo Community Association, is a nonprofit organization whose |
||||
|
mission is to support the collaborative development of Odoo features and |
||||
|
promote its widespread use. |
||||
|
|
||||
|
To contribute to this module, please visit https://odoo-community.org. |
@ -0,0 +1,4 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from . import models |
||||
|
from . import wizard |
@ -0,0 +1,22 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
{ |
||||
|
'name': 'Partner Financial Risk', |
||||
|
'summary': 'Manage partner risk', |
||||
|
'version': '9.0.1.0.0', |
||||
|
'category': 'Sales Management', |
||||
|
'license': 'AGPL-3', |
||||
|
'author': 'Tecnativa, Odoo Community Association (OCA)', |
||||
|
'website': 'https://www.tecnativa.com', |
||||
|
'depends': ['account'], |
||||
|
'data': [ |
||||
|
'data/partner_financial_risk_data.xml', |
||||
|
'views/res_config_view.xml', |
||||
|
'views/res_partner_view.xml', |
||||
|
'views/account_invoice_view.xml', |
||||
|
'wizard/partner_risk_exceeded_view.xml', |
||||
|
], |
||||
|
'installable': True, |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl-3). --> |
||||
|
<odoo> |
||||
|
<record id="ir_cron_due_invoice_every_day" model="ir.cron"> |
||||
|
<field name="name">Financial risk: Process due invoices</field> |
||||
|
<field name="interval_number">1</field> |
||||
|
<field name="interval_type">days</field> |
||||
|
<field name="numbercall">-1</field> |
||||
|
<field name="doall" eval="False"/> |
||||
|
<field name="model" eval="'res.partner'"/> |
||||
|
<field name="function" eval="'process_unpaid_invoices'"/> |
||||
|
<field name="args" eval="'()'"/> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,321 @@ |
|||||
|
# Translation of Odoo Server. |
||||
|
# This file contains the translation of the following modules: |
||||
|
# * partner_financial_risk |
||||
|
# |
||||
|
# Translators: |
||||
|
# Carlos Dauden <carlos.dauden@tecnativa.com>, 2016 |
||||
|
msgid "" |
||||
|
msgstr "" |
||||
|
"Project-Id-Version: partner-contact (9.0)\n" |
||||
|
"Report-Msgid-Bugs-To: \n" |
||||
|
"POT-Creation-Date: 2016-09-18 22:47+0000\n" |
||||
|
"PO-Revision-Date: 2016-09-19 01:14+0100\n" |
||||
|
"Last-Translator: Carlos Incaser <carlos@incaser.es>\n" |
||||
|
"Language-Team: Spanish (http://www.transifex.com/oca/OCA-partner-contact-9-0/" |
||||
|
"language/es/)\n" |
||||
|
"Language: 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 1.5.4\n" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.ui.view,arch_db:partner_financial_risk.partner_risk_exceeded_wizard |
||||
|
msgid "Cancel" |
||||
|
msgstr "Cancelar" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model,name:partner_financial_risk.model_res_company |
||||
|
msgid "Companies" |
||||
|
msgstr "Compañías" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.ui.view,arch_db:partner_financial_risk.partner_risk_exceeded_wizard |
||||
|
msgid "Continue" |
||||
|
msgstr "Continuar" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_continue_method |
||||
|
msgid "Continue method" |
||||
|
msgstr "Método continuo" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_create_uid |
||||
|
msgid "Created by" |
||||
|
msgstr "Creado por" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_create_date |
||||
|
msgid "Created on" |
||||
|
msgstr "Creado en" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_credit_policy |
||||
|
msgid "Credit policy" |
||||
|
msgstr "Póliza de crédito" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_partner_id |
||||
|
msgid "Customer" |
||||
|
msgstr "Cliente" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_account_config_settings_invoice_unpaid_margin |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_company_invoice_unpaid_margin |
||||
|
msgid "Days after due date to set an invoice as unpaid" |
||||
|
msgstr "" |
||||
|
"Días después de la fecha de vencimiento para considerar una factura como " |
||||
|
"impagada" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_account_amount |
||||
|
msgid "Difference between accounting credit and rest of totals" |
||||
|
msgstr "Diferencia entre el saldo contable y el resto de totales" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_display_name |
||||
|
msgid "Display Name" |
||||
|
msgstr "Nombre a mostrar" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_exception_msg |
||||
|
msgid "Exception msg" |
||||
|
msgstr "Se ha producido una anomalía" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.ui.view,arch_db:partner_financial_risk.res_partner_view_risk |
||||
|
#: model:ir.ui.view,arch_db:partner_financial_risk.view_account_config |
||||
|
msgid "Financial Risk" |
||||
|
msgstr "Riesgo financiero" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.ui.view,arch_db:partner_financial_risk.view_account_config |
||||
|
msgid "Financial Risk div" |
||||
|
msgstr "Riesgo financiero div" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: code:addons/partner_financial_risk/models/account_invoice.py:19 |
||||
|
#, python-format |
||||
|
msgid "Financial risk exceeded.\n" |
||||
|
msgstr "Riesgo financiero excedido.\n" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_account_amount_include |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_draft_include |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_open_include |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_unpaid_include |
||||
|
msgid "Full risk computation" |
||||
|
msgstr "Cómputo de riesgo total" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.ui.view,arch_db:partner_financial_risk.res_partner_view_risk |
||||
|
msgid "General Limits" |
||||
|
msgstr "Límites generales" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_id |
||||
|
msgid "ID" |
||||
|
msgstr "ID (identificación)" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_invoice_draft_include |
||||
|
msgid "Include Draft Invoices" |
||||
|
msgstr "Incluir facturas borrador" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_invoice_open_include |
||||
|
msgid "Include Open Invoices" |
||||
|
msgstr "Incluir facturas abiertas" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_account_amount_include |
||||
|
msgid "Include Other Account Amount" |
||||
|
msgstr "Incluir otros saldos contables" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_invoice_unpaid_include |
||||
|
msgid "Include Unpaid Invoices" |
||||
|
msgstr "Incluir facturas impagadas" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.ui.view,arch_db:partner_financial_risk.res_partner_view_risk |
||||
|
msgid "Info" |
||||
|
msgstr "Información" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model,name:partner_financial_risk.model_account_invoice |
||||
|
msgid "Invoice" |
||||
|
msgstr "Factura" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_exception |
||||
|
msgid "It Indicate if partner risk exceeded" |
||||
|
msgstr "Indica si se ha excedido el riesgo" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz___last_update |
||||
|
msgid "Last Modified on" |
||||
|
msgstr "Última modificación en" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_write_uid |
||||
|
msgid "Last Updated by" |
||||
|
msgstr "Última actualización de" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_write_date |
||||
|
msgid "Last Updated on" |
||||
|
msgstr "Última actualización en" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_invoice_draft_limit |
||||
|
msgid "Limit In Draft Invoices" |
||||
|
msgstr "Límite en facturas borrador" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_invoice_open_limit |
||||
|
msgid "Limit In Open Invoices" |
||||
|
msgstr "Límite en facturas abiertas" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_invoice_unpaid_limit |
||||
|
msgid "Limit In Unpaid Invoices" |
||||
|
msgstr "Límite en facturas impagadas" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_account_amount_limit |
||||
|
msgid "Limit Other Account Amount" |
||||
|
msgstr "Límite en otros saldos contables" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_account_config_settings_invoice_unpaid_margin |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_company_invoice_unpaid_margin |
||||
|
msgid "Maturity Margin" |
||||
|
msgstr "Margen vencimiento" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_origin_reference |
||||
|
msgid "Object" |
||||
|
msgstr "Objeto" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_account_amount |
||||
|
msgid "Other Account Amount" |
||||
|
msgstr "Otros saldos contables" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model,name:partner_financial_risk.model_res_partner |
||||
|
msgid "Partner" |
||||
|
msgstr "Empresa" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: code:addons/partner_financial_risk/wizard/parner_risk_exceeded.py:25 |
||||
|
#, python-format |
||||
|
msgid "Partner risk exceeded" |
||||
|
msgstr "Empresa con riesgo excedido" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_unpaid |
||||
|
msgid "" |
||||
|
"Residual amount of invoices in Open state and the date due is exceeded, " |
||||
|
"considering Unpaid Margin set in account settings" |
||||
|
msgstr "" |
||||
|
"Importe pendiente en facturas abiertas cuya fecha de vencimiento se ha " |
||||
|
"excedido, considerando el margen de días establecido en configuración de " |
||||
|
"contabilidad" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_open |
||||
|
msgid "" |
||||
|
"Residual amount of invoices in Open state and the date due is not exceeded, " |
||||
|
"considering Due Margin set in account settings" |
||||
|
msgstr "" |
||||
|
"Importe pendiente en facturas abiertas cuya fecha de vencimiento no se ha " |
||||
|
"excedido, considerando el margen de días establecido en configuración de " |
||||
|
"contabilidad" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_exception |
||||
|
msgid "Risk Exception" |
||||
|
msgstr "Excepción por riesgo" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_allow_edit |
||||
|
msgid "Risk allow edit" |
||||
|
msgstr "Permitir editar riesgo" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.ui.view,arch_db:partner_financial_risk.partner_risk_exceeded_wizard |
||||
|
msgid "Risk exceeded" |
||||
|
msgstr "Riesgo excedido" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_account_amount_limit |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_draft_limit |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_open_limit |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_unpaid_limit |
||||
|
msgid "Set 0 if it is not locked" |
||||
|
msgstr "Establece 0 si no está bloqueado" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.ui.view,arch_db:partner_financial_risk.res_partner_view_risk |
||||
|
msgid "Specific Limits" |
||||
|
msgstr "Límites específicos" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_total |
||||
|
msgid "Sum of total risk included" |
||||
|
msgstr "Suma de riesgo total incluido" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.ui.view,arch_db:partner_financial_risk.partner_risk_exceeded_wizard |
||||
|
msgid "The partner has exceeded his risk" |
||||
|
msgstr "La empresa ha excedido su riesgo" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: code:addons/partner_financial_risk/models/account_invoice.py:28 |
||||
|
#, python-format |
||||
|
msgid "This invoice exceeds the financial risk.\n" |
||||
|
msgstr "Esta factura excede el riesgo financiero.\n" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: code:addons/partner_financial_risk/models/account_invoice.py:23 |
||||
|
#, python-format |
||||
|
msgid "This invoice exceeds the open invoices risk.\n" |
||||
|
msgstr "Esta factura excede el riesgo de facturas abiertas.\n" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_invoice_draft |
||||
|
msgid "Total Draft Invoices" |
||||
|
msgstr "Total facturas borrador" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_invoice_open |
||||
|
msgid "Total Open Invoices" |
||||
|
msgstr "Total facturas borrador abiertas" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_total |
||||
|
msgid "Total Risk" |
||||
|
msgstr "Riesgo total" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_invoice_unpaid |
||||
|
msgid "Total Unpaid Invoices" |
||||
|
msgstr "Total facturas impagadas" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_draft |
||||
|
msgid "Total amount of invoices in Draft or Pro-forma state" |
||||
|
msgstr "Importe total de facturas borrador o pro-forma" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model,name:partner_financial_risk.model_account_config_settings |
||||
|
msgid "account.config.settings" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_financial_risk |
||||
|
#: model:ir.model,name:partner_financial_risk.model_partner_risk_exceeded_wiz |
||||
|
msgid "partner.risk.exceeded.wiz" |
||||
|
msgstr "" |
@ -0,0 +1,6 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from . import account_invoice |
||||
|
from . import res_company |
||||
|
from . import res_config |
||||
|
from . import res_partner |
@ -0,0 +1,38 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from openerp import api, models, _ |
||||
|
|
||||
|
|
||||
|
class AccountInvoice(models.Model): |
||||
|
_inherit = 'account.invoice' |
||||
|
|
||||
|
@api.multi |
||||
|
def invoice_open(self): |
||||
|
if self.env.context.get('bypass_risk', False): |
||||
|
return self.signal_workflow('invoice_open') |
||||
|
for invoice in self: |
||||
|
partner = invoice.partner_id |
||||
|
exception_msg = "" |
||||
|
if partner.risk_exception: |
||||
|
exception_msg = _("Financial risk exceeded.\n") |
||||
|
elif partner.risk_invoice_open_limit and ( |
||||
|
(partner.risk_invoice_open + invoice.amount_total) > |
||||
|
partner.risk_invoice_open_limit): |
||||
|
exception_msg = _( |
||||
|
"This invoice exceeds the open invoices risk.\n") |
||||
|
elif partner.risk_invoice_open_include and ( |
||||
|
(partner.risk_total + invoice.amount_total) > |
||||
|
partner.credit_limit): |
||||
|
exception_msg = _( |
||||
|
"This invoice exceeds the financial risk.\n") |
||||
|
if exception_msg: |
||||
|
return self.env['partner.risk.exceeded.wiz'].create({ |
||||
|
'exception_msg': exception_msg, |
||||
|
'partner_id': partner.id, |
||||
|
'origin_reference': |
||||
|
'%s,%s' % (self._model, invoice.id), |
||||
|
'continue_method': 'invoice_open', |
||||
|
}).action_show() |
||||
|
return self.signal_workflow('invoice_open') |
@ -0,0 +1,13 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from openerp import fields, models |
||||
|
|
||||
|
|
||||
|
class ResCompany(models.Model): |
||||
|
_inherit = 'res.company' |
||||
|
|
||||
|
invoice_unpaid_margin = fields.Integer( |
||||
|
string="Maturity Margin", |
||||
|
help="Days after due date to set an invoice as unpaid") |
@ -0,0 +1,12 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from openerp import fields, models |
||||
|
|
||||
|
|
||||
|
class AccountConfigSettings(models.TransientModel): |
||||
|
_inherit = 'account.config.settings' |
||||
|
|
||||
|
invoice_unpaid_margin = fields.Integer( |
||||
|
related='company_id.invoice_unpaid_margin') |
@ -0,0 +1,150 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from datetime import datetime |
||||
|
from dateutil.relativedelta import relativedelta |
||||
|
from openerp import api, fields, models |
||||
|
|
||||
|
|
||||
|
class ResPartner(models.Model): |
||||
|
_inherit = 'res.partner' |
||||
|
|
||||
|
risk_invoice_draft_include = fields.Boolean( |
||||
|
string='Include Draft Invoices', help='Full risk computation') |
||||
|
risk_invoice_draft_limit = fields.Monetary( |
||||
|
string='Limit In Draft Invoices', help='Set 0 if it is not locked') |
||||
|
risk_invoice_draft = fields.Monetary( |
||||
|
compute='_compute_risk_invoice', store=True, |
||||
|
string='Total Draft Invoices', |
||||
|
help='Total amount of invoices in Draft or Pro-forma state') |
||||
|
risk_invoice_open_include = fields.Boolean( |
||||
|
string='Include Open Invoices', help='Full risk computation') |
||||
|
risk_invoice_open_limit = fields.Monetary( |
||||
|
string='Limit In Open Invoices', help='Set 0 if it is not locked') |
||||
|
risk_invoice_open = fields.Monetary( |
||||
|
compute='_compute_risk_invoice', store=True, |
||||
|
string='Total Open Invoices', |
||||
|
help='Residual amount of invoices in Open state and the date due is ' |
||||
|
'not exceeded, considering Due Margin set in account ' |
||||
|
'settings') |
||||
|
risk_invoice_unpaid_include = fields.Boolean( |
||||
|
string='Include Unpaid Invoices', help='Full risk computation') |
||||
|
risk_invoice_unpaid_limit = fields.Monetary( |
||||
|
string='Limit In Unpaid Invoices', help='Set 0 if it is not locked') |
||||
|
risk_invoice_unpaid = fields.Monetary( |
||||
|
compute='_compute_risk_invoice', store=True, |
||||
|
string='Total Unpaid Invoices', |
||||
|
help='Residual amount of invoices in Open state and the date due is ' |
||||
|
'exceeded, considering Unpaid Margin set in account settings') |
||||
|
|
||||
|
risk_account_amount_include = fields.Boolean( |
||||
|
string='Include Other Account Amount', help='Full risk computation') |
||||
|
risk_account_amount_limit = fields.Monetary( |
||||
|
string='Limit Other Account Amount', help='Set 0 if it is not locked') |
||||
|
risk_account_amount = fields.Monetary( |
||||
|
compute='_compute_risk_account_amount', |
||||
|
string='Other Account Amount', |
||||
|
help='Difference between accounting credit and rest of totals') |
||||
|
|
||||
|
risk_total = fields.Monetary( |
||||
|
compute='_compute_risk_exception', |
||||
|
string='Total Risk', help='Sum of total risk included') |
||||
|
risk_exception = fields.Boolean( |
||||
|
compute='_compute_risk_exception', |
||||
|
string='Risk Exception', |
||||
|
help='It Indicate if partner risk exceeded') |
||||
|
credit_policy = fields.Char() |
||||
|
risk_allow_edit = fields.Boolean(compute='_compute_risk_allow_edit') |
||||
|
|
||||
|
@api.multi |
||||
|
def _compute_risk_allow_edit(self): |
||||
|
is_editable = self.env.user.has_group( |
||||
|
'base.group_sale_manager') or self.env.user.has_group( |
||||
|
'account.group_account_manager') |
||||
|
for partner in self: |
||||
|
partner.risk_allow_edit = is_editable |
||||
|
|
||||
|
@api.multi |
||||
|
@api.depends('invoice_ids', 'invoice_ids.state', |
||||
|
'invoice_ids.amount_total', 'invoice_ids.residual', |
||||
|
'invoice_ids.company_id.invoice_unpaid_margin') |
||||
|
def _compute_risk_invoice(self): |
||||
|
max_date = self._max_risk_date_due() |
||||
|
for partner in self: |
||||
|
invoices_out = partner.invoice_ids.filtered( |
||||
|
lambda x: x.type == 'out_invoice') |
||||
|
invoices = invoices_out.filtered( |
||||
|
lambda x: x.state in ['draft', 'proforma', 'proforma2']) |
||||
|
partner.risk_invoice_draft = sum(invoices.mapped('amount_total')) |
||||
|
invoices = invoices_out.filtered( |
||||
|
lambda x: x.state == 'open' and x.date_due >= max_date) |
||||
|
partner.risk_invoice_open = sum(invoices.mapped('residual')) |
||||
|
invoices = invoices_out.filtered( |
||||
|
lambda x: x.state == 'open' and x.date_due < max_date) |
||||
|
partner.risk_invoice_unpaid = sum(invoices.mapped('residual')) |
||||
|
|
||||
|
@api.multi |
||||
|
@api.depends('credit', 'risk_invoice_open', 'risk_invoice_unpaid') |
||||
|
def _compute_risk_account_amount(self): |
||||
|
for partner in self: |
||||
|
partner.risk_account_amount = ( |
||||
|
partner.credit - partner.risk_invoice_open - |
||||
|
partner.risk_invoice_unpaid) |
||||
|
|
||||
|
@api.multi |
||||
|
@api.depends(lambda x: x._get_depends_compute_risk_exception()) |
||||
|
def _compute_risk_exception(self): |
||||
|
risk_field_list = self._risk_field_list() |
||||
|
for partner in self: |
||||
|
amount = 0.0 |
||||
|
for risk_field in risk_field_list: |
||||
|
field_value = getattr(partner, risk_field[0], 0.0) |
||||
|
max_value = getattr(partner, risk_field[1], 0.0) |
||||
|
if max_value and field_value > max_value: |
||||
|
partner.risk_exception = True |
||||
|
if getattr(partner, risk_field[2], False): |
||||
|
amount += field_value |
||||
|
partner.risk_total = amount |
||||
|
if amount > partner.credit_limit: |
||||
|
partner.risk_exception = True |
||||
|
|
||||
|
@api.model |
||||
|
def _max_risk_date_due(self): |
||||
|
return fields.Date.to_string(datetime.today().date() - relativedelta( |
||||
|
days=self.env.user.company_id.invoice_unpaid_margin)) |
||||
|
|
||||
|
@api.model |
||||
|
def _risk_field_list(self): |
||||
|
return [ |
||||
|
('risk_invoice_draft', 'risk_invoice_draft_limit', |
||||
|
'risk_invoice_draft_include'), |
||||
|
('risk_invoice_open', 'risk_invoice_open_limit', |
||||
|
'risk_invoice_open_include'), |
||||
|
('risk_invoice_unpaid', 'risk_invoice_unpaid_limit', |
||||
|
'risk_invoice_unpaid_include'), |
||||
|
('risk_account_amount', 'risk_account_amount_limit', |
||||
|
'risk_account_amount_include'), |
||||
|
] |
||||
|
|
||||
|
@api.model |
||||
|
def _get_depends_compute_risk_exception(self): |
||||
|
# TODO: Improve code without performance loss |
||||
|
tuple_list = self._risk_field_list() |
||||
|
res = [x[0] for x in tuple_list] |
||||
|
res.extend([x[1] for x in tuple_list]) |
||||
|
res.extend([x[2] for x in tuple_list]) |
||||
|
res.append('credit_limit') |
||||
|
return res |
||||
|
|
||||
|
@api.model |
||||
|
def process_unpaid_invoices(self): |
||||
|
today = fields.Date.today() |
||||
|
ConfigParameter = self.env['ir.config_parameter'] |
||||
|
last_check = ConfigParameter.get_param( |
||||
|
'partner_financial_risk.last_check', default='2016-01-01') |
||||
|
invoices = self.env['account.invoice'].search([ |
||||
|
('date_due', '>=', last_check), ('date_due', '<', today)]) |
||||
|
invoices.mapped('partner_id')._compute_risk_invoice() |
||||
|
ConfigParameter.set_param('partner_financial_risk.last_check', today) |
||||
|
return True |
@ -0,0 +1,3 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from . import test_partner_financial_risk |
@ -0,0 +1,79 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from openerp.tests.common import TransactionCase |
||||
|
from openerp import fields |
||||
|
|
||||
|
|
||||
|
class TestPartnerFinancialRisk(TransactionCase): |
||||
|
def setUp(self): |
||||
|
super(TestPartnerFinancialRisk, self).setUp() |
||||
|
self.env.user.groups_id |= self.env.ref('base.group_sale_manager') |
||||
|
self.partner = self.env['res.partner'].create({ |
||||
|
'name': 'Partner test', |
||||
|
'customer': True, |
||||
|
}) |
||||
|
self.journal = self.env['account.journal'].create({ |
||||
|
'type': 'sale', |
||||
|
'name': 'Test Sales', |
||||
|
'code': 'TSALE', |
||||
|
}) |
||||
|
self.prod_account = self.env.ref('account.demo_coffee_machine_account') |
||||
|
self.inv_account = self.env.ref('account.demo_sale_of_land_account') |
||||
|
self.invoice = self.env['account.invoice'].create({ |
||||
|
'journal_id': self.journal.id, |
||||
|
'company_id': self.env.user.company_id.id, |
||||
|
'currency_id': self.env.user.company_id.currency_id.id, |
||||
|
'partner_id': self.partner.id, |
||||
|
'invoice_line_ids': [(0, 0, { |
||||
|
'account_id': self.prod_account.id, |
||||
|
'name': 'Test line', |
||||
|
'price_unit': 50, |
||||
|
'quantity': 10, |
||||
|
})] |
||||
|
}) |
||||
|
|
||||
|
def test_invoices(self): |
||||
|
self.partner.risk_invoice_draft_include = True |
||||
|
self.assertAlmostEqual(self.partner.risk_invoice_draft, 500.0) |
||||
|
self.assertAlmostEqual(self.partner.risk_total, 500.0) |
||||
|
self.invoice.signal_workflow('invoice_open') |
||||
|
self.assertAlmostEqual(self.partner.risk_invoice_draft, 0.0) |
||||
|
self.assertFalse(self.invoice.date_due) |
||||
|
self.partner.risk_invoice_unpaid_include = True |
||||
|
self.assertAlmostEqual(self.partner.risk_total, 500.0) |
||||
|
self.partner.credit_limit = 100.0 |
||||
|
self.assertTrue(self.partner.risk_exception) |
||||
|
self.partner.credit_limit = 1000.0 |
||||
|
self.assertFalse(self.partner.risk_exception) |
||||
|
self.partner.risk_invoice_unpaid_limit = 499.0 |
||||
|
self.assertTrue(self.partner.risk_exception) |
||||
|
invoice2 = self.invoice.copy() |
||||
|
wiz_dic = invoice2.invoice_open() |
||||
|
wiz = self.env[wiz_dic['res_model']].browse(wiz_dic['res_id']) |
||||
|
self.assertEqual(wiz.exception_msg, "Financial risk exceeded.\n") |
||||
|
self.partner.risk_invoice_unpaid_limit = 0.0 |
||||
|
self.assertFalse(self.partner.risk_exception) |
||||
|
self.partner.risk_invoice_open_limit = 300.0 |
||||
|
invoice2.date_due = fields.Date.today() |
||||
|
wiz_dic = invoice2.invoice_open() |
||||
|
wiz = self.env[wiz_dic['res_model']].browse(wiz_dic['res_id']) |
||||
|
self.assertEqual(wiz.exception_msg, |
||||
|
"This invoice exceeds the open invoices risk.\n") |
||||
|
self.partner.risk_invoice_open_limit = 0.0 |
||||
|
self.partner.risk_invoice_draft_include = False |
||||
|
self.partner.risk_invoice_open_include = True |
||||
|
self.partner.credit_limit = 900.0 |
||||
|
wiz_dic = invoice2.invoice_open() |
||||
|
wiz = self.env[wiz_dic['res_model']].browse(wiz_dic['res_id']) |
||||
|
self.assertEqual(wiz.exception_msg, |
||||
|
"This invoice exceeds the financial risk.\n") |
||||
|
self.assertAlmostEqual(self.partner.risk_invoice_open, 0.0) |
||||
|
wiz.button_continue() |
||||
|
self.assertAlmostEqual(self.partner.risk_invoice_open, 500.0) |
||||
|
self.assertTrue(self.partner.risk_allow_edit) |
||||
|
self.partner.process_unpaid_invoices() |
||||
|
self.assertEqual(self.env['ir.config_parameter'].get_param( |
||||
|
'partner_financial_risk.last_check'), |
||||
|
fields.Date.today()) |
@ -0,0 +1,15 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl-3). --> |
||||
|
<odoo> |
||||
|
<record id="invoice_partner_risk_form" model="ir.ui.view"> |
||||
|
<field name="name">account.invoice.partner.risk.form</field> |
||||
|
<field name="model">account.invoice</field> |
||||
|
<field name="inherit_id" ref="account.invoice_form"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<button name="invoice_open" position="attributes"> |
||||
|
<attribute name="type">object</attribute> |
||||
|
</button> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,21 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl-3). --> |
||||
|
<odoo> |
||||
|
|
||||
|
<record id="view_account_config" model="ir.ui.view"> |
||||
|
<field name="name">account settings</field> |
||||
|
<field name="model">account.config.settings</field> |
||||
|
<field name="inherit_id" ref="account.view_account_config_settings"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//div[@name='payment_acquirer']/.." position="after"> |
||||
|
<label for="id" string="Financial Risk"/> |
||||
|
<div name="financial_risk" string="Financial Risk div"> |
||||
|
<label for="invoice_unpaid_margin"/> |
||||
|
<field name="invoice_unpaid_margin" class="oe_inline"/> |
||||
|
</div> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,58 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl-3). --> |
||||
|
<odoo> |
||||
|
<record id="res_partner_view_risk" model="ir.ui.view"> |
||||
|
<field name="name">res.partner.view.risk</field> |
||||
|
<field name="model">res.partner</field> |
||||
|
<field name="inherit_id" ref="base.view_partner_form" /> |
||||
|
<field name="priority" eval="20"/> |
||||
|
<field name="groups_id" eval="[(4, ref('base.group_sale_salesman')), (4, ref('account.group_account_manager'))]"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<page name="sales_purchases" position="after"> |
||||
|
<page name="financial_risk" string="Financial Risk" attrs="{'invisible': [('customer','=',False)]}"> |
||||
|
<group name="risk_general" col="3"> |
||||
|
<group string="General Limits" name="risk_include" col="1" colspan="2"> |
||||
|
<group col="3" class="oe_subtotal_footer"> |
||||
|
<field name="risk_invoice_draft_include" |
||||
|
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/> |
||||
|
<field name="risk_invoice_draft" nolabel="1"/> |
||||
|
<field name="risk_invoice_open_include" |
||||
|
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/> |
||||
|
<field name="risk_invoice_open" nolabel="1"/> |
||||
|
<field name="risk_invoice_unpaid_include" |
||||
|
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/> |
||||
|
<field name="risk_invoice_unpaid" nolabel="1"/> |
||||
|
<field name="risk_account_amount_include" |
||||
|
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/> |
||||
|
<field name="risk_account_amount" nolabel="1"/> |
||||
|
<field name="risk_total" colspan="3" class="oe_subtotal_footer_separator"/> |
||||
|
</group> |
||||
|
</group> |
||||
|
<group string="Specific Limits" name="risk_limits" col="1"> |
||||
|
<group class="oe_subtotal_footer"> |
||||
|
<field name="risk_invoice_draft_limit" |
||||
|
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/> |
||||
|
<field name="risk_invoice_open_limit" |
||||
|
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/> |
||||
|
<field name="risk_invoice_unpaid_limit" |
||||
|
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/> |
||||
|
<field name="risk_account_amount_limit" |
||||
|
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/> |
||||
|
<field name="risk_allow_edit" invisible="1"/> |
||||
|
</group> |
||||
|
</group> |
||||
|
</group> |
||||
|
<group string="Info" col="4"> |
||||
|
<field name="credit_limit" |
||||
|
widget="monetary" |
||||
|
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/> |
||||
|
<field name="credit_policy" |
||||
|
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/> |
||||
|
<field name="risk_exception"/> |
||||
|
</group> |
||||
|
</page> |
||||
|
</page> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,3 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from . import parner_risk_exceeded |
@ -0,0 +1,37 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from openerp import api, fields, models, _ |
||||
|
|
||||
|
|
||||
|
class PartnerRiskExceededWiz(models.TransientModel): |
||||
|
_name = 'partner.risk.exceeded.wiz' |
||||
|
|
||||
|
partner_id = fields.Many2one( |
||||
|
comodel_name='res.partner', readonly=True, string='Customer') |
||||
|
exception_msg = fields.Text(readonly=True) |
||||
|
origin_reference = fields.Reference( |
||||
|
lambda self: [ |
||||
|
(m.model, m.name) for m in self.env['ir.model'].search([])], |
||||
|
string='Object') |
||||
|
continue_method = fields.Char() |
||||
|
|
||||
|
@api.multi |
||||
|
def action_show(self): |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'name': _('Partner risk exceeded'), |
||||
|
'res_model': self._name, |
||||
|
'res_id': self.id, |
||||
|
'view_type': 'form', |
||||
|
'view_mode': 'form', |
||||
|
'target': 'new', |
||||
|
} |
||||
|
|
||||
|
@api.multi |
||||
|
def button_continue(self): |
||||
|
self.ensure_one() |
||||
|
return getattr(self.origin_reference.with_context( |
||||
|
bypass_risk=True), self.continue_method)() |
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl-3). --> |
||||
|
<odoo> |
||||
|
<record id="partner_risk_exceeded_wizard" model="ir.ui.view"> |
||||
|
<field name="name">Partner risk exceeded</field> |
||||
|
<field name="model">partner.risk.exceeded.wiz</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form string="Risk exceeded"> |
||||
|
<p>The partner has exceeded his risk</p> |
||||
|
<field name="exception_msg" colspan="2" nolabel="1"/> |
||||
|
<group> |
||||
|
<field name="partner_id"/> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button string="Continue" |
||||
|
class="oe_highlight" |
||||
|
name="button_continue" |
||||
|
type="object" |
||||
|
groups="base.group_sale_manager,account.group_account_manager" |
||||
|
/> |
||||
|
<button string="Cancel" |
||||
|
class="oe_link" |
||||
|
special="cancel" |
||||
|
/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue