Browse Source

[9.0][FIX] partner_financial_risk: Invoice refunds add risk. (#476)

* [9.0][FIX] partner_financial_risk: Invoice refunds add risk. Date_maturity change

* [9.0][FIX] partner_financial_risk: Recompute when invoice_unpaid_margin change

* [9.0][IMP] partner_financial_risk: Improve heritability

* [9.0][IMP] partner_payment_return_risk: Unify with base method and split amount

* [9.0][IMP] partner_financial_risk: Improve code. Include archived contacts

* [9.0][WIP] partner_financial_risk: Different model in read_group list

* [9.0][WIP] partner_financial_risk: Invoices amount from account.move.line

* [9.0][WIP] partner_financial_risk: Change "©" to Copyright

* [9.0][IMP] partner_financial_risk: invoice_unpaid_margin in depends

* [9.0][IMP] partner_financial_risk: Descriptions and translation
pull/499/head
Carlos Dauden 7 years ago
committed by Rafael Blasco
parent
commit
158bc9a051
  1. 4
      partner_financial_risk/__openerp__.py
  2. 4
      partner_financial_risk/data/partner_financial_risk_data.xml
  3. 205
      partner_financial_risk/i18n/es.po
  4. 2
      partner_financial_risk/models/account_invoice.py
  5. 6
      partner_financial_risk/models/res_company.py
  6. 2
      partner_financial_risk/models/res_config.py
  7. 214
      partner_financial_risk/models/res_partner.py
  8. 59
      partner_financial_risk/tests/test_partner_financial_risk.py
  9. 2
      partner_financial_risk/views/account_invoice_view.xml
  10. 2
      partner_financial_risk/views/res_config_view.xml
  11. 7
      partner_financial_risk/views/res_partner_view.xml
  12. 2
      partner_financial_risk/wizard/parner_risk_exceeded.py
  13. 2
      partner_financial_risk/wizard/partner_risk_exceeded_view.xml
  14. 2
      partner_payment_return_risk/README.rst
  15. 30
      partner_payment_return_risk/i18n/es.po
  16. 50
      partner_payment_return_risk/models/res_partner.py
  17. 83
      partner_payment_return_risk/tests/test_payment_return_risk.py
  18. 2
      partner_payment_return_risk/views/res_partner_view.xml

4
partner_financial_risk/__openerp__.py

@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 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.2',
'version': '9.0.2.0.0',
'category': 'Sales Management',
'license': 'AGPL-3',
'author': 'Tecnativa, Odoo Community Association (OCA)',

4
partner_financial_risk/data/partner_financial_risk_data.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
<!-- Copyright 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">
@ -12,4 +12,4 @@
<field name="function" eval="'process_unpaid_invoices'"/>
<field name="args" eval="'()'"/>
</record>
</odoo>
</odoo>

205
partner_financial_risk/i18n/es.po

@ -1,7 +1,7 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_financial_risk
#
#
# Translators:
# Carlos Dauden <carlos.dauden@tecnativa.com>, 2016
# Pedro M. Baeza <pedro.baeza@gmail.com>, 2017
@ -9,15 +9,22 @@ msgid ""
msgstr ""
"Project-Id-Version: partner-contact (9.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-01-06 03:40+0000\n"
"PO-Revision-Date: 2017-01-05 18:28+0000\n"
"Last-Translator: Pedro M. Baeza <pedro.baeza@gmail.com>\n"
"Language-Team: Spanish (http://www.transifex.com/oca/OCA-partner-contact-9-0/language/es/)\n"
"POT-Creation-Date: 2017-10-08 23:36+0200\n"
"PO-Revision-Date: 2017-10-08 23:39+0200\n"
"Last-Translator: Carlos Dauden <carlos.dauden@tecnativa.com>\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: \n"
"Language: es\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.7.1\n"
#. module: partner_financial_risk
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_move_line_ids
msgid "Account Moves"
msgstr "Apuntes contables"
#. module: partner_financial_risk
#: model:ir.ui.view,arch_db:partner_financial_risk.partner_risk_exceeded_wizard
@ -62,13 +69,13 @@ 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"
msgid ""
"Days after due date to set an invoice as unpaid.The change of this field "
"recompute all partners risk,be patient."
msgstr ""
"Días posteriores a la fecha de vencimiento para establecer una factura como "
"impagada. El cambio de este campo recalculará el riesgo de todos los "
"clientes, tenga paciencia."
#. module: partner_financial_risk
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz_display_name
@ -98,12 +105,64 @@ 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"
msgstr "Computar en riesgo total."
#. module: partner_financial_risk
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_account_amount_unpaid_include
msgid ""
"Full risk computation.\n"
"Residual amount of move lines not reconciled with distinct account that is "
"set as partner receivable and date maturity exceeded, considering Due Margin "
"set in account settings."
msgstr ""
"Computar en riesgo total.\n"
"Importe residual de apuntes no conciliados con cuenta distinta a la "
"establecida como cuenta a cobrar del cliente y fecha vencimiento excedida, "
"teniendo en cuenta los días de margen establecidos en la configuración de "
"contabilidad."
#. module: partner_financial_risk
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_account_amount_include
msgid ""
"Full risk computation.\n"
"Residual amount of move lines not reconciled with distinct account that is "
"set as partner receivable and date maturity not exceeded, considering Due "
"Margin set in account settings."
msgstr ""
"Computar en riesgo total.\n"
"Importe residual de apuntes no conciliados con cuenta distinta a la "
"establecida como cuenta a cobrar del cliente y fecha vencimiento no "
"excedida, teniendo en cuenta los días de margen establecidos en la "
"configuración de contabilidad."
#. module: partner_financial_risk
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_unpaid_include
msgid ""
"Full risk computation.\n"
"Residual amount of move lines not reconciled with the same account that is "
"set as partner receivable and date maturity exceeded, considering Due Margin "
"set in account settings."
msgstr ""
"Computar en riesgo total.\n"
"Importe residual de apuntes no conciliados con cuenta igual a la establecida "
"como cuenta a cobrar del cliente y fecha vencimiento excedida, teniendo en "
"cuenta los días de margen establecidos en la configuración de contabilidad."
#. module: partner_financial_risk
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_open_include
msgid ""
"Full risk computation.\n"
"Residual amount of move lines not reconciled with the same account that is "
"set as partner receivable and date maturity not exceeded, considering Due "
"Margin set in account settings."
msgstr ""
"Computar en riesgo total.\n"
"Importe residual de apuntes no conciliados con cuenta igual a la establecida "
"como cuenta a cobrar del cliente y fecha vencimiento no excedida, teniendo "
"en cuenta los días de margen establecidos en la configuración de "
"contabilidad."
#. module: partner_financial_risk
#: model:ir.ui.view,arch_db:partner_financial_risk.res_partner_view_risk
@ -122,18 +181,23 @@ 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"
msgid "Include Open Invoices/Principal Balance"
msgstr "Incluir facturas/saldo principal abierto"
#. 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"
msgid "Include Other Account Open Amount"
msgstr "Incluir otro saldo contable abierto"
#. module: partner_financial_risk
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_account_amount_unpaid_include
msgid "Include Other Account Unpaid Amount"
msgstr "Incluir otro saldo contable impagado"
#. 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"
msgid "Include Unpaid Invoices/Principal Balance"
msgstr "Incluir facturas/saldo principal impagado"
#. module: partner_financial_risk
#: model:ir.ui.view,arch_db:partner_financial_risk.res_partner_view_risk
@ -150,6 +214,11 @@ msgstr "Factura"
msgid "It Indicate if partner risk exceeded"
msgstr "Indica si se ha excedido el riesgo"
#. module: partner_financial_risk
#: model:ir.model,name:partner_financial_risk.model_account_move_line
msgid "Journal Item"
msgstr "Apunte contable"
#. module: partner_financial_risk
#: model:ir.model.fields,field_description:partner_financial_risk.field_partner_risk_exceeded_wiz___last_update
msgid "Last Modified on"
@ -172,18 +241,23 @@ 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"
msgid "Limit In Open Invoices/Principal Balance"
msgstr "Límite en factures/saldo principal abierto"
#. 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"
msgid "Limit In Unpaid Invoices/Principal Balance"
msgstr "Límite en factures/saldo principal impagado"
#. 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"
msgid "Limit Other Account Open Amount"
msgstr "Límite en otro saldo contable abierto"
#. module: partner_financial_risk
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_account_amount_unpaid_limit
msgid "Limit Other Account Unpaid Amount"
msgstr "Límite en otro saldo contable impagado"
#. module: partner_financial_risk
#: model:ir.model.fields,field_description:partner_financial_risk.field_account_config_settings_invoice_unpaid_margin
@ -196,11 +270,6 @@ msgstr "Margen vencimiento"
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"
@ -212,19 +281,52 @@ msgstr "Empresa"
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_account_amount_unpaid
msgid ""
"Residual amount of move lines not reconciled with distinct account that is "
"set as partner receivable and date maturity exceeded, considering Due Margin "
"set in account settings."
msgstr ""
"Importe residual de apuntes no conciliados con cuenta distinta a la "
"establecida como cuenta a cobrar del cliente y fecha vencimiento excedida, "
"teniendo en cuenta los días de margen establecidos en la configuración de "
"contabilidad."
#. module: partner_financial_risk
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_account_amount
msgid ""
"Residual amount of move lines not reconciled with distinct account that is "
"set as partner receivable and date maturity not exceeded, considering Due "
"Margin set in account settings."
msgstr ""
"Importe residual de apuntes no conciliados con cuenta distinta a la "
"establecida como cuenta a cobrar del cliente y fecha vencimiento no "
"excedida, teniendo en cuenta los días de margen establecidos en la "
"configuración de contabilidad."
#. 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"
"Residual amount of move lines not reconciled with the same account that is "
"set as partner receivable and date maturity exceeded, considering Due Margin "
"set in account settings."
msgstr ""
"Importe residual de apuntes no conciliados con cuenta igual a la establecida "
"como cuenta a cobrar del cliente y fecha vencimiento excedida, teniendo en "
"cuenta los días de margen establecidos en la 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"
"Residual amount of move lines not reconciled with the same account that is "
"set as partner receivable and date maturity not exceeded, considering Due "
"Margin set in account settings."
msgstr ""
"Importe residual de apuntes no conciliados con cuenta igual a la establecida "
"como cuenta a cobrar del cliente y fecha vencimiento no excedida, teniendo "
"en cuenta los días de margen establecidos en la configuración de "
"contabilidad."
#. module: partner_financial_risk
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_exception
@ -243,6 +345,7 @@ 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_account_amount_unpaid_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
@ -265,7 +368,7 @@ 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
#: code:addons/partner_financial_risk/models/account_invoice.py:30
#, python-format
msgid "This invoice exceeds the financial risk.\n"
msgstr "Esta factura excede el riesgo financiero.\n"
@ -283,8 +386,18 @@ 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"
msgid "Total Open Invoices/Principal Balance"
msgstr "Total facturas/saldo principal abierto"
#. module: partner_financial_risk
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_account_amount
msgid "Total Other Account Open Amount"
msgstr "Total otro saldo contable abierto"
#. module: partner_financial_risk
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_account_amount_unpaid
msgid "Total Other Account Unpaid Amount"
msgstr "Total otro saldo contable impagado"
#. module: partner_financial_risk
#: model:ir.model.fields,field_description:partner_financial_risk.field_res_partner_risk_total
@ -293,8 +406,8 @@ 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"
msgid "Total Unpaid Invoices/Principal Balance"
msgstr "Total facturas/saldo principal impagado"
#. module: partner_financial_risk
#: model:ir.model.fields,help:partner_financial_risk.field_res_partner_risk_invoice_draft

2
partner_financial_risk/models/account_invoice.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import api, models, _

6
partner_financial_risk/models/res_company.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import fields, models
@ -10,4 +10,6 @@ class ResCompany(models.Model):
invoice_unpaid_margin = fields.Integer(
string="Maturity Margin",
help="Days after due date to set an invoice as unpaid")
help="Days after due date to set an invoice as unpaid."
"The change of this field recompute all partners risk,"
"be patient.")

2
partner_financial_risk/models/res_config.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import fields, models

214
partner_financial_risk/models/res_partner.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import datetime
@ -10,6 +10,11 @@ from openerp import api, fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
move_line_ids = fields.One2many(
comodel_name='account.move.line',
inverse_name='partner_id',
string='Account Moves'
)
risk_invoice_draft_include = fields.Boolean(
string='Include Draft Invoices', help='Full risk computation')
risk_invoice_draft_limit = fields.Monetary(
@ -18,34 +23,68 @@ class ResPartner(models.Model):
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')
string='Include Open Invoices/Principal Balance',
help='Full risk computation.\n'
'Residual amount of move lines not reconciled with the same '
'account that is set as partner receivable and date maturity '
'not exceeded, considering Due Margin set in account settings.')
risk_invoice_open_limit = fields.Monetary(
string='Limit In Open Invoices', help='Set 0 if it is not locked')
string='Limit In Open Invoices/Principal Balance',
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')
compute='_compute_risk_account_amount', store=True,
string='Total Open Invoices/Principal Balance',
help='Residual amount of move lines not reconciled with the same '
'account that is set as partner receivable and date maturity '
'not exceeded, considering Due Margin set in account settings.')
risk_invoice_unpaid_include = fields.Boolean(
string='Include Unpaid Invoices', help='Full risk computation')
string='Include Unpaid Invoices/Principal Balance',
help='Full risk computation.\n'
'Residual amount of move lines not reconciled with the same '
'account that is set as partner receivable and date maturity '
'exceeded, considering Due Margin set in account settings.')
risk_invoice_unpaid_limit = fields.Monetary(
string='Limit In Unpaid Invoices', help='Set 0 if it is not locked')
string='Limit In Unpaid Invoices/Principal Balance',
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')
compute='_compute_risk_account_amount', store=True,
string='Total Unpaid Invoices/Principal Balance',
help='Residual amount of move lines not reconciled with the same '
'account that is set as partner receivable and date maturity '
'exceeded, considering Due Margin set in account settings.')
risk_account_amount_include = fields.Boolean(
string='Include Other Account Amount', help='Full risk computation')
string='Include Other Account Open Amount',
help='Full risk computation.\n'
'Residual amount of move lines not reconciled with distinct '
'account that is set as partner receivable and date maturity '
'not exceeded, considering Due Margin set in account settings.')
risk_account_amount_limit = fields.Monetary(
string='Limit Other Account Amount', help='Set 0 if it is not locked')
string='Limit Other Account Open 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')
compute='_compute_risk_account_amount', store=True,
string='Total Other Account Open Amount',
help='Residual amount of move lines not reconciled with distinct '
'account that is set as partner receivable and date maturity '
'not exceeded, considering Due Margin set in account settings.')
risk_account_amount_unpaid_include = fields.Boolean(
string='Include Other Account Unpaid Amount',
help='Full risk computation.\n'
'Residual amount of move lines not reconciled with distinct '
'account that is set as partner receivable and date maturity '
'exceeded, considering Due Margin set in account settings.')
risk_account_amount_unpaid_limit = fields.Monetary(
string='Limit Other Account Unpaid Amount',
help='Set 0 if it is not locked')
risk_account_amount_unpaid = fields.Monetary(
compute='_compute_risk_account_amount', store=True,
string='Total Other Account Unpaid Amount',
help='Residual amount of move lines not reconciled with distinct '
'account that is set as partner receivable and date maturity '
'exceeded, considering Due Margin set in account settings.')
risk_total = fields.Monetary(
compute='_compute_risk_exception',
@ -67,53 +106,94 @@ class ResPartner(models.Model):
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',
'child_ids.invoice_ids', 'child_ids.invoice_ids.state',
'child_ids.invoice_ids.amount_total',
'child_ids.invoice_ids.residual',
'child_ids.invoice_ids.company_id.invoice_unpaid_margin')
@api.depends(
'invoice_ids', 'invoice_ids.state',
'invoice_ids.amount_total',
'child_ids.invoice_ids', 'child_ids.invoice_ids.state',
'child_ids.invoice_ids.amount_total')
def _compute_risk_invoice(self):
def sum_group(group, field):
return sum([x[field] for x in group if
x['partner_id'][0] in partner_ids])
customers = self.filtered('customer')
if not customers:
all_partners_and_children = {}
all_partner_ids = []
for partner in self.filtered('customer'):
all_partners_and_children[partner] = self.with_context(
active_test=False).search([('id', 'child_of', partner.id)]).ids
all_partner_ids += all_partners_and_children[partner]
if not all_partner_ids:
return # pragma: no cover
max_date = self._max_risk_date_due()
AccountInvoice = self.env['account.invoice']
partners = customers | customers.mapped('child_ids')
domain = [('type', 'in', ['out_invoice', 'out_refund']),
('partner_id', 'in', partners.ids)]
draft_group = AccountInvoice.read_group(
domain + [('state', 'in', ['draft', 'proforma', 'proforma2'])],
total_group = self.env['account.invoice'].sudo().read_group(
[('type', 'in', ['out_invoice', 'out_refund']),
('state', 'in', ['draft', 'proforma', 'proforma2']),
('partner_id', 'in', self.ids)],
['partner_id', 'amount_total'],
['partner_id'])
open_group = AccountInvoice.read_group(
domain + [('state', '=', 'open'), ('date_due', '>=', max_date)],
['partner_id', 'residual'],
['partner_id'])
unpaid_group = AccountInvoice.read_group(
domain + [('state', '=', 'open'), '|',
('date_due', '=', False), ('date_due', '<', max_date)],
['partner_id', 'residual'],
['partner_id'])
for partner in customers:
partner_ids = (partner | partner.child_ids).ids
partner.risk_invoice_draft = sum_group(draft_group, 'amount_total')
partner.risk_invoice_open = sum_group(open_group, 'residual')
partner.risk_invoice_unpaid = sum_group(unpaid_group, 'residual')
for partner, child_ids in all_partners_and_children.items():
partner.risk_invoice_draft = sum(
x['amount_total']
for x in total_group if x['partner_id'][0] in child_ids)
@api.model
def _risk_account_groups(self):
max_date = self._max_risk_date_due()
return {
'open': {
'domain': [('reconciled', '=', False),
('account_id.internal_type', '=', 'receivable'),
('date_maturity', '>=', max_date)],
'fields': ['partner_id', 'account_id', 'amount_residual'],
'group_by': ['partner_id', 'account_id']
},
'unpaid': {
'domain': [('reconciled', '=', False),
('account_id.internal_type', '=', 'receivable'),
('date_maturity', '<', max_date)],
'fields': ['partner_id', 'account_id', 'amount_residual'],
'group_by': ['partner_id', 'account_id']
}
}
@api.multi
@api.depends('credit', 'risk_invoice_open', 'risk_invoice_unpaid',
'child_ids.credit', 'child_ids.risk_invoice_open',
'child_ids.risk_invoice_unpaid')
@api.depends('move_line_ids.amount_residual',
'move_line_ids.date_maturity',
'company_id.invoice_unpaid_margin')
def _compute_risk_account_amount(self):
for partner in self.filtered('customer'):
partner.risk_account_amount = (
partner.credit - partner.risk_invoice_open -
partner.risk_invoice_unpaid)
AccountMoveLine = self.env['account.move.line'].sudo()
customers = self.filtered(lambda x: x.customer and not x.parent_id)
if not customers:
return
groups = self._risk_account_groups()
for key, group in groups.iteritems():
group['read_group'] = AccountMoveLine.read_group(
group['domain'] + [('partner_id', 'in', customers.ids)],
group['fields'],
group['group_by'],
lazy=False,
)
for partner in customers:
partner.update(partner._prepare_risk_account_vals(groups))
@api.multi
def _prepare_risk_account_vals(self, groups):
vals = {
'risk_invoice_open': 0.0,
'risk_invoice_unpaid': 0.0,
'risk_account_amount': 0.0,
'risk_account_amount_unpaid': 0.0,
}
for reg in groups['open']['read_group']:
if reg['partner_id'][0] != self.id:
continue
if self.property_account_receivable_id.id == reg['account_id'][0]:
vals['risk_invoice_open'] += reg['amount_residual']
else:
vals['risk_account_amount'] += reg['amount_residual']
for reg in groups['unpaid']['read_group']:
if reg['partner_id'][0] != self.id:
continue # pragma: no cover
if self.property_account_receivable_id.id == reg['account_id'][0]:
vals['risk_invoice_unpaid'] += reg['amount_residual']
else:
vals['risk_account_amount_unpaid'] += reg['amount_residual']
return vals
@api.multi
@api.depends(lambda x: x._get_depends_compute_risk_exception())
@ -148,6 +228,8 @@ class ResPartner(models.Model):
'risk_invoice_unpaid_include'),
('risk_account_amount', 'risk_account_amount_limit',
'risk_account_amount_include'),
('risk_account_amount_unpaid', 'risk_account_amount_unpaid_limit',
'risk_account_amount_unpaid_include'),
]
@api.model
@ -161,12 +243,16 @@ class ResPartner(models.Model):
@api.model
def process_unpaid_invoices(self):
today = fields.Date.today()
max_date = self._max_risk_date_due()
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)
move_lines = self.env['account.move.line'].search([
('reconciled', '=', False),
('account_id.internal_type', '=', 'receivable'),
('date_maturity', '>=', last_check),
('date_maturity', '<', max_date)])
move_lines.mapped('partner_id')._compute_risk_account_amount()
ConfigParameter.set_param(
'partner_financial_risk.last_check', max_date)
return True

59
partner_financial_risk/tests/test_partner_financial_risk.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp.tests.common import SavepointCase
@ -11,17 +11,8 @@ class TestPartnerFinancialRisk(SavepointCase):
def setUpClass(cls):
super(TestPartnerFinancialRisk, cls).setUpClass()
cls.env.user.groups_id |= cls.env.ref('base.group_sale_manager')
cls.partner = cls.env['res.partner'].create({
'name': 'Partner test',
'customer': True,
})
cls.invoice_address = cls.env['res.partner'].create({
'name': 'Partner test invoice',
'parent_id': cls.partner.id,
'type': 'invoice',
})
type_revenue = cls.env.ref('account.data_account_type_revenue')
type_payable = cls.env.ref('account.data_account_type_payable')
type_receivable = cls.env.ref('account.data_account_type_receivable')
tax_group_taxes = cls.env.ref('account.tax_group_taxes')
cls.account_sale = cls.env['account.account'].create({
'name': 'Sale',
@ -32,9 +23,25 @@ class TestPartnerFinancialRisk(SavepointCase):
cls.account_customer = cls.env['account.account'].create({
'name': 'Customer',
'code': 'XX_430',
'user_type_id': type_payable.id,
'user_type_id': type_receivable.id,
'reconcile': True,
})
cls.other_account_customer = cls.env['account.account'].create({
'name': 'Other Account Customer',
'code': 'XX_431',
'user_type_id': type_receivable.id,
'reconcile': True,
})
cls.partner = cls.env['res.partner'].create({
'name': 'Partner test',
'customer': True,
'property_account_receivable_id': cls.account_customer.id,
})
cls.invoice_address = cls.env['res.partner'].create({
'name': 'Partner test invoice',
'parent_id': cls.partner.id,
'type': 'invoice',
})
cls.journal_sale = cls.env['account.journal'].create({
'name': 'Test journal for sale',
'type': 'sale',
@ -70,7 +77,8 @@ class TestPartnerFinancialRisk(SavepointCase):
self.assertAlmostEqual(self.partner.risk_total, 550.0)
self.invoice.signal_workflow('invoice_open')
self.assertAlmostEqual(self.partner.risk_invoice_draft, 0.0)
self.assertFalse(self.invoice.date_due)
line = self.invoice.move_id.line_ids.filtered(lambda x: x.debit != 0.0)
line.date_maturity = '2017-01-01'
self.partner.risk_invoice_unpaid_include = True
self.assertAlmostEqual(self.partner.risk_total, 550.0)
self.partner.credit_limit = 100.0
@ -109,3 +117,28 @@ class TestPartnerFinancialRisk(SavepointCase):
self.assertEqual(self.env['ir.config_parameter'].get_param(
'partner_financial_risk.last_check'),
fields.Date.today())
def test_other_account_amount(self):
self.move = self.env['account.move'].create({
'journal_id': self.journal_sale.id,
'date': fields.Date.today(),
'line_ids': [
(0, 0, {
'name': 'Debit line',
'partner_id': self.partner.id,
'account_id': self.other_account_customer.id,
'debit': 100,
}),
(0, 0, {
'name': 'Credit line',
'partner_id': self.partner.id,
'account_id': self.account_sale.id,
'credit': 100,
}),
],
})
self.assertAlmostEqual(self.partner.risk_account_amount, 100.0)
line = self.move.line_ids.filtered(lambda x: x.debit != 0.0)
line.date_maturity = '2017-01-01'
self.assertAlmostEqual(self.partner.risk_account_amount, 0.0)
self.assertAlmostEqual(self.partner.risk_account_amount_unpaid, 100.0)

2
partner_financial_risk/views/account_invoice_view.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
<!-- Copyright 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">

2
partner_financial_risk/views/res_config_view.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
<!-- Copyright 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl-3). -->
<odoo>

7
partner_financial_risk/views/res_partner_view.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
<!-- Copyright 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">
@ -26,6 +26,9 @@
<field name="risk_account_amount_include"
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/>
<field name="risk_account_amount" nolabel="1"/>
<field name="risk_account_amount_unpaid_include"
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/>
<field name="risk_account_amount_unpaid" nolabel="1"/>
<field name="risk_total" colspan="3" class="oe_subtotal_footer_separator"/>
</group>
</group>
@ -39,6 +42,8 @@
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/>
<field name="risk_account_amount_limit"
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/>
<field name="risk_account_amount_unpaid_limit"
attrs="{'readonly': [('risk_allow_edit', '=', False)]}"/>
<field name="risk_allow_edit" invisible="1"/>
</group>
</group>

2
partner_financial_risk/wizard/parner_risk_exceeded.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 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, _

2
partner_financial_risk/wizard/partner_risk_exceeded_view.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
<!-- Copyright 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">

2
partner_payment_return_risk/README.rst

@ -63,4 +63,4 @@ 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.
To contribute to this module, please visit https://odoo-community.org.

30
partner_payment_return_risk/i18n/es.po

@ -6,21 +6,25 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-01-10 18:34+0100\n"
"PO-Revision-Date: 2017-01-10 18:40+0100\n"
"POT-Creation-Date: 2017-10-08 23:50+0200\n"
"PO-Revision-Date: 2017-10-08 23:53+0200\n"
"Last-Translator: Carlos Dauden <carlos.dauden@tecnativa.com>\n"
"Language-Team: \n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.7.1\n"
"Last-Translator: Carlos Dauden <carlos.dauden@tecnativa.com>\n"
"Language: es_ES\n"
#. module: partner_payment_return_risk
#: model:ir.model.fields,help:partner_payment_return_risk.field_res_partner_risk_payment_return_include
msgid "Full risk computation"
msgstr "Cálculo de riesgo completo"
msgid ""
"Full risk computation.\n"
"Residual amount of move lines not reconciled with returned lines related."
msgstr ""
"Computar en riesgo total.\n"
"Importe residual de apuntes no conciliados relacionados con apuntes devueltos."
#. module: partner_payment_return_risk
#: model:ir.model.fields,field_description:partner_payment_return_risk.field_res_partner_risk_payment_return_include
@ -37,6 +41,11 @@ msgstr "Límite en pagos devueltos"
msgid "Partner"
msgstr "Empresa"
#. module: partner_payment_return_risk
#: model:ir.model.fields,help:partner_payment_return_risk.field_res_partner_risk_payment_return
msgid "Residual amount of move lines not reconciled with returned lines related."
msgstr "Importe residual de apuntes no conciliados relacionados con apuntes devueltos."
#. module: partner_payment_return_risk
#: model:ir.model.fields,help:partner_payment_return_risk.field_res_partner_risk_payment_return_limit
msgid "Set 0 if it is not locked"
@ -44,10 +53,5 @@ msgstr "Establece 0 si no está bloqueado"
#. module: partner_payment_return_risk
#: model:ir.model.fields,field_description:partner_payment_return_risk.field_res_partner_risk_payment_return
msgid "Total Returned Invoices"
msgstr "Total facturas devueltas"
#. module: partner_payment_return_risk
#: model:ir.model.fields,help:partner_payment_return_risk.field_res_partner_risk_payment_return
msgid "Total returned invoices in Open state"
msgstr "Total facturas devueltas en estado abierto"
msgid "Total Payments Returns"
msgstr "Total pagos devueltos"

50
partner_payment_return_risk/models/res_partner.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 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
@ -9,27 +9,43 @@ class ResPartner(models.Model):
_inherit = 'res.partner'
risk_payment_return_include = fields.Boolean(
string='Include Payments Returns', help='Full risk computation')
string='Include Payments Returns',
help='Full risk computation.\n'
'Residual amount of move lines not reconciled with returned '
'lines related.')
risk_payment_return_limit = fields.Monetary(
string='Limit Payments Returns', help='Set 0 if it is not locked')
risk_payment_return = fields.Monetary(
compute='_compute_risk_payment_return', store=True,
string='Total Returned Invoices',
help='Total returned invoices in Open state')
compute='_compute_risk_account_amount', store=True,
string='Total Payments Returns',
help='Residual amount of move lines not reconciled with returned '
'lines related.')
@api.model
def _risk_account_groups(self):
res = super(ResPartner, self)._risk_account_groups()
res['open']['domain'] += [
('partial_reconcile_returned_ids', '=', False),
]
res['unpaid']['domain'] += [
('partial_reconcile_returned_ids', '=', False),
]
res['returned'] = {
'domain': [('reconciled', '=', False),
('account_id.internal_type', '=', 'receivable'),
('partial_reconcile_returned_ids', '!=', False)],
'fields': ['partner_id', 'account_id', 'amount_residual'],
'group_by': ['partner_id', 'account_id']
}
return res
@api.multi
@api.depends('invoice_ids.state', 'invoice_ids.returned_payment')
def _compute_risk_payment_return(self):
AccountInvoice = self.env['account.invoice']
for partner in self:
partner.risk_payment_return = AccountInvoice.read_group(
[('partner_id', '=', partner.id),
('returned_payment', '=', True),
('state', '=', 'open'),
],
['residual'],
[]
)[0]['residual']
def _prepare_risk_account_vals(self, groups):
vals = super(ResPartner, self)._prepare_risk_account_vals(groups)
vals['risk_payment_return'] = sum(
reg['amount_residual'] for reg in groups['returned']['read_group']
if reg['partner_id'][0] == self.id)
return vals
@api.model
def _risk_field_list(self):

83
partner_payment_return_risk/tests/test_payment_return_risk.py

@ -6,33 +6,80 @@ from openerp.tests import common
class TestPartnerPaymentReturnRisk(common.SavepointCase):
@classmethod
def setUpClass(cls):
super(TestPartnerPaymentReturnRisk, cls).setUpClass()
cls.partner = cls.env['res.partner'].create({
'name': 'Test partner',
'risk_payment_return_include': True,
'risk_payment_return_limit': 50.0,
cls.journal = cls.env['account.journal'].create({
'name': 'Test Sales Journal',
'code': 'tVEN',
'type': 'sale',
'update_posted': True,
})
cls.bank_journal = cls.env['account.journal'].create({
'name': 'Test Bank Journal',
'code': 'BANK',
'type': 'bank',
'update_posted': True,
})
cls.account_type = cls.env['account.account.type'].create({
'name': 'Test',
'type': 'receivable',
})
cls.account = cls.env['account.account'].create({
'name': 'Test account',
'code': 'TEST',
'user_type_id': cls.account_type.id,
'reconcile': True,
})
cls.user_type = cls.env.ref('account.data_account_type_revenue')
cls.account_income = cls.env['account.account'].create({
'name': 'Test income account',
'code': 'INCOME',
'user_type_id': cls.env['account.account.type'].create(
{'name': 'Test income'}).id,
})
cls.partner = cls.env['res.partner'].create({'name': 'Test'})
cls.invoice = cls.env['account.invoice'].create({
'journal_id': cls.journal.id,
'account_id': cls.account.id,
'company_id': cls.env.user.company_id.id,
'currency_id': cls.env.user.company_id.currency_id.id,
'partner_id': cls.partner.id,
'invoice_line_ids': [(0, 0, {
'name': 'Product Test',
'quantity': 1.0,
'uom_id': cls.env.ref('product.product_uom_unit').id,
'price_unit': 100.0,
'account_id': cls.env['account.account'].search([
('user_type_id', '=', cls.user_type.id)], limit=1).id,
'account_id': cls.account_income.id,
'name': 'Test line',
'price_unit': 50,
'quantity': 10,
})]
})
cls.reason = cls.env['payment.return.reason'].create({
'code': 'RTEST',
'name': 'Reason Test'
})
cls.invoice.signal_workflow('invoice_open')
cls.receivable_line = cls.invoice.move_id.line_ids.filtered(
lambda x: x.account_id.internal_type == 'receivable')
# Invert the move to simulate the payment
cls.payment_move = cls.invoice.move_id.copy({
'journal_id': cls.bank_journal.id
})
for move_line in cls.payment_move.line_ids:
move_line.with_context(check_move_validity=False).write({
'debit': move_line.credit, 'credit': move_line.debit})
cls.payment_line = cls.payment_move.line_ids.filtered(
lambda x: x.account_id.internal_type == 'receivable')
# Reconcile both
(cls.receivable_line | cls.payment_line).reconcile()
# Create payment return
cls.payment_return = cls.env['payment.return'].create(
{'journal_id': cls.bank_journal.id,
'line_ids': [
(0, 0, {'partner_id': cls.partner.id,
'move_line_ids': [(6, 0, cls.payment_line.ids)],
'amount': cls.payment_line.credit})]})
def test_payment_return_risk(self):
self.invoice.signal_workflow('invoice_open')
# Partner risk is zero because invoice is not returned
self.assertAlmostEqual(self.partner.risk_payment_return, 0.0)
# We simulate that the invoice is returned
self.invoice.returned_payment = True
# Partner risk has increased
self.assertAlmostEqual(self.partner.risk_payment_return, 100.0)
self.payment_return.action_confirm()
self.assertAlmostEqual(self.partner.risk_payment_return, 500.0)
self.payment_return.action_cancel()
self.assertAlmostEqual(self.partner.risk_payment_return, 0.0)

2
partner_payment_return_risk/views/res_partner_view.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
<!-- Copyright 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">

Loading…
Cancel
Save