Pass res_id correctly to lines to allow navigation on the fields In the open items ledger, the res_id attribute of the invoice in the report was getting: (id, move_name) The result was that, when clicking the line, it would redirect to a new record, instead of the existing. This passes only the id to the line, solving that issue. Fix menu item name TT29371
394 lines
15 KiB
Python
394 lines
15 KiB
Python
# ?? 2016 Julien Coux (Camptocamp)
|
|
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com)
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
|
|
import operator
|
|
from datetime import date, datetime
|
|
|
|
from odoo import api, models
|
|
from odoo.tools import float_is_zero
|
|
|
|
|
|
class OpenItemsReport(models.AbstractModel):
|
|
_name = "report.account_financial_report.open_items"
|
|
_description = "Open Items Report"
|
|
|
|
@api.model
|
|
def get_html(self, given_context=None):
|
|
return self._get_html()
|
|
|
|
def _get_html(self):
|
|
result = {}
|
|
rcontext = {}
|
|
context = dict(self.env.context)
|
|
rcontext.update(context.get("data"))
|
|
active_id = context.get("active_id")
|
|
wiz = self.env["open.items.report.wizard"].browse(active_id)
|
|
rcontext["o"] = wiz
|
|
result["html"] = self.env.ref(
|
|
"account_financial_report.report_open_items"
|
|
).render(rcontext)
|
|
return result
|
|
|
|
def _get_account_partial_reconciled(self, company_id, date_at_object):
|
|
domain = [("max_date", ">", date_at_object), ("company_id", "=", company_id)]
|
|
fields = ["debit_move_id", "credit_move_id", "amount"]
|
|
accounts_partial_reconcile = self.env["account.partial.reconcile"].search_read(
|
|
domain=domain, fields=fields
|
|
)
|
|
debit_amount = {}
|
|
credit_amount = {}
|
|
for account_partial_reconcile_data in accounts_partial_reconcile:
|
|
debit_move_id = account_partial_reconcile_data["debit_move_id"][0]
|
|
credit_move_id = account_partial_reconcile_data["credit_move_id"][0]
|
|
if debit_move_id not in debit_amount.keys():
|
|
debit_amount[debit_move_id] = 0.0
|
|
debit_amount[debit_move_id] += account_partial_reconcile_data["amount"]
|
|
if credit_move_id not in credit_amount.keys():
|
|
credit_amount[credit_move_id] = 0.0
|
|
credit_amount[credit_move_id] += account_partial_reconcile_data["amount"]
|
|
account_partial_reconcile_data.update(
|
|
{"debit_move_id": debit_move_id, "credit_move_id": credit_move_id}
|
|
)
|
|
return accounts_partial_reconcile, debit_amount, credit_amount
|
|
|
|
@api.model
|
|
def _get_new_move_lines_domain(
|
|
self, new_ml_ids, account_ids, company_id, partner_ids, target_moves
|
|
):
|
|
domain = [
|
|
("account_id", "in", account_ids),
|
|
("company_id", "=", company_id),
|
|
("id", "in", new_ml_ids),
|
|
]
|
|
if partner_ids:
|
|
domain += [("partner_id", "in", partner_ids)]
|
|
if target_moves == "posted":
|
|
domain += [("move_id.state", "=", "posted")]
|
|
return domain
|
|
|
|
def _recalculate_move_lines(
|
|
self,
|
|
move_lines,
|
|
debit_ids,
|
|
credit_ids,
|
|
debit_amount,
|
|
credit_amount,
|
|
ml_ids,
|
|
account_ids,
|
|
company_id,
|
|
partner_ids,
|
|
target_moves,
|
|
):
|
|
debit_ids = set(debit_ids)
|
|
credit_ids = set(credit_ids)
|
|
in_credit_but_not_in_debit = credit_ids - debit_ids
|
|
reconciled_ids = list(debit_ids) + list(in_credit_but_not_in_debit)
|
|
reconciled_ids = set(reconciled_ids)
|
|
ml_ids = set(ml_ids)
|
|
new_ml_ids = reconciled_ids - ml_ids
|
|
new_ml_ids = list(new_ml_ids)
|
|
new_domain = self._get_new_move_lines_domain(
|
|
new_ml_ids, account_ids, company_id, partner_ids, target_moves
|
|
)
|
|
ml_fields = [
|
|
"id",
|
|
"name",
|
|
"date",
|
|
"move_id",
|
|
"journal_id",
|
|
"account_id",
|
|
"partner_id",
|
|
"amount_residual",
|
|
"date_maturity",
|
|
"ref",
|
|
"debit",
|
|
"credit",
|
|
"reconciled",
|
|
"currency_id",
|
|
"amount_currency",
|
|
"amount_residual_currency",
|
|
]
|
|
new_move_lines = self.env["account.move.line"].search_read(
|
|
domain=new_domain, fields=ml_fields
|
|
)
|
|
move_lines = move_lines + new_move_lines
|
|
for move_line in move_lines:
|
|
ml_id = move_line["id"]
|
|
if ml_id in debit_ids:
|
|
move_line["amount_residual"] += debit_amount[ml_id]
|
|
if ml_id in credit_ids:
|
|
move_line["amount_residual"] -= credit_amount[ml_id]
|
|
return move_lines
|
|
|
|
@api.model
|
|
def _get_move_lines_domain(
|
|
self, company_id, account_ids, partner_ids, target_move, date_from
|
|
):
|
|
domain = [
|
|
("account_id", "in", account_ids),
|
|
("company_id", "=", company_id),
|
|
("reconciled", "=", False),
|
|
]
|
|
if partner_ids:
|
|
domain += [("partner_id", "in", partner_ids)]
|
|
if target_move == "posted":
|
|
domain += [("move_id.state", "=", "posted")]
|
|
if date_from:
|
|
domain += [("date", ">", date_from)]
|
|
return domain
|
|
|
|
def _get_accounts_data(self, accounts_ids):
|
|
accounts = self.env["account.account"].browse(accounts_ids)
|
|
accounts_data = {}
|
|
for account in accounts:
|
|
accounts_data.update(
|
|
{
|
|
account.id: {
|
|
"id": account.id,
|
|
"code": account.code,
|
|
"name": account.name,
|
|
"hide_account": False,
|
|
"currency_id": account.currency_id or False,
|
|
"currency_name": account.currency_id.name,
|
|
}
|
|
}
|
|
)
|
|
return accounts_data
|
|
|
|
def _get_journals_data(self, journals_ids):
|
|
journals = self.env["account.journal"].browse(journals_ids)
|
|
journals_data = {}
|
|
for journal in journals:
|
|
journals_data.update({journal.id: {"id": journal.id, "code": journal.code}})
|
|
return journals_data
|
|
|
|
def _get_data(
|
|
self,
|
|
account_ids,
|
|
partner_ids,
|
|
date_at_object,
|
|
target_move,
|
|
company_id,
|
|
date_from,
|
|
):
|
|
domain = self._get_move_lines_domain(
|
|
company_id, account_ids, partner_ids, target_move, date_from
|
|
)
|
|
ml_fields = [
|
|
"id",
|
|
"name",
|
|
"date",
|
|
"move_id",
|
|
"journal_id",
|
|
"account_id",
|
|
"partner_id",
|
|
"amount_residual",
|
|
"date_maturity",
|
|
"ref",
|
|
"debit",
|
|
"credit",
|
|
"reconciled",
|
|
"currency_id",
|
|
"amount_currency",
|
|
"amount_residual_currency",
|
|
]
|
|
move_lines = self.env["account.move.line"].search_read(
|
|
domain=domain, fields=ml_fields
|
|
)
|
|
journals_ids = set()
|
|
partners_ids = set()
|
|
partners_data = {}
|
|
if date_at_object < date.today():
|
|
(
|
|
acc_partial_rec,
|
|
debit_amount,
|
|
credit_amount,
|
|
) = self._get_account_partial_reconciled(company_id, date_at_object)
|
|
if acc_partial_rec:
|
|
ml_ids = list(map(operator.itemgetter("id"), move_lines))
|
|
debit_ids = list(
|
|
map(operator.itemgetter("debit_move_id"), acc_partial_rec)
|
|
)
|
|
credit_ids = list(
|
|
map(operator.itemgetter("credit_move_id"), acc_partial_rec)
|
|
)
|
|
move_lines = self._recalculate_move_lines(
|
|
move_lines,
|
|
debit_ids,
|
|
credit_ids,
|
|
debit_amount,
|
|
credit_amount,
|
|
ml_ids,
|
|
account_ids,
|
|
company_id,
|
|
partner_ids,
|
|
target_move,
|
|
)
|
|
move_lines = [
|
|
move_line
|
|
for move_line in move_lines
|
|
if move_line["date"] <= date_at_object
|
|
and not float_is_zero(move_line["amount_residual"], precision_digits=2)
|
|
]
|
|
|
|
open_items_move_lines_data = {}
|
|
for move_line in move_lines:
|
|
journals_ids.add(move_line["journal_id"][0])
|
|
acc_id = move_line["account_id"][0]
|
|
# Partners data
|
|
if move_line["partner_id"]:
|
|
prt_id = move_line["partner_id"][0]
|
|
prt_name = move_line["partner_id"][1]
|
|
else:
|
|
prt_id = 0
|
|
prt_name = "Missing Partner"
|
|
if prt_id not in partners_ids:
|
|
partners_data.update({prt_id: {"id": prt_id, "name": prt_name}})
|
|
partners_ids.add(prt_id)
|
|
|
|
# Move line update
|
|
original = 0
|
|
|
|
if not float_is_zero(move_line["credit"], precision_digits=2):
|
|
original = move_line["credit"] * (-1)
|
|
if not float_is_zero(move_line["debit"], precision_digits=2):
|
|
original = move_line["debit"]
|
|
|
|
if move_line["ref"] == move_line["name"]:
|
|
if move_line["ref"]:
|
|
ref_label = move_line["ref"]
|
|
else:
|
|
ref_label = ""
|
|
elif not move_line["ref"]:
|
|
ref_label = move_line["name"]
|
|
elif not move_line["name"]:
|
|
ref_label = move_line["ref"]
|
|
else:
|
|
ref_label = move_line["ref"] + str(" - ") + move_line["name"]
|
|
|
|
move_line.update(
|
|
{
|
|
"date": move_line["date"],
|
|
"date_maturity": move_line["date_maturity"]
|
|
and move_line["date_maturity"].strftime("%d/%m/%Y"),
|
|
"original": original,
|
|
"partner_id": prt_id,
|
|
"partner_name": prt_name,
|
|
"ref_label": ref_label,
|
|
"journal_id": move_line["journal_id"][0],
|
|
"move_name": move_line["move_id"][1],
|
|
"entry_id": move_line["move_id"][0],
|
|
"currency_id": move_line["currency_id"][0]
|
|
if move_line["currency_id"]
|
|
else False,
|
|
"currency_name": move_line["currency_id"][1]
|
|
if move_line["currency_id"]
|
|
else False,
|
|
}
|
|
)
|
|
|
|
# Open Items Move Lines Data
|
|
if acc_id not in open_items_move_lines_data.keys():
|
|
open_items_move_lines_data[acc_id] = {prt_id: [move_line]}
|
|
else:
|
|
if prt_id not in open_items_move_lines_data[acc_id].keys():
|
|
open_items_move_lines_data[acc_id][prt_id] = [move_line]
|
|
else:
|
|
open_items_move_lines_data[acc_id][prt_id].append(move_line)
|
|
journals_data = self._get_journals_data(list(journals_ids))
|
|
accounts_data = self._get_accounts_data(open_items_move_lines_data.keys())
|
|
return (
|
|
move_lines,
|
|
partners_data,
|
|
journals_data,
|
|
accounts_data,
|
|
open_items_move_lines_data,
|
|
)
|
|
|
|
@api.model
|
|
def _calculate_amounts(self, open_items_move_lines_data):
|
|
total_amount = {}
|
|
for account_id in open_items_move_lines_data.keys():
|
|
total_amount[account_id] = {}
|
|
total_amount[account_id]["residual"] = 0.0
|
|
for partner_id in open_items_move_lines_data[account_id].keys():
|
|
total_amount[account_id][partner_id] = {}
|
|
total_amount[account_id][partner_id]["residual"] = 0.0
|
|
for move_line in open_items_move_lines_data[account_id][partner_id]:
|
|
total_amount[account_id][partner_id]["residual"] += move_line[
|
|
"amount_residual"
|
|
]
|
|
total_amount[account_id]["residual"] += move_line["amount_residual"]
|
|
return total_amount
|
|
|
|
@api.model
|
|
def _order_open_items_by_date(
|
|
self, open_items_move_lines_data, show_partner_details
|
|
):
|
|
new_open_items = {}
|
|
if not show_partner_details:
|
|
for acc_id in open_items_move_lines_data.keys():
|
|
new_open_items[acc_id] = {}
|
|
move_lines = []
|
|
for prt_id in open_items_move_lines_data[acc_id]:
|
|
for move_line in open_items_move_lines_data[acc_id][prt_id]:
|
|
move_lines += [move_line]
|
|
move_lines = sorted(move_lines, key=lambda k: (k["date"]))
|
|
new_open_items[acc_id] = move_lines
|
|
else:
|
|
for acc_id in open_items_move_lines_data.keys():
|
|
new_open_items[acc_id] = {}
|
|
for prt_id in open_items_move_lines_data[acc_id]:
|
|
new_open_items[acc_id][prt_id] = {}
|
|
move_lines = []
|
|
for move_line in open_items_move_lines_data[acc_id][prt_id]:
|
|
move_lines += [move_line]
|
|
move_lines = sorted(move_lines, key=lambda k: (k["date"]))
|
|
new_open_items[acc_id][prt_id] = move_lines
|
|
return new_open_items
|
|
|
|
def _get_report_values(self, docids, data):
|
|
wizard_id = data["wizard_id"]
|
|
company = self.env["res.company"].browse(data["company_id"])
|
|
company_id = data["company_id"]
|
|
account_ids = data["account_ids"]
|
|
partner_ids = data["partner_ids"]
|
|
date_at = data["date_at"]
|
|
date_at_object = datetime.strptime(date_at, "%Y-%m-%d").date()
|
|
date_from = data["date_from"]
|
|
target_move = data["target_move"]
|
|
show_partner_details = data["show_partner_details"]
|
|
|
|
(
|
|
move_lines_data,
|
|
partners_data,
|
|
journals_data,
|
|
accounts_data,
|
|
open_items_move_lines_data,
|
|
) = self._get_data(
|
|
account_ids, partner_ids, date_at_object, target_move, company_id, date_from
|
|
)
|
|
|
|
total_amount = self._calculate_amounts(open_items_move_lines_data)
|
|
open_items_move_lines_data = self._order_open_items_by_date(
|
|
open_items_move_lines_data, show_partner_details
|
|
)
|
|
return {
|
|
"doc_ids": [wizard_id],
|
|
"doc_model": "open.items.report.wizard",
|
|
"docs": self.env["open.items.report.wizard"].browse(wizard_id),
|
|
"foreign_currency": data["foreign_currency"],
|
|
"show_partner_details": data["show_partner_details"],
|
|
"company_name": company.display_name,
|
|
"currency_name": company.currency_id.name,
|
|
"date_at": date_at_object.strftime("%d/%m/%Y"),
|
|
"hide_account_at_0": data["hide_account_at_0"],
|
|
"target_move": data["target_move"],
|
|
"journals_data": journals_data,
|
|
"partners_data": partners_data,
|
|
"accounts_data": accounts_data,
|
|
"total_amount": total_amount,
|
|
"Open_Items": open_items_move_lines_data,
|
|
}
|