From d45aea61c3ee689ed1dc1808a772aff0cb7f94ec Mon Sep 17 00:00:00 2001 From: Matias Peralta Date: Tue, 1 Jul 2025 16:37:31 -0300 Subject: [PATCH 1/4] Revert "[MIG] sale_exception_credit_limit: Migration to 18.0" This reverts commit 31220a22ecef4fbff22eed15f1a3925ba08e52ff. --- .vscode/settings.json | 3 ++ portal_sale_distributor/.vscode/settings.json | 3 ++ sale_exception_credit_limit/README.rst | 7 +++ .../models/__init__.py | 1 + .../models/account_move.py | 47 ++++++++++++++++++ .../models/res_partner.py | 49 ++++++++++++++----- .../views/res_partner_views.xml | 9 ++++ sale_ux/.vscode/settings.json | 3 ++ 8 files changed, 111 insertions(+), 11 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 portal_sale_distributor/.vscode/settings.json create mode 100644 sale_exception_credit_limit/models/account_move.py create mode 100644 sale_ux/.vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..ff5300ef4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.languageServer": "None" +} \ No newline at end of file diff --git a/portal_sale_distributor/.vscode/settings.json b/portal_sale_distributor/.vscode/settings.json new file mode 100644 index 000000000..ff5300ef4 --- /dev/null +++ b/portal_sale_distributor/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.languageServer": "None" +} \ No newline at end of file diff --git a/sale_exception_credit_limit/README.rst b/sale_exception_credit_limit/README.rst index ce6349496..fd9c7c7c2 100644 --- a/sale_exception_credit_limit/README.rst +++ b/sale_exception_credit_limit/README.rst @@ -15,6 +15,13 @@ Sale Exception Credit Limit =========================== #. It adds a new group 'can modify credit limit', only users with this group are allowed to change credit limit on partners. +#. It also adds an exception to check that you can not aproove sale orders that would exceed credit limit. It checks: + +* The current due of the partner +* The amount of Sale Orders aproved but not yet invoiced +* The invoices in draft state. +* The amount of the Sale Order to be aproved and compares it with the credit limit of the partner. If the credit limit is below this, then it is not to approve the Sale Order. + #. A credit limit equal to zero means that the partner has not credit limit. The precision of comparison depends on currency decimal places. Installation diff --git a/sale_exception_credit_limit/models/__init__.py b/sale_exception_credit_limit/models/__init__.py index 2a70e85b9..5b756bbd9 100644 --- a/sale_exception_credit_limit/models/__init__.py +++ b/sale_exception_credit_limit/models/__init__.py @@ -4,3 +4,4 @@ ############################################################################## from . import sale_order from . import res_partner +from . import account_move diff --git a/sale_exception_credit_limit/models/account_move.py b/sale_exception_credit_limit/models/account_move.py new file mode 100644 index 000000000..d9786924f --- /dev/null +++ b/sale_exception_credit_limit/models/account_move.py @@ -0,0 +1,47 @@ +############################################################################## +# For copyright and license notices, see __manifest__.py file in module root +# directory +############################################################################## +from odoo import models, _ +from odoo.tools import formatLang + + +class AccountMove(models.Model): + _inherit = "account.move" + + + def _build_credit_warning_message(self, record, current_amount=0.0, exclude_current=False, exclude_amount=0.0): + """ We override the original odoo method to change the total_credit (only that we change from the original method). We make it consider partner_id.credit_with_confirmed_orders and subtract partner_id.credit_to_invoice. """ + partner_id = record.partner_id.commercial_partner_id + credit_to_invoice = partner_id.credit_to_invoice - exclude_amount + ## Cambiamos credit por credit_with_confirmed_orders. + total_credit = partner_id.credit_with_confirmed_orders - partner_id.credit_to_invoice + credit_to_invoice + current_amount + ## + if not partner_id.credit_limit or total_credit <= partner_id.credit_limit: + return '' + msg = _( + '%(partner_name)s has reached its credit limit of: %(credit_limit)s', + partner_name=partner_id.name, + credit_limit=formatLang(self.env, partner_id.credit_limit, currency_obj=record.company_id.currency_id) + ) + total_credit_formatted = formatLang(self.env, total_credit, currency_obj=record.company_id.currency_id) + if credit_to_invoice > 0 and current_amount > 0: + return msg + '\n' + _( + 'Total amount due (including sales orders and this document): %(total_credit)s', + total_credit=total_credit_formatted + ) + elif credit_to_invoice > 0: + return msg + '\n' + _( + 'Total amount due (including sales orders): %(total_credit)s', + total_credit=total_credit_formatted + ) + elif current_amount > 0: + return msg + '\n' + _( + 'Total amount due (including this document): %(total_credit)s', + total_credit=total_credit_formatted + ) + else: + return msg + '\n' + _( + 'Total amount due: %(total_credit)s', + total_credit=total_credit_formatted + ) diff --git a/sale_exception_credit_limit/models/res_partner.py b/sale_exception_credit_limit/models/res_partner.py index fcf9cf723..b758a637c 100644 --- a/sale_exception_credit_limit/models/res_partner.py +++ b/sale_exception_credit_limit/models/res_partner.py @@ -9,7 +9,11 @@ class ResPartner(models.Model): _inherit = "res.partner" - user_credit_config = fields.Boolean(compute="_compute_user_credit_config") + credit_with_confirmed_orders = fields.Monetary(compute='_compute_credit_with_confirmed_orders', + string='Credit Taken', help="Total amount this customer owes you (including not invoiced confirmed sale orders and draft invoices).", + groups='account.group_account_invoice,account.group_account_readonly' + ) + user_credit_config = fields.Boolean(compute='_compute_user_credit_config') @api.depends_context("uid") def _compute_user_credit_config(self): @@ -17,13 +21,36 @@ def _compute_user_credit_config(self): def write(self, vals): """Si esta constraint trae dolores de cabeza la podemos sacar ya que este "bache" de seguridad esta en muchos - lugares aún mas criticos. Es un problema del ORM donde mucho se protege a nivel vista""" - if "credit_limit" in vals or "use_partner_credit_limit" in vals: - for record in self: - if not self.env.user.has_group("sale_exception_credit_limit.credit_config"): - new_credit_limit = vals.get("credit_limit", record.credit_limit) - if not record.parent_id or new_credit_limit != record.parent_id.credit_limit: - raise ValidationError( - "People without Credit limit Configuration Rights cannot modify credit limit parameters" - ) - return super().write(vals) + lugares aún mas criticos. es un problema del ORM donde mucho se protege a nivel vista""" + if not self.env.user.has_group('sale_exception_credit_limit.credit_config') and any( + not x.parent_id or x.credit_limit != x.parent_id.credit_limit for x in self + ): + raise ValidationError('People without Credit limit Configuration Rights cannot modify credit limit parameters') + + @api.depends_context('company') + def _compute_credit_with_confirmed_orders(self): + # Sets 0 when use_partner_credit_limit is not set avoiding unnecessary overloads + if not self.use_partner_credit_limit: + self.credit_with_confirmed_orders = 0 + else: + domain = [ + ('move_id.partner_id.commercial_partner_id', '=', self.commercial_partner_id.id), + ('move_id.move_type', 'in', ['out_invoice', 'out_refund']), + ('move_id.state', '=', 'draft'), + '|',('sale_line_ids', '=', False), + ('sale_line_ids.order_id.invoice_status', '=', 'invoiced')] + draft_invoice_lines = self.env['account.move.line'].search(domain) + draft_invoice_lines_amount = 0.0 + for line in draft_invoice_lines: + price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) + taxes = line.tax_ids.compute_all( + price, line.move_id.currency_id, + line.quantity, + product=line.product_id, partner=line.move_id.partner_id) + total = taxes['total_included'] + if line.move_id.currency_id != line.company_id.currency_id: + total = line.move_id.currency_id._convert( + taxes['total_included'], line.company_id.currency_id, line.company_id, fields.Date.today()) + draft_invoice_lines_amount += total + + self.credit_with_confirmed_orders = draft_invoice_lines_amount + self.credit + self.credit_to_invoice diff --git a/sale_exception_credit_limit/views/res_partner_views.xml b/sale_exception_credit_limit/views/res_partner_views.xml index 483e84e76..8bf82cd4b 100644 --- a/sale_exception_credit_limit/views/res_partner_views.xml +++ b/sale_exception_credit_limit/views/res_partner_views.xml @@ -5,6 +5,15 @@ res.partner + + 1 + + + + +
+ + diff --git a/sale_ux/.vscode/settings.json b/sale_ux/.vscode/settings.json new file mode 100644 index 000000000..ff5300ef4 --- /dev/null +++ b/sale_ux/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.languageServer": "None" +} \ No newline at end of file From 8fbe7af3e97d35d1f49cfcb452c590993ddba660 Mon Sep 17 00:00:00 2001 From: Matias Peralta Date: Wed, 2 Jul 2025 12:58:52 -0300 Subject: [PATCH 2/4] [REF] sale_exception_credit_limit: revert several changes --- .vscode/settings.json | 2 +- portal_sale_distributor/.vscode/settings.json | 3 - .../models/account_move.py | 87 ++++++++------ .../models/res_partner.py | 110 ++++++++++++------ .../views/res_partner_views.xml | 8 +- sale_ux/.vscode/settings.json | 3 - 6 files changed, 128 insertions(+), 85 deletions(-) delete mode 100644 portal_sale_distributor/.vscode/settings.json delete mode 100644 sale_ux/.vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json index ff5300ef4..277f7c989 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { "python.languageServer": "None" -} \ No newline at end of file +} diff --git a/portal_sale_distributor/.vscode/settings.json b/portal_sale_distributor/.vscode/settings.json deleted file mode 100644 index ff5300ef4..000000000 --- a/portal_sale_distributor/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "python.languageServer": "None" -} \ No newline at end of file diff --git a/sale_exception_credit_limit/models/account_move.py b/sale_exception_credit_limit/models/account_move.py index d9786924f..5d9c0e319 100644 --- a/sale_exception_credit_limit/models/account_move.py +++ b/sale_exception_credit_limit/models/account_move.py @@ -2,46 +2,59 @@ # For copyright and license notices, see __manifest__.py file in module root # directory ############################################################################## -from odoo import models, _ -from odoo.tools import formatLang +from odoo import models class AccountMove(models.Model): _inherit = "account.move" + # def _get_total_credit_all_companies(self, partner): + # credit = 0.0 + # credit_to_invoice = 0.0 + # for company in self.env["res.company"].search([]): + # credit += partner.with_context(force_company=company.id).credit + # credit_to_invoice += partner.with_context(force_company=company.id).credit_to_invoice + # return credit, credit_to_invoice - def _build_credit_warning_message(self, record, current_amount=0.0, exclude_current=False, exclude_amount=0.0): - """ We override the original odoo method to change the total_credit (only that we change from the original method). We make it consider partner_id.credit_with_confirmed_orders and subtract partner_id.credit_to_invoice. """ - partner_id = record.partner_id.commercial_partner_id - credit_to_invoice = partner_id.credit_to_invoice - exclude_amount - ## Cambiamos credit por credit_with_confirmed_orders. - total_credit = partner_id.credit_with_confirmed_orders - partner_id.credit_to_invoice + credit_to_invoice + current_amount - ## - if not partner_id.credit_limit or total_credit <= partner_id.credit_limit: - return '' - msg = _( - '%(partner_name)s has reached its credit limit of: %(credit_limit)s', - partner_name=partner_id.name, - credit_limit=formatLang(self.env, partner_id.credit_limit, currency_obj=record.company_id.currency_id) - ) - total_credit_formatted = formatLang(self.env, total_credit, currency_obj=record.company_id.currency_id) - if credit_to_invoice > 0 and current_amount > 0: - return msg + '\n' + _( - 'Total amount due (including sales orders and this document): %(total_credit)s', - total_credit=total_credit_formatted - ) - elif credit_to_invoice > 0: - return msg + '\n' + _( - 'Total amount due (including sales orders): %(total_credit)s', - total_credit=total_credit_formatted - ) - elif current_amount > 0: - return msg + '\n' + _( - 'Total amount due (including this document): %(total_credit)s', - total_credit=total_credit_formatted - ) - else: - return msg + '\n' + _( - 'Total amount due: %(total_credit)s', - total_credit=total_credit_formatted - ) + # @api.model + # def _build_credit_warning_message(self, record, current_amount=0.0, exclude_current=False, exclude_amount=0.0): + # partner = record.partner_id.commercial_partner_id + + # # Patch: sumar créditos de todas las compañías + # credit, credit_to_invoice = self._get_total_credit_all_companies(partner) + # credit_to_invoice -= exclude_amount + # total_credit = credit + credit_to_invoice + current_amount + + # if not partner.credit_limit or total_credit <= partner.credit_limit: + # return "" + + # msg = _( + # "%(partner_name)s has reached its credit limit of: %(credit_limit)s", + # partner_name=partner.name, + # credit_limit=formatLang(self.env, partner.credit_limit, currency_obj=record.company_id.currency_id), + # ) + # total_credit_formatted = formatLang(self.env, total_credit, currency_obj=record.company_id.currency_id) + + # if credit_to_invoice > 0 and current_amount > 0: + # return ( + # msg + # + "\n" + # + _( + # "Total amount due (including sales orders and this document): %(total_credit)s", + # total_credit=total_credit_formatted, + # ) + # ) + # elif credit_to_invoice > 0: + # return ( + # msg + # + "\n" + # + _("Total amount due (including sales orders): %(total_credit)s", total_credit=total_credit_formatted) + # ) + # elif current_amount > 0: + # return ( + # msg + # + "\n" + # + _("Total amount due (including this document): %(total_credit)s", total_credit=total_credit_formatted) + # ) + # else: + # return msg + "\n" + _("Total amount due: %(total_credit)s", total_credit=total_credit_formatted) diff --git a/sale_exception_credit_limit/models/res_partner.py b/sale_exception_credit_limit/models/res_partner.py index b758a637c..25611fcfb 100644 --- a/sale_exception_credit_limit/models/res_partner.py +++ b/sale_exception_credit_limit/models/res_partner.py @@ -4,16 +4,19 @@ ############################################################################## from odoo import api, fields, models from odoo.exceptions import ValidationError +from odoo.tools import SQL class ResPartner(models.Model): _inherit = "res.partner" - credit_with_confirmed_orders = fields.Monetary(compute='_compute_credit_with_confirmed_orders', - string='Credit Taken', help="Total amount this customer owes you (including not invoiced confirmed sale orders and draft invoices).", - groups='account.group_account_invoice,account.group_account_readonly' - ) - user_credit_config = fields.Boolean(compute='_compute_user_credit_config') + # credit_with_confirmed_orders = fields.Monetary( + # compute="_compute_credit_with_confirmed_orders", + # string="Credit Taken", + # help="Total amount this customer owes you (including not invoiced confirmed sale orders and draft invoices).", + # groups="account.group_account_invoice,account.group_account_readonly", + # ) + user_credit_config = fields.Boolean(compute="_compute_user_credit_config") @api.depends_context("uid") def _compute_user_credit_config(self): @@ -22,35 +25,68 @@ def _compute_user_credit_config(self): def write(self, vals): """Si esta constraint trae dolores de cabeza la podemos sacar ya que este "bache" de seguridad esta en muchos lugares aún mas criticos. es un problema del ORM donde mucho se protege a nivel vista""" - if not self.env.user.has_group('sale_exception_credit_limit.credit_config') and any( - not x.parent_id or x.credit_limit != x.parent_id.credit_limit for x in self - ): - raise ValidationError('People without Credit limit Configuration Rights cannot modify credit limit parameters') - - @api.depends_context('company') - def _compute_credit_with_confirmed_orders(self): - # Sets 0 when use_partner_credit_limit is not set avoiding unnecessary overloads - if not self.use_partner_credit_limit: - self.credit_with_confirmed_orders = 0 - else: - domain = [ - ('move_id.partner_id.commercial_partner_id', '=', self.commercial_partner_id.id), - ('move_id.move_type', 'in', ['out_invoice', 'out_refund']), - ('move_id.state', '=', 'draft'), - '|',('sale_line_ids', '=', False), - ('sale_line_ids.order_id.invoice_status', '=', 'invoiced')] - draft_invoice_lines = self.env['account.move.line'].search(domain) - draft_invoice_lines_amount = 0.0 - for line in draft_invoice_lines: - price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) - taxes = line.tax_ids.compute_all( - price, line.move_id.currency_id, - line.quantity, - product=line.product_id, partner=line.move_id.partner_id) - total = taxes['total_included'] - if line.move_id.currency_id != line.company_id.currency_id: - total = line.move_id.currency_id._convert( - taxes['total_included'], line.company_id.currency_id, line.company_id, fields.Date.today()) - draft_invoice_lines_amount += total - - self.credit_with_confirmed_orders = draft_invoice_lines_amount + self.credit + self.credit_to_invoice + if "credit_limit" in vals or "use_partner_credit_limit" in vals: + for record in self: + if not self.env.user.has_group("sale_exception_credit_limit.credit_config"): + new_credit_limit = vals.get("credit_limit", record.credit_limit) + if not record.parent_id or new_credit_limit != record.parent_id.credit_limit: + raise ValidationError( + "People without Credit limit Configuration Rights cannot modify credit limit parameters" + ) + return super().write(vals) + + def _credit_debit_get(self): + # Redefinimos método para que obtenga facturas en borrador. + if not self.ids: + self.debit = False + self.credit = False + return + + query = self.env["account.move.line"]._where_calc( + [("parent_state", "=", "posted"), ("company_id", "child_of", self.env.company.root_id.id)] + ) + self.env["account.move.line"].flush_model( + ["account_id", "amount_residual", "company_id", "parent_state", "partner_id", "reconciled"] + ) + self.env["account.account"].flush_model(["account_type"]) + + sql = SQL( + """ + SELECT account_move_line.partner_id, a.account_type, SUM(account_move_line.amount_residual) + FROM %s + LEFT JOIN account_account a ON (account_move_line.account_id=a.id) + WHERE a.account_type IN ('asset_receivable','liability_payable') + AND account_move_line.partner_id IN %s + AND account_move_line.reconciled IS NOT TRUE + AND %s + GROUP BY account_move_line.partner_id, a.account_type + """, + query.from_clause, + tuple(self.ids), + query.where_clause or SQL("TRUE"), + ) + + credit_map = {} + debit_map = {} + + for pid, account_type, val in self.env.execute_query(sql): + if account_type == "asset_receivable": + credit_map[pid] = val + elif account_type == "liability_payable": + debit_map[pid] = -val + + draft_moves = self.env["account.move"].search( + [ + ("state", "=", "draft"), + ("move_type", "in", ["out_invoice", "out_refund"]), + ("partner_id", "in", self.ids), + ("company_id", "child_of", self.env.company.root_id.id), + ] + ) + for move in draft_moves: + pid = move.partner_id.id + credit_map[pid] = credit_map.get(pid, 0.0) + move.amount_total_signed + + for partner in self: + partner.credit = credit_map.get(partner.id, 0.0) + partner.debit = debit_map.get(partner.id, 0.0) diff --git a/sale_exception_credit_limit/views/res_partner_views.xml b/sale_exception_credit_limit/views/res_partner_views.xml index 8bf82cd4b..7db349248 100644 --- a/sale_exception_credit_limit/views/res_partner_views.xml +++ b/sale_exception_credit_limit/views/res_partner_views.xml @@ -5,12 +5,12 @@ res.partner - + +
diff --git a/sale_ux/.vscode/settings.json b/sale_ux/.vscode/settings.json deleted file mode 100644 index ff5300ef4..000000000 --- a/sale_ux/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "python.languageServer": "None" -} \ No newline at end of file From 6355935565066af9d66b9b1980e77617522a6ee1 Mon Sep 17 00:00:00 2001 From: Franco Leyes Date: Mon, 14 Jul 2025 20:35:42 +0000 Subject: [PATCH 3/4] [IMP] sale_exception_credit_limit: optimize _credit_debit_get method to streamline draft invoice calculations --- .../models/res_partner.py | 68 ++++--------------- 1 file changed, 15 insertions(+), 53 deletions(-) diff --git a/sale_exception_credit_limit/models/res_partner.py b/sale_exception_credit_limit/models/res_partner.py index 25611fcfb..fd911cc60 100644 --- a/sale_exception_credit_limit/models/res_partner.py +++ b/sale_exception_credit_limit/models/res_partner.py @@ -36,57 +36,19 @@ def write(self, vals): return super().write(vals) def _credit_debit_get(self): - # Redefinimos método para que obtenga facturas en borrador. - if not self.ids: - self.debit = False - self.credit = False - return - - query = self.env["account.move.line"]._where_calc( - [("parent_state", "=", "posted"), ("company_id", "child_of", self.env.company.root_id.id)] - ) - self.env["account.move.line"].flush_model( - ["account_id", "amount_residual", "company_id", "parent_state", "partner_id", "reconciled"] - ) - self.env["account.account"].flush_model(["account_type"]) - - sql = SQL( - """ - SELECT account_move_line.partner_id, a.account_type, SUM(account_move_line.amount_residual) - FROM %s - LEFT JOIN account_account a ON (account_move_line.account_id=a.id) - WHERE a.account_type IN ('asset_receivable','liability_payable') - AND account_move_line.partner_id IN %s - AND account_move_line.reconciled IS NOT TRUE - AND %s - GROUP BY account_move_line.partner_id, a.account_type - """, - query.from_clause, - tuple(self.ids), - query.where_clause or SQL("TRUE"), - ) - - credit_map = {} - debit_map = {} - - for pid, account_type, val in self.env.execute_query(sql): - if account_type == "asset_receivable": - credit_map[pid] = val - elif account_type == "liability_payable": - debit_map[pid] = -val - - draft_moves = self.env["account.move"].search( - [ - ("state", "=", "draft"), - ("move_type", "in", ["out_invoice", "out_refund"]), - ("partner_id", "in", self.ids), - ("company_id", "child_of", self.env.company.root_id.id), - ] - ) - for move in draft_moves: - pid = move.partner_id.id - credit_map[pid] = credit_map.get(pid, 0.0) + move.amount_total_signed - + super()._credit_debit_get() + credit_map = { + res['partner_id'][0]: res['amount_total_signed'] + for res in self.env['account.move'].read_group( + [ + ("state", "=", "draft"), + ("move_type", "in", ["out_invoice", "out_refund"]), + ("partner_id", "in", self.ids), + ("company_id", "child_of", self.env.company.root_id.id), + ], + ["amount_total_signed"], + ["partner_id"] + ) if res['partner_id'] + } for partner in self: - partner.credit = credit_map.get(partner.id, 0.0) - partner.debit = debit_map.get(partner.id, 0.0) + partner.credit = partner.credit + credit_map.get(partner.id, 0.0) From 8fa69b0e56d3615f975a1b974a2fb659eab5c6c0 Mon Sep 17 00:00:00 2001 From: Matias Peralta Date: Wed, 23 Jul 2025 15:30:51 -0300 Subject: [PATCH 4/4] [FIX]sale_exception_credit_limit: fix credit computation per company --- .../models/res_partner.py | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/sale_exception_credit_limit/models/res_partner.py b/sale_exception_credit_limit/models/res_partner.py index fd911cc60..a56565d20 100644 --- a/sale_exception_credit_limit/models/res_partner.py +++ b/sale_exception_credit_limit/models/res_partner.py @@ -2,9 +2,10 @@ # For copyright and license notices, see __manifest__.py file in module root # directory ############################################################################## +from collections import defaultdict + from odoo import api, fields, models from odoo.exceptions import ValidationError -from odoo.tools import SQL class ResPartner(models.Model): @@ -37,18 +38,36 @@ def write(self, vals): def _credit_debit_get(self): super()._credit_debit_get() + # Esto busca fact en borrador credit_map = { - res['partner_id'][0]: res['amount_total_signed'] - for res in self.env['account.move'].read_group( + res["partner_id"][0]: res["amount_total_signed"] + for res in self.env["account.move"].read_group( [ ("state", "=", "draft"), ("move_type", "in", ["out_invoice", "out_refund"]), ("partner_id", "in", self.ids), - ("company_id", "child_of", self.env.company.root_id.id), + ("company_id", "in", self.env.companies.ids), ], ["amount_total_signed"], - ["partner_id"] - ) if res['partner_id'] + ["partner_id"], + ) + if res["partner_id"] } + sale_map = defaultdict(float) + + # Esto busca lineas pendientes de facturar pero confirm + sale_lines = self.env["sale.order.line"].search( + [ + ("order_id.state", "=", "sale"), + ("order_id.partner_id", "in", self.ids), + ("order_id.invoice_status", "in", ["no", "to invoice", "partial"]), + ("company_id", "in", self.env.companies.ids), + ] + ) + + for line in sale_lines: + partner_id = line.order_id.partner_id.id + sale_map[partner_id] += line.price_total + for partner in self: - partner.credit = partner.credit + credit_map.get(partner.id, 0.0) + partner.credit += credit_map.get(partner.id, 0.0) + sale_map.get(partner.id, 0.0)