-
-
Notifications
You must be signed in to change notification settings - Fork 351
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FIX] sale_commission_partial_settlement: major refactor
This commit refactors the data structure of the module entirely, in order to provide both a forecast and more detailed traceability of partial commissions, from invoice to settlement. The new data structure is a better fit for the way invoices and moves work in base Odoo as well.
- Loading branch information
Showing
19 changed files
with
624 additions
and
178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
sale_commission_partial_settlement/migrations/14.0.2.0.0/post-migrate.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import logging | ||
|
||
from openupgradelib import openupgrade | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
def recompute_partial_commission_forecast(env): | ||
""" | ||
Recompute forecast for all partial commissions | ||
""" | ||
_logger.info( | ||
"Computing partial commission forecast for all invoices. " | ||
"This may take some time..." | ||
) | ||
limit = 5000 | ||
offset = 0 | ||
while True: | ||
aila = env["account.invoice.line.agent"].search([], limit=limit, offset=offset) | ||
if not aila: | ||
break | ||
offset += limit | ||
aila._compute_invoice_line_agent_partial_ids() | ||
while env.all.tocompute: | ||
aila.flush() | ||
aila.invalidate_cache() # avoid MemoryError | ||
_logger.info( | ||
"%(offset)s invoice commission lines computed!" % {"offset": str(offset)} | ||
) | ||
_logger.info("Computation of partial commission forecast completed!") | ||
|
||
|
||
@openupgrade.migrate() | ||
def migrate(env, version): | ||
recompute_partial_commission_forecast(env) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 106 additions & 10 deletions
116
sale_commission_partial_settlement/models/account_invoice_line_agent_partial.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,124 @@ | ||
# Copyright 2023 Nextev | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import fields, models | ||
from odoo import api, fields, models | ||
|
||
|
||
class AccountInvoiceLineAgentPartial(models.Model): | ||
_name = "account.invoice.line.agent.partial" | ||
_description = "Partial agent commissions" | ||
_description = "Partial agent commissions. " | ||
"Tracks the expected commissions." | ||
|
||
move_line_id = fields.Many2one( | ||
"account.move.line", | ||
required=True, # TODO: migration? Probably cannot enforce | ||
ondelete="cascade", | ||
) | ||
invoice_line_agent_id = fields.Many2one( | ||
"account.invoice.line.agent", required=True, ondelete="cascade" | ||
) | ||
# logically a One2one | ||
agent_line = fields.Many2many( | ||
comodel_name="sale.commission.settlement.line", | ||
relation="settlement_agent_line_partial_rel", | ||
column1="agent_line_partial_id", | ||
column2="settlement_id", | ||
copy=False, | ||
settlement_line_partial_ids = fields.One2many( | ||
"sale.commission.settlement.line.partial", | ||
"invoice_agent_partial_id", | ||
compute="_compute_settlement_line_partial_ids", | ||
store=True, | ||
) | ||
account_partial_reconcile_id = fields.Many2one("account.partial.reconcile") | ||
account_partial_reconcile_id = fields.Many2one( | ||
"account.partial.reconcile" | ||
) # TODO: Remove | ||
amount = fields.Monetary( | ||
compute="_compute_amount", | ||
store=True, | ||
string="Commission Amount", | ||
) | ||
currency_id = fields.Many2one( | ||
related="invoice_line_agent_id.currency_id", | ||
) | ||
settled_amount = fields.Monetary( | ||
compute="_compute_settled_amount", | ||
store=True, | ||
) | ||
is_settled = fields.Boolean( | ||
compute="_compute_settled_amount", store=True, string="Fully settled" | ||
) | ||
|
||
move_id = fields.Many2one(related="move_line_id.move_id", string="Invoice") | ||
date_maturity = fields.Date( | ||
related="move_line_id.date_maturity", | ||
store=True, | ||
) | ||
invoice_line_id = fields.Many2one( | ||
related="invoice_line_agent_id.object_id", string="Invoice Line" | ||
) | ||
agent_id = fields.Many2one( | ||
related="invoice_line_agent_id.agent_id", | ||
store=True, | ||
) | ||
invoice_date = fields.Date( | ||
related="invoice_line_agent_id.invoice_date", | ||
store=True, | ||
) | ||
|
||
@api.depends( | ||
"settlement_line_partial_ids.amount", | ||
"settlement_line_partial_ids.is_settled", | ||
) | ||
def _compute_settled_amount(self): | ||
for rec in self: | ||
# TODO: handle different currencies | ||
rec.settled_amount = sum( | ||
x.amount for x in rec.settlement_line_partial_ids if x.is_settled | ||
) | ||
rec.is_settled = rec.currency_id.is_zero(rec.settled_amount - rec.amount) | ||
|
||
@api.depends( | ||
"move_line_id.balance", | ||
"move_line_id.move_id.amount_total", | ||
"invoice_line_agent_id.amount", | ||
) | ||
def _compute_amount(self): | ||
for rec in self: | ||
# move_line_id.balance | ||
# invoice_line_agent_id.amount | ||
# move_line_id.move_id.amount_total_signed | ||
# all 3 terms are signed | ||
rec.amount = ( | ||
rec.move_line_id.balance | ||
* rec.invoice_line_agent_id.amount | ||
/ rec.move_line_id.move_id.amount_total_signed | ||
) | ||
|
||
@api.depends( | ||
"invoice_line_agent_id.amount", | ||
"move_line_id.matched_debit_ids", | ||
"move_line_id.matched_credit_ids", | ||
) | ||
def _compute_settlement_line_partial_ids(self): | ||
""" | ||
Cf. method _get_reconciled_invoices_partials | ||
in odoo.addons.account.models.account_move.AccountMove. | ||
""" | ||
for rec in self: | ||
if not rec.invoice_line_agent_id.amount: | ||
rec.settlement_line_partial_ids = False | ||
continue | ||
pay_term_line = rec.move_line_id | ||
matched_partials = ( | ||
pay_term_line.matched_debit_ids + pay_term_line.matched_credit_ids | ||
) | ||
if not matched_partials: | ||
continue | ||
existing_partial_settlements = rec.settlement_line_partial_ids | ||
existing_partials = existing_partial_settlements.mapped( | ||
"partial_reconcile_id" | ||
) | ||
|
||
for partial in matched_partials: | ||
if partial not in existing_partials: | ||
existing_partial_settlements.create( | ||
{ | ||
"partial_reconcile_id": partial.id, | ||
"invoice_agent_partial_id": rec.id, | ||
"agent_line": [(4, rec.invoice_line_agent_id.id)], | ||
} | ||
) |
Oops, something went wrong.