From c088caf5d7f73dbb3384a90104fac0e30e1dd291 Mon Sep 17 00:00:00 2001 From: Andhitia Rama Date: Sat, 30 Dec 2017 14:40:21 +0700 Subject: [PATCH] [8.0.2.0.0] partner_financial_risk Various improvement: 1. Fix error when risk_total includes draft_invoices 2. Include Refund 3. Compute partner hierarchy 4. Add track visibility to credit limit Improvement from: * ee89a30f1f8f20562f54094d5b7b578451788cd7 * f2237b71bcf42f43e27fa77669a0e703c6960c84 * 63abcfb51909d76dfd2add7342258fb23c9cd4a3 * 1e038ee7481f995b8b69975ede9fa0bca9b1d21a * 158bc9a0513de3e03a4c5af6ba35c38c6729e705 --- partner_financial_risk/__openerp__.py | 2 +- .../models/account_invoice.py | 6 +- partner_financial_risk/models/res_company.py | 4 +- partner_financial_risk/models/res_partner.py | 70 ++++++++++++------- 4 files changed, 54 insertions(+), 28 deletions(-) diff --git a/partner_financial_risk/__openerp__.py b/partner_financial_risk/__openerp__.py index 9064e1e89..76cd03a9b 100644 --- a/partner_financial_risk/__openerp__.py +++ b/partner_financial_risk/__openerp__.py @@ -5,7 +5,7 @@ { 'name': 'Partner Financial Risk', 'summary': 'Manage partner risk', - 'version': '8.0.1.1.0', + 'version': '8.0.2.0.0', 'category': 'Sales Management', 'license': 'AGPL-3', 'author': 'Tecnativa, ' diff --git a/partner_financial_risk/models/account_invoice.py b/partner_financial_risk/models/account_invoice.py index 179fccdcb..657b3b957 100644 --- a/partner_financial_risk/models/account_invoice.py +++ b/partner_financial_risk/models/account_invoice.py @@ -13,7 +13,7 @@ class AccountInvoice(models.Model): if self.env.context.get('bypass_risk', False): return self.signal_workflow('invoice_open') for invoice in self: - partner = invoice.partner_id + partner = invoice.partner_id.commercial_partner_id exception_msg = "" if partner.risk_exception: exception_msg = _("Financial risk exceeded.\n") @@ -22,7 +22,9 @@ class AccountInvoice(models.Model): partner.risk_invoice_open_limit): exception_msg = _( "This invoice exceeds the open invoices risk.\n") - elif partner.risk_invoice_open_include and ( + # If risk_invoice_draft_include this invoice included in risk_total + elif not partner.risk_invoice_draft_include and ( + partner.risk_invoice_open_include and (partner.risk_total + invoice.amount_total) > partner.credit_limit): exception_msg = _( diff --git a/partner_financial_risk/models/res_company.py b/partner_financial_risk/models/res_company.py index 5cc6da9a2..b48a87da0 100644 --- a/partner_financial_risk/models/res_company.py +++ b/partner_financial_risk/models/res_company.py @@ -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.") diff --git a/partner_financial_risk/models/res_partner.py b/partner_financial_risk/models/res_partner.py index 7a6900303..4d2ecd777 100644 --- a/partner_financial_risk/models/res_partner.py +++ b/partner_financial_risk/models/res_partner.py @@ -56,38 +56,61 @@ class ResPartner(models.Model): help='It Indicate if partner risk exceeded') credit_policy = fields.Char() risk_allow_edit = fields.Boolean(compute='_compute_risk_allow_edit') + credit_limit = fields.Float(track_visibility='onchange') @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: + for partner in self.filtered('customer'): 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') + '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') 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: + return # pragma: no cover 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')) + 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'])], + ['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') @api.multi - @api.depends('credit', 'risk_invoice_open', 'risk_invoice_unpaid') + @api.depends('credit', 'risk_invoice_open', 'risk_invoice_unpaid', + 'child_ids.credit', 'child_ids.risk_invoice_open', + 'child_ids.risk_invoice_unpaid') def _compute_risk_account_amount(self): - for partner in self: + for partner in self.filtered('customer'): partner.risk_account_amount = ( partner.credit - partner.risk_invoice_open - partner.risk_invoice_unpaid) @@ -96,7 +119,7 @@ class ResPartner(models.Model): @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: + for partner in self.filtered('customer'): amount = 0.0 for risk_field in risk_field_list: field_value = getattr(partner, risk_field[0], 0.0) @@ -106,7 +129,7 @@ class ResPartner(models.Model): if getattr(partner, risk_field[2], False): amount += field_value partner.risk_total = amount - if amount > partner.credit_limit: + if partner.credit_limit and amount > partner.credit_limit: partner.risk_exception = True @api.model @@ -129,12 +152,11 @@ class ResPartner(models.Model): @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') + res = [] + for x in self._risk_field_list(): + res.extend((x[0], x[1], x[2], 'child_ids.%s' % x[0], + 'child_ids.%s' % x[1], 'child_ids.%s' % x[2])) + res.extend(('credit_limit', 'child_ids.credit_limit')) return res @api.model